use of org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint in project openhab-addons by openhab.
the class ModbusDataHandlerTest method testWriteRealTransformation.
@Test
public void testWriteRealTransformation() throws InvalidSyntaxException {
captureModbusWrites();
mockTransformation("MULTIPLY", new MultiplyTransformation());
ModbusDataThingHandler dataHandler = testWriteHandlingGeneric("50", "MULTIPLY(10)", ModbusConstants.ValueType.BIT, "coil", ModbusWriteFunctionCode.WRITE_COIL, "number", new DecimalType("2"), null, bundleContext);
assertSingleStateUpdate(dataHandler, CHANNEL_LAST_WRITE_SUCCESS, is(notNullValue(State.class)));
assertSingleStateUpdate(dataHandler, CHANNEL_LAST_WRITE_ERROR, is(nullValue(State.class)));
assertThat(writeRequests.size(), is(equalTo(1)));
ModbusWriteRequestBlueprint writeRequest = writeRequests.get(0);
assertThat(writeRequest.getFunctionCode(), is(equalTo(ModbusWriteFunctionCode.WRITE_COIL)));
assertThat(writeRequest.getReference(), is(equalTo(50)));
assertThat(((ModbusWriteCoilRequestBlueprint) writeRequest).getCoils().size(), is(equalTo(1)));
// Since transform output is non-zero, it is mapped as "true"
assertThat(((ModbusWriteCoilRequestBlueprint) writeRequest).getCoils().getBit(0), is(equalTo(true)));
}
use of org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint in project openhab-addons by openhab.
the class ModbusDataHandlerTest method testWriteRealTransformation2.
@Test
public void testWriteRealTransformation2() throws InvalidSyntaxException {
captureModbusWrites();
mockTransformation("ZERO", new TransformationService() {
@Override
public String transform(String function, String source) throws TransformationException {
return "0";
}
});
ModbusDataThingHandler dataHandler = testWriteHandlingGeneric("50", "ZERO(foobar)", ModbusConstants.ValueType.BIT, "coil", ModbusWriteFunctionCode.WRITE_COIL, "number", new DecimalType("2"), null, bundleContext);
assertSingleStateUpdate(dataHandler, CHANNEL_LAST_WRITE_SUCCESS, is(notNullValue(State.class)));
assertSingleStateUpdate(dataHandler, CHANNEL_LAST_WRITE_ERROR, is(nullValue(State.class)));
assertThat(writeRequests.size(), is(equalTo(1)));
ModbusWriteRequestBlueprint writeRequest = writeRequests.get(0);
assertThat(writeRequest.getFunctionCode(), is(equalTo(ModbusWriteFunctionCode.WRITE_COIL)));
assertThat(writeRequest.getReference(), is(equalTo(50)));
assertThat(((ModbusWriteCoilRequestBlueprint) writeRequest).getCoils().size(), is(equalTo(1)));
// Since transform output is zero, it is mapped as "false"
assertThat(((ModbusWriteCoilRequestBlueprint) writeRequest).getCoils().getBit(0), is(equalTo(false)));
}
use of org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint in project openhab-addons by openhab.
the class ModbusDataThingHandler method requestFromCommand.
@Nullable
private ModbusWriteRequestBlueprint requestFromCommand(ChannelUID channelUID, Command origCommand, ModbusDataConfiguration config, Command transformedCommand, Integer writeStart) {
ModbusWriteRequestBlueprint request;
boolean writeMultiple = config.isWriteMultipleEvenWithSingleRegisterOrCoil();
String writeType = config.getWriteType();
ModbusPollerThingHandler pollerHandler = this.pollerHandler;
if (writeType == null) {
// disposed thing
return null;
}
if (writeType.equals(WRITE_TYPE_COIL)) {
Optional<Boolean> commandAsBoolean = ModbusBitUtilities.translateCommand2Boolean(transformedCommand);
if (!commandAsBoolean.isPresent()) {
logger.warn("Cannot process command {} with channel {} since command is not OnOffType, OpenClosedType or Decimal trying to write to coil. Do not know how to convert to 0/1. Transformed command was '{}'", origCommand, channelUID, transformedCommand);
return null;
}
boolean data = commandAsBoolean.get();
request = new ModbusWriteCoilRequestBlueprint(slaveId, writeStart, data, writeMultiple, config.getWriteMaxTries());
} else if (writeType.equals(WRITE_TYPE_HOLDING)) {
ValueType writeValueType = this.writeValueType;
if (writeValueType == null) {
// Should not happen in practice, since we are not in configuration error (checked above)
// This will make compiler happy anyways with the null checks
logger.warn("Received command but write value type not set! Ignoring command");
return null;
}
final ModbusRegisterArray data;
if (writeValueType.equals(ValueType.BIT)) {
if (writeSubIndex.isEmpty()) {
// Should not happen! should be in configuration error
logger.error("Bug: sub index not present but writeValueType=BIT. Should be in configuration error");
return null;
}
Optional<Boolean> commandBool = ModbusBitUtilities.translateCommand2Boolean(transformedCommand);
if (commandBool.isEmpty()) {
logger.warn("Data thing is configured to write individual bit but we received command that is not convertible to 0/1 bit. Ignoring.");
return null;
} else if (pollerHandler == null) {
logger.warn("Bug: sub index present but not child of poller. Should be in configuration erro");
return null;
}
// writing bit of an individual register. Using cache from poller
AtomicReference<@Nullable ModbusRegisterArray> cachedRegistersRef = pollerHandler.getLastPolledDataCache();
ModbusRegisterArray mutatedRegisters = cachedRegistersRef.updateAndGet(cachedRegisters -> cachedRegisters == null ? null : combineCommandWithRegisters(cachedRegisters, writeStart, writeSubIndex.get(), commandBool.get()));
if (mutatedRegisters == null) {
logger.warn("Received command to thing with writeValueType=bit (pointing to individual bit of a holding register) but internal cache not yet populated. Ignoring command");
return null;
}
// extract register (first byte index = register index * 2)
byte[] allMutatedBytes = mutatedRegisters.getBytes();
int writeStartRelative = writeStart - pollStart;
data = new ModbusRegisterArray(allMutatedBytes[writeStartRelative * 2], allMutatedBytes[writeStartRelative * 2 + 1]);
} else {
data = ModbusBitUtilities.commandToRegisters(transformedCommand, writeValueType);
}
writeMultiple = writeMultiple || data.size() > 1;
request = new ModbusWriteRegisterRequestBlueprint(slaveId, writeStart, data, writeMultiple, config.getWriteMaxTries());
} else {
// We keep this here for future-proofing the code (new writeType values)
throw new IllegalStateException(String.format("writeType does not equal %s or %s and thus configuration is invalid. Should not end up this far with configuration error.", WRITE_TYPE_COIL, WRITE_TYPE_HOLDING));
}
return request;
}
use of org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint in project openhab-core by openhab.
the class SmokeTest method testOneOffWriteMultipleCoil.
/**
* @throws Exception
*/
@Test
public void testOneOffWriteMultipleCoil() throws Exception {
LoggerFactory.getLogger(this.getClass()).error("STARTING MULTIPLE");
generateData();
ModbusSlaveEndpoint endpoint = getEndpoint();
AtomicInteger unexpectedCount = new AtomicInteger();
AtomicReference<Object> lastData = new AtomicReference<>();
BitArray bits = new BitArray(true, true, false, false, true, true);
try (ModbusCommunicationInterface comms = modbusManager.newModbusCommunicationInterface(endpoint, null)) {
comms.submitOneTimeWrite(new ModbusWriteCoilRequestBlueprint(SLAVE_UNIT_ID, 3, bits, true, 1), result -> {
lastData.set(result.getResponse());
}, failure -> {
unexpectedCount.incrementAndGet();
});
waitForAssert(() -> {
assertThat(unexpectedCount.get(), is(equalTo(0)));
assertThat(lastData.get(), is(notNullValue()));
ModbusResponse response = (ModbusResponse) lastData.get();
assertThat(response.getFunctionCode(), is(equalTo(15)));
assertThat(modbustRequestCaptor.getAllReturnValues().size(), is(equalTo(1)));
ModbusRequest request = modbustRequestCaptor.getAllReturnValues().get(0);
assertThat(request.getFunctionCode(), is(equalTo(15)));
assertThat(((WriteMultipleCoilsRequest) request).getReference(), is(equalTo(3)));
assertThat(((WriteMultipleCoilsRequest) request).getBitCount(), is(equalTo(bits.size())));
BitVector writeRequestCoils = ((WriteMultipleCoilsRequest) request).getCoils();
BitArray writtenBits = new BitArray(BitSet.valueOf(writeRequestCoils.getBytes()), bits.size());
assertThat(writtenBits, is(equalTo(bits)));
}, 6000, 10);
}
LoggerFactory.getLogger(this.getClass()).error("ENDINGMULTIPLE");
}
use of org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint in project openhab-core by openhab.
the class SmokeTest method testOneOffWriteMultipleCoilError.
/**
* Write is out-of-bounds, slave should return error
*
* @throws Exception
*/
@Test
public void testOneOffWriteMultipleCoilError() throws Exception {
generateData();
ModbusSlaveEndpoint endpoint = getEndpoint();
AtomicInteger unexpectedCount = new AtomicInteger();
CountDownLatch callbackCalled = new CountDownLatch(1);
AtomicReference<Exception> lastError = new AtomicReference<>();
BitArray bits = new BitArray(500);
try (ModbusCommunicationInterface comms = modbusManager.newModbusCommunicationInterface(endpoint, null)) {
comms.submitOneTimeWrite(new ModbusWriteCoilRequestBlueprint(SLAVE_UNIT_ID, 3, bits, true, 1), result -> {
unexpectedCount.incrementAndGet();
callbackCalled.countDown();
}, failure -> {
lastError.set(failure.getCause());
callbackCalled.countDown();
});
assertTrue(callbackCalled.await(60, TimeUnit.SECONDS));
assertThat(unexpectedCount.get(), is(equalTo(0)));
assertTrue(lastError.get() instanceof ModbusSlaveErrorResponseException, lastError.toString());
assertThat(modbustRequestCaptor.getAllReturnValues().size(), is(equalTo(1)));
ModbusRequest request = modbustRequestCaptor.getAllReturnValues().get(0);
assertThat(request.getFunctionCode(), is(equalTo(15)));
assertThat(((WriteMultipleCoilsRequest) request).getReference(), is(equalTo(3)));
assertThat(((WriteMultipleCoilsRequest) request).getBitCount(), is(equalTo(bits.size())));
BitVector writeRequestCoils = ((WriteMultipleCoilsRequest) request).getCoils();
BitArray writtenBits = new BitArray(BitSet.valueOf(writeRequestCoils.getBytes()), bits.size());
assertThat(writtenBits, is(equalTo(bits)));
}
}
Aggregations