/**
* Copyright (c) 2010-2017 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.modbus.internal;
import static org.mockito.Mockito.*;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.openhab.binding.modbus.ModbusBindingProvider;
import org.openhab.core.library.types.DecimalType;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.osgi.service.cm.ConfigurationException;
import net.wimpi.modbus.procimg.InputRegister;
import net.wimpi.modbus.procimg.Register;
import net.wimpi.modbus.procimg.SimpleInputRegister;
import net.wimpi.modbus.procimg.SimpleRegister;
/**
* Parameterized test case that tests reading of both input and holding
* registers
*/
@RunWith(Parameterized.class)
public class ReadRegistersTestCase extends TestCaseSupport {
@Parameters
public static Collection<Object[]> parameters() {
List<Object[]> allParameters = new ArrayList<>();
List<Object[]> baseParameters = Arrays.asList(new Object[][] {
{ false, ModbusBindingProvider.TYPE_INPUT, SimpleInputRegister.class, "addInputRegister",
InputRegister.class },
{ true, ModbusBindingProvider.TYPE_INPUT, SimpleInputRegister.class, "addInputRegister",
InputRegister.class },
{ false, ModbusBindingProvider.TYPE_HOLDING, SimpleRegister.class, "addRegister", Register.class },
{ true, ModbusBindingProvider.TYPE_HOLDING, SimpleRegister.class, "addRegister", Register.class } });
for (ServerType serverType : TEST_SERVERS) {
for (Object[] params : baseParameters) {
ArrayList<Object> paramsWithServer = new ArrayList<>();
paramsWithServer.add(serverType);
paramsWithServer.addAll(Arrays.asList(params));
allParameters.add(paramsWithServer.toArray());
}
}
return allParameters;
}
private boolean nonZeroOffset;
private Constructor<Register> constructRegisterInt;
private Constructor<Register> constructRegister2Byte;
private String type;
private Method addRegisterMethod;
private String spiAddRegisterMethodName;
private Class<?> addRegisterArgClass;
/**
* Return value converted to bytes
*
* Bytes are returned in most significant bit (MSB) order
*/
private byte[] int32AsRegisters(int value) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(value); // writes all 4 bytes as MSB order
byte[] byteArray = baos.toByteArray();
return byteArray;
}
private byte[] int32AsRegistersSwapped(int value) throws IOException {
/**
* Return value converted to bytes (CDAB)
*
* Bytes are returned in most significant bit (MSB) order, but low and high 16 bits swapped (CDAB)
*/
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(value); // writes all 4 bytes as MSB order
byte[] byteArray = baos.toByteArray();
byte a = byteArray[0];
byte b = byteArray[1];
byteArray[0] = byteArray[2];
byteArray[1] = byteArray[3];
byteArray[2] = a;
byteArray[3] = b;
return byteArray;
}
/**
* Return value converted to bytes
*
* Bytes are returned in most significant bit (MSB) order
*/
private byte[] float32AsRegisters(float value) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeFloat(value); // writes all 4 bytes as MSB order
byte[] byteArray = baos.toByteArray();
return byteArray;
}
/**
* @param serverType
* @param nonZeroOffset
* whether to test non-zero start address in modbus binding
* @param type
* type of the slave (e.g. "holding")
* @param registerClass
* register class to instantiate when configuring SPI of the
* server
* @param spiAddRegisterMethodName
* method to call when adding register to SPI
* @param addRegisterArgClass
* argument type of the method corresponding to
* spiAddRegisterMethodName
*/
public ReadRegistersTestCase(ServerType serverType, boolean nonZeroOffset, String type,
Class<Register> registerClass, String spiAddRegisterMethodName, Class<?> addRegisterArgClass)
throws NoSuchMethodException, SecurityException {
this.serverType = serverType;
this.nonZeroOffset = nonZeroOffset;
this.type = type;
this.spiAddRegisterMethodName = spiAddRegisterMethodName;
this.addRegisterArgClass = addRegisterArgClass;
constructRegisterInt = registerClass.getDeclaredConstructor(new Class[] { int.class });
constructRegister2Byte = registerClass.getDeclaredConstructor(new Class[] { byte.class, byte.class });
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
addRegisterMethod = spi.getClass().getMethod(spiAddRegisterMethodName, new Class[] { addRegisterArgClass });
}
/**
* Test reading of input/holding registers, uses valuetype=int8
*/
@Test
public void testReadRegistersInt8()
throws InterruptedException, UnknownHostException, BindingConfigParseException, ConfigurationException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Modbus server ("modbus slave") has input registers
// first register has following bytes (hi byte, lo byte)
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance((byte) 1, (byte) 2));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance((byte) 3, (byte) -4));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance((byte) 5, (byte) 6));
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(99));
binding = new ModbusBinding();
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_INT8,
nonZeroOffset ? 1 : 0, 2));
configureNumberItemBinding(4, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
if (nonZeroOffset) {
// 2nd register, lo byte
verify(eventPublisher).postUpdate("Item1", new DecimalType(-4));
// 2nd register, hi byte
verify(eventPublisher).postUpdate("Item2", new DecimalType(3));
// 3rd register, lo byte
verify(eventPublisher).postUpdate("Item3", new DecimalType(6));
// 3rd register, hi byte
verify(eventPublisher).postUpdate("Item4", new DecimalType(5));
} else {
// 1st register, lo byte
verify(eventPublisher).postUpdate("Item1", new DecimalType(2));
// 1st register, hi byte
verify(eventPublisher).postUpdate("Item2", new DecimalType(1));
// 2nd register, lo byte
verify(eventPublisher).postUpdate("Item3", new DecimalType(-4));
// 2nd register, hi byte
verify(eventPublisher).postUpdate("Item4", new DecimalType(3));
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses valuetype=uint8
*/
@Test
public void testReadRegistersUint8()
throws InterruptedException, UnknownHostException, BindingConfigParseException, ConfigurationException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Modbus server ("modbus slave") has input registers
// first register has following bytes (hi byte, lo byte)
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance((byte) 1, (byte) 2));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance((byte) 3, (byte) -4));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance((byte) 5, (byte) 6));
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(99));
binding = new ModbusBinding();
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_UINT8,
nonZeroOffset ? 1 : 0, 2));
Assert.assertEquals(REFRESH_INTERVAL, binding.getRefreshInterval());
configureNumberItemBinding(4, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
if (nonZeroOffset) {
// 2nd register, lo byte
verify(eventPublisher).postUpdate("Item1", new DecimalType(256 - 4));
// 2nd register, hi byte
verify(eventPublisher).postUpdate("Item2", new DecimalType(3));
// 3rd register, lo byte
verify(eventPublisher).postUpdate("Item3", new DecimalType(6));
// 3rd register, hi byte
verify(eventPublisher).postUpdate("Item4", new DecimalType(5));
} else {
// 1st register, lo byte
verify(eventPublisher).postUpdate("Item1", new DecimalType(2));
// 1st register, hi byte
verify(eventPublisher).postUpdate("Item2", new DecimalType(1));
// 2nd register, lo byte
verify(eventPublisher).postUpdate("Item3", new DecimalType(256 - 4));
// 2nd register, hi byte
verify(eventPublisher).postUpdate("Item4", new DecimalType(3));
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses default valuetype
*/
@Test
public void testReadRegistersUint16()
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
UnknownHostException, ConfigurationException, BindingConfigParseException {
// Modbus server ("modbus slave") has input registers
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(2));
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(-4));
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(99));
binding = new ModbusBinding();
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, null, nonZeroOffset ? 1 : 0, 2));
configureNumberItemBinding(2, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
if (nonZeroOffset) {
verify(eventPublisher).postUpdate("Item1", new DecimalType(65532));
verify(eventPublisher).postUpdate("Item2", new DecimalType(99));
} else {
verify(eventPublisher).postUpdate("Item1", new DecimalType(2));
verify(eventPublisher).postUpdate("Item2", new DecimalType(65532));
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses valuetype=int16
*/
@Test
public void testReadRegistersInt16()
throws InterruptedException, UnknownHostException, BindingConfigParseException, ConfigurationException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Modbus server ("modbus slave") has input registers
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(2));
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(-4));
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(99));
binding = new ModbusBinding();
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_INT16,
nonZeroOffset ? 1 : 0, 2));
configureNumberItemBinding(2, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
if (nonZeroOffset) {
verify(eventPublisher).postUpdate("Item1", new DecimalType(-4));
verify(eventPublisher).postUpdate("Item2", new DecimalType(99));
} else {
verify(eventPublisher).postUpdate("Item1", new DecimalType(2));
verify(eventPublisher).postUpdate("Item2", new DecimalType(-4));
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses valuetype=bit
*
* Items refer to individual bits (lowest significant bit = index 0) of the
* 16bits registers.
*
* In this test, we have items referring to the all 32bits (two registers)
*/
@Test
public void testReadRegistersBit()
throws InterruptedException, UnknownHostException, BindingConfigParseException, ConfigurationException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Modbus server ("modbus slave") has input registers
// 0x0002 = 00000000 00000010
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(2));
// 0xFFFC = 11111111 11111100
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(-4));
// 0x0063 = 00000000 01100011
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(99));
binding = new ModbusBinding();
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_BIT,
nonZeroOffset ? 1 : 0, 2));
configureSwitchItemBinding(32, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
// Bits should correspond to bits of the register, in LSB order.
if (nonZeroOffset) {
verifyBitItems(new StringBuffer("1111111111111100").reverse().toString());
verifyBitItems(new StringBuffer("0000000001100011").reverse().toString(), 16);
} else {
// 1st register bits
verifyBitItems(new StringBuffer("0000000000000010").reverse().toString());
// 2nd register bits
verifyBitItems(new StringBuffer("1111111111111100").reverse().toString(), 16);
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses valuetype=uint32
*
* @throws IOException
*/
@Test
public void testReadRegistersUint32()
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
ConfigurationException, BindingConfigParseException, IOException {
// Modbus server ("modbus slave") has input registers
byte[] registerData = int32AsRegisters(123456789); // 0x075BCD15
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = int32AsRegisters(-123456789); // 0xF8A432EB
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = int32AsRegisters(123456788); // 0x075BCD14
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
binding = new ModbusBinding();
// read 4 registers = 2 uint32 numbers
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_UINT32,
nonZeroOffset ? 1 : 0, 4));
configureNumberItemBinding(2, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
if (nonZeroOffset) {
// 3440769188 = 0xCD15 F8A4 = (1st register lo byte, 2nd register hi
// byte)
verify(eventPublisher).postUpdate("Item1", new DecimalType(3440769188L));
// 854263643 = 0x32EB075B = (2nd register lo byte, 3rd register hi
// byte)
verify(eventPublisher).postUpdate("Item2", new DecimalType(854263643));
} else {
verify(eventPublisher).postUpdate("Item1", new DecimalType(123456789));
verify(eventPublisher).postUpdate("Item2", new DecimalType(4294967296L - 123456789L));
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses valuetype=int32
*
* @throws IOException
*/
@Test
public void testReadRegistersInt32()
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
ConfigurationException, BindingConfigParseException, IOException {
// Modbus server ("modbus slave") has input registers
byte[] registerData = int32AsRegisters(123456789); // 0x075BCD15
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = int32AsRegisters(-123456789); // 0xF8A432EB
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = int32AsRegisters(123456788); // 0x075BCD14
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
binding = new ModbusBinding();
// read 4 registers = 2 uint32 numbers
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_INT32,
nonZeroOffset ? 1 : 0, 4));
configureNumberItemBinding(2, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
if (nonZeroOffset) {
// -854198108 = 0xCD15F8A4 = (1st register lo byte, 2nd register hi
// byte)
verify(eventPublisher).postUpdate("Item1", new DecimalType(-854198108));
// 854263643 = 0x32EB 075B = (2nd register lo byte, 3rd register hi
// byte)
verify(eventPublisher).postUpdate("Item2", new DecimalType(854263643));
} else {
verify(eventPublisher).postUpdate("Item1", new DecimalType(123456789));
verify(eventPublisher).postUpdate("Item2", new DecimalType(-123456789));
}
}
/**
* Test reading of input/holding registers, uses valuetype=int32_swap
*
* @throws IOException
*/
@Test
public void testReadRegistersInt32Swap()
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
ConfigurationException, BindingConfigParseException, IOException {
// Modbus server ("modbus slave") has input registers
byte[] registerData = int32AsRegistersSwapped(123456789); // 0x075BCD15
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = int32AsRegistersSwapped(-123456789); // 0xF8A432EB
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = int32AsRegistersSwapped(123456788); // 0x075BCD14
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
binding = new ModbusBinding();
// read 4 registers = 2 uint32 numbers
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type,
ModbusBindingProvider.VALUE_TYPE_INT32_SWAP, nonZeroOffset ? 1 : 0, 4));
configureNumberItemBinding(2, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
// register data:
// CD15 075B
// 32EB F8A4
// CD14 075B
if (nonZeroOffset) {
// 075B32EB interpreted as CDAB int32 (1st register lo byte, 2nd register hi
// byte)
verify(eventPublisher).postUpdate("Item1", new DecimalType(854263643));
// F8A4CD14 interpreted as CDAB int32 (2nd register lo byte, 3rd register hi
// byte)
verify(eventPublisher).postUpdate("Item2", new DecimalType(-854263644));
} else {
verify(eventPublisher).postUpdate("Item1", new DecimalType(123456789));
verify(eventPublisher).postUpdate("Item2", new DecimalType(-123456789));
}
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading of input/holding registers, uses valuetype=float32
*
* @throws IOException
*/
@Test
public void testReadRegistersFloat32()
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
ConfigurationException, BindingConfigParseException, IOException {
// Modbus server ("modbus slave") has input registers
byte[] registerData = float32AsRegisters(123456789.95623f);
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
registerData = float32AsRegisters(-123456789.1241243f);
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[0], registerData[1]));
addRegisterMethod.invoke(spi, constructRegister2Byte.newInstance(registerData[2], registerData[3]));
binding = new ModbusBinding();
// read 4 registers = 2 uint32 numbers
binding.updated(
addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, ModbusBindingProvider.VALUE_TYPE_FLOAT32, 0, 4));
configureNumberItemBinding(2, SLAVE_NAME, 0);
binding.execute();
// Give the system some time to make the expected connections & requests
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
verify(eventPublisher).postUpdate("Item1", new DecimalType(123456789.95623f));
verify(eventPublisher).postUpdate("Item2", new DecimalType(-123456789.1241243f));
verifyNoMoreInteractions(eventPublisher);
}
/**
* Test reading same registers using different value types.
*/
@Test
public void testReadRegistersMultipleWays()
throws InterruptedException, UnknownHostException, BindingConfigParseException, ConfigurationException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 0x0002 = 00000000 00000010
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(2));
// 0xFFFC = 11111111 11111100
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(-4));
// 0x0063 = 00000000 01100011
addRegisterMethod.invoke(spi, constructRegisterInt.newInstance(99));
binding = new ModbusBinding();
Dictionary<String, Object> cfg = newLongPollBindingConfig();
for (String valueType : new String[] { ModbusBindingProvider.VALUE_TYPE_BIT,
ModbusBindingProvider.VALUE_TYPE_UINT8, ModbusBindingProvider.VALUE_TYPE_INT16 }) {
addSlave(cfg, SLAVE_NAME + valueType, type, valueType, nonZeroOffset ? 1 : 0, 2);
}
binding.updated(cfg);
// Here we test only some of the read values (int16 read but not tested)
configureSwitchItemBinding(32, SLAVE_NAME + ModbusBindingProvider.VALUE_TYPE_BIT, 0, "B", null);
configureNumberItemBinding(4, SLAVE_NAME + ModbusBindingProvider.VALUE_TYPE_UINT8, 0, "UI8", null);
binding.execute();
// Give the system some time to make the expected connections & requests
// We expect as many requests and connections as there are slaves conifigured for the binding.
// Note: same registers are read many times, there is currently no optimization implemented for this use case
waitForConnectionsReceived(3);
waitForRequests(3);
verify(eventPublisher, never()).postCommand(null, null);
verify(eventPublisher, never()).sendCommand(null, null);
// verify bit items
if (nonZeroOffset) {
verifyBitItems(new StringBuffer("1111111111111100").reverse().toString(), 0, "B");
verifyBitItems(new StringBuffer("0000000001100011").reverse().toString(), 16, "B");
} else {
// 1st register bits
verifyBitItems(new StringBuffer("0000000000000010").reverse().toString(), 0, "B");
// 2nd register bits
verifyBitItems(new StringBuffer("1111111111111100").reverse().toString(), 16, "B");
}
// verify int8 items
if (nonZeroOffset) {
// 2nd register, lo byte
verify(eventPublisher).postUpdate("UI8Item1", new DecimalType(0xFC));
// 2nd register, hi byte
verify(eventPublisher).postUpdate("UI8Item2", new DecimalType(0xFF));
// 3rd register, lo byte
verify(eventPublisher).postUpdate("UI8Item3", new DecimalType(0x63));
// 3rd register, hi byte
verify(eventPublisher).postUpdate("UI8Item4", new DecimalType(0x00));
} else {
// 1st register, lo byte
verify(eventPublisher).postUpdate("UI8Item1", new DecimalType(0x02));
// 1st register, hi byte
verify(eventPublisher).postUpdate("UI8Item2", new DecimalType(0x00));
// 2nd register, lo byte
verify(eventPublisher).postUpdate("UI8Item3", new DecimalType(0xFC));
// 2nd register, hi byte
verify(eventPublisher).postUpdate("UI8Item4", new DecimalType(0xFF));
}
verifyNoMoreInteractions(eventPublisher);
}
}