Search in sources :

Example 1 with ZWaveCommandClass

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

the class ZWaveController method pollNode.

/**
     * Polls a node for any dynamic information
     *
     * @param node
     */
public void pollNode(ZWaveNode node) {
    for (ZWaveCommandClass zwaveCommandClass : node.getCommandClasses()) {
        logger.trace("NODE {}: Inspecting command class {}", node.getNodeId(), zwaveCommandClass.getCommandClass().getLabel());
        if (zwaveCommandClass instanceof ZWaveCommandClassDynamicState) {
            logger.debug("NODE {}: Found dynamic state command class {}", node.getNodeId(), zwaveCommandClass.getCommandClass().getLabel());
            ZWaveCommandClassDynamicState zdds = (ZWaveCommandClassDynamicState) zwaveCommandClass;
            int instances = zwaveCommandClass.getInstances();
            if (instances == 1) {
                Collection<SerialMessage> dynamicQueries = zdds.getDynamicValues(true);
                for (SerialMessage serialMessage : dynamicQueries) {
                    sendData(serialMessage);
                }
            } else {
                for (int i = 1; i <= instances; i++) {
                    Collection<SerialMessage> dynamicQueries = zdds.getDynamicValues(true);
                    for (SerialMessage serialMessage : dynamicQueries) {
                        sendData(node.encapsulate(serialMessage, zwaveCommandClass, i));
                    }
                }
            }
        } else if (zwaveCommandClass instanceof ZWaveMultiInstanceCommandClass) {
            ZWaveMultiInstanceCommandClass multiInstanceCommandClass = (ZWaveMultiInstanceCommandClass) zwaveCommandClass;
            for (ZWaveEndpoint endpoint : multiInstanceCommandClass.getEndpoints()) {
                for (ZWaveCommandClass endpointCommandClass : endpoint.getCommandClasses()) {
                    logger.trace("NODE {}: Inspecting command class {} for endpoint {}", node.getNodeId(), endpointCommandClass.getCommandClass().getLabel(), endpoint.getEndpointId());
                    if (endpointCommandClass instanceof ZWaveCommandClassDynamicState) {
                        logger.debug("NODE {}: Found dynamic state command class {}", node.getNodeId(), endpointCommandClass.getCommandClass().getLabel());
                        ZWaveCommandClassDynamicState zdds2 = (ZWaveCommandClassDynamicState) endpointCommandClass;
                        Collection<SerialMessage> dynamicQueries = zdds2.getDynamicValues(true);
                        for (SerialMessage serialMessage : dynamicQueries) {
                            sendData(node.encapsulate(serialMessage, endpointCommandClass, endpoint.getEndpointId()));
                        }
                    }
                }
            }
        }
    }
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveCommandClassDynamicState(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClassDynamicState) ZWaveMultiInstanceCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveMultiInstanceCommandClass) Collection(java.util.Collection)

Example 2 with ZWaveCommandClass

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

the class ZWaveNode method setSecuredClasses.

/**
     * Invoked by {@link ZWaveSecurityCommandClass} when a
     * {@link ZWaveSecurityCommandClass#SECURITY_SUPPORTED_REPORT} is received.
     *
     * @param data the class id for each class which must be encrypted in transmission
     */
public void setSecuredClasses(byte[] data) {
    logger.info("NODE {}:  Setting secured command classes for node with {}", this.getNodeId(), SerialMessage.bb2hex(data));
    boolean afterMark = false;
    // reset the existing list
    securedCommandClasses.clear();
    for (final byte aByte : data) {
        // TODO: DB support extended commandClass format by checking for 0xF1 - 0xFF
        if (ZWaveSecurityCommandClass.bytesAreEqual(aByte, ZWaveSecurityCommandClass.COMMAND_CLASS_MARK)) {
            /**
                 * Marks the end of the list of supported command classes. The remaining classes are those
                 * that can be controlled by the device. These classes are created without values.
                 * Messages received cause notification events instead.
                 */
            afterMark = true;
            continue;
        }
        // Check if this is a commandClass that is already registered with the node
        final CommandClass commandClass = CommandClass.getCommandClass((aByte & 0xFF));
        if (commandClass == null) {
            // Not supported by OpenHab
            logger.error("NODE {}:  setSecuredClasses requested secure " + "class NOT supported by OpenHab: {}   afterMark={}", this.getNodeId(), commandClass, afterMark);
        } else {
            // can't be set that way since it's the one doing the encryption work So ignore that.
            if (commandClass == CommandClass.SECURITY) {
                continue;
            } else if (afterMark) {
                // Nothing to do, we don't track devices that control other devices
                logger.info("NODE {}:  is after mark for commandClass {}", this.getNodeId(), commandClass);
                break;
            } else {
                if (!this.supportsCommandClass(commandClass)) {
                    logger.info("NODE {}:  Adding secured command class to supported that wasn't in original list {}", this.getNodeId(), commandClass.getLabel());
                    final ZWaveCommandClass classInstance = ZWaveCommandClass.getInstance((aByte & 0xFF), this, controller);
                    if (classInstance != null) {
                        addCommandClass(classInstance);
                    }
                }
                securedCommandClasses.add(commandClass);
                logger.info("NODE {}:  (Secured) {}", this.getNodeId(), commandClass.getLabel());
            }
        }
    }
    if (logger.isInfoEnabled()) {
        // show which classes are still insecure after the update
        final StringBuilder buf = new StringBuilder("NODE " + this.getNodeId() + ": After update, INSECURE command classes are: ");
        for (final ZWaveCommandClass zwCommandClass : this.getCommandClasses()) {
            if (!securedCommandClasses.contains(zwCommandClass.getCommandClass())) {
                buf.append(zwCommandClass.getCommandClass() + ", ");
            }
        }
        logger.info(buf.toString().substring(0, buf.toString().length() - 1));
    }
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) 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)

Example 3 with ZWaveCommandClass

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

the class ZWaveConverterHandler method executeRefresh.

/**
     * Execute refresh method. This method is called every time a binding item
     * is refreshed and the corresponding node should be sent a message.
     *
     * @param provider
     *            the {@link ZWaveBindingProvider} that provides the item
     * @param itemName
     *            the name of the item to poll.
     * @param forceRefresh
     *            indicates that a polling refresh should be forced.
     */
@SuppressWarnings("unchecked")
public void executeRefresh(ZWaveBindingProvider provider, String itemName, boolean forceRefresh) {
    ZWaveBindingConfig bindingConfiguration = provider.getZwaveBindingConfig(itemName);
    ZWaveCommandClass commandClass;
    String commandClassName = bindingConfiguration.getArguments().get("command");
    // this binding is configured not to poll.
    if (!forceRefresh && bindingConfiguration.getRefreshInterval() != null && 0 == bindingConfiguration.getRefreshInterval()) {
        return;
    }
    ZWaveNode node = this.controller.getNode(bindingConfiguration.getNodeId());
    // ignore nodes that are not initialized.
    if (node == null) {
        return;
    }
    if (commandClassName != null) {
        // this is a report item, handle it with the report info converter.
        if (commandClassName.equalsIgnoreCase("info")) {
            infoConverter.executeRefresh(provider.getItem(itemName), node, bindingConfiguration.getEndpoint(), bindingConfiguration.getArguments());
            return;
        }
        // ignore nodes that are not initialized or dead.
        if (node.getNodeState() != ZWaveNodeState.ALIVE || node.isInitializationComplete() == false) {
            return;
        }
        commandClass = node.resolveCommandClass(CommandClass.getCommandClass(commandClassName), bindingConfiguration.getEndpoint());
        if (commandClass == null) {
            logger.warn("No command class found for item = {}, command class name = {}, ignoring execute refresh.", itemName, commandClassName);
            return;
        }
    } else {
        commandClass = resolveConverter(provider.getItem(itemName), node, bindingConfiguration.getEndpoint());
    }
    if (commandClass == null) {
        logger.warn("No converter found for item = {}, ignoring execute refresh.", itemName);
        return;
    }
    ZWaveCommandClassConverter<ZWaveCommandClass> converter = (ZWaveCommandClassConverter<ZWaveCommandClass>) getConverter(commandClass.getCommandClass());
    if (converter == null) {
        logger.warn("No converter found for item = {}, ignoring execute refresh.", itemName);
        return;
    }
    if (bindingConfiguration.getRefreshInterval() == null) {
        bindingConfiguration.setRefreshInterval(converter.getRefreshInterval());
        // this binding is configured not to poll.
        if (!forceRefresh && 0 == bindingConfiguration.getRefreshInterval()) {
            return;
        }
    }
    // not enough time has passed to refresh the item.
    if (!forceRefresh && bindingConfiguration.getLastRefreshed() != null && (bindingConfiguration.getLastRefreshed().getTime() + (bindingConfiguration.getRefreshInterval() * 1000) > Calendar.getInstance().getTimeInMillis())) {
        return;
    }
    bindingConfiguration.setLastRefreshed(Calendar.getInstance().getTime());
    SerialMessage serialMessage = converter.executeRefresh(node, commandClass, bindingConfiguration.getEndpoint(), bindingConfiguration.getArguments());
    if (serialMessage == null) {
        logger.warn("NODE {}: Generating message failed for command class = {}", node.getNodeId(), commandClass.getCommandClass().getLabel());
        return;
    }
    // This is a poll - treat it as a low priority!
    serialMessage.setPriority(SerialMessagePriority.Poll);
    // Queue the message
    this.controller.sendData(serialMessage);
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) ZWaveBindingConfig(org.openhab.binding.zwave.ZWaveBindingConfig) SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Example 4 with ZWaveCommandClass

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

the class ZWaveConverterHandler method receiveCommand.

/**
     * Receives a command from openHAB and translates it to an operation on the
     * Z-Wave network.
     *
     * @param provider
     *            the {@link ZWaveBindingProvider} that provides the item
     * @param itemName
     *            the name of the item that will receive the event.
     * @param command
     *            the received {@link Command}
     */
@SuppressWarnings("unchecked")
public void receiveCommand(ZWaveBindingProvider provider, String itemName, Command command) {
    ZWaveBindingConfig bindingConfiguration = provider.getZwaveBindingConfig(itemName);
    ZWaveNode node = this.controller.getNode(bindingConfiguration.getNodeId());
    if (node == null) {
        logger.error("Item {} has non existant node {}", itemName, bindingConfiguration.getNodeId());
        return;
    }
    ZWaveCommandClass commandClass;
    String commandClassName = bindingConfiguration.getArguments().get("command");
    if (commandClassName != null) {
        if (node.getNodeId() == this.controller.getOwnNodeId() && commandClassName.equalsIgnoreCase("switch_all")) {
            commandClass = ZWaveCommandClass.getInstance(0x27, node, this.controller);
        } else {
            commandClass = node.resolveCommandClass(CommandClass.getCommandClass(commandClassName), bindingConfiguration.getEndpoint());
            if (commandClass == null) {
                logger.warn("NODE {}: No command class found for item = {}. Class = {}({}), endpoint = {}. Ignoring command.", node.getNodeId(), itemName, commandClassName, CommandClass.getCommandClass(commandClassName).toString(), bindingConfiguration.getEndpoint());
                return;
            }
        }
    } else {
        commandClass = resolveConverter(provider.getItem(itemName), node, bindingConfiguration.getEndpoint());
    }
    if (commandClass == null) {
        logger.warn("NODE {}: No converter found for item = {}, ignoring command.", node.getNodeId(), itemName);
        return;
    }
    ZWaveCommandClassConverter<ZWaveCommandClass> converter = (ZWaveCommandClassConverter<ZWaveCommandClass>) getConverter(commandClass.getCommandClass());
    if (converter == null) {
        logger.warn("NODE {}: No converter found for item = {}, ignoring command.", node.getNodeId(), itemName);
        return;
    }
    converter.receiveCommand(provider.getItem(itemName), command, node, commandClass, bindingConfiguration.getEndpoint(), bindingConfiguration.getArguments());
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) ZWaveBindingConfig(org.openhab.binding.zwave.ZWaveBindingConfig)

Example 5 with ZWaveCommandClass

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

the class ZWaveNodeStageAdvancer method advanceNodeStage.

/**
     * Advances the initialization stage for this node. This method is called
     * after a response is received. We don't necessarily know if the response
     * is to the frame we requested though, so to be sure the initialisation
     * gets all the information it needs, the command class itself gets queried.
     * This method also handles the sending of frames. Since the initialisation
     * phase is a busy one we try and only have one outstanding request. Again
     * though, we can't be sure that a response is aligned with the node
     * advancer request so it is possible that more than one packet can be
     * released at once, but it will constrain things.
     */
public void advanceNodeStage(SerialMessageClass eventClass) {
    // handler when we're done, but just to be sure...
    if (currentStage == ZWaveNodeInitStage.DONE) {
        return;
    }
    logger.debug("NODE {}: Node advancer - {}: queue length({}), free to send({})", node.getNodeId(), currentStage.toString(), msgQueue.size(), freeToSend);
    // the stage, then reset.
    if (wakeupCount >= 3) {
        msgQueue.clear();
        wakeupCount = 0;
    }
    // Start the retry timer
    startIdleTimer();
    // again.
    if (eventClass == null) {
        freeToSend = true;
    }
    // If the queue is not empty, then we can't advance any further.
    if (sendMessage() == true) {
        // We're still sending messages, so we're not ready to proceed.
        return;
    }
    // The stageAdvanced flag is used to tell command classes that this
    // is the first iteration.
    // During the first iteration all messages are queued. After this,
    // only outstanding requests are returned.
    // This continues until there are no requests required.
    stageAdvanced = false;
    ZWaveProductDatabase database;
    // Then we will wait for the response before continuing
    do {
        // something that is broken, or not responding to a particular request
        if (stageAdvanced == true) {
            retryCount = 0;
        } else {
            retryCount++;
            if (retryCount > MAX_RETRIES) {
                retryCount = 0;
                logger.error("NODE {}: Node advancer: Retries exceeded at {}", node.getNodeId(), currentStage.toString());
                if (currentStage.isStageMandatory() == false) {
                    // If the current stage is not mandatory, then we skip forward to the next
                    // stage.
                    logger.debug("NODE {}: Retry timout: Advancing", node.getNodeId());
                    setCurrentStage(currentStage.getNextStage());
                } else {
                    // For static stages, we MUST complete all steps otherwise we end
                    // up with incomplete information about the device.
                    // During the static stages, we use the back off timer to pace things
                    // and retry until the stage is complete
                    logger.debug("NODE {}: Retry timout: Can't advance", node.getNodeId());
                    break;
                }
            }
        }
        logger.debug("NODE {}: Node advancer: loop - {} try {}: stageAdvanced({})", node.getNodeId(), currentStage.toString(), retryCount, stageAdvanced);
        switch(currentStage) {
            case EMPTYNODE:
                logger.debug("NODE {}: Node advancer: Initialisation starting", node.getNodeId());
                break;
            case PROTOINFO:
                // If the incoming frame is the IdentifyNode, then we continue
                if (eventClass == SerialMessageClass.IdentifyNode) {
                    break;
                }
                logger.debug("NODE {}: Node advancer: PROTOINFO - send IdentifyNode", node.getNodeId());
                addToQueue(new IdentifyNodeMessageClass().doRequest(node.getNodeId()));
                break;
            case NEIGHBORS:
                // If the incoming frame is the IdentifyNode, then we continue
                if (eventClass == SerialMessageClass.GetRoutingInfo) {
                    break;
                }
                logger.debug("NODE {}: Node advancer: NEIGHBORS - send RoutingInfo", node.getNodeId());
                addToQueue(new GetRoutingInfoMessageClass().doRequest(node.getNodeId()));
                break;
            case FAILED_CHECK:
                // If this is a controller, we're done
                if (node.getDeviceClass().getSpecificDeviceClass() == Specific.PC_CONTROLLER) {
                    logger.debug("NODE {}: Node advancer: FAILED_CHECK - Controller - terminating initialisation", node.getNodeId());
                    currentStage = ZWaveNodeInitStage.DONE;
                    break;
                }
                // If the incoming frame is the IdentifyNode, then we continue
                if (eventClass == SerialMessageClass.IsFailedNodeID) {
                    break;
                }
                addToQueue(new IsFailedNodeMessageClass().doRequest(node.getNodeId()));
                break;
            case WAIT:
                logger.debug("NODE {}: Node advancer: WAIT - Listening={}, FrequentlyListening={}", node.getNodeId(), node.isListening(), node.isFrequentlyListening());
                // If the node is listening, or frequently listening, then we progress.
                if (node.isListening() == true || node.isFrequentlyListening() == true) {
                    logger.debug("NODE {}: Node advancer: WAIT - Advancing", node.getNodeId());
                    break;
                }
                // If the device supports the wakeup class, then see if we're awake
                ZWaveWakeUpCommandClass wakeUpCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
                if (wakeUpCommandClass != null && wakeUpCommandClass.isAwake() == true) {
                    logger.debug("NODE {}: Node advancer: WAIT - Node is awake", node.getNodeId());
                    break;
                }
                // If it's not listening, and not awake,
                // we'll wait a while before progressing with initialisation.
                logger.debug("NODE {}: Node advancer: WAIT - Still waiting!", node.getNodeId());
                return;
            case PING:
                // who cares!
                if (eventClass == SerialMessageClass.SendData) {
                    break;
                }
                ZWaveNoOperationCommandClass noOpCommandClass = (ZWaveNoOperationCommandClass) node.getCommandClass(CommandClass.NO_OPERATION);
                if (noOpCommandClass == null) {
                    break;
                }
                logger.debug("NODE {}: Node advancer: PING - send NoOperation", node.getNodeId());
                SerialMessage msg = noOpCommandClass.getNoOperationMessage();
                if (msg != null) {
                    // We only send out a single PING - no retries at controller
                    // level! This is to try and reduce network congestion during
                    // initialisation.
                    // For battery devices, the PING will time-out. This takes 5
                    // seconds and if there are retries, it will be 15 seconds!
                    // This will block the network for a considerable time if there
                    // are a lot of battery devices (eg. 2 minutes for 8 battery devices!).
                    msg.attempts = 1;
                    addToQueue(msg);
                }
                break;
            case SECURITY_REPORT:
                // response to come back
                if (this.node.supportsCommandClass(CommandClass.SECURITY)) {
                    ZWaveSecurityCommandClassWithInitialization securityCommandClass = (ZWaveSecurityCommandClassWithInitialization) this.node.getCommandClass(CommandClass.SECURITY);
                    // For a node restored from a config file, this may or may not return a message
                    Collection<SerialMessage> messageList = securityCommandClass.initialize(stageAdvanced);
                    // Speed up retry timer as we use this to fetch outgoing messages instead of just retries
                    retryTimer = 400;
                    if (messageList == null) {
                        // This means we're waiting for a reply or we are done
                        if (isRestoredFromConfigfile()) {
                            // Since we were restored from a config file, redo from the dynamic node stage.
                            logger.debug("NODE {}: Node advancer: Restored from file - skipping static initialisation", node.getNodeId());
                            currentStage = ZWaveNodeInitStage.SESSION_START;
                            securityCommandClass.startSecurityEncapsulationThread();
                            break;
                        } else {
                            // This node was just included, check for success or failure
                            if (securityCommandClass.wasSecureInclusionSuccessful()) {
                                logger.debug("NODE {}: Secure inclusion complete, continuing with inclusion", node.getNodeId());
                                securityCommandClass.startSecurityEncapsulationThread();
                                // TODO: DB remove
                                nodeSerializer.SerializeNode(node);
                                // retryTimer will be reset to a normal value below
                                break;
                            } else {
                                // securityCommandClass output a message about the failure
                                logger.debug("NODE {}: Since secure inclusion failed, the node must be manually excluded via habmin", node.getNodeId());
                                // Stop the retry timer
                                resetIdleTimer();
                                // Remove the security command class since without a key, it's unusable
                                node.removeCommandClass(CommandClass.SECURITY);
                                // We remove the event listener to reduce loading now that we're done
                                controller.removeEventListener(this);
                                return;
                            }
                        }
                    } else if (messageList.isEmpty()) {
                        // Let ZWaveInputThread go back and wait for an incoming message
                        return;
                    } else {
                        // Add one or more messages to the queue
                        addToQueue(messageList);
                        SerialMessage nextSecurityMessageToSend = messageList.iterator().next();
                        if (!nextSecurityMessageToSend.equals(securityLastSentMessage)) {
                            // Reset our retry count since this is a different message
                            retryCount = 0;
                            securityLastSentMessage = nextSecurityMessageToSend;
                        }
                    }
                } else {
                    // !node.supportsCommandClass(CommandClass.SECURITY)
                    if (isRestoredFromConfigfile()) {
                        // Since we were restored from a config file, redo from the dynamic node stage.
                        logger.debug("NODE {}: Node advancer: Restored from file - skipping static initialisation", node.getNodeId());
                        currentStage = ZWaveNodeInitStage.SESSION_START;
                    }
                    logger.debug("NODE {}: does not support SECURITY_REPORT, proceeding to next stage.", this.node.getNodeId());
                }
                break;
            case DETAILS:
                // If restored from a config file, redo from the dynamic node stage.
                if (isRestoredFromConfigfile()) {
                    logger.debug("NODE {}: Node advancer: Restored from file - skipping static initialisation", node.getNodeId());
                    currentStage = ZWaveNodeInitStage.SESSION_START;
                    break;
                }
                // If the incoming frame is the IdentifyNode, then we continue
                if (node.getApplicationUpdateReceived() == true) {
                    logger.debug("NODE {}: Node advancer: received RequestNodeInfo", node.getNodeId());
                    break;
                }
                logger.debug("NODE {}: Node advancer: DETAILS - send RequestNodeInfo", node.getNodeId());
                addToQueue(new RequestNodeInfoMessageClass().doRequest(node.getNodeId()));
                break;
            case MANUFACTURER:
                // If we already know the device information, then continue
                if (node.getManufacturer() != Integer.MAX_VALUE && node.getDeviceType() != Integer.MAX_VALUE && node.getDeviceId() != Integer.MAX_VALUE) {
                    break;
                }
                // try and get the manufacturerSpecific command class.
                ZWaveManufacturerSpecificCommandClass manufacturerSpecific = (ZWaveManufacturerSpecificCommandClass) node.getCommandClass(CommandClass.MANUFACTURER_SPECIFIC);
                if (manufacturerSpecific != null) {
                    // If this node implements the Manufacturer Specific command
                    // class, we use it to get manufacturer info.
                    logger.debug("NODE {}: Node advancer: MANUFACTURER - send ManufacturerSpecific", node.getNodeId());
                    addToQueue(manufacturerSpecific.getManufacturerSpecificMessage());
                }
                break;
            case VERSION:
                // Try and get the version command class.
                ZWaveVersionCommandClass version = (ZWaveVersionCommandClass) node.getCommandClass(CommandClass.VERSION);
                // using the Version command class
                for (ZWaveCommandClass zwaveVersionClass : node.getCommandClasses()) {
                    logger.debug("NODE {}: Node advancer: VERSION - checking {}, version is {}", node.getNodeId(), zwaveVersionClass.getCommandClass().getLabel(), zwaveVersionClass.getVersion());
                    // See if we want to force the version of this command class
                    // We now should know all the command classes, so run through the database and set any options
                    database = new ZWaveProductDatabase();
                    if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == true) {
                        List<ZWaveDbCommandClass> classList = database.getProductCommandClasses();
                        if (classList != null) {
                            // Loop through the command classes in the data and update the records...
                            for (ZWaveDbCommandClass dbClass : classList) {
                                if (dbClass.version != null && zwaveVersionClass.getCommandClass().getKey() == dbClass.Id) {
                                    logger.debug("NODE {}: Node advancer: VERSION - Set {} to Version {}", node.getNodeId(), zwaveVersionClass.getCommandClass().getLabel(), dbClass.version);
                                    zwaveVersionClass.setVersion(dbClass.version);
                                }
                            }
                        }
                    }
                    if (version != null && zwaveVersionClass.getMaxVersion() > 1 && zwaveVersionClass.getVersion() == 0) {
                        logger.debug("NODE {}: Node advancer: VERSION - queued   {}", node.getNodeId(), zwaveVersionClass.getCommandClass().getLabel());
                        addToQueue(version.checkVersion(zwaveVersionClass));
                    } else if (zwaveVersionClass.getVersion() == 0) {
                        logger.debug("NODE {}: Node advancer: VERSION - VERSION default to 1", node.getNodeId());
                        zwaveVersionClass.setVersion(1);
                    }
                }
                logger.debug("NODE {}: Node advancer: VERSION - queued {} frames", node.getNodeId(), msgQueue.size());
                break;
            case APP_VERSION:
                ZWaveVersionCommandClass versionCommandClass = (ZWaveVersionCommandClass) node.getCommandClass(CommandClass.VERSION);
                if (versionCommandClass == null) {
                    logger.debug("NODE {}: Node advancer: APP_VERSION - VERSION node supported", node.getNodeId());
                    break;
                }
                // If we know the library type, then we've got the app version
                if (versionCommandClass.getLibraryType() != LibraryType.LIB_UNKNOWN) {
                    break;
                }
                // Request the version report for this node
                logger.debug("NODE {}: Node advancer: APP_VERSION - send VersionMessage", node.getNodeId());
                addToQueue(versionCommandClass.getVersionMessage());
                break;
            case ENDPOINTS:
                // Try and get the multi instance / channel command class.
                ZWaveMultiInstanceCommandClass multiInstance = (ZWaveMultiInstanceCommandClass) node.getCommandClass(CommandClass.MULTI_INSTANCE);
                if (multiInstance != null) {
                    logger.debug("NODE {}: Node advancer: ENDPOINTS - MultiInstance is supported", node.getNodeId());
                    addToQueue(multiInstance.initEndpoints(stageAdvanced));
                    logger.debug("NODE {}: Node advancer: ENDPOINTS - queued {} frames", node.getNodeId(), msgQueue.size());
                } else {
                    logger.debug("NODE {}: Node advancer: ENDPOINTS - MultiInstance not supported.", node.getNodeId());
                    // Set all classes to 1 instance.
                    for (ZWaveCommandClass commandClass : node.getCommandClasses()) {
                        commandClass.setInstances(1);
                    }
                }
                break;
            case UPDATE_DATABASE:
                // This stage reads information from the database to allow us to modify the configuration
                logger.debug("NODE {}: Node advancer: UPDATE_DATABASE", node.getNodeId());
                // We now should know all the command classes, so run through the database and set any options
                database = new ZWaveProductDatabase();
                if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == true) {
                    List<ZWaveDbCommandClass> classList = database.getProductCommandClasses();
                    if (classList != null) {
                        // Loop through the command classes and update the records...
                        for (ZWaveDbCommandClass dbClass : classList) {
                            // If we want to remove the class, then remove it!
                            if (dbClass.remove != null && dbClass.remove == true) {
                                // TODO: This will only remove the root nodes and ignores endpoint
                                // TODO: Do we need to search into multi_instance?
                                node.removeCommandClass(CommandClass.getCommandClass(dbClass.Id));
                                logger.debug("NODE {}: Node advancer: UPDATE_DATABASE - removing {}", node.getNodeId(), CommandClass.getCommandClass(dbClass.Id).getLabel());
                                continue;
                            }
                            // Get the command class
                            int endpoint = dbClass.endpoint == null ? 0 : dbClass.endpoint;
                            ZWaveCommandClass zwaveClass = node.resolveCommandClass(CommandClass.getCommandClass(dbClass.Id), endpoint);
                            // If we found the command class, then set its options
                            if (zwaveClass != null) {
                                zwaveClass.setOptions(dbClass);
                                continue;
                            }
                            // TODO: Does this need to account for multiple endpoints!?!
                            if (dbClass.add != null && dbClass.add == true) {
                                ZWaveCommandClass commandClass = ZWaveCommandClass.getInstance(dbClass.Id, node, controller);
                                if (commandClass != null) {
                                    logger.debug("NODE {}: Node advancer: UPDATE_DATABASE - adding {}", node.getNodeId(), CommandClass.getCommandClass(dbClass.Id).getLabel());
                                    node.addCommandClass(commandClass);
                                }
                            }
                        }
                    }
                }
                break;
            case STATIC_VALUES:
                // Loop through all classes looking for static initialisation
                for (ZWaveCommandClass zwaveStaticClass : node.getCommandClasses()) {
                    logger.debug("NODE {}: Node advancer: STATIC_VALUES - checking {}", node.getNodeId(), zwaveStaticClass.getCommandClass().getLabel());
                    if (zwaveStaticClass instanceof ZWaveCommandClassInitialization) {
                        logger.debug("NODE {}: Node advancer: STATIC_VALUES - found    {}", node.getNodeId(), zwaveStaticClass.getCommandClass().getLabel());
                        ZWaveCommandClassInitialization zcci = (ZWaveCommandClassInitialization) zwaveStaticClass;
                        int instances = zwaveStaticClass.getInstances();
                        logger.debug("NODE {}: Found {} instances of {}", node.getNodeId(), instances, zwaveStaticClass.getCommandClass());
                        if (instances == 1) {
                            addToQueue(zcci.initialize(stageAdvanced));
                        } else {
                            for (int i = 1; i <= instances; i++) {
                                addToQueue(zcci.initialize(stageAdvanced), zwaveStaticClass, i);
                            }
                        }
                    } else if (zwaveStaticClass instanceof ZWaveMultiInstanceCommandClass) {
                        ZWaveMultiInstanceCommandClass multiInstanceCommandClass = (ZWaveMultiInstanceCommandClass) zwaveStaticClass;
                        for (ZWaveEndpoint endpoint : multiInstanceCommandClass.getEndpoints()) {
                            for (ZWaveCommandClass endpointCommandClass : endpoint.getCommandClasses()) {
                                logger.debug("NODE {}: Node advancer: STATIC_VALUES - checking {} for endpoint {}", node.getNodeId(), endpointCommandClass.getCommandClass().getLabel(), endpoint.getEndpointId());
                                if (endpointCommandClass instanceof ZWaveCommandClassInitialization) {
                                    logger.debug("NODE {}: Node advancer: STATIC_VALUES - found    {}", node.getNodeId(), endpointCommandClass.getCommandClass().getLabel());
                                    ZWaveCommandClassInitialization zcci2 = (ZWaveCommandClassInitialization) endpointCommandClass;
                                    addToQueue(zcci2.initialize(stageAdvanced), endpointCommandClass, endpoint.getEndpointId());
                                }
                            }
                        }
                    }
                }
                logger.debug("NODE {}: Node advancer: STATIC_VALUES - queued {} frames", node.getNodeId(), msgQueue.size());
                break;
            case ASSOCIATIONS:
                // Do we support associations
                ZWaveAssociationCommandClass associationCommandClass = (ZWaveAssociationCommandClass) node.getCommandClass(CommandClass.ASSOCIATION);
                if (associationCommandClass == null) {
                    break;
                }
                // so just do this once
                if (stageAdvanced == false) {
                    break;
                }
                // Open the product database
                ZWaveProductDatabase associations = new ZWaveProductDatabase();
                if (associations.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == true) {
                    // We have this device in the database
                    // Assume the database is correct since some devices report invalid number of groups!
                    List<ZWaveDbAssociationGroup> groupList = associations.getProductAssociationGroups();
                    // No groups known
                    if (groupList == null) {
                        logger.debug("NODE {}: Node advancer: ASSOCIATIONS - none in database", node.getNodeId());
                        break;
                    }
                    // Request every group
                    for (ZWaveDbAssociationGroup group : groupList) {
                        logger.debug("NODE {}: Node advancer: ASSOCIATIONS request group {}", node.getNodeId(), group.Index);
                        addToQueue(associationCommandClass.getAssociationMessage(group.Index));
                    }
                } else {
                    for (int group = 1; group <= associationCommandClass.getMaxGroups(); group++) {
                        logger.debug("NODE {}: Node advancer: ASSOCIATIONS request group {}", node.getNodeId(), group);
                        addToQueue(associationCommandClass.getAssociationMessage(group));
                    }
                }
                break;
            case SET_WAKEUP:
                // It sets the node to point to us, and the time is left along
                if (controller.isMasterController() == false) {
                    break;
                }
                ZWaveWakeUpCommandClass wakeupCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
                if (wakeupCommandClass == null) {
                    logger.debug("NODE {}: Node advancer: SET_WAKEUP - Wakeup command class not supported", node.getNodeId());
                    break;
                }
                if (wakeupCommandClass.getTargetNodeId() == controller.getOwnNodeId()) {
                    logger.debug("NODE {}: Node advancer: SET_WAKEUP - TargetNode is set to controller", node.getNodeId());
                    break;
                }
                int value = 3600;
                if (wakeupCommandClass.getInterval() == 0) {
                    logger.debug("NODE {}: Node advancer: SET_WAKEUP - Interval is currently 0. Set to 3600", node.getNodeId());
                } else {
                    value = wakeupCommandClass.getInterval();
                }
                logger.debug("NODE {}: Node advancer: SET_WAKEUP - Set wakeup node to controller ({}), period {}", node.getNodeId(), controller.getOwnNodeId(), value);
                // Set the wake-up interval, and request an update
                addToQueue(wakeupCommandClass.setInterval(value));
                addToQueue(wakeupCommandClass.getIntervalMessage());
                break;
            case SET_ASSOCIATION:
                if (controller.isMasterController() == false) {
                    break;
                }
                database = new ZWaveProductDatabase();
                if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == false) {
                    // No database entry for this device!
                    logger.warn("NODE {}: Node advancer: SET_ASSOCIATION - Unknown device: {}:{}:{}", node.getNodeId(), Integer.toHexString(node.getManufacturer()), Integer.toHexString(node.getDeviceType()), Integer.toHexString(node.getDeviceId()));
                    break;
                }
                List<ZWaveDbAssociationGroup> groups = database.getProductAssociationGroups();
                if (groups == null || groups.size() == 0) {
                    logger.debug("NODE {}: Node advancer: SET_ASSOCIATION - No association groups", node.getNodeId());
                    break;
                }
                // Get the group members
                ZWaveAssociationCommandClass associationCls = (ZWaveAssociationCommandClass) node.getCommandClass(CommandClass.ASSOCIATION);
                if (associationCls == null) {
                    logger.debug("NODE {}: Node advancer: SET_ASSOCIATION - ASSOCIATION class not supported", node.getNodeId());
                    break;
                }
                // Loop through all the groups in the database
                for (ZWaveDbAssociationGroup group : groups) {
                    if (group.SetToController == true) {
                        // Check if we're already a member
                        if (associationCls.getGroupMembers(group.Index).contains(controller.getOwnNodeId())) {
                            logger.debug("NODE {}: Node advancer: SET_ASSOCIATION - ASSOCIATION set for group {}", node.getNodeId(), group.Index);
                        } else {
                            logger.debug("NODE {}: Node advancer: SET_ASSOCIATION - Adding ASSOCIATION to group {}", node.getNodeId(), group.Index);
                            // Set the association, and request the update so we confirm if it's set
                            addToQueue(associationCls.setAssociationMessage(group.Index, controller.getOwnNodeId()));
                            addToQueue(associationCls.getAssociationMessage(group.Index));
                        }
                    }
                }
                break;
            case GET_CONFIGURATION:
                database = new ZWaveProductDatabase();
                if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == false) {
                    // No database entry for this device!
                    logger.warn("NODE {}: Node advancer: GET_CONFIGURATION - Unknown device: {}:{}:{}", node.getNodeId(), Integer.toHexString(node.getManufacturer()), Integer.toHexString(node.getDeviceType()), Integer.toHexString(node.getDeviceId()));
                    break;
                }
                ZWaveConfigurationCommandClass configurationCommandClass = (ZWaveConfigurationCommandClass) node.getCommandClass(CommandClass.CONFIGURATION);
                // If there are no configuration entries for this node, then continue.
                List<ZWaveDbConfigurationParameter> configList = database.getProductConfigParameters();
                if (configList == null || configList.size() == 0) {
                    break;
                }
                // If the node doesn't support configuration class, then we better let people know!
                if (configurationCommandClass == null) {
                    logger.error("NODE {}: Node advancer: GET_CONFIGURATION - CONFIGURATION class not supported", node.getNodeId());
                    break;
                }
                // Request all parameters for this node
                for (ZWaveDbConfigurationParameter parameter : configList) {
                    // Some parameters don't return anything, so don't request them!
                    if (parameter.WriteOnly != null && parameter.WriteOnly == true) {
                        configurationCommandClass.setParameterWriteOnly(parameter.Index, parameter.Size, true);
                        continue;
                    }
                    // then request it!
                    if (configurationCommandClass.getParameter(parameter.Index) == null) {
                        addToQueue(configurationCommandClass.getConfigMessage(parameter.Index));
                    }
                }
                break;
            case DYNAMIC_VALUES:
                for (ZWaveCommandClass zwaveDynamicClass : node.getCommandClasses()) {
                    logger.debug("NODE {}: Node advancer: DYNAMIC_VALUES - checking {}", node.getNodeId(), zwaveDynamicClass.getCommandClass().getLabel());
                    if (zwaveDynamicClass instanceof ZWaveCommandClassDynamicState) {
                        logger.debug("NODE {}: Node advancer: DYNAMIC_VALUES - found    {}", node.getNodeId(), zwaveDynamicClass.getCommandClass().getLabel());
                        ZWaveCommandClassDynamicState zdds = (ZWaveCommandClassDynamicState) zwaveDynamicClass;
                        int instances = zwaveDynamicClass.getInstances();
                        logger.debug("NODE {}: Found {} instances of {}", node.getNodeId(), instances, zwaveDynamicClass.getCommandClass());
                        if (instances == 1) {
                            addToQueue(zdds.getDynamicValues(stageAdvanced));
                        } else {
                            for (int i = 1; i <= instances; i++) {
                                addToQueue(zdds.getDynamicValues(stageAdvanced), zwaveDynamicClass, i);
                            }
                        }
                    } else if (zwaveDynamicClass instanceof ZWaveMultiInstanceCommandClass) {
                        ZWaveMultiInstanceCommandClass multiInstanceCommandClass = (ZWaveMultiInstanceCommandClass) zwaveDynamicClass;
                        for (ZWaveEndpoint endpoint : multiInstanceCommandClass.getEndpoints()) {
                            for (ZWaveCommandClass endpointCommandClass : endpoint.getCommandClasses()) {
                                logger.debug("NODE {}: Node advancer: DYNAMIC_VALUES - checking {} for endpoint {}", node.getNodeId(), endpointCommandClass.getCommandClass().getLabel(), endpoint.getEndpointId());
                                if (endpointCommandClass instanceof ZWaveCommandClassDynamicState) {
                                    logger.debug("NODE {}: Node advancer: DYNAMIC_VALUES - found    {}", node.getNodeId(), endpointCommandClass.getCommandClass().getLabel());
                                    ZWaveCommandClassDynamicState zdds2 = (ZWaveCommandClassDynamicState) endpointCommandClass;
                                    addToQueue(zdds2.getDynamicValues(stageAdvanced), endpointCommandClass, endpoint.getEndpointId());
                                }
                            }
                        }
                    }
                }
                logger.debug("NODE {}: Node advancer: DYNAMIC_VALUES - queued {} frames", node.getNodeId(), msgQueue.size());
                break;
            case STATIC_END:
            case DONE:
                // Save the node information to file
                nodeSerializer.SerializeNode(node);
                if (currentStage != ZWaveNodeInitStage.DONE) {
                    break;
                }
                logger.debug("NODE {}: Node advancer: Initialisation complete!", node.getNodeId());
                // Stop the retry timer
                resetIdleTimer();
                // We remove the event listener to reduce loading now that we're done
                controller.removeEventListener(this);
                // Notify everyone!
                ZWaveEvent zEvent = new ZWaveInitializationCompletedEvent(node.getNodeId());
                controller.notifyEventListeners(zEvent);
                // increment the stage!
                return;
            case SESSION_START:
                // where to start initialisation if we restored from XML.
                break;
            default:
                logger.debug("NODE {}: Node advancer: Unknown node state {} encountered.", node.getNodeId(), currentStage.toString().toString());
                break;
        }
        // that we're starting again, then loop around again.
        if (currentStage != ZWaveNodeInitStage.DONE && sendMessage() == false) {
            // Move on to the next stage
            setCurrentStage(currentStage.getNextStage());
            stageAdvanced = true;
            // Reset the backoff timer
            retryTimer = BACKOFF_TIMER_START;
            logger.debug("NODE {}: Node advancer - advancing to {}", node.getNodeId(), currentStage.toString());
        }
    } while (msgQueue.isEmpty());
}
Also used : ZWaveVersionCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass) ZWaveEvent(org.openhab.binding.zwave.internal.protocol.event.ZWaveEvent) ZWaveInitializationCompletedEvent(org.openhab.binding.zwave.internal.protocol.event.ZWaveInitializationCompletedEvent) ZWaveCommandClassDynamicState(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClassDynamicState) SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage) ZWaveNoOperationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNoOperationCommandClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass) ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveDbCommandClass(org.openhab.binding.zwave.internal.config.ZWaveDbCommandClass) ZWaveConfigurationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveConfigurationCommandClass) ZWaveManufacturerSpecificCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveManufacturerSpecificCommandClass) ZWaveSecurityCommandClassWithInitialization(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClassWithInitialization) ZWaveMultiInstanceCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveMultiInstanceCommandClass) ZWaveEndpoint(org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint) ZWaveCommandClassInitialization(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClassInitialization) ZWaveProductDatabase(org.openhab.binding.zwave.internal.config.ZWaveProductDatabase) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) IsFailedNodeMessageClass(org.openhab.binding.zwave.internal.protocol.serialmessage.IsFailedNodeMessageClass) IdentifyNodeMessageClass(org.openhab.binding.zwave.internal.protocol.serialmessage.IdentifyNodeMessageClass) RequestNodeInfoMessageClass(org.openhab.binding.zwave.internal.protocol.serialmessage.RequestNodeInfoMessageClass) ZWaveDbConfigurationParameter(org.openhab.binding.zwave.internal.config.ZWaveDbConfigurationParameter) ZWaveEndpoint(org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint) ZWaveDbAssociationGroup(org.openhab.binding.zwave.internal.config.ZWaveDbAssociationGroup) GetRoutingInfoMessageClass(org.openhab.binding.zwave.internal.protocol.serialmessage.GetRoutingInfoMessageClass)

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