Skip to content
This repository has been archived by the owner on May 17, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1383 from nix843/modbus-value-types
Browse files Browse the repository at this point in the history
Modbus combined registers direct support
  • Loading branch information
kaikreuzer committed Sep 7, 2014
2 parents a6ad169 + 39aa017 commit 14e1b42
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ public interface ModbusBindingProvider extends BindingProvider {

static final String[] SLAVE_DATA_TYPES = { TYPE_COIL, TYPE_DISCRETE, TYPE_HOLDING, TYPE_INPUT };

/**
* Value type, primary for "input" type
*/
static final public String VALUE_TYPE_BIT = "bit";
static final public String VALUE_TYPE_INT8 = "int8";
static final public String VALUE_TYPE_UINT8 = "uint8";
static final public String VALUE_TYPE_INT16 = "int16";
static final public String VALUE_TYPE_UINT16 = "uint16";
static final public String VALUE_TYPE_INT32 = "int32";
static final public String VALUE_TYPE_UINT32 = "uint32";
static final public String VALUE_TYPE_FLOAT32 = "float32";

static final String[] VALUE_TYPES = { VALUE_TYPE_BIT, VALUE_TYPE_INT8, VALUE_TYPE_UINT8, VALUE_TYPE_INT16, VALUE_TYPE_UINT16, VALUE_TYPE_INT32, VALUE_TYPE_UINT32, VALUE_TYPE_FLOAT32 };

/**
* Returns Modbus item configuration
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import net.wimpi.modbus.procimg.InputRegister;
import net.wimpi.modbus.util.BitVector;
Expand Down Expand Up @@ -52,7 +55,7 @@ public class ModbusBinding extends AbstractActiveBinding<ModbusBindingProvider>
private static final String SERIAL_PREFIX = "serial";

private static final Pattern EXTRACT_MODBUS_CONFIG_PATTERN =
Pattern.compile("^("+TCP_PREFIX+"|"+SERIAL_PREFIX+"|)\\.(.*?)\\.(connection|id|pollInterval|start|length|type)$");
Pattern.compile("^("+TCP_PREFIX+"|"+SERIAL_PREFIX+"|)\\.(.*?)\\.(connection|id|pollInterval|start|length|type|valuetype)$");

/** Stores instances of all the slaves defined in cfg file */
private static Map<String, ModbusSlave> modbusSlaves = new ConcurrentHashMap<String, ModbusSlave>();
Expand Down Expand Up @@ -105,23 +108,63 @@ protected void internalUpdateItem(String slaveName, InputRegister[] registers,
if (provider.providesBindingFor(itemName)) {
ModbusBindingConfig config = provider.getConfig(itemName);
if (config.slaveName.equals(slaveName)) {
InputRegister value = registers[config.readRegister];
String slaveValueType = modbusSlaves.get(slaveName).getValueType();

State newState = extractStateFromRegisters(registers, config.readRegister, slaveValueType);
if (config.getItem() instanceof SwitchItem) {
if (value.getValue() == 0 && (provider.getConfig(itemName).getItemState() != OnOffType.OFF)) {
eventPublisher.postUpdate(itemName, OnOffType.OFF);
} else if (value.getValue() != 0 && (provider.getConfig(itemName).getItemState() != OnOffType.ON)) {
eventPublisher.postUpdate(itemName, OnOffType.ON);
}
} else {
DecimalType newState = new DecimalType(value.getValue());
if (!newState.equals(provider.getConfig(itemName).getItemState()))
eventPublisher.postUpdate(itemName, newState);
newState = newState.equals(DecimalType.ZERO) ? OnOffType.OFF : OnOffType.ON;
}

State currentState = config.getItemState();
if (! newState.equals(currentState))
eventPublisher.postUpdate(itemName, newState);
}
}
}
}

private DecimalType extractStateFromRegisters(InputRegister[] registers, int index, String type) {
if (type.equals(ModbusBindingProvider.VALUE_TYPE_BIT)) {
return new DecimalType((registers[index / 16].toUnsignedShort() >> (index % 16)) & 1);
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_INT8)) {
return new DecimalType(registers[index / 2].toBytes()[1 - (index % 2)]);
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_UINT8)) {
return new DecimalType((registers[index / 2].toUnsignedShort() >> (8 * (index % 2))) & 0xff);
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_INT16)) {
ByteBuffer buff = ByteBuffer.allocate(2);
buff.put(registers[index].toBytes());
return new DecimalType(buff.order(ByteOrder.BIG_ENDIAN).getShort(0));
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_UINT16)) {
return new DecimalType(registers[index].toUnsignedShort());
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_INT32)) {
ByteBuffer buff = ByteBuffer.allocate(4);
buff.put(registers[index * 2 + 0].toBytes());
buff.put(registers[index * 2 + 1].toBytes());
return new DecimalType(buff.order(ByteOrder.BIG_ENDIAN).getInt(0));
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_UINT32)) {
ByteBuffer buff = ByteBuffer.allocate(8);
buff.position(4);
buff.put(registers[index * 2 + 0].toBytes());
buff.put(registers[index * 2 + 1].toBytes());
return new DecimalType(buff.order(ByteOrder.BIG_ENDIAN).getLong(0));
}
else if (type.equals(ModbusBindingProvider.VALUE_TYPE_FLOAT32)) {
ByteBuffer buff = ByteBuffer.allocate(4);
buff.put(registers[index * 2 + 0].toBytes());
buff.put(registers[index * 2 + 1].toBytes());
return new DecimalType(buff.order(ByteOrder.BIG_ENDIAN).getFloat(0));
}
else {
throw new IllegalArgumentException();
}
}

/**
* Posts update event to OpenHAB bus for "coil" type slaves
* @param binding ModbusBinding to get item configuration from BindingProviding
Expand Down Expand Up @@ -253,6 +296,12 @@ public void updated(Dictionary<String, ?> config) throws ConfigurationException
} else {
throw new ConfigurationException(configKey, "the given slave type '" + value + "' is invalid");
}
} else if ("valuetype".equals(configKey)) {
if (ArrayUtils.contains(ModbusBindingProvider.VALUE_TYPES, value)) {
modbusSlave.setValueType(value);
} else {
throw new ConfigurationException(configKey, "the given value type '" + value + "' is invalid");
}
} else {
throw new ConfigurationException(configKey,
"the given configKey '" + configKey + "' is unknown");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public static void setWriteMultipleRegisters(boolean setwmr) {
}

/**
* Type of data porived by the physical device
* Type of data provided by the physical device
* "coil" and "discrete" use boolean (bit) values
* "input" and "holding" use byte values
*/
Expand All @@ -75,6 +75,15 @@ public static void setWriteMultipleRegisters(boolean setwmr) {

private int length = 0;

/**
* How to interpret Modbus register values.
* Examples:
* uint16 - one register - one unsigned integer value (default)
* int32 - every two registers will be interpreted as single 32-bit integer value
* bit - every register will be interpreted as 16 independent 1-bit values
*/
private String valueType = ModbusBindingProvider.VALUE_TYPE_UINT16;

private Object storage;
protected ModbusTransaction transaction = null;

Expand Down Expand Up @@ -358,4 +367,12 @@ void setType(String type) {
this.type = type;
}

String getValueType() {
return valueType;
}

void setValueType(String valueType) {
this.valueType = valueType;
}

}
5 changes: 5 additions & 0 deletions distribution/openhabhome/configurations/openhab_default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,11 @@ ntp:hostname=ptbtime1.ptb.de
# (optional, defaults to '0' - but set it to something meaningful)
#modbus:slave1.length=

# Value type, required for combined registers (details: http://www.simplymodbus.ca/FAQ.htm#Types)
# Can be "bit", "int8", "uint8", "int16", "uint16", "int32", "uint32", "float32"
# (optional, defaults to 'uint16')
#modbus:slave1.valuetype=

############################### PLC Bus Binding #######################################
#
# PLCBus adapter serial port
Expand Down

0 comments on commit 14e1b42

Please sign in to comment.