Skip to content
This repository has been archived by the owner on May 17, 2021. It is now read-only.

Added OpenPaths presence detection binding #7

Closed
wants to merge 5 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add watchdog to PiFace binding
sumnerboy12 committed Sep 26, 2013

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 0bc77bfb352d845f2c7d501b58a637f01b365052
17 changes: 15 additions & 2 deletions bundles/binding/org.openhab.binding.piface/scripts/ohpiface.py
Original file line number Diff line number Diff line change
@@ -13,6 +13,10 @@
import piface.pfio as pfio
import SocketServer

ERROR_ACK = 0
WATCHDOG_CMD = 14
WATCHDOG_ACK = 15

WRITE_OUT_CMD = 1
WRITE_OUT_ACK = 2
READ_OUT_CMD = 3
@@ -73,8 +77,17 @@ def handle(self):
response = UdpPacket(DIGITAL_READ_ACK, packet.pin, pfio.digital_read(packet.pin))
socket.sendto(response.for_network(), self.client_address)

elif verbose:
print "Unkown packet command (%d). Ignoring." % packet.command
elif packet.command == WATCHDOG_CMD:
if verbose:
print "Watchdog request"
response = UdpPacket(WATCHDOG_ACK, packet.pin)
socket.sendto(response.for_network(), self.client_address)

else:
if verbose:
print "Unknown packet command (%d)" % packet.command
response = UdpPacket(ERROR_ACK, packet.pin)
socket.sendto(response.for_network(), self.client_address)

def start():
global verbose
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@

import java.util.List;

import org.openhab.binding.piface.internal.PifacePin;
import org.openhab.binding.piface.internal.PifaceBindingConfig;
import org.openhab.core.binding.BindingProvider;
import org.openhab.core.items.Item;

@@ -55,17 +55,17 @@ public interface PifaceBindingProvider extends BindingProvider {
Class<? extends Item> getItemType(String itemName);

/**
* Returns the pin details associated with an <code>itemName</code>
* Returns the binding config details associated with an <code>itemName</code>
* or <code>null</code> if it could not be found.
*
*/
PifacePin getPifacePin(String itemName);
PifaceBindingConfig getPifaceBindingConfig(String itemName);


/**
* Returns the list of <code>itemNames</code> associated with the
* specified pin (id, type, and number)
*
*/
List<String> getItemNames(String pifaceId, PifacePin.PinType pinType, int pinNumber);
List<String> getItemNames(String pifaceId, PifaceBindingConfig.BindingType bindingType, int pinNumber);
}
Original file line number Diff line number Diff line change
@@ -56,5 +56,4 @@ public void start(BundleContext bc) throws Exception {
public void stop(BundleContext bc) throws Exception {
logger.info("Piface binding has been stopped.");
}

}
Original file line number Diff line number Diff line change
@@ -41,7 +41,8 @@
import java.util.Map;

import org.openhab.binding.piface.PifaceBindingProvider;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.binding.piface.internal.PifaceBindingConfig.BindingType;
import org.openhab.core.binding.AbstractActiveBinding;
import org.openhab.core.binding.BindingProvider;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.ContactItem;
@@ -51,7 +52,6 @@
import org.openhab.core.types.Command;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -62,7 +62,7 @@
* @author Ben Jones
* @since 1.3.0
*/
public class PifaceBinding extends AbstractBinding<PifaceBindingProvider> implements ManagedService {
public class PifaceBinding extends AbstractActiveBinding<PifaceBindingProvider> implements ManagedService {

private static final Logger logger = LoggerFactory.getLogger(PifaceBinding.class);

@@ -76,23 +76,65 @@ public class PifaceBinding extends AbstractBinding<PifaceBindingProvider> implem
// socket timeout (1 sec) - should probably be a configurable parameter
private static final int SOCKET_TIMEOUT_MS = 1000;
private static final byte ERROR_RESPONSE = -1;

// list of Piface nodes loaded from the binding configuration
private final Map<String, PifaceNode> pifaceNodes = new HashMap<String, PifaceNode>();

// keeps track of all Piface pins which require initial read requests
private final List<PifacePin> pifacePinsToInitialise =
Collections.synchronizedList(new ArrayList<PifacePin>());
private final List<PifaceBindingConfig> bindingConfigsToInitialise =
Collections.synchronizedList(new ArrayList<PifaceBindingConfig>());

// the Piface pin initialiser, which runs in a separate thread
private final PifaceInitialiser initialiser = new PifaceInitialiser();

// default watchdog interval (defaults to 1 minute)
private long watchdogInterval = 60000L;

@Override
protected String getName() {
return "PiFace Watchdog Service";
}

@Override
protected long getRefreshInterval() {
return watchdogInterval;
}

/**
* @{inheritDoc}
*/
@Override
public void execute() {
if (!bindingsExist()) {
logger.debug("There is no existing PiFace binding configuration => watchdog cycle aborted!");
return;
}

// send a watchdog ping to each node
for (Map.Entry<String, PifaceNode> entry : pifaceNodes.entrySet()) {
String pifaceId = entry.getKey();
PifaceNode node = entry.getValue();

int value = sendWatchdog(node.host, node.listenerPort);
for (String itemName : getItemNamesForPin(pifaceId, BindingType.WATCHDOG, 0)) {
updateItemState(itemName, value);
}
}
}

public void activate(ComponentContext componentContext) {
/**
* @{inheritDoc}
*/
@Override
public void activate() {
initialiser.start();
}

public void deactivate(ComponentContext componentContext) {
/**
* @{inheritDoc}
*/
@Override
public void deactivate() {
stopMonitors();
pifaceNodes.clear();
providers.clear();
@@ -119,9 +161,9 @@ private void stopMonitors() {
public void bindingChanged(BindingProvider provider, String itemName) {
if (provider instanceof PifaceBindingProvider) {
PifaceBindingProvider pifaceProvider = (PifaceBindingProvider) provider;
PifacePin pin = pifaceProvider.getPifacePin(itemName);
if (pin != null && !pifacePinsToInitialise.contains(pin)) {
pifacePinsToInitialise.add(pin);
PifaceBindingConfig bindingConfig = pifaceProvider.getPifaceBindingConfig(itemName);
if (bindingConfig != null && isInitialisableBindingConfig(bindingConfig)) {
bindingConfigsToInitialise.add(bindingConfig);
}
}
}
@@ -133,14 +175,23 @@ public void allBindingsChanged(BindingProvider provider) {
if (provider instanceof PifaceBindingProvider) {
PifaceBindingProvider pifaceProvider = (PifaceBindingProvider) provider;
for (String itemName : pifaceProvider.getItemNames()) {
PifacePin pin = pifaceProvider.getPifacePin(itemName);
if (pin != null && !pifacePinsToInitialise.contains(pin)) {
pifacePinsToInitialise.add(pin);
PifaceBindingConfig bindingConfig = pifaceProvider.getPifaceBindingConfig(itemName);
if (bindingConfig != null && isInitialisableBindingConfig(bindingConfig)) {
bindingConfigsToInitialise.add(bindingConfig);
}
}
}
}

private boolean isInitialisableBindingConfig(PifaceBindingConfig bindingConfig) {
// only want to initialise each binding once
if (bindingConfigsToInitialise.contains(bindingConfig))
return false;

// ignore watchdog configs - don't need to initialise these
return bindingConfig.getBindingType() != BindingType.WATCHDOG;
}

private void updateItemState(String itemName, int value) {
Class<? extends Item> itemType = getItemType(itemName);
if (itemType.equals(SwitchItem.class)) {
@@ -166,12 +217,12 @@ private void updateItemState(String itemName, int value) {
@Override
public void internalReceiveCommand(String itemName, Command command) {
for (PifaceBindingProvider provider : getProvidersForItemName(itemName)) {
PifacePin pin = provider.getPifacePin(itemName);
PifaceBindingConfig pin = provider.getPifaceBindingConfig(itemName);
if (pin == null) {
logger.warn("No Piface pin configuration exists for '" + itemName + "'");
continue;
}
if (pin.getPinType() == PifacePin.PinType.IN) {
if (pin.getBindingType() == PifaceBindingConfig.BindingType.IN) {
logger.warn("Unable to send a command to a Piface 'IN' pin - these pin types are read-only");
continue;
}
@@ -195,18 +246,20 @@ public void internalReceiveCommand(String itemName, Command command) {
}
}

private int sendWatchdog(String host, int port) {
byte response = sendCommand(host, port,
PifaceCommand.WATCHDOG_CMD.toByte(), PifaceCommand.WATCHDOG_ACK.toByte(), 0, 0);
return response == ERROR_RESPONSE ? 0 : 1;
}

private void sendDigitalWrite(String host, int port, int pinNumber, int pinValue) {
sendCommand(host, port, PifaceCommand.DIGITAL_WRITE_CMD.toByte(), PifaceCommand.DIGITAL_WRITE_ACK.toByte(), pinNumber, pinValue);
}

private int sendDigitalRead(String host, int port, int pinNumber) {
byte response = sendCommand(host, port,
PifaceCommand.DIGITAL_READ_CMD.toByte(), PifaceCommand.DIGITAL_READ_ACK.toByte(), pinNumber, 0);
if (response == ERROR_RESPONSE) {
return -1;
}

return (int) response;
return response == ERROR_RESPONSE ? -1 : (int)response;
}

private byte sendCommand(String host, int port, byte command, byte commandAck, int pinNumber, int pinValue) {
@@ -231,6 +284,10 @@ private byte sendCommand(String host, int port, byte command, byte commandAck, i
socket.receive(receivePacket);

// check the response is valid
if (receiveData[0] == PifaceCommand.ERROR_ACK.toByte()) {
logger.error("Error 'ack' received");
return ERROR_RESPONSE;
}
if (receiveData[0] != commandAck) {
logger.error("Unexpected 'ack' code received - expecting " + commandAck + " but got " + receiveData[0]);
return ERROR_RESPONSE;
@@ -241,7 +298,7 @@ private byte sendCommand(String host, int port, byte command, byte commandAck, i
}

// return the data value
logger.debug("Command successfully sent and acknowledged (returned " + receiveData[2]+ ")");
logger.debug("Command successfully sent and acknowledged (returned " + receiveData[2] + ")");
return receiveData[2];
} catch (IOException e) {
logger.error("Failed to send UDP packet", e);
@@ -263,7 +320,7 @@ private List<PifaceBindingProvider> getProvidersForItemName(String itemName) {
return providers;
}

private List<String> getItemNamesForPin(String pifaceId, PifacePin.PinType pinType, int pinNumber) {
private List<String> getItemNamesForPin(String pifaceId, PifaceBindingConfig.BindingType pinType, int pinNumber) {
List<String> itemNames = new ArrayList<String>();
for (PifaceBindingProvider provider : this.providers) {
itemNames.addAll(provider.getItemNames(pifaceId, pinType, pinNumber));
@@ -296,6 +353,11 @@ public void updated(Dictionary config) throws ConfigurationException {
continue;
}

if ("watchdog.interval".equalsIgnoreCase(key)) {
watchdogInterval = Integer.parseInt(value);
continue;
}

String[] keyParts = key.split("\\.");
String pifaceId = keyParts[0];
String configKey = keyParts[1];
@@ -319,6 +381,9 @@ public void updated(Dictionary config) throws ConfigurationException {

// start the monitor threads for each PiFace node
startMonitors();

// starts the watch dog thread
setProperlyConfigured(true);
}
}

@@ -383,7 +448,7 @@ public void run() {
int pinValue = receiveData[1];
logger.debug(getName() + " received message for pin " + pinNumber + " (value=" + pinValue + ")");

for (String itemName : getItemNamesForPin(pifaceId, PifacePin.PinType.IN, pinNumber)) {
for (String itemName : getItemNamesForPin(pifaceId, PifaceBindingConfig.BindingType.IN, pinNumber)) {
updateItemState(itemName, pinValue);
}
}
@@ -421,11 +486,11 @@ public void setInterrupted(boolean interrupted) {
public void run() {
// as long as no interrupt is requested, continue running
while (!interrupted) {
if (pifacePinsToInitialise.size() > 0) {
if (bindingConfigsToInitialise.size() > 0) {
// we first clone the list, so that it stays unmodified
ArrayList<PifacePin> clonedList =
new ArrayList<PifacePin>(pifacePinsToInitialise);
initialisePifacePins(clonedList);
ArrayList<PifaceBindingConfig> clonedList =
new ArrayList<PifaceBindingConfig>(bindingConfigsToInitialise);
initialiseBindingConfigs(clonedList);
}
// just wait before looping again
try {
@@ -436,24 +501,23 @@ public void run() {
}
}

private void initialisePifacePins(ArrayList<PifacePin> clonedList) {
for (PifacePin pin : clonedList) {
private void initialiseBindingConfigs(ArrayList<PifaceBindingConfig> clonedList) {
for (PifaceBindingConfig bindingConfig : clonedList) {
try {
// the Piface node might not have been read from the binding config yet so just skip
// and we will try again on the next loop
PifaceNode node = pifaceNodes.get(pin.getPifaceId());
PifaceNode node = pifaceNodes.get(bindingConfig.getPifaceId());
if (node == null)
continue;

int pinValue = sendDigitalRead(node.host, node.listenerPort, pin.getPinNumber());
for (String itemName : getItemNamesForPin(pin.getPifaceId(), pin.getPinType(), pin.getPinNumber()))
updateItemState(itemName, pinValue);
pifacePinsToInitialise.remove(pin);
int value = sendDigitalRead(node.host, node.listenerPort, bindingConfig.getPinNumber());
for (String itemName : getItemNamesForPin(bindingConfig.getPifaceId(), bindingConfig.getBindingType(), bindingConfig.getPinNumber()))
updateItemState(itemName, value);
bindingConfigsToInitialise.remove(bindingConfig);
} catch (Exception e) {
logger.warn("Failed to initialise value for Piface pin {} ({}): {}", new Object[] { pin.getPinNumber(), pin.getPifaceId(), e.getMessage() });
logger.warn("Failed to initialise value for Piface pin {} ({}): {}", new Object[] { bindingConfig.getPinNumber(), bindingConfig.getPifaceId(), e.getMessage() });
}
}
}
}

}
Loading