In Zilker, Device Service is responsible for the management and interactions with all devices. Devices can connect with various protocols and technologies including Zigbee and OpenHome (with BLE, Thread, CHIP, and others possible in the future). Note that much of the discussion in this documentation is about Zigbee devices, but many of the concepts applies to devices on other technologies. Devices belong to a Device Class which defines the type of device. Some examples of Device Classes are Light, Door Lock, and Sensor (and many others). Each Device Class supports one or more endpoints, each of which supports an Endpoint Profile. An endpoint on a device can be thought of as a port number in networking. An endpoint provides a logical set of functionality such as a light switch.
Devices are exposed to clients as a set of resources that can be read, written, and executed depending on their type and purpose. More details on how devices are composed and how to interact with their resources are below.
Device Service's log file can be found in /tmp/logs/xhDeviceService.log on devices other than gateways. For gateways the entire stack (except ZigbeeCore) log to /rdklogs/logs/ZilkerLog.txt.
Devices that are allowed in our ecosystem are vetted by our Ecosystem team which works with vendors to ensure their device is well behaved and tested. Once a device passes our certification a Device Descriptor is created for it and it is added to an 'allow list' (also known as the Whitelist). This list is published to a content server and downloaded by Zilker when it changes.
When a Zigbee device joins our network as part of the pairing process Zilker reads its manufacturer name, model, hardware version, and firmware version. These 4 attributes are used to locate the appropriate Device Descriptor. If no Descriptor is found, the device is rejected and told to leave the network. An example of a Device Descriptor is:
<DeviceDescriptor>
<uuid>f7d49c2b-7324-4857-96eb-cdee9a44d996</uuid>
<description>ZigBee_Gen2_PIR_Std</description>
<category>zigbee</category>
<manufacturer>Bosch</manufacturer>
<model>RFPR-ZB-MS</model>
<hardwareVersions>19</hardwareVersions>
<firmwareVersions>0x21115401,0x22115401,0x23115401,0x23125401,0x23125402</firmwareVersions>
<latestFirmware>
<version>0x23125402</version>
<filename>Bosch_Motion_G2_V23125402.ota</filename>
<type>ota</type>
</latestFirmware>
</DeviceDescriptor>
As shown, the Device Descriptor also contains information about the latest firmware for the device. This is downloaded and supplied to the device if it needs a firmware upgrade.
As previously described, devices use a URI based resource model to expose functionality. One architectural goal of the resource model is to hide the underlying technology that the device uses (Zigbee, BLE, etc.). This allows clients of devices to function without change against devices of any class and to get automatic support for new devices once new subsystems and device drivers are added.
Here are example resources and their values for a door/window sensor:
000d6f000f486af8: Bedroom 1 Window 2, Class: sensor
/000d6f000f486af8/r/battVolts = 2700
/000d6f000f486af8/r/communicationFailure = true
/000d6f000f486af8/r/dateAdded = 1575386127578
/000d6f000f486af8/r/dateLastContacted = 1579810368616
/000d6f000f486af8/r/feLqi = 255
/000d6f000f486af8/r/feRssi = -84
/000d6f000f486af8/r/firmwareUpdateStatus = (null)
/000d6f000f486af8/r/firmwareVersion = 0x20190422
/000d6f000f486af8/r/hardwareVersion = 1
/000d6f000f486af8/r/lowBatt = false
/000d6f000f486af8/r/manufacturer = Universal Electronics Inc
/000d6f000f486af8/r/model = URC4460BC0-X-R
/000d6f000f486af8/r/neLqi = 243
/000d6f000f486af8/r/neRssi = -54
/000d6f000f486af8/r/resetToFactoryDefaults = (null)
/000d6f000f486af8/r/temp = 1900
Endpoint 1: Profile: sensor
/000d6f000f486af8/ep/1/r/bypassed = false
/000d6f000f486af8/ep/1/r/faulted = false
/000d6f000f486af8/ep/1/r/label = Bedroom 1 Window 2
/000d6f000f486af8/ep/1/r/qualified = true
/000d6f000f486af8/ep/1/r/tampered = false
/000d6f000f486af8/ep/1/r/type = contactSwitch
Some resources are read-only such as /000d6f000f486af8/r/battVolts. Some resources are executable such as /000d6f000f486af8/r/resetToFactoryDefaults. Resources like /000d6f000f486af8/ep/1/r/label are read-writable.
Most resources will emit events when they change (broadcast locally from Device Service to other interested services). In this example when the door/window sensor is opened /000d6f000f486af8/ep/1/r/faulted will change to 'true' and SecurityService will get notified to take appropriate action.
Note that the relationship between resources and Zigbee attributes is not always 1:1.
Device Drivers are bits of code responsible for the mapping of resources to functionality on a device. The current set of drivers available in Zilker are:
- openHomeCamera
- philipsHue
- xbb
- zigbeeDoorLock
- zigbeeLegacyLight
- zigbeeLegacySecurityController
- zigbeeLegacySensor
- zigbeeLegacySirenRepeater
- zigbeeLight
- zigbeeLightController
- zigbeePresence
- zigbeeSecurityController
- zigbeeSensor
- zigbeeThermostat
- zigbeeWindowCovering
Drivers are responsible for the configuration of a device (performed during pairing), creation of its resources, and reacting to changes from the device and to its resources.
Subsystems in Device Service provide access to lower level parts of the stack in a manner safe for concurrent use by device drivers. Currently Zilker has a subsystem for Zigbee. Future subsystems for BLE, CHIP, and Thread are possible.
Device Service stores all of its configuration in /opt/etc/storage/devicedb (on RDK devices it is /nvram/icontrol/etc/storage/devicedb). An example directory listing is:
000d6f000f2081e7 000d6f000f4839e3 000d6f000f4877bc 000d6f0010abe463 systemProperties
000d6f000f4525fb 000d6f000f486af8 000d6f000f6ca643 6cc1d2000052829b
Note that there will also be backup versions of these files ending in .bak which were omitted here.
Each file, other than systemProperties represents a single device. For Zigbee devices the filenames are EUI64s for the corresponding device. Below is an example of a Zigbee sensor's database file contents.
{
"deviceDriver": "ZigBeeSensorDD",
"deviceClass": "sensor",
"deviceClassVersion": 1,
"uri": "/000d6f000f2081e7",
"uuid": "000d6f000f2081e7",
"deviceEndpoints": {
"1": {
"uri": "/000d6f000f2081e7/ep/1",
"id": "1",
"profile": "sensor",
"enabled": true,
"profileVersion": 0,
"resources": {
"faulted": {
"id": "faulted",
"uri": "/000d6f000f2081e7/ep/1/r/faulted",
"mode": 57,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "false",
"type": "com.icontrol.boolean"
},
"qualified": {
"id": "qualified",
"uri": "/000d6f000f2081e7/ep/1/r/qualified",
"mode": 1,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "true",
"type": "com.icontrol.boolean"
},
"bypassed": {
"id": "bypassed",
"uri": "/000d6f000f2081e7/ep/1/r/bypassed",
"mode": 35,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "false",
"type": "com.icontrol.boolean"
},
"type": {
"id": "type",
"uri": "/000d6f000f2081e7/ep/1/r/type",
"mode": 1,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "motion",
"type": "com.icontrol.sensorType"
},
"tampered": {
"id": "tampered",
"uri": "/000d6f000f2081e7/ep/1/r/tampered",
"mode": 57,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "false",
"type": "com.icontrol.boolean"
},
"label": {
"id": "label",
"uri": "/000d6f000f2081e7/ep/1/r/label",
"mode": 59,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "Master Bedroom Motion",
"type": "com.icontrol.label"
}
},
"metadatas": {
"zigbee_epid": {
"id": "zigbee_epid",
"uri": "/000d6f000f2081e7/ep/1/m/zigbee_epid",
"value": "1"
},
"migratedUserProperties": {
"id": "migratedUserProperties",
"uri": "/000d6f000f2081e7/ep/1/m/migratedUserProperties",
"value": {
"Zone.SensorId": "29",
"Zone.FunctionType": "10",
"Zone.ZoneType": "3",
"orderIndex": "18",
"Zone.Edited": "true",
"Zone.Bypassed": "false",
"Zone.TestMode": "false",
"NearEndLqi": "255",
"Zone.ZoneNumber": "32",
"label": "Master Bedroom Motion",
"NearEndRssi": "-54",
"Zone.SwingerShutdown": "false",
"IASZoneStatus": "32"
}
},
"migrationAlias": {
"id": "migrationAlias",
"uri": "/000d6f000f2081e7/ep/1/m/migrationAlias",
"value": "000d6f000f2081e7.1"
},
"secZone": {
"id": "secZone",
"uri": "/000d6f000f2081e7/ep/1/m/secZone",
"value": {
"zoneNumber": 32,
"sensorId": 29,
"displayIndex": 5,
"isTroubled": false,
"isConfigured": true,
"inSwingerShutdown": false,
"isInTestMode": false,
"isWirelessDevice": false,
"isBatteryDevice": false,
"hasTemperature": false,
"zoneType": 3,
"zoneFunction": 10,
"zoneMute": 0
}
}
}
}
},
"deviceResources": {
"manufacturer": {
"id": "manufacturer",
"uri": "/000d6f000f2081e7/r/manufacturer",
"mode": 1,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "Visonic",
"type": "com.icontrol.string"
},
"model": {
"id": "model",
"uri": "/000d6f000f2081e7/r/model",
"mode": 1,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "MP-841",
"type": "com.icontrol.string"
},
"hardwareVersion": {
"id": "hardwareVersion",
"uri": "/000d6f000f2081e7/r/hardwareVersion",
"mode": 1,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "1",
"type": "com.icontrol.version"
},
"firmwareVersion": {
"id": "firmwareVersion",
"uri": "/000d6f000f2081e7/r/firmwareVersion",
"mode": 57,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "0x00000025",
"type": "com.icontrol.version"
},
"firmwareUpdateStatus": {
"id": "firmwareUpdateStatus",
"uri": "/000d6f000f2081e7/r/firmwareUpdateStatus",
"mode": 57,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "upToDate",
"type": "com.icontrol.firmwareVersionStatus"
},
"dateAdded": {
"id": "dateAdded",
"uri": "/000d6f000f2081e7/r/dateAdded",
"mode": 1,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "1516290469399",
"type": "com.icontrol.dateTime"
},
"dateLastContacted": {
"id": "dateLastContacted",
"uri": "/000d6f000f2081e7/r/dateLastContacted",
"mode": 89,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "1579809077821",
"type": "com.icontrol.dateTime"
},
"communicationFailure": {
"id": "communicationFailure",
"uri": "/000d6f000f2081e7/r/communicationFailure",
"mode": 57,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 1582149774116,
"value": "true",
"type": "com.icontrol.trouble"
},
"resetToFactoryDefaults": {
"id": "resetToFactoryDefaults",
"uri": "/000d6f000f2081e7/r/resetToFactoryDefaults",
"mode": 4,
"cachingPolicy": 0,
"dateOfLastSyncMillis": 0,
"type": "com.icontrol.resetToFactoryOperation"
},
"feRssi": {
"id": "feRssi",
"uri": "/000d6f000f2081e7/r/feRssi",
"mode": 89,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "-51",
"type": "rssi"
},
"feLqi": {
"id": "feLqi",
"uri": "/000d6f000f2081e7/r/feLqi",
"mode": 89,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "255",
"type": "lqi"
},
"neRssi": {
"id": "neRssi",
"uri": "/000d6f000f2081e7/r/neRssi",
"mode": 89,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "-54",
"type": "rssi"
},
"neLqi": {
"id": "neLqi",
"uri": "/000d6f000f2081e7/r/neLqi",
"mode": 89,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "255",
"type": "lqi"
},
"temp": {
"id": "temp",
"uri": "/000d6f000f2081e7/r/temp",
"mode": 89,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "1900",
"type": "com.icontrol.temperature"
},
"lowBatt": {
"id": "lowBatt",
"uri": "/000d6f000f2081e7/r/lowBatt",
"mode": 57,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "false",
"type": "com.icontrol.boolean"
},
"battVolts": {
"id": "battVolts",
"uri": "/000d6f000f2081e7/r/battVolts",
"mode": 121,
"cachingPolicy": 1,
"dateOfLastSyncMillis": 0,
"value": "3000",
"type": "battery.voltage"
}
},
"metadatas": {
"discoveredDetails": {
"id": "discoveredDetails",
"uri": "/000d6f000f2081e7/m/discoveredDetails",
"value": {
"eui64": "000d6f000f2081e7",
"manufacturer": "Visonic",
"model": "MP-841",
"hwVer": 1,
"fwVer": 37,
"appVer": 1,
"type": "unknown",
"power": "unknown",
"endpoints": [{
"id": 1,
"profileId": 260,
"deviceId": 1026,
"deviceVer": 0,
"serverClusterInfos": [{
"id": 2821,
"isServer": true,
"attributeIds": [283, 284, 285]
}, {
"id": 0,
"isServer": true,
"attributeIds": [0, 1, 2, 3, 4, 5, 7]
}, {
"id": 1,
"isServer": true,
"attributeIds": [62, 32, 49, 51, 54, 55, 56, 57]
}, {
"id": 32,
"isServer": true,
"attributeIds": [1, 2, 3, 4, 6, 0]
}, {
"id": 1280,
"isServer": true,
"attributeIds": [0, 16, 1, 17, 2]
}, {
"id": 3,
"isServer": true,
"attributeIds": [0]
}, {
"id": 1026,
"isServer": true,
"attributeIds": [0, 1, 2]
}],
"clientClusterInfos": [{
"id": 25,
"isServer": false,
"attributeIds": [0, 1, 2, 4, 6, 7, 8, 9, 10]
}]
}]
}
},
"migratedDevice": {
"id": "migratedDevice",
"uri": "/000d6f000f2081e7/m/migratedDevice",
"value": "true"
},
"lpmPolicy": {
"id": "lpmPolicy",
"uri": "/000d6f000f2081e7/m/lpmPolicy",
"value": "armedAway"
},
"troubles": {
"id": "troubles",
"uri": "/000d6f000f2081e7/m/troubles",
"value": {
"32548": {
"_evId": 32543,
"_evCode": 255,
"_evVal": 0,
"_evTime": 1582149774139,
"troubleEvent": {
"trouble": {
"troubleObj": {
"description": "sensor TROUBLE_REASON_COMM_FAIL",
"eventId": 32543,
"troubleId": 32548,
"acknowledged": false,
"restored": false,
"treatAsLifeSafety": false,
"eventTime": 1582149774139,
"type": 5,
"reason": 4,
"critical": 2,
"indicationGroup": 1,
"indication": 3,
"extra": {
"rootId": "000d6f000f2081e7",
"ownerUri": "/000d6f000f2081e7",
"resourceUri": "/000d6f000f2081e7/r/communicationFailure",
"deviceClass": "sensor",
"zoneNumber": 32,
"zoneType": 3,
"alarmArmType": 0,
"alarmStatusType": 0
}
}
},
"panelStatus": {
"systemPanelStatus": {
"testModeSecsRemaining": 0,
"trouble": true,
"bypassActive": false,
"alarmStatus": 2,
"armMode": 0
}
},
"alarm": {
"alarmDetails": {
"contactId": "138101005",
"alarmSessionId": 0,
"sendImmediately": false,
"isZoneInSwingerShutdown": false,
"isDuressCodeAlarm": false,
"isExitError": false,
"isRecentClosing": false,
"isWithinCancelWindow": false,
"isZonesFaulted": false,
"alarmReason": 0
}
}
}
}
}
}
}
}
The systemProperties file contains some Device Service specific configuration details. For example:
{
"ZIGBEE_INCREMENT_COUNTERS_ON_NEXT_INIT": "false",
"zigbeeTelemetryStartDate": "1588944626812",
"currentDeviceDescriptorUrl": "https://pod-bundle.beta.xhsyndication.com/bundle/lists/ConvergeDevicesAllowed20200624-Beta.xml",
"currentBlacklistMd5": "e4999307cad3e2df24e46a0e4245a725",
"ZIGBEE_NETWORK_CONFIG_DATA": "oxMAAAQQAAAULkZFblsJTyShkzLZS/SvAAAAAAAAAAAAAAAAAAAAAAAAKUQDGQIBAABZsmTDjXOEauQQwl8Pn4utGwCaC297bXQGPhLSmvl/jF0KAPj/BwAAAAA=",
"ZIGBEE_LOCAL_EUI64": "001bad8b9f0f5fc2",
"schemaVersion": "1",
"ZIGBEE_REJECT_UNKNOWN_DEVICES": "true",
"currentBlacklistUrl": "http://pod-bundle.beta.xhsyndication.com/bundle/lists/blacklist-nothing.xml",
"deviceDescriptorBypass": "false",
"currentDeviceDescriptorMd5": "95c55b67c9cfe93318be19c7a6eab752"
}
Device Service has a component that is responsible for detecting communication failure with the devices it manages. Once the Device Communication Watchdog determines that a device is in communication failure, the device's communicationFailure resource (/000d6f000f486af8/r/communicationFailure from the example device earlier) is set to "true". This triggers a resource changed event that is handled by Security Service which creates a trouble that gets reported to the server through Comm Service.
For Zigbee devices, the watchdog tracks the amount of time since the last successful message to or from the device. By default the watchdog will report communication failure after 1 hour without any successful communication. This allows for two missed checkin intervals, which are configured for 27 minutes. Some devices use different failure detection intervals.
Once Device Service reports a security related device is in communication failure, Security Service's logic takes over and the event may not be reported to the server until logic covered by CPE properties "touchscreen.sensor.commFail.troubleDelay" and/or "touchscreen.sensor.commFail.alarmDelay" take over.
These components are in the xhfw/zigbee git repository.
The ZigbeeSubsystem is a layer in between Zigbee device drivers and ZHAL responsible for safely sharing the Zigbee infrastructure between device drivers.
ZHAL is the Zigbee Hardware Abstraction Layer. It is a C library (source/libs/zhal) that converts function calls and events into IPC to the Zigbee implementation.
ZigbeeCore is an implementation of the ZHAL API and is the lowest level process that runs on the main CPE processor for Zigbee support. It has the following responsibilities:
- Provide access and functionality of a Zigbee Coordinator and Trust Center
- Receive requests from Device Service's Zigbee Subsystem
- Sends events to Zigbee Subsystem
- Serves firmware images to devices
- Manages firmware on the Zigbee processor
ZigbeeCore's log can be found at /tmp/logs/ZigbeeCore.log on non gateway devices. For gateways this log data is sent to standard output and therefore does not appear in the standard log files. It can be accessed with journalctl (specify the 'zilker' unit).
The firmware that runs on the Zigbee processor is the lowest level of Zilker related to Zigbee. It is built upon Silicon Laboratories NCP framework that handles the lower level radio and Zigbee Trust center among other things. Comcast modifications include support for low power mode, RMA, and some Zigbee 3 security features.
Most Zigbee devices are compliant with the Over the Air Upgrade cluster's firmware management mechanisms that were introduced with the Home Automation profile version 1.2. There are some device's in our ecosystem that were created before this standard was available. These devices we call 'legacy' and their firmware is managed differently as discussed below.
As mentioned in the Device Descriptor section, when a new firmware image is available for a device, the Device Descriptor List (aka whitelist/allowlist) is updated with the new firmware version number and filename. When this updated list is published and downloaded by Zilker it is scanned for descriptors matching paired devices. If a paired device needs an upgrade its file is downloaded from the content server and placed in /opt/zigbeeFirmware/ota (or /nvram/icontrol/zigbeeFirmware/ota on gateways). This upgrade mechanism is "pulled" from the device through image block requests made to ZigbeeCore. The process starts when the device sends a "query next image" request which contains its current firmware version. The response will indicate if ZigbeeCore has a newer image for it and the device will start pulling blocks until it finishes.
This upgrade mechanism can take a while, especially on battery powered devices. While the device is downloading the firmware image it remains fully functional until the image is fully downloaded and verified at which point it reboots to the new image. Reboots typically take less than a second.
Note that once a firmware image for a device is downloaded an "image notify" command is sent to the device in an attempt to start the upgrade immediately, however many of our devices are "sleepy" so they will not receive this message. Devices are required to check once a day, minimum, to see if ZigbeeCore has a new firmware image available.
Devices that do not support the Over the Air Upgrade cluster include older security sensors, some older Centralite lighting modules, and the older RTCoA thermostat. This upgrade mechanism is risky due to the way the packets are routed and because the device is non-functional for the duration of the upgrade. For these reasons we only upgrade these devices if there are critical issues.
Similar to the above process, these firmware files are downloaded to /opt/zigbeeFirmware/legacy (or /nvram/icontrol/zigbeeFirmware/legacy on gateways). This upgrade mechanism is a "push" model where ZigbeeCore requests the device boot into its bootloader then starts pushing packets at it until complete. Once this process starts the device will not be functional until it completes successfully since it overwrites its flash as packets are received. If the process fails or is interrupted, the device will change to channel 13 and await rescue.
Device Service has a utility called xhDeviceUtil which provides access to devices and can control certain aspects of Device Service. The utility can be run either interactively (when no options are specified) or can be fed command line arguments for non-interactive operation. It has detailed help and offers history with command callback and tab key initiated command completion when in interactive mode. The help output as of the time of this writing is:
deviceUtil> help
Core:
history : print the history of commands run interactively
listDevices|list [device class] : list all devices, or all devices in a class
getDeviceCountBySubsystem <subsystem> : Get the number of devices by subsystem
Examples:
getDeviceCountBySubsystem zigbee
printDevice|pd <uuid> : print information for a device
printAllDevices|pa [device class] : print information for all devices, or all devices in a class
readResource|rr <uri> : read the value of a resource
Examples:
readResource /000d6f000aae8410/r/communicationFailure
writeResource|wr <uri> [value] : write the value of a resource
Examples:
writeResource /000d6f000aae8410/ep/1/r/label "Front Door"
execResource|er <uri> [value] : execute a resource
queryResources|qr <uri pattern> : query resources with a pattern
Examples:
qr */lowBatt
readMetadata|rm <uri> : read metadata
Examples:
rm /000d6f000aae8410/m/lpmPolicy
writeMetadata|wm <uri> : write metadata
Examples:
wm /000d6f000aae8410/m/lpmPolicy never
queryMetadata|qm <uri pattern> : query metadata through a uri pattern
Examples:
qm */rejoins
discoverStart|dstart <device class> : Start discovery for a device class
discoverRepairStart|drstart <device class> : Start discovery for orphaned devices in a device class
discoverStop|dstop : Stop device discovery
removeDevice|rd <uuid> : Remove a device by uuid
removeEndpoint|re <uri> : Remove an endpoint by uri
dumpDevice|dd <uuid> : Dump all details about a device
dumpAllDevices|dump : Dump all details about all devices
readSystemProperty <key> : Read a device service system property
writeSystemProperty <key> [value] : Write a device service system property
ddl override <path> | clearoverride | process | bypass | clearbypass : Configure and control device descriptor processing
Examples:
ddl override /opt/etc/WhiteList.xml.override
ddl clearoverride
ddl process
ddl bypass
ddl clearbypass
getStatus|gs : Get the status of device service
Zigbee:
zigbeeStatus|zs : get the status of the zigbee subsystem
zigbeeDumpCounters : dump the current zigbee counters
zigbeeNetworkMap : Print the Zigbee network map
zigbeeSetChannel <channel number or 0 to pick best> [dryrun] : Change the Zigbee channel
Examples:
zigbeeSetChannel 25
zigbeeSetChannel 0 dryrun
zigbeeEnergyScan [<duration mS> <number of scans> <channels to scan...>] : Scan for background noise on Zigbee channels
Examples:
zigbeeEnergyScan
zigbeeEnergyScan 30 16 11 20 25
To see what devices are paired we use the "list" command:
deviceUtil> list
7894b4ef0ca1: Class: camera
Endpoint camera: Profile: camera, Label: Front Door
Endpoint sensor: Profile: sensor, Label: (null)
000d6f0004ae46af: Class: light
Endpoint 1: Profile: light, Label: Garage Door Indicator
000d6f0012c529a0: Class: sensor
Endpoint 1: Profile: sensor, Label: Back Door
e0606614be56: Class: camera
Endpoint camera: Profile: camera, Label: Back Door
Endpoint sensor: Profile: sensor, Label: (null)
0022a3000004e039: Class: light
Endpoint 1: Profile: light, Label: Upstairs Nightlight
000d6f0012c47ebf: Class: sensor
Endpoint 1: Profile: sensor, Label: Front Door
000d6f0012c6087b: Class: sensor
Endpoint 1: Profile: sensor, Label: Garage Door
0022a300002f164c: Class: light
Endpoint 1: Profile: light, Label: Garge Door Indicator Up
Endpoint 3: Profile: lightSwitch, Label: (null)
To display the resources for a device in a user-friendly way we use "printDevice" (or "pd" for short):
deviceUtil> printDevice 000d6f0004ae46af
000d6f0004ae46af: Garage Door Indicator, Class: light
/000d6f0004ae46af/r/communicationFailure = true
/000d6f0004ae46af/r/dateAdded = 1578949352641
/000d6f0004ae46af/r/dateLastContacted = 1595336347583
/000d6f0004ae46af/r/feLqi = 255
/000d6f0004ae46af/r/feRssi = -13
/000d6f0004ae46af/r/firmwareUpdateStatus = upToDate
/000d6f0004ae46af/r/firmwareVersion = 0x10015110
/000d6f0004ae46af/r/hardwareVersion = 1
/000d6f0004ae46af/r/manufacturer = CentraLite
/000d6f0004ae46af/r/model = 3420
/000d6f0004ae46af/r/neLqi = 255
/000d6f0004ae46af/r/neRssi = -35
/000d6f0004ae46af/r/resetToFactoryDefaults = (null)
Endpoint 1: Profile: light
/000d6f0004ae46af/ep/1/r/currentLevel = 100
/000d6f0004ae46af/ep/1/r/isDimmableMode = true
/000d6f0004ae46af/ep/1/r/isOn = true
/000d6f0004ae46af/ep/1/r/label = Garage Door Indicator
To perform an action on a device we write to a resource (or in rare cases, execute a resource). For example, to turn on a light:
deviceUtil> writeResource /0022a300002f164c/ep/1/r/isOn true
resourceUpdated: id=isOn, uri=/0022a300002f164c/ep/1/r/isOn, ownerId=1, ownerClass=light, value=true, type=com.icontrol.boolean, mode=0x7b (rw-del-)
deviceUtil>
resourceUpdated: id=currentLevel, uri=/0022a300002f164c/ep/1/r/currentLevel, ownerId=1, ownerClass=light, value=0, type=com.icontrol.lightLevel, mode=0x7b (rw-del-)
resourceUpdated: id=currentLevel, uri=/0022a300002f164c/ep/1/r/currentLevel, ownerId=1, ownerClass=light, value=35, type=com.icontrol.lightLevel, mode=0x7b (rw-del-)
resourceUpdated: id=currentLevel, uri=/0022a300002f164c/ep/1/r/currentLevel, ownerId=1, ownerClass=light, value=69, type=com.icontrol.lightLevel, mode=0x7b (rw-del-)
resourceUpdated: id=currentLevel, uri=/0022a300002f164c/ep/1/r/currentLevel, ownerId=1, ownerClass=light, value=99, type=com.icontrol.lightLevel, mode=0x7b (rw-del-)
resourceUpdated: id=currentLevel, uri=/0022a300002f164c/ep/1/r/currentLevel, ownerId=1, ownerClass=light, value=100, type=com.icontrol.lightLevel, mode=0x7b (rw-del-)
Note how in the above example writing "true" to the light's "isOn" resource triggered several resource updated events that are printed when running device util in interactive mode. The first event shown is the "isOn" resource changing to true which happens as a result of the light device sending an attribute report for the ON_OFF attribute. The remaining events are similarly triggered by attribute reports as the light slowly transitions from 0% dim level to 100%.
Wildcards can be used when querying resources which can be useful to see the same resource across multiple devices. For example:
deviceUtil> queryResources */communicationFailure
resources:
/000d6f0004ae46af/r/communicationFailure = true
/000d6f0012c47ebf/r/communicationFailure = false
/000d6f0012c529a0/r/communicationFailure = false
/000d6f0012c6087b/r/communicationFailure = false
/0022a3000004e039/r/communicationFailure = false
/0022a300002f164c/r/communicationFailure = false
/7894b4ef0ca1/r/communicationFailure = false
/d187bc81-927a-4ad6-8634-a74b38bf7c0c/r/communicationFailure = false
/e0606614be56/r/communicationFailure = false