Skip to content

Commit

Permalink
Several fixes to make command class polling fully functional for Swit…
Browse files Browse the repository at this point in the history
…chBinary and Meter commands. Also fixed several discovery issue in node detection and action transaction completion detection.
  • Loading branch information
renarj committed May 16, 2015
1 parent 1567c5b commit e6d2d8c
Show file tree
Hide file tree
Showing 21 changed files with 172 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.oberasoftware.home.zwave;

import com.oberasoftware.home.zwave.api.ControllerConnector;
import com.oberasoftware.home.zwave.exceptions.RuntimeAutomationException;
import com.oberasoftware.home.zwave.api.messages.ZWaveRawMessage;
import com.oberasoftware.home.zwave.core.utils.IOSupplier;
import com.oberasoftware.home.zwave.exceptions.RuntimeAutomationException;
import com.oberasoftware.home.zwave.exceptions.ZWaveException;
import com.oberasoftware.home.zwave.api.messages.ZWaveRawMessage;
import com.oberasoftware.home.zwave.threading.ReceiverThread;
import com.oberasoftware.home.zwave.threading.SenderThread;
import gnu.io.*;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -41,32 +45,36 @@ public class SerialZWaveConnector implements ControllerConnector {
@Autowired
private SenderThread senderThread;

private boolean isConnected = false;

/**
* Connect to the zwave controller
*
* @throws ZWaveException if unable to connect to the serial device
*/
@PostConstruct
public void connect() throws ZWaveException {
LOG.info("Connecting to ZWave serial port device: {}", portName);
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
CommPort commPort = portIdentifier.open("zwaveport", 2000);
this.serialPort = (SerialPort) commPort;
this.serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
this.serialPort.enableReceiveThreshold(1);
this.serialPort.enableReceiveTimeout(ZWAVE_RECEIVE_TIMEOUT);

this.receiverThread.start();
this.senderThread.start();

LOG.info("ZWave controller is connected");
} catch (NoSuchPortException e) {
throw new ZWaveException(String.format("Serial port %s does not exist", portName), e);
} catch (PortInUseException e) {
throw new ZWaveException(String.format("Serial port %s is in use", portName), e);
} catch (UnsupportedCommOperationException e) {
throw new ZWaveException(String.format("Unsupported operation on serial port %s", portName), e);
public synchronized void connect() throws ZWaveException {
if(!isConnected) {
LOG.info("Connecting to ZWave serial port device: {}", portName);
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
CommPort commPort = portIdentifier.open("zwaveport", 2000);
this.serialPort = (SerialPort) commPort;
this.serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
this.serialPort.enableReceiveThreshold(1);
this.serialPort.enableReceiveTimeout(ZWAVE_RECEIVE_TIMEOUT);

this.receiverThread.start();
this.senderThread.start();

this.isConnected = true;
LOG.info("ZWave controller is connected");
} catch (NoSuchPortException e) {
throw new ZWaveException(String.format("Serial port %s does not exist", portName), e);
} catch (PortInUseException e) {
throw new ZWaveException(String.format("Serial port %s is in use", portName), e);
} catch (UnsupportedCommOperationException e) {
throw new ZWaveException(String.format("Unsupported operation on serial port %s", portName), e);
}
}
}

Expand All @@ -81,6 +89,7 @@ public void close() throws ZWaveException {

serialPort.close();
serialPort = null;
isConnected = false;
}

public OutputStream getOutputStream() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ private boolean isDeviceReady(ZWaveAction action) {

//we can send if the device is a battery device that is awake, or if not a battery device at all
return (batteryDevice && node.getAvailability() == AWAKE) || !batteryDevice;
} else {
LOG.warn("We have no node information for node: {} device is not ready", ((ZWaveDeviceAction) action).getNodeId());
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void initializeNetwork() {
}

@Override
public <T> void subscribe(EventHandler eventListener) {
public void subscribe(EventHandler eventListener) {
eventBus.registerHandler(eventListener);
}

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/oberasoftware/home/zwave/ZwaveSessionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.oberasoftware.home.zwave.api.ZWaveSession;
import com.oberasoftware.home.zwave.core.NodeManager;
import com.oberasoftware.home.zwave.exceptions.HomeAutomationException;
import com.oberasoftware.home.zwave.exceptions.ZWaveException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand All @@ -24,9 +25,18 @@ public class ZwaveSessionImpl implements ZWaveSession {
@Autowired
private ZWaveScheduler zWaveScheduler;

@Autowired
private SerialZWaveConnector zWaveConnector;

@Autowired
private NodeManager nodeManager;

@Override
public void connect() throws ZWaveException {
zWaveConnector.connect();
zWaveController.initializeNetwork();
}

@Override
public boolean isNetworkReady() {
return zWaveController.isNetworkReady();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface Controller {

int getControllerId();

<T> void subscribe(EventHandler topicListener);
void subscribe(EventHandler topicListener);

int send(ZWaveAction message) throws HomeAutomationException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.oberasoftware.base.event.EventHandler;
import com.oberasoftware.home.zwave.core.NodeManager;
import com.oberasoftware.home.zwave.exceptions.HomeAutomationException;
import com.oberasoftware.home.zwave.exceptions.ZWaveException;

import java.util.concurrent.TimeUnit;

/**
* @author renarj
*/
public interface ZWaveSession {
void connect() throws ZWaveException;

boolean isNetworkReady();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public CommandClass getCommandClass() {
public String toString() {
return "GenerateCommandClassPollAction{" +
"nodeId=" + nodeId +
", endpointId=" + endpointId +
", commandClass=" + commandClass +
'}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ public MultiInstanceEndpointAction(int nodeId) {
public int getNodeId() {
return nodeId;
}

@Override
public String toString() {
return "MultiInstanceEndpointAction{" +
"nodeId=" + nodeId +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.oberasoftware.home.zwave.api.actions.devices;

import com.oberasoftware.home.zwave.api.ZWaveAction;
import com.oberasoftware.home.zwave.api.ZWaveDeviceAction;

/**
* @author renarj
*/
public class RequestNodeInfoAction implements ZWaveAction {
public class RequestNodeInfoAction implements ZWaveDeviceAction {

private final int nodeId;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.oberasoftware.home.zwave.api.events.devices;

import com.oberasoftware.home.zwave.api.events.controller.TransactionEvent;
import com.oberasoftware.home.zwave.api.messages.types.MeterScale;

import java.util.List;

/**
* @author renarj
*/
public class MeterScalesEvent implements DeviceEvent, TransactionEvent {
private final int nodeId;
private final int endpointId;
private final List<MeterScale> scales;

public MeterScalesEvent(int nodeId, int endpointId, List<MeterScale> scales) {
this.nodeId = nodeId;
this.endpointId = endpointId;
this.scales = scales;
}

@Override
public int getNodeId() {
return nodeId;
}

public int getEndpointId() {
return endpointId;
}

public List<MeterScale> getScales() {
return scales;
}

@Override
public boolean isTransactionCompleted() {
return true;
}

@Override
public String toString() {
return "MeterScalesEvent{" +
"nodeId=" + nodeId +
", endpointId=" + endpointId +
", scales=" + scales +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.oberasoftware.home.zwave.api.events.devices;

import com.oberasoftware.home.zwave.api.events.controller.TransactionEvent;

/**
* @author renarj
*/
public class SwitchEvent implements DeviceEvent {
public class SwitchEvent implements DeviceEvent, TransactionEvent {
private final int nodeId;
private final boolean on;
private final int endpointId;
Expand Down Expand Up @@ -31,6 +33,11 @@ public int getEndpointId() {
return endpointId;
}

@Override
public boolean isTransactionCompleted() {
return true;
}

@Override
public String toString() {
return "SwitchEvent{" +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.oberasoftware.home.zwave.api.events.devices;

import com.oberasoftware.home.zwave.api.events.controller.TransactionEvent;

/**
* @author renarj
*/
public class SwitchLevelEvent implements DeviceEvent {
public class SwitchLevelEvent implements DeviceEvent, TransactionEvent {
private final int nodeId;
private final int value;

Expand All @@ -21,6 +23,11 @@ public int getValue() {
return value;
}

@Override
public boolean isTransactionCompleted() {
return true;
}

@Override
public String toString() {
return "SwitchLevelEvent{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.oberasoftware.home.zwave.core.NodeManager;
import com.oberasoftware.home.zwave.core.NodeStatus;
import com.oberasoftware.home.zwave.core.ZWaveNode;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand All @@ -18,12 +19,15 @@
import java.util.concurrent.ConcurrentHashMap;

import static com.google.common.collect.Lists.newArrayList;
import static org.slf4j.LoggerFactory.getLogger;

/**
* @author renarj
*/
@Component
public class NodeManagerImpl implements NodeManager {
private static final Logger LOG = getLogger(NodeManagerImpl.class);

private Map<Integer, ZWaveNode> nodeMap = new ConcurrentHashMap<>();

@Autowired
Expand Down Expand Up @@ -92,7 +96,11 @@ public ZWaveNode setNodeAvailability(int nodeId, NodeAvailability availability)
public boolean isBatteryDevice(int nodeId) {
ZWaveNode node = getNode(nodeId);

return node != null && node.getNodeInformation().isPresent() && !node.getNodeInformation().get().isListening();
boolean isBattery = node != null && node.getNodeInformation().isPresent() && !node.getNodeInformation().get().isListening();

LOG.debug("Checking if node: {} is battery device: {}", node, isBattery);

return isBattery;
}

@Override
Expand All @@ -111,18 +119,19 @@ public List<ZWaveNode> getNodes() {
public void setNodeInformation(int nodeId, NodeIdentifyEvent nodeIdentifyEvent) {
ZWaveNode node = getNode(nodeId);

replaceOrSetNode(new ZWaveNodeImpl(node.getNodeId()).setNodeInformation(nodeIdentifyEvent));
replaceOrSetNode(node.cloneNode().setNodeInformation(nodeIdentifyEvent));
}

@Override
public void setNodeInformation(int nodeId, ManufactorInfoEvent manufactorInfoEvent) {
ZWaveNode node = getNode(nodeId);

replaceOrSetNode(new ZWaveNodeImpl(node.getNodeId()).setManufacturerInformation(manufactorInfoEvent));
replaceOrSetNode(node.cloneNode().setManufacturerInformation(manufactorInfoEvent));
}

private ZWaveNode replaceOrSetNode(ZWaveNode node) {
int nodeId = node.getNodeId();
LOG.debug("Updating information of node: {} to: {}", nodeId, node);
nodeMap.put(nodeId, node);

eventBus.publish(new NodeUpdatedEvent(node.getNodeId(), node));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,13 @@ public ZWaveNodeImpl cloneNode() {
public String toString() {
return "ZWaveNodeImpl{" +
"nodeId=" + nodeId +
", endpoints=" + endpoints +
", nodeStatus=" + nodeStatus +
", availability=" + availability +
", nodeInformation=" + (optionalNodeInformation.isPresent() ? optionalNodeInformation.get().toString() : "") +
", manufacturerInformation=" + (optionalManufacturerInformation.isPresent() ? optionalManufacturerInformation.get().toString() : "") +
", optionalNodeInformation=" + optionalNodeInformation +
", optionalManufacturerInformation=" + optionalManufacturerInformation +
", commandClasses=" + commandClasses +
", endpoints=" + endpoints +
", nodeProperties=" + nodeProperties +
'}';
}
}
Loading

0 comments on commit e6d2d8c

Please sign in to comment.