diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/.classpath b/bundles/binding/org.openhab.binding.ucprelayboard/.classpath new file mode 100644 index 00000000000..6566c1e3a03 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/.project b/bundles/binding/org.openhab.binding.ucprelayboard/.project new file mode 100644 index 00000000000..2439531489a --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/.project @@ -0,0 +1,33 @@ + + + org.openhab.binding.ucprelayboard + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/.settings/org.eclipse.pde.core.prefs b/bundles/binding/org.openhab.binding.ucprelayboard/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..18f2d04958e --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Fri Oct 08 00:21:11 CEST 2010 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/META-INF/MANIFEST.MF b/bundles/binding/org.openhab.binding.ucprelayboard/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..b08eaafc798 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: openHAB UCProjects.eu RelayBoard Binding +Bundle-SymbolicName: org.openhab.binding.ucprelayboard +Bundle-Version: 1.8.0.qualifier +Bundle-Vendor: openHAB.org +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Import-Package: gnu.io, + javax.mail;version="1.4.0", + org.apache.commons.io, + org.apache.commons.lang, + org.openhab.core.binding, + org.openhab.core.events, + org.openhab.core.items, + org.openhab.core.library.items, + org.openhab.core.library.types, + org.openhab.core.types, + org.openhab.model.item.binding, + org.osgi.framework, + org.osgi.service.cm, + org.osgi.service.event, + org.slf4j +Export-Package: org.openhab.binding.ucprelayboard +Service-Component: OSGI-INF/binding.xml, OSGI-INF/genericbindingprovider.xml +Bundle-ClassPath: . diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/OSGI-INF/binding.xml b/bundles/binding/org.openhab.binding.ucprelayboard/OSGI-INF/binding.xml new file mode 100644 index 00000000000..aa06f7be510 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/OSGI-INF/binding.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/OSGI-INF/genericbindingprovider.xml b/bundles/binding/org.openhab.binding.ucprelayboard/OSGI-INF/genericbindingprovider.xml new file mode 100644 index 00000000000..f1ca06e2621 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/OSGI-INF/genericbindingprovider.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/build.properties b/bundles/binding/org.openhab.binding.ucprelayboard/build.properties new file mode 100644 index 00000000000..1dac3558597 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/build.properties @@ -0,0 +1,5 @@ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/ +source.. = src/main/java/ diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/pom.xml b/bundles/binding/org.openhab.binding.ucprelayboard/pom.xml new file mode 100644 index 00000000000..8c47113cdde --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/pom.xml @@ -0,0 +1,37 @@ + + + + + org.openhab.bundles + binding + 1.8.0-SNAPSHOT + + + openHAB UCProjects.eu RelayBoard Binding + + + org.openhab.binding.ucprelayboard + org.openhab.binding.ucprelayboard + openhab-addon-binding-ucprelayboard + ${project.name} + openhab-addon-io-serial + + + 4.0.0 + org.openhab.binding + org.openhab.binding.ucprelayboard + + eclipse-plugin + + + + + org.vafer + jdeb + + + + + diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/UCPRelayBoardBindingProvider.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/UCPRelayBoardBindingProvider.java new file mode 100644 index 00000000000..5ef9109dd6b --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/UCPRelayBoardBindingProvider.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard; + +/** + * @author Robert Michalak + * @since 1.8.0 + */ +import org.openhab.binding.ucprelayboard.internal.UCPRelayConfig; +import org.openhab.core.binding.BindingProvider; +import org.openhab.core.items.Item; + +public interface UCPRelayBoardBindingProvider extends BindingProvider { + + /** + * Returns the binding configuration for an item + * @param itemName + * @return + */ + public UCPRelayConfig getRelayConfigForItem(String itemName); + + public Item getItemForRelayConfig(UCPRelayConfig config); + +} \ No newline at end of file diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/DowCRC.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/DowCRC.java new file mode 100644 index 00000000000..6aca864550a --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/DowCRC.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; +/** + * Implementation of Dallas One Wire CRC formula based on http://www.maximintegrated.com/en/app-notes/index.mvp/id/27 + * + * @author Robert Michalak + * + */ +public class DowCRC { + private static final char crc8[] = { + 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, + 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, + 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, + 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, + 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, + 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, + 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, + 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, + 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, + 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, + 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, + 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, + 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, + 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, + 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, + 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53 + }; + + public static byte compute(byte[] tab) { + int result = 0; + for (byte value : tab) { + result = crc8[ (int)value ^ result]; + } + return (byte) result; + } +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/InitializationException.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/InitializationException.java new file mode 100644 index 00000000000..d081cc4acc9 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/InitializationException.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; + +/** + * @author Robert Michalak + * @since 1.8.0 + */ +public class InitializationException extends Exception { + + private static final long serialVersionUID = -5106059856757667266L; + + public InitializationException(String msg) { + super(msg); + } + + public InitializationException(Throwable cause) { + super(cause); + } + + public InitializationException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/SerialDevice.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/SerialDevice.java new file mode 100644 index 00000000000..ecd9f371606 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/SerialDevice.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; + +import gnu.io.CommPortIdentifier; +import gnu.io.NoSuchPortException; +import gnu.io.PortInUseException; +import gnu.io.SerialPort; +import gnu.io.UnsupportedCommOperationException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class represents a serial device + * + * @author Robert Michalak + * @since 1.8.0 + */ + +public class SerialDevice { + + private static final Logger logger = LoggerFactory + .getLogger(SerialDevice.class); + + private SerialDeviceConfig config; + + private CommPortIdentifier portId; + private SerialPort serialPort; + + private InputStream inputStream; + private OutputStream outputStream; + + public SerialDevice(SerialDeviceConfig config) { + this.config = config; + } + + public SerialDeviceConfig getConfig() { + return config; + } + + /** + * Initialize this device and open the serial port + * + * @throws InitializationException + * if port can not be opened + */ + public void initialize() throws InitializationException { + try { + portId = CommPortIdentifier.getPortIdentifier(config.getPort()); + + if (portId != null) { + // initialize serial port + serialPort = (SerialPort) portId.open("openHAB", 2000); + + // set port parameters + serialPort.setSerialPortParams(config.getBaud(), + SerialPort.DATABITS_8, SerialPort.STOPBITS_1, + SerialPort.PARITY_NONE); + + inputStream = serialPort.getInputStream(); + + outputStream = serialPort.getOutputStream(); + + } else { + throw new InitializationException("Serial port '" + + config.getPort() + "' could not be found.\n"); + } + } catch (UnsupportedCommOperationException e) { + throw new InitializationException(e); + } catch (IOException e) { + throw new InitializationException(e); + } catch (PortInUseException e) { + throw new InitializationException(e); + } catch (NoSuchPortException e) { + throw new InitializationException(e); + } + } + + /** + * Sends a string to the serial port of this device + * + * @param relayBoardCommand + * the string to send + */ + public void writeBytes(byte[] relayBoardCommand) { + try { + // write bytes to serial port + outputStream.write(relayBoardCommand); + outputStream.flush(); + } catch (IOException e) { + logger.error("Error writing to serial port {}: {}", new Object[] { + config.getPort(), e.getMessage() }); + } + } + + public byte[] readBytes(final byte[] buffer) { + try { + if (inputStream.available() > 0) { + inputStream.read(buffer); + } + } catch (IOException e) { + logger.error("Error reading from serial port {}: {}", new Object[] { + config.getPort(), e.getMessage() }); + } + return buffer; + } + + /** + * Close this serial device + */ + public void close() { + IOUtils.closeQuietly(outputStream); + IOUtils.closeQuietly(inputStream); + serialPort.close(); + } + +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/SerialDeviceConfig.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/SerialDeviceConfig.java new file mode 100644 index 00000000000..acaf9f3b8ff --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/SerialDeviceConfig.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; + +/** + * This class represents configuration for a serial device + * + * @author Robert Michalak + * @since 1.8.0 + */ +public class SerialDeviceConfig { + + private String name; + private String port; + private int baud = 57600; // default value + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public int getBaud() { + return baud; + } + + public void setBaud(int baud) { + this.baud = baud; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isValid() { + return (name != null && port != null); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + baud; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((port == null) ? 0 : port.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SerialDeviceConfig other = (SerialDeviceConfig) obj; + if (baud != other.baud) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (port == null) { + if (other.port != null) + return false; + } else if (!port.equals(other.port)) + return false; + return true; + } + + +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardBinding.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardBinding.java new file mode 100644 index 00000000000..58c5a744211 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardBinding.java @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.openhab.binding.ucprelayboard.UCPRelayBoardBindingProvider; +import org.openhab.core.binding.AbstractActiveBinding; +import org.openhab.core.items.Item; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.types.Command; +import org.openhab.core.types.State; +import org.osgi.framework.BundleContext; + +/** + * Binding for relay boards available from http://www.ucprojects.eu/ + * + * @author Robert Michalak + * @since 1.8.0 + */ +public class UCPRelayBoardBinding extends + AbstractActiveBinding { + + private Map serialDevices = new HashMap(); + + private long refreshInterval = 60000; + + /** + * {@inheritDoc} + */ + @Override + public void internalReceiveCommand(String itemName, Command command) { + + UCPRelayConfig config = getRelayConfigForItem(itemName); + if (config != null) { + SerialDevice serialDevice = serialDevices.get(config.getBoardName()); + if (command instanceof OnOffType) { + byte[] relayBoardCommand = prepareRelayCommand( + config, ((OnOffType) command)); + serialDevice.writeBytes(relayBoardCommand); + } + } + } + + private UCPRelayConfig getRelayConfigForItem(String itemName) { + for (UCPRelayBoardBindingProvider provider : providers) { + if (provider.providesBindingFor(itemName)) { + return provider.getRelayConfigForItem(itemName); + } + } + return null; + } + + private byte[] prepareRelayCommand(UCPRelayConfig config, OnOffType onOffType) { + + switch (config.translateCommand(onOffType)) { + case OFF: + return UCPRelayBoardMessages.OFF[config.getRelayNumber()]; + case ON: + return UCPRelayBoardMessages.ON[config.getRelayNumber()]; + } + return null; + } + + public void activate(final BundleContext bundleContext, + final Map properties) throws InitializationException { + if (properties == null) { + return; + } + + Map configs = prepareConfiguration(properties); + for (SerialDeviceConfig config : configs.values()) { + prepareSerialDevice(config); + } + if (serialDevices.size() > 0) { + setProperlyConfigured(true); + } + } + + public void modified(final Map properties) throws InitializationException { + if (properties == null) { + return; + } + Map configs = prepareConfiguration(properties); + //create new and modify existing ones + for (Map.Entry config : configs.entrySet()) { + if (serialDevices.containsKey(config.getKey())) { + SerialDevice device = serialDevices.get(config.getKey()); + if (!config.equals(device.getConfig())) { + device.close(); + prepareSerialDevice(config.getValue()); + } + } else { + prepareSerialDevice(config.getValue()); + } + } + //close removed ones + for (String name : serialDevices.keySet()) { + if (!configs.containsKey(name)) { + SerialDevice device = serialDevices.get(name); + device.close(); + serialDevices.remove(name); + } + } + if (serialDevices.size() > 0) { + setProperlyConfigured(true); + } else { + setProperlyConfigured(false); + } + + } + + private void prepareSerialDevice(SerialDeviceConfig config) + throws InitializationException { + SerialDevice serialDevice = new SerialDevice(config); + serialDevice.initialize(); + serialDevices.put(config.getName(), serialDevice); + } + + private Map prepareConfiguration( + final Map properties) { + Map configs = new HashMap(); + + for (String key : properties.keySet()) { + + Object property = properties.get(key); + if (!(property instanceof String)) { + continue; + } + + String value = StringUtils.trimToNull((String) property); + + if ("refresh".equals(key)) { + try { + refreshInterval = Long.parseLong(value); + } catch (NumberFormatException ignored) { + } + continue; + } + + String[] split = StringUtils.split(key, "."); + if (split.length != 3 || value == null || !"board".equals(split[0])) { + continue; + } + + SerialDeviceConfig config = configs.get(split[1]); + if (config == null) { + config = new SerialDeviceConfig(); + config.setName(split[1]); + configs.put(split[1], config); + } + + if ("port".equals(split[2])) { + config.setPort(value); + } else if ("baud".equals(split[2])) { + config.setBaud(Integer.valueOf(value)); + } + } + return configs; + } + + public void deactivate(final int reason) { + for (SerialDevice serialDevice : serialDevices.values()) { + serialDevice.close(); + } + serialDevices.clear(); + } + + private void retrieveStateFromRelayBoard(SerialDevice serialDevice) { + //consume any bytes left in a stream + serialDevice.readBytes(new byte[100]); + serialDevice.writeBytes(UCPRelayBoardMessages.GET_STATE); + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + readAndDecodeResponse(serialDevice); + } + + private void readAndDecodeResponse(SerialDevice serialDevice) { + byte response[] = serialDevice.readBytes(new byte[5]); + if (validateResponse(response)) { + for (int relay = 0; relay < 8; relay++) { + Item item = getItemForRelay(serialDevice, relay); + if (item != null) { + UCPRelayConfig config = getRelayConfigForItem(item.getName()); + State state = getRelayState(response, relay, config); + eventPublisher.postUpdate(item.getName(), state); + } + } + } + } + + private boolean validateResponse(byte[] response) { + if (response[0] != 85) { + return false; + } + if (!checkCRC(response)) { + return false; + } + return true; + } + + private boolean checkCRC(byte[] response) { + final byte[] tab = Arrays.copyOfRange(response, 1, 4); + final byte crc = DowCRC.compute(tab); + if (crc != response[4]) { + return false; + } else { + return true; + } + } + + private OnOffType getRelayState(byte[] response, int relay, UCPRelayConfig config) { + OnOffType state; + if ((response[3] & (1 << relay)) > 0) { + state = OnOffType.ON; + } else { + state = OnOffType.OFF; + } + return config.translateCommand(state); + } + + private Item getItemForRelay(SerialDevice serialDevice, int relay) { + for (UCPRelayBoardBindingProvider provider : providers) { + Item item = provider.getItemForRelayConfig(new UCPRelayConfig(serialDevice.getConfig().getName(), relay)); + if (item != null) { + return item; + } + } + return null; + } + + @Override + protected void execute() { + for (SerialDevice serialDevice : serialDevices.values()) { + retrieveStateFromRelayBoard(serialDevice); + } + + } + + @Override + protected long getRefreshInterval() { + return refreshInterval; + } + + @Override + protected String getName() { + return "UCProjects.eu Relay Board Binding Thread"; + } +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardGenericBindingProvider.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardGenericBindingProvider.java new file mode 100644 index 00000000000..86fc01c7a37 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardGenericBindingProvider.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; + +import java.util.Map; +import java.util.Set; + +import org.openhab.binding.ucprelayboard.UCPRelayBoardBindingProvider; +import org.openhab.core.binding.BindingConfig; +import org.openhab.core.items.Item; +import org.openhab.core.library.items.SwitchItem; +import org.openhab.model.item.binding.AbstractGenericBindingProvider; +import org.openhab.model.item.binding.BindingConfigParseException; + +/** + * @author Robert Michalak + * @since 1.8.0 + */ +public class UCPRelayBoardGenericBindingProvider extends + AbstractGenericBindingProvider implements UCPRelayBoardBindingProvider { + + @Override + public String getBindingType() { + return "ucprelayboard"; + } + + /** + * {@inheritDoc} + */ + @Override + public void validateItemType(Item item, String bindingConfig) + throws BindingConfigParseException { + if (!(item instanceof SwitchItem)) { + throw new BindingConfigParseException( + "item '" + + item.getName() + + "' is of type '" + + item.getClass().getSimpleName() + + "', only SwitchItems are allowed - please check your *.items configuration"); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void processBindingConfiguration(String context, Item item, + String bindingConfig) throws BindingConfigParseException { + + super.processBindingConfiguration(context, item, bindingConfig); + + UCPRelayConfig config = UCPRelayConfig.fromString(bindingConfig); + + addBindingConfig(item, config); + + } + + @Override + public UCPRelayConfig getRelayConfigForItem(String itemName) { + return (UCPRelayConfig) bindingConfigs.get(itemName); + } + + @Override + public Item getItemForRelayConfig(UCPRelayConfig config) { + for (Map.Entry bindingConfig : bindingConfigs.entrySet()) { + if (bindingConfig.getValue().equals(config)) { + for (Map.Entry> context : contextMap.entrySet()) { + for (Item item : context.getValue()) { + if (item.getName().equals(bindingConfig.getKey())) { + return item; + } + } + } + } + } + return null; + } +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardMessages.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardMessages.java new file mode 100644 index 00000000000..b42669ae357 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayBoardMessages.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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.ucprelayboard.internal; +/** + * Predefined messages + * + * @author Robert Michalak + * @since 1.8.0 + */ +public class UCPRelayBoardMessages { + + public static final byte[][] ON = new byte[][] { + new byte[] { 0x55, 0x01, 0x4f, 0x00, 0x28 }, + new byte[] { 0x55, 0x01, 0x4f, 0x01, 0x76 }, + new byte[] { 0x55, 0x01, 0x4f, 0x02, (byte) 0x94 }, + new byte[] { 0x55, 0x01, 0x4f, 0x03, (byte) 0xca }, + new byte[] { 0x55, 0x01, 0x4f, 0x04, 0x49 }, + new byte[] { 0x55, 0x01, 0x4f, 0x05, 0x17 }, + new byte[] { 0x55, 0x01, 0x4f, 0x06, (byte) 0xf5 }, + new byte[] { 0x55, 0x01, 0x4f, 0x07, (byte) 0xab } }; + + public static final byte[][] OFF = new byte[][] { + new byte[] { 0x55, 0x01, 0x46, 0x00, (byte) 0x9a }, + new byte[] { 0x55, 0x01, 0x46, 0x01, (byte) 0xc4 }, + new byte[] { 0x55, 0x01, 0x46, 0x02, 0x26 }, + new byte[] { 0x55, 0x01, 0x46, 0x03, 0x78 }, + new byte[] { 0x55, 0x01, 0x46, 0x04, (byte) 0xfb }, + new byte[] { 0x55, 0x01, 0x46, 0x05, (byte) 0xa5 }, + new byte[] { 0x55, 0x01, 0x46, 0x06, 0x47 }, + new byte[] { 0x55, 0x01, 0x46, 0x07, 0x19 } }; + + /** + * This message can be sent to retrieve current state of relays. + * Board should respond with 5 bytes ('0x55' '0x01' '0x52' '' ''), + * where every bit in is a state of one relay. + * + * is computed using 'Dow CRC' algorithm for bytes 2-4 in a message + */ + public static final byte[] GET_STATE = new byte[] {0x55, 0x01, 0x47, 0x00, 0x5e}; + +} diff --git a/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayConfig.java b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayConfig.java new file mode 100644 index 00000000000..e4d1a305307 --- /dev/null +++ b/bundles/binding/org.openhab.binding.ucprelayboard/src/main/java/org/openhab/binding/ucprelayboard/internal/UCPRelayConfig.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2010-2015, openHAB.org and others. + * + * 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 + */ + +/** + * Configuration of a Switch + * + * @author Robert Michalak + */ +package org.openhab.binding.ucprelayboard.internal; + +import org.apache.commons.lang.StringUtils; +import org.openhab.core.binding.BindingConfig; +import org.openhab.core.library.types.OnOffType; +import org.openhab.model.item.binding.BindingConfigParseException; + +/** + * @author Robert Michalak + * @since 1.8.0 + */ +public class UCPRelayConfig implements BindingConfig { + private String boardName; + private int relayNumber; + private boolean inverted = false; + + public UCPRelayConfig(String boardName, int relayNumber) { + this(boardName, relayNumber, false); + } + + public UCPRelayConfig(String boardName, int relayNumber, boolean inverted) { + this.boardName = boardName; + this.relayNumber = relayNumber; + this.inverted = inverted; + } + + public String getBoardName() { + return boardName; + } + + public int getRelayNumber() { + return relayNumber; + } + + public OnOffType translateCommand(OnOffType command) { + if (inverted) { + return OnOffType.values()[1 - command.ordinal()]; + } else { + return command; + } + } + + public static UCPRelayConfig fromString(final String config) throws BindingConfigParseException { + String boardName = null; + int relayNumber = -1; + boolean inverted = false; + final String[] params = StringUtils.split(config, ";"); + for (String param : params) { + final String[] nameValue = StringUtils.split(param, "="); + if (nameValue.length != 2) { + continue; + } + if ("board".equals(nameValue[0])) { + boardName = nameValue[1]; + } else if ("relay".equals(nameValue[0])) { + try { + relayNumber = Integer.parseInt(nameValue[1]); + } catch (NumberFormatException e) { + throw new BindingConfigParseException("Wrong item configuration. " + e.getMessage()); + } + } else if ("inverted".equals(nameValue[0])) { + inverted = Boolean.valueOf(nameValue[1]); + } + } + if (boardName == null && relayNumber < 0) { + throw new BindingConfigParseException("Wrong item configuration. missing 'board' or 'relay' values"); + } + return new UCPRelayConfig(boardName, relayNumber, inverted); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((boardName == null) ? 0 : boardName.hashCode()); + result = prime * result + relayNumber; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UCPRelayConfig other = (UCPRelayConfig) obj; + if (boardName == null) { + if (other.boardName != null) + return false; + } else if (!boardName.equals(other.boardName)) + return false; + if (relayNumber != other.relayNumber) + return false; + return true; + } + + +} diff --git a/bundles/binding/pom.xml b/bundles/binding/pom.xml index eaced5bea7e..4d63ab98d2b 100644 --- a/bundles/binding/pom.xml +++ b/bundles/binding/pom.xml @@ -158,12 +158,13 @@ org.openhab.binding.panasonictv org.openhab.binding.enphaseenergy org.openhab.binding.lightwaverf - org.openhab.binding.souliss + org.openhab.binding.souliss org.openhab.binding.sagercaster org.openhab.binding.ipx800 org.openhab.binding.tacmi org.openhab.binding.rwesmarthome org.openhab.binding.lcn org.openhab.binding.sapp + org.openhab.binding.ucprelayboard diff --git a/distribution/openhabhome/configurations/openhab_default.cfg b/distribution/openhabhome/configurations/openhab_default.cfg index 6f021a82899..99365fca17f 100644 --- a/distribution/openhabhome/configurations/openhab_default.cfg +++ b/distribution/openhabhome/configurations/openhab_default.cfg @@ -2171,3 +2171,12 @@ tcp:refreshinterval=250 # # MQTT broker port SiteWhere is listening to. # sitewhere:mqttPort=1883 + +################################ UCProjects.eu Relay Board Binding ################################### +# +# Port and baud rate (optional, defaults to 57600) for every device +# ucprelayboard:board.one.port=/dev/tyUSB0 +# ucprelayboard:board..baud= +# +# Refresh of relay board state interval in miliseconds (optional, defaults to 60000) +# ucprelayboard:refresh= diff --git a/distribution/pom.xml b/distribution/pom.xml index fbb87cf060d..62d378ab645 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -1341,6 +1341,12 @@ ${project.version} jar + + org.openhab.binding + org.openhab.binding.ucprelayboard + ${project.version} + jar + org.openhab.io