use of org.openhab.binding.modbus.internal.ModbusConfigurationException in project openhab-addons by openhab.
the class ModbusDataThingHandler method validateAndParseReadParameters.
private void validateAndParseReadParameters(ModbusDataConfiguration config) throws ModbusConfigurationException {
ModbusReadFunctionCode functionCode = this.functionCode;
boolean readingDiscreteOrCoil = functionCode == ModbusReadFunctionCode.READ_COILS || functionCode == ModbusReadFunctionCode.READ_INPUT_DISCRETES;
boolean readStartMissing = config.getReadStart() == null || config.getReadStart().isBlank();
boolean readValueTypeMissing = config.getReadValueType() == null || config.getReadValueType().isBlank();
if (childOfEndpoint && readRequest == null) {
if (!readStartMissing || !readValueTypeMissing) {
String errmsg = String.format("Thing %s readStart=%s, and readValueType=%s were specified even though the data thing is child of endpoint (that is, write-only)!", getThing().getUID(), config.getReadStart(), config.getReadValueType());
throw new ModbusConfigurationException(errmsg);
}
}
// we assume readValueType=bit by default if it is missing
boolean allMissingOrAllPresent = (readStartMissing && readValueTypeMissing) || (!readStartMissing && (!readValueTypeMissing || readingDiscreteOrCoil));
if (!allMissingOrAllPresent) {
String errmsg = String.format("Thing %s readStart=%s, and readValueType=%s should be all present or all missing!", getThing().getUID(), config.getReadStart(), config.getReadValueType());
throw new ModbusConfigurationException(errmsg);
} else if (!readStartMissing) {
// all read values are present
isReadEnabled = true;
if (readingDiscreteOrCoil && readValueTypeMissing) {
readValueType = ModbusConstants.ValueType.BIT;
} else {
try {
readValueType = ValueType.fromConfigValue(config.getReadValueType());
} catch (IllegalArgumentException e) {
String errmsg = String.format("Thing %s readValueType=%s is invalid!", getThing().getUID(), config.getReadValueType());
throw new ModbusConfigurationException(errmsg);
}
}
if (readingDiscreteOrCoil && !ModbusConstants.ValueType.BIT.equals(readValueType)) {
String errmsg = String.format("Thing %s invalid readValueType: Only readValueType='%s' (or undefined) supported with coils or discrete inputs. Value type was: %s", getThing().getUID(), ModbusConstants.ValueType.BIT, config.getReadValueType());
throw new ModbusConfigurationException(errmsg);
}
} else {
isReadEnabled = false;
}
if (isReadEnabled) {
String readStart = config.getReadStart();
if (readStart == null) {
throw new ModbusConfigurationException(String.format("Thing %s invalid readStart: %s", getThing().getUID(), config.getReadStart()));
}
String[] readParts = readStart.split("\\.", 2);
try {
readIndex = Optional.of(Integer.parseInt(readParts[0]));
if (readParts.length == 2) {
readSubIndex = Optional.of(Integer.parseInt(readParts[1]));
} else {
readSubIndex = Optional.empty();
}
} catch (IllegalArgumentException e) {
String errmsg = String.format("Thing %s invalid readStart: %s", getThing().getUID(), config.getReadStart());
throw new ModbusConfigurationException(errmsg);
}
}
readTransformation = new CascadedValueTransformationImpl(config.getReadTransform());
validateReadIndex();
}
use of org.openhab.binding.modbus.internal.ModbusConfigurationException in project openhab-addons by openhab.
the class ModbusDataThingHandler method validateReadIndex.
private void validateReadIndex() throws ModbusConfigurationException {
@Nullable ModbusReadRequestBlueprint readRequest = this.readRequest;
ValueType readValueType = this.readValueType;
if (!readIndex.isPresent() || readRequest == null) {
return;
}
assert readValueType != null;
// bits represented by the value type, e.g. int32 -> 32
int valueTypeBitCount = readValueType.getBits();
int dataElementBits;
switch(readRequest.getFunctionCode()) {
case READ_INPUT_REGISTERS:
case READ_MULTIPLE_REGISTERS:
dataElementBits = 16;
break;
case READ_COILS:
case READ_INPUT_DISCRETES:
dataElementBits = 1;
break;
default:
throw new IllegalStateException(readRequest.getFunctionCode().toString());
}
boolean bitQuery = dataElementBits == 1;
if (bitQuery && readSubIndex.isPresent()) {
String errmsg = String.format("readStart=X.Y is not allowed to be used with coils or discrete inputs!");
throw new ModbusConfigurationException(errmsg);
}
if (valueTypeBitCount >= 16 && readSubIndex.isPresent()) {
String errmsg = String.format("readStart=X.Y notation is not allowed to be used with value types larger than 16bit! Use readStart=X instead.");
throw new ModbusConfigurationException(errmsg);
} else if (!bitQuery && valueTypeBitCount < 16 && !readSubIndex.isPresent()) {
// User has specified value type which is less than register width (16 bits).
// readStart=X.Y notation must be used to define which data to extract from the 16 bit register.
String errmsg = String.format("readStart=X.Y must be used with value types (readValueType) less than 16bit!");
throw new ModbusConfigurationException(errmsg);
} else if (readSubIndex.isPresent() && (readSubIndex.get() + 1) * valueTypeBitCount > 16) {
// the sub index Y (in X.Y) is above the register limits
String errmsg = String.format("readStart=X.Y, the value Y is too large");
throw new ModbusConfigurationException(errmsg);
}
// Determine bit positions polled, both start and end inclusive
int pollStartBitIndex = readRequest.getReference() * dataElementBits;
int pollEndBitIndex = pollStartBitIndex + readRequest.getDataLength() * dataElementBits - 1;
// Determine bit positions read, both start and end inclusive
int readStartBitIndex = readIndex.get() * dataElementBits + readSubIndex.orElse(0) * valueTypeBitCount;
int readEndBitIndex = readStartBitIndex + valueTypeBitCount - 1;
if (readStartBitIndex < pollStartBitIndex || readEndBitIndex > pollEndBitIndex) {
String errmsg = String.format("Out-of-bounds: Poller is reading from index %d to %d (inclusive) but this thing configured to read '%s' starting from element %d. Exceeds polled data bounds.", pollStartBitIndex / dataElementBits, pollEndBitIndex / dataElementBits, readValueType, readIndex.get());
throw new ModbusConfigurationException(errmsg);
}
}
use of org.openhab.binding.modbus.internal.ModbusConfigurationException in project openhab-addons by openhab.
the class ModbusDataThingHandler method validateWriteIndex.
private void validateWriteIndex() throws ModbusConfigurationException {
@Nullable ModbusReadRequestBlueprint readRequest = this.readRequest;
if (!writeStart.isPresent() || !writeSubIndex.isPresent()) {
//
return;
} else if (readRequest == null) {
// should not happen, already validated
throw new ModbusConfigurationException("Must poll data with writeStart=X.Y");
}
if (writeSubIndex.isPresent() && (writeSubIndex.get() + 1) > 16) {
// the sub index Y (in X.Y) is above the register limits
String errmsg = String.format("readStart=X.Y, the value Y is too large");
throw new ModbusConfigurationException(errmsg);
}
// Determine bit positions polled, both start and end inclusive
int pollStartBitIndex = readRequest.getReference() * 16;
int pollEndBitIndex = pollStartBitIndex + readRequest.getDataLength() * 16 - 1;
// Determine bit positions read, both start and end inclusive
int writeStartBitIndex = writeStart.get() * 16 + readSubIndex.orElse(0);
int writeEndBitIndex = writeStartBitIndex - 1;
if (writeStartBitIndex < pollStartBitIndex || writeEndBitIndex > pollEndBitIndex) {
String errmsg = String.format("Out-of-bounds: Poller is reading from index %d to %d (inclusive) but this thing configured to write starting from element %d. Must write within polled limits", pollStartBitIndex / 16, pollEndBitIndex / 16, writeStart.get());
throw new ModbusConfigurationException(errmsg);
}
}
use of org.openhab.binding.modbus.internal.ModbusConfigurationException in project openhab-addons by openhab.
the class ModbusDataThingHandler method initialize.
@Override
public synchronized void initialize() {
// Long running initialization should be done asynchronously in background.
try {
logger.trace("initialize() of thing {} '{}' starting", thing.getUID(), thing.getLabel());
ModbusDataConfiguration localConfig = config = getConfigAs(ModbusDataConfiguration.class);
updateUnchangedValuesEveryMillis = localConfig.getUpdateUnchangedValuesEveryMillis();
Bridge bridge = getBridge();
if (bridge == null || !bridge.getStatus().equals(ThingStatus.ONLINE)) {
logger.debug("Thing {} '{}' has no bridge or it is not online", getThing().getUID(), getThing().getLabel());
updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "No online bridge");
return;
}
BridgeHandler bridgeHandler = bridge.getHandler();
if (bridgeHandler == null) {
logger.warn("Bridge {} '{}' has no handler.", bridge.getUID(), bridge.getLabel());
String errmsg = String.format("Bridge %s '%s' configuration incomplete or with errors", bridge.getUID(), bridge.getLabel());
throw new ModbusConfigurationException(errmsg);
}
if (bridgeHandler instanceof ModbusEndpointThingHandler) {
// Write-only thing, parent is endpoint
ModbusEndpointThingHandler endpointHandler = (ModbusEndpointThingHandler) bridgeHandler;
slaveId = endpointHandler.getSlaveId();
comms = endpointHandler.getCommunicationInterface();
childOfEndpoint = true;
functionCode = null;
readRequest = null;
} else {
ModbusPollerThingHandler localPollerHandler = (ModbusPollerThingHandler) bridgeHandler;
pollerHandler = localPollerHandler;
ModbusReadRequestBlueprint localReadRequest = localPollerHandler.getRequest();
if (localReadRequest == null) {
logger.debug("Poller {} '{}' has no read request -- configuration is changing or bridge having invalid configuration?", bridge.getUID(), bridge.getLabel());
updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, String.format("Poller %s '%s' has no poll task", bridge.getUID(), bridge.getLabel()));
return;
}
readRequest = localReadRequest;
slaveId = localReadRequest.getUnitID();
functionCode = localReadRequest.getFunctionCode();
comms = localPollerHandler.getCommunicationInterface();
pollStart = localReadRequest.getReference();
childOfEndpoint = false;
}
validateAndParseReadParameters(localConfig);
validateAndParseWriteParameters(localConfig);
validateMustReadOrWrite();
updateStatusIfChanged(ThingStatus.ONLINE);
} catch (ModbusConfigurationException | EndpointNotInitializedException e) {
logger.debug("Thing {} '{}' initialization error: {}", getThing().getUID(), getThing().getLabel(), e.getMessage());
updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
} finally {
logger.trace("initialize() of thing {} '{}' finished", thing.getUID(), thing.getLabel());
}
}
use of org.openhab.binding.modbus.internal.ModbusConfigurationException in project openhab-addons by openhab.
the class ModbusSerialThingHandler method configure.
@Override
protected void configure() throws ModbusConfigurationException {
ModbusSerialConfiguration config = getConfigAs(ModbusSerialConfiguration.class);
String port = config.getPort();
int baud = config.getBaud();
String flowControlIn = config.getFlowControlIn();
String flowControlOut = config.getFlowControlOut();
String stopBits = config.getStopBits();
String parity = config.getParity();
String encoding = config.getEncoding();
if (port == null || flowControlIn == null || flowControlOut == null || stopBits == null || parity == null || encoding == null) {
throw new ModbusConfigurationException("port, baud, flowControlIn, flowControlOut, stopBits, parity, encoding all must be non-null!");
}
this.config = config;
EndpointPoolConfiguration poolConfiguration = new EndpointPoolConfiguration();
this.poolConfiguration = poolConfiguration;
poolConfiguration.setConnectMaxTries(config.getConnectMaxTries());
poolConfiguration.setConnectTimeoutMillis(config.getConnectTimeoutMillis());
poolConfiguration.setInterTransactionDelayMillis(config.getTimeBetweenTransactionsMillis());
// Never reconnect serial connections "automatically"
poolConfiguration.setInterConnectDelayMillis(1000);
poolConfiguration.setReconnectAfterMillis(-1);
endpoint = new ModbusSerialSlaveEndpoint(port, baud, flowControlIn, flowControlOut, config.getDataBits(), stopBits, parity, encoding, config.isEcho(), config.getReceiveTimeoutMillis());
}
Aggregations