package org.openhab.binding.zwave.internal.protocol.commandclass; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.openhab.binding.zwave.internal.protocol.SerialMessage; import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessageClass; import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessagePriority; import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessageType; import org.openhab.binding.zwave.internal.protocol.ZWaveController; import org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint; import org.openhab.binding.zwave.internal.protocol.ZWaveNode; import org.openhab.binding.zwave.internal.protocol.event.ZWaveCommandClassValueEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * Handles Barrier Operator Command Class for Items like Garage Door Opener etc... * * @author sankala * */ @XStreamAlias("barrierOperatorCommandClass") public class ZWaveBarrierOperatorCommandClass extends ZWaveCommandClass implements ZWaveGetCommands, ZWaveSetCommands { private static final Logger logger = LoggerFactory.getLogger(ZWaveBarrierOperatorCommandClass.class); public static final int BARRIER_OPERATOR_SET = 0x01; public static final int BARRIER_OPERATOR_GET = 0x02; public static final int BARRIER_OPERATOR_REPORT = 0x03; public static final int BARRIER_OPERATOR_SIGNAL_SUPPORTED_GET = 0x04; public static final int BARRIER_OPERATOR_SIGNAL_SUPPORTED_REPORT = 0x05; public static final int BARRIER_OPERATOR_SIGNAL_SET = 0x06; public static final int BARRIER_OPERATOR_SIGNAL_GET = 0x07; public static final int BARRIER_OPERATOR_SIGNAL_REPORT = 0x08; public ZWaveBarrierOperatorCommandClass(ZWaveNode node, ZWaveController controller, ZWaveEndpoint endpoint) { super(node, controller, endpoint); } @Override public SerialMessage setValueMessage(int value) { logger.debug("NODE {}: Creating new message for application command BARRIER_OPERATOR_SET", this.getNode().getNodeId()); SerialMessage result = new SerialMessage(this.getNode().getNodeId(), SerialMessageClass.SendData, SerialMessageType.Request, SerialMessageClass.SendData, SerialMessagePriority.Set); byte[] newPayload = { (byte) this.getNode().getNodeId(), 3, (byte) getCommandClass().getKey(), (byte) BARRIER_OPERATOR_SET, (byte) (value > 0 ? 0xFF : 0x00) }; result.setMessagePayload(newPayload); return result; } @Override public SerialMessage getValueMessage() { logger.debug("NODE {}: Creating new message for command BARRIER_OPERATOR_GET", this.getNode().getNodeId()); SerialMessage result = new SerialMessage(this.getNode().getNodeId(), SerialMessageClass.SendData, SerialMessageType.Request, SerialMessageClass.ApplicationCommandHandler, SerialMessagePriority.Get); byte[] newPayload = { (byte) this.getNode().getNodeId(), 2, (byte) getCommandClass().getKey(), (byte) BARRIER_OPERATOR_GET }; result.setMessagePayload(newPayload); return result; } @Override public CommandClass getCommandClass() { return CommandClass.BARRIER_OPERATOR; } @Override public void handleApplicationCommandRequest(SerialMessage serialMessage, int offset, int endpoint) { logger.debug("NODE {}: Received Barrier Operator Request", this.getNode().getNodeId()); int command = serialMessage.getMessagePayloadByte(offset); switch (command) { case BARRIER_OPERATOR_GET: case BARRIER_OPERATOR_SET: case BARRIER_OPERATOR_SIGNAL_GET: case BARRIER_OPERATOR_SIGNAL_SET: case BARRIER_OPERATOR_SIGNAL_REPORT: case BARRIER_OPERATOR_SIGNAL_SUPPORTED_GET: case BARRIER_OPERATOR_SIGNAL_SUPPORTED_REPORT: logger.warn("Command {} not implemented.", command); return; case BARRIER_OPERATOR_REPORT: logger.trace("Process Barrier Operator Report"); int value = serialMessage.getMessagePayloadByte(offset + 1); logger.debug("NODE {}: Barrier Operator report, value = {}", this.getNode().getNodeId(), value); ZWaveCommandClassValueEvent zEvent = new ZWaveBarrierOperatorValueEvent(this.getNode().getNodeId(), endpoint, this.getCommandClass(), value, BarrierOperatorStateType.getBarrierOperatorStateType(value)); this.getController().notifyEventListeners(zEvent); break; default: logger.warn(String.format("Unsupported Command 0x%02X for command class %s (0x%02X).", command, this.getCommandClass().getLabel(), this.getCommandClass().getKey())); } } @XStreamAlias("barrierOperatorState") public static enum BarrierOperatorStateType { STATE_CLOSED(0x00, "Closed"), STATE_CLOSING(0xFC, "Closing"), STATE_OPENED(0xFF, "Open"), STATE_OPENING(0xFE, "Opening"), STATE_STOPPED(0xFD, "Stopped"); private static Map<Integer, BarrierOperatorStateType> codeToBarrierOperatorStateTypeMapping; private int key; private String label; private static void initMapping() { codeToBarrierOperatorStateTypeMapping = new ConcurrentHashMap<Integer, ZWaveBarrierOperatorCommandClass.BarrierOperatorStateType>(); for (BarrierOperatorStateType s : values()) { codeToBarrierOperatorStateTypeMapping.put(s.key, s); } } public static BarrierOperatorStateType getBarrierOperatorStateType(int i) { if (codeToBarrierOperatorStateTypeMapping == null) { initMapping(); } BarrierOperatorStateType barrierOperatorStateType = codeToBarrierOperatorStateTypeMapping.get(i); // If the state is stopped, then the value indicates what is the percentage of opening. So it will not // directly yeild us the "StateStopped" . We have to force it to StateStopped. if (barrierOperatorStateType == null && (i < 99 && i > 0)) { barrierOperatorStateType = STATE_STOPPED; } return barrierOperatorStateType; } private BarrierOperatorStateType(int key, String label) { this.key = key; this.label = label; } public static Map<Integer, BarrierOperatorStateType> getCodeToBarrierOperatorStateTypeMapping() { return codeToBarrierOperatorStateTypeMapping; } public int getKey() { return key; } public int getValue() { return key; } public String getLabel() { return label; } } /** * Enhanced command class to provide all the various states possible for the BarrierOperator * * @author sankala * */ public static class ZWaveBarrierOperatorValueEvent extends ZWaveCommandClassValueEvent { private BarrierOperatorStateType barrierState; public ZWaveBarrierOperatorValueEvent(int nodeId, int endpoint, CommandClass commandClass, Object value, BarrierOperatorStateType barrierState) { super(nodeId, endpoint, commandClass, value); this.barrierState = barrierState; } public BarrierOperatorStateType getBarrierState() { return barrierState; } } }