Search in sources :

Example 6 with ZWaveCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass in project openhab1-addons by openhab.

the class ApplicationUpdateMessageClass method handleRequest.

@Override
public boolean handleRequest(ZWaveController zController, SerialMessage lastSentMessage, SerialMessage incomingMessage) {
    int nodeId;
    boolean result = true;
    UpdateState updateState = UpdateState.getUpdateState(incomingMessage.getMessagePayloadByte(0));
    switch(updateState) {
        case NODE_INFO_RECEIVED:
            // We've received a NIF, and this contains the node ID.
            nodeId = incomingMessage.getMessagePayloadByte(1);
            logger.debug("NODE {}: Application update request. Node information received.", nodeId);
            int length = incomingMessage.getMessagePayloadByte(2);
            ZWaveNode node = zController.getNode(nodeId);
            if (node == null) {
                logger.debug("NODE {}: Application update request. Node not known!", nodeId);
                // This allows everyone to be notified.
                if (nodeId > 0 && nodeId <= 232) {
                    zController.notifyEventListeners(new ZWaveInclusionEvent(ZWaveInclusionEvent.Type.IncludeDone, incomingMessage.getMessagePayloadByte(2)));
                }
                break;
            }
            node.resetResendCount();
            // Remember that we've received this so we can continue initialisation
            node.setApplicationUpdateReceived(true);
            // If we're finished initialisation, then we can treat this like a HAIL
            if (node.getNodeInitializationStage() == ZWaveNodeInitStage.DONE) {
                // If this node supports associations, then assume this should be handled through that mechanism
                if (node.getCommandClass(CommandClass.ASSOCIATION) == null) {
                    // If we receive an Application Update Request and the node is already
                    // fully initialised we assume this is a request to the controller to
                    // re-get the current node values
                    logger.debug("NODE {}: Application update request. Requesting node state.", nodeId);
                    zController.pollNode(node);
                }
            } else {
                List<Integer> nif = new ArrayList<Integer>();
                for (int i = 6; i < length + 3; i++) {
                    int data = incomingMessage.getMessagePayloadByte(i);
                    if (data == 0xef) {
                        // TODO: Implement control command classes
                        break;
                    }
                    logger.trace(String.format("NODE %d: Command class 0x%02X is supported.", nodeId, data));
                    // See if the command class already exists on the node
                    CommandClass commandClass = CommandClass.getCommandClass(data);
                    if (node.getCommandClass(commandClass) == null) {
                        // add it
                        ZWaveCommandClass zwaveCommandClass = ZWaveCommandClass.getInstance(data, node, zController);
                        if (zwaveCommandClass != null) {
                            logger.trace(String.format("NODE %d: Application update request. Adding Command class %s.", nodeId, commandClass));
                            node.addCommandClass(zwaveCommandClass);
                        }
                    }
                }
                node.updateNIF(nif);
            }
            // Notify we received an info frame
            zController.notifyEventListeners(new ZWaveNodeInfoEvent(nodeId));
            // Treat the node information frame as a wakeup
            ZWaveWakeUpCommandClass wakeUp = (ZWaveWakeUpCommandClass) node.getCommandClass(ZWaveCommandClass.CommandClass.WAKE_UP);
            if (wakeUp != null) {
                wakeUp.setAwake(true);
            }
            break;
        case NODE_INFO_REQ_FAILED:
            // Make sure we can correlate the request before we use the nodeId
            if (lastSentMessage.getMessageClass() != SerialMessageClass.RequestNodeInfo) {
                logger.warn("Got ApplicationUpdateMessage without request, ignoring. Last message was {}.", lastSentMessage.getMessageClass());
                return false;
            }
            // The failed message doesn't contain the node number, so use the info from the request.
            nodeId = lastSentMessage.getMessageNode();
            logger.debug("NODE {}: Application update request. Node Info Request Failed.", nodeId);
            // Handle retries
            if (--lastSentMessage.attempts >= 0) {
                logger.error("NODE {}: Got Node Info Request Failed. Requeueing", nodeId);
                zController.enqueue(lastSentMessage);
            } else {
                logger.warn("NODE {}: Node Info Request Failed 3x. Discarding message: {}", nodeId, lastSentMessage.toString());
            }
            // Transaction is not successful
            incomingMessage.setTransactionCanceled();
            result = false;
            break;
        default:
            logger.warn("TODO: Implement Application Update Request Handling of {} ({}).", updateState.getLabel(), updateState.getKey());
    }
    // Check if this completes the transaction
    checkTransactionComplete(lastSentMessage, incomingMessage);
    return result;
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) ZWaveInclusionEvent(org.openhab.binding.zwave.internal.protocol.event.ZWaveInclusionEvent) ArrayList(java.util.ArrayList) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass) CommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNodeInfoEvent(org.openhab.binding.zwave.internal.protocol.event.ZWaveNodeInfoEvent) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)

Example 7 with ZWaveCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass in project openhab1-addons by openhab.

the class ApplicationCommandMessageClass method resolveZWaveCommandClass.

/**
     * Takes the given commandClassCode and tries to instantiate the corresponding {@link ZWaveCommandClass}
     * for the given node
     *
     * @return the zwave command class for this node or null if it is not possible
     */
private ZWaveCommandClass resolveZWaveCommandClass(ZWaveNode node, int commandClassCode, ZWaveController zController) {
    CommandClass commandClass = CommandClass.getCommandClass(commandClassCode & 0xff);
    if (commandClass == null) {
        logger.error(String.format("NODE %d: Unsupported command class 0x%02x", node.getNodeId(), commandClassCode));
        return null;
    }
    logger.debug(String.format("NODE %d: Incoming command class %s (0x%02x)", node.getNodeId(), commandClass.getLabel(), commandClass.getKey()));
    ZWaveCommandClass zwaveCommandClass = node.getCommandClass(commandClass);
    // Let's add it now then to support handling this message.
    if (zwaveCommandClass == null) {
        logger.debug(String.format("NODE %d: Command class %s (0x%02x) not found, trying to add it.", node.getNodeId(), commandClass.getLabel(), commandClass.getKey()));
        zwaveCommandClass = ZWaveCommandClass.getInstance(commandClass.getKey(), node, zController);
        if (zwaveCommandClass == null) {
            // We got an unsupported command class, leave zwaveCommandClass as null
            logger.error(String.format("NODE %d: Unsupported zwave command class %s (0x%02x)", node.getNodeId(), commandClass.getLabel(), commandClassCode));
        } else {
            logger.debug(String.format("NODE %d: Adding command class %s (0x%02x)", node.getNodeId(), commandClass.getLabel(), commandClass.getKey()));
            node.addCommandClass(zwaveCommandClass);
        }
    }
    return zwaveCommandClass;
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) CommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass) ZWaveSecurityCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass)

Example 8 with ZWaveCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass in project openhab1-addons by openhab.

the class ApplicationCommandMessageClass method handleRequest.

@Override
public boolean handleRequest(ZWaveController zController, SerialMessage lastSentMessage, SerialMessage incomingMessage) {
    logger.trace("Handle Message Application Command Request");
    int nodeId = incomingMessage.getMessagePayloadByte(1);
    ZWaveNode node = zController.getNode(nodeId);
    if (node == null) {
        logger.warn("NODE {}: Not initialized yet, ignoring message.", nodeId);
        return false;
    }
    logger.debug("NODE {}: Application Command Request ({}:{})", nodeId, node.getNodeState().toString(), node.getNodeInitializationStage().toString());
    // If the node is DEAD, but we've just received a message from it, then it's not dead!
    if (node.isDead()) {
        node.setNodeState(ZWaveNodeState.ALIVE);
    }
    node.resetResendCount();
    node.incrementReceiveCount();
    int commandClassCode = incomingMessage.getMessagePayloadByte(3);
    ZWaveCommandClass zwaveCommandClass = resolveZWaveCommandClass(node, commandClassCode, zController);
    if (zwaveCommandClass == null) {
        // Error message was logged in resolveZWaveCommandClass
        return false;
    }
    final int commandByte = incomingMessage.getMessagePayloadByte(4);
    if (zwaveCommandClass instanceof ZWaveSecurityCommandClass && (ZWaveSecurityCommandClass.bytesAreEqual(ZWaveSecurityCommandClass.SECURITY_MESSAGE_ENCAP, commandByte) || ZWaveSecurityCommandClass.bytesAreEqual(ZWaveSecurityCommandClass.SECURITY_MESSAGE_ENCAP_NONCE_GET, commandByte))) {
        boolean isEncapNonceGet = ZWaveSecurityCommandClass.bytesAreEqual(ZWaveSecurityCommandClass.SECURITY_MESSAGE_ENCAP_NONCE_GET, commandByte);
        // Intercept security encapsulated messages here and decrypt them.
        ZWaveSecurityCommandClass zwaveSecurityCommandClass = (ZWaveSecurityCommandClass) zwaveCommandClass;
        logger.trace("NODE {}: Preparing to decrypt security encapsulated message, messagePayload={}", nodeId, SerialMessage.bb2hex(incomingMessage.getMessagePayload()));
        int toDecryptLength = incomingMessage.getMessageBuffer().length - 9;
        byte[] toDecrypt = new byte[toDecryptLength];
        System.arraycopy(incomingMessage.getMessageBuffer(), 8, toDecrypt, 0, toDecryptLength);
        byte[] decryptedBytes = zwaveSecurityCommandClass.decryptMessage(toDecrypt, 0);
        if (decryptedBytes == null) {
            logger.error("NODE {}: Failed to decrypt message out of {} .", nodeId, incomingMessage);
        } else {
            // call handleApplicationCommandRequest with the decrypted message. Note that we do NOT set
            // incomingMessage as that needs to be processed below with the original security encapsulated message
            final SerialMessage decryptedMessage = new SerialMessage(incomingMessage.getMessageClass(), incomingMessage.getMessageType(), incomingMessage.getExpectedReply(), incomingMessage.getPriority());
            decryptedMessage.setMessagePayload(decryptedBytes);
            // Get the new command class with the decrypted contents
            zwaveCommandClass = resolveZWaveCommandClass(node, decryptedBytes[1], zController);
            // Use a flag bc we need to handle isEncapNonceGet either way
            boolean failed = false;
            if (zwaveCommandClass == null) {
                // Error message was logged in resolveZWaveCommandClass
                failed = true;
            } else {
                // Note that we do not call node.doesMessageRequireSecurityEncapsulation since it was encapsulated.
                // Messages that are not required to be are allowed to be, just not the other way around
                logger.debug("NODE {}: After decrypt, found Command Class {}, passing to handleApplicationCommandRequest", nodeId, zwaveCommandClass.getCommandClass().getLabel());
                zwaveCommandClass.handleApplicationCommandRequest(decryptedMessage, 2, 0);
            }
            if (isEncapNonceGet) {
                // the device also needs another nonce; send it regardless of the success/failure of decryption
                zwaveSecurityCommandClass.sendNonceReport();
            }
            if (failed) {
                return false;
            }
        }
    } else {
        // Message does not require decryption
        if (node.doesMessageRequireSecurityEncapsulation(incomingMessage)) {
            // Should have been security encapsulation but wasn't!
            logger.error("NODE {}: Command Class {} {} was required to be security encapsulation but it wasn't!  Dropping message.", nodeId, zwaveCommandClass.getCommandClass().getKey(), zwaveCommandClass.getCommandClass().getLabel());
        // do not call zwaveCommandClass.handleApplicationCommandRequest();
        } else {
            logger.trace("NODE {}: Found Command Class {}, passing to handleApplicationCommandRequest", nodeId, zwaveCommandClass.getCommandClass().getLabel());
            zwaveCommandClass.handleApplicationCommandRequest(incomingMessage, 4, 0);
        }
    }
    if (node.getNodeId() == lastSentMessage.getMessageNode()) {
        checkTransactionComplete(lastSentMessage, incomingMessage);
    } else {
        logger.debug("NODE {}: Transaction not completed: node address inconsistent.  lastSent={}, incoming={}", lastSentMessage.getMessageNode(), lastSentMessage.getMessageNode(), incomingMessage.getMessageNode());
    }
    return true;
}
Also used : ZWaveSecurityCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Example 9 with ZWaveCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass in project openhab1-addons by openhab.

the class IdentifyNodeMessageClass method handleResponse.

@Override
public boolean handleResponse(ZWaveController zController, SerialMessage lastSentMessage, SerialMessage incomingMessage) {
    logger.trace("Handle Message Get Node ProtocolInfo Response");
    // Check that this request is consistent with the response
    if (lastSentMessage.getMessageClass() != SerialMessageClass.IdentifyNode) {
        logger.warn("Got IdentifyNodeMessage without request, ignoring. Last message was {}.", lastSentMessage.getMessageClass());
        return false;
    }
    int nodeId = lastSentMessage.getMessagePayloadByte(0);
    logger.debug("NODE {}: ProtocolInfo", nodeId);
    ZWaveNode node = zController.getNode(nodeId);
    boolean listening = (incomingMessage.getMessagePayloadByte(0) & 0x80) != 0 ? true : false;
    boolean routing = (incomingMessage.getMessagePayloadByte(0) & 0x40) != 0 ? true : false;
    int version = (incomingMessage.getMessagePayloadByte(0) & 0x07) + 1;
    boolean frequentlyListening = (incomingMessage.getMessagePayloadByte(1) & 0x60) != 0 ? true : false;
    boolean beaming = ((incomingMessage.getMessagePayloadByte(1) & 0x10) != 0);
    boolean security = ((incomingMessage.getMessagePayloadByte(1) & 0x01) != 0);
    int maxBaudRate = 9600;
    if ((incomingMessage.getMessagePayloadByte(0) & 0x38) == 0x10) {
        maxBaudRate = 40000;
    }
    logger.debug("NODE {}: Listening = {}", nodeId, listening);
    logger.debug("NODE {}: Routing = {}", nodeId, routing);
    logger.debug("NODE {}: Beaming = {}", nodeId, beaming);
    logger.debug("NODE {}: Version = {}", nodeId, version);
    logger.debug("NODE {}: FLIRS = {}", nodeId, frequentlyListening);
    logger.debug("NODE {}: Security = {}", nodeId, security);
    logger.debug("NODE {}: Max Baud = {}", nodeId, maxBaudRate);
    node.setListening(listening);
    node.setRouting(routing);
    node.setVersion(version);
    node.setFrequentlyListening(frequentlyListening);
    node.setSecurity(security);
    node.setBeaming(beaming);
    node.setMaxBaud(maxBaudRate);
    Basic basic = Basic.getBasic(incomingMessage.getMessagePayloadByte(3));
    if (basic == null) {
        logger.error(String.format("NODE %d: Basic device class 0x%02x not found", nodeId, incomingMessage.getMessagePayloadByte(3)));
        return false;
    }
    logger.debug("NODE {}: Basic = {}", nodeId, basic.getLabel());
    Generic generic = Generic.getGeneric(incomingMessage.getMessagePayloadByte(4));
    if (generic == null) {
        logger.error(String.format("NODE %d: Generic device class 0x%02x not found", nodeId, incomingMessage.getMessagePayloadByte(4)));
        return false;
    }
    logger.debug("NODE {}: Generic = {}", nodeId, generic.getLabel());
    Specific specific = Specific.getSpecific(generic, incomingMessage.getMessagePayloadByte(5));
    if (specific == null) {
        logger.error(String.format("NODE %d: Specific device class 0x%02x not found", nodeId, incomingMessage.getMessagePayloadByte(5)));
        return false;
    }
    logger.debug("NODE {}: Specific = {}", nodeId, specific.getLabel());
    ZWaveDeviceClass deviceClass = node.getDeviceClass();
    deviceClass.setBasicDeviceClass(basic);
    deviceClass.setGenericDeviceClass(generic);
    deviceClass.setSpecificDeviceClass(specific);
    // Add mandatory command classes as specified by its generic device class.
    for (CommandClass commandClass : generic.getMandatoryCommandClasses()) {
        ZWaveCommandClass zwaveCommandClass = ZWaveCommandClass.getInstance(commandClass.getKey(), node, zController);
        if (zwaveCommandClass != null) {
            zController.getNode(nodeId).addCommandClass(zwaveCommandClass);
        }
    }
    // Add mandatory command classes as specified by its specific device class.
    for (CommandClass commandClass : specific.getMandatoryCommandClasses()) {
        ZWaveCommandClass zwaveCommandClass = ZWaveCommandClass.getInstance(commandClass.getKey(), node, zController);
        if (zwaveCommandClass != null) {
            node.addCommandClass(zwaveCommandClass);
        }
    }
    checkTransactionComplete(lastSentMessage, incomingMessage);
    return true;
}
Also used : Basic(org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Basic) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) Generic(org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Generic) CommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) Specific(org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Specific) ZWaveDeviceClass(org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass)

Example 10 with ZWaveCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass in project openhab1-addons by openhab.

the class ZWaveNode method addCommandClass.

/**
     * Adds a command class to the list of supported command classes by this node.
     * Does nothing if command class is already added.
     *
     * @param commandClass the command class instance to add.
     */
public void addCommandClass(ZWaveCommandClass commandClass) {
    CommandClass key = commandClass.getCommandClass();
    if (!supportedCommandClasses.containsKey(key)) {
        logger.debug("NODE {}: Adding command class {} to the list of supported command classes.", nodeId, commandClass.getCommandClass().getLabel());
        supportedCommandClasses.put(key, commandClass);
        if (commandClass instanceof ZWaveEventListener) {
            this.controller.addEventListener((ZWaveEventListener) commandClass);
        }
    }
}
Also used : ZWaveMultiInstanceCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveMultiInstanceCommandClass) ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass) CommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass) ZWaveSecurityCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass) ZWaveVersionCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass) ZWaveNodeNamingCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNodeNamingCommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass)

Aggregations

ZWaveCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass)11 ZWaveNode (org.openhab.binding.zwave.internal.protocol.ZWaveNode)6 CommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass)5 ZWaveMultiInstanceCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveMultiInstanceCommandClass)4 ZWaveSecurityCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass)4 ZWaveWakeUpCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)4 ZWaveBindingConfig (org.openhab.binding.zwave.ZWaveBindingConfig)3 SerialMessage (org.openhab.binding.zwave.internal.protocol.SerialMessage)3 ZWaveAssociationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass)3 ZWaveVersionCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass)3 ZWaveCommandClassDynamicState (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClassDynamicState)2 ZWaveNodeNamingCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNodeNamingCommandClass)2 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 ZWaveDbAssociationGroup (org.openhab.binding.zwave.internal.config.ZWaveDbAssociationGroup)1 ZWaveDbCommandClass (org.openhab.binding.zwave.internal.config.ZWaveDbCommandClass)1 ZWaveDbConfigurationParameter (org.openhab.binding.zwave.internal.config.ZWaveDbConfigurationParameter)1 ZWaveProductDatabase (org.openhab.binding.zwave.internal.config.ZWaveProductDatabase)1 ZWaveDeviceClass (org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass)1 Basic (org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Basic)1