Coder Social home page Coder Social logo

mdeweerd / zha-toolkit Goto Github PK

View Code? Open in Web Editor NEW
171.0 7.0 18.0 1.47 MB

🧰 Zigbee Home Assistant Toolkit - service for "rare" Zigbee operations using ZHA on Home Assistant

License: GNU General Public License v3.0

Python 99.59% Shell 0.41%
zha home-assistant home-assistant-component zigbee zigpy home-assistant-hacs

zha-toolkit's Introduction

hacs_badge hacs_installszha_installs Version Downloads latest Downloads pre-commit Open ZHA-Toolkit inside your Home Assistant Community Store (HACS).

ZHA Toolkit (Zigbee Home Assistant Toolkit) helps go beyond some limitations when using the ZHA integration component in Home Assistant (an open source home automation software). It does so by providing extra methods to execute Zigbee requests and helps bridge between ZHA functionality and Home Assistant.

You can add ZHA Toolkit to Home Assistant using HACS (Home Assistant Community Store). ZHA Toolkit is available in HACS' default repository list.

Purpose

The purpose of ZHA Toolkit and its Home Assistant 'Services' feature, is to provide direct control over low-level zigbee commands provided in ZHA or Zigpy that are not otherwise available or too limited for some use cases.

ZHA Toolkit can also:

  • Serve as a framework to do local low-level coding. ZHA Toolkit applies code changes immediately by reloading its python modules on each call, including the user custom modules.

  • Provide access to some higher-level commands such as ZNP backup (and restore).

  • Make it easier to perform one-time operations where (some) Zigbee knowledge is sufficient and avoid the need to understand the inner workings of ZHA or Zigpy (methods, quirks, etc).

  • Download Firmware referenced in Koenkk/zigbee-OTA.

Highlights

  • Reads Zigbee attributes into Home Assistant states/attributes
  • Daily ZNP Coordinator backup (See blueprint)
  • Provides "Low level" access to most Zigbee commands (read/write/(un)bind/report/cmd/discover)

Table of Contents

Setup

"Downloading" zha-toolkit to the custom_components directory

ZHA Toolkit uses the well-known HACS installation mechanism. It is recommended to use HACS which facilitates the installation of many other custom components as well.

If you already have HACS (Tutorial), simply look for "ZHA Toolkit" under Integrations or click this redirection to add it.

image

If you are not using HACS, you need add the files in custom_components/zha_toolkit. See installNoHacsFromZip.sh and installNoHacsWithGit.sh for possible procedures.

Enabling zha-toolkit

In all cases (HACS or manual), the ZHA Toolkit integration is only active on your Home Assistance instance after adding next line to configuration.yaml, and restarting Home Assistant.

zha_toolkit:

Setting permanent logging verbosity

Before restarting, you may also want to enable debug verbosity. zha-toolkit isn't verbose when you use it occasionnaly. As it's a service, there is no really good way to inform the user about errors other than the log.

Logging will help verify that the commands you send have the desired effect.

Add/update the logger configuration (in the configuration.yaml file):

logger:
  # The next line sets the default logging level, for all python modules.
  # It seems "recommended" to set it to avoid too much logging.
  default: warning
  logs:
    custom_components.zha_toolkit: debug

Setting logger verbosity dynamically

You can also change the log configuration dynamically by calling the logger.setlevel service. Example that sets the debug level for this zha_toolkit component and for zigpy.zcl (which helps to see some information about actual ZCL frames sent). This method allows you to enable debug logging only for a limited duration :

service: logger.set_level
data:
  custom_components.zha_toolkit: debug
  zigpy.zcl: debug

Automations

This is a list (of 1) automation:

  • DAILY BACKUP OF ZNP DONGLE: Open your Home Assistant instance and show the Daily Backup Blueprint pre-filled.
  • ⚠️ Under test DAILY BACKUP OF ZNP/EZSP(Bellows) DONGLE TYPE : Open your Home Assistant instance and show the Daily Backup Blueprint pre-filled.

Using zha-toolkit

This component provides a single service (zha_toolkit.execute) that provides several commands (command parameter) providing access to ZHA/Zigbee actions that are not otherwise available.

You can use a service as an action in automations. So you can send the commands according to a schedule or other triggers. For instance, you could plan a daily backup of your TI-ZNP USB Key configuration.

It will be more common to send a Zigbee command only once: for instance bind one device to another, set a manufacturer attribute, ... .
You can perform them using the developer tools.
The developer tools are handy to test the service first before adding them to an automation.

Go to Developer Tools > Services in your instance : Open your Home Assistant instance and show your service developer tools..

Choose the generic service zha_toolkit.execute or - more convenient - the specific zha_toolkit.<COMMAND> as the service.
Most parameters can be set using the UI, there are some cases where you may want to enable Yaml entry - you'll have some more flexibility and all parameters fit in your browser view. On the other hand, the UI interface makes it easier to select the entity. You can switch back and forth!

There are several examples below for different commands. You can copy/paste them to start from.

Not all available commands are documented. The undocumented ones were in the original repository.
Some of these undocumented commands seem to be very specific trials from the original authors.
Feel free to propose documentation updates.

General recommendations

  • Check this README.
  • Use scan_device to find out more about your device.
  • Use the Service Response to see what happens.
  • Use Events to see what happens (if you can't use the service Response).
  • Use home-assistant.log to see what happened.
  • Set the log level to debug (See Setup to get more facts.
  • Check the Github open and closed issues
  • Check the Home Assistant Forum
  • Check the examples directory
  • Check zhaquirks for hints about available attributes (available ones, meaning of their values)
  • Wake up sleepy devices (generally devices on a battery) just after sending a command so that they can receive it. It's also recommended to set the tries parameter to a fairly high number for these devices (in some cases over a 100 tries (more than 10 minutes) are needed to successfully communicate with a sleepy device).

Zigbee crash course

Note: this crash course's wording may deviate from Zigbee's wording.

Zigbee is a wireless communication protocol used for creating networks of devices. To understand Zigbee, we can look at it from two perspectives: the network-oriented view and the device-oriented view.

From a network perspective, there is a coordinator, which is the main device controlling the network (often your Home Assistant instance), and there are other devices categorized as routers and end devices.
Routers are permanently powered devices that store and forward messages, while end devices can be any type of device. End devices can reply to requests and communicate autonomously if they have reporting configurations and bindings set up. Reporting configurations determine when a device should communicate attribute changes, and bindings specify which device or group should receive these changes.
Commands, such as those triggered by a button press, can also be bound to specific devices or groups.

From a device perspective, devices are organized into endpoints.
An endpoint represents a function or feature of the device. For example, a device with two switches would have an endpoint for each switch function, and a device with a temperature and humidity sensor may have an endpoint for each sensor.
Endpoints can also represent Zigbee-specific functionalities like Over The Air (OTA) updates or Green Power functionality.

Each endpoint has attributes associated with it.
Attributes allow you to control the configuration of the device or retrieve values for its current state, such as on/off status or temperature readings.
Attributes are grouped into clusters, which are reusable sets of features.
Clusters represent things like on/off state, color control, temperature measurement, energy metering, and more.

In practice, clusters are defined on endpoints, and each attribute has a unique address consisting of the IEEE address (a 64-bit number), the endpoint ID (a byte), the cluster ID (a two byte word), and the attribute ID (a two byte word as well).

Attributes have different types, such as boolean, unsigned and signed byte, arrays, timestamps, and more. In most cases, the attribute type can be determined automatically by tools like zha-toolkit and ZHA.

The Zigbee Cluster Library (ZCL) document defines standard attributes and their organization in clusters. Manufacturers also have the freedom to add their own attributes that are not defined in the ZCL.

Commands and attribute read/write operations are typically initiated from the coordinator. However, Zigbee devices can also send commands to other devices, like a switch instructing a light bulb to turn on or off.

To avoid excessive network traffic caused by constantly polling devices for their internal state, devices can be configured to report their state changes to other devices in the network.
This reporting is accompanied by bindings, which specify the devices or groups that should receive the data.

Binding can also make an endpoint on a device respond to commands sent to a specific group.
For example, if you add a switch's endpoint and multiple light bulbs to a group, the switch can control all the bulbs in that group.

When a new device is added to a Zigbee network through Home Assistant's ZHA integration, an initial configuration is sent to the device. This configuration sets up reporting and binding settings to ensure that the device notifies the coordinator about its state changes or any relevant data changes, such as energy consumption metrics or simply informing that a light has been switched on.

Zigbee routers play an important role in the network by relaying messages between devices, bridging longer distances, and temporarily storing messages for battery-powered devices that wake up periodically. Messages are typically stored for around 6 seconds.

Battery-powered devices are considered "sleepy" devices because they conserve energy by sleeping most of the time. However, this can lead to data requests and commands being lost if the device is asleep when they are sent. To ensure successful communication, requests may need to be actively repeated until the sleepy device wakes up and responds.

In some cases, it is necessary to provide the manufacturer ID to access a manufacturer-specific attribute or execute a manufacturer-specific command to use features or functionalities specific to the device manufacturer,

Zigbee, ZHA, zha-device-handlers, zigpy, ZHA-toolkit

ZHA and zha-device-handlers and zigpy intend to wrap the zigbee attribute operations and commands so that the Zigbee device features are immediately usable in Home Assistant. The quality of these integrations and libraries are ensured through unit tests.

  • zigpy is a library/gateway that bridges the gap between python and the zigbee coordinator hardware.
  • ZHA interfaces zigpy with Home Assistant.
  • The zha-device-quirks library is delivered at the same time as ZHA and adapts "quirky" device behavior to interface with Home Assistant through ZHA. "Quirky" device behavior means that a device is providing functionality not or not as anticipated in the Zigbee specifications.
  • ZHA-Toolkit is there to help with using device functionalities that are not fully supported yet in ZHA, or help implement scripts and automations that are not part of the main focus of the ZHA integration. There currently are no test cases - so there is less quality assurance and a function might accidentally drop at some point. It is not autonomously listening in on Zigbee messages to generate Home Assistant events for instance, but you can use it to poll devices and update state values directly, or send commands you can't send through ZHA. ZHA-Toolkit can help with diagnostics and device configurations.

Common options

ieee: A reference to the device

In almost all commands you need to provide a reference to the device that you want to control.

Easiest, use an entity name:

service: zha_toolkit.SOME_SERVICE
data:
  # entity name (one of them)
  ieee: light.tz3000_odygigth_ts0505a_12c90efe_level_light_color_on_off

Harder, find and use the IEEE address:

service: zha_toolkit.SOME_SERVICE
data:
  # Valid possibilities for the ieee address
  # The full IEEE address:
  ieee: 00:12:4b:00:24:42:d1:dc

Even more difficult, find and use the devices' short address, which may change over time.

service: zha_toolkit.SOME_SERVICE
data:
  # The short network address
  ieee: 0x2F3E

The ieee address can be the IEEE address, the short network address (0x1203 for instance), or the entity name (example: light.tz3000_odygigth_ts0505a_12c90efe_level_light_color_on_off). Be aware that the network address can change over time but it is shorter to enter if you know it.

There is no universal "best" way of selecting the device.

  • The IEEE address is the only reference that does not change over time.
  • The entity name is surely easiest to find. While as a user you can change it, it is also somewhat stable when you replace a device - you could keep the same entity name for a difference device.
  • The short address might be shorter to type if you already know it, but do not rely on it if you scripts needs to continue to work over time.

Sometime the command_data field provides a reference to a device (for instance, when binding one device to another). It has the same flexibility as the ieee argument.

Response data

The zha-toolkit services return their results as response data for Home Assistant installations that have at least version 2023.7 .

This response is available in automations and script by adding response_variable: VAR_NAME to the zha_toolkit service call. That will make the data available under VAR_NAME inside the automation or script.
An example using the response data can be found in script_use_zha_devices_response.yaml.

The response data feature of Home Assistant also makes the response available when calling the service interactively.
The image below shows a an interactive attribute read using the zha-toolkit service attr_read. The response data is shown in Yaml format when the call finishes.

Service Response Example

Events

Events in Home Assistant are a way to trigger or proceed in automations and scripts, and convey data.

All zha-toolkit commands support setting event names that are fired at the end of the command execution.

You can interactively listen for events in the Developer Tools>Events page which is a good way to check the result of a zha-toolkit service that you start in another tab of your browser.

You can set the event names as follows:

service: zha_toolkit.SERVICE_NAME
data:
  # You can set the next events to use as a trigger.
  # The event data has the result of the command
  event_success: my_read_success_trigger_event
  event_fail: my_read_fail_trigger_event
  event_done: my_read_done_trigger_event

It's recommended to use the event_done event during interactive use. You can use Developer Tools > Events > Listen to events to see the result of the service call. You need to use Listen to events in a separate navigator tab, START LISTENING and leave it open to see the data of the events.

By listening for the event, you can see the list of groups that is found when using zha_toolkit.get_groups for instance.
Otherwise you need to set the debug level and watch the home-assistant.log. That can be useful if you do a lot of service calls in sequence and you want to look back what happened.

You can also simply always enable debugging for zha_toolkit if you use it sporadically - it is quite verbose and tends to fill up the logs if you use it often.

Raise an exception on failure

service: zha_toolkit.SERVICE_CALL
data:
  fail_exception: true

By default, the result of a zigbee transaction is "ignored" for the end result of the service call: it will appear as if it succeeds (unless you have the parameters wrong).

So, if you want the Developer Tools > Services > CALL SERVICE button to turn red in case the zigbee transaction result is not SUCCESS, then add fail_exception: true to the options

Tries

service: zha_toolkit.SERVICE_CALL
data:
  tries: 10

Tries indicates how many times a zigbee transaction is repeated until it succeeds. An individual zigbee transaction may fail because of radio interference or because the device is sleeping.

So by setting tries: 100 you'll request that zigbee requests are repeated up to 100 times.

This is not applied everywhere, but it's applied for attribute reading, writing and report configuration. It's handy when you want to change the report configuration of your battery powered thermometer for instance.

You may still need to wake them up just after sending the command so that they can receive it.

Service commands

Services are easy to called once or tested through Developer Tools > Services . And you can also use them in scripts, automations, etc. .

Quite a few services can be configured from the UI. And you can also start using the UI (to select the ieee/entity for instance), and then Go To YAML mode to add the other parameters.

Empty UI example: image

An example of event data is shown below. The data>errors field can be useful to understand what went wrong. The ieee_org fields take the original value of the "ieee" parameter, and the ieee field is the actual IEEE address found.

{
  "event_type": "my_write_done_trigger_event",
  "data": {
    "ieee_org": "sensor.test_smartenergy_metering",
    "ieee": "00:12:4b:00:24:42:d1:dc",
    "command": "attr_write",
    "start_time": "2022-01-17T21:51:50.416725+00:00",
    "errors": [],
    "params": {
      "cmd_id": null,
      "endpoint_id": 1,
      "cluster_id": 0,
      "attr_id": 16,
      "attr_type": 66,
      "attr_val": "BureauTest",
      "min_interval": 60,
      "max_interval": 300,
      "reportable_change": 1,
      "dir": null,
      "manf": null,
      "tries": 1,
      "expect_reply": true,
      "args": [],
      "state_id": "sensor.test",
      "state_attr": null,
      "allow_create": true,
      "event_success": "my_write_success_trigger_event",
      "event_fail": "my_write_fail_trigger_event",
      "event_done": "my_write_done_trigger_event",
      "read_before_write": true,
      "read_after_write": true,
      "write_if_equal": false
    },
    "str": "BureauTest",
    "read_before": [
      {
        "16": "Bureau"
      },
      {}
    ],
    "result_write": [
      [
        {
          "status": 0,
          "attrid": null
        }
      ]
    ],
    "result_read": [
      {
        "16": "BureauTest"
      },
      {}
    ],
    "success": true
  },
  "origin": "LOCAL",
  "time_fired": "2022-01-17T21:52:02.066310+00:00",
  "context": {
    "id": "c5d4d0d14f7801fda3b9ad471dcbd83b",
    "parent_id": null,
    "user_id": null
  }
}

Home Assistant evolved and now shows the event data as a yaml structure.

Services that are not documented in the sections that follow below (not including undocumented ezsp commands):

  • all_routes_and_neighbours
  • bind_group
  • get_routes_and_neighbours
  • ieee_ping
  • unbind_group
  • zdo_flood_parent_annce
  • zdo_update_nwk_id

attr_read: Read an attribute value

Read a zigbee attribute value, optionally write to a state.

service: zha_toolkit.attr_read
data:
  ieee: sensor.zigbee_sensor
  # The endpoint is optional - when missing tries to find endpoint matching the cluster
  # endpoint: 1
  # Cluster Id - Can be omitted if attribute is unique string.
  cluster: 0xb04
  # Attribute Id or String - Example "pi_heating_demand"
  attribute: 0x50f
  # Optional, read the value from memory cache, do not make a zigbee read request.
  # Can be false, true, 0, 1 or 2 where '2' requests to fallback to a real read
  # if the value is not in cache.
  use_cache: true
  # Optional, state to write the read value to
  state_id: sensor.test
  # Optional, state attribute to write the value to, when missing: writes state itself
  state_attr: option
  # Optional, when true, allows creating the state (if not the state must exist)
  allow_create: true
  # The manufacturer should be set only for manufacturer attributes
  manf: 0x1212
  # Write read value to CSV file
  # Can be useful in automation/script
  # Format: <timestamp>,<name|attr_id>,<value>,<attr_id>,<cluster_id>,<ep_id>,<ieee>,<manf_id>
  # Optional: CSV file to write attribute to - located in /config/csv/...
  csvout: testcsv.csv
  # optional: csvlabel (default label = name from zigpy or attribute id)
  csvlabel: MyAttributeLabel

Example: attribute read with write to CSV file

service: zha_toolkit.attr_read
data:
  ieee: light.texasinstruments_ti_samplelight_d77add01_level_light_color_on_off
  event_done: zha_done
  attribute: 0
  cluster: 0
  csvout: testcsv.csv

Example of CSV output

Below is the result in /config/csv/testcsv.csv produced by the attr_read shown above.

2022-02-01T00:10:50.202707+00:00,zcl_version,1,0x0000,0x0000,11,00:12:4b:00:01:dd:7a:d7,,0x20

Fields in this output:

ISO8601_Timestamp,cluster_name,attribute_name,value,attr_id,cluster_id,endpoint_id,IEEE,manf,attr_type

Example, read attribute value from cache in HA state

This example reads the raw temperature value from cache into a home state attribute value.

The purpose of this example is to get the unrounded reported value from a temperature sensor.

A battery powered temperature sensor is often sleepy and doing a real attribute read may need many tries.

So this technique allows reading the value from the attribute cache. It does not use the attribute cache database table, but tries to get the value from the in-memory cache.

When use_cache is 2, an actual read will be executed if the attribute is not in cache.

service: zha_toolkit.attr_read
data:
  ieee: sensor.temperature_chambre_x_temperature_2
  cluster: 1026
  attribute: 0
  use_cache: true
  state_id: sensor.temperature_chambre_x_temperature_2
  state_attr: raw_degc
  # When defined, the read attribute is converted using this template string
  # before writing it to the state.
  # Note that no curly braces should be used here!
  state_value_template: value/100

For a real use case, see the example danfoss_ally_remote_temperature_min_delay.yaml where the automation attempts to read the temperature from the zigbee cache to get more precision (0.01°C) as ZHA rounds values to 0.1°C.

attr_write: Write(/Read) an attribute value

Write an attribute value to any endpoint/cluster/attribute.

You can provide the numerical value of the attribute id, or the internal zigpy name (string).

Before and after writing, the value is read from the attribute. If debug logging is active, this will be visible in the home_assistant.log. The last read this can be written to a state.

Note that the format/typing of the value for attr_val depends on the attribute type. uint*, int* and enum* types can be specified as numbers, most other types must be specified as an array of bytes or a string. If you are not sure how to represent the value, you could do an attr_read first while observing the event_done event to check how the attr_val is returned upon read.

In the yaml example detailing the available parameters to attr_write it is shown how to specify the value for an octet_string as an array/list.

service: zha_toolkit.attr_write
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # The endpoint is optional,
  # when missing, attr_write will find the endpoint
  # by matching the cluster which works if there is
  # only one endpoint with that cluster.
  endpoint: 11
  cluster: 0x1706
  attribute: 0x0000
  attr_type: 0x41
  # Example of octet strings (the length is added because of attr_type)
  attr_val: [41, 33, 8, 45, 52, 46, 50, 191, 55, 57, 136, 60, 100, 102, 63]
  # Optional manufacturer Id
  # - The manufacturer should be set only for manufacturer attributes
  manf: 0x1021
  # Optional, state to write the read value to
  state_id: sensor.test
  # Optional, state attribute to write the value to, when missing: writes state itself
  state_attr: option
  # Optional, when true, allows creating the state (if not the state must exist)
  allow_create: true
  # You can set the next events to use as a trigger.
  # The event data has the result of the command (currently attr_read, attr_write)
  event_success: my_read_success_trigger_event
  event_fail: my_read_fail_trigger_event
  event_done: my_read_done_trigger_event
  # Settings for attr_write
  # Read attribute before writing it (defaults to True)
  read_before_write: true
  # Read attribute after writing it (defaults to True)
  read_after_write: true
  # Write attribute when the read value matches (defaults to False)
  write_if_equal: false

In case ZCL Array type needs to be written, attr_val needs to be provided as a raw sequence of bytes, i.e. user is responsible to generate a sequence which complies to the ZCL spec.
The following examples illustrates configuration of Ubisys C4 (see the device manual - section 7.8.5.2. InputActions Attribute - example):

service: zha_toolkit.attr_write
data:
  ieee: 00:1f:ee:00:00:aa:aa:aa
  endpoint: 232
  cluster: 64512
  attribute: 1
  attr_type: 0x48
  # For the array type (type 0x48):
  #  - The first byte is the type of items.  here 65 or 0x41: octet str.
  #  - The second and third byte compose the length (little endian)
  #    So here: `4, 0` is 0x0004, so four octet strings the array.
  #  - All the octet strings in this example have a length of 6.
  attr_val: [65, 4, 0, 6, 0, 13, 1, 6, 0, 2, 6, 1, 13, 2, 6, 0, 2, 6, 2, 13, 3, 6,
    0, 2, 6, 3, 13, 4, 6, 0, 2]
  read_before_write: false
  read_after_write: false
  use_cache: false

Such a packet decoded using tshark/wireshark, the above results in:

ZigBee Cluster Library Frame, Command: Write Attributes, Seq: 40
    Frame Control Field: Profile-wide (0x00)
        .... ..00 = Frame Type: Profile-wide (0x0)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...0 .... = Disable Default Response: False
    Sequence Number: 40
    Command: Write Attributes (0x02)
    Attribute Field
        Attribute: Unknown (0xfde8)
        Data Type: Array (0x48)
        Elements Type: Octet String (0x41)
        Elements Number: 4
        Element #1, Octets: 00:0d:01:06:00:02
            Octet String: 00:0d:01:06:00:02
        Element #2, Octets: 01:0d:02:06:00:02
            Octet String: 01:0d:02:06:00:02
        Element #3, Octets: 02:0d:03:06:00:02
            Octet String: 02:0d:03:06:00:02
        Element #4, Octets: 03:0d:04:06:00:02
            Octet String: 03:0d:04:06:00:02

Decrypted ZigBee Payload (45 bytes) - only Array related data is shown:
0000                                         48 41 04   @........(...HA.
0010  00 06 00 0d 01 06 00 02 06 01 0d 02 06 00 02 06   ................
0020  02 0d 03 06 00 02 06 03 0d 04 06 00 02            .............

Using the symbolic name of the attribute, and automatic endpoint selection.

service: zha_toolkit.attr_write
data:
  ieee: button.fictious_model_dcd14224_identify
  cluster: 0
  attribute: location_desc
  attr_val: My Location

A more complex example using HA's templating feature can be found below.
Each call will increment the previous target temperature by 0.5 degrees (increment by 50 in Zigbee's unit) up to 22.50 degrees and restart from 20 degrees.
On the first call (when the state is not set yet), the setpoint temperature is 21.5 degrees.

The toolkit implements a read after each write (and it is not disabled by a read_after_write parameter), so it will write the temperature value to the state sensor.tgt_temperature.

Note that a template is evaluated before calling the service, so the read_before_write can't influence the attribute to write during the same service call even though it updates the attribute. The read before write could still be useful if you want to track updates in history graphs for instance.

This example also uses the attribute name, not the attribute id.

Tries is set to 3 to cope with some uncommon communication issues.

service: zha_toolkit.attr_write
data:
  ieee: entity.my_thermostat_entity
  cluster: 0x201
  attribute: occupied_heating_setpoint
  attr_val: "{% set t = states('sensor.tgt_temperature') %}{{ [(t|int+50) % 2300,2000]|max
    if is_number(t) else 2150 }}"
  state_id: sensor.tgt_temperature
  allow_create: true
  read_before_write: false
  tries: 3
  fail_exception: true

Binding related

The default list of binding clusters is currently as follows:

  • in clusters:
    • 0x0006 - OnOff
    • 0x0008 - Level
    • 0x0300 - Color Control
  • out clusters:
    • 0x0402 - Temperature

bind_ieee: Bind matching cluster to another device

Bind all available default and matching clusters from ieee to command_data on all endpoints.
Binds to the coordinator if command_data is not set or 0.
By default only binds cluster types in the internal list, i.e. OnOff, Level and Color Control clusters.

The cluster must exist on both devices, except when the coordinator is the target.

If you set the cluster, you can bind another cluster type and only that cluster will be bound (both in and out clusters).

Use binds_get to verify that the configuration worked.

It's possible to attempt binding specific endpoints between ieee and command_data.
The endpoint for ieee (source) can be provided by endpoint.
If it's not specified then all endpoints on ieee are considered.
Endpoint for command_data (destination) can be provided by dst_endpoint. If it's not specified then all endpoints on command_data are considered
and the first one that matches cluster-wise will be picked.

service: zha_toolkit.bind_ieee
data:
  ieee: entity.my_thermostat_entity
  # Optional, when not set or 0, bind to the coordinator.
  command_data: 00:12:4b:00:22:08:ed:1a
  # Optional, if you want to bind a cluster not internally selected.
  cluster: 0x0006
  # Optional: source endpoint (for ieee)
  endpoint: 2
  # Optional: destination endpoint (for command_data)
  dst_endpoint: 3

binds_get: Get binding table from the device

Get the bindings from the device.
Listen to the event, or enable debug and check the log to get the information.

service: zha_toolkit.binds_get
data:
  ieee: 00:15:8d:00:04:7b:83:69
  # Optional number of tries for each sub-request,
  # useful for sleepy devices
  tries: 100
  event_done: event_binds_get_done

binds_remove_all: Remove all device to device bindings

Remove all bindings from the device.
This internally fetches all the existing bindings (binds_get service) and requests the device to remove them.

service: zha_toolkit.binds_remove_all
data:
  ieee: entity.my_thermostat_entity
  # Optional - only remove binding to device
  command_data: 00:12:4b:00:01:6a:41:0c
  # Optional - name of generated event when done
  event_done: zhat_event
  # Optional - Endpoint or list of endpoints for which to remove bindings
  # endpoint: [20, 30]
  # Optional - Cluster or list of clusters for which to remove bindings
  # cluster: [0x0006, 0x0300]
  # Optional
  tries: 100

unbind_coordinator: Remove all bindings to the coordinator

Remove all bindings from the device to the coordinator. Typically, on device initialization Home Assistant sets up bindings with the main clusters to that it is informed about state changes.

This command will use binds_remove_all and set the coordinator's ieee address as the command_data parameter automatically avoiding that you have to look it up.

service: zha_toolkit.unbind_coordinator
data:
  ieee: entity.my_thermostat_entity
  # Optional - name of generated event when done
  event_done: zhat_event
  # Optional - Endpoint or list of endpoints for which to remove bindings
  # endpoint: [20, 30]
  # Optional - Cluster or list of clusters for which to remove bindings
  # cluster: [0x0006, 0x0300]
  # Optional
  tries: 100

conf_report: Configure reporting

Set the minimum and maximum delay between two reports and set the level of change required to report a value (before the maximum delay is expired).

This example configures Temperature reporting on a SonOff SNZB-02 (eWeLink/TH01). Note that on some devices you (may) need to press the button on the thermometer just after requesting the command (it's a sleepy device and does not wake up often). With a temperature sensor it may be more appropriate to sure a high temperature rise to force it to report the temperature and allow ZHA to send the configuration.

After succeeding the configuration, the minimum delay was actually 20s which is likely the measurement period itself. The changes were reported when they exceeded 0.10 degrees C.

For sleepy devices, you can add the parameter 'tries' which will retry until the devices confirms (with success or error)

service: zha_toolkit.conf_report
data:
  ieee: 00:12:4b:00:23:b3:da:a5
  # Optional endpoint, when missing will match cluster
  # endpoint: 1
  cluster: 0x402
  attribute: 0x0000
  min_interval: 60
  max_interval: 300
  reportable_change: 10
  # Optional manufacturer
  #manf: 0x1204
  # Optional number of configuration attempts
  tries: 3
  # You can set the next events to use as a trigger.
  # The event data has the result of the command (currently attr_read, attr_write)
  event_success: my_conf_success_trigger_event
  event_fail: my_conf_fail_trigger_event
  event_done: my_conf_done_trigger_event

Example of data available in the event report.

{
  "event_type": "my_conf_done_trigger_event",
  "data": {
    "ieee": "00:12:4b:00:24:42:d1:dc",
    "command": "conf_report",
    "start_time": "2022-01-16T21:56:21.393322+00:00",
    "params": {
      "cmd_id": null,
      "endpoint_id": 1,
      "cluster_id": 513,
      "attr_id": 0,
      "attr_type": null,
      "attr_val": null,
      "min_interval": 60,
      "max_interval": 300,
      "reportable_change": 10,
      "dir": null,
      "manf": null,
      "tries": 3,
      "expect_reply": true,
      "args": [],
      "state_id": "sensor.test",
      "state_attr": null,
      "allow_create": true,
      "event_success": "my_conf_success_trigger_event",
      "event_fail": "my_conf_fail_trigger_event",
      "event_done": "my_conf_done_trigger_event",
      "read_before_write": true,
      "read_after_write": true,
      "write_if_equal": false
    },
    "result_conf": [
      [
        {
          "status": 0,
          "direction": null,
          "attrid": null
        }
      ]
    ]
  },
  "origin": "LOCAL",
  "time_fired": "2022-01-16T21:56:28.248353+00:00",
  "context": {
    "id": "596b9ba7b29d76545295881ea73c5708",
    "parent_id": null,
    "user_id": null
  }
}

conf_report_read: Read configured reporting

Read the report configuration of a cluster.

service: zha_toolkit.conf_report_read
data:
  ieee: 00:12:4b:00:23:b3:da:a5
  # Optional endpoint, when missing will match cluster
  # endpoint: 1
  cluster: 0x402
  attribute: 0x0000
  # Optional manufacturer
  #manf: 0x1204
  event_done: my_conf_read_done_trigger_event

Example result (partial event data) where the min and max reporting intervals are provided, as well as the reportable change:

{
  "result_conf": [
    {
      "cluster": "Metering",
      "cluster_id": "0x0702",
      "attr_id": "0x0000",
      "direction": 0,
      "type": "0x25",
      "min_interval": 1,
      "max_interval": 300,
      "reportable_change": 1,
      "status": 0
    }
  ]
}

scan_device: Scan a device/Read all attribute values

scan_device will generated a report the discovered clusters, attributes, values and commands if the device implements this feature.

This can help you in discovering what you can configure on your device and what the values are at some point in time.

If the device does not fully support the discovery features, you could still write a script that would try to read the attributes that you want to poke using attr_read.

The result of the scan is written to the scan directory located in the configuration directory of Home Assistant (config/scan/*_result.txt).

The result is also added to the event data in the event['data']['scan'] field which is also available in the response data.

service: zha_toolkit.scan_device
data:
  ieee: 00:12:4b:00:22:08:ed:1a
  # Optional: endpoint to scan, when missing: all known endpoints
  # endpoint: 1
  # Optional: endpoints to scan, when missing: all known endpoints
  endpoint: [1, 2]
  # Optional: tries  Default:3 higher is useful for sleepy devices
  tries: 100

Scan using the entity name:

service: zha_toolkit.scan_device
data:
  ieee: light.tz3000_odygigth_ts0505a_12c90efe_level_light_color_on_off

zdo_scan_now: Do a topology scan

Runs topology.scan().

service: zha_toolkit.execute
data:
  command: zdo_scan_now

Join & Network presence related

handle_join: Handle join - rediscover device

You may want to try misc_reinitialize as handle_join will not redo any joining step that already completed.

service: zha_toolkit.execute
data:
  # Address of the device that joined
  ieee: 00:12:4b:00:22:08:ed:1a
  command: handle_join
  # NWK address of device that joined (must be exact)
  command_data: 0x604e

misc_reinitialize: Reinitialize device

misc_reinitialize is a pretty dirty (white-hat) hack to reinitialize a device by making zigpy think the device is not initialized, and then requesting an initialization.

This is more than handle_join which is not reinitializing much when the device is already set up in zigpy.

misc_reinitialize sets several device attributes to None and False so that the zigpy initialization code will proceed with initialization.

service: zha_toolkit.misc_reinitialize
data:
  # Reference of the device that should be reinitialized
  ieee: 00:12:4b:00:22:08:ed:1a

leave

Send Leave Request to the device.

service: zha_toolkit.leave
data:
  # Reference of the device that should be reinitialized
  ieee: 00:12:4b:00:22:08:ed:1a
  # (Parent ) IEEE address (router) that removes the device (required).
  command_data: 00:12:4b:00:01:6a:41:0c

rejoin

Send Rejoin Request to the device (=Leave with Rejoin).

service: zha_toolkit.rejoin
data:
  # Reference of the device that should be rejoined
  ieee: 00:12:4b:00:22:08:ed:1a
  # Optional, device that will accept joining.
  command_data: 00:12:4b:00:10:00:1d:1a

zdo_join_with_code

Currently for "bellow's" radio types.

service: zha_toolkit.zdo_join_with_code
data:
  # Reference of the device that allows the join
  ieee: 00:12:4b:00:22:08:ed:1a
  # The code to be used in the join
  code: Joining Code

zcl_cmd: Send a Cluster command

Allows you to send a cluster command. Also accepts command arguments.

Note:
There is also the official core service zha.issue_zigbee_cluster_command. You may want to use that instead if it suits your needs.
The zha_toolkit version allows lists of bytes as arg parameters, and has a hack to allow "Add Scene". It is also easier to adapt than the core that has though release procedures and is not as easily modifiable as a custom_component.

service: zha_toolkit.zcl_cmd
data:
  # Device IEEE address - mandatory
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Command id - mandatory
  cmd: 0
  # Cluster id - mandatory
  cluster: 1006
  # Endpoint - mandatory
  endpoint: 111
  # Optional: direction (0=to in_cluster (default), 1=to out_cluster),
  dir: 0
  # Optional: expect_reply  (default=true - false when 0 or 'false')
  expect_reply: true
  # Optional: manf - manufacturer - default : None
  manf: 0x0000
  # Optional: tries - default : 1
  tries: 1
  # Optional (only add when the command requires it): arguments (default=empty)
  args: [1, 3, [1, 2, 3]]

zcl_cmd Example: Send on command to an OnOff Cluster.

service: zha_toolkit.zcl_cmd
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  cmd: 1
  cluster: 6
  endpoint: 11

zcl_cmd Example: Send off command to an OnOff Cluster:

service: zha_toolkit.execute
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  command: zcl_cmd
  cmd: 0
  cluster: 6
  endpoint: 11

zcl_cmd Example: "Store Scene"

service: zha_toolkit.execute
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  command: zcl_cmd
  cmd: 4
  cluster: 5
  endpoint: 11
  args: [2, 5]

zcl_cmd Example: "Recall Scene"

service: zha_toolkit.execute
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  command: zcl_cmd
  cmd: 5
  cluster: 5
  endpoint: 11
  args: [2, 5]

Results in (sniffed):

ZigBee Cluster Library Frame
    Frame Control Field: Cluster-specific (0x01)
        .... ..01 = Frame Type: Cluster-specific (0x1)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...0 .... = Disable Default Response: False
    Sequence Number: 94
    Command: Recall Scene (0x05)
    Payload
        Group ID: 0x0002
        Scene ID: 0x05

zcl_cmd Example: "Add Scene"

This example shows that you can provide a list of bytes for an argument:

service: zha_toolkit.execute
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  command: zcl_cmd
  cmd: 0
  cluster: 5
  endpoint: 11
  args:
    - 2
    - 5
    - 2
    - Final Example
    # Two bytes of cluster Id (LSB first), length, attribute value bytes
    #   repeat as needed (inside the list!)
    - [0x06, 0x00, 1, 1]

sniffed as:

ZigBee Cluster Library Frame
    Frame Control Field: Cluster-specific (0x01)
        .... ..01 = Frame Type: Cluster-specific (0x1)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...0 .... = Disable Default Response: False
    Sequence Number: 76
    Command: Add Scene (0x00)
    Payload, String: Final Example
        Group ID: 0x0002
        Scene ID: 0x05
        Transition Time: 2 seconds
        Length: 13
        String: Final Example
        Extension Set: 06000101

Group related services

add_group

Add a group on the endpoint (or all endpoints).

service: zha_toolkit.add_group
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Group Id
  command_data: 0x0021
  # Optional endpoint
  endpoint: 1
  event_done: zha_done

get_groups

Get the groups defined on the endpoint (or all endpoints)

service: zha_toolkit.get_groups
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Optional endpoint
  endpoint: 1
  # Optional event
  event_done: zha_done

remove_group

Remove a group defined on the endpoint (or all endpoints)

service: zha_toolkit.remove_group
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Group Id
  command_data: 0x0021
  # Optional endpoint
  endpoint: 1
  # Optional event
  event_done: zha_done

remove_all_groups

service: zha_toolkit.remove_all_groups
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Optional endpoint
  endpoint: 1
  # Optional event
  event_done: zha_done

add_to_group

Similar to add_group but uses another method internally.

service: zha_toolkit.add_to_group
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Group Id
  command_data: 0x0021
  # Optional endpoint
  endpoint: 1
  # Optional event
  event_done: zha_done

remove_from_group

Similar to remove_group but uses another method internally.

service: zha_toolkit.remove_from_group
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Group Id
  command_data: 0x0021
  # Optional endpoint
  endpoint: 1
  # Optional event
  event_done: zha_done

get_zll_groups

Get groups on Zigbee Light Link cluster (uses get group identifiers)

service: zha_toolkit.get_zll_groups
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # Optional endpoint
  endpoint: 1
  # Optional event
  event_done: zha_done

EZSP/Bellows

ezsp refers to EmberZNet Serial Protocol proposed by Silicon Labs. bellows refers to the library providing the interface between zigpy and ezsp compatible zigbee solutions.

This section lists the commands that are used specifically with the bellows library.

The following commands are not documented:

  • ezsp_add_key
  • ezsp_clear_keys
  • ezsp_get_config_value
  • ezsp_get_ieee_by_nwk
  • ezsp_get_keys
  • ezsp_get_policy
  • ezsp_get_token
  • ezsp_get_value
  • ezsp_set_channel
  • ezsp_start_mfg

ezsp_backup: Backup ezsp/bellows network data

⚠️ Under test

Used to transfer to another coordinator later, backup or simply get network key and other info.

The output is written to {custom_component_dir}/local/nwk_backup{command_data}.json.

You can use the blueprint to setup daily backup: Open your Home Assistant instance and show the blueprint import dialog with the Daily backup blueprint pre-filled..

The name of that backup is according to the format

service: zha_toolkit.ezsp_backup
data:
  # Optional command_data, string added to the basename.
  # With this example the backup is written to `nwk_backup_20220105.json`
  command_data: _20220105

ZNP related (TI Zigbee Radio)

ZNP stands for "Zigbee Network Processor" and refers to the network layer proposed by TI's zigbee solutions. zigpy-znp refers to the plugin/library that provides the layer that interfaces zigpy with the ZNP radio.

This section lists the services that specifically target ZNP processors.

znp_nvram_backup: Backup ZNP NVRAM data

The output is written to the customization directory as local/nvram_backup.json when command_data is empty or not provided. When command_data is provided, it is added just after nvram_backup.

Note: currently under test.

service: zha_toolkit.execute
data:
  command: znp_nvram_backup
  # Optional command_data, string added to the basename.
  # With this example the backup is written to `nwk_backup_20220105.json`
  command_data: _20220105

znp_nvram_restore: Restore ZNP NVRAM data

Will restore ZNP NVRAM data from local/nvram_backup.json where local is a directory in the zha_toolkit directory.

Note: currently under test.

For safety, a backup is made of the current network before restoring local/nvram_backup.json. The name of that backup is according to the format local/nvram_backup_YYmmDD_HHMMSS.json.

service: zha_toolkit.znp_nvram_restore

znp_nvram_reset: Reset ZNP NVRAM data

Will reset ZNP NVRAM data from local/nvram_backup.json where local is a directory in the zha_toolkit directory.

Note: currently under test.

For safety, a backup is made of the current network before restoring local/nvram_backup.json. The name of that backup is according to the format local/nvram_backup_YYmmDD_HHMMSS.json.

service: zha_toolkit.znp_nvram_reset

znp_backup: Backup ZNP network data

Used to transfer to another ZNP key later, backup or simply get network key and other info.

The output is written to the customization directory as local/nwk_backup.json when command_data is empty or not provided. When command_data is provided, it is added just after "nwk_backup".

You can use the blueprint to setup daily backup: Open your Home Assistant instance and show the blueprint import dialog with the ZNP Daily backup blueprint pre-filled..

The name of that backup is according to the format nwk_backup{command_data}.json.

service: zha_toolkit.znp_backup
data:
  # Optional command_data, string added to the basename.
  # With this example the backup is written to `nwk_backup_20220105.json`
  command_data: _20220105

znp_restore: Restore ZNP network data

Will restore network data from local/nwk_backup.json where local is a directory in the zha_toolkit directory.

Note: currently under test.

For safety, a backup is made of the current network before restoring local/nwk_backup.json. The name of that backup is according to the format local/nwk_backup_YYmmDD_HHMMSS.json.

A typical use for this is when you migrate from one key to another.

The procedure should be:

  1. Backup using the znp_backup command in the zha_toolkit service. Verify that the nwk_backup.json file is generated in the local directory.
    1. Remove the original Coordinator from your system (e.g., remove the USB key, ...).
    2. Insert the new Coordinator.
    3. Only when migrating to a Coordinator with different port/serial path/socket.
      Remove/Disable the ZHA Integration from Home Assistant.
      The alternative is to modify HA’s config file directly to update the current integration’s serial path and baudrate
    4. Copy the zigbee.db file (for backup).
      Moving/renaming it should not be needed. If you Move or Rename the zigbee.db the Entity name are lost after the restore (which impacts your automations, UI, etc).
    1. Restart Home Assistant.
    2. Enable/Add the ZHA Integration to Home Assistant (needed if you disabled or removed the ZHA integration in step 2.iii.)
  2. Restore using the znp_restore command.
    (If you used a custom file name for the backup then make sure you copy it to nwk_backup.json).
  3. Check the logs (currently the pre_shutdown call failed for the first successful test, but that is not critical).
  4. Restart HA
  5. Check that everything is ok.

NOTES :

  • Devices may take a while to rejoin the network as the Zigbee specification requires them to "back-off" in case of communication problems.
  • You may speed up the process by power cycling devices.
  • Devices may not be instantly responsive because the zigbee mesh needs to be recreated (try the zdo_scan_now command to speed that up).

(See the Home Assistant Community Forum for a success story.)

service: zha_toolkit.execute
data:
  command: znp_restore
  # Optional:
  #  command_data = Counter_increment (for tx).
  #                 defaults to 2500
  command_data: 2500

Miscellaneous

backup: Backup the coordinator

The backup service starts a backup of the coordinator by calling upon znp_backup or ezsp_backup.

It provides a radio independent service for backups.

service: zha_toolkit.backup
data:
  # Optional command_data, string added to the basename.
  # With this example the backup is written to `nwk_backup_20220105.json`
  command_data: _20220105

misc_settime: Set attributes of a Time Cluster

Sets the time and DST configuration for a Time Cluster from HA's current time and default timezone.

The TimeStatus attribute is not set. You likely need to set it to 2 (synchronized).

Before and after writing, the attributes are read from the cluster and available in the event data, unless options disable these reads.

service: zha_toolkit.misc_settime
data:
  ieee: 5c:02:72:ff:fe:92:c2:5d
  # The endpoint is optional - by default the endpoint containing the Time Cluster
  endpoint: 11
  # You can set the next events to use as a trigger.
  # The event data has the result of the command (currently attr_read, attr_write)
  event_success: my_read_success_trigger_event
  event_fail: my_read_fail_trigger_event
  event_done: my_read_done_trigger_event
  # Settings for attr_write
  # Read attribute before writing it (defaults to True)
  read_before_write: true
  # Read attribute after writing it (defaults to True)
  read_after_write: true

ota_notify - Download/Trigger Device FW update

ota_notify helps you update the firmware of a zigbee device without restarting Home Assistant. It can use the already available firmware images, or download them using Koenkk/zigbee-OTA's list and resources. It also notifies the device that it should issue a request to be updated. That launches the update process.

OTA is the acronym for "Over the Air" and we implicitly add "update" or "upgrade".

You must have configured the otau_directory. This is where ZHA/zigpy looks for firmware images, and where downloaded firmware images will be placed.

ota_notify will indicate to the device that an update is available, which will trigger the device to request this update from the coordinator (in this case zigpy).

Prior to notifying the device, ota_notify will request all image providers to update the list of available images. By default, this is only done on startup, so when you add a new image to your local directory or when a new update is available from a third party, you'd have to restart HA. But with ota_notify no restart is required.

For details on how to setup your images sources, check the zigpy wiki section. Also read about the possibilities to enable logging, and that some devices require to be re-associated.

To trigger the OTA update, use ota_notify instead. The debug log is useful to check the update progress or indication that no update is available.
When the update starts, be patient: it can take a while.

service: zha_toolkit.ota_notify
data:
  # Reference of the device that should be notified about an update.
  # Using one of the entity/sensor names is so much easier !
  ieee: sensor.lixee_zlinky_tic_00000000_electrical_measurement
  # Optional, when true download images from info at https://github.com/Koenkk/zigbee-OTA
  download: true
  # Optional, directory to write OTA files to (default: same as ZHA configuration)
  path: /config/zb_ota

zha_devices: Device Information to Event or CSV or Script variable

Get Device information as event data or in a CSV file.

You can select the data fields in the CSV and the event data through the command_data parameter. If you do not provide a list, a default list is used for the CSV file, and all available data is provided in the devices field of the event data.

You also get this data in the 'devices' field of the generated events which allows you to get information about endpoints and services as well.

service: zha_toolkit.zha_devices
data:
  # Optional: Device to report on, by default all devices are in the report
  ieee: sensor.my_zha_sensor
  # Optional list of fields to write to the CSV, all non-list fields by default.
  command_data: [name, ieee, rssi, lqi]
  # Optional, field the list is sorted by (example: sort by signal strength)
  csvlabel: rssi
  csvout: ../www/devices.csv
  event_done: zha_devices

The above should write the CSV to the www directory, so it's available as 'INSTANCEURL/local/devices.csv' and you could add a button to your UI for downloading:

type: button
name: Devices CSV File
tap_action:
  action: url
  url_path: /local/devices.csv

See script_use_zha_devices.yaml to see how you can loop over the device list provided in the event data.

See script_use_zha_devices_response.yaml shows how a new method available since Home Assistant 2023.7 that allows us to avoid the complexity of event_data by using the response from the zha-toolkit service.

register_services: Reregister ZHA-Toolkit services

The services may have evolved after an update of the code and calling register_services will reload the services.yaml file defining the options available in the UI interface, as well as internal structures that define the validation rules for the parameters.

Most of the time this operation will be done automatically (when upgrading through HACS), but during development no version or file changes may be detected, and a manual update may be due for testing or accessing updated interfaces.

service: zha_toolkit.register_services

ha_set_state - Update HA state

Set/update any Home Assistant state.

service: zha_toolkit.ha_set_state
data:
  fail_exception: true
  state_id: sensor.mysensor
  attr_val: 10
  # optional Parameters
  state_attr: some_attribute
  allow_create: true
  # When defined, the read attribute is converted using this template string
  # before writing it to the state.
  # Note that no curly braces should be used here!
  state_value_template: value + 2
  csvout: set_state.csv
  csvlabel: Example reason

state_value_template is a template(-like) expression that is interpreted where attr_val is available as value and attr_value. This a template expression without the curly parentheses ({{ }}). If the curly parentheses are used, the expression would be expanded before the zha service code is entered which is incompatible with this functionality.

This is not strictly a zha specific tool, but useful in some scripting situations.

User method

You can add your own Python commands in local/user.py. Your file is reloaded on each call and will survive updates because it's inside the local directory.

Example of user_test that has the expected method signature, but just prints that it's executed:

import logging

LOGGER = logging.getLogger(__name__)


async def user_test(app, listener, ieee, cmd, data, service, params, event_data):
    LOGGER.debug(f"User test called")

The service call to execute it looks like this:

service: zha_toolkit.execute
data:
  command: user_test

You're free to reuse the parameters already available for the other commands. If you add your own, you'll need to parse them yourself from service.data. You can check out utils.py/extractParams to look for ideas, and you can examine the other methods to see how you can use ZHA.

This is a powerful tool to develop your own custom tool, and propose it for inclusion in the zha-toolkit when it's ready and of potential use to others.

Manufacturers

Tuya

Shame on Tuya to be a member of the Zigbee Alliance and deviate from the Zigbee Specifications.

These commands help fix some of that.

tuya_magic - Tuya Magic spell

This was labelled the standard tuya "magic spell" as it makes most Tuya devices work normally.

currently only the "read" part is implemented - if needed a super_magic_spell can be added to also execute the write procedure.

It has to be done using the "execute" command it's not implemented as a searchable service.

service: zha_toolkit.execute
data:
  command: tuya_magic
  ieee: light.tz3000_dbou1ap4_ts0505a_level_light_color_on_off

Credits/Motivation

This project was forked from Adminiguaga/zha_custom where the "hard tricks" for providing services and accessing ZHA functions were implemented/demonstrated. The original codeowners were "dmulcahey" and "Adminiuga".

The znp and ezsp backup core code is work originally created by @puddly either available in the official zigpy/zigpy_znp repository or the pudly/bellows fork.

The initial purpose of this fork was mainly to add custom attribute writes, custom reporting and more binding possibilities.

The structure was then updated to be compliant with HACS integration so that the component can be easily added to a Home Assistant setup.

License

I set the License the same as Home Assistant that has the ZHA component. The original zha_custom repository does not mention a license.

Contributing

#See Contributing.md

zha-toolkit's People

Contributors

adminiuga avatar bendikrb avatar conorsham avatar filmgarage avatar hedda avatar mattwestb avatar mdeweerd avatar nomis avatar pdecat avatar regevbr avatar theorlangur avatar tomasbedrich avatar wrt54g avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zha-toolkit's Issues

can not resart homeassistant after install zha_toolkit

Error info:
module 'homeassistant.helpers.config_validation' has no attribute 'entity_id_or_uuid'
Details:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 185, in handle_call_service
await hass.services.async_call(
File "/usr/src/homeassistant/homeassistant/core.py", line 1495, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1530, in _execute_service
await handler.job.target(service_call)
File "/usr/src/homeassistant/homeassistant/components/hassio/init.py", line 585, in async_handle_core_service
errors = await conf_util.async_check_ha_config_file(hass)
File "/usr/src/homeassistant/homeassistant/config.py", line 938, in async_check_ha_config_file
res = await check_config.async_check_ha_config_file(hass)
File "/usr/src/homeassistant/homeassistant/helpers/check_config.py", line 139, in async_check_ha_config_file
component = integration.get_component()
File "/usr/src/homeassistant/homeassistant/loader.py", line 522, in get_component
cache[self.domain] = importlib.import_module(self.pkg_path)
File "/usr/local/lib/python3.9/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1030, in _gcd_import
File "", line 1007, in _find_and_load
File "", line 986, in _find_and_load_unlocked
File "", line 680, in _load_unlocked
File "", line 850, in exec_module
File "", line 228, in _call_with_frames_removed
File "/config/custom_components/zha_toolkit/init.py", line 38, in
cv.entity_id_or_uuid, t.EUI64.convert
AttributeError: module 'homeassistant.helpers.config_validation' has no attribute 'entity_id_or_uuid'

attr_read: AttributeError: 'NoneType' object has no attribute 'aps_data_request'

executing this service call:

service: zha_toolkit.execute
data:
  command: attr_read
  ieee: 28:6d:97:00:01:12:aa:33
  cluster: 0xfc02
  attribute: 0x0000
  manf: 4673

i get this error:

2022-09-14 22:08:27.900 DEBUG (MainThread) [custom_components.zha_toolkit] event_data {'zha_toolkit_version': 'v0.8.16', 'zigpy_version': '0.50.3', 'zigpy_rf_version': None, 'ieee_org': 28:6d:97:00:01:12:aa:33, 'ieee': '28:6d:97:00:01:12:aa:33', 'command': 'attr_read', 'command_data': None, 'start_time': '2022-09-14T20:08:27.882539+00:00', 'errors': ['AttributeError("\'NoneType\' object has no attribute \'aps_data_request\'")'], 'params': {'cluster_id': 0, 'attr_id': 4, 'dir': 0, 'manf': 18035, 'tries': 1, 'expect_reply': True, 'args': [], 'read_before_write': True, 'read_after_write': True}, 'success': False}
2022-09-14 22:08:27.903 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: 'NoneType' object has no attribute 'aps_data_request'

any idea why?

here the full log and a scan of this device
error.log
multi_Samjin_000112aa33_scan_results-txt.json.txt

Binding manufacture cluster on more endpoints

I have one new device IKEA Symfonisk 2 with updated firmware and i need binding cluster 0xfc80 on EP 2 and 3 to the coordinator for getting the command from them and implanting them in one device quirk.
Device signature:

{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4476, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0006",
      "in_clusters": [
        "0x0000",
        "0x0001",
        "0x0003",
        "0x0020",
        "0x1000",
        "0xfc7c"
      ],
      "out_clusters": [
        "0x0003",
        "0x0004",
        "0x0006",
        "0x0008",
        "0x0019",
        "0x1000"
      ]
    },
    "2": {
      "profile_id": 260,
      "device_type": "0x0006",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0xfc80"
      ],
      "out_clusters": [
        "0x0003",
        "0x0004",
        "0xfc80"
      ]
    },
    "3": {
      "profile_id": 260,
      "device_type": "0x0006",
      "in_clusters": [
        "0x0000",
        "0x0003",
        "0xfc80"
      ],
      "out_clusters": [
        "0x0003",
        "0x0004",
        "0xfc80"
      ]
    }
  },
  "manufacturer": "IKEA of Sweden",
  "model": "SYMFONISK sound remote gen2",
  "class": "ikea.symfonisk.IkeaSYMFONISKgen2V2"
}

I trying bind IEEE with this command but wireshark is showing ZHA is not sending it.

service: zha_toolkit.bind_ieee
data:
  ieee: 1c:34:f1:ff:fe:78:57:15
  command_data: "0"
  cluster: 64640
  tries: 5

If is trying couster 6 is doing binding on EP 1 OK.
ZHA log then trying binding:

2023-03-05 10:46:33.254 DEBUG (MainThread) [zigpy.zcl] [0xBD72:1:0x0006] Received command 0x02 (TSN 24): toggle()
2023-03-05 10:46:33.256 DEBUG (MainThread) [zigpy.zcl] [0xBD72:1:0x0006] No explicit handler for cluster command 0x02: toggle()
2023-03-05 10:46:33.749 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Running websocket_api script
2023-03-05 10:46:33.750 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Executing step call service
2023-03-05 10:46:33.754 INFO (MainThread) [custom_components.zha_toolkit] Running ZHA Toolkit service: <ServiceCall zha_toolkit.bind_ieee (c:01GTRJMVWHZ68FHRHQ63QQ47K5): ieee=1c:34:f1:ff:fe:78:57:15, command_data=0, cluster=64640, tries=5>
2023-03-05 10:46:33.843 DEBUG (MainThread) [custom_components.zha_toolkit] module is <module 'custom_components.zha_toolkit' from '/config/custom_components/zha_toolkit/__init__.py'>
2023-03-05 10:46:33.855 DEBUG (MainThread) [custom_components.zha_toolkit.utils] Parameters '{'ieee': 1c:34:f1:ff:fe:78:57:15, 'command_data': '0', 'cluster': 64640, 'tries': 5}'
2023-03-05 10:46:33.857 DEBUG (MainThread) [custom_components.zha_toolkit.utils] Final manf 'None'
2023-03-05 10:46:33.860 DEBUG (MainThread) [custom_components.zha_toolkit] 'ieee' parameter: '1c:34:f1:ff:fe:78:57:15' -> IEEE Addr: '1c:34:f1:ff:fe:78:57:15'
2023-03-05 10:46:33.862 DEBUG (MainThread) [custom_components.zha_toolkit] Default handler for bind_ieee
2023-03-05 10:46:33.862 DEBUG (MainThread) [custom_components.zha_toolkit] Handler: <function command_handler_default at 0x8d3f9b20>
2023-03-05 10:46:33.863 DEBUG (MainThread) [custom_components.zha_toolkit] running default command: <ServiceCall zha_toolkit.bind_ieee (c:01GTRJMVWHZ68FHRHQ63QQ47K5): ieee=1c:34:f1:ff:fe:78:57:15, command_data=0, cluster=64640, tries=5>
2023-03-05 10:46:33.873 DEBUG (MainThread) [custom_components.zha_toolkit.default] Trying to import custom_components.zha_toolkit.binds to call bind_ieee
2023-03-05 10:46:33.885 DEBUG (MainThread) [custom_components.zha_toolkit.utils] NWK addr 0x0000 -> 00:0d:6f:ff:fe:12:db:36
2023-03-05 10:46:33.886 DEBUG (MainThread) [custom_components.zha_toolkit.utils] IEEE for get_device: 00:0d:6f:ff:fe:12:db:36
2023-03-05 10:46:33.888 DEBUG (MainThread) [custom_components.zha_toolkit.binds] 0xBD72: got endpoints [2, 3] for out-cluster 0xFC80
2023-03-05 10:46:33.892 DEBUG (MainThread) [custom_components.zha_toolkit.binds] 0xBD72: got endpoints [2, 3] for in cluster 0xFC80
2023-03-05 10:46:33.893 DEBUG (MainThread) [custom_components.zha_toolkit] event_data {'zha_toolkit_version': 'dev', 'zigpy_version': '0.53.2', 'zigpy_rf_version': '0.34.9', 'ieee_org': 1c:34:f1:ff:fe:78:57:15, 'ieee': '1c:34:f1:ff:fe:78:57:15', 'command': 'bind_ieee', 'command_data': '0', 'start_time': '2023-03-05T09:46:33.860528+00:00', 'errors': [], 'params': {'cluster_id': 64640, 'dir': 0, 'tries': 5, 'expect_reply': True, 'args': [], 'read_before_write': True, 'read_after_write': True}, 'result': {}, 'success': False}
2023-03-05 10:46:34.626 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xBD72](SYMFONISK sound remote gen2): Device seen - marking the device available and resetting counter
2023-03-05 10:46:34.628 DEBUG (MainThread) [homeassistant.components.zha.core.device] [0xBD72](SYMFONISK sound remote gen2): Update device availability - device available: True - new availability: True - changed: False

Can you pleas hinting my what i is doing wrong ?

Thanks in advance !!

Weird error - EZSP_BACKUP

Hi,

I tried to create a backup of my EZSP stick, but I got an error. Here's a snippet from my home-assistant.log:

2022-01-19 17:17:43 DEBUG (MainThread) [custom_components.zha_toolkit.utils] Parameters '{'command': 'ezsp_backup'}'
2022-01-19 17:17:43 DEBUG (MainThread) [custom_components.zha_toolkit] module is <module 'custom_components.zha_toolkit' from '/config/custom_components/zha_toolkit/__init__.py'>
2022-01-19 17:17:43 DEBUG (MainThread) [custom_components.zha_toolkit] event_data {'ieee_org': None, 'ieee': 'None', 'command': 'ezsp_backup', 'start_time': '2022-01-19T16:17:43.731062+00:00', 'errors': ['AttributeError("\'ControllerApplication\' object has no attribute \'_znp\'")'], 'params': {'cmd_id': None, 'endpoint_id': None, 'cluster_id': None, 'attr_id': None, 'attr_type': None, 'attr_val': None, 'min_interval': None, 'max_interval': None, 'reportable_change': None, 'dir': None, 'manf': None, 'tries': 1, 'expect_reply': True, 'args': [], 'state_id': None, 'state_attr': None, 'allow_create': False, 'event_success': None, 'event_fail': None, 'event_done': None, 'read_before_write': True, 'read_after_write': True, 'write_if_equal': False}, 'success': False}
2022-01-19 17:17:43 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: 'ControllerApplication' object has no attribute '_znp'

Apart from the fact that the error is not very descriptive for an end user, I also suspect that somethings going wrong. I'm calling the EZSP backup procedure, so, I don't expect something with znp in it. Can this be a bug? If not: what can I try to fix it?

Service zha_toolkit.execute is not exposed after fresh install

Hey
Just installed HACS + ZHA Toolkit (v0.8.13).
Here's the error I'm getting when launching the automation based on the supplied blueprint:

2022-08-24 16:02:32.091 ERROR (MainThread) [homeassistant.components.automation.daily_znp_backup_monthly_rotation_2] Daily ZNP Backup - Monthly rotation: Error executing script. Service not found for call_service at pos 1: Unable to find service zha_toolkit.execute
2022-08-24 16:02:32.096 ERROR (MainThread) [homeassistant.components.automation.daily_znp_backup_monthly_rotation_2] Error while executing automation automation.daily_znp_backup_monthly_rotation_2: Unable to find service zha_toolkit.execute

Also when trying to run the service manually (Developer > Services), the zha_toolkit.execute is not exposed as the rest of the services and fails when trying to manually execute.

2022-08-24 16:09:10.032 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Service not found for call_service at pos 1: Unable to find service zha_toolkit.execute
2022-08-24 16:09:10.037 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [548350774528] Error handling message: Unable to find service zha_toolkit.execute (unknown_error)

My system:
Home Assistant 2022.8.6
Supervisor 2022.08.3
Operating System 7.0
Frontend 20220802.0 - latest
Running on RPi 4

Fail to reinitialize

Feb 06 15:28:36 assistant hass[581]: 2023-02-06 15:28:36.475 WARNING (MainThread) [zigpy.device] Device <Device model='FLOALT panel WS 30x90' manuf='IKEA of Sweden' nwk=0xF044 ieee=00:0d:6f:ff:fe:5b:2e:63 is_initialized=False> failed to initialize due to unexpected error
Feb 06 15:28:36 assistant hass[581]: Traceback (most recent call last):
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy/device.py", line 177, in initialize
Feb 06 15:28:36 assistant hass[581]:     await self._initialize()
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy/util.py", line 131, in retry
Feb 06 15:28:36 assistant hass[581]:     r = await func()
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy/device.py", line 210, in _initialize
Feb 06 15:28:36 assistant hass[581]:     status, _, endpoints = await self.zdo.Active_EP_req(
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy/util.py", line 131, in retry
Feb 06 15:28:36 assistant hass[581]:     r = await func()
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy/device.py", line 297, in request
Feb 06 15:28:36 assistant hass[581]:     await self._application.request(
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy/application.py", line 690, in request
Feb 06 15:28:36 assistant hass[581]:     await self.send_packet(
Feb 06 15:28:36 assistant hass[581]:   File "/opt/assistant/lib64/python3.10/site-packages/zigpy_znp/zigbee/application.py", line 1012, in send_packet
Feb 06 15:28:36 assistant hass[581]:     route_status = await self._znp.request(
Feb 06 15:28:36 assistant hass[581]: AttributeError: 'NoneType' object has no attribute 'request'

Latest ZHA latest ZHA Toolkit latest HASS.

[SUGGESTION] Move this zha-toolkit repository to the shared zigpy organization?

@mdeweerd can I suggest that you consider asking/discussing the possibility of having your zha-toolkit repository moved from https://github.com/mdeweerd/zha-toolkit moved to the zigpy organization @ https://github.com/zigpy/ on GitHub so that the mainstream copy of this repo will stay there become upstream for shared access together by the collective of developers that make up the zigpy organization?

Note that "organization" is just GitHub's terminology as I understand it is more an informal collaboration between like-minded ZHA and zigpy developers in order to collect ZHA and zigpy projects ín one place and shared access rights, (noting that the zigpy organization on GitHub has no public members and that you must be a member to see who’s a part of that organization, which I am not myself).

https://github.com/zigpy/

Most ZHA related repositories have been moved there over time as a way for like-minded ZHA and zigpy developers that are members of the zigpy organization with yourself included can have shared ownership and access to your zha-toolkit repository and the other projects for collaboration within that community?

Moving it could potentially also help new ZHA developers take notice of this zha-toolkit project.

Hope that you at least will consider this option and if you think it is a good idea then hoping that you all could come to an agreement that will make everyone happy with you continuing this zha-toolkit repository under the zigpy organization together without getting offended by any ownership conflicts.

PS: Same people who are members of that zigpy organization on GitHub also share another GitHub organization called "zha-ng" (short for "ZHA next-generation"?) which contains additional early experimental projects before they became mature to be moved:

https://github.com/zha-ng

Can backups be backed up?

I installed zha_toolkit, whose installation worked exactly as the instructions say. I imported the blueprint, and it also runs exactly as it should. Great. Here is my request. I back up my HA implementation automatically to NextCloud where it is safe. I just examined the backup file, and the zigbee backup is not stored in a place where it would be backed up. Is there a way to integrate that so that the zigbee network is backed up on my server with the NC backup?

EDIT: There is a kludge with a shell_command. In my configuration.yaml I have:

shell_command:
  backup_zigbee_to_nextcloud: ls /config/custom_components/zha_toolkit/local/*.json | xargs -I% curl -u USER:PASSWORD -T "%" "http://NEXTCLOUD_IP:PORT/remote.php/dav/files/USER/zigbee/"

where everything in CAPS is specific to my nextcloud setup. Then created an automation to run this command daily.

Add SWBuild read before starting update (Was:OTA events not firing at the correct time)

I've setup the event_success, event_fail and event_done to use "ota_success" "ota_fail" and "ota_done" as event names and an automation that listens for the ota_done event to fire and send a notification to my phone when an update is done.

However all those three events seem to fire when initiating an update, so I get a notification as soon as I call the ota.notify service. but no event is fired when the update is actually finished.

All three events seem to fire when starting the update, not after its done.

module 'zigpy_znp' has no attribute '__version__'

Unable to run automation in new release of HASS (Home Assistant 2023.3.0)

Automation:
platform: time_pattern
minutes: /5
condition: []
action:
service: zha_toolkit.execute
data:
command: attr_read
ieee: 8c:f6:81:ff:fe:c4:2d:dc
cluster: 1029
attribute: 0
tries: 10
event_done: zha_done
service: zha_toolkit.execute
data:
command: attr_read
ieee: 8c:f6:81:ff:fe:c4:2d:dc
cluster: 1026
attribute: 0
tries: 10
event_done: zha_done
mode: single

Log/Error:

Logger: homeassistant.components.automation.manually_refresh_multi_sensors
Source: custom_components/zha_toolkit/utils.py:192
Integration: Automation (documentation, issues)
First occurred: 7:50:00 PM (4 occurrences)
Last logged: 7:50:38 PM

Manually Refresh Multi Sensors: Error executing script. Unexpected error for call_service at pos 1: module 'zigpy_znp' has no attribute 'version'
While executing automation automation.manually_refresh_multi_sensors
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 451, in _async_step
await getattr(self, handler)()
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 684, in _async_call_service_step
await service_task
File "/usr/src/homeassistant/homeassistant/core.py", line 1808, in async_call
task.result()
File "/usr/src/homeassistant/homeassistant/core.py", line 1845, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/config/custom_components/zha_toolkit/init.py", line 699, in toolkit_service
"zigpy_rf_version": u.get_radio_version(app),
File "/config/custom_components/zha_toolkit/utils.py", line 192, in get_radio_version
return zigpy_znp.version
AttributeError: module 'zigpy_znp' has no attribute 'version'

attr_type value for attr_write

I am a little confused what my attr_type value should be when I want to do an attr_write. I need to write a uint16. Could you please clarify?

I have found a list of the Zigbee data types here, which indicates my attr_type should probably be 0x21.

attr_val: 0x2710
attr_type: 0x21

2022-02-08 15:10:38 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [1706284752] Error handling message: Unknown error Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 27, in _handle_async_response await func(hass, connection, msg) File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 534, in handle_execute_script await script_obj.async_run(msg.get("variables"), context=context) File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1253, in async_run await asyncio.shield(run.async_run()) File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 354, in async_run await self._async_step(log_exceptions=False) File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 372, in _async_step await getattr(self, handler)() File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 575, in _async_call_service_step await service_task File "/usr/src/homeassistant/homeassistant/core.py", line 1630, in async_call task.result() File "/usr/src/homeassistant/homeassistant/core.py", line 1667, in _execute_service await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)( File "/config/custom_components/zha_toolkit/__init__.py", line 415, in toolkit_service raise handler_exception File "/config/custom_components/zha_toolkit/__init__.py", line 379, in toolkit_service await handler( File "/config/custom_components/zha_toolkit/zcl_attr.py", line 164, in attr_write attr_val = f.TypeValue(attr_type, t.FixedIntType(compare_val)) File "/usr/local/lib/python3.9/site-packages/zigpy/types/basic.py", line 57, in __new__ raise TypeError(f"{cls} is abstract and cannot be created") TypeError: <class 'zigpy.types.basic.FixedIntType'> is abstract and cannot be created

This occurs even if I pass attr_val: 10000 (both quoted and not)
Thanks!

AttributeError reading __name__ from a string

Aug 17 07:07:49 assistant hass[40674]: 2022-08-17 07:07:49.512 ERROR (MainThread) [homeassistant.core] Error executing service: <ServiceCall zha_toolkit.scan_device (c:01GAN9V6CQHGW1ANFBFEZSC0QF): ieee=00:17:88:01:0c:c3:a8:43, event_done=zha_done>
Aug 17 07:07:49 assistant hass[40674]: Traceback (most recent call last):
Aug 17 07:07:49 assistant hass[40674]:   File "/opt/assistant/lib64/python3.10/site-packages/homeassistant/core.py", line 1731, in catch_exceptions
Aug 17 07:07:49 assistant hass[40674]:     await coro_or_task
Aug 17 07:07:49 assistant hass[40674]:   File "/opt/assistant/lib64/python3.10/site-packages/homeassistant/core.py", line 1750, in _execute_service
Aug 17 07:07:49 assistant hass[40674]:     await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/__init__.py", line 698, in toolkit_service
Aug 17 07:07:49 assistant hass[40674]:     raise handler_exception
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/__init__.py", line 662, in toolkit_service
Aug 17 07:07:49 assistant hass[40674]:     await handler(
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/__init__.py", line 747, in command_handler_default
Aug 17 07:07:49 assistant hass[40674]:     await default.default(
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/default.py", line 33, in default
Aug 17 07:07:49 assistant hass[40674]:     await handler(app, listener, ieee, cmd, data, service, params, event_data)
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/scan_device.py", line 398, in scan_device
Aug 17 07:07:49 assistant hass[40674]:     scan = await scan_results(device, endpoints, manufacturer=manf)
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/scan_device.py", line 81, in scan_results
Aug 17 07:07:49 assistant hass[40674]:     endpoint.update(await scan_endpoint(ep, manufacturer))
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/scan_device.py", line 120, in scan_endpoint
Aug 17 07:07:49 assistant hass[40674]:     clusters[key] = await scan_cluster(
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/scan_device.py", line 154, in scan_cluster
Aug 17 07:07:49 assistant hass[40674]:     cmds_gen: await discover_commands_generated(cluster, is_server),
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/scan_device.py", line 360, in discover_commands_generated
Aug 17 07:07:49 assistant hass[40674]:     cmd_args = [arg.__name__ for arg in cmd_args]
Aug 17 07:07:49 assistant hass[40674]:   File "/var/lib/assistant/custom_components/zha_toolkit/scan_device.py", line 360, in <listcomp>
Aug 17 07:07:49 assistant hass[40674]:     cmd_args = [arg.__name__ for arg in cmd_args]
Aug 17 07:07:49 assistant hass[40674]: AttributeError: 'str' object has no attribute '__name__'

from the latest stable zha_toolkit published via HACS.

Implement configuration flow

Add an UI configuration flow which will make it easier to enable the toolkit (and disable/enable it dynamically).

The configuration flow could also lead to some globel defaults for:

  • event_fail, event_done, event_success: set a default event name applied to all services (which can be set on a per service call basis);
  • backup name format;
  • ... .

See https://github.com/home-assistant/architecture/blob/master/adr/0007-integration-config-yaml-structure.md for more information.

_TZ3210_frm6149r - wrong ota firmware applied

Apologies if this is the wrong place to report this. Please close if it is.

I (foolishly) sent an ota_notify command to the following LED strip controller using the zha toolkit inside Home Assistant. I think it flashed the wrong OTA firmware, as the device now appears as a power switch.

Can I use zha-toolkit to roll back/revert/reset to the previous firmware? I have not been able to find the device's firmware via Google

I reported this issue to the OTA repo here:
Koenkk/zigbee-OTA#174

Automation getting: 'Discarding _save_attribute event' using zha_toolkit.execute

Hi, anyone seen this error? Discarding _save_attribute event
I have two radiator values that my automation is reading the value open position of every 5mins. This is has been working great for many months but now I'm seeing this error in the logs. As far as I know... nothing has changed so I'm wondering why it's now failing to read the values. If I go to the device and directly read the value, the correct current value is being read and returned.

image

This error originated from a custom integration.

Logger: zigpy.appdb
Source: custom_components/zha_toolkit/utils.py:778
Integration: 🧰 ZHA Toolkit Service (documentation, issues)
First occurred: 10 January 2023 at 19:40:00 (1060 occurrences)
Last logged: 15:45:00

Discarding _save_attribute event

Automation is:

alias: Read additional thermostat values and store them to sensors
description: Read additional thermostat values and store them to sensors
trigger:
  - platform: time_pattern
    minutes: /5
condition: []
action:
  - service: zha_toolkit.execute
    data:
      command: attr_read
      ieee: 80:4b:50:ff:fe:4a:09:18
      endpoint: 1
      cluster: 513
      attribute: 16388
      state_id: sensor.lounge_radiator_thermostat_valve_raw
      allow_create: true
  - service: zha_toolkit.execute
    data:
      command: attr_read
      ieee: 84:fd:27:ff:fe:8a:ee:9c
      endpoint: 1
      cluster: 513
      attribute: 16388
      state_id: sensor.dining_radiator_thermostat_valve_raw
      allow_create: true

Manual read:
image

Remote as AlarmControlPanel device type

The zigbee remote controls (Heiman or Woox) are seen as an AlarmControlPanel. This is a choice of the integrators that does not correspond to the use

The problem is that if you want to monitor the events you will find that it sends several in a row and it is impossible to differentiate them.

The temporary solution is to process only the first one in single mode and pause it. But this is not a totally reliable solution, especially if you operate several of them...

I tried to change the type :

zha:
  device_config:
     a4:c1:38:96:0b:cf:xx:xx-1:
       type: "remote"  # or button

It doesn't work

I noticed that under Z2MQTT it works fine as a remote, the behavior is normal and we can process the information correctly.


> arm_day_zones
> arm_all_zones
> disarm
> emergency

So under ZHA we should be able to choose the operating mode.

I tried to play with clusters or ZhaToolkit without success...

Information and updates welcome...

all_routes_and_neighbours Exception

While executing all_routes_and_neighbours:

Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/core.py", line 1756, in catch_exceptions await coro_or_task File "/usr/src/homeassistant/homeassistant/core.py", line 1775, in _execute_service await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)( File "/config/custom_components/zha_toolkit/__init__.py", line 717, in toolkit_service raise handler_exception File "/config/custom_components/zha_toolkit/__init__.py", line 681, in toolkit_service await handler( File "/config/custom_components/zha_toolkit/__init__.py", line 766, in command_handler_default await default.default( File "/config/custom_components/zha_toolkit/default.py", line 33, in default await handler(app, listener, ieee, cmd, data, service, params, event_data) File "/config/custom_components/zha_toolkit/neighbours.py", line 79, in all_routes_and_neighbours await _routes_and_neighbours(device, listener) File "/config/custom_components/zha_toolkit/neighbours.py", line 43, in _routes_and_neighbours nbns = await asyncio.wait_for(async_get_neighbours(device), 180) File "/usr/local/lib/python3.10/asyncio/tasks.py", line 445, in wait_for return fut.result() File "/config/custom_components/zha_toolkit/neighbours.py", line 167, in async_get_neighbours neighbors = val.NeighborTableList AttributeError: 'Neighbors' object has no attribute 'NeighborTableList'

Would be great to have it working !
Boris.

[Feature] Notify OTA updates

It would be awesome to be able to hook into ZHA to be able to trigger automations when OTA update events occur.

My use case: I've had some issues recently with some IKEA devices behaving weirdly and it took me time to understand they were caused by recent OTA updates.

PS: not sure it is even feasible without modifying ZHA.

[Feature Request] Force state update

A common issue with ZHA is that the state does not update correctly for a few devices in HA after a batch or light group turn_off/turn_on command.

It would be great to have a service call to request state updates from device(s)/groups that we could call after a batch command.

deprecated `async_get_registry` In core 2022.6.x

Thanks for this great toolkit! Since core 2022.6 a deprecated call is used:

Logger: homeassistant.helpers.frame
Source: helpers/frame.py:103 
First occurred: 10:20:00 (2 occurrences) 
Last logged: 10:20:00

Detected integration that uses deprecated `async_get_registry` to access entity registry, use async_get instead. Please report issue to the custom component author for zha_toolkit using this method at custom_components/zha_toolkit/utils.py, line 220: await listener._hass.helpers.entity_registry.async_get_registry()
Detected integration that uses deprecated `async_get_registry` to access device registry, use async_get instead. Please report issue to the custom component author for zha_toolkit using this method at custom_components/zha_toolkit/utils.py, line 232: await listener._hass.helpers.device_registry.async_get_registry()

Device name with `/` make scan_device crash

Device name that contains / generate error while using zha_toolkit.scan_device. (eg: NHPB/SHUTTER/1)

Logs
FileNotFoundError: [Errno 2] No such file or directory: '/config/scans/NHPB/SHUTTER/tmpv0p8u0dy'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/core.py", line 1731, in catch_exceptions
await coro_or_task
File "/usr/src/homeassistant/homeassistant/core.py", line 1750, in _execute_service
await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
File "/config/custom_components/zha_toolkit/__init__.py", line 697, in toolkit_service
raise handler_exception
File "/config/custom_components/zha_toolkit/__init__.py", line 661, in toolkit_service
await handler(
File "/config/custom_components/zha_toolkit/__init__.py", line 746, in command_handler_default
await default.default(
File "/config/custom_components/zha_toolkit/default.py", line 33, in default
await handler(app, listener, ieee, cmd, data, service, params, event_data)
File "/config/custom_components/zha_toolkit/scan_device.py", line 422, in scan_device
u.write_json_to_file(
File "/config/custom_components/zha_toolkit/utils.py", line 401, in write_json_to_file
save_json(file_name, data)
File "/usr/src/homeassistant/homeassistant/util/json.py", line 94, in save_json
write_utf8_file(filename, json_data, private)
File "/usr/src/homeassistant/homeassistant/util/file.py", line 70, in write_utf8_file
raise WriteError(error) from error
homeassistant.util.file.WriteError: [Errno 2] No such file or directory: '/config/scans/NHPB/SHUTTER/tmpv0p8u0dy'

Should we create safer filename by simply replacing / by - or add directory creation based on device name ?

Logo suggestion

What about a new logo for the ZHA toolbox that is more related to the Zitbeen look and feel?

I have the following suggestion:

logo

What do you think about it?

Version change reported

I have a strange issue using zha-toolkit in the lateset version with the latest HA 2022.8.x
When my automations call the toolkit the following happens and zha-toolkit is litterally restarted:

2022-08-10 16:36:23.395 INFO (MainThread) [homeassistant.components.automation.ext_temp_wohnzimmer_couch_update] 011.9 Ext_Temp_Wohnzimmer.update: Running automation actions
2022-08-10 16:36:23.395 INFO (MainThread) [homeassistant.components.automation.ext_temp_wohnzimmer_couch_update] 011.9 Ext_Temp_Wohnzimmer.update: Executing step call service
2022-08-10 16:36:23.419 INFO (MainThread) [homeassistant.components.script.danfossgeneric_update_ext_temperature] DANFOSS.generic_update_ext_temperature: Running script sequence
2022-08-10 16:36:23.419 INFO (MainThread) [homeassistant.components.script.danfossgeneric_update_ext_temperature] DANFOSS.generic_update_ext_temperature: Executing step call service
2022-08-10 16:36:23.426 INFO (MainThread) [custom_components.zha_toolkit] Running ZHA Toolkit service: <ServiceCall zha_toolkit.attr_write (c:01GA42YRYVJVP9DVS2W8AS7646): ieee=84:2e:14:ff:fe:62:0d:bb, endpoint=1, cluster=513, attribute=16405, attr_val=2540, tries=3>
2022-08-10 16:36:23.451 DEBUG (MainThread) [custom_components.zha_toolkit] module is <module 'custom_components.zha_toolkit' from '/config/custom_components/zha_toolkit/__init__.py'>
2022-08-10 16:36:23.456 DEBUG (MainThread) [custom_components.zha_toolkit.utils] Read version from /config/custom_components/zha_toolkit/manifest.json 1655277700.195671<>0
2022-08-10 16:36:23.457 DEBUG (MainThread) [custom_components.zha_toolkit] Reload services because version changed from  to v0.8.11

This has some side effects I don't understand so far but at least one my switches shorty goes on and off without me seeing anything in the HA protocol unfortunately.

I tried it with re-installation of HACS and zha-toolkit but that doesn't help. Also in the runup there is something strange:

2022-08-10 17:16:39.305 DEBUG (MainThread) [custom_components.hacs] <Integration mdeweerd/zha-toolkit> Running checks against v0.8.11
2022-08-10 17:16:39.743 DEBUG (MainThread) [custom_components.hacs] 'states' is undefined
2022-08-10 17:16:39.770 DEBUG (MainThread) [custom_components.hacs] unexpected char '`' at 1364
2022-08-10 17:16:40.134 DEBUG (MainThread) [custom_components.hacs] unexpected char '\\' at 21072

Maybe it's related to HACS itself? Any help appreciated.

Wrong byte order in scan_device filename

Thanks for this toolkit. I tried the scan_device for a couple of devices and the resulting filename was always the same for all devices. The devices are from the same manufacturer and are all of the same model. The only difference is just one byte in the IEEE address. The current code uses the first 4 bytes instead of the last 5 bytes of the IEEE and this also in reverse order and this results in the same filename for the different devices. The spec says the first 3 bytes of the IEEE defines the manufacturer and the last 5 bytes are defined by the manufacturer.

The following fixes this for me:

    if model is not None and manufacturer is not None:
        ieee_tail = "".join([f"{o:02x}" for o in ieee[4::-1]])
        file_name = f"{model}_{manufacturer}_{ieee_tail}_scan_results.txt"
    else:
        ieee_tail = "".join([f"{o:02x}" for o in ieee[::-1]])
        file_name = f"{ieee_tail}_scan_results.txt"

Can get any of the zha_toolkit services to run'

In Developer Tools/Services I run:

service: zha_toolkit.backup
data:
  command_data: _initial

In the log I get:

2022-10-26 20:28:05.924 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Running websocket_api script
2022-10-26 20:28:05.925 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Executing step call service
2022-10-26 20:28:05.927 INFO (MainThread) [custom_components.zha_toolkit] Running ZHA Toolkit service: <ServiceCall zha_toolkit.backup (c:01GGBM99N3V4NGXHAEK1K16X24): command_data=_initial>
2022-10-26 20:28:05.964 DEBUG (MainThread) [custom_components.zha_toolkit] module is <module 'custom_components.zha_toolkit' from '/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py'>
2022-10-26 20:28:05.972 DEBUG (MainThread) [custom_components.zha_toolkit.utils] Parameters '{'command_data': '_initial'}'
2022-10-26 20:28:05.972 DEBUG (MainThread) [custom_components.zha_toolkit.utils] Final manf 'None'
2022-10-26 20:28:05.973 DEBUG (MainThread) [custom_components.zha_toolkit] Default handler for backup
2022-10-26 20:28:05.973 DEBUG (MainThread) [custom_components.zha_toolkit] Handler: <function command_handler_default at 0x7fced3ade3a0>
2022-10-26 20:28:05.973 DEBUG (MainThread) [custom_components.zha_toolkit] running default command: <ServiceCall zha_toolkit.backup (c:01GGBM99N3V4NGXHAEK1K16X24): command_data=_initial>
2022-10-26 20:28:05.976 DEBUG (MainThread) [custom_components.zha_toolkit.default] Trying to import custom_components.zha_toolkit.misc to call backup
2022-10-26 20:28:06.027 DEBUG (MainThread) [custom_components.zha_toolkit] event_data {'zha_toolkit_version': 'v0.8.20', 'zigpy_version': '0.51.3', 'zigpy_rf_version': '0.34.2', 'ieee_org': None, 'ieee': 'None', 'command': 'backup', 'command_data': '_initial', 'start_time': '2022-10-27T02:28:05.973004+00:00', 'errors': ['AssertionError()'], 'params': {'dir': 0, 'tries': 1, 'expect_reply': True, 'args': [], 'read_before_write': True, 'read_after_write': True}, 'success': False}
2022-10-26 20:28:06.028 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: 
Traceback (most recent call last):
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 684, in _async_call_service_step
    await service_task
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/core.py", line 1738, in async_call
    task.result()
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/core.py", line 1775, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py", line 717, in toolkit_service
    raise handler_exception
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py", line 681, in toolkit_service
    await handler(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py", line 766, in command_handler_default
    await default.default(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/misc.py", line 60, in backup
    await ezsp.ezsp_backup(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/ezsp.py", line 328, in ezsp_backup
    result = await bellows_backup._backup(app._ezsp)
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/bellows/cli/backup.py", line 88, in _backup
    assert status == t.EmberStatus.SUCCESS
AssertionError
2022-10-26 20:28:06.036 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140526569325616] Error handling message: Unknown error (unknown_error)
Traceback (most recent call last):
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/components/websocket_api/decorators.py", line 27, in _handle_async_response
    await func(hass, connection, msg)
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/components/websocket_api/commands.py", line 648, in handle_execute_script
    await script_obj.async_run(msg.get("variables"), context=context)
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 1524, in async_run
    await asyncio.shield(run.async_run())
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 409, in async_run
    await self._async_step(log_exceptions=False)
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 453, in _async_step
    self._handle_exception(
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 476, in _handle_exception
    raise exception
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 684, in _async_call_service_step
    await service_task
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/core.py", line 1738, in async_call
    task.result()
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/homeassistant/core.py", line 1775, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py", line 717, in toolkit_service
    raise handler_exception
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py", line 681, in toolkit_service
    await handler(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/__init__.py", line 766, in command_handler_default
    await default.default(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/misc.py", line 60, in backup
    await ezsp.ezsp_backup(
  File "/home/homeassistant/.homeassistant/custom_components/zha_toolkit/ezsp.py", line 328, in ezsp_backup
    result = await bellows_backup._backup(app._ezsp)
  File "/home/homeassistant/homeassistant/lib/python3.9/site-packages/bellows/cli/backup.py", line 88, in _backup
    assert status == t.EmberStatus.SUCCESS
AssertionError

Same thing happens for all zha_toolkit services.

I am running core Home Assistant 2022.10.5 (Frontend 20221010.0) and zha_toolkit 0.8.20

What can I do to fix it, or find the problem?

Thanks!

Error on binds_remove_all

When trying to remove all binds on a light, I get the following error.

zha_toolkit_version: v0.8.19
zigpy_version: 0.51.3
zigpy_rf_version: 0.19.0

websocket_api script: Error executing script. Unexpected error for call_service at pos 1: 'dst_ieee'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 684, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1738, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1775, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/config/custom_components/zha_toolkit/__init__.py", line 717, in toolkit_service
    raise handler_exception
  File "/config/custom_components/zha_toolkit/__init__.py", line 681, in toolkit_service
    await handler(
  File "/config/custom_components/zha_toolkit/__init__.py", line 766, in command_handler_default
    await default.default(
  File "/config/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/config/custom_components/zha_toolkit/binds.py", line 418, in binds_remove_all
    raise e
  File "/config/custom_components/zha_toolkit/binds.py", line 361, in binds_remove_all
    dst_ieee = t.EUI64.convert(binding["dst"]["dst_ieee"])
KeyError: 'dst_ieee'

Equivalent to 're-configure device' in ZHA toolkit?

I have to situations where I was to reconfigure a device programmatically.

One is a lightbulb that misbehaves (stops obeying it’s bound switch) and then fixes itself when reconfigured.
The second is a battery powered device in an inaccessible place that I accidentally unbound from the co-ordinator but does send ‘checkin’ requests - so I want to send a re-configure request when I know its awake (when it checks in)

Is there a service call in ZHA-toolkit to call the ZHA ‘reconfigure device’ option?

If so I could build an automation to do this for me.

Bug in last release 0.7.23

Hi,

with the update from 0.7.22 to 0.7.23 I get the following error:

  File "/config/custom_components/zha_toolkit/utils.py", line 178, in get_radio_version
    import deconz
ModuleNotFoundError: No module named 'deconz'

This is a little bit nasty as the toolkit is not working right anymore 😏 reverting back to 0.7.22 fixed the issue for me.

Problem with write attribute to TS011F

Hi,
Thank you for your work. I found this addon when I searched how to delete energy delivered from my Smart Socket.
I try reset this value to 0. First. I read this attribute. I wrote:

service: zha_toolkit.attr_read
data:
  cluster: 1794
  attribute: 0
  csvout: test.csv
  ieee: sensor.microwave_oven_energy

And I got:
2023-02-02T20:01:51.332227+00:00,TuyaZBMeteringCluster,current_summ_delivered,154,0x0000,0x0702,1,a4:c1:38:48:57:68:9f:fd,,0x25
And it is ok. Mayby one problem, when I used cluster: 0x0702 nothing happned.
Next I tried cange this value:

service: zha_toolkit.attr_write
data:
  ieee: sensor.microwave_oven_energy
  cluster: 1794
  attribute: 0
  read_before_write: true
  read_after_write: true
  csvout: test.csv
  attr_val: "0"

But nothing happened. A green tick appeared on the button but, no new lines in test.csv file. I tried change "0" to '0' or 0. Not helped. When is empty I can't execute service, so, IMHO, the command syntax is correct
Am I doing something wrong or is it just not possible to change this value?
I'm new to Zigbee and controlling it, so I chose ZHA integration because it seems the simplest. From the ZHA level I can also manage this cluster and read the value 154, but to change it I need the manufacturer's code, which I don't know what it is and I don't know where to find it. It seemed to me that using your add-on I would be able to do without this code.
obraz

Deprication warning

Hi
Just to inform you. Since the update to core 2022.10, this warning is logged:

Logger: homeassistant.helpers.frame
Source: helpers/frame.py:77 
First occurred: 11:50:33 (2 occurrences) 
Last logged: 11:50:33

Detected integration that uses deprecated `async_get_registry` to access entity registry, use async_get instead. Please report issue to the custom integration author for zha_toolkit using this method at custom_components/zha_toolkit/utils.py, line 239: await listener._hass.helpers.entity_registry.async_get_registry()
Detected integration that uses deprecated `async_get_registry` to access device registry, use async_get instead. Please report issue to the custom integration author for zha_toolkit using this method at custom_components/zha_toolkit/utils.py, line 256: await listener._hass.helpers.device_registry.async_get_registry()

Errors on bind commands

Getting some errors in homeasssistant 2022.4.2

2022-04-14 09:40:02 DEBUG (MainThread) [custom_components.zha_toolkit] 'ieee' parameter: 'b4:e3:f9:ff:fe:bc:5b:fc' -> IEEE Addr: 'b4:e3:f9:ff:fe:bc:5b:fc'
2022-04-14 09:40:02 DEBUG (MainThread) [custom_components.zha_toolkit] Default handler for binds_remove_all
2022-04-14 09:40:02 DEBUG (MainThread) [custom_components.zha_toolkit] Handler: <function command_handler_default at 0x7f6da295e0>
2022-04-14 09:40:02 DEBUG (MainThread) [custom_components.zha_toolkit] running default command: <ServiceCall zha_toolkit.binds_remove_all (c:c6fc95b97c8eb4fc8c887c17636f3e03): ieee=b4:e3:f9:ff:fe:bc:5b:fc>
2022-04-14 09:40:02 DEBUG (MainThread) [custom_components.zha_toolkit.default] Trying to import custom_components.zha_toolkit.binds to call binds_remove_all
2022-04-14 09:40:22 DEBUG (MainThread) [custom_components.zha_toolkit] event_data {'zha_toolkit_version': 'v0.8.0', 'zigpy_version': '0.44.1', 'zigpy_rf_version': '0.15.0', 'ieee_org': b4:e3:f9:ff:fe:bc:5b:fc, 'ieee': 'b4:e3:f9:ff:fe:bc:5b:fc', 'command': None, 'command_data': None, 'start_time': '2022-04-14T08:40:02.452267+00:00', 'errors': ["DeliveryError('[0x4b65:0:0x0033]: Message send failure')"], 'params': {'dir': 0, 'tries': 1, 'expect_reply': True, 'args': [], 'read_before_write': True, 'read_after_write': True}, 'replies': [], 'success': False}
2022-04-14 09:40:22 ERROR (MainThread) [homeassistant.core] Error executing service: <ServiceCall zha_toolkit.binds_remove_all (c:c6fc95b97c8eb4fc8c887c17636f3e03): ieee=b4:e3:f9:ff:fe:bc:5b:fc>
  File "/config/custom_components/zha_toolkit/__init__.py", line 693, in toolkit_service
  File "/config/custom_components/zha_toolkit/__init__.py", line 657, in toolkit_service
  File "/config/custom_components/zha_toolkit/__init__.py", line 742, in command_handler_default
  File "/config/custom_components/zha_toolkit/default.py", line 33, in default
  File "/config/custom_components/zha_toolkit/binds.py", line 345, in binds_remove_all
  File "/config/custom_components/zha_toolkit/binds.py", line 453, in binds_get

Error after invoking scan_device

Hello,

I'm using HA core 2022.4.1 with ZHA Toolkit 0.8.0. When I try to invoke scan_device, in UI there appeears error "Unknown error", in logs:

2022-04-10 20:08:37 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: Failed to convert manufacturer=b'' from type <class 'bytes'> to <class 'zigpy.types.basic.uint16_t'>
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/zigpy/types/struct.py", line 39, in _convert_type
return self.type(value)
File "/usr/local/lib/python3.9/site-packages/zigpy/types/basic.py", line 61, in new
n = super().new(cls, *args, **kwargs)
ValueError: invalid literal for int() with base 10: b''

full log is attached. Scanned device is Smart Air Zigbee sensor, Quirk: zhaquirks.tuya.air.ts0601_air_quality.TuyaCO2SensorGPP. Same error I receive when I scan Zigbee Immax Plug-230V-ZB3.0 - both devices also support Router function, could that be connected?

Same error was there even on previous version of HA & ZHA Toolkit - I tried to solve it by upgrading both, but unfortunately it didn't help. Is anyone experiencing same issue?

Thanx Jarda

Wrong type Init with data16

Hi.
I used this integration for test a zigbee device.
I noticed that during data16 attributes write it crashes. In particular utils.py try to create an object data16 which at the end is a list. The list in python cannot be made by int argument so it crashes. Locally I resolved it converting int to bytes array.
Line 607 of utils.py
compare_val = data_type(str2int(attr_val_in))
Breaks. So I just converted attr_val_in to bytes array and it works.
Is it right?

Read EPs

I was trying scan_device and many device have ZCL r8 attributes (tuya and IKEA with updated firmware) and tuya have very much undocumented attributes hidden little here and there !!

I have one problem redig attribute on cluster that ZHA have not configured all endpoints that was not initiated then the device was being pared (TS004F with working mode switched) then ZHA is only reading the device endpoints then it inisinating the device and cant doing it later.
Is it possible implanting command for reading the device endpoint and also doing it before and using it then doing the attribute scan ?

Thanks for great work and its very good functions you is adding to our system for more advance users and devs !!!

'Unable to find service zha_toolkit.execute'

I have not idea with this happens, but the ZHA_TOOLKIT integration kind of "disappear" from time to time, maybe after a soft reload.
When I do a complete server reboot, the service is working, but after a HASC package install, or some automation reload, the service disapear, and I see the following message in the logs:

Service not found for call_service at pos 1: Unable to find service zha_toolkit.execute

Handling Chameleon devices that ZHA dont like.

So back to the TS004F is one "normal tuya Zigbee devices".
Its standard mode is one dimmer switch with one EP and mess of cluster.

        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.DIMMER_SWITCH,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    OnOff.cluster_id,
                    LightLink.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Time.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },

Firs i was deleting the in on/off and group cluster in the quirk because is not one its not long light or outlet. Later i was finding that group binding of On/off and level cluster was not working but adding the group cluster as is ZHA making it possible adding in groups as one loght.
The OnOff cluster as out is OK but if adding it as one in cluster ZHA is making one light switch in the GU that is not wanted then its having no output relay or LED drive.

Then we is coming to mode switching of the device.
By sending 1 to attribute 0x8004 on the out on/off cluster is start sending commands with unicast from it but with "custom values" for click, bobble and hold from button 1 on EP1.
We have found that tuya is casting some magic spells then initiating the device by first reading some attributes and the sending one leave with rejoin and then its sending device accouterments they is sending the 0x8004 with value 1 to the on/off cluster and its start using EP 2-4.
My problem is that ZHA is cant re reading the EPs after the device is inseminated.

My test is now sending this commands with your tool but its not working.
I have implanted the custom attribute in tuya INIT and with the right quirk loaded i can reading and sending the attribute on the on/off out cluster. The implementation: https://github.com/zigpy/zha-device-handlers/blob/23a166902e50d5c32019e0d4d32a968715041bb6/zhaquirks/tuya/__init__.py#L857

So i think its little strange ZHA cad sending and receiving the attribute but the tool is not.

By the way its easier saying what is OK with this device then what is not and its not Zigbee certified and 90% of all tuya devices but the problem many users is having them and like getting the 12 "scene commands" working. I like getting both modes working OK so its also possible using it as one good dimmer switch and also sending clicks if the user preferring that.

If i can sending and reading attribute with tool its being easier testing then trying doing it in the quirk code then no one have helping getting it working only some example that is broken then the syntax is wrong and / or the import is not correct and i cant getting it working then my code knowledge is to low.

Back to code:

service: zha_toolkit.attr_read
data:
  endpoint: 1
  cluster: 6
  attribute: 32772
  ieee: 60:a4:23:ff:fe:fd:dc:14

is generating error but the device is having one 0x0006 out cluster after the quirk is loaded.
The replace in the quirks is for the moment like this:

   replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,  # Is needed for adding group then binding is not working.
                    LightLink.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Ota.cluster_id,
                    Time.cluster_id,
                    Identify.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaSmartRemoteOnOffCluster,
#                    TuyaZBOnOffAttributeCluster,
                    LevelControl.cluster_id,
                    Color.cluster_id,
                    LightLink.cluster_id,
                ],
            },

The 2 On/Off cluster types is for normal ONOff with extra attribute and the other with tuya "scene" commands but only one is activated at one time then testing then its not OK having two cluster of same type on one EP in ZIgbee.

Thanks for support and great coding !!

Error on scan device command

service: zha_toolkit.scan_device
data:
  ieee: light.livingroom_window_right
  endpoint: 1

gives:

This error originated from a custom integration.

Logger: homeassistant.helpers.script.websocket_api_script
Source: custom_components/zha_toolkit/scan_device.py:91
Integration: 🧰 ZHA Toolkit Service (documentation, issues)
First occurred: 13:07:26 (5 occurrences)
Last logged: 13:07:52

websocket_api script: Error executing script. Unexpected error for call_service at pos 1: local variable 'endpoint' referenced before assignment
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 379, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 582, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1634, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1671, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/config/custom_components/zha_toolkit/__init__.py", line 692, in toolkit_service
    raise handler_exception
  File "/config/custom_components/zha_toolkit/__init__.py", line 656, in toolkit_service
    await handler(
  File "/config/custom_components/zha_toolkit/__init__.py", line 741, in command_handler_default
    await default.default(
  File "/config/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/config/custom_components/zha_toolkit/scan_device.py", line 394, in scan_device
    scan = await scan_results(device, endpoints, manufacturer=manf)
  File "/config/custom_components/zha_toolkit/scan_device.py", line 91, in scan_results
    ep_result.append(endpoint)
UnboundLocalError: local variable 'endpoint' referenced before assignment

I'm using a Silicon Labs EZSP stick and trying to scan a Signify (Philips Hue) E27 light (LCT015)

zha_toolkit.execute command: attr_read - read error

Hi, I'm trying to use zha-toolkit to read an attribute from a IR Blaster, but I get the below error:

data:
  command: attr_read
  ieee: 18:7a:3e:ff:fe:2f:04:34
  endpoint: 0x0001
  cluster: 0xe004
  attribute: 0x0000
  state_id: sensor.lounge_ir_blaster_read_code
  allow_create: true
This error originated from a custom integration.

Logger: custom_components.zha_toolkit.zcl_attr
Source: custom_components/zha_toolkit/zcl_attr.py:303
Integration: 🧰 ZHA Toolkit (documentation, issues)
First occurred: 22:23:48 (2 occurrences)
Last logged: 22:28:14

Result: [ReadAttributeRecord(attrid=0x0000)] - Attribute 0 not in read ({0: 'DUAjlBEoAigCXQJ9Bl0CQAdAA8ALQAcDfQYoAoABgAuAD8ALAV0CgAsBXQKAAwUoAigCXQLAAwR9Bl0CKGABQAeAAwJ9BijgAAMBKAJADwldAt6cQCO5CCgC'}, [ReadAttributeRecord(attrid=0x0000)])

Example of it working using the Manager Zigbee Device tool:
image

Am I doing something wrong or is there something odd going on.

Contactor Legrand 412171

The contactor Legrand 412171 (or 70) is recognized in ZHA, by default it is in HC/HP mode but the option to switch it to on/off mode is not present (unlike z2m).

To add this you can theoretically do it with ZHA services or ZHA Toolkit but it doesn't work or I missed something (change attribute 0 of cluster 0xfc01 (6512) from 4 to 3).

Anyway, I'm stumped, if someone has already played with these functions...

  "config" : [
    {"endpoint" : 1,"cluster":64513,"attribute":0,"manufacturer":64513,"name":"Mode","type":"select","values":[{"value":3,"name":"on/off"},{"value":4,"name":"hp/hc"}]},
    {"endpoint" : 1,"cluster":64513,"attribute":1,"manufacturer":64513,"name":"Led dark","type":"select","values":[{"value":0,"name":"Off"},{"value":1,"name":"On"}]},
    {"endpoint" : 1,"cluster":64513,"attribute":2,"manufacturer":64513,"name":"Led if on","type":"select","values":[{"value":0,"name":"Off"},{"value":1,"name":"On"}]}
  ],
My test:
`service: zha_toolkit.attr_write
data:
  ieee: 00:04:74:00:00:83:f4:f6
  endpoint: 1
  cluster: 64513
  attribute: 0
  attr_val: "3"
  attr_type: 0x21
  manf: 4129
  allow_create: true`

Merci ;-)

SQL error due to 🧰 icon in description

( Reported by @jes1417 )
Seeing this in my logs

Logger: homeassistant.components.recorder.core
Source: components/recorder/core.py:760
Integration: Recorder (documentation, issues)
First occurred: 12:24:38 AM (1 occurrences)
Last logged: 12:24:38 AM

Unhandled database error while processing task EventTask(event=<Event state_changed[L]: entity_id=update.zha_toolkit_service_for_advanced_zigbee_usage_update, old_state=None, new_state=<state update.zha_toolkit_service_for_advanced_zigbee_usage_update=off; auto_update=False, installed_version=v0.8.11, in_progress=False, latest_version=v0.8.11, release_summary=None, release_url=https://github.com/mdeweerd/zha-toolkit/releases/v0.8.11, skipped_version=None, title=None, entity_picture=https://brands.home-assistant.io/_/zha_toolkit/icon.png, friendly_name=🧰 ZHA Toolkit - Service for advanced Zigbee Usage update, supported_features=21 @ 2022-08-15T00:22:31.560428-05:00>>): (MySQLdb.OperationalError) (1267, "Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb3_general_ci,COERCIBLE) for operation '='") [SQL: SELECT state_attributes.attributes_id FROM state_attributes WHERE state_attributes.hash = %s AND state_attributes.shared_attrs = %s] [parameters: (438846145, '{"auto_update":false,"installed_version":"v0.8.11","latest_version":"v0.8.11","release_url":"https://github.com/mdeweerd/zha-toolkit/releases/v0.8.11","skipped_version":null,"title":null,"friendly_name":"🧰 ZHA Toolkit - Service for advanced Zigbee Usage update"}')] (Background on this error at: https://sqlalche.me/e/14/e3q8)
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1819, in _execute_context
    self.dialect.do_execute(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
    cursor.execute(statement, parameters)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 206, in execute
    res = self._query(query)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 319, in _query
    db.query(q)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/connections.py", line 254, in query
    _mysql.connection.query(self, query)
MySQLdb.OperationalError: (1267, "Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb3_general_ci,COERCIBLE) for operation '='")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 645, in _process_one_task_or_recover
    return task.run(self)
  File "/usr/src/homeassistant/homeassistant/components/recorder/tasks.py", line 211, in run
    instance._process_one_event(self.event)
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 741, in _process_one_event
    self._process_state_changed_event_into_session(event)
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 847, in _process_state_changed_event_into_session
    if attributes_id := self._find_shared_attr_in_db(attr_hash, shared_attrs):
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 760, in _find_shared_attr_in_db
    if attributes_id := self.event_session.execute(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1712, in execute
    result = conn._execute_20(statement, params or {}, execution_options)
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1631, in _execute_20
    return meth(self, args_10style, kwargs_10style, execution_options)
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/sql/lambdas.py", line 516, in _execute_on_connection
    return connection._execute_clauseelement(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1498, in _execute_clauseelement
    ret = self._execute_context(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1862, in _execute_context
    self._handle_dbapi_exception(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2043, in _handle_dbapi_exception
    util.raise_(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
    raise exception
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1819, in _execute_context
    self.dialect.do_execute(
  File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
    cursor.execute(statement, parameters)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 206, in execute
    res = self._query(query)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/cursors.py", line 319, in _query
    db.query(q)
  File "/usr/local/lib/python3.10/site-packages/MySQLdb/connections.py", line 254, in query
    _mysql.connection.query(self, query)
sqlalchemy.exc.OperationalError: (MySQLdb.OperationalError) (1267, "Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb3_general_ci,COERCIBLE) for operation '='")
[SQL: SELECT state_attributes.attributes_id 
FROM state_attributes 
WHERE state_attributes.hash = %s AND state_attributes.shared_attrs = %s]
[parameters: (438846145, '{"auto_update":false,"installed_version":"v0.8.11","latest_version":"v0.8.11","release_url":"https://github.com/mdeweerd/zha-toolkit/releases/v0.8.11","skipped_version":null,"title":null,"friendly_name":"🧰 ZHA Toolkit - Service for advanced Zigbee Usage update"}')]
(Background on this error at: https://sqlalche.me/e/14/e3q8)

Originally posted by @jes1417 in #77 (comment)

Howto avoid Timeout errors with attr_read -> 'tries' & 'conf_report'

First thanks for your nice Toolkit. This issue is not new, It's still happening in the latest version v0.8.11.
I'm running this simple automation script once per 10 minutes to poll attributes of two power plugs:

alias: 'Poll ZHA devices '
description: ''
trigger:
  - platform: time_pattern
    minutes: /10
condition: []
action:
  - service: zha_toolkit.attr_read
    data:
      ieee: sensor.innr_sp_120_38ea6103_smartenergy_metering_summation_delivered
      cluster: 1794
      attribute: 0
  - service: zha_toolkit.attr_read
    data:
      ieee: sensor.innr_sp_120_6d921702_smartenergy_metering_summation_delivered
      cluster: 1794
      attribute: 0
mode: single

Many of these read calls cause timeout errors:

Logger: homeassistant.components.automation.poll_zha_services
Source: custom_components/zha_toolkit/utils.py:733 
Integration: Automation (documentation, issues) 
First occurred: 10:50:07 (12 occurrences) 
Last logged: 14:20:07

Poll ZHA devices : Error executing script. Unexpected error for call_service at pos 2:
While executing automation automation.poll_zha_services
Poll ZHA devices : Error executing script. Unexpected error for call_service at pos 1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 490, in wait_for
    return fut.result()
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 447, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 680, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1704, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1741, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/config/custom_components/zha_toolkit/__init__.py", line 695, in toolkit_service
    raise handler_exception
  File "/config/custom_components/zha_toolkit/__init__.py", line 659, in toolkit_service
    await handler(
  File "/config/custom_components/zha_toolkit/__init__.py", line 744, in command_handler_default
    await default.default(
  File "/config/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/config/custom_components/zha_toolkit/zcl_attr.py", line 262, in attr_read
    await attr_write(*args, **kwargs)
  File "/config/custom_components/zha_toolkit/zcl_attr.py", line 304, in attr_write
    result_read = await u.cluster_read_attributes(
  File "/config/custom_components/zha_toolkit/utils.py", line 733, in cluster_read_attributes
    return await cluster.read_attributes(attrs, manufacturer=manufacturer)
  File "/usr/local/lib/python3.9/site-packages/zigpy/zcl/__init__.py", line 441, in read_attributes
    result = await self.read_attributes_raw(to_read, manufacturer=manufacturer)
  File "/usr/local/lib/python3.9/site-packages/zigpy/quirks/__init__.py", line 233, in read_attributes_raw
    results = await super().read_attributes_raw(
  File "/usr/local/lib/python3.9/site-packages/zigpy/device.py", line 327, in request
    return await asyncio.wait_for(req.result, timeout)
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 492, in wait_for
    raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError

Not sure who is causing these errors (toolkit, ZHA or quirk). So sorry if this toolkit is not the one to raise this issue 😉

Unknown error while running service: zha_toolkit.backup

Same error occurs if I try the same with zha_toolkit.execute (command: backup)

2022-03-08 15:54:36 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [281473033533136] Error handling message: Unknown error
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 27, in _handle_async_response
    await func(hass, connection, msg)
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 552, in handle_execute_script
    await script_obj.async_run(msg.get("variables"), context=context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1243, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 349, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 367, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 570, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1636, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1673, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/config/custom_components/zha_toolkit/__init__.py", line 670, in toolkit_service
    raise handler_exception
  File "/config/custom_components/zha_toolkit/__init__.py", line 634, in toolkit_service
    await handler(
  File "/config/custom_components/zha_toolkit/__init__.py", line 719, in command_handler_default
    await default.default(
  File "/config/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/config/custom_components/zha_toolkit/misc.py", line 71, in backup
    raise Exception(
Exception: Radio type RadioType.UNKNOWN not supported for backup

Unsupported Attribute

Hello,

Seems I am missing something, I am trying to read value of an attribute from a specific cluster using command :

service: zha_toolkit.attr_read
data:
  ieee: 3c:6a:2c:ff:fe:d2:12:5b
  endpoint: 1
  cluster: 0x0702
  attribute: 0x4000

It returns an error of Unsupported Attribute :

2022-07-18 11:45:49 DEBUG (MainThread) [custom_components.zha_toolkit] event_data {'zha_toolkit_version': 'v0.8.11', 'zigpy_version': '0.47.3', 'zigpy_rf_version': '0.8.1', 'ieee_org': 'sensor.pince_ampere_5b12d2fe_smartenergy_metering', 'ieee': '3c:6a:2c:ff:fe:d2:12:5b', 'command': None, 'command_data': None, 'start_time': '2022-07-18T11:45:48.960822+00:00', 'errors': [], 'params': {'cluster_id': 1794, 'attr_id': 16384, 'dir': 0, 'tries': 1, 'expect_reply': True, 'args': [], 'read_before_write': True, 'read_after_write': True, 'csvfile': 'Valophase1'}, 'write_is_equal': False, 'result_read': ({}, {16384: <Status.UNSUPPORTED_ATTRIBUTE: 134>}), 'warnings': ['Result: {16384: <Status.UNSUPPORTED_ATTRIBUTE: 134>} - Attribute 16384 not in read ({}, {16384: <Status.UNSUPPORTED_ATTRIBUTE: 134>})'], 'success': False}

while this attribute is available when using the scan_devices fonction.

Full scan available there : https://transfer.sh/8k8nub/pc321.txt

Is it something expected ?

Regards,
Adrien

Unexpected error for call_service at pos 1: 'ZCLAttributeDef' object is not subscriptable

Hi

I'm getting a pop error when running scan_device:

Failed to call service zha_toolkit.scan_device. Unknown error

Looking at the logs, this is the error -

websocket_api script: Error executing script. Unexpected error for call_service at pos 1: 'ZCLAttributeDef' object is not subscriptable

This device scanned ok last week, and not sure what I've changed in my system to impact how these tools work.

Any guidance appreciated.

Thanks

binds_remove_all and binds_remove_coordinator return invalid literal for int() with base 10: '0x4'

I'm trying to unbind a Philips RWL 020 with

service: zha_toolkit.binds_remove_all
data:
  ieee: 00:17:88:01:08:6E:7E:78
  tries: 100
  event_success: zha_event
  event_fail: zha_event

but this returns the following stack trace in the logs

Logger: homeassistant.helpers.script.websocket_api_script
Source: custom_components/zha_toolkit/binds.py:442
Integration: 🧰 ZHA Toolkit Service ([documentation](https://github.com/mdeweerd/zha-toolkit), [issues](https://github.com/mdeweerd/zha-toolkit/issues))
First occurred: 12:31:28 AM (5 occurrences)
Last logged: 1:18:03 AM

websocket_api script: Error executing script. Unexpected error for call_service at pos 1: invalid literal for int() with base 10: '0x4'
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/srv/homeassistant/lib/python3.9/site-packages/homeassistant/helpers/script.py", line 684, in _async_call_service_step
    await service_task
  File "/srv/homeassistant/lib/python3.9/site-packages/homeassistant/core.py", line 1744, in async_call
    task.result()
  File "/srv/homeassistant/lib/python3.9/site-packages/homeassistant/core.py", line 1781, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/srv/homeassistant/config/custom_components/zha_toolkit/__init__.py", line 717, in toolkit_service
    raise handler_exception
  File "/srv/homeassistant/config/custom_components/zha_toolkit/__init__.py", line 681, in toolkit_service
    await handler(
  File "/srv/homeassistant/config/custom_components/zha_toolkit/__init__.py", line 766, in command_handler_default
    await default.default(
  File "/srv/homeassistant/config/custom_components/zha_toolkit/default.py", line 33, in default
    await handler(app, listener, ieee, cmd, data, service, params, event_data)
  File "/srv/homeassistant/config/custom_components/zha_toolkit/binds.py", line 378, in unbind_coordinator
    await binds_remove_all(
  File "/srv/homeassistant/config/custom_components/zha_toolkit/binds.py", line 499, in binds_remove_all
    raise e
  File "/srv/homeassistant/config/custom_components/zha_toolkit/binds.py", line 442, in binds_remove_all
    dst_addr.nwk = t.uint16_t(binding["dst"]["group"])
  File "/srv/homeassistant/lib/python3.9/site-packages/zigpy/types/basic.py", line 91, in __new__
    n = super().__new__(cls, *args, **kwargs)
ValueError: invalid literal for int() with base 10: '0x4'

Debug logging configuration in readme is wrong

When I try to enable debug logging as documented in the readme, HA refuses to restart because of an invalid configuration file. The log file contains this error:

2022-03-18 14:58:56 ERROR (MainThread) [homeassistant.components.hassio] The system cannot restart because the configuration is not valid: Invalid config for [logger]: [log] is an invalid option for [logger]. Check: logger->logger->log. (See /config/configuration.yaml, line 56).

It looks like it has to be logs instead of log because this works:

logger:
  logs:
    custom_components.zha_toolkit: debug

But it looks like this not only enables debug logging for zha_toolkit, but for everything? At least I now also get debug logs for other things, e.g. [homeassistant.core].

Please document how the logging configuration has to look to enable debug logging for zha_toolkit, but leave logging for all other components on default levels.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.