Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[modbus] Modbus transport API simplification #7994

Merged
merged 57 commits into from
Jul 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
20fa36e
[modbus] exceptions moved to their own namespace
ssalonen Apr 23, 2020
f335ec1
[modbus] read callback refactoring
ssalonen Apr 23, 2020
2db2cd2
[modbus] Write callbacks converted to Functional
ssalonen May 11, 2020
a0a39ed
[modbus] Remove abstraction (unnecessary interfaces not meant for exten)
ssalonen May 11, 2020
9cb3e59
[modbus] ModbusManagerAPI accepts arguments directly, no Task
ssalonen May 15, 2020
14fec3c
[modbus] ModbusManager indirection (Supplier) removed
ssalonen May 17, 2020
722e76c
[modbus] BitArray abstractions removed
ssalonen May 17, 2020
4bb288b
[modbus] ModbusRegister abstractions removed
ssalonen May 17, 2020
b22a525
[modbus] ModbusRegisterArray abstraction removed
ssalonen May 17, 2020
96a895a
[modbus] Write API taking parameters directly
ssalonen May 17, 2020
6b12304
[modbus] rename classes
ssalonen May 17, 2020
5e18326
[modbus] Communication interface to track connection usage
ssalonen May 31, 2020
de935c8
[modbus] spotless:apply
ssalonen Jun 2, 2020
4019373
[modbus.sunspec] Accomodate to new ModbusCommunicationInterface API
ssalonen Jun 2, 2020
4a2574e
[modbus] Tests fixed. Removed Modbus Manager Listener
ssalonen Jun 3, 2020
bfcf519
[modbus] Null fix, connection closed. test for connection closing
ssalonen Jun 5, 2020
8ced7f7
[modbus] test tuning (sometimes fails?)
ssalonen Jun 14, 2020
57967b4
[modbus][sunspec] Removed unused references from sunspec package (#4)
mrbig Jun 16, 2020
d59eed0
[modbus] avoid memory leaking when unregistering poll tasks
ssalonen Jun 16, 2020
81298cc
[modbus] logging severity reduced
ssalonen Jun 16, 2020
73064c5
[modbus] itests: removed unnecessary stubbings
ssalonen Jun 17, 2020
284ae82
[modbus] test fix (callbacks were counted twice in one test)
ssalonen Jun 17, 2020
00525c1
[modbus] tests: increase timeouts, assert before closing comms
ssalonen Jun 17, 2020
125cc5c
[modbus] readability
ssalonen Jun 17, 2020
e72c3c5
[modbus] fixed more tests where we want to close comms after assertions
ssalonen Jun 17, 2020
52be997
[modbus] test hardening, more clear assertions
ssalonen Jun 18, 2020
8cd5aa8
[modbus] connection closing behaviour finetuned
ssalonen Jun 18, 2020
9191ccb
[modbus] Check and disconnect idle connections without transactions
ssalonen Jun 23, 2020
96722e4
[modbus] mvn spotless:apply
ssalonen Jun 23, 2020
6019fce
[modbubs] Fixed log message
ssalonen Jun 24, 2020
f24cc19
[modbus] Race condition fix
ssalonen Jun 24, 2020
6bcf0a2
[modbus] small test fix
ssalonen Jun 24, 2020
65141e6
[modbus] readcallback changed to nonnull
mrbig Jun 29, 2020
e314ead
[modbus] Refactored ModbusCommunicationInterface to have seperate cal…
mrbig Jun 29, 2020
3336492
[modbus] SmokeTest refactored to new api
mrbig Jun 29, 2020
498688c
[modbus] Modbus bundle refactored to use the new api
mrbig Jun 29, 2020
53d99b7
[modbus][sunspec] refactored sunspec bundle to use the new modbus API
mrbig Jun 29, 2020
5c46267
[modbus] refactor modbus tests to use the new api
mrbig Jun 29, 2020
17eabd0
[modbus] Removed ModbusWriteCallback interface from ModbusDataThingHa…
mrbig Jun 30, 2020
995f84f
[modbus] ModbusDataThingHandler does not implement ModbusReadCallback…
mrbig Jun 30, 2020
edc0fc2
[modbus] Fixed caching in ModbusPollerThingHandler
mrbig Jun 30, 2020
d46a349
[modbus] read modbus data as Optionals
ssalonen Jul 4, 2020
95031aa
[modbus] toString for PollResult
ssalonen Jul 4, 2020
27b0ebd
[modbus] fixed confusing variable name
ssalonen Jul 4, 2020
100532d
[modbus] Disallow null callbacks
ssalonen Jul 4, 2020
2db4f20
[modbus] mvn spotless:apply
ssalonen Jul 4, 2020
1b2a6ca
[modbus] Removing Nullable decorations
ssalonen Jul 4, 2020
d2d6d71
[modbus] submitOneTimeWrite simplification
ssalonen Jul 4, 2020
a988ff5
[modbus] Less verbose logging
ssalonen Jul 4, 2020
80e7a5f
[modbus] submitOneTimePoll simplification
ssalonen Jul 4, 2020
8de2bd3
[modbus] Less verbose logging
ssalonen Jul 4, 2020
c65e3a6
[modbus] Many null warnings removed
ssalonen Jul 4, 2020
735d9d6
[modbus] Fix: no need for a @NonNull annotation because it is default
ssalonen Jul 4, 2020
34ade13
[modbus] Removing unneeded Nullable, using final in immutables
ssalonen Jul 6, 2020
1a8df8d
[modbus] Explicit functional interface
ssalonen Jul 6, 2020
00b7f76
[modbus] @Nullable and @NonNullByDefault aligned with coding conventions
ssalonen Jul 8, 2020
6a46de1
[modbus] Collections.emptyMap instead of allocating new map every time.
ssalonen Jul 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.common.registry.Identifiable;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.openhab.io.transport.modbus.ModbusManager;
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;

/**
* Base interface for thing handlers of endpoint things
Expand All @@ -29,13 +28,13 @@
public interface ModbusEndpointThingHandler extends Identifiable<ThingUID> {

/**
* Gets the {@link ModbusSlaveEndpoint} represented by the thing
* Gets the {@link ModbusCommunicationInterface} represented by the thing
*
* Note that the endpoint can be <code>null</code> in case of incomplete initialization
* Note that this can be <code>null</code> in case of incomplete initialization
*
* @return endpoint represented by this thing handler
* @return communication interface represented by this thing handler
*/
public @Nullable ModbusSlaveEndpoint asSlaveEndpoint();
public @Nullable ModbusCommunicationInterface getCommunicationInterface();

/**
* Get Slave ID, also called as unit id, represented by the thing
Expand All @@ -45,13 +44,6 @@ public interface ModbusEndpointThingHandler extends Identifiable<ThingUID> {
*/
public int getSlaveId() throws EndpointNotInitializedException;

/**
* Get {@link ModbusManager}
*
* @return reference to ModbusManager
*/
public ModbusManager getModbusManager();

/**
* Return true if auto discovery is enabled for this endpoint
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@
import org.openhab.binding.modbus.internal.config.ModbusPollerConfiguration;
import org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler;
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
import org.openhab.io.transport.modbus.ModbusManager;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
import org.openhab.io.transport.modbus.ModbusReadCallback;
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
import org.openhab.io.transport.modbus.PollTask;
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -159,17 +158,16 @@ public ModbusPollerReadRequest(ModbusPollerConfiguration config,
private ModbusPollerConfiguration config;
private long cacheMillis;
private volatile @Nullable PollTask pollTask;
private volatile @Nullable ModbusSlaveEndpoint endpoint;
private volatile @Nullable ModbusReadRequestBlueprint request;
private ModbusManager modbusManager;
private volatile boolean disposed;
private volatile List<ModbusReadCallback> childCallbacks = new CopyOnWriteArrayList<>();
@NonNullByDefault({})
private ModbusCommunicationInterface comms;

private ReadCallbackDelegator callbackDelegator = new ReadCallbackDelegator();

public ModbusPollerThingHandler(Bridge bridge, ModbusManager modbusManager) {
public ModbusPollerThingHandler(Bridge bridge) {
super(bridge);
this.modbusManager = modbusManager;
}

@Override
Expand Down Expand Up @@ -211,6 +209,7 @@ public synchronized void initialize() {
updateStatus(ThingStatus.OFFLINE);
}
this.callbackDelegator.resetCache();
comms = null;
disposed = false;
logger.trace("Initializing {} from status {}", this.getThing().getUID(), this.getThing().getStatus());
try {
Expand All @@ -233,6 +232,7 @@ public synchronized void dispose() {
disposed = true;
unregisterPollTask();
this.callbackDelegator.resetCache();
comms = null;
}

/**
Expand All @@ -248,11 +248,11 @@ public synchronized void unregisterPollTask() {
PollTask localPollTask = this.pollTask;
if (localPollTask != null) {
logger.debug("Unregistering polling from ModbusManager");
modbusManager.unregisterRegularPoll(localPollTask);
comms.unregisterRegularPoll(localPollTask);
}
this.pollTask = null;
request = null;
endpoint = null;
comms = null;
updateStatus(ThingStatus.OFFLINE);
}

Expand All @@ -278,14 +278,14 @@ private synchronized void registerPollTask() throws EndpointNotInitializedExcept
logger.debug("No bridge handler available -- aborting init for {}", this);
return;
}
ModbusSlaveEndpoint localEndpoint = slaveEndpointThingHandler.asSlaveEndpoint();
this.endpoint = localEndpoint;
if (localEndpoint == null) {
ModbusCommunicationInterface localComms = slaveEndpointThingHandler.getCommunicationInterface();
if (localComms == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, String.format(
"Bridge '%s' not completely initialized", Optional.ofNullable(getBridge()).map(b -> b.getLabel())));
logger.debug("Bridge not initialized fully (no endpoint) -- aborting init for {}", this);
logger.debug("Bridge not initialized fully (no communication interface) -- aborting init for {}", this);
return;
}
this.comms = localComms;

ModbusReadRequestBlueprint localRequest = new ModbusPollerReadRequest(config, slaveEndpointThingHandler);
this.request = localRequest;
Expand All @@ -295,8 +295,7 @@ private synchronized void registerPollTask() throws EndpointNotInitializedExcept
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, "Not polling");
} else {
logger.debug("Registering polling with ModbusManager");
pollTask = modbusManager.registerRegularPoll(localEndpoint, localRequest, config.getRefresh(), 0,
callbackDelegator);
pollTask = localComms.registerRegularPoll(localRequest, config.getRefresh(), 0, callbackDelegator);
assert pollTask != null;
updateStatus(ThingStatus.ONLINE);
}
Expand Down Expand Up @@ -330,15 +329,6 @@ public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) {
}
}

/**
* Get {@link ModbusManager}
*
* @return ModbusManger instance
*/
public ModbusManager getModbusManager() {
return modbusManager;
}

/**
* Return {@link ModbusReadRequestBlueprint} represented by this thing.
*
Expand All @@ -351,14 +341,12 @@ public ModbusManager getModbusManager() {
}

/**
* Return {@link ModbusSlaveEndpoint} associated with this thing
*
* Note that endpoint might be <code>null</code> in case initialization is not complete.
* Get communication interface associated with this poller
*
* @return endpoint associated with this poller
* @return
*/
public @Nullable ModbusSlaveEndpoint getEndpoint() {
return endpoint;
public ModbusCommunicationInterface getCommunicationInterface() {
return comms;
}

/**
Expand All @@ -383,9 +371,9 @@ public void refresh() {
// cache expired, poll new data
logger.debug("Poller {} received refresh() but the cache is not applicable. Polling new data",
getThing().getUID());
ModbusSlaveEndpoint localEndpoint = endpoint;
if (localEndpoint != null) {
modbusManager.submitOneTimePoll(localEndpoint, localRequest, callbackDelegator);
ModbusCommunicationInterface localComms = comms;
if (localComms != null) {
localComms.submitOneTimePoll(localRequest, callbackDelegator);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new ModbusSerialThingHandler((Bridge) thing, manager);
} else if (thingTypeUID.equals(THING_TYPE_MODBUS_POLLER)) {
logger.debug("createHandler Modbus poller");
return new ModbusPollerThingHandler((Bridge) thing, manager);
return new ModbusPollerThingHandler((Bridge) thing);
} else if (thingTypeUID.equals(THING_TYPE_MODBUS_DATA)) {
logger.debug("createHandler data");
return new ModbusDataThingHandler(thing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.smarthome.core.types.Command;
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
import org.openhab.binding.modbus.internal.ModbusConfigurationException;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
import org.openhab.io.transport.modbus.ModbusManager;
import org.openhab.io.transport.modbus.ModbusManagerListener;
import org.openhab.io.transport.modbus.endpoint.EndpointPoolConfiguration;
Expand Down Expand Up @@ -49,6 +50,8 @@ public abstract class AbstractModbusEndpointThingHandler<E extends ModbusSlaveEn
@Nullable
protected volatile EndpointPoolConfiguration poolConfiguration;
private final Logger logger = LoggerFactory.getLogger(AbstractModbusEndpointThingHandler.class);
@NonNullByDefault({})
private ModbusCommunicationInterface comms;

public AbstractModbusEndpointThingHandler(Bridge bridge, ModbusManager modbusManager) {
super(bridge);
Expand Down Expand Up @@ -76,7 +79,7 @@ public void initialize() {
throw new IllegalArgumentException("endpoint null after configuration!");
}
modbusManager.addListener(this);
modbusManager.setEndpointPoolConfiguration(endpoint, poolConfiguration);
comms = modbusManager.newModbusCommunicationInterface(endpoint, poolConfiguration);
updateStatus(ThingStatus.ONLINE);
} catch (ModbusConfigurationException e) {
logger.debug("Exception during initialization", e);
Expand All @@ -91,16 +94,13 @@ public void initialize() {
@Override
public void dispose() {
modbusManager.removeListener(this);
}

@Override
public @Nullable ModbusSlaveEndpoint asSlaveEndpoint() {
return endpoint;
}

@Override
public ModbusManager getModbusManager() {
return modbusManager;
try {
comms.close();
} catch (Exception e) {
logger.error("Error closing modbus communication interface", e);
ssalonen marked this conversation as resolved.
Show resolved Hide resolved
} finally {
comms = null;
}
}

@Override
Expand All @@ -119,6 +119,11 @@ public void onEndpointPoolConfigurationSet(ModbusSlaveEndpoint otherEndpoint,
}
}

@Override
public @Nullable ModbusCommunicationInterface getCommunicationInterface() {
return comms;
}

@Override
public abstract int getSlaveId();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@
import org.openhab.io.transport.modbus.AsyncModbusWriteResult;
import org.openhab.io.transport.modbus.BitArray;
import org.openhab.io.transport.modbus.ModbusBitUtilities;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
import org.openhab.io.transport.modbus.ModbusConstants;
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
import org.openhab.io.transport.modbus.ModbusManager;
import org.openhab.io.transport.modbus.ModbusReadCallback;
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
Expand All @@ -77,10 +77,8 @@
import org.openhab.io.transport.modbus.ModbusWriteCoilRequestBlueprint;
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
import org.openhab.io.transport.modbus.exception.ModbusConnectionException;
import org.openhab.io.transport.modbus.exception.ModbusTransportException;
import org.openhab.io.transport.modbus.internal.BasicWriteTask;
import org.openhab.io.transport.modbus.json.WriteRequestJsonUtilities;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
Expand Down Expand Up @@ -143,8 +141,8 @@ public class ModbusDataThingHandler extends BaseThingHandler implements ModbusRe
private volatile @Nullable ModbusReadFunctionCode functionCode;
private volatile @Nullable ModbusReadRequestBlueprint readRequest;
private volatile long updateUnchangedValuesEveryMillis;
private volatile @Nullable ModbusSlaveEndpoint slaveEndpoint;
private volatile @Nullable ModbusManager modbusManager;
@NonNullByDefault({})
private volatile ModbusCommunicationInterface comms;
private volatile boolean isWriteEnabled;
private volatile boolean isReadEnabled;
private volatile boolean writeParametersHavingTransformationOnly;
Expand All @@ -168,8 +166,7 @@ public synchronized void handleCommand(ChannelUID channelUID, Command command) {
logger.trace("Thing {} '{}' received command '{}' to channel '{}'", getThing().getUID(), getThing().getLabel(),
command, channelUID);
ModbusDataConfiguration config = this.config;
ModbusManager manager = this.modbusManager;
if (config == null || manager == null) {
if (config == null) {
return;
}

Expand Down Expand Up @@ -223,14 +220,12 @@ public synchronized void handleCommand(ChannelUID channelUID, Command command) {

ModbusWriteRequestBlueprint request = requestFromCommand(channelUID, command, config, transformedCommand.get(),
writeStart);
ModbusSlaveEndpoint slaveEndpoint = this.slaveEndpoint;
if (request == null || slaveEndpoint == null) {
if (request == null) {
return;
}

BasicWriteTask writeTask = new BasicWriteTask(slaveEndpoint, request, this);
logger.trace("Submitting write task: {}", writeTask);
manager.submitOneTimeWrite(writeTask);
logger.trace("Submitting write task {} to endpoint {}", request, comms.getEndpoint());
comms.submitOneTimeWrite(request, this);
}

/**
Expand Down Expand Up @@ -316,9 +311,8 @@ public synchronized void handleCommand(ChannelUID channelUID, Command command) {
}

private void processJsonTransform(Command command, String transformOutput) {
ModbusSlaveEndpoint slaveEndpoint = this.slaveEndpoint;
ModbusManager manager = this.modbusManager;
if (slaveEndpoint == null || manager == null) {
ModbusCommunicationInterface localComms = this.comms;
if (localComms == null) {
return;
}
Collection<ModbusWriteRequestBlueprint> requests;
Expand All @@ -331,9 +325,10 @@ private void processJsonTransform(Command command, String transformOutput) {
return;
}

requests.stream().map(request -> new BasicWriteTask(slaveEndpoint, request, this)).forEach(writeTask -> {
logger.trace("Submitting write task: {} (based from transformation {})", writeTask, transformOutput);
manager.submitOneTimeWrite(writeTask);
requests.stream().forEach(request -> {
logger.trace("Submitting write request: {} to endpoint {} (based from transformation {})", request,
localComms.getEndpoint(), transformOutput);
localComms.submitOneTimeWrite(request, this);
});
}

Expand Down Expand Up @@ -362,16 +357,14 @@ public synchronized void initialize() {
// Write-only thing, parent is endpoint
ModbusEndpointThingHandler endpointHandler = (ModbusEndpointThingHandler) bridgeHandler;
slaveId = endpointHandler.getSlaveId();
slaveEndpoint = endpointHandler.asSlaveEndpoint();
modbusManager = endpointHandler.getModbusManager();
comms = endpointHandler.getCommunicationInterface();
childOfEndpoint = true;
functionCode = null;
readRequest = null;
} else {
ModbusPollerThingHandler localPollerHandler = (ModbusPollerThingHandler) bridgeHandler;
pollerHandler = localPollerHandler;
ModbusReadRequestBlueprint localReadRequest = localPollerHandler.getRequest();
ModbusSlaveEndpoint localEndpoint = localPollerHandler.getEndpoint();
if (localReadRequest == null) {
logger.debug("Poller {} '{}' has no read request -- configuration is changing?", bridge.getUID(),
bridge.getLabel());
Expand All @@ -381,9 +374,8 @@ public synchronized void initialize() {
}
readRequest = localReadRequest;
slaveId = localReadRequest.getUnitID();
slaveEndpoint = localEndpoint;
functionCode = localReadRequest.getFunctionCode();
modbusManager = localPollerHandler.getModbusManager();
comms = localPollerHandler.getCommunicationInterface();
pollStart = localReadRequest.getReference();
childOfEndpoint = false;
}
Expand Down Expand Up @@ -413,8 +405,7 @@ public synchronized void dispose() {
writeStart = null;
pollStart = 0;
slaveId = 0;
slaveEndpoint = null;
modbusManager = null;
comms = null;
functionCode = null;
readRequest = null;
isWriteEnabled = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.function.Supplier;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand Down
Loading