package com.intelligt.modbus.jlibmodbus.slave;
|
|
import com.intelligt.modbus.jlibmodbus.Modbus;
|
import com.intelligt.modbus.jlibmodbus.data.DataHolder;
|
import com.intelligt.modbus.jlibmodbus.data.DataHolderBuilder;
|
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
|
import com.intelligt.modbus.jlibmodbus.net.ModbusConnection;
|
import com.intelligt.modbus.jlibmodbus.utils.FrameEvent;
|
import com.intelligt.modbus.jlibmodbus.utils.FrameEventListener;
|
import com.intelligt.modbus.jlibmodbus.utils.FrameEventListenerList;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Observable;
|
import java.util.Observer;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
/*
|
* Copyright (C) 2016 "Invertor" Factory", JSC
|
* [http://www.sbp-invertor.ru]
|
*
|
* This file is part of JLibModbus.
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*
|
* Authors: Vladislav Y. Kochedykov, software engineer.
|
* email: vladislav.kochedykov@gmail.com
|
*/
|
|
abstract public class ModbusSlave implements FrameEventListenerList {
|
final private List<ModbusConnection> connectionList = new ArrayList<ModbusConnection>();
|
final private AtomicBoolean listening = new AtomicBoolean(false);
|
final private AtomicBoolean broadcastEnabled = new AtomicBoolean(false);
|
private Observable observable = new Observable() {
|
@Override
|
public void notifyObservers(Object arg) {
|
setChanged();
|
super.notifyObservers(arg);
|
}
|
};
|
private int serverAddress = Modbus.BROADCAST_ID;
|
private DataHolder dataHolder = new DataHolder();
|
/**
|
* a timeout for single connection handler. if master makes a new connection for every data request,
|
* we should close it's last connection as soon as possible. Else, if master is working through a single connection,
|
* we should be waiting for the next request as long as it is possible :).
|
*/
|
private volatile int readTimeout = Modbus.MAX_RESPONSE_TIMEOUT;
|
|
protected ModbusSlave() {
|
}
|
|
public int getReadTimeout() {
|
return readTimeout;
|
}
|
|
public void setReadTimeout(int readTimeout) {
|
this.readTimeout = readTimeout;
|
for (ModbusConnection conn : getConnectionList()) {
|
conn.setReadTimeout(readTimeout);
|
}
|
}
|
|
abstract protected void listenImpl() throws ModbusIOException;
|
|
abstract protected void shutdownImpl() throws ModbusIOException;
|
|
/**
|
* starts the ModbusSlave thread.
|
*/
|
final public void listen() throws ModbusIOException {
|
listenImpl();
|
setListening(true);
|
}
|
|
/**
|
* should have stop the thread of the ModbusSlave.
|
*/
|
final public void shutdown() throws ModbusIOException {
|
setListening(false);
|
shutdownImpl();
|
}
|
|
public boolean isListening() {
|
return listening.get();
|
}
|
|
protected void setListening(boolean listening) {
|
this.listening.set(listening);
|
}
|
|
/*Getters & Setters*/
|
public DataHolder getDataHolder() {
|
return dataHolder;
|
}
|
|
public void setDataHolder(DataHolderBuilder builder) {
|
setDataHolder(builder.build());
|
}
|
|
public void setDataHolder(DataHolder dataHolder) {
|
this.dataHolder = dataHolder;
|
}
|
|
public int getServerAddress() {
|
return serverAddress;
|
}
|
|
public void setServerAddress(int serverAddress) {
|
if (Modbus.checkServerAddress(serverAddress))
|
this.serverAddress = serverAddress;
|
}
|
|
public boolean isBroadcastEnabled() {
|
return broadcastEnabled.get();
|
}
|
|
public void setBroadcastEnabled(boolean broadcastEnabled) {
|
this.broadcastEnabled.set(broadcastEnabled);
|
}
|
|
protected List<ModbusConnection> getConnectionList() {
|
return connectionList;
|
}
|
|
void connectionOpened(ModbusConnection connection) {
|
connection.setReadTimeout(getReadTimeout());
|
getConnectionList().add(connection);
|
}
|
|
void connectionClosed(ModbusConnection connection) {
|
getConnectionList().remove(connection);
|
}
|
|
@Override
|
public void addListener(FrameEventListener listener) {
|
for (ModbusConnection c : getConnectionList()) {
|
c.addListener(listener);
|
}
|
}
|
|
@Override
|
public void removeListener(FrameEventListener listener) {
|
for (ModbusConnection c : getConnectionList()) {
|
c.removeListener(listener);
|
}
|
}
|
|
@Override
|
public void removeListeners() {
|
for (ModbusConnection c : getConnectionList()) {
|
c.removeListeners();
|
}
|
}
|
|
@Override
|
public void fireFrameReceivedEvent(FrameEvent event) {
|
for (ModbusConnection c : getConnectionList()) {
|
c.fireFrameReceivedEvent(event);
|
}
|
}
|
|
@Override
|
public void fireFrameSentEvent(FrameEvent event) {
|
for (ModbusConnection c : getConnectionList()) {
|
c.fireFrameSentEvent(event);
|
}
|
}
|
|
@Override
|
public int countListeners() {
|
int count = 0;
|
for (ModbusConnection c : getConnectionList()) {
|
count += c.countListeners();
|
}
|
return count;
|
}
|
|
/*
|
facade
|
*/
|
public void addObserver(Observer observer) {
|
observable.addObserver(observer);
|
}
|
|
public void deleteObserver(Observer observer) {
|
observable.deleteObserver(observer);
|
}
|
|
public void deleteObservers() {
|
observable.deleteObservers();
|
}
|
|
public int countObservers() {
|
return observable.countObservers();
|
}
|
|
protected void notifyObservers(Object o) {
|
observable.notifyObservers(o);
|
}
|
}
|