/**
* 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.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import java.util.Dictionary;
import org.junit.Before;
import org.junit.Test;
import org.openhab.binding.modbus.ModbusBindingProvider;
import org.openhab.binding.modbus.internal.Transformation.TransformationHelperWrapper;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.transform.TransformationException;
import org.openhab.core.transform.TransformationService;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.osgi.framework.BundleContext;
import net.wimpi.modbus.procimg.SimpleDigitalOut;
/**
* Tests for items with extended syntax. Run only against TCP server.
*
*/
public class WriteCoilExtendedItemConfigurationTestCase extends TestCaseSupport {
private ModbusGenericBindingProvider provider;
@Before
public void initSlaveAndServer() throws Exception {
spi.addDigitalOut(new SimpleDigitalOut(true));
spi.addDigitalOut(new SimpleDigitalOut(false));
//
binding = new ModbusBinding();
Dictionary<String, Object> config = newLongPollBindingConfig();
addSlave(config, SLAVE_NAME, ModbusBindingProvider.TYPE_COIL, null, 0, 2);
binding.updated(config);
// Configure items
provider = new ModbusGenericBindingProvider();
binding.setEventPublisher(eventPublisher);
binding.addBindingProvider(provider);
}
@Test
public void testWriteCoilItemManyConnections() throws BindingConfigParseException {
// Inspired by https://github.com/openhab/openhab/issues/4745
// item reads from coil index 0, and writes to coil index 1. Both ON and OFF are translated to "true" on the
// wire
provider.processBindingConfiguration("test.items", new SwitchItem("Item1"),
String.format(
"<[%1$s:0:trigger=*],>[%1$s:1:trigger=ON,transformation=1],>[%1$s:1:trigger=OFF,transformation=1]",
SLAVE_NAME));
binding.execute();
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher).postUpdate("Item1", OnOffType.ON);
verifyNoMoreInteractions(eventPublisher);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(false)));
// send OFF to the item and ensure that coil is set as specified by the transformation
binding.receiveCommand("Item1", OnOffType.OFF);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(true)));
verifyNoMoreInteractions(eventPublisher);
// reset coil
spi.getDigitalOut(1).set(false);
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(false)));
// send ON to the item
binding.receiveCommand("Item1", OnOffType.ON);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(true)));
verifyNoMoreInteractions(eventPublisher);
}
@Test
public void testWriteCoilItemNonNumericConstantTransformationManyConnections() throws BindingConfigParseException {
// Inspired by https://github.com/openhab/openhab/issues/4745
// item reads from coil index 0, and writes to coil index 1. Both ON and OFF are translated to "true" on the
// wire
provider.processBindingConfiguration("test.items", new SwitchItem("Item1"),
String.format(
"<[%1$s:0:trigger=*],>[%1$s:1:trigger=ON,transformation=ON],>[%1$s:1:trigger=OFF,transformation=ON]",
SLAVE_NAME));
binding.execute();
waitForConnectionsReceived(1);
waitForRequests(1);
verify(eventPublisher).postUpdate("Item1", OnOffType.ON);
verifyNoMoreInteractions(eventPublisher);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(false)));
// send OFF to the item and ensure that coil is set as specified by the transformation
binding.receiveCommand("Item1", OnOffType.OFF);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(true)));
verifyNoMoreInteractions(eventPublisher);
}
@Test
public void testCoilWriteFiltered() throws BindingConfigParseException {
provider.processBindingConfiguration("test.items", new SwitchItem("Item1"),
String.format(">[%1$s:1:trigger=ON]", SLAVE_NAME));
binding.execute();
waitForConnectionsReceived(1);
waitForRequests(1);
verifyNoMoreInteractions(eventPublisher);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(false)));
// send OFF to the item -- it is not processed
binding.receiveCommand("Item1", OnOffType.OFF);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(false)));
verifyNoMoreInteractions(eventPublisher);
// ON command is processed
binding.receiveCommand("Item1", OnOffType.ON);
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(true)));
verifyNoMoreInteractions(eventPublisher);
}
@Test
public void testRegisterStringItemWriteNumberItemComplexTransformation() throws BindingConfigParseException {
provider.processBindingConfiguration("test.items", new StringItem("Item1"),
String.format(">[%1$s:1:trigger=*,transformation=PARSEBOOL()]", SLAVE_NAME));
ModbusBindingConfig config = provider.getConfig("Item1");
// Inject transformation
for (ItemIOConnection itemIOConnection : config.getWriteConnections()) {
itemIOConnection.getTransformation().setTransformationHelper(new TransformationHelperWrapper() {
@Override
public TransformationService getTransformationService(BundleContext context,
String transformationServiceName) {
if ("PARSEBOOL".equals(transformationServiceName)) {
return new TransformationService() {
@Override
public String transform(String ignored, String arg) throws TransformationException {
if (arg.equals("true") || arg.equals("T")) {
return "1";
} else if (arg.equals("false") || arg.equals("F")) {
return "0";
} else {
throw new AssertionError("unexpected arg in test");
}
}
};
} else {
throw new AssertionError("unexpected transformation");
}
}
});
}
binding.execute();
verifyNoMoreInteractions(eventPublisher); // write-only item, no event sent
binding.receiveCommand("Item1", new StringType("T"));
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(true)));
binding.receiveCommand("Item1", new StringType("F"));
assertThat(spi.getDigitalOut(0).isSet(), is(equalTo(true)));
assertThat(spi.getDigitalOut(1).isSet(), is(equalTo(false)));
}
}