Developers new to the OpenZWave project are often confused by system behavior immediately after the application is started. I thought I’d quickly write up a blog entry detailing some of what I’ve learned about the system, hopefully this will be of value to OpenZWave developers and/or users.
One common point of confusion among new users is that the system takes some time to initialize. At startup, the application queries the controller and all registered devices for their state and configuration information. Attempting to perform operations on the network during this initialization phase can result in errors or inconsistent/confusing responses. It often comes as a surprise to new users that this phase can take quite some time to complete. Network size, the state of devices on the network, congestion or weak signals, and a plethora of other factors can contribute to long startup times; an average network of Z-Wave devices can take several minutes to initialize.
The initialization phase of OpenZWave can be broken down into twp distinct phases: driver initialization and node initialization.
The first step of initialization is locating the controller, determining its capabilities, and finding all registered (associated) nodes. This phase is broken into five distinct queries.
The response to this query defines which library is in use by the controller and its current version. The response looks similar to the following:
2011-06-01 23:06:02:502 Received reply to FUNC_ID_ZW_GET_VERSION:
2011-06-01 23:06:02:502 Installer library, version Z-Wave 2.78
The response to this query contains the ZWave home ID and the node id of the controller:
2011-06-01 23:06:02:517 Received reply to FUNC_ID_ZW_MEMORY_GET_ID. Home ID = 0x003d8522. Our node ID = 1
Query response indicates the location of the SIS (if present) as well as the primary controller:
2011-06-01 23:06:02:529 Received reply to FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES:
2011-06-01 23:06:02:529 There is no SUC ID Server (SIS) in this network.
2011-06-01 23:06:02:529 The PC controller is a primary controller.
This query determines the ZWave application version as well as details for the controller:
2011-06-01 23:06:02:544 Received reply to FUNC_ID_SERIAL_API_GET_CAPABILITIES
2011-06-01 23:06:02:544 Application Version: 1
2011-06-01 23:06:02:544 Application Revision: 16
2011-06-01 23:06:02:544 Manufacturer ID: 0x001e
2011-06-01 23:06:02:544 Product Type: 0x0001
2011-06-01 23:06:02:544 Product ID: 0x0002
This final driver initialization phase retrieves the list of all included devices to query in the next phase.
2011-06-01 23:06:02:603 Received reply to FUNC_ID_SERIAL_API_GET_INIT_DATA:
2011-06-01 23:06:02:603 Node 001 - New
2011-06-01 23:06:02:603 Node 002 - New
2011-06-01 23:06:02:603 Node 003 - New
2011-06-01 23:06:02:603 Node 004 - New
2011-06-01 23:06:02:603 Node 006 - New
2011-06-01 23:06:02:603 Node 007 - New
2011-06-01 23:06:02:604 Node 008 - New
Phase Completion Notification: DriverReady
At the end of this phase, the system sends a DriverReady notification, followed by NodeNew and/or NodeAdded notifications for each node retrieved via the FUNC_ID_SERIAL_API_GET_INIT_DATA query.
The next initialization phase retrieves basic information about each node retrieved via FUNC_ID_SERIAL_API_GET_INIT_DATA request in the previous phase. This phase is typically very quick, even in large networks.
This query retrieves basic information from each node, including version support, capabilities, device class, and supported command classes:
2011-06-01 23:06:06:009 Received reply to FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO for node 2
2011-06-01 23:06:06:009 Protocol Info for Node 2:
2011-06-01 23:06:06:009 Listening = true
2011-06-01 23:06:06:010 Routing = true
2011-06-01 23:06:06:010 Max Baud Rate = 40000
2011-06-01 23:06:06:010 Version = 2
2011-06-01 23:06:06:010 Security = 0x0c
2011-06-01 23:06:06:010 Node(2) Basic device class (0x04) - Routing Slave
2011-06-01 23:06:06:010 Node(2) Generic device Class (0x11) - Multilevel Switch
2011-06-01 23:06:06:010 Node(2) Specific device class (0x04) - Multilevel Scene Switch
2011-06-01 23:06:06:010 COMMAND_CLASS_BASIC will be mapped to COMMAND_CLASS_SWITCH_MULTILEVEL
2011-06-01 23:06:06:010 Mandatory Command Classes for Node 2:
2011-06-01 23:06:06:010 COMMAND_CLASS_BASIC
2011-06-01 23:06:06:010 COMMAND_CLASS_SWITCH_MULTILEVEL
2011-06-01 23:06:06:010 COMMAND_CLASS_SWITCH_ALL
2011-06-01 23:06:06:010 COMMAND_CLASS_MANUFACTURER_SPECIFIC
2011-06-01 23:06:06:010 Mandatory Command Classes controlled by Node 2:
2011-06-01 23:06:06:011 None
One thing to note here is the automatic mapping of COMMAND_CLASS_BASIC to an appropriate device command class. This allows for uniform control of devices via several API calls, but can cause some issues for GUI/Controller development; see below for more details (TODO: add link here to issue)
A NodeProtocolInfo notification will be sent after the response to this query is received, followed by ValueAdded notifications for each of the node’s reported values. Note that the ValueID reference contained in the notification IS REQUIRED for several of the value-related API calls; see below for more details. (TODO: add link here to issue)
This query requests additional command classes supported by the node.
2011-06-01 23:06:06:145 UPDATE_STATE_NODE_INFO_RECEIVED from node 2
2011-06-01 23:06:06:145 Optional command classes for node 2:
2011-06-01 23:06:06:145 Node(2)::CommandClass 0x2b (COMMAND_CLASS_SCENE_ACTIVATION) - NOT REQUIRED
2011-06-01 23:06:06:145 Node(2)::CommandClass 0x2c (COMMAND_CLASS_SCENE_ACTUATOR_CONF) - NOT REQUIRED
2011-06-01 23:06:06:145 COMMAND_CLASS_ASSOCIATION
2011-06-01 23:06:06:146 COMMAND_CLASS_VERSION
2011-06-01 23:06:06:146 Node(2)::CommandClass 0x91 (COMMAND_CLASS_MANUFACTURER_PROPRIETARY) - NOT REQUIRED
2011-06-01 23:06:06:146 COMMAND_CLASS_NODE_NAMING
2011-06-01 23:06:06:146 COMMAND_CLASS_POWERLEVEL
2011-06-01 23:06:06:146 Optional command classes controlled by node 2:
2011-06-01 23:06:06:146 COMMAND_CLASS_HAIL
ValueAdded notifications are also sent at the end of this query step for library version, protocol version, and application version.
This query requests manufacturer and product information for the node.
2011-06-01 23:06:06:279 Received manufacturer specific report from node 2: Manufacturer=Leviton, Product=VRI06-1L Multilevel Scene Switch
This query requests the specific version for each reported command class for the node.
2011-06-01 23:06:24:773 Received Command Class Version report from node 2: CommandClass=COMMAND_CLASS_BASIC, Version=1
Get Association Groupings
This query retrieves the association groupings for the node. Each device which supports COMMAND_CLASS_ASSOCIATION defines one or more groups; the functional meaning of each group is device specific; check device documentation for details. For example, the Leviton VRI06-1L dimmer specifies one group; members of this group will receive notifications when the dimming level changes.
2011-06-01 23:06:26:257 Received Association Groupings report from node 2. Number of groups is 1
Retrieves the Node’s version information
2011-06-01 23:06:26:289 Received Version report from node 2: Library=3, Protocol=2.09, Application=0.04
ValueChanged notifications will also be sent once the query result is returned from the node.
This query is sent for each of the association groupings returned via the “Get Association Groupings” query above.
2011-06-01 23:06:26:418 Received Association report from node 2, group 1, containing 1 associations
2011-06-01 23:06:26:418 The group contains:
2011-06-01 23:06:26:418 Node 1
A Group notification is sent for each result returned via this query.
This query retrieves the “Neighbor” nodes for the specified node. This information is used by the ZWave network for routing messages from device to device.
2011-06-01 23:06:26:529 Received reply to FUNC_ID_ZW_GET_ROUTING_INFO
2011-06-01 23:06:26:529 Neighbors of this node are:
2011-06-01 23:06:26:529 Node 3
2011-06-01 23:06:26:529 Node 4
2011-06-01 23:06:26:530 Node 6
2011-06-01 23:06:26:530 Node 7
Static and Dynamic Node Queries
Depending upon the command classes supported by the node, the system will query the node for static information (node name, supported states) and dynamic values (current level, switch setting, etc). Examples are omitted here for the sake of brevity.
Once the processing has completed for a given node, a NodeQueriesComplete notification is sent out for the node.
Once the node initialization is complete for all active nodes, one of two notifications is sent:
- AllNodesQueried is sent if all nodes were awake (iow none were sleeping) during initialization
- AwakeNodesQueried is sent if one or more nodes were asleep (or otherwise unresponsive) during initialization.
At this point the system has been initialized and is ready to control.
I hope people find this post helpful. If you have any questions or feedback, please leave a comment!