Search in sources :

Example 1 with ZWaveAssociationCommandClass

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

the class ZWaveNetworkMonitor method nextHealStage.

/**
     * Perform the next step in the heal process. This function also handles the
     * retries. Each time through the loop it increments the retry counter. If
     * the max retries is exceeded then the failed state is saved and we return
     * to allow other nodes to continue.
     *
     * @param healing
     *            The node on which to perform the heal
     */
private void nextHealStage(HealNode healing) {
    // Don't do anything if it's failed already
    if (healing.state == HealState.FAILED) {
        return;
    }
    healing.lastChange = Calendar.getInstance().getTime();
    // Set the ping time into the future.
    // This holds off the routine ping when there's a heal in progress
    // to avoid congestion and false timeouts.
    pingNodeTime = System.currentTimeMillis() + HEAL_TIMEOUT_PERIOD + 20000;
    // Set the timeout
    networkHealNextTime = System.currentTimeMillis() + HEAL_TIMEOUT_PERIOD;
    // Only do something if the node is awake!
    ZWaveNode node = zController.getNode(healing.nodeId);
    if (node != null) {
        ZWaveWakeUpCommandClass wakeupCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
        if (wakeupCommandClass != null && wakeupCommandClass.isAwake() == false) {
            // Device is asleep - don't do anything now!
            logger.debug("NODE {}: Node is asleep. Defer heal until it's awake", healing.nodeId);
            return;
        }
    }
    // Handle retries
    healing.retryCnt++;
    if (healing.retryCnt >= HEAL_MAX_RETRIES) {
        logger.debug("NODE {}: Maximum retries in state {}", healing.nodeId, healing.state);
        // continue with the heal than to abort here.
        if (healing.state == HealState.UPDATENEIGHBORS) {
            healing.state = healing.stateNext;
            healing.retryCnt = 0;
            logger.debug("NODE {}: Heal - continuing to state {}", healing.nodeId, healing.stateNext);
        } else {
            logger.debug("NODE {}: Network heal has exceeded maximum retries!", healing.nodeId);
            healing.failState = healing.state;
            healing.state = HealState.FAILED;
            // Save the XML file. This serialises the data we've just updated
            // (neighbors etc)
            healing.node.setHealState(this.getNodeState(healing.node.getNodeId()));
            ZWaveNodeSerializer nodeSerializer = new ZWaveNodeSerializer();
            nodeSerializer.SerializeNode(healing.node);
            return;
        }
    }
    // Set the timeout
    networkHealNextTime = System.currentTimeMillis() + HEAL_TIMEOUT_PERIOD;
    switch(healing.state) {
        case WAITING:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - STARTING", healing.nodeId);
            // Reset the resend count.
            // This also resets the time so that we cycle through all the nodes
            healing.node.resetResendCount();
            healing.state = HealState.PING;
        case PING:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            if (healing.nodeId != zController.getOwnNodeId()) {
                healing.state = HealState.PING;
                ZWaveNoOperationCommandClass zwaveCommandClass = (ZWaveNoOperationCommandClass) healing.node.getCommandClass(CommandClass.NO_OPERATION);
                if (zwaveCommandClass != null) {
                    zController.sendData(zwaveCommandClass.getNoOperationMessage());
                    healing.stateNext = HealState.SETSUCROUTE;
                    break;
                }
            }
            healing.state = HealState.SETSUCROUTE;
        case SETSUCROUTE:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            // Only set the route if this is not the controller and there is an SUC in the network
            if (healing.nodeId != zController.getOwnNodeId() && zController.getSucId() != 0) {
                // Update the route to the controller
                logger.debug("NODE {}: Heal is setting SUC route.", healing.nodeId);
                healing.event = ZWaveNetworkEvent.Type.AssignSucReturnRoute;
                healing.stateNext = HealState.UPDATENEIGHBORS;
                zController.requestAssignSucReturnRoute(healing.nodeId);
                break;
            }
            healing.state = HealState.UPDATENEIGHBORS;
        case UPDATENEIGHBORS:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            healing.event = ZWaveNetworkEvent.Type.NodeNeighborUpdate;
            healing.stateNext = HealState.GETASSOCIATIONS;
            zController.requestNodeNeighborUpdate(healing.nodeId);
            break;
        case GETASSOCIATIONS:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            // Check if this node supports associations
            ZWaveAssociationCommandClass associationCommandClass = (ZWaveAssociationCommandClass) healing.node.getCommandClass(CommandClass.ASSOCIATION);
            if (associationCommandClass != null) {
                logger.debug("NODE {}: Heal is requesting device associations.", healing.nodeId);
                healing.stateNext = HealState.UPDATEROUTES;
                healing.event = ZWaveNetworkEvent.Type.AssociationUpdate;
                associationCommandClass.getAllAssociations();
                break;
            }
            healing.stateNext = HealState.UPDATEROUTES;
        case UPDATEROUTES:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            // Get the list of routes for this node
            healing.routeList = healing.node.getRoutingList();
            if (healing.routeList != null && healing.routeList.size() != 0) {
                // Delete all the return routes for the node
                logger.debug("NODE {}: Heal is deleting routes.", healing.nodeId);
                healing.event = ZWaveNetworkEvent.Type.DeleteReturnRoute;
                healing.stateNext = HealState.UPDATEROUTESNEXT;
                zController.requestDeleteAllReturnRoutes(healing.nodeId);
                break;
            }
            healing.stateNext = HealState.UPDATEROUTESNEXT;
        case UPDATEROUTESNEXT:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            if (healing.routeList != null && healing.routeList.size() != 0) {
                // Loop through all the nodes and set the return route
                logger.debug("NODE {}: Adding return route to {}", healing.nodeId, healing.routeList.get(0));
                healing.stateNext = HealState.GETNEIGHBORS;
                healing.event = ZWaveNetworkEvent.Type.AssignReturnRoute;
                zController.requestAssignReturnRoute(healing.nodeId, healing.routeList.get(0));
                break;
            }
            healing.stateNext = HealState.GETNEIGHBORS;
        case GETNEIGHBORS:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            healing.event = ZWaveNetworkEvent.Type.NodeRoutingInfo;
            healing.stateNext = HealState.SAVE;
            logger.debug("NODE {}: Heal is requesting node neighbor info.", healing.nodeId);
            zController.requestNodeRoutingInfo(healing.nodeId);
            break;
        case SAVE:
            // Log what we're up to...
            logger.debug("NODE {}: NETWORK HEAL - {}", healing.nodeId, healing.state);
            healing.state = HealState.DONE;
            networkHealNextTime = System.currentTimeMillis() + HEAL_DELAY_PERIOD;
            // Save the XML file. This serialises the data we've just updated
            // (neighbors etc)
            healing.node.setHealState(this.getNodeState(healing.node.getNodeId()));
            ZWaveNodeSerializer nodeSerializer = new ZWaveNodeSerializer();
            nodeSerializer.SerializeNode(healing.node);
            break;
        default:
            break;
    }
    healing.node.setHealState(this.getNodeState(healing.node.getNodeId()));
}
Also used : ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveNodeSerializer(org.openhab.binding.zwave.internal.protocol.initialization.ZWaveNodeSerializer) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) ZWaveNoOperationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNoOperationCommandClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)

Example 2 with ZWaveAssociationCommandClass

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

the class ZWaveConfiguration method doSet.

@Override
public void doSet(String domain, String value) {
    logger.debug("doSet domain '{}' to '{}'", domain, value);
    String[] splitDomain = domain.split("/");
    // If the controller isn't ready, then ignore any requests
    if (zController.isConnected() == false) {
        logger.debug("Controller not ready - Ignoring request to '{}'", domain);
        return;
    }
    // There must be at least 2 components to the domain
    if (splitDomain.length < 2) {
        logger.error("Error malformed domain in doSet '{}'", domain);
        return;
    }
    if (splitDomain[0].equals("nodes")) {
        int nodeId = Integer.parseInt(splitDomain[1].substring(4));
        ZWaveNode node = zController.getNode(nodeId);
        if (node == null) {
            logger.error("Error finding node in doSet '{}'", domain);
            return;
        }
        // TODO: Should we check that the node is finished initialising
        ZWaveProductDatabase database = new ZWaveProductDatabase();
        if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == false) {
            logger.error("NODE {}: Error in doSet - no database found", nodeId);
            return;
        }
        if (splitDomain.length == 3) {
            if (splitDomain[2].equals("Name")) {
                node.setName(value);
            }
            if (splitDomain[2].equals("Location")) {
                node.setLocation(value);
            }
            if (splitDomain[2].equals("SwitchAll")) {
                ZWaveSwitchAllCommandClass switchAllCommandClass = (ZWaveSwitchAllCommandClass) node.getCommandClass(CommandClass.SWITCH_ALL);
                if (switchAllCommandClass == null) {
                    logger.error("NODE {}: Error getting switchAllCommandClass in doSet", nodeId);
                    return;
                }
                // Set the switch all mode
                int mode = Integer.parseInt(value);
                PendingCfg.Add(ZWaveSwitchAllCommandClass.CommandClass.SWITCH_ALL.getKey(), node.getNodeId(), 0, mode);
                SerialMessage msg = switchAllCommandClass.setValueMessage(mode);
                this.zController.sendData(msg);
                // And request a read-back
                this.zController.sendData(switchAllCommandClass.getValueMessage());
            }
            // Write the node to disk
            ZWaveNodeSerializer nodeSerializer = new ZWaveNodeSerializer();
            nodeSerializer.SerializeNode(node);
        } else if (splitDomain.length == 4) {
            if (splitDomain[2].equals("parameters")) {
                ZWaveConfigurationCommandClass configurationCommandClass = (ZWaveConfigurationCommandClass) node.getCommandClass(CommandClass.CONFIGURATION);
                if (configurationCommandClass == null) {
                    logger.error("NODE {}: Error getting configurationCommandClass in doSet", nodeId);
                    return;
                }
                int paramIndex = Integer.parseInt(splitDomain[3].substring(13));
                List<ZWaveDbConfigurationParameter> configList = database.getProductConfigParameters();
                // Get the size
                int size = 1;
                for (ZWaveDbConfigurationParameter parameter : configList) {
                    if (parameter.Index == paramIndex) {
                        size = parameter.Size;
                        break;
                    }
                }
                logger.debug("Set parameter index '{}' to '{}'", paramIndex, value);
                PendingCfg.Add(ZWaveCommandClass.CommandClass.CONFIGURATION.getKey(), nodeId, paramIndex, Integer.valueOf(value));
                ConfigurationParameter configurationParameter = new ConfigurationParameter(paramIndex, Integer.valueOf(value), size);
                // Set the parameter
                this.zController.sendData(configurationCommandClass.setConfigMessage(configurationParameter));
                // And request a read-back
                this.zController.sendData(configurationCommandClass.getConfigMessage(paramIndex));
            }
            if (splitDomain[2].equals("wakeup")) {
                ZWaveWakeUpCommandClass wakeupCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
                if (wakeupCommandClass == null) {
                    logger.error("NODE {}: Error getting wakeupCommandClass in doSet", nodeId);
                    return;
                }
                logger.debug("NODE {}: Set wakeup interval to '{}'", nodeId, value);
                // Add this as a pending transaction
                PendingCfg.Add(ZWaveCommandClass.CommandClass.WAKE_UP.getKey(), node.getNodeId(), Integer.parseInt(value));
                // Set the wake-up interval
                this.zController.sendData(wakeupCommandClass.setInterval(Integer.parseInt(value)));
                // And request a read-back
                this.zController.sendData(wakeupCommandClass.getIntervalMessage());
            }
            if (splitDomain[2].equals("controller")) {
                if (splitDomain[3].equals("Type")) {
                    ZWaveDeviceType type = ZWaveDeviceType.fromString(value);
                    logger.error("NODE {}: Setting controller type to {}", nodeId, type.toString());
                // ZW_EnableSUC and ZW_SetSUCNodeID
                }
            }
        } else if (splitDomain.length == 5) {
            if (splitDomain[2].equals("associations")) {
                ZWaveAssociationCommandClass associationCommandClass = (ZWaveAssociationCommandClass) node.getCommandClass(CommandClass.ASSOCIATION);
                if (associationCommandClass == null) {
                    logger.error("NODE {}: Error getting associationCommandClass in doSet", nodeId);
                    return;
                }
                int assocId = Integer.parseInt(splitDomain[3].substring(11));
                int assocArg = Integer.parseInt(splitDomain[4].substring(4));
                if (value.equalsIgnoreCase("true")) {
                    PendingCfg.Add(ZWaveCommandClass.CommandClass.ASSOCIATION.getKey(), nodeId, assocId, assocArg, 1);
                    logger.debug("Add association index '{}' to '{}'", assocId, assocArg);
                    this.zController.sendData(associationCommandClass.setAssociationMessage(assocId, assocArg));
                } else {
                    PendingCfg.Add(ZWaveCommandClass.CommandClass.ASSOCIATION.getKey(), nodeId, assocId, assocArg, 0);
                    logger.debug("Remove association index '{}' to '{}'", assocId, assocArg);
                    this.zController.sendData(associationCommandClass.removeAssociationMessage(assocId, assocArg));
                }
                // Request an update to the group
                this.zController.sendData(associationCommandClass.getAssociationMessage(assocId));
                // So, let's start a network heal - just for this node right now
                if (networkMonitor != null) {
                    networkMonitor.startNodeHeal(nodeId);
                }
            }
        }
    }
}
Also used : ZWaveDeviceType(org.openhab.binding.zwave.internal.protocol.ZWaveDeviceType) ConfigurationParameter(org.openhab.binding.zwave.internal.protocol.ConfigurationParameter) ZWaveSwitchAllCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSwitchAllCommandClass) SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass) ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveNodeSerializer(org.openhab.binding.zwave.internal.protocol.initialization.ZWaveNodeSerializer) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) ZWaveConfigurationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveConfigurationCommandClass) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with ZWaveAssociationCommandClass

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

the class ZWaveConfiguration method doAction.

@Override
public void doAction(String domain, String action) {
    logger.trace("doAction domain '{}' to '{}'", domain, action);
    String[] splitDomain = domain.split("/");
    // There must be at least 2 components to the domain
    if (splitDomain.length < 2) {
        logger.error("Error malformed domain in doAction '{}'", domain);
        return;
    }
    // Process Controller Reset requests even if the controller isn't initialised
    if (splitDomain[0].equals("binding") && splitDomain[1].equals("network")) {
        if (action.equals("SoftReset")) {
            zController.requestSoftReset();
        } else if (action.equals("HardReset")) {
            zController.requestHardReset();
        }
    }
    // If the controller isn't ready, then ignore any further requests
    if (zController.isConnected() == false) {
        logger.debug("Controller not ready - Ignoring request to '{}'", domain);
        return;
    }
    if (splitDomain[0].equals("binding")) {
        if (splitDomain[1].equals("network")) {
            if (action.equals("Heal")) {
                if (networkMonitor != null) {
                    networkMonitor.rescheduleHeal();
                }
            }
            if (action.equals("Include") || action.equals("Exclude")) {
                // Only do include/exclude if it's not already in progress
                if (inclusion == false && exclusion == false) {
                    if (action.equals("Include")) {
                        inclusion = true;
                        zController.requestAddNodesStart();
                        setInclusionTimer();
                    }
                    if (action.equals("Exclude")) {
                        exclusion = true;
                        zController.requestRemoveNodesStart();
                        setInclusionTimer();
                    }
                } else {
                    logger.debug("Exclusion/Inclusion already in progress.");
                }
            }
        }
    }
    if (splitDomain[0].equals("nodes")) {
        int nodeId = Integer.parseInt(splitDomain[1].substring(4));
        // Get the node - if it exists
        ZWaveNode node = zController.getNode(nodeId);
        if (node == null) {
            logger.error("NODE {}: Error finding node in doAction", nodeId);
            return;
        }
        if (splitDomain.length == 2) {
            if (action.equals("Heal")) {
                logger.debug("NODE {}: Heal node", nodeId);
                if (networkMonitor != null) {
                    networkMonitor.startNodeHeal(nodeId);
                }
            }
            if (action.equals("Save")) {
                logger.debug("NODE {}: Saving node", nodeId);
                // Write the node to disk
                ZWaveNodeSerializer nodeSerializer = new ZWaveNodeSerializer();
                nodeSerializer.SerializeNode(node);
            }
            if (action.equals("Initialise")) {
                logger.debug("NODE {}: re-initialising node", nodeId);
                // Delete the saved XML
                ZWaveNodeSerializer nodeSerializer = new ZWaveNodeSerializer();
                nodeSerializer.DeleteNode(nodeId);
                this.zController.reinitialiseNode(nodeId);
            }
            if (action.equals("Delete")) {
                logger.debug("NODE {}: Delete node", nodeId);
                this.zController.requestRemoveFailedNode(nodeId);
            }
            // in the domain array
            return;
        }
        if (splitDomain[2].equals("parameters")) {
            ZWaveConfigurationCommandClass configurationCommandClass = (ZWaveConfigurationCommandClass) node.getCommandClass(CommandClass.CONFIGURATION);
            if (configurationCommandClass == null) {
                return;
            }
            if (action.equals("Refresh")) {
                logger.debug("NODE {}: Refresh parameters", nodeId);
                ZWaveProductDatabase database = new ZWaveProductDatabase();
                if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == false) {
                    return;
                }
                List<ZWaveDbConfigurationParameter> configList = database.getProductConfigParameters();
                // Request all parameters for this node
                for (ZWaveDbConfigurationParameter parameter : configList) {
                    this.zController.sendData(configurationCommandClass.getConfigMessage(parameter.Index));
                }
            }
        }
        if (splitDomain[2].equals("wakeup")) {
            if (action.equals("Refresh")) {
                // Only update if we support the wakeup class
                ZWaveWakeUpCommandClass wakeupCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
                if (wakeupCommandClass == null) {
                    return;
                }
                logger.debug("NODE {}: Refresh wakeup capabilities", nodeId);
                // Request the wakeup interval for this node
                this.zController.sendData(wakeupCommandClass.getIntervalMessage());
                // Request the wakeup parameters for this node
                this.zController.sendData(wakeupCommandClass.getIntervalCapabilitiesMessage());
            }
        }
        if (splitDomain[2].equals("neighbors")) {
            if (action.equals("Refresh")) {
                // this.zController.requestNodeNeighborUpdate(nodeId);
                // .requestNodeNeighborUpdate(nodeId);
                this.zController.requestNodeRoutingInfo(nodeId);
            }
        }
        if (splitDomain[2].equals("associations")) {
            if (action.equals("Refresh")) {
                // Make sure the association class is supported
                ZWaveAssociationCommandClass associationCommandClass = (ZWaveAssociationCommandClass) node.getCommandClass(CommandClass.ASSOCIATION);
                if (associationCommandClass == null) {
                    return;
                }
                logger.debug("NODE {}: Refresh associations", nodeId);
                ZWaveProductDatabase database = new ZWaveProductDatabase();
                if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == false) {
                    logger.error("NODE {}: Error in doAction - no database found", nodeId);
                    return;
                }
                if (splitDomain.length == 3) {
                    // Request all groups for this node
                    associationCommandClass.getAllAssociations();
                } else if (splitDomain.length == 4) {
                    // Request a single group
                    int nodeArg = Integer.parseInt(splitDomain[3].substring(11));
                    this.zController.sendData(associationCommandClass.getAssociationMessage(nodeArg));
                }
            }
        }
    }
}
Also used : ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveNodeSerializer(org.openhab.binding.zwave.internal.protocol.initialization.ZWaveNodeSerializer) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) ZWaveConfigurationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveConfigurationCommandClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)

Example 4 with ZWaveAssociationCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass 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)

Example 5 with ZWaveAssociationCommandClass

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

the class ZWaveConfiguration method getConfiguration.

@Override
public List<OpenHABConfigurationRecord> getConfiguration(String domain) {
    // We only deal with top level domains here!
    if (domain.endsWith("/") == false) {
        logger.error("Malformed domain request in getConfiguration '{}'", domain);
        return null;
    }
    List<OpenHABConfigurationRecord> records = new ArrayList<OpenHABConfigurationRecord>();
    OpenHABConfigurationRecord record;
    if (domain.equals("status/")) {
        return null;
    }
    if (domain.startsWith("products/")) {
        ZWaveProductDatabase database = new ZWaveProductDatabase();
        String[] splitDomain = domain.split("/");
        switch(splitDomain.length) {
            case 1:
                // Just list the manufacturers
                for (ZWaveDbManufacturer manufacturer : database.GetManufacturers()) {
                    record = new OpenHABConfigurationRecord(domain + manufacturer.Id.toString() + "/", manufacturer.Name);
                    records.add(record);
                }
                break;
            case 2:
                // Get products list
                if (database.FindManufacturer(Integer.parseInt(splitDomain[1])) == false) {
                    break;
                }
                record = new OpenHABConfigurationRecord(domain, "ManufacturerID", "Manufacturer ID", true);
                record.value = Integer.toHexString(database.getManufacturerId());
                records.add(record);
                for (ZWaveDbProduct product : database.GetProducts()) {
                    record = new OpenHABConfigurationRecord(domain + product.Reference.get(0).Type + "/" + product.Reference.get(0).Id + "/", product.Model);
                    record.value = database.getLabel(product.Label);
                    records.add(record);
                }
                break;
            case 4:
                // Get product
                if (database.FindProduct(Integer.parseInt(splitDomain[1]), Integer.parseInt(splitDomain[2]), Integer.parseInt(splitDomain[3]), MAX_VERSION) == false) {
                    break;
                }
                if (database.doesProductImplementCommandClass(ZWaveCommandClass.CommandClass.CONFIGURATION.getKey()) == true) {
                    record = new OpenHABConfigurationRecord(domain + "parameters/", "Configuration Parameters");
                    records.add(record);
                }
                if (database.doesProductImplementCommandClass(ZWaveCommandClass.CommandClass.ASSOCIATION.getKey()) == true) {
                    record = new OpenHABConfigurationRecord(domain + "associations/", "Association Groups");
                    records.add(record);
                }
                record = new OpenHABConfigurationRecord(domain + "classes/", "Command Classes");
                records.add(record);
                break;
            case 5:
                // Get product
                if (database.FindProduct(Integer.parseInt(splitDomain[1]), Integer.parseInt(splitDomain[2]), Integer.parseInt(splitDomain[3]), MAX_VERSION) == false) {
                    break;
                }
                if (splitDomain[4].equals("parameters")) {
                    List<ZWaveDbConfigurationParameter> configList = database.getProductConfigParameters();
                    // Loop through the parameters and add to the records...
                    for (ZWaveDbConfigurationParameter parameter : configList) {
                        record = new OpenHABConfigurationRecord(domain, "configuration" + parameter.Index, database.getLabel(parameter.Label), true);
                        if (parameter != null) {
                            record.value = parameter.Default;
                        }
                        // Add the data type
                        try {
                            record.type = OpenHABConfigurationRecord.TYPE.valueOf(parameter.Type.toUpperCase());
                        } catch (IllegalArgumentException e) {
                            logger.error("Error with parameter type for {} - Set {} - assuming LONG", parameter.Label.toString(), parameter.Type);
                            record.type = OpenHABConfigurationRecord.TYPE.LONG;
                        }
                        if (parameter.Item != null) {
                            for (ZWaveDbConfigurationListItem item : parameter.Item) {
                                record.addValue(Integer.toString(item.Value), database.getLabel(item.Label));
                            }
                        }
                        // Add the description
                        record.description = database.getLabel(parameter.Help);
                        records.add(record);
                    }
                }
                if (splitDomain[4].equals("associations")) {
                    List<ZWaveDbAssociationGroup> groupList = database.getProductAssociationGroups();
                    if (groupList != null) {
                        // records...
                        for (ZWaveDbAssociationGroup group : groupList) {
                            record = new OpenHABConfigurationRecord(domain, "association" + group.Index, database.getLabel(group.Label), true);
                            // Add the description
                            record.description = database.getLabel(group.Help);
                            records.add(record);
                        }
                    }
                }
                if (splitDomain[4].equals("classes")) {
                    List<ZWaveDbCommandClass> classList = database.getProductCommandClasses();
                    if (classList != null) {
                        // records...
                        for (ZWaveDbCommandClass iClass : classList) {
                            // Make sure the command class exists!
                            if (ZWaveCommandClass.CommandClass.getCommandClass(iClass.Id) == null) {
                                continue;
                            }
                            record = new OpenHABConfigurationRecord(domain, "class" + iClass.Id, ZWaveCommandClass.CommandClass.getCommandClass(iClass.Id).getLabel(), true);
                            if (ZWaveCommandClass.CommandClass.getCommandClass(iClass.Id).getCommandClassClass() == null) {
                                record.state = OpenHABConfigurationRecord.STATE.WARNING;
                            }
                            records.add(record);
                        }
                    }
                }
                break;
        }
        return records;
    }
    // All domains after here must have an initialised ZWave network
    if (zController == null) {
        logger.error("Controller not initialised in call to getConfiguration");
        return null;
    }
    if (domain.equals("nodes/")) {
        ZWaveProductDatabase database = new ZWaveProductDatabase();
        // Return the list of nodes
        for (ZWaveNode node : zController.getNodes()) {
            if (node.getName() == null || node.getName().isEmpty()) {
                record = new OpenHABConfigurationRecord("nodes/" + "node" + node.getNodeId() + "/", "Node " + node.getNodeId());
            } else {
                record = new OpenHABConfigurationRecord("nodes/" + "node" + node.getNodeId() + "/", node.getNodeId() + ": " + node.getName());
            }
            // If we can't find the product, then try and find just the manufacturer
            if (node.getManufacturer() == Integer.MAX_VALUE) {
            // The device isn't know, print nothing!
            } else if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == false) {
                if (database.FindManufacturer(node.getManufacturer()) == false) {
                    record.value = "Manufacturer:" + node.getManufacturer() + " [ID:" + Integer.toHexString(node.getDeviceId()) + ",Type:" + Integer.toHexString(node.getDeviceType()) + "]";
                } else {
                    record.value = database.getManufacturerName() + " [ID:" + Integer.toHexString(node.getDeviceId()) + ",Type:" + Integer.toHexString(node.getDeviceType()) + "]";
                }
                logger.debug("NODE {}: No database entry: {}", node.getNodeId(), record.value);
            } else {
                if (node.getLocation() == null || node.getLocation().isEmpty()) {
                    record.value = database.getProductName();
                } else {
                    record.value = database.getProductName() + ": " + node.getLocation();
                }
            }
            // Set the state
            boolean canDelete = false;
            switch(node.getNodeState()) {
                case DEAD:
                    record.state = OpenHABConfigurationRecord.STATE.ERROR;
                    break;
                case FAILED:
                    record.state = OpenHABConfigurationRecord.STATE.ERROR;
                    canDelete = true;
                    break;
                case ALIVE:
                    Date lastDead = node.getDeadTime();
                    Long timeSinceLastDead = Long.MAX_VALUE;
                    if (lastDead != null) {
                        timeSinceLastDead = System.currentTimeMillis() - lastDead.getTime();
                    }
                    if (node.getNodeInitializationStage() != ZWaveNodeInitStage.DONE) {
                        record.state = OpenHABConfigurationRecord.STATE.INITIALIZING;
                    } else if (node.getDeadCount() > 0 && timeSinceLastDead < 86400000) {
                        record.state = OpenHABConfigurationRecord.STATE.WARNING;
                    } else if (node.getSendCount() > 20 && (node.getRetryCount() * 100 / node.getSendCount()) > 5) {
                        record.state = OpenHABConfigurationRecord.STATE.WARNING;
                    } else {
                        record.state = OpenHABConfigurationRecord.STATE.OK;
                    }
                    break;
            }
            // Add the action buttons
            record.addAction("Heal", "Heal Node");
            record.addAction("Initialise", "Reinitialise Node");
            // Add the delete button if the node is not "operational"
            if (canDelete) {
                record.addAction("Delete", "Delete Node");
            }
            records.add(record);
        }
        return records;
    }
    if (domain.startsWith("nodes/node")) {
        String nodeNumber = domain.substring(10);
        int next = nodeNumber.indexOf('/');
        String arg = null;
        if (next != -1) {
            arg = nodeNumber.substring(next + 1);
            nodeNumber = nodeNumber.substring(0, next);
        }
        int nodeId = Integer.parseInt(nodeNumber);
        // Return the detailed configuration for this node
        ZWaveNode node = zController.getNode(nodeId);
        if (node == null) {
            return null;
        }
        // Open the product database
        ZWaveProductDatabase database = new ZWaveProductDatabase();
        // Process the request
        if (arg.equals("")) {
            record = new OpenHABConfigurationRecord(domain, "Name", "Name", false);
            record.value = node.getName();
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Location", "Location", false);
            record.value = node.getLocation();
            records.add(record);
            ZWaveSwitchAllCommandClass switchAllCommandClass = (ZWaveSwitchAllCommandClass) node.getCommandClass(ZWaveCommandClass.CommandClass.SWITCH_ALL);
            if (node.getCommandClass(CommandClass.SWITCH_ALL) != null) {
                record = new OpenHABConfigurationRecord(domain, "SwitchAll", "Switch All", false);
                record.type = OpenHABConfigurationRecord.TYPE.LIST;
                record.addValue("0", "Exclude from All On and All Off groups");
                record.addValue("1", "Include in All On group");
                record.addValue("2", "Include in All Off group");
                record.addValue("255", "Include in All On and All Off groups");
                record.value = String.valueOf(switchAllCommandClass.getMode());
                records.add(record);
            }
            // Get the configuration command class for this node if it's supported
            if (node.getCommandClass(CommandClass.CONFIGURATION) != null) {
                record = new OpenHABConfigurationRecord(domain + "parameters/", "Configuration Parameters");
                record.addAction("Refresh", "Refresh");
                records.add(record);
            }
            if (node.getCommandClass(CommandClass.ASSOCIATION) != null) {
                record = new OpenHABConfigurationRecord(domain + "associations/", "Association Groups");
                record.addAction("Refresh", "Refresh");
                records.add(record);
            }
            if (node.getCommandClass(CommandClass.WAKE_UP) != null) {
                record = new OpenHABConfigurationRecord(domain + "wakeup/", "Wakeup Period");
                record.addAction("Refresh", "Refresh");
                records.add(record);
            }
            // Is this a controller
            if (nodeId == zController.getOwnNodeId()) {
                record = new OpenHABConfigurationRecord(domain + "controller/", "Controller");
                records.add(record);
            }
            record = new OpenHABConfigurationRecord(domain + "neighbors/", "Neighbors");
            record.addAction("Refresh", "Refresh");
            records.add(record);
            record = new OpenHABConfigurationRecord(domain + "status/", "Status");
            records.add(record);
            record = new OpenHABConfigurationRecord(domain + "info/", "Information");
            records.add(record);
        } else if (arg.equals("switch_all/")) {
        /*
                 * ZWaveSwitchAllCommandClass switchAllCommandClass =
                 * (ZWaveSwitchAllCommandClass)node.getCommandClass(ZWaveCommandClass.CommandClass.SWITCH_ALL);
                 * if (switchAllCommandClass != null) {
                 * logger.debug("NODE {}: Supports Switch All Command Class Adding Switch All Configuration ",
                 * (Object)nodeId);
                 * record = new OpenHABConfigurationRecord(domain, "Mode", "Mode", true);
                 * record.type = OpenHABConfigurationRecord.TYPE.LIST;
                 * record.addValue("0x00", "Exclude from All On and All Off groups");
                 * record.addValue("0x01", "Include in All On group");
                 * record.addValue("0x02", "Include in All Off group");
                 * record.addValue("0xFF", "Include in All On and All Off groups");
                 * records.add(record);
                 * }
                 */
        } else if (arg.equals("info/")) {
            record = new OpenHABConfigurationRecord(domain, "NodeID", "Node ID", true);
            record.value = Integer.toString(node.getNodeId());
            records.add(record);
            if (node.getManufacturer() != Integer.MAX_VALUE) {
                if (database.FindManufacturer(node.getManufacturer()) == true) {
                    record = new OpenHABConfigurationRecord(domain, "Manufacturer", "Manufacturer", true);
                    record.value = database.getManufacturerName();
                    records.add(record);
                }
                if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) == true) {
                    record = new OpenHABConfigurationRecord(domain, "Product", "Product", true);
                    record.value = database.getProductName();
                    records.add(record);
                }
            }
            record = new OpenHABConfigurationRecord(domain, "ManufacturerID", "Manufacturer ID", true);
            if (node.getDeviceId() == Integer.MAX_VALUE) {
                record.value = "UNKNOWN";
            } else {
                record.value = Integer.toHexString(node.getManufacturer());
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "DeviceID", "Device ID", true);
            if (node.getDeviceId() == Integer.MAX_VALUE) {
                record.value = "UNKNOWN";
            } else {
                record.value = Integer.toHexString(node.getDeviceId());
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "DeviceType", "Device Type", true);
            if (node.getDeviceId() == Integer.MAX_VALUE) {
                record.value = "UNKNOWN";
            } else {
                record.value = Integer.toHexString(node.getDeviceType());
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Version", "Version", true);
            record.value = Integer.toString(node.getVersion());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Listening", "Listening", true);
            record.value = Boolean.toString(node.isListening());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Routing", "Routing", true);
            record.value = Boolean.toString(node.isRouting());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Power", "Power", true);
            ZWaveBatteryCommandClass batteryCommandClass = (ZWaveBatteryCommandClass) node.getCommandClass(CommandClass.BATTERY);
            if (batteryCommandClass != null) {
                if (batteryCommandClass.getBatteryLevel() == null) {
                    record.value = "BATTERY " + "UNKNOWN";
                } else {
                    record.value = "BATTERY " + batteryCommandClass.getBatteryLevel() + "%";
                }
                // If the node is reporting low battery, mark it up...
                if (batteryCommandClass.getBatteryLow() == true) {
                    record.value += " LOW";
                }
            } else if (node.getNodeInitializationStage().getStage() <= ZWaveNodeInitStage.DETAILS.getStage()) {
                // If we haven't passed the DETAILS stage, then we don't know the source
                record.value = "UNKNOWN";
            } else {
                record.value = "MAINS";
            }
            records.add(record);
            ZWaveVersionCommandClass versionCommandClass = (ZWaveVersionCommandClass) node.getCommandClass(CommandClass.VERSION);
            if (versionCommandClass != null) {
                record = new OpenHABConfigurationRecord(domain, "LibType", "Library Type", true);
                if (versionCommandClass.getLibraryType() == null) {
                    record.value = "Unknown";
                } else {
                    record.value = versionCommandClass.getLibraryType().getLabel();
                }
                records.add(record);
                record = new OpenHABConfigurationRecord(domain, "ProtocolVersion", "Protocol Version", true);
                if (versionCommandClass.getProtocolVersion() == null) {
                    record.value = "Unknown";
                } else {
                    record.value = versionCommandClass.getProtocolVersion();
                }
                records.add(record);
                record = new OpenHABConfigurationRecord(domain, "AppVersion", "Application Version", true);
                if (versionCommandClass.getApplicationVersion() == null) {
                    record.value = "Unknown";
                } else {
                    record.value = versionCommandClass.getApplicationVersion();
                }
                records.add(record);
            }
            ZWaveDeviceClass devClass = node.getDeviceClass();
            if (devClass != null) {
                record = new OpenHABConfigurationRecord(domain, "BasicClass", "Basic Device Class", true);
                record.value = devClass.getBasicDeviceClass().toString();
                records.add(record);
                record = new OpenHABConfigurationRecord(domain, "GenericClass", "Generic Device Class", true);
                record.value = devClass.getGenericDeviceClass().toString();
                records.add(record);
                record = new OpenHABConfigurationRecord(domain, "SpecificClass", "Specific Device Class", true);
                record.value = devClass.getSpecificDeviceClass().toString();
                records.add(record);
            }
        } else if (arg.equals("status/")) {
            record = new OpenHABConfigurationRecord(domain, "LastSent", "Last Packet Sent", true);
            if (node.getLastSent() == null) {
                record.value = "NEVER";
            } else {
                record.value = df.format(node.getLastSent());
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "LastReceived", "Last Packet Received", true);
            if (node.getLastReceived() == null) {
                record.value = "NEVER";
            } else {
                record.value = df.format(node.getLastReceived());
            }
            records.add(record);
            if (networkMonitor != null) {
                record = new OpenHABConfigurationRecord(domain, "LastHeal", "Heal Status", true);
                if (node.getHealState() == null) {
                    record.value = networkMonitor.getNodeState(nodeId);
                } else {
                    record.value = node.getHealState();
                }
                records.add(record);
            }
            record = new OpenHABConfigurationRecord(domain, "NodeStage", "Node Stage", true);
            record.value = node.getNodeState() + " " + node.getNodeInitializationStage() + " " + df.format(node.getQueryStageTimeStamp());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Packets", "Packet Statistics", true);
            record.value = node.getRetryCount() + " / " + node.getSendCount();
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Dead", "Dead", true);
            if (node.getDeadCount() == 0) {
                record.value = Boolean.toString(node.isDead());
            } else {
                record.value = Boolean.toString(node.isDead()) + " [" + node.getDeadCount() + " previous - last @ " + df.format(node.getDeadTime()) + "]";
            }
            records.add(record);
        } else if (arg.equals("parameters/")) {
            if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) != false) {
                List<ZWaveDbConfigurationParameter> configList = database.getProductConfigParameters();
                if (configList == null) {
                    return records;
                }
                // Get the configuration command class for this node if it's supported
                ZWaveConfigurationCommandClass configurationCommandClass = (ZWaveConfigurationCommandClass) node.getCommandClass(CommandClass.CONFIGURATION);
                if (configurationCommandClass == null) {
                    return null;
                }
                // Loop through the parameters and add to the records...
                for (ZWaveDbConfigurationParameter parameter : configList) {
                    record = new OpenHABConfigurationRecord(domain, "configuration" + parameter.Index, parameter.Index + ": " + database.getLabel(parameter.Label), false);
                    ConfigurationParameter configurationParameter = configurationCommandClass.getParameter(parameter.Index);
                    // This is the only way we can be sure of its real value
                    if (configurationParameter != null && configurationParameter.getWriteOnly() == false) {
                        record.value = Integer.toString(configurationParameter.getValue());
                    }
                    // If the value is in our PENDING list, then use that instead
                    Integer pendingValue = PendingCfg.Get(ZWaveCommandClass.CommandClass.CONFIGURATION.getKey(), nodeId, parameter.Index);
                    if (pendingValue != null) {
                        record.value = Integer.toString(pendingValue);
                        record.state = OpenHABConfigurationRecord.STATE.PENDING;
                    }
                    try {
                        record.type = OpenHABConfigurationRecord.TYPE.valueOf(parameter.Type.toUpperCase());
                    } catch (IllegalArgumentException e) {
                        record.type = OpenHABConfigurationRecord.TYPE.LONG;
                    }
                    if (parameter.Item != null) {
                        for (ZWaveDbConfigurationListItem item : parameter.Item) {
                            record.addValue(Integer.toString(item.Value), database.getLabel(item.Label));
                        }
                    }
                    // Add any limits
                    record.minimum = parameter.Minimum;
                    record.maximum = parameter.Maximum;
                    // Add the description
                    record.description = database.getLabel(parameter.Help);
                    records.add(record);
                }
            }
        } else if (arg.equals("associations/")) {
            if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) != false) {
                List<ZWaveDbAssociationGroup> groupList = database.getProductAssociationGroups();
                if (groupList == null) {
                    return records;
                }
                // Get the association command class for this node if it's supported
                ZWaveAssociationCommandClass associationCommandClass = (ZWaveAssociationCommandClass) node.getCommandClass(CommandClass.ASSOCIATION);
                if (associationCommandClass == null) {
                    return null;
                }
                // records...
                for (ZWaveDbAssociationGroup group : groupList) {
                    record = new OpenHABConfigurationRecord(domain, "association" + group.Index + "/", database.getLabel(group.Label), true);
                    // Add the description
                    record.description = database.getLabel(group.Help);
                    // For the 'value', describe how many devices are set and the maximum allowed
                    int memberCnt = 0;
                    List<Integer> members = associationCommandClass.getGroupMembers(group.Index);
                    if (members != null) {
                        memberCnt = members.size();
                    }
                    record.value = memberCnt + " of " + group.Maximum + " group members";
                    // Add the action for refresh
                    record.addAction("Refresh", "Refresh");
                    records.add(record);
                }
            }
        } else if (arg.startsWith("associations/association")) {
            if (database.FindProduct(node.getManufacturer(), node.getDeviceType(), node.getDeviceId(), node.getApplicationVersion()) != false) {
                String groupString = arg.substring(24);
                int nextDelimiter = groupString.indexOf('/');
                // String arg = null;
                if (nextDelimiter != -1) {
                    // arg = nodeNumber.substring(nextDelimiter + 1);
                    groupString = groupString.substring(0, nextDelimiter);
                }
                int groupId = Integer.parseInt(groupString);
                // Get the requested group so we have access to the
                // attributes
                List<ZWaveDbAssociationGroup> groupList = database.getProductAssociationGroups();
                if (groupList == null) {
                    return null;
                }
                ZWaveDbAssociationGroup group = null;
                for (int cnt = 0; cnt < groupList.size(); cnt++) {
                    if (groupList.get(cnt).Index == groupId) {
                        group = groupList.get(cnt);
                        break;
                    }
                }
                // Return if the group wasn't found
                if (group == null) {
                    return null;
                }
                // Get the group members
                ZWaveAssociationCommandClass associationCommandClass = (ZWaveAssociationCommandClass) node.getCommandClass(CommandClass.ASSOCIATION);
                // First we build a list of all nodes, starting with the group members
                // This ensures that old nodes included in a group, but not now part
                // of the network will still be listed, and can be removed.
                List<Integer> nodes = new ArrayList<Integer>();
                nodes.addAll(associationCommandClass.getGroupMembers(groupId));
                for (ZWaveNode nodeList : zController.getNodes()) {
                    // Don't allow an association with itself
                    if (nodeList.getNodeId() == node.getNodeId()) {
                        continue;
                    }
                    if (!nodes.contains(nodeList.getNodeId())) {
                        nodes.add(nodeList.getNodeId());
                    }
                }
                // Let's sort them!
                Collections.sort(nodes);
                // Now we loop through the node list and create an entry for each node.
                List<Integer> members = associationCommandClass.getGroupMembers(groupId);
                for (int i = 0; i < nodes.size(); i++) {
                    int nodeNum = nodes.get(i);
                    ZWaveNode nodeList = zController.getNode(nodeNum);
                    // Add the member
                    if (nodeList == null || nodeList.getName() == null || nodeList.getName().isEmpty()) {
                        record = new OpenHABConfigurationRecord(domain, "node" + nodeNum, "Node " + nodeNum, false);
                    } else {
                        record = new OpenHABConfigurationRecord(domain, "node" + nodeNum, nodeList.getName(), false);
                    }
                    record.type = OpenHABConfigurationRecord.TYPE.LIST;
                    record.addValue("true", "Member");
                    record.addValue("false", "Non-Member");
                    if (members != null && members.contains(nodeNum)) {
                        record.value = "true";
                    } else {
                        record.value = "false";
                    }
                    // If the value is in our PENDING list, then use that instead
                    Integer pendingValue = PendingCfg.Get(ZWaveCommandClass.CommandClass.ASSOCIATION.getKey(), nodeId, groupId, nodeNum);
                    if (pendingValue != null) {
                        if (pendingValue == 1) {
                            record.value = "true";
                        } else {
                            record.value = "false";
                        }
                        record.state = OpenHABConfigurationRecord.STATE.PENDING;
                    }
                    records.add(record);
                }
            }
        } else if (arg.equals("wakeup/")) {
            ZWaveWakeUpCommandClass wakeupCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
            if (wakeupCommandClass == null) {
                logger.debug("NODE {}: wakeupCommandClass not supported", nodeId);
                return null;
            }
            // Display the wakeup parameters.
            // Note that only the interval is writable.
            record = new OpenHABConfigurationRecord(domain, "Interval", "Wakeup Interval", false);
            record.minimum = wakeupCommandClass.getMinInterval();
            record.maximum = wakeupCommandClass.getMaxInterval();
            record.value = Integer.toString(wakeupCommandClass.getInterval());
            // If the value is in our PENDING list, then use that instead
            Integer pendingValue = PendingCfg.Get(ZWaveCommandClass.CommandClass.WAKE_UP.getKey(), nodeId);
            if (pendingValue != null) {
                record.value = Integer.toString(pendingValue);
                record.state = OpenHABConfigurationRecord.STATE.PENDING;
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "LastWake", "Last Wakeup", true);
            if (wakeupCommandClass.getLastWakeup() == null) {
                record.value = "NEVER";
            } else {
                record.value = df.format(wakeupCommandClass.getLastWakeup());
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Target", "Target Node", true);
            record.value = Integer.toString(wakeupCommandClass.getTargetNodeId());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Minimum", "Minimum Interval", true);
            record.value = Integer.toString(wakeupCommandClass.getMinInterval());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Maximum", "Maximum Interval", true);
            record.value = Integer.toString(wakeupCommandClass.getMaxInterval());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Default", "Default Interval", true);
            record.value = Integer.toString(wakeupCommandClass.getDefaultInterval());
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "Step", "Interval Step", true);
            record.value = Integer.toString(wakeupCommandClass.getIntervalStep());
            records.add(record);
        } else if (arg.equals("neighbors/")) {
            // Check that we have the neighbor list for this node
            if (node.getNeighbors() == null) {
                return null;
            }
            for (Integer neighbor : node.getNeighbors()) {
                ZWaveNode nodeNeighbor = zController.getNode(neighbor);
                String neighborName;
                if (nodeNeighbor == null) {
                    neighborName = "Node " + neighbor + " (UNKNOWN)";
                } else if (nodeNeighbor.getName() == null || nodeNeighbor.getName().isEmpty()) {
                    neighborName = "Node " + neighbor;
                } else {
                    neighborName = nodeNeighbor.getName();
                }
                // Create the record
                record = new OpenHABConfigurationRecord(domain, "node" + neighbor, neighborName, false);
                record.readonly = true;
                // If this node isn't known, mark it as an error
                if (nodeNeighbor == null) {
                    record.state = OpenHABConfigurationRecord.STATE.ERROR;
                }
                records.add(record);
            }
        } else if (arg.equals("controller/")) {
            // Create the record
            record = new OpenHABConfigurationRecord(domain, "Type", "Controller Type", true);
            record.type = OpenHABConfigurationRecord.TYPE.LIST;
            record.value = zController.getControllerType().getLabel();
            record.addValue(ZWaveDeviceType.PRIMARY.toString(), ZWaveDeviceType.PRIMARY.getLabel());
            record.addValue(ZWaveDeviceType.SECONDARY.toString(), ZWaveDeviceType.SECONDARY.getLabel());
            record.addValue(ZWaveDeviceType.SUC.toString(), ZWaveDeviceType.SUC.getLabel());
            // Set the read-only if this isn't a controller!
            switch(zController.getControllerType()) {
                case SUC:
                case PRIMARY:
                case SECONDARY:
                    record.readonly = true;
                    break;
                default:
                    record.readonly = true;
                    break;
            }
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "APIVersion", "API Version", true);
            record.value = zController.getSerialAPIVersion();
            records.add(record);
            record = new OpenHABConfigurationRecord(domain, "ZWaveVersion", "ZWave Version", true);
            record.value = zController.getZWaveVersion();
            records.add(record);
        }
        return records;
    }
    return null;
}
Also used : ZWaveVersionCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass) ArrayList(java.util.ArrayList) ConfigurationParameter(org.openhab.binding.zwave.internal.protocol.ConfigurationParameter) ZWaveSwitchAllCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSwitchAllCommandClass) ZWaveDeviceClass(org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass) ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveConfigurationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveConfigurationCommandClass) ArrayList(java.util.ArrayList) List(java.util.List) ZWaveBatteryCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveBatteryCommandClass) Date(java.util.Date) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode)

Aggregations

ZWaveAssociationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass)6 ZWaveWakeUpCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)6 ZWaveNode (org.openhab.binding.zwave.internal.protocol.ZWaveNode)4 ZWaveConfigurationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveConfigurationCommandClass)4 ArrayList (java.util.ArrayList)3 ZWaveNodeSerializer (org.openhab.binding.zwave.internal.protocol.initialization.ZWaveNodeSerializer)3 List (java.util.List)2 ConfigurationParameter (org.openhab.binding.zwave.internal.protocol.ConfigurationParameter)2 SerialMessage (org.openhab.binding.zwave.internal.protocol.SerialMessage)2 ZWaveNoOperationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNoOperationCommandClass)2 ZWaveSwitchAllCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSwitchAllCommandClass)2 ZWaveVersionCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass)2 Date (java.util.Date)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 ZWaveDeviceType (org.openhab.binding.zwave.internal.protocol.ZWaveDeviceType)1 ZWaveEndpoint (org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint)1