Sounds like you got it working!
I prefer Z2M anyways…
Are you using the gateway, or only the zigbee card in the lock?
I did indeed! The lock most connection one day, and after re-adding it, it has been very stable and the battery level is updating.
I’m using the module and a Sonoff Zigbee Plus-E Coordinator.
I like Z2M so far.
Thanks!
Cool, I’ll give Nimly a go.
Z2M is great because of the frequent updates, most zigbee stuff works!
Yeah, the ZHA support for Nimly is poor to say the least.
What is even more annoying, is that ZHA can apparently read out a whole bunch of interesting values from the lock, but for some reason, chose not to. See this picture from my setup, where I chose “Configure device” in the three dots menu next to reconfigure
and then select the “Power configuration” cluster, and quite a long bit down the list of attributes, chose “battery_percentage_remaining”
(there is a bunch of other batteries named 1, 2, 3 etc. but if you scroll down even further, you’ll find the right one)
Finally, click “READ ATTRIBUTE” and you’ll get the sought after value.
What bothers me is why the ZHA developers chose to omit such an important value from the UI? I guess they can’t keep track of every device in the world, but reading out the battery status ought to be one of the most prioritized values in all battery operated devices, right?
I think the reason why ZHA is not showing battery percentage is because Nimly lock incorrectly presents itself as a Mains powered device. See Basic → power_source attribute.
My guess is that adding a simple quirk to zigpy/zha-device-handlers repository that changes it to a battery powered device should fix this issue.
Could you elaborate more on this? Is it like in “simple for me”, or “easy for anyone” ?
As in it should be a quite easy contribution by someone familiar with zha quirks. Note that you can also add your own local quirk to achieve the same (see here Zigbee Guide: How-to add/setup local custom ZHA Device Handlers (also known as ”quirks”) in the ZHA integration).
I’m planning to do it at some point when having more time. I can post the instructions here if I’ll get around doing it.
I spent the entire evening yesterday, at first with high hopes and a “how hard can it be, actually?” -attitude. It turns out that it’s far from trivial. I am a hardware developer, and besides that, have been writing simple code for my own use for the last 40 years. But I must admit that I’m having trouble with the level of abstraction that modern coding techniques has brought us.
I have no issues grasping the concept of translating the output of one device (Zigbee) into a structure readable by another device (HA), but I just can’t wrap my head around the how. All these class calls everywhere, overloads and substitutions just got the better of me.
If there was a step-by-step instruction, I’d stand a chance, but writing my own device handler in Python - a language I’m not familiar with - is more than I can do.
I will just have to patiently wait until someone skilled in the art, decides it’s worth his or her time to do it. Or, hope that one day, the ZHA developers make a user-friendly helper that allows to turn any arbitrary Zigbee cluster from any Zigbee device, into a HA device entity that is accessible from the UI as well as from automations and the rest of the HA environment.
I know that is a hell of a task to accomplish, but in the end it could relieve the ZHA devs from this endless flood of quirk requests from lesser users like me.
That sounds like a rough experience, sorry to hear that. You might be interested in their new quirckv2 API which supposed to be much simpler: ZHA Device Handlers version 2 (ZHA-Quirks V2) architectural design developer discussion
Documentation draft can be found here: zha-device-handlers/quirks_v2.md at a97ee3baa790b13b7e468f5489233d6b1ed558c1 · zigpy/zha-device-handlers · GitHub
I finally got around making the custom quirk that changes the Power Source for nimly lock. I’ll submit PR to the upstream zha-device-handlers repo, but in the meantime you can just create a quirk file with the following code:
from zigpy.quirks.v2 import QuirkBuilder
from zigpy.zdo.types import NodeDescriptor
NIMLY = "Onesti Products AS"
NIMLY_LOCK_NODE_DESCRIPTOR = NodeDescriptor(
logical_type=2,
complex_descriptor_available=0,
user_descriptor_available=0,
reserved=0,
aps_flags=0,
frequency_band=8,
manufacturer_code=4660,
maximum_buffer_size=108,
maximum_incoming_transfer_size=127,
server_mask=11264,
maximum_outgoing_transfer_size=127,
descriptor_capability_field=0,
mac_capability_flags=140 & ~NodeDescriptor.MACCapabilityFlags.MainsPowered
)
(
QuirkBuilder(NIMLY, "NimlyPRO")
.also_applies_to(NIMLY, "NimlyCode")
.also_applies_to(NIMLY, "NimlyTouch")
.also_applies_to(NIMLY, "NimlyIn")
.also_applies_to(NIMLY, "EasyFingerTouch")
.also_applies_to(NIMLY, "EasyCodeTouch")
.node_descriptor(NIMLY_LOCK_NODE_DESCRIPTOR)
.add_to_registry()
)
EDIT:
And here is submitted PR: Add Nimly smart lock quirk by uvNikita · Pull Request #3457 · zigpy/zha-device-handlers · GitHub
Interestingly, ZHA reports that my lock has 20% remaining battery after applying this quirk while battery_percentage_remaining reports as 40%. Not sure which number is correct.
I get a similar result. The battery entity reports 37 while the battery remaining percentage reports the double 74.
I vaguely remember hearing about this doubling/halving for battery status on another forum perhaps Z2M.
Not sure how to adapt the quirk v2 for this though.
TheJulianJES explained in the PR that the battery_percentage_remaining
attribute should be from 0 to 200 according to the standard. So unless nimly violates the standard, the value reported by ZHA should be correct.
Looks like it’s time for me to replace the batteries I’ll do that and if it will show 50% on the new batteries, I’ll open another PR to fix this.
In any case, PR has been merged so after home assistant will pull the changes there should be no need for custom quirk.
I’ll also see if I’ll manage to add other features from Z2M (like last user) into ZHA.
Thank you so much for those two links, especially the latter one. I thought I had sifted through every piece of documentation, but apparently not.
Now the pieces come together nicely, even for an old chap like me. Things are always so much easier once you understand what you’re actually doing!
Now I will have a go at that doubled battery percentage value. I know for instance it has already been solved for the IKEA remotes, as you can see on line 97 and 124 in the code: zha-device-handlers/zhaquirks/ikea/opencloseremote.py at 263e68c4877852d489688d4d23c1fe9e49795cd8 · zigpy/zha-device-handlers · GitHub
Unfortunately my limitations in Python won’t allow me to fully understand from where line 39 imports the code for “DoublingPowerConfig1CRCluster”. Maybe I’ll have to resort to ChatGPT for an explanation.
Anyways, excellent work, @uvnikita and thank you for taking your time to elaborate on what you have done. That’s really helpful, and an excellent example of good will towards others.
Thanks for the kind words
DoublingPowerConfig1CRCluster
is coming from __init__.py
file from the ikea module, here: zha-device-handlers/zhaquirks/ikea/__init__.py at 263e68c4877852d489688d4d23c1fe9e49795cd8 · zigpy/zha-device-handlers · GitHub
I’m not sure yet if we need to fix this battery levels. Apparently, battery_percentage_remaining
should go from 0 to 200 where 200 actually means 100%, so ZHA just automatically recalculates this number (see comment here: Fix Nimly smart lock mains-powered capability by uvNikita · Pull Request #3457 · zigpy/zha-device-handlers · GitHub).
So, if Nimly is doing everything according to zigbee standard, we should see 200 in that attribute when we replace the batteries. If not, then we can use “doubling power configuration cluster” mentioned by TheJulianJES to fix it.
Unfortunately, I swapped out my batteries just the other day, and now I have a cluster reading of “100”, and hence a battery indicaton of only 50%.
You are right, unlike their old EachTouch/EasyFinger locks, new Nimly locks require this fix. There is more information over at Z2M here: Fix for showing 50% battery instead of 100% by newlund · Pull Request #6940 · Koenkk/zigbee-herdsman-converters · GitHub.
I created a new PR that should fix this: Add DoublingPowerConfigurationCluster for some nimly locks by uvNikita · Pull Request #3465 · zigpy/zha-device-handlers · GitHub.
Here is new code for a custom quirk (make sure to read value from the battery_percentage_remaining
attribute to update the reported battery level by ZHA):
from zigpy.quirks.v2 import QuirkBuilder
from zigpy.zdo.types import NodeDescriptor
from zhaquirks import DoublingPowerConfigurationCluster
NIMLY = "Onesti Products AS"
NIMLY_LOCK_NODE_DESCRIPTOR = NodeDescriptor(
logical_type=2,
complex_descriptor_available=0,
user_descriptor_available=0,
reserved=0,
aps_flags=0,
frequency_band=8,
manufacturer_code=4660,
maximum_buffer_size=108,
maximum_incoming_transfer_size=127,
server_mask=11264,
maximum_outgoing_transfer_size=127,
descriptor_capability_field=0,
mac_capability_flags=NodeDescriptor.MACCapabilityFlags.AllocateAddress|NodeDescriptor.MACCapabilityFlags.RxOnWhenIdle,
)
(
QuirkBuilder(NIMLY, "EasyFingerTouch")
.also_applies_to(NIMLY, "EasyCodeTouch")
.node_descriptor(NIMLY_LOCK_NODE_DESCRIPTOR)
.add_to_registry()
)
(
QuirkBuilder(NIMLY, "NimlyPRO")
.also_applies_to(NIMLY, "NimlyCode")
.also_applies_to(NIMLY, "NimlyTouch")
.also_applies_to(NIMLY, "NimlyIn")
.node_descriptor(NIMLY_LOCK_NODE_DESCRIPTOR)
.replaces(DoublingPowerConfigurationCluster, endpoint_id=11)
.add_to_registry()
)
Hmm… I replaced the previous quirk code with the new one from above, but I still only get 50% battery status. First I reloaded the ZHA integration, but when that didn’t improve, I restarted the whole box. Still the same 50%. Is there a quirk cache I need to purge somewhere to get the new code into play?
Did you try to re-read the value from Manage Zigbee device → DoublingPowerConfigurationCluster → battery_percentage_remaining.
Might also need to click on “Reconfigure” button for the device.
Re-reading the value from the DoublingPowerConfigurationCluster did the trick!
Thanks again; I wouldn’t have figured that out in a million years