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 all commits
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 @@ -23,10 +23,7 @@
import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory;
import org.openhab.binding.modbus.sunspec.internal.handler.InverterHandler;
import org.openhab.binding.modbus.sunspec.internal.handler.MeterHandler;
import org.openhab.io.transport.modbus.ModbusManager;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -45,23 +42,6 @@ public class SunSpecHandlerFactory extends BaseThingHandlerFactory {
*/
private final Logger logger = LoggerFactory.getLogger(SunSpecHandlerFactory.class);

/**
* Reference to the modbus manager
*/
private ModbusManager manager;

/**
* This factory needs a reference to the ModbusManager wich is provided
* by the org.openhab.io.transport.modbus bundle. Please make
* sure it's installed and enabled before using this bundle
*
* @param manager reference to the ModbusManager. We use this for modbus communication
*/
@Activate
public SunSpecHandlerFactory(@Reference ModbusManager manager) {
this.manager = manager;
}

@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.containsValue(thingTypeUID);
Expand All @@ -75,12 +55,12 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|| thingTypeUID.equals(THING_TYPE_INVERTER_SPLIT_PHASE)
|| thingTypeUID.equals(THING_TYPE_INVERTER_THREE_PHASE)) {
logger.debug("New InverterHandler created");
return new InverterHandler(thing, manager);
return new InverterHandler(thing);
} else if (thingTypeUID.equals(THING_TYPE_METER_SINGLE_PHASE)
|| thingTypeUID.equals(THING_TYPE_METER_SPLIT_PHASE) || thingTypeUID.equals(THING_TYPE_METER_WYE_PHASE)
|| thingTypeUID.equals(THING_TYPE_METER_DELTA_PHASE)) {
logger.debug("New MeterHandler created");
return new MeterHandler(thing, manager);
return new MeterHandler(thing);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,14 @@
import org.openhab.binding.modbus.sunspec.internal.dto.CommonModelBlock;
import org.openhab.binding.modbus.sunspec.internal.dto.ModelBlock;
import org.openhab.binding.modbus.sunspec.internal.parser.CommonModelParser;
import org.openhab.io.transport.modbus.BasicModbusReadRequestBlueprint;
import org.openhab.io.transport.modbus.BasicPollTaskImpl;
import org.openhab.io.transport.modbus.BitArray;
import org.openhab.io.transport.modbus.AsyncModbusFailure;
import org.openhab.io.transport.modbus.ModbusBitUtilities;
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
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.ModbusRegisterArray;
import org.openhab.io.transport.modbus.ModbusSlaveErrorResponseException;
import org.openhab.io.transport.modbus.PollTask;
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
import org.openhab.io.transport.modbus.exception.ModbusSlaveErrorResponseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -68,11 +64,6 @@ public class SunspecDiscoveryProcess {
*/
private final ModbusEndpointThingHandler handler;

/**
* The endpoint where we can reach the device
*/
private final ModbusSlaveEndpoint endpoint;

/**
* Listener for the discovered devices. We get this
* from the main discovery service, and it is used to
Expand Down Expand Up @@ -116,6 +107,11 @@ public class SunspecDiscoveryProcess {
*/
private @Nullable CommonModelBlock lastCommonBlock = null;

/**
* Communication interface to the endpoint
*/
private ModbusCommunicationInterface comms;

/**
* New instances of this class should get a reference to the handler
*
Expand All @@ -125,9 +121,9 @@ public SunspecDiscoveryProcess(ModbusEndpointThingHandler handler, ModbusDiscove
throws EndpointNotInitializedException {
this.handler = handler;

ModbusSlaveEndpoint endpoint = this.handler.asSlaveEndpoint();
if (endpoint != null) {
this.endpoint = endpoint;
ModbusCommunicationInterface localComms = handler.getCommunicationInterface();
if (localComms != null) {
this.comms = localComms;
} else {
throw new EndpointNotInitializedException();
}
Expand Down Expand Up @@ -158,30 +154,13 @@ public void detectModel() {
baseAddress = possibleAddresses.poll();
logger.trace("Beginning scan for SunSpec device at address {}", baseAddress);

BasicModbusReadRequestBlueprint request = new BasicModbusReadRequestBlueprint(slaveId,
ModbusReadRequestBlueprint request = new ModbusReadRequestBlueprint(slaveId,
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, baseAddress, // Start address
SUNSPEC_ID_SIZE, // number or words to return
maxTries);

PollTask task = new BasicPollTaskImpl(endpoint, request, new ModbusReadCallback() {

@Override
public void onRegisters(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) {
headerReceived(registers);
}

@Override
public void onError(ModbusReadRequestBlueprint request, Exception error) {
handleError(error);
}

@Override
public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitArray bits) {
// don't care, we don't expect this result
}
});

handler.getManagerRef().get().submitOneTimePoll(task);
comms.submitOneTimePoll(request, result -> result.getRegisters().ifPresent(this::headerReceived),
this::handleError);
}

/**
Expand Down Expand Up @@ -210,30 +189,13 @@ private void headerReceived(ModbusRegisterArray registers) {
*/
private void lookForModelBlock() {

BasicModbusReadRequestBlueprint request = new BasicModbusReadRequestBlueprint(slaveId,
ModbusReadRequestBlueprint request = new ModbusReadRequestBlueprint(slaveId,
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, baseAddress, // Start address
MODEL_HEADER_SIZE, // number or words to return
maxTries);

PollTask task = new BasicPollTaskImpl(endpoint, request, new ModbusReadCallback() {

@Override
public void onRegisters(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) {
modelBlockReceived(registers);
}

@Override
public void onError(ModbusReadRequestBlueprint request, Exception error) {
handleError(error);
}

@Override
public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitArray bits) {
// don't care, we don't expect this result
}
});

handler.getManagerRef().get().submitOneTimePoll(task);
comms.submitOneTimePoll(request, result -> result.getRegisters().ifPresent(this::modelBlockReceived),
this::handleError);
}

/**
Expand Down Expand Up @@ -280,30 +242,13 @@ private void modelBlockReceived(ModbusRegisterArray registers) {
* @param block
*/
private void readCommonBlock(ModelBlock block) {
BasicModbusReadRequestBlueprint request = new BasicModbusReadRequestBlueprint(slaveId,
ModbusReadRequestBlueprint request = new ModbusReadRequestBlueprint(slaveId,
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, block.address, // Start address
block.length, // number or words to return
maxTries);

PollTask task = new BasicPollTaskImpl(endpoint, request, new ModbusReadCallback() {

@Override
public void onRegisters(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) {
parseCommonBlock(registers);
}

@Override
public void onError(ModbusReadRequestBlueprint request, Exception error) {
handleError(error);
}

@Override
public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitArray bits) {
// don't care, we don't expect this result
}
});

handler.getManagerRef().get().submitOneTimePoll(task);
comms.submitOneTimePoll(request, result -> result.getRegisters().ifPresent(this::parseCommonBlock),
this::handleError);
}

/**
Expand Down Expand Up @@ -367,25 +312,22 @@ private void parsingFinished() {
/**
* Handle errors received during communication
*/
private void handleError(Exception error) {
String msg = "";
String cls = "";

if (blocksFound > 1 && error instanceof ModbusSlaveErrorResponseException) {
int code = ((ModbusSlaveErrorResponseException) error).getExceptionCode();
private void handleError(AsyncModbusFailure<ModbusReadRequestBlueprint> failure) {
if (blocksFound > 1 && failure.getCause() instanceof ModbusSlaveErrorResponseException) {
int code = ((ModbusSlaveErrorResponseException) failure.getCause()).getExceptionCode();
if (code == ModbusSlaveErrorResponseException.ILLEGAL_DATA_ACCESS
|| code == ModbusSlaveErrorResponseException.ILLEGAL_DATA_VALUE) {
// It is very likely that the slave does not report an end block (0xffff) after the main blocks
// so we treat this situation as normal.
logger.debug(
"Seems like slave device does not report an end block. Continouing with the dectected blocks");
"Seems like slave device does not report an end block. Continuing with the dectected blocks");
parsingFinished();
return;
}
}

cls = error.getClass().getName();
msg = error.getMessage();
String cls = failure.getCause().getClass().getName();
String msg = failure.getCause().getMessage();

logger.warn("Error with read at address {}: {} {}", baseAddress, cls, msg);

Expand Down
Loading