- Notifications
You must be signed in to change notification settings - Fork37
🧰 Zigbee Home Assistant Toolkit - service for "rare" Zigbee operations using ZHA on Home Assistant
License
mdeweerd/zha-toolkit
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
ZHA Toolkit (Zigbee HomeAssistant Toolkit) helps go beyond some limitations when using theZHA integration componentinHome Assistant (an open source homeautomation software). It does so by providing extra methods to executeZigbee requests and helps bridge between ZHA functionality and HomeAssistant.
You canadd ZHA Toolkit to Home AssistantusingHACS (Home Assistant Community Store). ZHAToolkit is available in HACS' default repository list.
The purpose of ZHA Toolkit and its Home Assistant 'Services' feature, is toprovide direct control over low-level zigbee commands provided in ZHA orZigpy 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 appliescode 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 (andrestore).
Make it easier to perform one-time operations where (some) Zigbeeknowledge is sufficient and avoid the need to understand the innerworkings of ZHA or Zigpy (methods, quirks, etc).
Download Firmware referenced inKoenkk/zigbee-OTA.
- 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)
- Purpose
- Table of Contents
- Setup
- Automations
- Using
zha-toolkit
- General recommendations
- Zigbee crash course
- Common options
- Service commands
attr_read
: Read an attribute valueattr_write
: Write(/Read) an attribute value- Binding related
conf_report
: Configure reportingconf_report_read
: Read configured reportingscan_device
: Scan a device/Read all attribute valueszdo_scan_now
: Do a topology scan- Join & Network presence related
zcl_cmd
: Send a Cluster command- Group related services
- EZSP/Bellows
- ZNP related (TI Zigbee Radio)
- Miscellaneous
backup
: Backup the coordinatormisc_settime
: Set attributes of a Time Clusterota_notify
- Download/Trigger Device FW updatezha_devices
: Device Information to Event or CSV or Script variableregister_services
: Reregister ZHA-Toolkit servicesha_set_state
- Update HA statemisc_energy_scan
: Perform an energy scan
- User method
- Manufacturers
- Credits/Motivation
- License
- Contributing
ZHA Toolkit uses the well-known HACS installation mechanism. It isrecommended to use HACS which facilitates the installation of many othercustom components as well.
If you already haveHACS(Tutorial),simply look for "ZHA Toolkit" under Integrations orclick this redirectionto add it.
If you are not using HACS, you need add the files incustom_components/zha_toolkit
. SeeinstallNoHacsFromZip.sh andinstallNoHacsWithGit.sh for possibleprocedures.
In all cases (HACS or manual), the ZHA Toolkit integration is only activeon your Home Assistance instance after adding next line toconfiguration.yaml
, and restarting Home Assistant.
zha_toolkit:
Before restarting, you may also want to enable debug verbosity.zha-toolkit
isn't verbose when you use it occasionnaly. As it's aservice, there is no really good way to inform the user about errors otherthan the log.
Logging will help verify that the commands you send havethe desired effect.
Add/update the logger configuration (in theconfiguration.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:warninglogs:custom_components.zha_toolkit:debug
You can also change the log configuration dynamically by calling thelogger.setlevel
service. Example that sets the debug level for thiszha_toolkit
component and forzigpy.zcl
(which helps to see someinformation about actual ZCL frames sent). This method allows you to enabledebug logging only for a limited duration :
service:logger.set_leveldata:custom_components.zha_toolkit:debugzigpy.zcl:debug
This is a list (of 1) automation:
This component provides a single service (zha_toolkit.execute
) thatprovides several commands (command
parameter) providing access toZHA/Zigbee actions that are not otherwise available.
You can use a service as an action in automations. So you can send thecommands according to a schedule or other triggers. For instance, you couldplan a daily backup of your TI-ZNP USB Key configuration.
It will be more common to send a Zigbee command only once: for instancebind one device to another, set a manufacturer attribute, ... .
You canperform them using the developer tools.
The developer tools are handy totest the service first before adding them to an automation.
Go to Developer Tools > Services in your instance :.
Choose the generic servicezha_toolkit.execute
or - more convenient - thespecificzha_toolkit.<COMMAND>
as the service.
Most parameters can beset using the UI, there are some cases where you may want to enable Yamlentry - you'll have some more flexibility and all parameters fit in yourbrowser view. On the other hand, the UI interface makes it easier to selectthe entity. You can switch back and forth!
There are several examples below for different commands. You can copy/pastethem to start from.
Not all available commands are documented. The undocumented ones were inthe original repository.
Some of these undocumented commands seem to bevery specific trials from the original authors.
Feel free to proposedocumentation updates.
- 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 theGithub open and closed issues
- Check theHome Assistant Forum
- Check theexamples directory
- Checkzhaquirksfor hints about available attributes (available ones, meaning of theirvalues)
- Wake up sleepy devices (generally devices on a battery) just aftersending a command so that they can receive it. It's also recommended toset the
tries
parameter to a fairly high number for these devices (insome cases over a 100 tries (more than 10 minutes) are needed tosuccessfully communicate with a sleepy device).
Note: this crash course's wording may deviate from Zigbee's wording.
Zigbee is a wireless communication protocol used for creating networks ofdevices. To understand Zigbee, we can look at it from two perspectives: thenetwork-oriented view and the device-oriented view.
From a network perspective, there is a coordinator, which is the maindevice controlling the network (often your Home Assistant instance), andthere are other devices categorized as routers and end devices.
Routersare permanently powered devices that store and forward messages, while enddevices can be any type of device. End devices can reply to requests andcommunicate autonomously if they have reporting configurations and bindingsset up. Reporting configurations determine when a device should communicateattribute changes, and bindings specify which device or group shouldreceive these changes.
Commands, such as those triggered by a buttonpress, can also be bound to specific devices or groups.
From a device perspective, devices are organized into endpoints.
Anendpoint represents a function or feature of the device. For example, adevice with two switches would have an endpoint for each switch function,and a device with a temperature and humidity sensor may have an endpointfor each sensor.
Endpoints can also represent Zigbee-specificfunctionalities like Over The Air (OTA) updates or Green Powerfunctionality.
Each endpoint has attributes associated with it.
Attributes allow you tocontrol the configuration of the device or retrieve values for its currentstate, such as on/off status or temperature readings.
Attributes aregrouped into clusters, which are reusable sets of features.
Clustersrepresent things like on/off state, color control, temperature measurement,energy metering, and more.
In practice, clusters are defined on endpoints, and each attribute has aunique address consisting of the IEEE address (a 64-bit number), theendpoint ID (a byte), the cluster ID (a two byte word), and the attributeID (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 bedetermined automatically by tools like zha-toolkit and ZHA.
The Zigbee Cluster Library (ZCL) document defines standard attributes andtheir organization in clusters. Manufacturers also have the freedom to addtheir own attributes that are not defined in the ZCL.
Commands and attribute read/write operations are typically initiated fromthe coordinator. However, Zigbee devices can also send commands to otherdevices, like a switch instructing a light bulb to turn on or off.
To avoid excessive network traffic caused by constantly polling devices fortheir internal state, devices can be configured to report their statechanges to other devices in the network.
This reporting is accompanied bybindings, 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 aspecific group.
For example, if you add a switch's endpoint and multiplelight 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 ZHAintegration, an initial configuration is sent to the device. Thisconfiguration sets up reporting and binding settings to ensure that thedevice notifies the coordinator about its state changes or any relevantdata changes, such as energy consumption metrics or simply informing that alight has been switched on.
Zigbee routers play an important role in the network by relaying messagesbetween devices, bridging longer distances, and temporarily storingmessages for battery-powered devices that wake up periodically. Messagesare typically stored for around 6 seconds.
Battery-powered devices are considered "sleepy" devices because theyconserve energy by sleeping most of the time. However, this can lead todata requests and commands being lost if the device is asleep when they aresent. To ensure successful communication, requests may need to be activelyrepeated until the sleepy device wakes up and responds.
In some cases, it is necessary to provide the manufacturer ID to access amanufacturer-specific attribute or execute a manufacturer-specific commandto use features or functionalities specific to the device manufacturer,
ZHAandzha-device-handlersandzigpy intend to wrap the zigbeeattribute operations and commands so that the Zigbee device features areimmediately usable in Home Assistant. The quality of these integrations andlibraries are ensured through unit tests.
zigpy
is a library/gateway that bridges the gap between python and thezigbee coordinator hardware.- ZHA interfaces zigpy with Home Assistant.
- The zha-device-quirks library is delivered at the same time as ZHA andadapts "quirky" device behavior to interface with Home Assistant throughZHA. "Quirky" device behavior means that a device is providingfunctionality not or not as anticipated in the Zigbee specifications.
- ZHA-Toolkit is there to help with using device functionalities that arenot fully supported yet in ZHA, or help implement scripts and automationsthat are not part of the main focus of the ZHA integration. Therecurrently are no test cases - so there is less quality assurance and afunction might accidentally drop at some point. It is not autonomouslylistening in on Zigbee messages to generate Home Assistant events forinstance, but you can use it to poll devices and update state valuesdirectly, or send commands you can't send through ZHA. ZHA-Toolkit canhelp with diagnostics and device configurations.
In almost all commands you need to provide a reference to the device thatyou want to control.
Easiest, use an entity name:
service:zha_toolkit.SOME_SERVICEdata:# 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_SERVICEdata:# 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 maychange over time.
service:zha_toolkit.SOME_SERVICEdata:# The short network addressieee:0x2F3E
Theieee
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
). Beaware that the network address can change over time but it is shorter toenter 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 changeit, it is also somewhat stable when you replace a device - you could keepthe same entity name for a difference device.
- The short address might be shorter to type if you already know it, but donot rely on it if you scripts needs to continue to work over time.
Sometime thecommand_data
field provides a reference to a device (forinstance, when binding one device to another). It has the same flexibilityas theieee
argument.
The zha-toolkit services return their results asresponse datafor Home Assistant installations that have at least version 2023.7 .
This response is available in automations and script by addingresponse_variable: VAR_NAME
to thezha_toolkit
service call. That willmake the data available under VAR_NAME inside the automation or script.
Anexample using the response data can be found inscript_use_zha_devices_response.yaml.
The response data feature of Home Assistant also makes the responseavailable when calling the service interactively.
The image below shows aan interactive attribute read using the zha-toolkit service attr_read. Theresponse data is shown in Yaml format when the call finishes.
Events in Home Assistant are a way to trigger or proceed in automations andscripts, and convey data.
All zha-toolkit commands support setting event names that are fired at theend of the command execution.
You can interactively listen for events in the Developer Tools>Events pagewhich is a good way to check the result of a zha-toolkit service that youstart in another tab of your browser.
You can set the event names as follows:
service:zha_toolkit.SERVICE_NAMEdata:# You can set the next events to use as a trigger.# The event data has the result of the commandevent_success:my_read_success_trigger_eventevent_fail:my_read_fail_trigger_eventevent_done:my_read_done_trigger_event
It's recommended to use theevent_done
event during interactive use. Youcan useDeveloper Tools > Events > Listen to events
to see the result ofthe service call. You need to useListen to events
in a separatenavigator tab,START LISTENING
and leave it open to see the data of theevents.
By listening for the event, you can see the list of groups that is foundwhen usingzha_toolkit.get_groups
for instance.
Otherwise you need toset the debug level and watch thehome-assistant.log
. Thatcan be useful if you do a lot of service calls in sequence and you want tolook back what happened.
You can also simply always enable debugging forzha_toolkit
if you use itsporadically - it is quite verbose and tends to fill up the logs if you useit often.
service:zha_toolkit.SERVICE_CALLdata:fail_exception:true
By default, the result of a zigbee transaction is "ignored" for the endresult of the service call: it will appear as if it succeeds (unless youhave the parameters wrong).
So, if you want theDeveloper Tools > Services > CALL SERVICE
button toturn red in case the zigbee transaction result is notSUCCESS
, then addfail_exception: true
to the options
service:zha_toolkit.SERVICE_CALLdata:tries:10
Tries indicates how many times a zigbee transaction is repeated until itsucceeds. An individual zigbee transaction may fail because of radiointerference or because the device is sleeping.
So by settingtries: 100
you'll request that zigbee requests are repeatedup 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 thereport configuration of your battery powered thermometer for instance.
You may still need to wake them up just after sending the command so thatthey can receive it.
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 startusing the UI (to select the ieee/entity for instance), and then Go To YAMLmode to add the other parameters.
An example of event data is shown below. Thedata>errors
field can beuseful to understand what went wrong. Theieee_org
fields take theoriginal value of the "ieee" parameter, and theieee
field is the actualIEEE 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 (notincluding 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
Read a zigbee attribute value, optionally write to a state.
service:zha_toolkit.attr_readdata: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 tostate_id:sensor.test# Optional, state attribute to write the value to, when missing: writes state itselfstate_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 attributesmanf: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
service:zha_toolkit.attr_readdata:ieee:light.texasinstruments_ti_samplelight_d77add01_level_light_color_on_offevent_done:zha_doneattribute:0cluster:0csvout:testcsv.csv
Below is the result in/config/csv/testcsv.csv
produced by theattr_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
This example reads the raw temperature value from cache into a home stateattribute value.
The purpose of this example is to get the unrounded reported value from atemperature sensor.
A battery powered temperature sensor is often sleepy and doing a realattribute read may need many tries.
So this technique allows reading the value from the attribute cache. Itdoes not use the attribute cache database table, but tries to get the valuefrom the in-memory cache.
Whenuse_cache
is 2, an actual read will be executed if the attribute isnot in cache.
service:zha_toolkit.attr_readdata:ieee:sensor.temperature_chambre_x_temperature_2cluster:1026attribute:0use_cache:truestate_id:sensor.temperature_chambre_x_temperature_2state_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 exampledanfoss_ally_remote_temperature_min_delay.yamlwhere the automation attempts to read the temperature from the zigbee cacheto get more precision (0.01°C) as ZHA rounds values to 0.1°C.
Write an attribute value to any endpoint/cluster/attribute.
You can provide the numerical value of the attribute id, or the internalzigpy name (string).
Before and after writing, the value is read from the attribute. If debuglogging is active, this will be visible in thehome_assistant.log
. Thelast read this can be written to a state.
Note that the format/typing of the value forattr_val
depends on theattribute type.uint*
,int*
andenum*
types can be specified asnumbers, most other types must be specified as an array of bytes or astring. If you are not sure how to represent the value, you could do anattr_read
first while observing theevent_done
event to check how theattr_val
is returned upon read.
In the yaml example detailing the available parameters toattr_write
itis shown how to specify the value for anoctet_string
as an array/list.
service:zha_toolkit.attr_writedata: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:11cluster:0x1706attribute:0x0000attr_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 attributesmanf:0x1021# Optional, state to write the read value tostate_id:sensor.test# Optional, state attribute to write the value to, when missing: writes state itselfstate_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_eventevent_fail:my_read_fail_trigger_eventevent_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 providedas a raw sequence of bytes, i.e. user is responsible to generate a sequencewhich complies to the ZCL spec.
The following examples illustratesconfiguration of Ubisys C4 (seethe device manual- section 7.8.5.2. InputActions Attribute - example):
service:zha_toolkit.attr_writedata:ieee:00:1f:ee:00:00:aa:aa:aaendpoint:232cluster:64512attribute:1attr_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:falseread_after_write:falseuse_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:02Decrypted 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_writedata:ieee:button.fictious_model_dcd14224_identifycluster:0attribute:location_descattr_val:My Location
A more complex example using HA's templating feature can be foundbelow.
Each call will increment the previous target temperature by 0.5degrees (increment by 50 in Zigbee's unit) up to 22.50 degrees and restartfrom 20 degrees.
On the first call (when the state is not set yet), thesetpoint temperature is 21.5 degrees.
The toolkit implements a read after each write (and it is not disabled by aread_after_write
parameter), so it will write the temperature value tothe statesensor.tgt_temperature
.
Note that a template is evaluated before calling the service, so theread_before_write
can't influence the attribute to write during the sameservice call even though it updates the attribute. The read before writecould still be useful if you want to track updates in history graphs forinstance.
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_writedata:ieee:entity.my_thermostat_entitycluster:0x201attribute:occupied_heating_setpointattr_val:"{% set t = states('sensor.tgt_temperature') %}{{ [(t|int+50) % 2300,2000]|max if is_number(t) else 2150 }}"state_id:sensor.tgt_temperatureallow_create:trueread_before_write:falsetries:3fail_exception:true
The default list of binding clusters is currently as follows:
- in clusters:
- 0x0006 - OnOff
- 0x0008 - Level
- 0x0300 - Color Control
- out clusters:
- 0x0402 - Temperature
Bind all available default and matching clusters fromieee
tocommand_data
on all endpoints.
Binds to the coordinator ifcommand_data
is not set or 0.
By default only binds cluster types in theinternal list, i.e. OnOff, Level and Color Control clusters.
The cluster must exist on both devices, except when the coordinator is thetarget.
If you set thecluster
, you can bind another cluster type and only thatcluster will be bound (both in and out clusters).
Usebinds_get
to verify that the configuration worked.
It's possible to attempt binding specific endpoints betweenieee
andcommand_data
.
The endpoint forieee
(source) can be provided byendpoint
.
If it's not specified then all endpoints onieee
areconsidered.
Endpoint forcommand_data
(destination) can be provided bydst_endpoint
. If it's not specified then all endpoints oncommand_data
are considered
and the first one that matches cluster-wise will be picked.
service:zha_toolkit.bind_ieeedata: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
Get the bindings from the device.
Listen to the event, or enable debug andcheck the log to get the information.
service:zha_toolkit.binds_getdata:ieee:00:15:8d:00:04:7b:83:69# Optional number of tries for each sub-request,# useful for sleepy devicestries:100event_done:event_binds_get_done
Remove all bindings from the device.
This internally fetches all theexisting bindings (binds_get
service) and requests the device to removethem.
service:zha_toolkit.binds_remove_alldata:ieee:entity.my_thermostat_entity# Optional - only remove binding to devicecommand_data:00:12:4b:00:01:6a:41:0c# Optional - name of generated event when doneevent_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]# Optionaltries:100
Remove all bindings from the device to the coordinator. Typically, ondevice initialization Home Assistant sets up bindings with the mainclusters to that it is informed about state changes.
This command will usebinds_remove_all
and set the coordinator's ieeeaddress as thecommand_data
parameter automatically avoiding that youhave to look it up.
service:zha_toolkit.unbind_coordinatordata:ieee:entity.my_thermostat_entity# Optional - name of generated event when doneevent_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]# Optionaltries:100
Set the minimum and maximum delay between two reports and set the level ofchange 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 thebutton on the thermometer just after requesting the command (it's a sleepydevice and does not wake up often). With a temperature sensor it may bemore appropriate to sure a high temperature rise to force it to report thetemperature and allow ZHA to send the configuration.
After succeeding the configuration, the minimum delay was actually 20swhich is likely the measurement period itself. The changes were reportedwhen they exceeded 0.10 degrees C.
For sleepy devices, you can add the parameter 'tries' which will retryuntil the devices confirms (with success or error)
service:zha_toolkit.conf_reportdata:ieee:00:12:4b:00:23:b3:da:a5# Optional endpoint, when missing will match cluster# endpoint: 1cluster:0x402attribute:0x0000min_interval:60max_interval:300reportable_change:10# Optional manufacturer#manf: 0x1204# Optional number of configuration attemptstries: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_eventevent_fail:my_conf_fail_trigger_eventevent_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 }}
Read the report configuration of a cluster.
service:zha_toolkit.conf_report_readdata:ieee:00:12:4b:00:23:b3:da:a5# Optional endpoint, when missing will match cluster# endpoint: 1cluster:0x402attribute:0x0000# Optional manufacturer#manf: 0x1204event_done:my_conf_read_done_trigger_event
Example result (partial event data) where the min and max reportingintervals 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
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 andwhat the values are at some point in time.
If the device does not fully support the discovery features, you couldstill write a script that would try to read the attributes that you want topoke usingattr_read
.
The result of the scan is written to thescan
directory located in theconfiguration directory of Home Assistant (config/scan/*_result.txt
).
The result is also added to the event data in theevent['data']['scan']
field which is also available in the response data.
service:zha_toolkit.scan_devicedata: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 endpointsendpoint:[1, 2]# Optional: tries Default:3 higher is useful for sleepy devicestries:100
Scan using the entity name:
service:zha_toolkit.scan_devicedata:ieee:light.tz3000_odygigth_ts0505a_12c90efe_level_light_color_on_off
Runstopology.scan()
.
service:zha_toolkit.executedata:command:zdo_scan_now
You may want to trymisc_reinitialize
ashandle_join
will not redo any joining step that already completed.
service:zha_toolkit.executedata:# Address of the device that joinedieee:00:12:4b:00:22:08:ed:1acommand:handle_join# NWK address of device that joined (must be exact)command_data:0x604e
misc_reinitialize
is a pretty dirty (white-hat) hack to reinitialize adevice by making zigpy think the device is not initialized, and thenrequesting an initialization.
This is more thanhandle_join
which is not reinitializing much when thedevice is already set up in zigpy.
misc_reinitialize
sets several device attributes to None and False sothat the zigpy initialization code will proceed with initialization.
service:zha_toolkit.misc_reinitializedata:# Reference of the device that should be reinitializedieee:00:12:4b:00:22:08:ed:1a
Send Leave Request to the device.
service:zha_toolkit.leavedata:# Reference of the device that should be reinitializedieee: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
Send Rejoin Request to the device (=Leave with Rejoin).
service:zha_toolkit.rejoindata:# Reference of the device that should be rejoinedieee:00:12:4b:00:22:08:ed:1a# Optional, device that will accept joining.command_data:00:12:4b:00:10:00:1d:1a
Currently for "bellow's" radio types.
service:zha_toolkit.zdo_join_with_codedata:# Reference of the device that allows the joinieee:00:12:4b:00:22:08:ed:1a# The code to be used in the joincode:Joining Code
Allows you to send a cluster command. Also accepts command arguments.
Note:
There is also the official core servicezha.issue_zigbee_cluster_command
. You may want to use that instead if itsuits your needs.
Thezha_toolkit
version allows lists of bytes as argparameters, and has a hack to allow "Add Scene". It is also easier to adaptthan the core that has though release procedures and is not as easilymodifiable as acustom_component
.
service:zha_toolkit.zcl_cmddata:# Device IEEE address - mandatoryieee:5c:02:72:ff:fe:92:c2:5d# Command id - mandatorycmd:0# Cluster id - mandatorycluster:1006# Endpoint - mandatoryendpoint: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 : Nonemanf:0x0000# Optional: tries - default : 1tries:1# Optional (only add when the command requires it): arguments (default=empty)args:[1, 3, [1, 2, 3]]
service:zha_toolkit.zcl_cmddata:ieee:5c:02:72:ff:fe:92:c2:5dcmd:1cluster:6endpoint:11
service:zha_toolkit.executedata:ieee:5c:02:72:ff:fe:92:c2:5dcommand:zcl_cmdcmd:0cluster:6endpoint:11
service:zha_toolkit.executedata:ieee:5c:02:72:ff:fe:92:c2:5dcommand:zcl_cmdcmd:4cluster:5endpoint:11args:[2, 5]
service:zha_toolkit.executedata:ieee:5c:02:72:ff:fe:92:c2:5dcommand:zcl_cmdcmd:5cluster:5endpoint:11args:[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
This example shows that you can provide a list of bytes for an argument:
service:zha_toolkit.executedata:ieee:5c:02:72:ff:fe:92:c2:5dcommand:zcl_cmdcmd:0cluster:5endpoint:11args: -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
kwargs
allows passing arbitrary keyword arguments to the underlying ZHAcluster command handler. For instance, this enables sending an IR remotecode to the cluster command handler in the Tuya TS1201 quirk (seehttps://github.com/ferehcarb/zha-device-handlers/blob/fd90c398bd746df22a5cd55e53cd3134fbd7e009/zhaquirks/tuya/ts1201.py#L125).
action:zha_toolkit.zcl_cmdmetadata:{}data:ieee:switch.ir_blaster_switchcluster:57348cmd:2kwargs:code:BXcjrhE/AuATAQF+BuAVA8AB4Acn4AMBQBvgBwFAE8ADB92ZdyPMCD8C
Add a group on the endpoint (or all endpoints).
service:zha_toolkit.add_groupdata:ieee:5c:02:72:ff:fe:92:c2:5d# Group Idcommand_data:0x0021# Optional endpointendpoint:1event_done:zha_done
Get the groups defined on the endpoint (or all endpoints)
service:zha_toolkit.get_groupsdata:ieee:5c:02:72:ff:fe:92:c2:5d# Optional endpointendpoint:1# Optional eventevent_done:zha_done
Remove a group defined on the endpoint (or all endpoints)
service:zha_toolkit.remove_groupdata:ieee:5c:02:72:ff:fe:92:c2:5d# Group Idcommand_data:0x0021# Optional endpointendpoint:1# Optional eventevent_done:zha_done
service:zha_toolkit.remove_all_groupsdata:ieee:5c:02:72:ff:fe:92:c2:5d# Optional endpointendpoint:1# Optional eventevent_done:zha_done
Similar toadd_group
but uses another method internally.
service:zha_toolkit.add_to_groupdata:ieee:5c:02:72:ff:fe:92:c2:5d# Group Idcommand_data:0x0021# Optional endpointendpoint:1# Optional eventevent_done:zha_done
Similar toremove_group
but uses another method internally.
service:zha_toolkit.remove_from_groupdata:ieee:5c:02:72:ff:fe:92:c2:5d# Group Idcommand_data:0x0021# Optional endpointendpoint:1# Optional eventevent_done:zha_done
Get groups on Zigbee Light Link cluster (usesget group identifiers
)
service:zha_toolkit.get_zll_groupsdata:ieee:5c:02:72:ff:fe:92:c2:5d# Optional endpointendpoint:1# Optional eventevent_done:zha_done
ezsp
refers toEmberZNet Serial Protocol
proposed by Silicon Labs.bellows
refers to the library providing the interface betweenzigpy
andezsp
compatible zigbee solutions.
This section lists the commands that are used specifically with thebellows
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
Used to transfer to another coordinator later, backup or simply get networkkey 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:.
The name of that backup is according to the format
service:zha_toolkit.ezsp_backupdata:# Optional command_data, string added to the basename.# With this example the backup is written to `nwk_backup_20220105.json`command_data:_20220105
ZNP stands for "Zigbee Network Processor" and refers to the network layerproposed by TI's zigbee solutions.zigpy-znp
refers to the plugin/librarythat provides the layer that interfaceszigpy
with the ZNP radio.
This section lists the services that specifically target ZNP processors.
The output is written to the customization directory aslocal/nvram_backup.json
whencommand_data
is empty or not provided.Whencommand_data
is provided, it is added just after nvram_backup.
Note: currently under test.
service:zha_toolkit.executedata: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
Will restore ZNP NVRAM data fromlocal/nvram_backup.json
wherelocal
isa directory in thezha_toolkit
directory.
Note: currently under test.
For safety, a backup is made of the current network before restoringlocal/nvram_backup.json
. The name of that backup is according to theformatlocal/nvram_backup_YYmmDD_HHMMSS.json
.
service:zha_toolkit.znp_nvram_restore
Will reset ZNP NVRAM data fromlocal/nvram_backup.json
wherelocal
is adirectory in thezha_toolkit
directory.
Note: currently under test.
For safety, a backup is made of the current network before restoringlocal/nvram_backup.json
. The name of that backup is according to theformatlocal/nvram_backup_YYmmDD_HHMMSS.json
.
service:zha_toolkit.znp_nvram_reset
Used to transfer to another ZNP key later, backup or simply get network keyand other info.
The output is written to the customization directory aslocal/nwk_backup.json
whencommand_data
is empty or not provided. Whencommand_data
is provided, it is added just after "nwk_backup".
You can use the blueprint to setup daily backup:.
The name of that backup is according to the formatnwk_backup{command_data}.json
.
service:zha_toolkit.znp_backupdata:# Optional command_data, string added to the basename.# With this example the backup is written to `nwk_backup_20220105.json`command_data:_20220105
Will restore network data fromlocal/nwk_backup.json
wherelocal
is adirectory in thezha_toolkit
directory.
Note: currently under test.
For safety, a backup is made of the current network before restoringlocal/nwk_backup.json
. The name of that backup is according to the formatlocal/nwk_backup_YYmmDD_HHMMSS.json
.
A typical use for this is when you migrate from one key to another.
The procedure should be:
- Backup using the
znp_backup
command in thezha_toolkit
service.Verify that thenwk_backup.json
file is generated in thelocal
directory. - Remove the original Coordinator from your system (e.g., remove theUSB key, ...).
- Insert the new Coordinator.
- Only when migrating to a Coordinator with different port/serialpath/socket.
Remove/Disable the ZHA Integration from HomeAssistant.
The alternative is to modify HA’s config file directly toupdate the current integration’s serial path and baudrate - Copy the zigbee.db file (for backup).
Moving/renaming it should notbe needed. If you Move or Rename thezigbee.db
the Entity name arelost after the restore (which impacts your automations, UI, etc).
- Restart Home Assistant.
- Enable/Add the ZHA Integration to Home Assistant (needed if youdisabled or removed the ZHA integration in step 2.iii.)
- Restore using the
znp_restore
command.
(If you used a custom filename for the backup then make sure you copy it tonwk_backup.json
). - Check the logs (currently the
pre_shutdown
call failed for the firstsuccessful test, but that is not critical). - Restart HA
- Check that everything is ok.
NOTES :
- Devices may take a while to rejoin the network as the Zigbeespecification requires them to "back-off" in case of communicationproblems.
- You may speed up the process by power cycling devices.
- Devices may not be instantly responsive because the zigbee mesh needs tobe recreated (try the
zdo_scan_now
command to speed that up).
(See theHome Assistant Community Forumfor a success story.)
service:zha_toolkit.executedata:command:znp_restore# Optional:# command_data = Counter_increment (for tx).# defaults to 2500command_data:2500
The backup service starts a backup of the coordinator by calling uponznp_backup
orezsp_backup
.
It provides a radio independent service for backups.
service:zha_toolkit.backupdata:# Optional command_data, string added to the basename.# With this example the backup is written to `nwk_backup_20220105.json`command_data:_20220105
Sets the time and DST configuration for a Time Cluster from HA's currenttime 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 andavailable in the event data, unless options disable these reads.
service:zha_toolkit.misc_settimedata:ieee:5c:02:72:ff:fe:92:c2:5d# The endpoint is optional - by default the endpoint containing the Time Clusterendpoint: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_eventevent_fail:my_read_fail_trigger_eventevent_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
helps you update the firmware of a zigbee device withoutrestarting Home Assistant. It can use the already available firmwareimages, or download them usingKoenkk/zigbee-OTA's list andresources. It also notifies the device that it should issue a request to beupdated. That launches the update process.
OTA
is the acronym for "Over the Air" and we implicitly add "update" or"upgrade".
You must have configured theotau_directory.This is where ZHA/zigpy looks for firmware images, and where downloadedfirmware images will be placed.
ota_notify
will indicate to the device that an update is available, whichwill trigger the device to request this update from the coordinator (inthis case zigpy).
Prior to notifying the device,ota_notify
will request all imageproviders to update the list of available images. By default, this is onlydone on startup, so when you add a new image to your local directory orwhen a new update is available from a third party, you'd have to restartHA. But withota_notify
no restart is required.
For details on how to setup your images sources, check thezigpy wiki section.Also read about the possibilities to enable logging, and that some devicesrequire to be re-associated.
To trigger the OTA update, useota_notify
instead. The debug log isuseful to check the update progress or indication that no update isavailable.
When the update starts, be patient: it can take a while.
service:zha_toolkit.ota_notifydata:# 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-OTAdownload:true# Optional, directory to write OTA files to (default: same as ZHA configuration)path:/config/zb_ota
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 thecommand_data parameter. If you do not provide a list, a default list isused for the CSV file, and all available data is provided in the devicesfield of the event data.
You also get this data in the 'devices' field of the generated events whichallows you to get information about endpoints and services as well.
service:zha_toolkit.zha_devicesdata:# Optional: Device to report on, by default all devices are in the reportieee: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:rssicsvout:../www/devices.csv# Optional: JSON file to write devices data to - located in /config/json/...json_out:zha_devices.json# Optional: Add timestamp to Filename of JSON file. Defaults to False.json_timestamp:trueevent_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 fordownloading:
type:buttonname:Devices CSV Filetap_action:action:urlurl_path:/local/devices.csv
Seescript_use_zha_devices.yaml tosee how you can loop over the device list provided in the event data.
Seescript_use_zha_devices_response.yamlshows how a new method available since Home Assistant 2023.7 that allows usto avoid the complexity of event_data by using the response from thezha-toolkit service.
The services may have evolved after an update of the code and callingregister_services
will reload theservices.yaml
file defining theoptions available in the UI interface, as well as internal structures thatdefine the validation rules for the parameters.
Most of the time this operation will be done automatically (when upgradingthrough HACS), but during development no version or file changes may bedetected, and a manual update may be due for testing or accessing updatedinterfaces.
service:zha_toolkit.register_services
Set/update any Home Assistant state.
service:zha_toolkit.ha_set_statedata:fail_exception:truestate_id:sensor.mysensorattr_val:10# optional Parametersstate_attr:some_attributeallow_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 + 2csvout:set_state.csvcsvlabel:Example reason
state_value_template
is a template(-like) expression that is interpretedwhereattr_val
is available asvalue
andattr_value
. This a templateexpression without the curly parentheses ({{ }}
). If the curlyparentheses are used, the expression would be expanded before the zhaservice code is entered which is incompatible with this functionality.
This is not strictly azha
specific tool, but useful in some scriptingsituations.
Scan Zigbee channels for congestion level. The value is a percentage fromzero to 100. A lower value is less congested.
service:zha_toolkit.misc_energy_scandata:# Optional: CSV file to write attribute to - located in /config/csv/...csvout:energy_scan.csv
The values can vary quite a bit between scans. You can create helpers tostore results which will allow you to see trends via the History tab. Thisautomation runs each hour:
- id: zigbee_energy_scan alias: Zigbee Energy Scan mode: single triggers: - trigger: time_pattern # Matches every hour at 17 minutes past the hour minutes: 17 actions: - action: zha_toolkit.execute data: command: misc_energy_scan response_variable: scan - repeat: for_each: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] sequence: - action: input_number.set_value target: entity_id: "input_number.zigbee_energy_channel_{{ repeat.item }}" data: value: "{{ scan['energy_scan'][repeat.item] | round }}"
Creating 16 input_number helpers can be tedious. ZHA recommends onlychannels 15, 20, and 25 be used. Alternatively you can create just threehelpers and reduce the for_each list to only those three channels.
You can add your own Python commands inlocal/user.py
. Your file isreloaded on each call and will survive updates because it's inside thelocal
directory.
Example ofuser_test
that has the expected method signature, but justprints that it's executed:
importloggingLOGGER=logging.getLogger(__name__)asyncdefuser_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.executedata:command:user_test
You're free to reuse the parameters already available for the othercommands. If you add your own, you'll need to parse them yourself fromservice.data
. You can check oututils.py/extractParams
to look forideas, 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 forinclusion in thezha-toolkit
when it's ready and of potential use toothers.
Shame on Tuya to be amember of the Zigbee Allianceand deviate from the Zigbee Specifications.
These commands help fix some of that.
This was labelled thestandard tuya "magic spell"as it makes most Tuya devices work normally.
currently only the "read" part is implemented - if needed asuper_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 asearchable service.
service:zha_toolkit.executedata:command:tuya_magicieee:light.tz3000_dbou1ap4_ts0505a_level_light_color_on_off
This project was forked fromAdminiguaga/zha_custom where the"hard tricks" for providing services and accessing ZHA functions wereimplemented/demonstrated. The original codeowners were"dmulcahey" and"Adminiuga".
The znp and ezsp backup core code is work originally created by @puddlyeither available in the officialzigpy/zigpy_znp
repository or thepudly/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 sothat the component can be easily added to a Home Assistant setup.
I set the License the same as Home Assistant that has the ZHA component.The originalzha_custom
repository does not mention a license.
#SeeContributing.md
About
🧰 Zigbee Home Assistant Toolkit - service for "rare" Zigbee operations using ZHA on Home Assistant