public void init() { queue.sendMsg(Msg.createZWaveGetVersion((byte) 0xFF), QueuePriority.Command); queue.sendMsg(Msg.createZWaveMemoryGetId((byte) 0xFF), QueuePriority.Command); queue.sendMsg(Msg.createZWaveGetControllerCapabilities((byte) 0xFF), QueuePriority.Command); queue.sendMsg(Msg.createZWaveSerialAPIGetCapabilities((byte) 0xFF), QueuePriority.Command); queue.sendMsg(Msg.createZWaveGetSUCNodeId((byte) 0xFF), QueuePriority.Command); }
private boolean handleErrorResponse(byte error, byte nodeId, String funcStr, boolean sleepcheck) { Node node = getNode(nodeId); if (error == Defs.TRANSMIT_COMPLETE_NOROUTE) { logs.add(String.format("Error: %s failed. No route found.", funcStr)); // if (node != null) { // node.setNodeAlive(false); // } } else if (error == Defs.TRANSMIT_COMPLETE_NO_ACK) { logs.add(String.format("Error: %s failed. No ACK found.", funcStr)); if (queue.getCurrentMsg() != null) { if (moveMsgToWakeUpQueue(SafeCast.nodeIdFromMsg(queue.getCurrentMsg()), sleepcheck)) { return true; } } } else if (error == Defs.TRANSMIT_COMPLETE_FAIL) { logs.add(String.format("Error: %s failed. Network busy.", funcStr)); } else if (error == Defs.TRANSMIT_COMPLETE_NOT_IDLE) { logs.add(String.format("Error: %s failed. Network busy.", funcStr)); } if (node != null && node.incErrorCount() >= 3) { node.setNodeAlive(false); } return false; }
public void handleApplicationCommandHandlerRequest(byte[] data) { byte status = data[2]; byte nodeId = data[3]; byte classId = data[5]; Node node = getNode(nodeId); if ((status & Defs.RECEIVE_STATUS_ROUTED_BUSY) != 0) {} if ((status & Defs.RECEIVE_STATUS_TYPE_BROAD) != 0) { /* receive 500ms */ } if (node != null) { if (queue.getExpectedReply() == Defs.FUNC_ID_APPLICATION_COMMAND_HANDLER && queue.getExpectedNodeId() == nodeId) { // update RTT } else { // received unsolicited } } if ((byte) 0x22 == classId) { // TODO: Test this class function or implement } else if ((byte) 0x21 == classId) { // TODO: Test this class function or implement } else if (node != null) { node.applicationCommandHandler(data); } }
public boolean handleApplicationUpdateRequest(byte[] data) { boolean messageRemoved = false; byte nodeId = data[3]; Node node = getNode(nodeId); Node tnode = null; if (node != null && !node.isNodeAlive()) { node.setNodeAlive(true); } switch (data[2]) { case Defs.UPDATE_STATE_SUC_ID: logs.add(String.format("Update SUC Id node %d", SafeCast.toInt(nodeId))); sucNodeId = nodeId; break; case Defs.UPDATE_STATE_DELETE_DONE: logs.add(String.format("Remove node %d", SafeCast.toInt(nodeId))); removeNode(nodeId); break; case Defs.UPDATE_STATE_NEW_ID_ASSIGNED: logs.add(String.format("Add node %d", SafeCast.toInt(nodeId))); addNode(nodeId); break; case Defs.UPDATE_STATE_ROUTING_PENDING: logs.add(String.format("Routing pending node %d", nodeId)); break; case Defs.UPDATE_STATE_NODE_INFO_REQ_FAILED: if (queue.getCurrentMsg() != null) { logs.add( String.format( "Update failed node %d", SafeCast.nodeIdFromMsg(queue.getCurrentMsg()))); tnode = getNode(SafeCast.nodeIdFromMsg(queue.getCurrentMsg())); if (tnode != null) { tnode.queryStageRetry(QueryStage.NodeInfo, (byte) 2); if (moveMsgToWakeUpQueue(tnode.getNodeId(), true)) { messageRemoved = true; } } } break; case Defs.UPDATE_STATE_NODE_INFO_REQ_DONE: logs.add(String.format("Update done node %d", nodeId)); break; case Defs.UPDATE_STATE_NODE_INFO_RECEIVED: logs.add(String.format("Update info receive node %d", nodeId)); if (node != null) { node.updateNodeInfo( Arrays.copyOfRange(data, 8, data.length), (byte) ((SafeCast.toInt(data[4]) - 3))); } break; } if (messageRemoved) { queue.removeExpectedAndACK(); } return messageRemoved; }
public void handleGetSerialAPICapabilitiesResponse(byte[] data) { primaryController.setSerialAPIVersion(new byte[] {data[2], data[3]}); primaryController.setManufacturerShortId( (short) (SafeCast.toShort(data[4]) << 8 | SafeCast.toShort(data[5]))); primaryController.setProductShortType( (short) (SafeCast.toShort(data[6]) << 8 | SafeCast.toShort(data[7]))); primaryController.setProductShortId( (short) (SafeCast.toShort(data[8]) << 8 | SafeCast.toShort(data[9]))); primaryController.setApiMask(Arrays.copyOfRange(data, 10, 32)); logs.add( String.format( "FUNC_ID_SERIAL_API_GET_CAPABILITIES -- Serial API: v%d.%d," + " Man. Id = 0x%04x, Prod. Type = 0x%04x, Prod. Id = 0x%04x", primaryController.getSerialAPIVersion()[0], primaryController.getSerialAPIVersion()[1], primaryController.getManufacturerShortId(), primaryController.getProductShortType(), primaryController.getProductShortId())); Msg msg; if (primaryController.isBridgeController()) { msg = new Msg((byte) 0xFF, Defs.REQUEST, Defs.FUNC_ID_ZW_GET_VIRTUAL_NODES, false); queue.sendMsg(msg, QueuePriority.Command); } else if (primaryController.isAPICallSupported(Defs.FUNC_ID_ZW_GET_RANDOM)) { msg = new Msg((byte) 0xFF, Defs.REQUEST, Defs.FUNC_ID_ZW_GET_RANDOM, false); msg.append((byte) 32); queue.sendMsg(msg, QueuePriority.Command); } msg = new Msg((byte) 0xFF, Defs.REQUEST, Defs.FUNC_ID_SERIAL_API_GET_INIT_DATA, false); queue.sendMsg(msg, QueuePriority.Command); msg = new Msg( (byte) 0xFF, Defs.REQUEST, Defs.FUNC_ID_SERIAL_API_APPL_NODE_INFORMATION, false, false); msg.appends(new byte[] {Defs.APPLICATION_NODEINFO_LISTENING, 0x02, 0x01, 0x01, 0x2B}); // msg.appends(new byte[] { Defs.APPLICATION_NODEINFO_LISTENING, 0x02, // 0x01, 0x00 }); queue.sendMsg(msg, QueuePriority.Command); }
public void handleGetRoutingInfoResponse(byte[] data) { Node node = getNode(SafeCast.nodeIdFromMsg(queue.getCurrentMsg())); if (node != null) { node.setNeighbors(Arrays.copyOfRange(data, 2, 29)); logs.add( String.format( "FUNC_ID_ZW_GET_ROUTING_INFO -- Neighbors of node %d are:", node.getNodeId())); boolean neighbors = false; for (int i = 0; i < 29; i++) { for (int j = 0; j < 8; j++) { if ((data[2 + i] & (0x01 << j)) != 0) { logs.add(String.format("--- Node %d", (i << 3) + j + 1)); neighbors = true; } } } if (!neighbors) { logs.add(String.format("no neighbor on node %d", node.getNodeId())); } } }
// ----------------------------------------------------------------------------------------- // Request Methods // ----------------------------------------------------------------------------------------- public void handleSendDataRequest(byte[] data, boolean replication) { byte nodeId = SafeCast.nodeIdFromMsg(queue.getCurrentMsg()); if (data[2] != queue.getExpectedCallbackId()) { logs.add( String.format( "Unexpected callback id: received %d != %d", SafeCast.toInt(data[2]), SafeCast.toInt(queue.getExpectedCallbackId()))); } else { Node node = getNode(nodeId); if (node != null && queue.getCurrentMsg() != null) { if (data[3] != 0) { if (!handleErrorResponse( data[3], nodeId, replication ? "ZW_REPLICATION_END_DATA" : "ZW_SEND_DATA", !replication)) { if (queue.getCurrentMsg().isNoOperation() && (node.getQueryStage() == QueryStage.Probe1 || node.getQueryStage() == QueryStage.Probe2)) { node.queryStageRetry(node.getQueryStage(), (byte) 3); } } } else { if (queue.getCurrentMsg().isWakeUpNoMoreInformationCommand()) { WakeUp wu = (WakeUp) node.getCommandClassManager().getCommandClass(WakeUp.COMMAND_CLASS_ID); if (wu != null) { wu.setAwake(false); } } if (!node.isNodeAlive()) { node.setNodeAlive(true); } } } queue.setExpectedCallbackId((byte) 0); } }
private void commonAddNodeStatusRequestHandler(byte funcId, byte[] data) { ControllerCmd cci = queue.getCurrentControllerCmd(); ControllerState state = ControllerState.Normal; if (cci != null) { state = cci.getControllerState(); } switch (data[3]) { case Defs.ADD_NODE_STATUS_LEARN_READY: logs.add("ADD_NODE_STATUS_LEARN_READY"); if (cci != null) { cci.setControllerAdded(false); } state = ControllerState.Waiting; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } break; case Defs.ADD_NODE_STATUS_NODE_FOUND: logs.add("ADD_NODE_STATUS_NODE_FOUND"); state = ControllerState.InProgress; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } break; case Defs.ADD_NODE_STATUS_ADDING_SLAVE: logs.add("ADD_NODE_STATUS_ADDING_SLAVE --- Node: " + String.valueOf(data[4])); if (cci != null) { cci.setControllerAdded(false); cci.setControllerCommandNode(data[4]); } break; case Defs.ADD_NODE_STATUS_ADDING_CONTROLLER: logs.add("ADD_NODE_STATUS_ADDING_CONTROLLER --- Node: " + String.valueOf(data[4])); if (cci != null) { cci.setControllerAdded(true); cci.setControllerCommandNode(data[4]); } break; case Defs.ADD_NODE_STATUS_PROTOCOL_DONE: logs.add("ADD_NODE_STATUS_PROTOCOL_DONE"); primaryController.addNodeStop(funcId); break; case Defs.ADD_NODE_STATUS_DONE: logs.add("ADD_NODE_STATUS_DONE"); state = ControllerState.Completed; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } if (cci != null && cci.getControllerCommandNode() != (byte) 0xFF) { addNode(cci.getControllerCommandNode()); } if (funcId != Defs.FUNC_ID_ZW_ADD_NODE_TO_NETWORK && cci != null && cci.isControllerAdded()) { initAllNodes(); } break; case Defs.ADD_NODE_STATUS_FAILED: logs.add("ADD_NODE_STATUS_FAILED"); state = ControllerState.Failed; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } queue.removeCurrentMsg(); primaryController.addNodeStop(funcId); break; default: logs.add("No detected ..."); break; } primaryController.updateControllerState(state); }
public void handleRemoveNodeFromNetworkRequest(byte[] data) { ControllerCmd cci = queue.getCurrentControllerCmd(); if (cci == null) { return; } ControllerState state = cci.getControllerState(); switch (data[3]) { case Defs.REMOVE_NODE_STATUS_LEARN_READY: logs.add("REMOVE_NODE_STATUS_LEARN_READY"); state = ControllerState.Waiting; cci.setControllerCommandNode((byte) 0); if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } break; case Defs.REMOVE_NODE_STATUS_NODE_FOUND: logs.add("REMOVE_NODE_STATUS_NODE_FOUND"); state = ControllerState.InProgress; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } break; case Defs.REMOVE_NODE_STATUS_REMOVING_SLAVE: logs.add("REMOVE_NODE_STATUS_REMOVING_SLAVE --- Node: " + String.valueOf(data[4])); cci.setControllerCommandNode(data[4]); break; case Defs.REMOVE_NODE_STATUS_REMOVING_CONTROLLER: logs.add("REMOVE_NODE_STATUS_REMOVING_CONTROLLER --- Node: " + String.valueOf(data[4])); // mCurrentControllerCommand.mControllerCommandNode = data[4]; cci.setControllerCommandNode(data[4]); if (data[4] == (byte) 0) { if (data[5] >= 3) { for (int i = 0; i < Defs.MAX_TOTAL_NODES; i++) { Node node = getNode((byte) i); synchronized (node) { if (node == null || primaryController == null) { continue; } if (node.getNodeId() == primaryController.getNodeId()) { continue; } // Ignore primary controller // See if we can match another way if (node.getBasicDeviceClassID() == data[6] && node.getGenericDeviceClassID() == data[7] && node.getSpecificDeviceClassID() == data[8]) { if (cci.getControllerCommandNode() != 0) { // TODO: Alternative controller found } else { cci.setControllerCommandNode(node.getNodeId()); } } } } } else { // TODO: error message not enough data } } else { cci.setControllerCommandNode(data[4]); } break; case Defs.REMOVE_NODE_STATUS_DONE: logs.add("REMOVE_NODE_STATUS_DONE"); state = ControllerState.Completed; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } if (!cci.isControllerCommandDone()) { primaryController.updateControllerState(ControllerState.Completed); primaryController.addNodeStop(Defs.FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK); if (cci.getControllerCommandNode() == (byte) 0) { if (data[4] != (byte) 0) { cci.setControllerCommandNode(data[4]); } } if (cci.getControllerCommandNode() != (byte) 0 && cci.getControllerCommandNode() != (byte) 0xFF) { removeNode(cci.getControllerCommandNode()); } } return; case Defs.REMOVE_NODE_STATUS_FAILED: logs.add("REMOVE_NODE_STATUS_FAILED"); primaryController.addNodeStop(Defs.FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK); state = ControllerState.Failed; if (cci != null && cci.getControllerCallback() != null) { cci.getControllerCallback().onAction(state, null, null); } break; default: logs.add("No Detected ..."); break; } primaryController.updateControllerState(state); }
public boolean moveMsgToWakeUpQueue(byte targetNodeId, boolean move) { Node node = getNode(targetNodeId); if (node != null && !node.isListeningDevice() && !node.isFrequentListeningDevice() && primaryController != null && targetNodeId != primaryController.getNodeId()) { WakeUp wu = (WakeUp) node.getCommandClassManager().getCommandClass(WakeUp.COMMAND_CLASS_ID); if (wu != null) { wu.setAwake(false); if (move) { if (queue.getCurrentControllerCmd() != null) { queue.removeCurrentMsg(); } if (queue.getCurrentMsg() != null) { Msg msg = queue.getCurrentMsg(); if (targetNodeId == SafeCast.nodeIdFromMsg(msg)) { if (!msg.isWakeUpNoMoreInformationCommand() && !msg.isNoOperation()) { QueueItem item = new QueueItem(); item.setCommand(QueueCommand.SendMessage); item.setMsg(msg); wu.queueItem(item); } queue.removeCurrentMsg(); } } for (int i = 0; i < queue.size(); ++i) { Iterator<QueueItem> iter = queue.getQueue().iterator(); while (iter.hasNext()) { boolean remove = false; QueueItem it = iter.next(); if (it.getCommand() == QueueCommand.SendMessage && targetNodeId == SafeCast.nodeIdFromMsg(it.getMsg())) { if (!it.getMsg().isWakeUpNoMoreInformationCommand() && !it.getMsg().isNoOperation()) { wu.queueItem(it); } else { it.setMsg(null); } remove = true; } else if (it.getCommand() == QueueCommand.QueryStageComplete && targetNodeId == SafeCast.nodeIdFromMsg(it.getMsg())) { wu.queueItem(it); remove = true; } else if (it.getCommand() == QueueCommand.Controller && targetNodeId == SafeCast.nodeIdFromMsg(it.getMsg())) { wu.queueItem(it); remove = true; } if (remove) { iter.remove(); } } } if (queue.getCurrentControllerCmd() != null) { primaryController.updateControllerState(ControllerState.Sleeping); queue.sendControllerCommand(queue.getCurrentControllerCmd()); } return true; } } } return false; }