Ah, ok - so maybe mine is working “in accordance with spec” for when it was made, but not “as expected” for real world use today?
I can’t really speak to the motivation behind the changes in the specification. You’ll have to ask Silicon Labs that. I can only guess that it’s like all things that develop overtime, they added new functionality, it was optional for whatever reason, and realized later that it should be required. The spec is constantly updated.
You can read it for yourself if you want: Z-Wave Application Command Class Specification. Section 4.74.2.5 State idle and 4.74.2.11 Version 8.
Oh, I’m (unfortunately) all too aware of “the spec changed” and working around ambiguous varying implementations of stuff at work (but that’s all like client/server messages not this fancy RF voodoo).
I would have presumed though that if it changed and that’s identifiable, ideally you would have different versions of a class (software library) to substitute in matching the specs that were in effect for the thing you’re talking to, or design it to “fail gracefully” accounting for previous versions.
This methodology though usually assumes that the software in question has existed thru the lifetime of the specs, so I’m guessing ZwaveJS is “too new” to have been in the wild with the older versions and either decided to only support what they expected was in the wild, or didn’t know about all the finer details of the deltas and is playing catch-up with problems like this one we’re discussing, or just hasn’t got there yet because it can’t all be done at once.
That combined with manufacturers that are probably trying to recycle old code and ship new stuff always makes for “exciting” things happening especially if the QA testing focuses on “go-path” instead of “no-go” testing to prove it works correctly (this is annoyingly common in my experience working software).
One of my favorite notes a coworker put on a test procedure when doing testing shortly after I got hired was “IAWS but probably wrong” (IAWS = In Accordance With Specifications). Basically the particular software in question complied with the letter of the specs, but the results observed was probably not what a user would expect or want. Then there are tough management decisions do you stick to the spec or try to make it work the way the user wants, and pick who you make mad…which there’s ALWAYS someone mad when that happens.
So that little tangent is why I’m in the camp of “ugh why can’t this just work” and “I guess I need to find a way to reinvent something to work around it myself because I forsee a deadlock on fixing it” when I start to hear spec-vs-reality debate.
So I’ve been digging thru the events table on what I think my YRD256 supports…found something interesting at least one value I can test is mis-mapped (if I lock with the keypad, it reports “manually locked” value of 1) but I’m making progress.
I also stumbled onto at least one other “unknown” code that isn’t the keypad tamper alarm that I believe fails back to the “old” way of doing it but I have an idea (yet to test) that if I can re-enable those disabled sensor values and they actually report properly I can have the “unknown” 254 event pass up the state of the “old” sensor I used to have reporting and maybe even get more of the alarms and values reported thru again.
So far what I’ve got…
template:
trigger:
# Lock jammed
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Access Control-Lock state
id: value_updated
# Keypad PIN Lockout
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Access Control-Keypad state
id: value_updated
# Keypad Tamper Alarm and other "legacy" alarms
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Access Control-unknown
id: value_updated
# Normal lock/unlock events
- platform: event
event_type: zwave_js_notification
id: notification
event_data:
device_id: c5b2bbe667f11062ecea27ead06b8705
command_class: 113
type: 6
sensor:
- name: "Inside Garage Door Lock"
#unique_id: deadbolt_inside_garage_door_status
#attributes:
# friendly_name: "Inside Garage Door Lock"
state: >-
{% if trigger.id == "value_updated" %}
{% set value = trigger.current_value_raw %}
{% if value == 11 %}
Motor Jammed
{% elif value == 16 %}
Too many failed PIN attempts
{% elif value == 254 %}
Unknown Legacy Alarm
{% else %}
Unknown Value Update = {{value}}
{% endif %}
{% else %}
{% set value = trigger.event.data.event %}
{% if value == 1 %}
Locked Manually
{% elif value == 2 %}
Unlock by Manual Mechanical
{% elif value == 3 %}
Locked by RF Remote
{% elif value == 4 %}
Unlocked by RF Remote
{% elif value == 6 %}
{% set userId = trigger.event.data.parameters.userId %}
{% if userId == 251 %}
Unlocked by Keypad Master PIN
{% else %}
Unlocked by Keypad Slot {{ userId }} PIN
{% endif %}
{% elif value == 18 %}
Master PIN Changed at Keypad
{% else %}
Unknown Event = {{value}}
{% endif %}
{% endif %}
So…I’m calling this a mostly success so far. Still more to do but its clearly headed the correct direction.
The top/bottom locks are on the “old zwave” still, the middle (inside garage) one is moved to the new zwave network on ZwaveJS to MQTT.
I simulated what guests do “mostly-closing” the door after tapping the keypad to command a lock and it jammed hitting the frame.
Now to clear the jam, I pushed the door until it latches and manually lock it
Success!
I’m totally fine with it being “unknown” after a reboot because that’s equivalent to the “old” zwave that indicated “no report” until a lock operation happened.
Still on my TODO list:
- Figure out if I can use the lock entity_id instead of the horrible random device ID
- Figure out a few of the “legacy” ones that it reports as “unknown” and map those
- Research if there’s a way to have my old entity_id and different friendly_name
- Research if there is “something else” that lets me differentiate mechanical manual lock (inside knob) from the keypad-locked (outside tap keypad) again, so I can tell if someone left the house (unlock inside, lock outside) or just let someone in (unlock inside, lock inside).
The good news is it seems like this is no longer an insurmountable problem and just a matter of enough hours to write the code.
Also just thought I’d share the (useless) answer from Yale, basically throws it back on “the zwave controller needs to support your model of lock properly”
Thank you for reaching out to us.
We do apologize for the inconvenience this has caused you. Let us help!
We would like to review and troubleshoot the issue with you. In this case, you can try to exclude/include the integration with Z-wave. The “exclusion” process starts from your Z-wave controller or application. Then you complete the process with the Smart Lock by entering your master code followed by the gear/setting symbol > 7 followed by the gear/settings symbol > 3 followed by the gear/settings symbol. Then try the “inclusion” process from your Z-wave controller/application. Finalize it with the Smart Lock, by entering your master code followed by the gear/settings symbol > 7 followed by the gear/settings symbol > 1 followed by the gear/settings symbol.
- Is this behavior also happening with the door wide open?
- Does the lock keeps an error beeping when you unlock/lock it from your Z-wave application?
Answering your questions, there is no newer version for the Z-wave module. We suggest contacting the Z-wave provider to confirm if the new Z-wave controller is fully compatible with the Yale Smart Lock.
In the meantime, let us know if you have further questions or concerns
Thank you for your time.
Have a great day!
As a software engineer, I read between the lines as “closed: won’t-fix”
Hey guys I suggest you email [email protected] [email protected]
As I understand these devices are actually non-compliant with the Notification V8
command class which is supposed to auto re-idle the value.
I think if we spam the cert group they will maybe make some progress?
You can see my reply below on the zwaveJS forum.
From what I understand (at least in my case) Yale only supports up to v4 not v8 though, and maybe that is an important distinction?
Good point → because then its maybe working as-is - but in that case it sounds like an issue with ZwaveJS which isn’t idling it automatically correctly?
Yeah, though I’m still wading thru all the “what IS the right spec” and whatnot.
In the end, I’m stuck between a lock maker that says “its up to your controller to support what a device does” and then ZwaveJS that at least for now sounds unsure what they are supposed to do with the differences in how its handled.
I’m not thrilled with this migration from the old Zwave honestly, but we’re at a point where waiting is no longer an option with the old Zwave being pulled entirely soon, and that’s why I’m going more for the “build my own workaround” because it looks like its not going to be fixed with zwavejs before the old ozw goes away next month.
Matt…as the owner of 3 YRD256 locks, I share your frustration in how they report to Zwave JS…I’m currently listening to binary_senor.lock_xxxxxx_access_control_lock_jammed to monitor the locks and send me a push notification if they report as jammed. I then use a python script from a lovelace button to reset them when I clear the jam…certainly not ideal but I LOVE the direction you are going. To be honest I don’t understand most of it, but it would be fantastic if you could share your workaround when it’s all said and done for these locks!
Also - When I was using these locks with the depreciated/original Zwave baked in integration, I was able to grab the user who engaged the lock from alarm_level / alarm_type reporting that doesn’t seem to be present within ZWave JS…Have you had any luck getting that data back?
Nice work!!
Yep, I’ll post it here when I’m happy with it (I have 3 of them myself - hammering out kinks on the one that’s a semi-interior garage door before doing exterior security doors).
For example, let the dogs out and the door was partly closed, and I got distracted…so it told me. And then I could go operate the lock manually and that auto-reset it. That’s how it USED TO work, and how I want to have my automations work again. This is my “end goal” and I think I now am armed with the required knowledge to get “most” of it working, but need more time (I work full-time…spent ALL of last weekend on this, Saturday was fighting my dimmer fan/light switches and Sunday all day was this lock)
Also by having the automation send out to everyone what was cleared how it avoids anyone else having to check it because we all know its dealt with. So I don’t want others to have to “learn” a new process, just operate it and verify its turning all the way. I spent a TON of time getting the doors hung precisely to have the bolt move with zero effort (even getting 3" screws for everything to reduce seasonal movement)
I’ve had an automation that sends everyone in the house a Telegram message to know if its got an alarm, and again to tell that the alarm was cleared by what means. I REALLY want this functionality back.
So it seems like if you enable those entities you do get that data, but ONLY if it hits a value_change that the new ZwaveJS doesn’t understand what to do with. For example, “handing the lock” sends those, as does “Keypad removed tamper” (to test, unscrew the back half and unplug the keypad wiring harness while its powered up - it’ll scream and beep and send a zwave alert out)
The things I care about are more/less
- Too many PIN tries
- Jams (happens a lot with guests)
- Someone smashing the keypad to try and break in
- Someone using the master PIN to open the door (should never happen - we all have codes)
- Someone adding/deleting a user without everyone discussing it first
- Battery is low (as reported by the lock) ← I think this might be working properly, but I need to get some low/dead batteries to prove it. My batteries seem to last at least a year in the most-used lock…so maybe August at this rate? I may sacrifice a set of batteries (or rechargables) with a dummy load to test it faster once I get the rest hammered out.
I’d like to get “factory reset” alarm caught but I’m too chicken to hose all the user codes and programming to test that alert so it will probably be untested.
haha…I understand…I constantly say to myself: I thought Home Automation was supposed to make my life easier? I’ve spent a few weekends dedicated to getting things (or attempting) to work the way they are supposed to. Nevertheless, best of luck on getting the bugs worked out. You’ve obviously gotten farther in the past couple days than ANYONE else has on these locks in the past year. I look forward to seeing (and using!) the end result!
Thanks!
Yeah I have been chasing circles with what others have done in threads across this forum, GitHub, Reddit, and official documentation. Still learning the format of the “spec” stuff but its not dissimilar from what I have to do at work (software engineer) making computers talk to each other in how messages are relayed on the wire…which probably helps. And trying to learn what tools I have to analyze the zwave bits looking under the hood (I’m used to using Wireshark, but I don’t have that here).
EDIT: Maybe when all is said and done I’ll be bold and reset the back door lock “For Science” to prove what alert that fires off…at least that will be less likely to trap anyone outside if it goes badly and I end up hand-reprogramming everything. That’d also be a good one to test “handing the lock” because it opens the opposite direction so I will get more variety on my test-cases and validation of whatever I build.
Overall it is easier, I can have the inner garage deadbolt open when an authorized user unlocks the outer one saving a step. I can have it auto-relock after a while (if the door is shut) also factoring in if I’m coming/going a lot (not relock while I’m unloading groceries like the built-in auto lock does). But that easy requires first lots of prep and aligning of planets.
I think I may have the majority of it worked out if you want to give it a shot. I use “packages” YAML files so this is the whole file that is more or less working like I used to have a high level lock status before.
I’ve tried to put in LOTS of comments for explaining what I know (for others and my own sanity), the only thing I believe I have to yet work out is low-battery if the “built in” low battery alerts work, or if its passed thru and I should be capturing it in my scripts.
Anything unknown should print “unknown” and the raw values to aid in debugging.
If you figure out things I’ve missed please pass them along what it is and how to test it so I can incorporate them! I’m not sure what else these YRD256 locks might pass along.
File: inside_garage_door_lock_status.yaml
# Required changes to use:
#
# 1) Find your device_id and do a find/replace to put it in all the triggers
# NOTE: Easiest way to get the device_id field value is:
# Developer Tools > Events
# Listen for: "zwave_js_notification"
# Then trigger door unlock/lock and observe fields
#
# 2) Enable the disabled-entities in the home assistant device for your lock:
# > alarmtype
# > alarmlevel
# NOTE: these should be named like entity_id of:
# sensor.my_lock_location_alarmtype
# sensor.my_lock_location_alarmlevel
# Take note of the prefix before the alarmtype and alarmlevel entity IDs
#
# 3) Scroll down to the line a bit after "sensor:" which contains
# {% set lock_sensor_id_prefix = '' %}
# and input the aforementioned sensor prefix for the alarmtype and alarmlevel
# Example: {% set lock_sensor_id_prefix = 'sensor.my_lock_location' %}
# NOTE: Omit the _alarmtype and _alarmlevel as those are automatically added
#
# 4) Reload the template-sensors (or restart Home Assistant core) and test
#
template:
trigger:
# Power to RF Module Restored (e.g. batteries installed)
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Power Management-Power status
id: value_updated
# Battery Low - Replace Soon
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Power Management-Battery maintenance status
id: value_updated
# Lock jammed
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Access Control-Lock state
id: value_updated
# Keypad PIN Lockout
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Access Control-Keypad state
id: value_updated
# Legacy Alarm
- platform: device
device_id: c5b2bbe667f11062ecea27ead06b8705
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 113
property: Access Control-unknown
id: value_updated
# Normal lock/unlock events
- platform: event
event_type: zwave_js_notification
id: notification
event_data:
device_id: c5b2bbe667f11062ecea27ead06b8705
command_class: 113
type: 6
sensor:
- name: "Inside Garage Door Lock"
state: >-
{% if trigger.id == "value_updated" %}
{% set value = trigger.current_value_raw %}
{% if value == 1 %}
Power to RF Module Restored
{% elif value == 10 %}
Low Battery
{% elif value == 11 %}
Motor Jammed
{% elif value == 16 %}
Too many failed PIN attempts
{% elif value == 254 %}
{% set lock_sensor_id_prefix = 'sensor.deadbolt_inside_garage_door' %}
{% set alarm_type = states(lock_sensor_id_prefix + '_alarmtype') | int(-1) %}
{% set alarm_level = states(lock_sensor_id_prefix + '_alarmlevel') | int(-1) %}
{% if alarm_type == 161 and alarm_level == 2 %}
Keypad Front Escutcheon Removed
{% elif alarm_type == 129 and alarm_level == 0 %}
Handing Completed (Right)
{% elif alarm_type == 129 and alarm_level == 1 %}
Handing Completed (Left)
{% else %}
Unknown Legacy alarm_type={{ alarm_type }}, level={{ alarm_level }}
{% endif %}
{% else %}
Unknown Value Update = {{value}}
{% endif %}
{% else %}
{% set value = trigger.event.data.event %}
{% if value == 1 %}
Locked Manually
{% elif value == 2 %}
Unlock by Manual Mechanical
{% elif value == 3 %}
Locked by RF Remote
{% elif value == 4 %}
Unlocked by RF Remote
{% elif value == 5 %}
{% set userId = trigger.event.data.parameters.userId %}
{% if userId == 251 %}
Locked by Keypad Master PIN
{% else %}
Locked by Keypad Slot {{ userId }} PIN
{% endif %}
{% elif value == 6 %}
{% set userId = trigger.event.data.parameters.userId %}
{% if userId == 251 %}
Unlocked by Keypad Master PIN
{% else %}
Unlocked by Keypad Slot {{ userId }} PIN
{% endif %}
{% elif value == 9 %}
Locked by Auto-Lock
{% elif value == 12 %}
All User Codes Erased
{% elif value == 13 %}
Deleted User Code
{% elif value == 14 %}
Added User Code
{% elif value == 18 %}
Master PIN Changed at Keypad
{% else %}
Unknown Event = {{value}}
{% endif %}
{% endif %}
# List of value-change alarms
# 1 Power applied (batteries installed)
# 11 Lock jammed
# 16 PIN fail keypad lockout
# 254 Unknown Legacy alarm_type alarm_level
# 254 Legacy 161 2 Keypad Front Escutcheon Removed
# Legacy 129 0 Lock Handed (right)
# Legacy 129 1 Lock Handed (left)
#
# List of event values
# 1 Lock by Manual (NOTE: Both mechancial and one-touch-keypad)
# 2 Unlock by Mechanical
# 3 Lock by RF
# 4 Unlock by RF
# 5 Unlock by Keypad (parameters.userId / 251=master)
# NOTE: Only works if you disable "one touch locking".
# One touch locking keypad-lock reports as 1 "Lock by Manual"
# and the new ZWave events seems to not specify manual method.
# 6 Unlock by Keypad (parameters.userId / 251=master)
# 9 Auto Lock
# 12 All user-codes deleted (not tested)
# 13 User PIN Deleted (does not send slot #)
# 14 New User PIN Added (does not send slot #)
# 18 Master PIN Changed
# TODO: Figure out what these map to now:
#
# {% elif alarm_type == 48 %}
# Factory Reset Defaults
# {% elif alarm_type == 168 %}
# Low Battery Critical
# {% elif alarm_type == 169 %}
# Low Battery Cannot Operate
# {% else %}
Yeah I had to look that one up too back when I was finding the documentation. I’d never heard of it…technically the “zwave interoperability” document from Yale for the “old” way doesn’t ever call it a keypad but I added that word because it seemed much easier to understand “someone pried the keypad off” than “the escutcheon was removed”
BTW the “tamper sense” is simply on “is the outside part plugged into the inside part” for what trips the alarm, afaik it can’t tell someone has pried it off until they break/cut the wires. I tested it by unscrewing the rear half and unplugging the connector to the front. I reset it by removing a battery, plugging the connector in, and reinstalling the battery; then operating the deadbolt normally to “send” a new status.
Also trivia, one thing I found in support/troubleshooting calls the “back half” of the lock with the motor/handle/batteries on the interior as the “rear escutcheon”. Being a simple person with too many words in my head already, I’d call it “the back half” or “the inside part”.
Thanks @mmiller7 ! This looks awesome and so long overdue! I look forward to playing around with it this weekend when I have some time! Thanks again! You rock!
I’d be very interested to hear if it works as expected especially if you’ve got the same lock if you get any “unknown” status numbers popping up I may not have stumbled onto.
I know I’ve not yet worked out the “low battery” status messages yet so that’s going to require at least 1 update (which I’ll post when I have one with a low battery to test)
Got another wrench in my plan…I got my other 2 locks moved over and it tells me some of the stuff doesn’t exist!
Logger: homeassistant.config
Source: config.py:454
First occurred: 5:21:55 PM (2 occurrences)
Last logged: 5:21:55 PM
Invalid config for [template]: Value 32-113-0-Access Control-unknown can't be found on node Node(node_id=32). Got OrderedDict([('trigger', [OrderedDict([('platform', 'device'), ('device_id', 'da3bc521d2bd7446ce2a56ce42c0bf40'), ('domain', 'zwave_js'), ('type', 'zwave_js.value_updated.value'), ('command_class', 113), ('property', 'Power Management-Power status'), ('id', 'value_updated')]), OrderedDict([('platform', 'device'), ('device_id', 'da3bc521d2bd7446ce2a56ce42c0bf40'), ('domain', 'zwave_js'), ('type', 'zwave_js.value_updated.value'), ('command_class', 113), ('property', 'Access Control-Lock state').... (See ?, line ?).
Invalid config for [template]: Value 33-113-0-Access Control-unknown can't be found on node Node(node_id=33). Got OrderedDict([('trigger', [OrderedDict([('platform', 'device'), ('device_id', '33ee4d0b89ec25cf825c70254ddbc298'), ('domain', 'zwave_js'), ('type', 'zwave_js.value_updated.value'), ('command_class', 113), ('property', 'Power Management-Power status'), ('id', 'value_updated')]), OrderedDict([('platform', 'device'), ('device_id', '33ee4d0b89ec25cf825c70254ddbc298'), ('domain', 'zwave_js'), ('type', 'zwave_js.value_updated.value'), ('command_class', 113), ('property', 'Access Control-Lock state').... (See ?, line ?).
But it clearly does, so I’m guessing its a false-alarm somehow.
After fiddling for a while re-interviewing stuff, enabling EVERY sensor even the ones I don’t want to use, restarting the physical machine and even triggering some of the “events” at the lock…I’ll be darned if I can figure out what makes it work. One of them just started working for no apparent reason.
Off to fiddle with the other and see if it reproduces the same success…
EDIT: Yes, I think I found a way that worked. Not sure if it was ALL required but I only have 3 locks to try on.
Process:
- Pair it with Zwave
- Re-interview
- Enable ALL the sensors (even ones that don’t work right) in Home Assistant > Device > Your Lock Device Name
- Wait about a minute
- Re-interview device
- Wait about a minute
- Go to the Integrations page
- On the “3 dots” menu for the ZwaveJS integration, pick “Reload”
- With the door open, lock your lock
- Enter the master PIN and Settings menu, pick option 3 (Advanced) and option 5 (Handing the Lock) then gear to “accept”. It will re-learn which edge of the door its on (may or may not operate bolt, just let it alone with the door open). This will cause an “unknown” event to fire off and force it to “see” the existence of “unknown”.
- Go to the Integrations page
- On the “3 dots” menu for the ZwaveJS integration, pick “Reload”
- Go to the Settings and “Validate” now it should be happy
- Reload Home Assistant to make sure its all fully in sync.
Optionally go back thru “handing the lock” in settings and verify that it shows the status on your dashboard properly for it.
…At least I think that’s what did it.
This one is created at runtime, and doesn’t appear in your screenshot. The others are created during the device interview. Therefore, HA is correct because the value doesn’t exist yet, until you trigger it and bring it into existence.