From d5d751b7765448492d33b40284db90c3d9c3b9d1 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 26 Jan 2016 23:17:35 +0100 Subject: [PATCH 1/4] esh-inf added parameter and serial closing to allow binding restart correctly --- .../ESH-INF/thing/thing-types.xml | 7 + .../mysensors/MySensorsBindingConstants.java | 2 - .../handler/MySensorsBridgeHandler.java | 5 +- .../internal/MySensorsBridgeConnection.java | 112 +++++++------ .../serial/MySensorsSerialConnection.java | 155 ++++++++---------- 5 files changed, 137 insertions(+), 144 deletions(-) diff --git a/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml index 66468db1c5a03..bb62aebd784af 100644 --- a/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml +++ b/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml @@ -53,6 +53,13 @@ 100 + + baudrate + + Baudrate for serial port + + 115200 + diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java index ab4d18090c555..66191f04905ec 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java @@ -27,8 +27,6 @@ public class MySensorsBindingConstants { public static final String BINDING_ID = "mysensors"; - public static final int DEFAULT_SERIAL_BAUDRATE = 115200; - public static final String PARAMETER_NODEID = "nodeId"; public static final String PARAMETER_CHILDID = "childId"; public static final String PARAMETER_IPADDRESS = "ipAddress"; diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java index ca8dc21dbaa62..c951f56085ae5 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java @@ -58,9 +58,10 @@ public void initialize() { MySensorsBridgeConfiguration configuration = getConfigAs(MySensorsBridgeConfiguration.class); + logger.debug("BAUDRATE {} {}", configuration.baudRate, configuration.sendDelay); + if (getThing().getThingTypeUID().equals(THING_TYPE_BRIDGE_SER)) { - mysCon = new MySensorsSerialConnection(configuration.serialPort, - (configuration.baudRate == null) ? DEFAULT_SERIAL_BAUDRATE : configuration.baudRate, + mysCon = new MySensorsSerialConnection(configuration.serialPort, configuration.baudRate, configuration.sendDelay); } else if (getThing().getThingTypeUID().equals(THING_TYPE_BRIDGE_ETH)) { mysCon = new MySensorsIpConnection(configuration.ipAddress, configuration.tcpPort, configuration.sendDelay); diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java index c9e5dbf703258..1bbd75c4fcb3b 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java @@ -7,65 +7,63 @@ import java.util.List; import org.openhab.binding.mysensors.handler.MySensorsUpdateListener; -import org.openhab.binding.mysensors.protocol.ip.MySensorsIpConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class MySensorsBridgeConnection extends Thread { - - private Logger logger = LoggerFactory.getLogger(MySensorsBridgeConnection.class); - - public List updateListeners; - - public List MySensorsMessageOutboundQueue = Collections.synchronizedList(new LinkedList()); - - public boolean connected = false; - - protected boolean stopReader = false; - - public MySensorsBridgeConnection() { - updateListeners = new ArrayList<>(); - } - - /** - * @param listener An Object, that wants to listen on status updates - */ - public void addUpdateListener(MySensorsUpdateListener listener) { - synchronized (updateListeners) { - updateListeners.add(listener); - } - } - - public void removeUpdateListener(MySensorsUpdateListener listener) { - synchronized (updateListeners) { - if(updateListeners.contains(listener)) - updateListeners.remove(listener); - } - } - - public void addMySensorsOutboundMessage(MySensorsMessage msg) { - MySensorsMessageOutboundQueue.add(msg); - } - - public void removeMySensorsOutboundMessage(MySensorsMessage msg) { - Iterator iterator = MySensorsMessageOutboundQueue.iterator(); - while(iterator.hasNext()) { - MySensorsMessage msgInQueue = iterator.next(); - if(msgInQueue.getNodeId() == msg.getNodeId() - && msgInQueue.getChildId() == msg.getChildId() - && msgInQueue.getMsgType() == msg.getMsgType() - && msgInQueue.getSubType() == msg.getSubType() - && msgInQueue.getAck() == msg.getAck() - && msgInQueue.getMsg().equals(msg.getMsg())) { - iterator.remove(); - } - } - } - - /** - * Stop the communication with the serial/ip interface (stop Thread) - */ - public void stopReader() { - this.stopReader = true; - } + + private Logger logger = LoggerFactory.getLogger(MySensorsBridgeConnection.class); + + public List updateListeners; + + public List MySensorsMessageOutboundQueue = Collections + .synchronizedList(new LinkedList()); + + public boolean connected = false; + + protected boolean stopReader = false; + + public MySensorsBridgeConnection() { + updateListeners = new ArrayList<>(); + } + + /** + * @param listener An Object, that wants to listen on status updates + */ + public void addUpdateListener(MySensorsUpdateListener listener) { + synchronized (updateListeners) { + updateListeners.add(listener); + } + } + + public void removeUpdateListener(MySensorsUpdateListener listener) { + synchronized (updateListeners) { + if (updateListeners.contains(listener)) { + updateListeners.remove(listener); + } + } + } + + public void addMySensorsOutboundMessage(MySensorsMessage msg) { + MySensorsMessageOutboundQueue.add(msg); + } + + public void removeMySensorsOutboundMessage(MySensorsMessage msg) { + Iterator iterator = MySensorsMessageOutboundQueue.iterator(); + while (iterator.hasNext()) { + MySensorsMessage msgInQueue = iterator.next(); + if (msgInQueue.getNodeId() == msg.getNodeId() && msgInQueue.getChildId() == msg.getChildId() + && msgInQueue.getMsgType() == msg.getMsgType() && msgInQueue.getSubType() == msg.getSubType() + && msgInQueue.getAck() == msg.getAck() && msgInQueue.getMsg().equals(msg.getMsg())) { + iterator.remove(); + } + } + } + + /** + * Stop the communication with the serial/ip interface (stop Thread) + */ + public void stopReader() { + this.stopReader = true; + } } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java index 66c26acf1d8ea..4e3db9ace4d48 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java @@ -1,18 +1,9 @@ package org.openhab.binding.mysensors.protocol.serial; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import gnu.io.NRSerialPort; import org.openhab.binding.mysensors.handler.MySensorsStatusUpdateEvent; import org.openhab.binding.mysensors.handler.MySensorsUpdateListener; @@ -22,83 +13,81 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import gnu.io.NRSerialPort; + /** * @author Tim Oberföll * - * Connection to the serial interface where the MySensors Gateway is conncted + * Connection to the serial interface where the MySensors Gateway is conncted */ -public class MySensorsSerialConnection extends MySensorsBridgeConnection{ - - private Logger logger = LoggerFactory.getLogger(MySensorsSerialConnection.class); - - private String serialPort = ""; - private int baudRate = 115200; - public int sendDelay = 0; - - - private NRSerialPort serialConnection = null; - - private MySensorsSerialWriter mysConWriter = null; - - - public MySensorsSerialConnection(String serialPort, int baudRate, int sendDelay) { - super(); - - this.serialPort = serialPort; - this.baudRate = baudRate; - this.sendDelay = sendDelay; - - serialConnection = new NRSerialPort(serialPort, baudRate); - if(serialConnection.connect()) { - connected = true; - logger.debug("Successfully connected to serial port."); - mysConWriter = new MySensorsSerialWriter(serialConnection, this, sendDelay); - } else { - logger.error("Can't connect to serial port. Wrong port?"); - } - - - - } - - - - - /** - * Thread that holds the serial connection and listens to messages - * send from the MySensors network via serial to the controller - */ - public void run() { - - mysConWriter.start(); - - DataInputStream ins = new DataInputStream(serialConnection.getInputStream()); - - BufferedReader buffRead = new BufferedReader(new InputStreamReader(ins)); - - while(!stopReader) { - try { - - // Is there something to read? - - String line = buffRead.readLine(); - if(line != null) { - logger.debug(line); - MySensorsMessage msg = MySensorsMessageParser.parse(line); - if(msg != null) { - MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); - for (MySensorsUpdateListener mySensorsEventListener : updateListeners) { - mySensorsEventListener.statusUpdateReceived(event); - } - } - } - } catch (IOException e) { - // Ignore this, there is nothing to read - } - } - - mysConWriter.stopWriting(); - logger.debug("Shutting down serial connection!"); - } +public class MySensorsSerialConnection extends MySensorsBridgeConnection { + + private Logger logger = LoggerFactory.getLogger(MySensorsSerialConnection.class); + + private String serialPort = ""; + private int baudRate = 115200; + public int sendDelay = 0; + + private NRSerialPort serialConnection = null; + + private MySensorsSerialWriter mysConWriter = null; + + public MySensorsSerialConnection(String serialPort, int baudRate, int sendDelay) { + super(); + + this.serialPort = serialPort; + this.baudRate = baudRate; + this.sendDelay = sendDelay; + + logger.debug("Connecting to {} [baudRate:{}]", serialPort, baudRate); + + serialConnection = new NRSerialPort(serialPort, baudRate); + if (serialConnection.connect()) { + connected = true; + logger.debug("Successfully connected to serial port."); + mysConWriter = new MySensorsSerialWriter(serialConnection, this, sendDelay); + } else { + logger.error("Can't connect to serial port. Wrong port?"); + } + + } + + /** + * Thread that holds the serial connection and listens to messages + * send from the MySensors network via serial to the controller + */ + @Override + public void run() { + + mysConWriter.start(); + + DataInputStream ins = new DataInputStream(serialConnection.getInputStream()); + + BufferedReader buffRead = new BufferedReader(new InputStreamReader(ins)); + + while (!stopReader) { + try { + // Is there something to read? + String line = buffRead.readLine(); + if (line != null) { + logger.debug(line); + MySensorsMessage msg = MySensorsMessageParser.parse(line); + if (msg != null) { + MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); + for (MySensorsUpdateListener mySensorsEventListener : updateListeners) { + mySensorsEventListener.statusUpdateReceived(event); + } + } + } + } catch (IOException e) { + // Ignore this, there is nothing to read + } + } + + logger.debug("Shutting down serial connection!"); + + serialConnection.disconnect(); + mysConWriter.stopWriting(); + } } From 6d9f478d8364146050ed23b80fc36293a96aff11 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 26 Jan 2016 23:48:54 +0100 Subject: [PATCH 2/4] removed debug log before initialize --- .../ESH-INF/thing/thing-types.xml | 13 ++++++------- .../mysensors/MySensorsBindingConstants.java | 1 + .../mysensors/handler/MySensorsBridgeHandler.java | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml b/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml index bb62aebd784af..a249541a15eb6 100644 --- a/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml +++ b/addons/binding/org.openhab.binding.mysensors/ESH-INF/thing/thing-types.xml @@ -24,6 +24,12 @@ 100 + + + Baudrate for serial port + + 115200 + @@ -53,13 +59,6 @@ 100 - - baudrate - - Baudrate for serial port - - 115200 - diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java index 66191f04905ec..568243ae67d55 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/MySensorsBindingConstants.java @@ -32,6 +32,7 @@ public class MySensorsBindingConstants { public static final String PARAMETER_IPADDRESS = "ipAddress"; public static final String PRAMETER_TCPPORT = "tcpPort"; public static final String PARAMETER_SENDDELAY = "sendDelay"; + public static final String PARAMETER_BAUDRATE = "baudRate"; public static final String PARAMETER_REQUESTACK = "requestack"; public static final int MYSENSORS_MSG_TYPE_PRESENTATION = 0; diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java index c951f56085ae5..47c0f70fdaf54 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java @@ -58,8 +58,6 @@ public void initialize() { MySensorsBridgeConfiguration configuration = getConfigAs(MySensorsBridgeConfiguration.class); - logger.debug("BAUDRATE {} {}", configuration.baudRate, configuration.sendDelay); - if (getThing().getThingTypeUID().equals(THING_TYPE_BRIDGE_SER)) { mysCon = new MySensorsSerialConnection(configuration.serialPort, configuration.baudRate, configuration.sendDelay); From 2d251f5efe739de9e2069fa5e10124109802ff1f Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 28 Jan 2016 22:53:10 +0100 Subject: [PATCH 3/4] thread managing improved --- .../discovery/MySensorsDiscoveryService.java | 258 +++++++------ .../handler/MySensorsBridgeHandler.java | 29 +- .../mysensors/handler/MySensorsHandler.java | 365 +++++++++--------- .../internal/MySensorsBridgeConnection.java | 18 +- .../mysensors/protocol/MySensorsWriter.java | 179 +++++---- .../protocol/ip/MySensorsIpConnection.java | 169 ++++---- .../protocol/ip/MySensorsIpWriter.java | 31 +- .../serial/MySensorsSerialConnection.java | 21 +- .../serial/MySensorsSerialWriter.java | 29 +- 9 files changed, 597 insertions(+), 502 deletions(-) diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/discovery/MySensorsDiscoveryService.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/discovery/MySensorsDiscoveryService.java index 1a6343bf8665d..d703e765c93a8 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/discovery/MySensorsDiscoveryService.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/discovery/MySensorsDiscoveryService.java @@ -9,138 +9,150 @@ import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; import org.eclipse.smarthome.core.thing.ThingUID; -import org.eclipse.smarthome.core.thing.binding.builder.GenericThingBuilder; import org.openhab.binding.mysensors.handler.MySensorsBridgeHandler; -import org.openhab.binding.mysensors.handler.MySensorsStatusUpdateEvent; -import org.openhab.binding.mysensors.handler.MySensorsUpdateListener; import org.openhab.binding.mysensors.internal.MySensorsMessage; import org.openhab.binding.mysensors.service.DiscoveryThread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - - - /** * @author Tim Oberföll - * - * Discoveryservice for MySensors devices + * + * Discoveryservice for MySensors devices */ public class MySensorsDiscoveryService extends AbstractDiscoveryService { - - private Logger logger = LoggerFactory.getLogger(MySensorsDiscoveryService.class); - - private MySensorsBridgeHandler bridgeHandler = null; - - private DiscoveryThread discoThread = null; - - public MySensorsDiscoveryService(MySensorsBridgeHandler bridgeHandler) { - super(SUPPORTED_THING_TYPES_UIDS, 3000, false); - this.bridgeHandler = bridgeHandler; - } - - @Override - protected void startScan() { - if(discoThread == null) - discoThread = new DiscoveryThread(bridgeHandler.mysCon, this); - discoThread.start(); - } - - public void activate() { - - } - - public void deactivate() { - if(discoThread == null) - discoThread = new DiscoveryThread(bridgeHandler.mysCon, this); - discoThread.stop(); - } - - @Override - protected void stopScan() { - if(discoThread == null) - discoThread = new DiscoveryThread(bridgeHandler.mysCon, this); - discoThread.stop(); - } - - public void newDevicePresented(MySensorsMessage msg) { - - // Representation Message? - if(msg.getMsgType() == MYSENSORS_MSG_TYPE_PRESENTATION) { - logger.debug("Representation Message received"); - logger.debug("Preparing new thing for inbox"); - - - ThingUID uid = null; - - // uid must not contains dots - switch (msg.getSubType()) { - case MYSENSORS_SUBTYPE_S_HUM: - uid = new ThingUID(THING_TYPE_HUMIDITY, bridgeHandler.getThing().getUID(), "Humidity_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_TEMP: - uid = new ThingUID(THING_TYPE_TEMPERATURE, bridgeHandler.getThing().getUID(), "Temperature_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_MULTIMETER: - uid = new ThingUID(THING_TYPE_MULTIMETER, bridgeHandler.getThing().getUID(), "Multimeter_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_LIGHT: - uid = new ThingUID(THING_TYPE_LIGHT, bridgeHandler.getThing().getUID(), "Light_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_POWER: - uid = new ThingUID(THING_TYPE_POWER, bridgeHandler.getThing().getUID(), "Power_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_BARO: - uid = new ThingUID(THING_TYPE_BARO, bridgeHandler.getThing().getUID(), "Baro_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_DOOR: - uid = new ThingUID(THING_TYPE_DOOR, bridgeHandler.getThing().getUID(), "Door_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_MOTION: - uid = new ThingUID(THING_TYPE_MOTION, bridgeHandler.getThing().getUID(), "Motion_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_SMOKE: - uid = new ThingUID(THING_TYPE_SMOKE, bridgeHandler.getThing().getUID(), "Smoke_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_DIMMER: - uid = new ThingUID(THING_TYPE_DIMMER, bridgeHandler.getThing().getUID(), "Dimmer_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_COVER: - uid = new ThingUID(THING_TYPE_COVER, bridgeHandler.getThing().getUID(), "Cover_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_WIND: - uid = new ThingUID(THING_TYPE_WIND, bridgeHandler.getThing().getUID(), "Wind_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_RAIN: - uid = new ThingUID(THING_TYPE_RAIN, bridgeHandler.getThing().getUID(), "Rain_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_UV: - uid = new ThingUID(THING_TYPE_UV, bridgeHandler.getThing().getUID(), "UV_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_WEIGHT: - uid = new ThingUID(THING_TYPE_WEIGHT, bridgeHandler.getThing().getUID(), "Weight_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_DISTANCE: - uid = new ThingUID(THING_TYPE_DISTANCE, bridgeHandler.getThing().getUID(), "Distance_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - case MYSENSORS_SUBTYPE_S_LIGHT_LEVEL: - uid = new ThingUID(THING_TYPE_LIGHT_LEVEL, bridgeHandler.getThing().getUID(), "Light_level_" + msg.getNodeId() + "_" + msg.getChildId()); - break; - } - if(uid!=null) { - Map properties = new HashMap<>(2); - properties.put(PARAMETER_NODEID , ""+msg.getNodeId()); - properties.put(PARAMETER_CHILDID, ""+msg.getChildId()); - DiscoveryResult result = DiscoveryResultBuilder.create(uid) - .withProperties(properties) - .withLabel("MySensors Device (" + msg.getNodeId() + ";" + msg.getChildId() +")") - .withBridge(bridgeHandler.getThing().getUID()) - .build(); - thingDiscovered(result); - - logger.debug("Discovered device submitted"); - } - } - } + + private Logger logger = LoggerFactory.getLogger(MySensorsDiscoveryService.class); + + private MySensorsBridgeHandler bridgeHandler = null; + + private DiscoveryThread discoThread = null; + + public MySensorsDiscoveryService(MySensorsBridgeHandler bridgeHandler) { + super(SUPPORTED_THING_TYPES_UIDS, 3000, false); + this.bridgeHandler = bridgeHandler; + } + + @Override + protected void startScan() { + if (discoThread == null) { + discoThread = new DiscoveryThread(bridgeHandler.getBridgeConnection(), this); + } + discoThread.start(); + } + + public void activate() { + + } + + @Override + public void deactivate() { + if (discoThread == null) { + discoThread = new DiscoveryThread(bridgeHandler.getBridgeConnection(), this); + } + discoThread.stop(); + } + + @Override + protected void stopScan() { + if (discoThread == null) { + discoThread = new DiscoveryThread(bridgeHandler.getBridgeConnection(), this); + } + discoThread.stop(); + } + + public void newDevicePresented(MySensorsMessage msg) { + + // Representation Message? + if (msg.getMsgType() == MYSENSORS_MSG_TYPE_PRESENTATION) { + logger.debug("Representation Message received"); + logger.debug("Preparing new thing for inbox"); + + ThingUID uid = null; + + // uid must not contains dots + switch (msg.getSubType()) { + case MYSENSORS_SUBTYPE_S_HUM: + uid = new ThingUID(THING_TYPE_HUMIDITY, bridgeHandler.getThing().getUID(), + "Humidity_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_TEMP: + uid = new ThingUID(THING_TYPE_TEMPERATURE, bridgeHandler.getThing().getUID(), + "Temperature_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_MULTIMETER: + uid = new ThingUID(THING_TYPE_MULTIMETER, bridgeHandler.getThing().getUID(), + "Multimeter_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_LIGHT: + uid = new ThingUID(THING_TYPE_LIGHT, bridgeHandler.getThing().getUID(), + "Light_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_POWER: + uid = new ThingUID(THING_TYPE_POWER, bridgeHandler.getThing().getUID(), + "Power_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_BARO: + uid = new ThingUID(THING_TYPE_BARO, bridgeHandler.getThing().getUID(), + "Baro_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_DOOR: + uid = new ThingUID(THING_TYPE_DOOR, bridgeHandler.getThing().getUID(), + "Door_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_MOTION: + uid = new ThingUID(THING_TYPE_MOTION, bridgeHandler.getThing().getUID(), + "Motion_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_SMOKE: + uid = new ThingUID(THING_TYPE_SMOKE, bridgeHandler.getThing().getUID(), + "Smoke_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_DIMMER: + uid = new ThingUID(THING_TYPE_DIMMER, bridgeHandler.getThing().getUID(), + "Dimmer_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_COVER: + uid = new ThingUID(THING_TYPE_COVER, bridgeHandler.getThing().getUID(), + "Cover_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_WIND: + uid = new ThingUID(THING_TYPE_WIND, bridgeHandler.getThing().getUID(), + "Wind_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_RAIN: + uid = new ThingUID(THING_TYPE_RAIN, bridgeHandler.getThing().getUID(), + "Rain_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_UV: + uid = new ThingUID(THING_TYPE_UV, bridgeHandler.getThing().getUID(), + "UV_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_WEIGHT: + uid = new ThingUID(THING_TYPE_WEIGHT, bridgeHandler.getThing().getUID(), + "Weight_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_DISTANCE: + uid = new ThingUID(THING_TYPE_DISTANCE, bridgeHandler.getThing().getUID(), + "Distance_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + case MYSENSORS_SUBTYPE_S_LIGHT_LEVEL: + uid = new ThingUID(THING_TYPE_LIGHT_LEVEL, bridgeHandler.getThing().getUID(), + "Light_level_" + msg.getNodeId() + "_" + msg.getChildId()); + break; + } + if (uid != null) { + Map properties = new HashMap<>(2); + properties.put(PARAMETER_NODEID, "" + msg.getNodeId()); + properties.put(PARAMETER_CHILDID, "" + msg.getChildId()); + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) + .withLabel("MySensors Device (" + msg.getNodeId() + ";" + msg.getChildId() + ")") + .withBridge(bridgeHandler.getThing().getUID()).build(); + thingDiscovered(result); + + logger.debug("Discovered device submitted"); + } + } + } } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java index 47c0f70fdaf54..e069c8a7a3c57 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsBridgeHandler.java @@ -7,6 +7,9 @@ import java.util.Iterator; import java.util.List; import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.thing.Bridge; @@ -36,13 +39,16 @@ public class MySensorsBridgeHandler extends BaseBridgeHandler implements MySenso private Logger logger = LoggerFactory.getLogger(MySensorsBridgeHandler.class); - public MySensorsBridgeConnection mysCon = null; - public Collection connectedThings = Lists.newArrayList(); // List of Ids that OpenHAB has given, in response to an id request from a sensor node private List givenIds = new ArrayList(); + // Executor that hold the bridge reader thread + private ExecutorService executor = Executors.newSingleThreadExecutor(); + private Future future = null; + private MySensorsBridgeConnection mysCon = null; + public MySensorsBridgeHandler(Bridge bridge) { super(bridge); } @@ -65,8 +71,8 @@ public void initialize() { mysCon = new MySensorsIpConnection(configuration.ipAddress, configuration.tcpPort, configuration.sendDelay); } - if (mysCon.connected) { - mysCon.start(); + if (mysCon.connect()) { + future = executor.submit(mysCon); mysCon.addUpdateListener(this); updateStatus(ThingStatus.ONLINE); } else { @@ -86,7 +92,16 @@ public void initialize() { @Override public void dispose() { if (mysCon != null) { - mysCon.stopReader(); + mysCon.disconnect(); + } + + if (future != null) { + future.cancel(true); + } + + if (executor != null) { + executor.shutdown(); + executor.shutdownNow(); } } @@ -186,4 +201,8 @@ public void revertToOldStatus(MySensorsStatusUpdateEvent event) { } + public MySensorsBridgeConnection getBridgeConnection() { + return mysCon; + } + } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsHandler.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsHandler.java index 8118f945a87ae..9131daa12bbba 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsHandler.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/handler/MySensorsHandler.java @@ -13,7 +13,6 @@ import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.library.types.StopMoveType; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.library.types.UpDownType; import org.eclipse.smarthome.core.thing.Bridge; @@ -24,7 +23,6 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.StateOption; import org.openhab.binding.mysensors.config.MySensorsSensorConfiguration; import org.openhab.binding.mysensors.internal.MySensorsMessage; import org.slf4j.Logger; @@ -33,191 +31,206 @@ /** * The {@link MySensorsHandler} is responsible for handling commands, which are * sent to one of the channels. - * + * * @author Tim Oberföll - Initial contribution */ public class MySensorsHandler extends BaseThingHandler implements MySensorsUpdateListener { private Logger logger = LoggerFactory.getLogger(MySensorsHandler.class); - + private MySensorsSensorConfiguration configuration = null; - + private int nodeId = 0; private int childId = 0; private boolean requestack = false; - + private State oldState = null; - - public MySensorsHandler(Thing thing) { - super(thing); - } - - public void initialize() { - super.initialize(); - - configuration = getConfigAs(MySensorsSensorConfiguration.class); - nodeId = Integer.parseInt(configuration.nodeId); - childId = Integer.parseInt(configuration.childId); - requestack = configuration.requestack; - - updateStatus(ThingStatus.ONLINE); - } - - public void dispose() { - getBridgeHandler().mysCon.removeUpdateListener(this); - updateStatus(ThingStatus.OFFLINE); - super.dispose(); - } - - /* (non-Javadoc) - * @see org.eclipse.smarthome.core.thing.binding.ThingHandler#handleCommand(org.eclipse.smarthome.core.thing.ChannelUID, org.eclipse.smarthome.core.types.Command) - */ - public void handleCommand(ChannelUID channelUID, Command command) { - - - } - - /* (non-Javadoc) - * @see org.eclipse.smarthome.core.thing.binding.BaseThingHandler#handleUpdate(org.eclipse.smarthome.core.thing.ChannelUID, org.eclipse.smarthome.core.types.State) - */ - public void handleUpdate(ChannelUID channelUID, org.eclipse.smarthome.core.types.State newState) { - - String msg = ""; - int subType = 0; - int int_requestack = 0; - if(requestack) - int_requestack = 1; - - if(channelUID.getId().equals(CHANNEL_STATUS)) { - - subType = MYSENSORS_SUBTYPE_V_STATUS; - - if((OnOffType) newState == OnOffType.ON) - msg = "1"; - else if ((OnOffType) newState == OnOffType.OFF) - msg = "0"; - - + + public MySensorsHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + super.initialize(); + + configuration = getConfigAs(MySensorsSensorConfiguration.class); + nodeId = Integer.parseInt(configuration.nodeId); + childId = Integer.parseInt(configuration.childId); + requestack = configuration.requestack; + + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void dispose() { + getBridgeHandler().getBridgeConnection().removeUpdateListener(this); + updateStatus(ThingStatus.OFFLINE); + super.dispose(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.smarthome.core.thing.binding.ThingHandler#handleCommand(org.eclipse.smarthome.core.thing.ChannelUID, + * org.eclipse.smarthome.core.types.Command) + */ + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.smarthome.core.thing.binding.BaseThingHandler#handleUpdate(org.eclipse.smarthome.core.thing. + * ChannelUID, org.eclipse.smarthome.core.types.State) + */ + @Override + public void handleUpdate(ChannelUID channelUID, org.eclipse.smarthome.core.types.State newState) { + + String msg = ""; + int subType = 0; + int int_requestack = 0; + if (requestack) { + int_requestack = 1; + } + + if (channelUID.getId().equals(CHANNEL_STATUS)) { + + subType = MYSENSORS_SUBTYPE_V_STATUS; + + if ((OnOffType) newState == OnOffType.ON) { + msg = "1"; + } else if ((OnOffType) newState == OnOffType.OFF) { + msg = "0"; + } + } else if (channelUID.getId().equals(CHANNEL_DIMMER)) { - if(newState.getClass() == PercentType.class) { - msg = ((PercentType) newState).toString(); - subType = MYSENSORS_SUBTYPE_V_PERCENTAGE; - } else { - if((OnOffType) newState == OnOffType.ON) - msg = "1"; - else if ((OnOffType) newState == OnOffType.OFF) - msg = "0"; - subType = MYSENSORS_SUBTYPE_V_STATUS; - } + if (newState.getClass() == PercentType.class) { + msg = ((PercentType) newState).toString(); + subType = MYSENSORS_SUBTYPE_V_PERCENTAGE; + } else { + if ((OnOffType) newState == OnOffType.ON) { + msg = "1"; + } else if ((OnOffType) newState == OnOffType.OFF) { + msg = "0"; + } + subType = MYSENSORS_SUBTYPE_V_STATUS; + } } else if (channelUID.getId().equals(CHANNEL_COVER)) { - if(newState.getClass() == PercentType.class) { - msg = ((PercentType) newState).toString(); - subType = MYSENSORS_SUBTYPE_V_PERCENTAGE; - } else { - if((UpDownType) newState == UpDownType.UP) - subType = MYSENSORS_SUBTYPE_V_UP; - else if ((UpDownType) newState == UpDownType.DOWN) - subType = MYSENSORS_SUBTYPE_V_DOWN; - /*else if ((StopMoveType) newState == StopMoveType.STOP) - subType = MYSENSORS_SUBTYPE_V_STOP;*/ - msg = "1"; - - } + if (newState.getClass() == PercentType.class) { + msg = ((PercentType) newState).toString(); + subType = MYSENSORS_SUBTYPE_V_PERCENTAGE; + } else { + if ((UpDownType) newState == UpDownType.UP) { + subType = MYSENSORS_SUBTYPE_V_UP; + } else if ((UpDownType) newState == UpDownType.DOWN) { + subType = MYSENSORS_SUBTYPE_V_DOWN; + } + /* + * else if ((StopMoveType) newState == StopMoveType.STOP) + * subType = MYSENSORS_SUBTYPE_V_STOP; + */ + msg = "1"; + + } + } + + MySensorsMessage newMsg = new MySensorsMessage(nodeId, childId, MYSENSORS_MSG_TYPE_SET, int_requestack, subType, + msg); + + getBridgeHandler().getBridgeConnection().addMySensorsOutboundMessage(newMsg); + oldState = newState; + } + + /* + * (non-Javadoc) + * + * @see + * org.openhab.binding.mysensors.handler.MySensorsUpdateListener#statusUpdateReceived(org.openhab.binding.mysensors. + * handler.MySensorsStatusUpdateEvent) + */ + @Override + public void statusUpdateReceived(MySensorsStatusUpdateEvent event) { + MySensorsMessage msg = event.getData(); + + // or is this an update message? + if (nodeId == msg.getNodeId()) { // is this message for me? + if (msg.getMsgType() == MYSENSORS_MSG_TYPE_SET) { + if (childId == msg.getChildId()) { // which child should be updated? + + // Do we get an ACK? + if (msg.getAck() == 1) { + getBridgeHandler().getBridgeConnection().removeMySensorsOutboundMessage(msg); + } else if (CHANNEL_MAP.containsKey(msg.getSubType())) { + String channel = CHANNEL_MAP.get(msg.getSubType()); + if (channel.equals(CHANNEL_BARO)) { + updateState(channel, new StringType(msg.getMsg())); + } else if (channel.equals(CHANNEL_STATUS)) { + if (msg.getMsg().equals("1")) { + updateState(channel, OnOffType.ON); + } else { + updateState(channel, OnOffType.OFF); + } + } else if (channel.equals(CHANNEL_ARMED) || channel.equals(CHANNEL_TRIPPED)) { + if (msg.getMsg().equals("1")) { + updateState(channel, OpenClosedType.OPEN); + } else { + updateState(channel, OpenClosedType.CLOSED); + } + } else if (channel.equals(CHANNEL_DIMMER)) { + updateState(channel, new PercentType(msg.getMsg())); + } else if (channel.equals(CHANNEL_COVER)) { + if (msg.getMsg().equals(MYSENSORS_SUBTYPE_V_UP)) { + updateState(channel, UpDownType.UP); + } else if (msg.getMsg().equals(MYSENSORS_SUBTYPE_V_DOWN)) { + updateState(channel, UpDownType.DOWN); + } + } else { + logger.debug(channel); + logger.debug("subtype:" + msg.getSubType()); + updateState(channel, new DecimalType(msg.getMsg())); + } + } + } + } else if (msg.getMsgType() == MYSENSORS_MSG_TYPE_INTERNAL) { // INTERNAL MESSAGE? + if (CHANNEL_MAP_INTERNAL.containsKey(msg.getSubType())) { + String channel = CHANNEL_MAP_INTERNAL.get(msg.getSubType()); + if (channel.equals(CHANNEL_VERSION)) { + updateState(channel, new StringType(msg.getMsg())); + } else if (channel.equals(CHANNEL_BATTERY)) { + updateState(channel, new DecimalType(msg.getMsg())); + } + } + } } - - - MySensorsMessage newMsg = new MySensorsMessage( nodeId, - childId, - MYSENSORS_MSG_TYPE_SET, - int_requestack, - subType, - msg); - - getBridgeHandler().mysCon.addMySensorsOutboundMessage(newMsg); - oldState = newState; - } - - /* (non-Javadoc) - * @see org.openhab.binding.mysensors.handler.MySensorsUpdateListener#statusUpdateReceived(org.openhab.binding.mysensors.handler.MySensorsStatusUpdateEvent) - */ - @Override - public void statusUpdateReceived(MySensorsStatusUpdateEvent event) { - MySensorsMessage msg = event.getData(); - - - // or is this an update message? - if(nodeId == msg.getNodeId()) { // is this message for me? - if (msg.getMsgType() == MYSENSORS_MSG_TYPE_SET) { - if(childId == msg.getChildId()) { // which child should be updated? - - // Do we get an ACK? - if(msg.getAck() == 1) { - getBridgeHandler().mysCon.removeMySensorsOutboundMessage(msg); - } else if(CHANNEL_MAP.containsKey(msg.getSubType())) { - String channel = CHANNEL_MAP.get(msg.getSubType()); - if(channel.equals(CHANNEL_BARO)) { - updateState(channel, new StringType(msg.getMsg())); - } else if(channel.equals(CHANNEL_STATUS)) { - if(msg.getMsg().equals("1")) - updateState(channel, OnOffType.ON); - else - updateState(channel, OnOffType.OFF); - } else if(channel.equals(CHANNEL_ARMED) || channel.equals(CHANNEL_TRIPPED)) { - if(msg.getMsg().equals("1")) - updateState(channel, OpenClosedType.OPEN); - else - updateState(channel, OpenClosedType.CLOSED); - } else if(channel.equals(CHANNEL_DIMMER)) { - updateState(channel, new PercentType(msg.getMsg())); - } else if(channel.equals(CHANNEL_COVER)) { - if(msg.getMsg().equals(MYSENSORS_SUBTYPE_V_UP)) - updateState(channel, UpDownType.UP); - else if(msg.getMsg().equals(MYSENSORS_SUBTYPE_V_DOWN)) - updateState(channel, UpDownType.DOWN); - } else { - logger.debug(channel); - logger.debug("subtype:" + msg.getSubType()); - updateState(channel, new DecimalType(msg.getMsg())); - } - } - } - } else if(msg.getMsgType() == MYSENSORS_MSG_TYPE_INTERNAL) { // INTERNAL MESSAGE? - if(CHANNEL_MAP_INTERNAL.containsKey(msg.getSubType())) { - String channel = CHANNEL_MAP_INTERNAL.get(msg.getSubType()); - if(channel.equals(CHANNEL_VERSION)) { - updateState(channel, new StringType(msg.getMsg())); - } else if (channel.equals(CHANNEL_BATTERY)){ - updateState(channel, new DecimalType(msg.getMsg())); - } - } - } - } - - - } - - /** - * Returns the BridgeHandler of the bridge/gateway to the MySensors network - * @return BridgeHandler of the bridge/gateway to the MySensors network - */ - public synchronized MySensorsBridgeHandler getBridgeHandler() { - MySensorsBridgeHandler myBridgeHandler = null; - - Bridge bridge = getBridge(); - myBridgeHandler = (MySensorsBridgeHandler)bridge.getHandler(); - - - return myBridgeHandler; - } - - protected void bridgeHandlerInitialized(ThingHandler thingHandler, Bridge bridge){ - MySensorsBridgeHandler bridgeHandler = (MySensorsBridgeHandler)thingHandler; - bridgeHandler.mysCon.addUpdateListener(this); - } - - @Override - public void revertToOldStatus(MySensorsStatusUpdateEvent event) { - - - } + + } + + /** + * Returns the BridgeHandler of the bridge/gateway to the MySensors network + * + * @return BridgeHandler of the bridge/gateway to the MySensors network + */ + public synchronized MySensorsBridgeHandler getBridgeHandler() { + MySensorsBridgeHandler myBridgeHandler = null; + + Bridge bridge = getBridge(); + myBridgeHandler = (MySensorsBridgeHandler) bridge.getHandler(); + + return myBridgeHandler; + } + + @Override + protected void bridgeHandlerInitialized(ThingHandler thingHandler, Bridge bridge) { + MySensorsBridgeHandler bridgeHandler = (MySensorsBridgeHandler) thingHandler; + bridgeHandler.getBridgeConnection().addUpdateListener(this); + } + + @Override + public void revertToOldStatus(MySensorsStatusUpdateEvent event) { + + } } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java index 1bbd75c4fcb3b..af1949d43311b 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java @@ -10,7 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class MySensorsBridgeConnection extends Thread { +public abstract class MySensorsBridgeConnection implements Runnable { private Logger logger = LoggerFactory.getLogger(MySensorsBridgeConnection.class); @@ -19,7 +19,7 @@ public abstract class MySensorsBridgeConnection extends Thread { public List MySensorsMessageOutboundQueue = Collections .synchronizedList(new LinkedList()); - public boolean connected = false; + protected boolean connected = false; protected boolean stopReader = false; @@ -27,6 +27,20 @@ public MySensorsBridgeConnection() { updateListeners = new ArrayList<>(); } + /** + * startup connection with bridge + * + * @return + */ + public abstract boolean connect(); + + /** + * shutodown method that allows the correct disconnection with the used bridge + * + * @return + */ + public abstract void disconnect(); + /** * @param listener An Object, that wants to listen on status updates */ diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java index 06724a287add0..8f353f9707c90 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java @@ -1,10 +1,11 @@ package org.openhab.binding.mysensors.protocol; -import static org.openhab.binding.mysensors.MySensorsBindingConstants.MYSENSORS_NUMBER_OF_RETRIES; -import static org.openhab.binding.mysensors.MySensorsBindingConstants.MYSENSORS_RETRY_TIMES; +import static org.openhab.binding.mysensors.MySensorsBindingConstants.*; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.PrintWriter; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.openhab.binding.mysensors.handler.MySensorsStatusUpdateEvent; import org.openhab.binding.mysensors.handler.MySensorsUpdateListener; @@ -14,79 +15,99 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class MySensorsWriter extends Thread implements MySensorsUpdateListener { - protected Logger logger = LoggerFactory.getLogger(MySensorsWriter.class); - - protected boolean stopWriting = false; - protected long lastSend = System.currentTimeMillis(); - protected DataOutputStream outs = null; - protected int sendDelay = 0; - protected MySensorsBridgeConnection mysCon = null; - - public synchronized void run() { - - - while(!stopWriting) { - if(lastSend + sendDelay < System.currentTimeMillis()) { - // Is there something to write? - if(!mysCon.MySensorsMessageOutboundQueue.isEmpty()) { - MySensorsMessage msg = mysCon.MySensorsMessageOutboundQueue.get(0); - if(msg.getNextSend() < System.currentTimeMillis()) { - mysCon.MySensorsMessageOutboundQueue.remove(0); - // if we request an ACK we will wait for it and keep the message in the queue (at the end) - // otherwise we remove the message from the queue - if(msg.getAck() == 1) { - msg.setRetries(msg.getRetries()+1); - if(!(msg.getRetries() >= MYSENSORS_NUMBER_OF_RETRIES)) { - msg.setNextSend(System.currentTimeMillis() + MYSENSORS_RETRY_TIMES[msg.getRetries()]); - mysCon.addMySensorsOutboundMessage(msg); - } else { - logger.warn("NO ACK from nodeId: " + msg.getNodeId()); - - // Revert to old state - MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); - for (MySensorsUpdateListener mySensorsEventListener : mysCon.updateListeners) { - mySensorsEventListener.revertToOldStatus(event); - } - - continue; - } - } - String output = MySensorsMessageParser.generateAPIString(msg); - logger.debug("Sending to MySensors: " + output); - - sendMessage(output); - - } - lastSend = System.currentTimeMillis(); - } - } - } - } - - protected void sendMessage(String output) { - try { - outs.writeBytes(output); - outs.flush(); - } catch (IOException e) { - // TODO Auto-generated catch block - logger.error(e.toString()); - } - } - - public void stopWriting() { - this.stopWriting = true; - } - - @Override - public void statusUpdateReceived(MySensorsStatusUpdateEvent event) { - // TODO Auto-generated method stub - - } - - @Override - public void revertToOldStatus(MySensorsStatusUpdateEvent event) { - // TODO Auto-generated method stub - - } +public abstract class MySensorsWriter implements MySensorsUpdateListener, Runnable { + protected Logger logger = LoggerFactory.getLogger(MySensorsWriter.class); + + protected boolean stopWriting = false; + protected long lastSend = System.currentTimeMillis(); + protected PrintWriter outs = null; + protected int sendDelay = 0; + protected MySensorsBridgeConnection mysCon = null; + + protected ExecutorService executor = Executors.newSingleThreadExecutor(); + protected Future future = null; + + public void startWriter() { + future = executor.submit(this); + } + + @Override + public synchronized void run() { + + while (!stopWriting) { + if (lastSend + sendDelay < System.currentTimeMillis()) { + // Is there something to write? + if (!mysCon.MySensorsMessageOutboundQueue.isEmpty()) { + MySensorsMessage msg = mysCon.MySensorsMessageOutboundQueue.get(0); + if (msg.getNextSend() < System.currentTimeMillis()) { + mysCon.MySensorsMessageOutboundQueue.remove(0); + // if we request an ACK we will wait for it and keep the message in the queue (at the end) + // otherwise we remove the message from the queue + if (msg.getAck() == 1) { + msg.setRetries(msg.getRetries() + 1); + if (!(msg.getRetries() >= MYSENSORS_NUMBER_OF_RETRIES)) { + msg.setNextSend(System.currentTimeMillis() + MYSENSORS_RETRY_TIMES[msg.getRetries()]); + mysCon.addMySensorsOutboundMessage(msg); + } else { + logger.warn("NO ACK from nodeId: " + msg.getNodeId()); + + // Revert to old state + MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); + for (MySensorsUpdateListener mySensorsEventListener : mysCon.updateListeners) { + mySensorsEventListener.revertToOldStatus(event); + } + + continue; + } + } + String output = MySensorsMessageParser.generateAPIString(msg); + logger.debug("Sending to MySensors: " + output); + + sendMessage(output); + + } + lastSend = System.currentTimeMillis(); + } + } + } + } + + protected void sendMessage(String output) { + outs.println(output); + outs.flush(); + } + + public void stopWriting() { + + logger.debug("Stopping Writer thread"); + + this.stopWriting = true; + + if (future != null) { + future.cancel(true); + } + + if (executor != null) { + executor.shutdown(); + executor.shutdownNow(); + } + + if (outs != null) { + outs.flush(); + outs.close(); + } + + } + + @Override + public void statusUpdateReceived(MySensorsStatusUpdateEvent event) { + // TODO Auto-generated method stub + + } + + @Override + public void revertToOldStatus(MySensorsStatusUpdateEvent event) { + // TODO Auto-generated method stub + + } } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java index a0d4cc609b643..a9745fcac3d62 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java @@ -1,6 +1,5 @@ package org.openhab.binding.mysensors.protocol.ip; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -16,80 +15,96 @@ import org.slf4j.LoggerFactory; public class MySensorsIpConnection extends MySensorsBridgeConnection { - - private Logger logger = LoggerFactory.getLogger(MySensorsIpConnection.class); - - private String ipAddress = ""; - private int tcpPort = 0; - public int sendDelay = 0; - - private BufferedReader buffRead = null; - private Socket sock = null; - - private MySensorsIpWriter mysConWriter = null; - - - public MySensorsIpConnection(String ipAddress, int tcpPort, int sendDelay) { - super(); - this.ipAddress = ipAddress; - this.tcpPort = tcpPort; - this.sendDelay = sendDelay; - - connect(); - } - - public void connect() { - logger.debug("Connecting to bridge ..."); - - try { - sock = new Socket(ipAddress, tcpPort); - buffRead = new BufferedReader(new InputStreamReader(sock.getInputStream())); - mysConWriter = new MySensorsIpWriter(sock, this, sendDelay); - } catch (UnknownHostException e) { - logger.error("Error while trying to connect to: " + ipAddress + ":" + tcpPort); - e.printStackTrace(); - } catch (IOException e) { - logger.error("Error while trying to connect InputStreamReader"); - e.printStackTrace(); - } - - if(buffRead != null) { - connected = true; - logger.debug("Connection to ethernet gateway successful!"); - } else { - logger.error("Something went wrong!"); - } - } - - public void run() { - mysConWriter.start(); - try { - if(buffRead != null) { - while(!stopReader) { - // Is there something to read? - - String line = buffRead.readLine(); - - if(line != null) { - logger.debug(line); - MySensorsMessage msg = MySensorsMessageParser.parse(line); - if(msg != null) { - MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); - for (MySensorsUpdateListener mySensorsEventListener : updateListeners) { - mySensorsEventListener.statusUpdateReceived(event); - } - } - } - } - } - - mysConWriter.stopWriting(); - - // Shut down socket - sock.close(); - } catch (IOException e) { - logger.error("Can't close socket!"); - e.printStackTrace(); - } - } + + private Logger logger = LoggerFactory.getLogger(MySensorsIpConnection.class); + + private String ipAddress = ""; + private int tcpPort = 0; + public int sendDelay = 0; + + private BufferedReader buffRead = null; + private Socket sock = null; + + private MySensorsIpWriter mysConWriter = null; + + public MySensorsIpConnection(String ipAddress, int tcpPort, int sendDelay) { + super(); + this.ipAddress = ipAddress; + this.tcpPort = tcpPort; + this.sendDelay = sendDelay; + } + + @Override + public boolean connect() { + logger.debug("Connecting to bridge ..."); + + try { + sock = new Socket(ipAddress, tcpPort); + buffRead = new BufferedReader(new InputStreamReader(sock.getInputStream())); + mysConWriter = new MySensorsIpWriter(sock, this, sendDelay); + } catch (UnknownHostException e) { + logger.error("Error while trying to connect to: " + ipAddress + ":" + tcpPort); + e.printStackTrace(); + } catch (IOException e) { + logger.error("Error while trying to connect InputStreamReader"); + e.printStackTrace(); + } + + if (buffRead != null) { + connected = true; + logger.debug("Connection to ethernet gateway successful!"); + } else { + logger.error("Something went wrong!"); + } + + return connected; + } + + @Override + public void run() { + mysConWriter.startWriter(); + try { + if (buffRead != null) { + while (!stopReader) { + // Is there something to read? + + String line = buffRead.readLine(); + + if (line != null) { + logger.debug(line); + MySensorsMessage msg = MySensorsMessageParser.parse(line); + if (msg != null) { + MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); + for (MySensorsUpdateListener mySensorsEventListener : updateListeners) { + mySensorsEventListener.statusUpdateReceived(event); + } + } + } + } + } + + } catch (IOException e) { + logger.error("exception on reading from socket, message: {}", e.getMessage()); + } + } + + @Override + public void disconnect() { + mysConWriter.stopWriting(); + + // Shut down socket + try { + + if (buffRead != null) { + buffRead.close(); + } + + if (sock != null) { + sock.close(); + } + } catch (IOException e) { + logger.error("cannot disconnect from socket, message: {}", e.getMessage()); + } + + } } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpWriter.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpWriter.java index 6bbbf44ac9007..71f25d588501f 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpWriter.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpWriter.java @@ -1,25 +1,24 @@ package org.openhab.binding.mysensors.protocol.ip; -import java.io.DataOutputStream; import java.io.IOException; +import java.io.PrintWriter; import java.net.Socket; -import org.openhab.binding.mysensors.handler.MySensorsStatusUpdateEvent; import org.openhab.binding.mysensors.protocol.MySensorsWriter; public class MySensorsIpWriter extends MySensorsWriter { - - private Socket sock = null; - - public MySensorsIpWriter(Socket sock, MySensorsIpConnection mysCon, int sendDelay){ - this.mysCon = mysCon; - this.sock = sock; - this.sendDelay = sendDelay; - try { - outs = new DataOutputStream(sock.getOutputStream()); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + + private Socket sock = null; + + public MySensorsIpWriter(Socket sock, MySensorsIpConnection mysCon, int sendDelay) { + this.mysCon = mysCon; + this.sock = sock; + this.sendDelay = sendDelay; + try { + outs = new PrintWriter(sock.getOutputStream()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java index 4e3db9ace4d48..a27b354967d22 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java @@ -1,7 +1,6 @@ package org.openhab.binding.mysensors.protocol.serial; import java.io.BufferedReader; -import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; @@ -39,6 +38,10 @@ public MySensorsSerialConnection(String serialPort, int baudRate, int sendDelay) this.baudRate = baudRate; this.sendDelay = sendDelay; + } + + @Override + public boolean connect() { logger.debug("Connecting to {} [baudRate:{}]", serialPort, baudRate); serialConnection = new NRSerialPort(serialPort, baudRate); @@ -50,6 +53,7 @@ public MySensorsSerialConnection(String serialPort, int baudRate, int sendDelay) logger.error("Can't connect to serial port. Wrong port?"); } + return connected; } /** @@ -59,11 +63,10 @@ public MySensorsSerialConnection(String serialPort, int baudRate, int sendDelay) @Override public void run() { - mysConWriter.start(); - - DataInputStream ins = new DataInputStream(serialConnection.getInputStream()); + mysConWriter.startWriter(); - BufferedReader buffRead = new BufferedReader(new InputStreamReader(ins)); + InputStreamReader ins = new InputStreamReader(serialConnection.getInputStream()); + BufferedReader buffRead = new BufferedReader(ins); while (!stopReader) { try { @@ -80,12 +83,18 @@ public void run() { } } } catch (IOException e) { - // Ignore this, there is nothing to read + // Strange behavior... + logger.error("exception on reading from serial port, message: {}", e.getMessage()); } } + } + + @Override + public void disconnect() { logger.debug("Shutting down serial connection!"); + stopReader(); serialConnection.disconnect(); mysConWriter.stopWriting(); } diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialWriter.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialWriter.java index 6d29cf7a19dd3..39f1430964d55 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialWriter.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialWriter.java @@ -1,27 +1,20 @@ package org.openhab.binding.mysensors.protocol.serial; -import java.io.BufferedWriter; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.Date; +import java.io.PrintWriter; -import org.openhab.binding.mysensors.internal.MySensorsMessageParser; import org.openhab.binding.mysensors.protocol.MySensorsWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import gnu.io.NRSerialPort; public class MySensorsSerialWriter extends MySensorsWriter { - - private NRSerialPort serialConnection = null; - - public MySensorsSerialWriter(NRSerialPort serialConnection, MySensorsSerialConnection mysCon, int sendDelay){ - this.mysCon = mysCon; - this.serialConnection = serialConnection; - this.sendDelay = sendDelay; - - outs = new DataOutputStream(serialConnection.getOutputStream()); - } + + private NRSerialPort serialConnection = null; + + public MySensorsSerialWriter(NRSerialPort serialConnection, MySensorsSerialConnection mysCon, int sendDelay) { + this.mysCon = mysCon; + this.serialConnection = serialConnection; + this.sendDelay = sendDelay; + + outs = new PrintWriter(serialConnection.getOutputStream()); + } } From 54499837af1248106afb21c2940bd2ffdc48733a Mon Sep 17 00:00:00 2001 From: Andrea Date: Sun, 31 Jan 2016 19:37:36 +0100 Subject: [PATCH 4/4] little fix allows correct start and stop for binding --- .../internal/MySensorsBridgeConnection.java | 1 + .../mysensors/protocol/MySensorsWriter.java | 1 - .../protocol/ip/MySensorsIpConnection.java | 9 +++- .../serial/MySensorsSerialConnection.java | 44 +++++++++++-------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java index af1949d43311b..e3229784ec9ac 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/internal/MySensorsBridgeConnection.java @@ -16,6 +16,7 @@ public abstract class MySensorsBridgeConnection implements Runnable { public List updateListeners; + // FIXME must be replaced with a blocking queue public List MySensorsMessageOutboundQueue = Collections .synchronizedList(new LinkedList()); diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java index 8f353f9707c90..b7544760bc32d 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/MySensorsWriter.java @@ -33,7 +33,6 @@ public void startWriter() { @Override public synchronized void run() { - while (!stopWriting) { if (lastSend + sendDelay < System.currentTimeMillis()) { // Is there something to write? diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java index a9745fcac3d62..57c71d516cc1e 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/ip/MySensorsIpConnection.java @@ -90,7 +90,12 @@ public void run() { @Override public void disconnect() { - mysConWriter.stopWriting(); + + if (mysConWriter != null) { + mysConWriter.stopWriting(); + } + + stopReader(); // Shut down socket try { @@ -99,7 +104,7 @@ public void disconnect() { buffRead.close(); } - if (sock != null) { + if (sock != null && sock.isConnected()) { sock.close(); } } catch (IOException e) { diff --git a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java index a27b354967d22..6c401b25e018b 100644 --- a/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java +++ b/addons/binding/org.openhab.binding.mysensors/src/main/java/org/openhab/binding/mysensors/protocol/serial/MySensorsSerialConnection.java @@ -1,7 +1,6 @@ package org.openhab.binding.mysensors.protocol.serial; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import org.openhab.binding.mysensors.handler.MySensorsStatusUpdateEvent; @@ -46,8 +45,8 @@ public boolean connect() { serialConnection = new NRSerialPort(serialPort, baudRate); if (serialConnection.connect()) { - connected = true; logger.debug("Successfully connected to serial port."); + connected = true; mysConWriter = new MySensorsSerialWriter(serialConnection, this, sendDelay); } else { logger.error("Can't connect to serial port. Wrong port?"); @@ -65,27 +64,28 @@ public void run() { mysConWriter.startWriter(); - InputStreamReader ins = new InputStreamReader(serialConnection.getInputStream()); - BufferedReader buffRead = new BufferedReader(ins); + BufferedReader buffRead = new BufferedReader(new InputStreamReader(serialConnection.getInputStream())); + String line = null; while (!stopReader) { + // Is there something to read? + // String line = buffRead.readLine(); try { - // Is there something to read? - String line = buffRead.readLine(); - if (line != null) { - logger.debug(line); - MySensorsMessage msg = MySensorsMessageParser.parse(line); - if (msg != null) { - MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); - for (MySensorsUpdateListener mySensorsEventListener : updateListeners) { - mySensorsEventListener.statusUpdateReceived(event); - } + line = buffRead.readLine(); + logger.debug(line); + MySensorsMessage msg = MySensorsMessageParser.parse(line); + if (msg != null) { + MySensorsStatusUpdateEvent event = new MySensorsStatusUpdateEvent(msg); + for (MySensorsUpdateListener mySensorsEventListener : updateListeners) { + mySensorsEventListener.statusUpdateReceived(event); } } - } catch (IOException e) { - // Strange behavior... - logger.error("exception on reading from serial port, message: {}", e.getMessage()); + } catch (Exception e) { + // FIXME this exception has to be fixed, is not normal to have exception: Underlying input stream + // returned zero bytes + // logger.error("exception on reading from serial port, message: {}", e.getMessage()); } + } } @@ -94,9 +94,15 @@ public void run() { public void disconnect() { logger.debug("Shutting down serial connection!"); + if (mysConWriter != null) { + mysConWriter.stopWriting(); + } + stopReader(); - serialConnection.disconnect(); - mysConWriter.stopWriting(); + + if (serialConnection != null && serialConnection.isConnected()) { + serialConnection.disconnect(); + } } }