/**
* 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.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.List;
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.OnOffType;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.osgi.service.cm.ConfigurationException;
import net.wimpi.modbus.procimg.DigitalIn;
import net.wimpi.modbus.procimg.DigitalOut;
import net.wimpi.modbus.procimg.Register;
import net.wimpi.modbus.procimg.SimpleDigitalIn;
import net.wimpi.modbus.procimg.SimpleDigitalOut;
/**
* Parameterized test case that tests reading of both coils (i.e. boolean 0/1
* output signals) and discrete inputs (i.e. boolean 0/1 inputs signals)
* registers
*/
@RunWith(Parameterized.class)
public class ReadCoilsAndDiscreteTestCase extends TestCaseSupport {
@Parameters
public static Collection<Object[]> parameters() {
List<Object[]> allParameters = new ArrayList<>();
List<Object[]> baseParameters = Arrays.asList(new Object[][] {
{ false, ModbusBindingProvider.TYPE_COIL, SimpleDigitalOut.class, "addDigitalOut", DigitalOut.class },
{ true, ModbusBindingProvider.TYPE_COIL, SimpleDigitalOut.class, "addDigitalOut", DigitalOut.class },
{ false, ModbusBindingProvider.TYPE_DISCRETE, SimpleDigitalIn.class, "addDigitalIn", DigitalIn.class },
{ true, ModbusBindingProvider.TYPE_DISCRETE, SimpleDigitalIn.class, "addDigitalIn",
DigitalIn.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> constructBoolStore;
private String type;
private Method addRegisterMethod;
private String spiAddRegisterMethodName;
private Class<?> addRegisterArgClass;
/**
* @param serverType
* @param nonZeroOffset
* whether to test non-zero start address in modbus binding
* @param type
* type of the slave (e.g. "holding")
* @param storeClass
* "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 ReadCoilsAndDiscreteTestCase(ServerType serverType, boolean nonZeroOffset, String type,
Class<Register> storeClass, String spiAddRegisterMethodName, Class<?> addRegisterArgClass)
throws NoSuchMethodException, SecurityException {
this.serverType = serverType;
this.nonZeroOffset = nonZeroOffset;
this.type = type;
this.spiAddRegisterMethodName = spiAddRegisterMethodName;
this.addRegisterArgClass = addRegisterArgClass;
constructBoolStore = storeClass.getDeclaredConstructor(new Class[] { boolean.class });
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
addRegisterMethod = spi.getClass().getMethod(spiAddRegisterMethodName, new Class[] { addRegisterArgClass });
}
/**
* Test reading of discrete inputs/outputs, uses default valuetype
*/
@Test
public void testReadDigitals()
throws InterruptedException, UnknownHostException, BindingConfigParseException, ConfigurationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
// Modbus server ("modbus slave") has two digital inputs/outputs
addRegisterMethod.invoke(spi, constructBoolStore.newInstance(false));
addRegisterMethod.invoke(spi, constructBoolStore.newInstance(true));
addRegisterMethod.invoke(spi, constructBoolStore.newInstance(false));
binding = new ModbusBinding();
binding.updated(addSlave(newLongPollBindingConfig(), SLAVE_NAME, type, null, nonZeroOffset ? 1 : 0, 2));
configureSwitchItemBinding(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", OnOffType.ON);
verify(eventPublisher).postUpdate("Item2", OnOffType.OFF);
} else {
verify(eventPublisher).postUpdate("Item1", OnOffType.OFF);
verify(eventPublisher).postUpdate("Item2", OnOffType.ON);
}
verifyNoMoreInteractions(eventPublisher);
}
}