Search in sources :

Example 61 with SerialMessage

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

the class IdentifyNodeMessageClass method doRequest.

public SerialMessage doRequest(int nodeId) {
    SerialMessage newMessage = new SerialMessage(SerialMessageClass.IdentifyNode, SerialMessageType.Request, SerialMessageClass.IdentifyNode, SerialMessagePriority.High);
    byte[] newPayload = { (byte) nodeId };
    newMessage.setMessagePayload(newPayload);
    return newMessage;
}
Also used : SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Example 62 with SerialMessage

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

the class IsFailedNodeMessageClass method doRequest.

public SerialMessage doRequest(int nodeId) {
    logger.debug("NODE {}: Requesting IsFailedNode status from controller.", nodeId);
    SerialMessage newMessage = new SerialMessage(SerialMessageClass.IsFailedNodeID, SerialMessageType.Request, SerialMessageClass.IsFailedNodeID, SerialMessagePriority.High);
    byte[] newPayload = { (byte) nodeId };
    newMessage.setMessagePayload(newPayload);
    return newMessage;
}
Also used : SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Example 63 with SerialMessage

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

the class ZWaveSecureNonceTracker method buildNonceGetIfNeeded.

synchronized SerialMessage buildNonceGetIfNeeded() {
    if (hasNonceBeenRequested()) {
        logger.debug("NODE {}: already waiting for nonce", node.getNodeId());
        return null;
    }
    logger.debug("NODE {}: requesting nonce", node.getNodeId());
    SerialMessage message = new SerialMessage(node.getNodeId(), SerialMessageClass.SendData, SerialMessageType.Request, SerialMessageClass.ApplicationCommandHandler, ZWaveSecurityCommandClass.SECURITY_MESSAGE_PRIORITY);
    byte[] payload = { (byte) node.getNodeId(), 2, (byte) ZWaveSecurityCommandClass.getSecurityCommandClass().getKey(), ZWaveSecurityCommandClass.SECURITY_NONCE_GET };
    if (ZWaveSecurityCommandClass.OVERRIDE_DEFAULT_TRANSMIT_OPTIONS) {
        logger.trace("NODE {}: Using custom transmit options", node.getNodeId());
        message.setTransmitOptions(ZWaveController.TRANSMIT_OPTION_ACK | ZWaveController.TRANSMIT_OPTION_AUTO_ROUTE);
    }
    // We only try once as strange things happen with NONCE_GET requests TODO: DB add more detail as to what we are
    // trying to fix here
    message.setMessagePayload(payload);
    if (requestNonceTimer != null) {
        logger.warn("NODE {}: requestNonceTimer != null but generating a new request", node.getNodeId());
    }
    requestNonceTimer = new NonceTimer(NonceTimerType.REQUESTED, node);
    requestNonceMessage = message;
    return message;
}
Also used : SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Example 64 with SerialMessage

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

the class ZWaveSecurityCommandClass method sendNextMessageUsingDeviceNonce.

/**
     * Gets the next message from {@link #payloadEncapsulationQueue}, encapsulates (encrypts and MACs) it, then
     * transmits
     * Invoked by {@link ZWaveSecurityEncapsulationThread}. This method must only be called by
     * {@link ZWaveSecurityEncapsulationThread}
     */
protected void sendNextMessageUsingDeviceNonce() {
    checkInit();
    if (!checkRealNetworkKeyLoaded()) {
        return;
    }
    if (encryptKey == null) {
        // when loaded from xml, encrypt key will be null so we load it here
        setupNetworkKey(false);
    }
    if (payloadEncapsulationQueue.isEmpty()) {
        logger.warn("NODE {}: payloadQueue was empty, returning", this.getNode().getNodeId());
        return;
    }
    Nonce deviceNonce = nonceGeneration.getUseableDeviceNonce();
    if (deviceNonce == null) {
        SerialMessage nonceGetMessage = nonceGeneration.buildNonceGetIfNeeded();
        if (nonceGetMessage == null) {
        // Nothing to do, we are already waiting for a nonce from the device
        } else {
            transmitMessage(nonceGetMessage);
        }
        return;
    }
    // Fetch the next payload from the queue and encapsulate it
    ZWaveSecurityPayloadFrame securityPayload = payloadEncapsulationQueue.poll();
    if (securityPayload == null) {
        logger.warn("NODE {}: payloadQueue was empty, returning", this.getNode().getNodeId());
        return;
    }
    // Encapsulate the message fragment
    traceHex("SecurityPayloadBytes", securityPayload.getMessageBytes());
    // Note that we set the expected reply to that of the original message, as it can vary
    SecurityEncapsulatedSerialMessage message = new SecurityEncapsulatedSerialMessage(SerialMessageClass.SendData, SerialMessageType.Request, securityPayload.getOriginalMessage());
    message.setDeviceNonceId(deviceNonce.getNonceBytes()[0]);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write((byte) this.getNode().getNodeId());
    baos.write(securityPayload.getLength() + 20);
    baos.write(this.getCommandClass().getKey());
    byte commandByte = SECURITY_MESSAGE_ENCAP;
    if (USE_SECURITY_MESSAGE_ENCAP_NONCE_GET && !disableEncapNonceGet) {
        boolean useNonceGetMessage = false;
        if (payloadEncapsulationQueue.size() > 0) {
            useNonceGetMessage = true;
            logger.debug("NODE {}: using SECURITY_MESSAGE_ENCAP_NONCE_GET with queue size of {}", this.getNode().getNodeId(), payloadEncapsulationQueue.size());
        } else if (false) {
            // Check for messages that we know will have a follow-up request that is secure TODO: DB
            // change flag to AGGRESSIVE, etc? or just remove..
            useNonceGetMessage = bytesAreEqual(securityPayload.getMessageBytes()[0], ZWaveCommandClass.CommandClass.DOOR_LOCK.getKey()) && bytesAreEqual(securityPayload.getMessageBytes()[1], ZWaveDoorLockCommandClass.DOORLOCK_SET);
            if (useNonceGetMessage) {
                logger.debug("NODE {}: using SECURITY_MESSAGE_ENCAP_NONCE_GET since there will be a followup command", this.getNode().getNodeId());
            }
        }
        if (useNonceGetMessage) {
            commandByte = SECURITY_MESSAGE_ENCAP_NONCE_GET;
            nonceGeneration.sendingEncapNonceGet(message);
        }
    }
    logger.trace("NODE {}: Used nonce to form {} ({}).", this.getNode().getNodeId(), commandToString(commandByte), securityPayload.getLogMessage());
    baos.write(commandByte);
    // create the iv
    byte[] initializationVector = new byte[16];
    // Generate a new nonce and fill the first half of the IV buffer with it
    byte[] nonceBytes = nonceGeneration.generateNonceForEncapsulationMessage();
    System.arraycopy(nonceBytes, 0, initializationVector, 0, HALF_OF_IV);
    // the 2nd half of the IV is the nonce provided by the device
    System.arraycopy(deviceNonce.getNonceBytes(), 0, initializationVector, HALF_OF_IV, HALF_OF_IV);
    try {
        // Append the first 8 bytes of the IV (our nonce) to the message
        baos.write(initializationVector, 0, HALF_OF_IV);
        int totalParts = securityPayload.getTotalParts();
        if (totalParts < 1 || totalParts > 2) {
            logger.error("NODE {}: securityPayload had invalid number of parts: {}   Send aborted.", this.getNode().getNodeId(), totalParts);
            return;
        }
        // at most, the payload will be securityPayload length + 1 byte for the sequence byte
        byte[] plaintextMessageBytes = new byte[1 + securityPayload.getLength()];
        plaintextMessageBytes[0] = securityPayload.getSequenceByte();
        System.arraycopy(securityPayload.getMessageBytes(), 0, plaintextMessageBytes, 1, securityPayload.getLength());
        // Append the message payload after encrypting it with AES-OFB
        traceHex("Input frame for encryption:", plaintextMessageBytes);
        traceHex("IV:", initializationVector);
        // This will use hardware AES acceleration when possible (default in JDK 8)
        Cipher encryptCipher = Cipher.getInstance("AES/OFB/NoPadding");
        encryptCipher.init(Cipher.ENCRYPT_MODE, encryptKey, new IvParameterSpec(initializationVector));
        byte[] ciphertextBytes = encryptCipher.doFinal(plaintextMessageBytes);
        traceHex("Encrypted Output", ciphertextBytes);
        baos.write(ciphertextBytes);
        // Append the nonce identifier which is the first byte of the device nonce
        baos.write(deviceNonce.getNonceBytes()[0]);
        int commandClassByteOffset = 2;
        // Start at command class byte
        int toMacLength = baos.toByteArray().length - commandClassByteOffset;
        byte[] toMac = new byte[toMacLength];
        System.arraycopy(baos.toByteArray(), commandClassByteOffset, toMac, 0, toMacLength);
        // Generate the MAC
        byte sendingNode = (byte) this.getController().getOwnNodeId();
        byte[] mac = generateMAC(commandByte, ciphertextBytes, sendingNode, (byte) getNode().getNodeId(), initializationVector);
        traceHex("Auth mac", mac);
        baos.write(mac);
        byte[] payload = baos.toByteArray();
        debugHex(String.format("Outgoing encrypted message (device nonce=%02X): ", initializationVector[HALF_OF_IV]), payload);
        message.setMessagePayload(payload);
        message.setSecurityPayload(securityPayload);
        lastEncapsulatedRequstMessage = message;
        transmitMessage(message);
    } catch (GeneralSecurityException e) {
        logger.error("NODE {}: Error in sendNextMessageWithNonce, message not sent", e);
    } catch (IOException e) {
        logger.error("NODE {}: Error in sendNextMessageWithNonce, message not sent", e);
    }
}
Also used : SecurityEncapsulatedSerialMessage(org.openhab.binding.zwave.internal.protocol.SecurityEncapsulatedSerialMessage) GeneralSecurityException(java.security.GeneralSecurityException) SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage) SecurityEncapsulatedSerialMessage(org.openhab.binding.zwave.internal.protocol.SecurityEncapsulatedSerialMessage) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ZWaveEndpoint(org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint) Nonce(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecureNonceTracker.Nonce) IvParameterSpec(javax.crypto.spec.IvParameterSpec) Cipher(javax.crypto.Cipher)

Example 65 with SerialMessage

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

the class ZWaveSwitchAllCommandClass method getValueMessage.

public SerialMessage getValueMessage() {
    if (!this.isGetSupported) {
        logger.debug("NODE {}: Node doesn't support get requests", this.getNode().getNodeId());
        return null;
    }
    logger.debug("NODE {}: Creating new message for command SWITCH_ALL_GET", this.getNode().getNodeId());
    SerialMessage result = new SerialMessage(this.getNode().getNodeId(), SerialMessage.SerialMessageClass.SendData, SerialMessage.SerialMessageType.Request, SerialMessage.SerialMessageClass.ApplicationCommandHandler, SerialMessage.SerialMessagePriority.Get);
    byte[] newPayload = { (byte) this.getNode().getNodeId(), 2, (byte) this.getCommandClass().getKey(), (byte) SWITCH_ALL_GET };
    result.setMessagePayload(newPayload);
    return result;
}
Also used : SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Aggregations

SerialMessage (org.openhab.binding.zwave.internal.protocol.SerialMessage)125 State (org.openhab.core.types.State)12 ZWaveEndpoint (org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint)8 ByteArrayOutputStream (java.io.ByteArrayOutputStream)7 HashMap (java.util.HashMap)5 ZWaveNode (org.openhab.binding.zwave.internal.protocol.ZWaveNode)5 ZWaveWakeUpCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 Map (java.util.Map)3 ConfigurationParameter (org.openhab.binding.zwave.internal.protocol.ConfigurationParameter)3 SecurityEncapsulatedSerialMessage (org.openhab.binding.zwave.internal.protocol.SecurityEncapsulatedSerialMessage)3 ZWaveCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 ZWaveDbConfigurationParameter (org.openhab.binding.zwave.internal.config.ZWaveDbConfigurationParameter)2 ZWaveProductDatabase (org.openhab.binding.zwave.internal.config.ZWaveProductDatabase)2 MultiLevelPercentCommandConverter (org.openhab.binding.zwave.internal.converter.command.MultiLevelPercentCommandConverter)2 ZWaveAssociationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass)2 ZWaveConfigurationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveConfigurationCommandClass)2 ZWaveNetworkEvent (org.openhab.binding.zwave.internal.protocol.event.ZWaveNetworkEvent)2