ZigbeeDevice Class

This is a class that inherits from the Device class, but extends behavior with Zigbee-specific functionality. These functions are documented in the class documentation below.

Configuring Zigbee Devices

With Zigbee devices it is very common to want to configure attribute reporting for either when values change or on a schedule. There are a few different ways to do this. The first option is to define the doConfigure lifecycle event handler for your driver, manually building and sending configuration commands that are needed for your device. The Zigbee Device object also provides two options for adding attribute configurations either as a “configured attribute” or as a “monitored attribute”.

Configured Attributes

A configured attribute will result in sending a bind request ZDO command as well as a ZCL configure reporting command to the device when ZigbeeDevice:configure() is called. These can be added to a device using the st.zigbee.Device:add_configured_attribute. Typically you would add these as a part of the device object construction via the init lifecycle event, however, it can be done in whatever way makes sense for the device. These attributes will also automatically be read from the device when ZigbeeDevice:refresh() is called.

Monitored Attributes

Monitored attributes are those that will have their reports tracked by the platform and will automatically issue a read if the attribute hasn’t reported within the requested max reporting interval. These can be added using the ZigbeDevice:add_monitored_attribute(config). In order to avoid sending an immediate read if the max interval is exceeded slightly due to network issues, a grace period of half the max interval will be allowed before issuing the read. Additionally, the check if an attribute is out of date will happen every 30 seconds, so it could be up to 1.5 * max reporting interval + 30 seconds before a read is sent. In general this should not be needed if the device supports reporting configuration, however, some Zigbee devices (such as those using the ZLL profile) don’t and so it can be helpful to have periodic checks of attributes.

Zigbee device configuration from defaults

As described in the defaults section, quite a bit of default behavior is supported based on the capabilities a device supports defined in it’s profile. If your driver registers for defaults, there are a number of attribute configurations that will be added as configured and monitored attributes, which means calling ZigbeeDevice:configure() or ZigbeeDevice:refresh() will include these defaults.

Multi-Component devices

There are a number of situations where the SmartThings model of the device makes sense to be broken down into several “components”. A classic example of this would be a smart power strip, where it is a single device on the network, but each outlet can be controlled separately. This would best be modeled as a single device, with a component for each switch.

Within Zigbee these separate pieces of functionality are often modeled as “endpoints”, and messages to the devices can be addressed to the specific endpoint you want to control and interact with. In order to promote code reuse the ZigbeeDevice object provides a way for your driver to define how you want to map between components and endpoints that can then be used by the rest of the Zigbee Lua standard library to automatically generate events for the correct components or send messages to the correct endpoint. As an important note, as with most things in the standard library this is built to support the most common model, but it is likely that there will be individual devices that don’t adhere to this model and will need to override this behavior.

In order to opt in to this behavior you can use the following functions:

function ZigbeeDevice:set_component_to_endpoint_fn(comp_ep_fn)
function ZigbeeDevice:set_endpoint_to_component_fn(ep_comp_fn)

Here you can provide a function for each direction to map a Zigbee endpoint id (1 byte number) to a SmartThings component id (string), and vice versa. Once these are set the following functions on the device are used for event generation and message addressing:

function ZigbeeDevice:get_endpoint_for_component_id(comp_id)
function ZigbeeDevice:get_component_id_for_endpoint(ep)

If these functions are used without settign the mapping functions above, they will return the defaults (“main” for a component, and device.fingerprinted_endpoint_id for the endpoint). Further as a convenience method the following function is provided as well

function ZigbeeDevice:emit_event_for_endpoint(endpoint, event)

That will automatically generate the event for the correct endpoint.

example

Here is a simple example of a driver that supports multi switch Zigbee outlet where the profiles are defined as follows:

name: two-outlet
components:
- id: main
  capabilities:
  - id: switch
    version: 1
  categories:
  - name: Switch
- id: switch1
  capabilities:
  - id: switch
    version: 1
  categories:
  - name: Switch

name: three-outlet
components:
- id: main
  capabilities:
  - id: switch
    version: 1
  categories:
  - name: Switch
- id: switch1
  capabilities:
  - id: switch
    version: 1
  categories:
  - name: Switch
- id: switch2
  capabilities:
  - id: switch
    version: 1
  categories:
  - name: Switch

And uses Zigbee endpoints 0x00 for the first outlet and increments by one for each additional outlet. Then the following driver will be able to use the built-in behavior to correctly generate events and address commands.

local capabilities = require "st.capabilities"
local ZigbeeDriver = require "st.zigbee"
local defaults = require "st.zigbee.defaults"

local function component_to_endpoint(device, component_id)
  if component_id == "main" then
    return device.fingerprinted_endpoint_id
  else
    local ep_num = component_id:match("switch(%d)")
    return ep_num and tonumber(ep_num) or device.fingerprinted_endpoint_id
  end
end

local function endpoint_to_component(device, ep)
  if ep == device.fingerprinted_endpoint_id then
    return "main"
  else
    return string.format("switch%d", ep)
  end
end

local device_init = function(self, device)
  device:set_component_to_endpoint_fn(component_to_endpoint)
  device:set_endpoint_to_component_fn(endpoint_to_component)
end

local zigbee_outlet_driver_template = {
  supported_capabilities = {
    capabilities.switch,
  },
  lifecycle_handlers = {
    init = device_init,
  },
}

defaults.register_for_default_handlers(zigbee_outlet_driver_template, zigbee_outlet_driver_template.supported_capabilities)
local zigbee_outlet = ZigbeeDriver("zigbee_bulb", zigbee_outlet_driver_template)
zigbee_outlet:run()

Class Documentation

class st.zigbee.Device: st.Device
get_endpoint(cluster)

Find the endpoint of the device that supports the given cluster

fingerprinted_endpoint_id if none include the cluster

Parameters

cluster (number) – The cluster ID to find the endpoint for on the device

Returns

the first endpoint with the cluster listed in its server clusters, or the

Return type

number

get_manufacturer()

Find the manufacturer of this device

Returns

The manufacturer of this device, nil if none present

Return type

str

get_model()

Find the model of this device

Returns

The model of this device, nil if none present

Return type

str

get_short_address()

Get the numeric zigbee short address for this device

Returns

The 2 byte Zigbee short address of this device

Return type

number

add_attributes_from_driver_template(attr_config_list)

Add a series of attribute configurations to this device

These devices will be added as configured and/or monitored attributes based on the config flags configurable and monitored. These flags are assumed to be true. That is, any value (or non value if they aren’t set) is treated as being set true, and only if it is explicitly set to false will a attribute in the list not be added.

A configured attribute will generate a configure reporting and bind request messages when configure is called on the device. A monitored attribute will monitor responses from the device for the corresponding attributes and send periodic reads if the value isn’t updated in too long.

configurations to add

Parameters

attr_config_list (list[AttributeConfiguration]) – the list of attribute

set_ias_zone_config_method(ias_zone_config_type)

Set the configuration type for IAS Zone on this device

If unset it is assumed that this device does not need IAS Zone configuration

Parameters

ias_zone_config_type (IAS_ZONE_CONFIGURE_TYPE) – The type of configuration this device needs

supports_server_cluster(cluster_id, endpoint_id)

Check if this devices supports a specific cluster as a server

Parameters
  • cluster_id (number) – the cluster ID to check for

  • endpoint_id (number or nil) – the endpoint to check cluster support

Return type

boolean

add_configured_attribute(config)

Add a configured attribute for this device

A configured attribute will generate a configure reporting and bind request messages when configure is called on the device.

Parameters

config (AttributeConfiguration) – the attribute configuration to add

add_monitored_attribute(config)

Add a monitored attribute for this device

A monitored attribute will monitor responses from the device for the corresponding attributes and send periodic reads if the value isn’t updated in too long. That length is determined by config.maximum_interval * 1.5

Parameters

config (AttributeConfiguration) – the attribute configuration to add

check_monitored_attributes()

Check all monitored attributes for this device and send a read where necessary

This will look through all monitored attributes that have been added to this device and if we have not heard from or sent a read in above the expected interval, we will send a read attribute to update our status.

attribute_monitor(zb_rx)

Check a ZigbeeRx message against our monitored attributes and update the status

This message is expected to be called with all messages that are received from this device. If this is a read or report for a monitored attribute the timestamps are updated. If there is a status involving an unsupported attribute, or a read attribute failure, the offending attribute is removed from the monitored attributes for this device to avoid spurious monitor reads

Parameters

zb_rx (st.zigbee.ZigbeeMessageRx) – A received Zigbee message from this device

remove_monitored_attribute(cluster, attribute)

Remove a monitored attribute on this device

This will prevent future monitoring of this attribute.

Parameters
  • cluster (number) – The id of the cluster of the attribute to remove

  • attribute (number) – The id of the attribute to remove

remove_configured_attribute(cluster, attribute)

Remove a configured attribute on this device.

This will prevent configuration of this attribute. This must be done before device:configure() is called or it will have no effect.

Parameters
  • cluster (number) – The id of the cluster of the attribute to remove

  • attribute (number) – The id of the attribute to remove

configure()

Send the necessary bind requests and reporting configurations to this device

For each configured attribute on this device send the necessary configure reporting and bind requests to have the device send attribute updates. Attributes are configured for all zigbee endpoints that support the clusters.

set_component_to_endpoint_fn(comp_ep_fn)

Set a function to map this devices SmartThings components to Zigbee endpoints

Parameters

comp_ep_fn (CompToEp) – function to do the mapping for this device

set_endpoint_to_component_fn(ep_comp_fn)

Set a function to map this devices Zigbee endpoints to SmartThings components

Parameters

ep_comp_fn (EpToComp) – function to do the mapping for this device

get_endpoint_for_component_id(comp_id)

Given the component ID find the corresponding endpoint for this device

This will use the function set by st.zigbee.Device:set_component_to_endpoint_fn to return the appropriate endpoint given the component. If the function is unset it defaults to the devices “fingerprinted_endpoint_id”

Parameters

comp_id (str) – the component ID to find the endpoint for

Returns

the endpoint this component matches to

Return type

number

get_component_id_for_endpoint(ep)

Given the endpoint ID find the corresponding component for this device

This will use the function set by st.zigbee.Device:set_endpoint_to_component_fn to return the appropriate component given the endpoint. If the function is unset it defaults to “main”

Parameters

ep (number) – the endpoint ID to find the component for

Returns

the component ID the endpoint matches to

Return type

str

emit_event_for_endpoint(endpoint, event)

Emit a capability event for this device coming from the given endpoint

This uses st.zigbee.Device:get_component_id_for_endpoint to find the appropriate component and emit the event for that component

Parameters
  • endpoint (number) – the endpoint ID a message was received from

  • event (table) – the capability event to generate

refresh()

Send a read attribute command for all configured attributes on this device

send(zb_tx)

Send a ZigbeeMessageTx to this device

Parameters

zb_tx (st.zigbee.ZigbeeMessageTx) – the message to send to this device

send_to_component(component_id, zb_tx)

Send a ZigbeeMessageTx to this device and component

Parameters
  • component_id (str) – the component id to send this message to

  • zb_tx (st.zigbee.ZigbeeMessageTx) – the message to send to this device