Zwave - Yale YRD220 Lock

z-wave
Tags: #<Tag:0x00007f1e6dd32538>
(Jeremy Johnson) #1

@chris - I was trying to edit the Yale YRD220 lock settings via the paper UI and ran into a few issues and wasn’t sure they were reported yet.

  • Parameter #2 (Auto Re-lock) is defined twice. The UI is showing the first as -1 and the second as blank. Based on how my lock is working, it should be showing as “On”.

  • The save icon isn’t enabled after editing several fields, it’s only triggered when I fill in the blank drop-down listed above. I’m assuming this is because there is input validation and the field is required?

  • If I fill in the parameter #2, then try to change the auto-lock time, the UI says it saves, but the change never happens. I also see the following error in the trace log:

    2017-09-13 22:28:59.725 [DEBUG] [ding.zwave.handler.ZWaveThingHandler] - NODE 20: Configuration update received
    2017-09-13 22:28:59.732 [DEBUG] [ding.zwave.handler.ZWaveThingHandler] - NODE 20: Configuration update usercode_code_139 to null
    2017-09-13 22:28:59.736 [ERROR] [ome.io.rest.core.thing.ThingResource] - Exception during HTTP PUT request for update config at 'things/zwave:device:15a076229ab:node20/config' for thing 'zwave:device:15a076229ab:node20': null

I have a trace log after this point if you’d like, but I didn’t see any obvious errors.

Lastly, is it possible to add another channel to get the raw alarm code (which I believe includes the user code)? I wasn’t clear from threads if that’s possible. We have the base alarm code which is great - thanks for adding that.

0 Likes

Kwikset Z-wave Door Locks never update status in OpenHab
(Chris Jackson) #2

I’ve removed one from the database.

I guess this is a paper UI issue - not the binding.

Maybe it’s related to the duplication of parameters. Let’s fix that (I’ll look at doing an update tonight with the updated database) then if it continues, can you open the debugger in your browser and see what data is sent from the UI to OH (in the network tab in the debugger).

I will change the current definition to use the alarm_raw channel. This is quite different but gives all the information you need. It’s a json string though so it will need a little processing in a rule to get the data out. Is this ok?

0 Likes

(Jeremy Johnson) #3

@chris, Thanks! I’m fine with the switch to JSON if it gets more data. But say that as someone who hasn’t had to process JSON in a rule before :slight_smile:

0 Likes

(Chris Jackson) #4

@5iver might be able to give you an example :wink: .

0 Likes

(Scott Rushworth) #5

Here is my current rule for parsing alarm_raw. My locks (Schlage BE469) do not update the lock_door channel, so I use alarm_raw to update the items linked to lock_door, and base rules off of that item’s state. Maybe all locks behave this way? You’ll find several examples of using the JSONPATH transform to parse the data in the lambda. This can be tricky though, because JSONPATH will throw an exception if the element name you are searching for does not exist in the JSON. I haven’t had any issues with the binding not providing the data I was expecting, but some try/catch blocks would be a good idea. You can find some detailed info on JSONPATH here.

This rule requires at least a OH 2.2 release build to utilize triggeringItem.

REQUIRED

MAP transformation service
JSONPATH transformation service

MAP (lock.map)

OFF=Unlocked
ON=Locked
undefined=Unknown
-=Unknown
NULL=Unknown

ITEMS

Group:Switch:OR(OFF,ON)    gLock	                          "Locks [MAP(lock.map):%s]"                    <lock>
Switch 	                   Lock_EntranceFront	                  "Lock (Front Entrance) [MAP(lock.map):%s]" 	  <lock>      (gLock)    {channel="zwave:device:55555:node5:lock_door"}
String 	                   Lock_EntranceFront_Alarm_Raw           "Lock (Front Entrance): Alarm Raw [%s]"       <shield>               {channel="zwave:device:55555:node5:alarm_raw"}
Switch 	                   Lock_GarageAttached_Inner	          "Lock (Front Entrance) [MAP(lock.map):%s]" 	  <lock>      (gLock)    {channel="zwave:device:55555:node5:lock_door"}
String 	                   Lock_GarageAttached_Inner_Alarm_Raw    "Lock (Front Entrance): Alarm Raw [%s]"       <shield>               {channel="zwave:device:55555:node5:alarm_raw"}
Switch 	                   Lock_GarageAttached_Outer              "Lock (Front Entrance) [MAP(lock.map):%s]" 	  <lock>      (gLock)    {channel="zwave:device:55555:node5:lock_door"}
String 	                   Lock_GarageAttached_Outer_Alarm_Raw    "Lock (Front Entrance): Alarm Raw [%s]"       <shield>               {channel="zwave:device:55555:node5:alarm_raw"}

Specifically, all of the Switch items need to be in gLock, and if the Switch item is named XXXXX then the String item should be named XXXXX_Alarm_Raw.

RULE

rule "Lock: Update lock states after alarm_raw event"
when
    Item Lock_EntranceFront_Alarm_Raw received update
    or
    Item Lock_GarageAttached_Inner_Alarm_Raw received update
    or
    Item Lock_GarageAttached_Outer_Alarm_Raw received update
then
    val actionItem = gLock.members.findFirst[ item | item.name.toString == triggeringItem.name.toString.replace("_Alarm_Raw","") ]
    logDebug("Rules", "Lock: Alarm events: {}=[{}]",actionItem.name,triggeringItem.state.toString)
    switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
        case "ACCESS_CONTROL" : {
            switch (transform("JSONPATH", "$.event", triggeringItem.state.toString)) {
                case "1", case "3", case "5" : {
                    actionItem.postUpdate(ON)
                    logDebug("Rules", "Lock: Alarm events: {} updated to ON (locked)",actionItem.name)
                }
                case "2", case "4" : {
                    actionItem.postUpdate(OFF)
                    logDebug("Rules", "Lock: Alarm events: {} updated to OFF (unlocked)",actionItem.name)
                }
                case "6" : {
                    actionItem.postUpdate(OFF)
                    val StringBuilder message = new StringBuilder(actionItem.name)
                    message.append(" was unlocked with")
                    switch (transform("JSONPATH", "$.code", triggeringItem.state.toString)) {
                        case "1" : {
                            message.append(" user code 1")
                        }
                        case "2" : {
                            message.append(" user code 2")
                        }
                    }
                    logDebug("Rules", "Lock: {}",message.toString)
                    //SMS_Notification.sendCommand(message.toString)
                    //Kodi_Notification.sendCommand(message.toString)
                }
                case "11" : {
                    logDebug("Rules", "Lock: Alarm events: {} is jammed, so setting lock to OFF (unlocked)",actionItem.label)
                    actionItem.postUpdate(OFF)
                    //SMS_Notification.sendCommand(actionItem.label + " is jammed")
                    //Kodi_Notification.sendCommand(actionItem.label + " is jammed")
                }
                case "16" : {
                    val String message = actionItem.label + " keypad is disabled due to too many failed codes"
                    logDebug("Rules", "Lock: Alarm events: {}",message)
                    //SMS_Notification.sendCommand(message)
                    //Kodi_Notification.sendCommand(message)
                }
                default : {
                    val String message = "Unknown door lock Event, " + triggeringItem.state.toString
                    logDebug("Rules", "Lock: Alarm events: {}",message)
                    //SMS_Notification.sendCommand(message)
                }
            }
            if (transform("JSONPATH", "$.event", triggeringItem.previousState(true).state.toString) == "11" && transform("JSONPATH", "$.event", triggeringItem.state.toString) != "11") {
                val String message = actionItem.label + " is no longer jammed"
                logDebug("Rules", "Lock: Alarm events: {}",message)
                //SMS_Notification.sendCommand(message)
                //Kodi_Notification.sendCommand(message)
            }
        }
        case "BURGLAR" : {
            //gSiren.sendCommand(ON)
            val String message = "Intruder at " + actionItem.label
            logDebug("Rules", "Lock: Alarm events: {}",message)
            //SMS_Notification.sendCommand(message)
            //Audio_Notification.sendCommand(message)
        }
        case "POWER_MANAGEMENT" : {
            val String message = "Power Management alarm for " + actionItem.label + ", " + triggeringItem.state.toString
            logDebug("Rules", "Lock: Alarm events: {}",message)
            //SMS_Notification.sendCommand(message)
        }
        default : {
            val String message = "Unknown Type in alarmRawParser, " + triggeringItem.state.toString
            logDebug("Rules", "Lock: Alarm events: {}",message)
            //SMS_Notification.sendCommand(message)
        }
    }
    /*
        {"notification":"ACCESS__MANUAL_LOCK",                          "type":"ACCESS_CONTROL","event":"1","status":"255"}
        {"notification":"ACCESS__MANUAL_UNLOCK",                        "type":"ACCESS_CONTROL","event":"2","status":"255"}
        unlocked with zwave? event 3
        locked with zwave? event 4
        {"notification":"ACCESS__KEYPAD_LOCK",  "code":"1",             "type":"ACCESS_CONTROL","event":"5","status":"255"}
        {"notification":"ACCESS__KEYPAD_UNLOCK","code":"1",             "type":"ACCESS_CONTROL","event":"6","status":"255"}
        {"notification":"ACCESS__LOCK_JAMMED",                          "type":"ACCESS_CONTROL","event":"11","status":"255"}
        {"notification":"ACCESS__KEYPAD_LOCK",                          "type":"ACCESS_CONTROL","event":"5","status":"255"}
        {"notification":"ACCESS_CONTROL__KEYPAD_TEMPORARILY_DISABLED",  "type":"ACCESS_CONTROL","event":"16","status":"255"}
        {"notification":"BURGLAR__TAMPER_UNKNOWN",                      "type":"BURGLAR","event":"2","status":"255"}
        {"notification":"HOME_SECURITY__INTRUSION_UNKNOWN",             "type":"BURGLAR","event":"2","status":"255"}
        {"notification":"POWER__REPLACE_BATTERY_SOON",                  "type":"POWER_MANAGEMENT","event":"10","status":"255"}
        {"notification":"POWER_MANAGEMENT__REPLACE_BATTERY_SOON",       "type":"POWER_MANAGEMENT","event":"10","status":"255"}
    */
end

[EDIT: updated lambda to include too many incorrect keypad entries]
[EDIT: refactor to use single item]
[EDIT: removed lambda]

1 Like

Schlage BE469 - Zwave binding with security - missing features
OH2 Z-Wave refactoring and testing... and SECURITY
Zwave Lock, no alarms
OH2 Z-Wave refactoring and testing... and SECURITY
Schlage BE469 - Zwave binding with security - missing features
OH2 Z-Wave refactoring and testing... and SECURITY
OH2 Z-Wave refactoring and testing... and SECURITY
OpenHab2 and Linear NGD00Z-4 Garage Door Controller
OH2 Z-Wave refactoring and testing... and SECURITY
Schlage BE469 - Zwave binding with security - missing features
Schlage BE469 - Zwave binding with security - missing features
Schlage Lock and Zwave snapshot binding [Solved]
Yale YRD446 Manual Lock/Unlock Events
[SOLVED] ZWave schlage not triggering updates
[SOLVED] Schlage FE599NX Node XML / PaperUI
Zwave Door Lock Reporting
Kwikset Smart Convert Zigbee Lock -- No status update when lock changed manually
Request to add device to the Z-wave DB - New version of ID Lock
(Jeremy Johnson) #6

@5iver - Thanks for the detailed response – I’ll give that a shot

0 Likes

(Jeremy Johnson) #7

@chris, Thanks for building the new binding version. I installed it, and still get a 500 error when attempting to save. The error is on a put call to /rest/things/zwave:device:15a076229ab:node20/config

The payload is as follows: https://pastebin.com/PsWKRzqT (User codes redacted of course). I notice keys with apparently negative numbers in them, is that correct?

I should also note that the value for config parameter #2 still doesn’t load correctly - not sure if that’s related.

0 Likes

(Chris Jackson) #8

I thought I’d fixed the negative number issue.

Try to edit the XML. Look in the COMMAND_CLASS_USER_CODE command class and change numberOfUsersSupported to a small number (eg 10 or 20). See if that helps for starters…

0 Likes

(Jeremy Johnson) #9

Just edit the xml file in userdata/zwave? Do I have to clear cache or something? I tried changing the number of users to 20 and while the UI only shows 20, the HTTP request is trying to set the full amount. I also noticed the XML has negative user code numbers in it. I edited the file to remove but no luck.

I did set the value through the REST API manually it works (although it’s locking after about 180 seconds instead of the 255 so I’m not sure what that’s about).

0 Likes

(Chris Jackson) #10

Sorry - I should have been clearer. You can only edit the XML when the binding is not running, so you need to stop if, then change the above users supported variable, then restart the binding. This won’t solve all the current invalid codes - you could also delete them from the XML at the same time (maybe just delete ALL codes in the XML - they will be regenerated on startup, and it will only request 20 codes if you set the above to 20). I’ll make a quick fix to see if I can stop that as well.

I’m not sure if this is why you get the errors when saving of course…

0 Likes

(Chris Jackson) #11

This was fixed previously, but somehow crept back in. I’ve now added a test to catch it if it changes again!

0 Likes

(Paul Muldoon) #12

I’ve been experimenting and trying to get the above Rule to work with my Kwikset lock. I’m not certain if its differences in the lock or perhaps me just not fully understanding the rule.

First my alarm raw only shows a Type and Value, and does not show an “ACCESS_CONTROL” Again, perhaps I’m making it more complicated then it should be. For my lock a Type 19, Value 1 would meant I entered Code 1 on the keypad, and I’m trying to send an notification to my phone when it unlocks.

Currently I’m getting this error in my logs when attempting

16:48:03.674 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Lock: Update lock states after alarm_raw event (Lock_EntranceFront)': Could not invoke method: org.eclipse.smarthome.core.items.GenericItem.getState() on instance: {"type":"21","value":"1"}
2017-11-09 16:48:29.199 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Lock: Update lock states after alarm_raw event (Lock_EntranceFront)': Could not invoke method: org.eclipse.smarthome.core.items.GenericItem.getState() on instance: {"type":"19","value":"1"}
2017-11-09 16:48:36.139 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Lock: Update lock states after alarm_raw event (Lock_EntranceFront)': Could not invoke method: org.eclipse.smarthome.core.items.GenericItem.getState() on instance: {"type":"21","value":"1"}

I did try to modify the rule eliminating ACCESS Control, and changing $.event to $.type where I thought was correct as following, but still get the same error message in the logs.

0 Likes

(Scott Rushworth) #13

Which version of OH are you running and what model of Kwikset lock?

0 Likes

(Paul Muldoon) #14

I’m on Snapshop/Build 1073 and have the KwikSet 916 Deadbolt. However the OH2 binding see’s it has the 914TRL, although I don’t think that makes a difference as I can control everything. here’s a screenshot of the lock info.

FYI, Type 21, Value 1 is locking the door from the inside on this lock.

0 Likes

(Paul Muldoon) #15

I’ve further stripped the rule down to this, but still keep getting the same error. I wonder if its the rule, the import at the top or something else?

import org.eclipse.xtext.xbase.lib.Functions

val Functions$Function2<GenericItem, GenericItem, Boolean> alarmRawParser = [
    lockAlarmRaw,
    lockItem |
    
    logDebug("Rules", "Lock: Alarm events: {}=[{}]",lockItem.getName,lockAlarmRaw.state.toString)
            switch (transform("JSONPATH", "$.type", lockAlarmRaw.state.toString)) {
                case "21" : {
                    lockItem.postUpdate(ON)
                    logDebug("Rules", "Lock: Alarm events: {} updated to ON (locked)",lockItem.getName)
                    sendNotification("xxxxxx@gmail.com", "Front Door Unlocked.")
                }
                case "22" : {
                    lockItem.postUpdate(OFF)
                    logDebug("Rules", "Lock: Alarm events: {} updated to OFF (unlocked)",lockItem.getName)
                    sendNotification("xxxxx@gmail.com", "Front Door locked.")
                }
                case "19" : {
                    val StringBuilder presenceMessage = new StringBuilder
                    switch (transform("JSONPATH", "$.value", lockAlarmRaw.state.toString)) {
                        case "1" : {
                            sendNotification("xxxxx@gmail.com", "Front Door Unlocked.")
                        }
                        case "2" : {
                            sendNotification("xxxxxx@gmail.com", "Front Door Unlocked.")
                        }
                    }
                    lockItem.postUpdate(OFF)
                    logDebug("Rules", "Lock: {}",presenceMessage.toString)
                    //SMS_Notification.sendCommand(presenceMessage.toString)
                }
            }
    true
]

rule "Lock: Update lock states after alarm_raw event (Lock_EntranceFront)"
when
	Item Lock_FrontDoor_Alarm_Raw received update
then
    alarmRawParser.apply(Lock_FrontDoor_Alarm_Raw.state.toString,Lock_FrontDoor,"Lock (Front Entrance)")
end
0 Likes

(Scott Rushworth) #16

The Schlage BE469 (which is what I have) and the Yale YRD220 do not automatically report the lock position, which is a big reason for these rules/lambda. In the big zwave thread, you mentioned that your lock reports the state of the lock all on it’s own, so you probably just need a rule for acting on user code entries. You could take out the lines with postUpdate in them, and you probably don’t need to act on type 21 or 22. The database entry on Chris’ site has some other codes you might want to act on though. Your lock also only supports Alarm V1, so your alarm messages are a little different (just type and value, based on this commit).

Did you install the JSONPath Transformation service? That import is required in order to use lambdas, and should be placed at the very top of the file. You can also strip out the three lines with presenceMessage in them.

0 Likes

[SOLVED] Schlage FE599NX Node XML / PaperUI
(Paul Muldoon) #17

Yes, the JSON Transformation is installed, and I have the import as the first line in the file. I’ve also stripped out the presenceMessage. You may notice I removed the “ACCESS_CONTROL” and Burglar Case stuff, not sure if that apply’s to my lock or not. And just have the JSONPATH looking at $.type and $.value.

And yea, I had thought perhaps my lock was always reporting back the state, but that does appear to be the case. I remember with WINK, their app somehow got the status update, probably also using the raw alarm info.

So currently, I can control the lock, but anything do manually, either with the keypad or manually turning the deadbolt does not update to OH2 yet.

I’ll get there :slight_smile: so much learning to do!

Latest, stripped down version of the rule and still getting same error

import org.eclipse.xtext.xbase.lib.Functions

val Functions$Function2<GenericItem, GenericItem, Boolean> alarmRawParser = [
    lockAlarmRaw,
    lockItem |
    
    logDebug("Rules", "Lock: Alarm events: {}=[{}]",lockItem.getName,lockAlarmRaw.state.toString)
            switch (transform("JSONPATH", "$.type", lockAlarmRaw.state.toString)) {
                case "21" : {
                    //lockItem.postUpdate(ON)
                    logDebug("Rules", "Lock: Alarm events: {} updated to ON (locked)",lockItem.getName)
                    sendNotification("xxxx@gmail.com", "Front Door Unlocked.")
                }
                case "22" : {
                    //lockItem.postUpdate(OFF)
                    logDebug("Rules", "Lock: Alarm events: {} updated to OFF (unlocked)",lockItem.getName)
                    sendNotification("xxxx@gmail.com", "Front Door locked.")
                }
                case "19" : {
                    switch (transform("JSONPATH", "$.value", lockAlarmRaw.state.toString)) {
                        case "1" : {
                            sendNotification("xxx@gmail.com", "Front Door Unlocked.")
                        }
                        case "2" : {
                            sendNotification("xxx@gmail.com", "Front Door Unlocked.")
                        }
                    }
                }
            }
    true
]

rule "Lock: Update lock states after alarm_raw event (Lock_EntranceFront)"
when
	Item Lock_FrontDoor_Alarm_Raw received update
then
    alarmRawParser.apply(Lock_FrontDoor_Alarm_Raw.state.toString,Lock_FrontDoor,"Lock (Front Entrance)")
end
0 Likes

(Scott Karns) #18

Hi Paul. I don’t have a Z-Wave lock myself, but from an inspection of your rules, which appear to be a pretty straightforward copy of @5iver’s rules from post 5 of this thread, you are supplying a string object as the first argument to the alarmRawParser lambda, but the definition of that lambda declares the first argument as an object of type GenericItem. That, I think, is the cause of the error you reported.

In your rule “Lock: Update lock states after alarm_raw event (Lock_EntranceFront)”, you should change:

alarmRawParser.apply(Lock_FrontDoor_Alarm_Raw.state.toString,Lock_FrontDoor,"Lock (Front Entrance)")

to:

alarmRawParser.apply(Lock_FrontDoor_Alarm_Raw,Lock_FrontDoor,"Lock (Front Entrance)")

With that change I think the error will be gone.

1 Like

(Paul Muldoon) #19

Great catch on that, and now its working. I’ve getting a Notifications now on my phone when the door is unlocked and by who, as well when it is locked.

I’ll probably add a separate rule now to send notice if the door is unlocked after a certain PM night time as well.

0 Likes

(Scott Rushworth) #20

That’s embarrassing… when I edited the lambda, I forgot to update the rule! I’ve corrected it now. Thank you!

Sorry for the headache @ptmuldoon!

0 Likes