There is currently no direct way to use the zigbee timed switch feature (aka timed_with_on_off) on a Zigbee device. For the curious, this is a more secure way to turn on then turn off a device when you want to be sure that the device will be turned off after a amount of time despite an hass restart/crash/murphy law/etc. For example, you want to be sure your water/gaz valve will be turned off and not flood your neighborhood.
To workaround that I issue a zha.issue_zigbee_cluster_command directly to the device which requires the ieee address of the device.
This service doesnāt accept target or entity args and unfortunately device_attr("light.room3", "ieee") does not work.
Currently to extract the device ieee I use {{ (device_attr("light.room3", "identifiers")|list).0.1 }}. Is this the best way to get the ieee attribute or to match a device with zha.issue_zigbee_cluster_command ?
Examining the code that sets up the templating mechanism, we can see that not that many things are exposed:
So this seems to be close to the best approach. I think that one could verify that the first item in the list item is āzhaā, and a more general implementation would be to go through the list to find the item where the first value is āzhaā. But I guess that in this case you kind of know what you are talking to and it does not have to be fool-proof.
def device_attr(hass: HomeAssistant, device_or_entity_id: str, attr_name: str) -> Any:
"""Get the device specific attribute."""
device_reg = device_registry.async_get(hass)
if not isinstance(device_or_entity_id, str):
raise TemplateError("Must provide a device or entity ID")
device = None
if (
"." in device_or_entity_id
and (_device_id := device_id(hass, device_or_entity_id)) is not None
):
device = device_reg.async_get(_device_id)
elif "." not in device_or_entity_id:
device = device_reg.async_get(device_or_entity_id)
if device is None or not hasattr(device, attr_name):
return None
return getattr(device, attr_name)
It basically returns getattr(device, attr_name) after finding the device object and a ZHA Device has this attribute:
class ZHADevice(LogMixin):
"""ZHA Zigbee device object."""
...
@property
def ieee(self):
"""Return ieee address for device."""
return self._zigpy_device.ieee
And getattr() on a property should works in python.
$ ipython
In [1]: class Toto:
ā¦: @property
ā¦: def foo(self):
ā¦: return 42
ā¦:
In [2]: getattr(Toto(), āfooā)
Out[2]: 42
FYI: I revisited this thread to check the method to get the IEEE of a device.
I added an implementation accepting entity_names and short network addrssses to zha_custom.
That will also allow you to do what you wanted as I added the functionnality to send Cluster commands. But apparently that also exists in ZHA (I just (re)discovered that here).
Is there something similar in ZHA-toolkit for endpoints? Iāve been working on a Blueprint that uses ZHA-toolkit, and Iād love to be able to only need the entity-ID as an input. Thanks!
Edit: Sorry. I just read the documentation and saw that itās optional. Itās working really well. Thank you!
I was playing with this, I just wanted to share a slightly improved version of it:
"{{ device_attr('light.room3', 'identifiers') | selectattr(0,'eq','zha') | map(attribute=1) | first }}"
This is more resilient in that if in a future version of ZHA the identifiers attributes (which is an array) returns more than one ID, this will select the one that contains the IEEE, whichever order theyāre in.
Also, if someoneās got a progammatical way to get the endpoint_id Iād be game (Iām trying to use zha.issue_zigbee_cluster_command in a blueprint, and trying to see if I can avoid asking for the endpoint id in an input)! Although it seems to always be 1 or 11?
zha-toolkit actually determines the endpoint by matching the cluster_id to the available clusters.
That works if only one endpoint has the cluster id.
As you are trying to send a command, you need zha_toolkit.zcl_cmd. The documentation still show examples using zha_toolkit.execute, but you can use use the zcl_cmd service instead which is more convenient.
The endpoint is an optional parameter, while the cluster is mandatory.
May I build upon this question, and ask if there is a way through jinja to get all the zigbee info so i can extract ieee aswell as check quirk for siren?
device_attr() returns a list of the form: [ [ "zigbee", "the_actual_ieee" ] ]
and I couldnāt figure out how to access the content of that other than my solution, let me know if Iām stupid.
The list comes from the core.device_registry, where at least in my configuration all (zigbee) devices have the āconnectionsā item, it still feels like quite the fiddly workaround, there should definitely be a built-in function or attribute for this.
Anyways maybe itāll be good for somethingā¦