[modbus] Add convenience class for ThingHandlers (#8634)

* [modbus] Add convenience class for ThingHandlers

Signed-off-by: Fabian Wolter <github@fabian-wolter.de>
This commit is contained in:
Fabian Wolter
2020-11-24 03:38:07 +01:00
committed by GitHub
parent 4911fd0c4a
commit d0b5267ff3
2 changed files with 263 additions and 2 deletions

View File

@@ -75,21 +75,70 @@ You can also use `modpoll` to write data:
./modpoll -m tcp -a 1 -r 1 -t4:float -p 502 127.0.0.1 3.14
```
## Extending Modbus binding
## Extending Modbus Binding
This Modbus binding can be extended by other OSGi bundles to add more specific support for Modbus enabled devices.
To do so to you have to create a new OSGi bundle which has the same binding id as this binding.
The best way is to use the `ModbusBindingConstants.BINDING_ID` constant.
### Thing Handler
You will have to create one or more handler classes for the devices you want to support.
For the modbus connection setup and handling you can use the Modbus TCP Slave or Modbus Serial Slave handlers.
Your handler should use these handlers as bridges and you can set up your regular or one shot modbus requests to read from the slave.
This is done by by creating a `BasicPollTaskImpl` and submitting it using the `ModbusManager` `submitOneTimePoll` and `registerRegularPoll` methods.
This is done by extending your `ThingHandler` by `BaseModbusThingHandler`.
You can use the inherited methods `submitOneTimePoll()` and `registerRegularPoll()` to poll values and `submitOneTimeWrite()` to send values to a slave.
The `BaseModbusThingHandler` takes care that every regular poll task is cancelled, when the Thing is disposed.
Despite that, you can cancel the task manually by storing the return value of `registerRegularPoll()` and use it as an argument to `unregisterRegularPoll()`.
Please keep in mind that these reads are asynchronous and they will call your callback once the read is done.
Once you have your data read from the modbus device you can parse and transform them then update your channels to publish these data to the openHAB system.
See the following example:
```java
@NonNullByDefault
public class MyHandler extends BaseModbusThingHandler {
public MyHandler(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
ModbusReadRequestBlueprint blueprint = new ModbusReadRequestBlueprint(42,
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, 0, 1, 2);
submitOneTimePoll(blueprint, this::readSuccessful, this::readError);
}
}
@Override
public void initialize() {
super.initialize();
// do other Thing initialization
ModbusReadRequestBlueprint blueprint = new ModbusReadRequestBlueprint(42,
ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, 0, 1, 2);
registerRegularPoll(blueprint, 1000, 0, this::readSuccessful, this::readError);
}
private void readSuccessful(AsyncModbusReadResult result) {
result.getRegisters().ifPresent(registers -> {
Optional<DecimalType> value = ModbusBitUtilities.extractStateFromRegisters(registers, 0, ValueType.INT16);
// process value
});
}
private void readError(AsyncModbusFailure<ModbusReadRequestBlueprint> error) {
// set the Thing offline
}
}
```
### Discovery
If you write a device specific handler then adding discovery for this device is very welcome.