use of org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint in project openhab-addons by openhab.
the class StiebelEltronHandler method writeInt16.
/**
* @param address address of the value to be written on the modbus
* @param shortValue value to be written on the modbus
*/
protected void writeInt16(int address, short shortValue) {
StiebelEltronConfiguration myconfig = StiebelEltronHandler.this.config;
ModbusCommunicationInterface mycomms = StiebelEltronHandler.this.comms;
if (myconfig == null || mycomms == null) {
throw new IllegalStateException("registerPollTask called without proper configuration");
}
// big endian byte ordering
byte hi = (byte) (shortValue >> 8);
byte lo = (byte) shortValue;
ModbusRegisterArray data = new ModbusRegisterArray(hi, lo);
ModbusWriteRegisterRequestBlueprint request = new ModbusWriteRegisterRequestBlueprint(slaveId, address, data, false, myconfig.getMaxTries());
mycomms.submitOneTimeWrite(request, result -> {
if (hasConfigurationError()) {
return;
}
logger.debug("Successful write, matching request {}", request);
StiebelEltronHandler.this.updateStatus(ThingStatus.ONLINE);
}, failure -> {
StiebelEltronHandler.this.handleWriteError(failure);
});
}
use of org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint in project openhab-addons by openhab.
the class ModbusDataHandlerTest method testWriteRealTransformation5.
@Test
public void testWriteRealTransformation5() throws InvalidSyntaxException {
captureModbusWrites();
mockTransformation("PLUS", new TransformationService() {
@Override
public String transform(String arg, String source) throws TransformationException {
return String.valueOf(Integer.parseInt(arg) + Integer.parseInt(source));
}
});
mockTransformation("CONCAT", new TransformationService() {
@Override
public String transform(String function, String source) throws TransformationException {
return source + function;
}
});
mockTransformation("MULTIPLY", new MultiplyTransformation());
ModbusDataThingHandler dataHandler = testWriteHandlingGeneric("50", "MULTIPLY:3∩PLUS(2)∩CONCAT(0)", ModbusConstants.ValueType.INT16, "holding", ModbusWriteFunctionCode.WRITE_SINGLE_REGISTER, "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_SINGLE_REGISTER)));
assertThat(writeRequest.getReference(), is(equalTo(50)));
assertThat(((ModbusWriteRegisterRequestBlueprint) writeRequest).getRegisters().size(), is(equalTo(1)));
assertThat(((ModbusWriteRegisterRequestBlueprint) writeRequest).getRegisters().getRegister(0), is(equalTo(/* (2*3 + 2) + '0' */
80)));
}
use of org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint in project openhab-addons by openhab.
the class ModbusDataHandlerTest method testWriteRealTransformation3.
@Test
public void testWriteRealTransformation3() throws InvalidSyntaxException {
captureModbusWrites();
mockTransformation("RANDOM", new TransformationService() {
@Override
public String transform(String function, String source) throws TransformationException {
return "5";
}
});
ModbusDataThingHandler dataHandler = testWriteHandlingGeneric("50", "RANDOM(foobar)", ModbusConstants.ValueType.INT16, "holding", ModbusWriteFunctionCode.WRITE_SINGLE_REGISTER, "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_SINGLE_REGISTER)));
assertThat(writeRequest.getReference(), is(equalTo(50)));
assertThat(((ModbusWriteRegisterRequestBlueprint) writeRequest).getRegisters().size(), is(equalTo(1)));
assertThat(((ModbusWriteRegisterRequestBlueprint) writeRequest).getRegisters().getRegister(0), is(equalTo(5)));
}
use of org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint 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.ModbusWriteRegisterRequestBlueprint in project openhab-core by openhab.
the class WriteRequestJsonUtilities method constructBluerint.
private static ModbusWriteRequestBlueprint constructBluerint(int unitId, @Nullable JsonElement functionCodeElem, @Nullable JsonElement addressElem, @Nullable JsonElement maxTriesElem, @Nullable JsonArray valuesElem) {
int functionCodeNumeric;
if (functionCodeElem == null || functionCodeElem.isJsonNull()) {
throw new IllegalStateException(String.format("Value for '%s' is invalid", JSON_FUNCTION_CODE));
}
try {
functionCodeNumeric = functionCodeElem.getAsInt();
} catch (ClassCastException | IllegalStateException e) {
throw new IllegalStateException(String.format("Value for '%s' is invalid", JSON_FUNCTION_CODE), e);
}
ModbusWriteFunctionCode functionCode = ModbusWriteFunctionCode.fromFunctionCode(functionCodeNumeric);
int address;
if (addressElem == null || addressElem.isJsonNull()) {
throw new IllegalStateException(String.format("Value for '%s' is invalid", JSON_ADDRESS));
}
try {
address = addressElem.getAsInt();
} catch (ClassCastException | IllegalStateException e) {
throw new IllegalStateException(String.format("Value for '%s' is invalid", JSON_ADDRESS), e);
}
int maxTries;
if (maxTriesElem == null || maxTriesElem.isJsonNull()) {
// Go with default
maxTries = DEFAULT_MAX_TRIES;
} else {
try {
maxTries = maxTriesElem.getAsInt();
} catch (ClassCastException | IllegalStateException e) {
throw new IllegalStateException(String.format("Value for '%s' is invalid", JSON_MAX_TRIES), e);
}
}
if (valuesElem == null || valuesElem.isJsonNull()) {
throw new IllegalArgumentException(String.format("Expecting non-null value, got: %s", valuesElem));
}
AtomicBoolean writeSingle = new AtomicBoolean(false);
switch(functionCode) {
case WRITE_COIL:
writeSingle.set(true);
if (valuesElem.size() != 1) {
throw new IllegalArgumentException(String.format("Expecting single value with functionCode=%s, got: %d", functionCode, valuesElem));
}
// fall-through to WRITE_MULTIPLE_COILS
case WRITE_MULTIPLE_COILS:
if (valuesElem.size() == 0) {
throw new IllegalArgumentException("Must provide at least one coil");
} else if (valuesElem.size() > ModbusConstants.MAX_BITS_WRITE_COUNT) {
throw new IllegalArgumentException(String.format("Trying to write too many coils (%d). Maximum is %s", valuesElem.size(), ModbusConstants.MAX_BITS_WRITE_COUNT));
}
BitArray bits = new BitArray(valuesElem.size());
for (int i = 0; i < valuesElem.size(); i++) {
bits.setBit(i, valuesElem.get(i).getAsInt() != 0);
}
return new ModbusWriteCoilRequestBlueprint(unitId, address, bits, !writeSingle.get(), maxTries);
case WRITE_SINGLE_REGISTER:
writeSingle.set(true);
if (valuesElem.size() != 1) {
throw new IllegalArgumentException(String.format("Expecting single value with functionCode=%s, got: %d", functionCode, valuesElem));
}
// fall-through to WRITE_MULTIPLE_REGISTERS
case WRITE_MULTIPLE_REGISTERS:
{
int[] registers = new int[valuesElem.size()];
if (registers.length == 0) {
throw new IllegalArgumentException("Must provide at least one register");
} else if (valuesElem.size() > ModbusConstants.MAX_REGISTERS_WRITE_COUNT) {
throw new IllegalArgumentException(String.format("Trying to write too many registers (%d). Maximum is %s", valuesElem.size(), ModbusConstants.MAX_REGISTERS_WRITE_COUNT));
}
for (int i = 0; i < valuesElem.size(); i++) {
registers[i] = valuesElem.get(i).getAsInt();
}
return new ModbusWriteRegisterRequestBlueprint(unitId, address, new ModbusRegisterArray(registers), !writeSingle.get(), maxTries);
}
default:
throw new IllegalArgumentException("Unknown function code");
}
}
Aggregations