Zwave - Yale YRD220 Lock

Change the $.code to $.level. And change the codes to match yours.

Yes.

1 Like

Thanks Scott. Do you know if theres a way to remotely unlock the door using codes for testing purposes? ie: not physically entering the code.

I assume by switching the lock on/off via PaperUI it would count this as RF Lock or RF unlock (Alarm type 0x19 or 0x18)

The codes are only able to be used on the keypad.

Yes. I believe you have examples of both here…

Indeed, Level 1 (RF function), Event 3 - Lock or Even 4, Unlock

Getting my head around it now!

Hi Scott,

In your rule, what is this used for? It appears commented.Id like to build into a dashboard an ability to display who/who unlocked/locked the door last.

/*
        {"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"}
    */

It’s a multiline comment… just information, in case someone could use it. It’s a list of all alarms I’ve seen. I need to fill in the event 3 & 4.

I think the easiest way to do that may be to add another Item to hold that info. Then set it in case 6. The rule currently doesn’t identify who locked a door with a code, but tthat coud easily be added.

Hi Scott

So define a proxy item

String UserCode                       "Last Code Used on the Door"

With rule modification


                case "6" : {
                    val StringBuilder message = new StringBuilder(actionItem.name)
                    message.append(" was unlocked with")
                    switch (transform("JSONPATH", "$.level", triggeringItem.state.toString)) {
                        case "1" : {
                            message.append(" Jodies Code")
                            UserCode.postUpdate(message.append.toString)
                        }

???

                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(" Jodie's code")
                        }
                        case "2" : {
                            message.append(" Kris' code")
                        }
                    }
                    logDebug("Rules", "Lock: {}",message.toString)
                    UserCode.postUpdate(message.toString)
                }

Kris, sorry for the late response, I must have missed the notification on this. I had a few errors. First my mysql persistence was not working due to a misconfiguration on my end. I uninstalled everything and reinstalled and reconfigured everything from scratch and that began working. Then I didn’t understand that you could do persistence for individual items vs groups so I had that configured incorrectly as well. Once I read a little more into it and figured out ow it all worked, I reconfigured and everything began working. It’s been a little bit since I fixed it so there may be more but that was what I remembered from it.

1 Like

Thanks fifo! I managed to get mine all sorted too :slight_smile:

EDIT: Spoke too soon

ok great to hear! :slight_smile:

@5iver

I recently moved my system to a new machine and am encountering this error again.

My PaperUI default persistence is as you suggested, influx.

19:51:34.391 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'Lock: Update lock states after alarm_raw event': cannot invoke method public abstract org.eclipse.smarthome.core.types.State org.eclipse.smarthome.core.persistence.HistoricItem.getState() on null

My persistance file is as it was

MapDB.persist

 FrontDoor_DoorLock_Alarm_Raw : strategy = everyChange
 FrontDoor_DoorLock : strategy = everyChange, everyHour, everyDay, restoreOnStartup

There was nothing relating to the locks in influxdb.persist.

And the rule is as it was. The error triggered when I used a manual twist of the lock.

rule "Lock: Update lock states after alarm_raw event" when
    Item FrontDoor_DoorLock_Alarm_Raw received update then
    val actionItem = gLock.members.findFirst[ item | item.name.toString == triggeringItem.name.toString.replace("_Alarm_Raw","") ]
    logInfo("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" : {
                    actionItem.postUpdate(ON)
                    logInfo("FrontDoor", "Lock: Alarm events: {} updated to Locked",actionItem.name)
                    val StringBuilder message = new StringBuilder("Locked via")
                    switch (transform("JSONPATH", "$.level", triggeringItem.state.toString)) {
                       case "1" : {
                            message.append(" Twist Knob")
                        }
                        case "2" : {
                            message.append(" Lock and Leave")
                        }
                    }
                     logInfo("FrontDoor", "Lock: {}",message.toString)
                    if(gPresenceSensors.state == OFF) {
                        sendBroadcastNotification(message.toString)
                    }
                    if(gPresenceSensors.state == ON) {
                    /*gAllEchoAlerts.sendCommand(message.toString)*/
                    UserCode.postUpdate(message.toString)
                  }
                }
                case "2" : {
                    actionItem.postUpdate(OFF)
                    val StringBuilder message = new StringBuilder("Unlocked via TwistKnob")
                    logInfo("FrontDoor", "Unlock: {}",message.toString)
                    if(gPresenceSensors.state == OFF) {
                    sendBroadcastNotification(message.toString)
                    }
                    if(gPresenceSensors.state == ON) {
                    /*gAllEchoAlerts.sendCommand(message.toString)*/
                    UserCode.postUpdate(message.toString)
                  }
                }
                case "3" : {
                    actionItem.postUpdate(ON)
                    val StringBuilder message = new StringBuilder("Locked via UI")
                    logInfo("FrontDoor", "Lock: {}",message.toString)
                    if(gPresenceSensors.state == OFF) {
                      sendBroadcastNotification(message.toString)
                    }
                    if(gPresenceSensors.state == ON) {
                      /*gAllEchoAlerts.sendCommand(message.toString)*/
                      UserCode.postUpdate(message.toString)
                  }
                }
                case "4" : {
                    actionItem.postUpdate(OFF)
                    val StringBuilder message = new StringBuilder("Unlocked via UI")
                    logInfo("FrontDoor", "Unlock: {}",message.toString)
                    if(gPresenceSensors.state == OFF) {
                      sendBroadcastNotification(message.toString)
                    }
                    if(gPresenceSensors.state == ON) {
                      /*gAllEchoAlerts.sendCommand(message.toString)*/
                      UserCode.postUpdate(message.toString)
                    }
                }
                case "5" : {
                    actionItem.postUpdate(ON)
                    val StringBuilder message = new StringBuilder("Locked with ")
                    switch (transform("JSONPATH", "$.level", triggeringItem.state.toString)) {
                        case "1" : {
                            message.append(" Jodies Code")
                        }
                        case "2" : {
                            message.append(" Kris Code")
                        }
                        case "3" : {
                            message.append(" user code 3")
                        }
                        case "4" : {
                            message.append(" user code 4")
                        }
                        case "5" : {
                            message.append(" user code 5")
                        }
                    }
                    logInfo("FrontDoor", "Lock: {}",message.toString)
                    if(gPresenceSensors.state == OFF) {
                        sendBroadcastNotification(message.toString)
                    }
                    if(gPresenceSensors.state == ON) {
                        /*gAllEchoAlerts.sendCommand(message.toString)*/
                        UserCode.postUpdate(message.toString)
                    }
                }
                case "6" : {
                    actionItem.postUpdate(OFF)
                    val StringBuilder message = new StringBuilder("Unlocked with")
                    switch (transform("JSONPATH", "$.level", triggeringItem.state.toString)) {
                        case "1" : {
                            message.append(" Jodies Code")
                        }
                        case "2" : {
                            message.append(" Kris Code")
                        }
                        case "3" : {
                            message.append(" user code 3")
                        }
                        case "4" : {
                            message.append(" user code 4")
                        }
                        case "5" : {
                            message.append(" user code 5")
                        }
                        case "251" : {
                            message.append(" Master code")
                        }
                    }
                    logInfo("Rules", "Unlock: {}",message.toString)
                    if(gPresenceSensors.state == OFF) {
                        sendBroadcastNotification(message.toString)
                     }
                     if(gPresenceSensors.state == ON) {
                          /*gAllEchoAlerts.sendCommand(message.toString)*/
                          UserCode.postUpdate(message.toString)
                      }
                }
                case "11" : {
                    logInfo("Rules", "Lock: Alarm events: {} is jammed, so setting lock to OFF (unlocked)",actionItem.label)
                    actionItem.postUpdate(OFF)
                    sendBroadcastNotification(actionItem.label + " is jammed")
                }
                case "13" : {
                    val String message = "Front Door Usercode has been deleted"
                    logInfo("Rules", "Door Lock: User Code: {}",message)
                }
                case "14" : {
                    val String message = "Front Door Usercode has been added"
                    logInfo("Rules", "Door Lock: User Code: {}",message)
                }
                case "16" : {
                    val String message = actionItem.label + " keypad is disabled due to too many failed codes"
                    logInfo("Rules", "Lock: Alarm events: {}",message)
                }
                default : {
                    val String message = "Unknown door lock Event, " + triggeringItem.state.toString
                    logInfo("Rules", "Lock: Alarm events: {}",message)
                    sendBroadcastNotification(message)
                }
            }
            if (transform("JSONPATH", "$.event", triggeringItem.previousState(true, "influxdb").state.toString) == "11" && transform("JSONPATH", "$.event", triggeringItem.state.toString)
!= "11") {
                val String message = actionItem.label + " is no longer jammed"
                logInfo("Rules", "Lock: Alarm events: {}",message)
            }
        }
        case "BURGLAR" : {
            FrontDoorLock_Tamper.sendCommand(ON)
            val String message = "Intruder at " + actionItem.name
            logInfo("Tamper Alert", "Lock: Alarm events: {}",message)
        }
        case "POWER_MANAGEMENT" : {
            val String message = "Power Management alarm for " + actionItem.label + ", " + triggeringItem.state.toString
            logInfo("Rules", "Lock: Alarm events: {}",message)
            //SMS_Notification.sendCommand(message)
        }
        default : {
            val String message = "Unknown Type in alarmRawParser, " + triggeringItem.state.toString
            logInfo("Rules", "Lock: Alarm events: {}",message)
            //SMS_Notification.sendCommand(message)
        }
    }
end

If you are using influx for persistence, then you need an influx.persist file, and FrontDoor_DoorLock_Alarm_Raw needs to be in there.

1 Like

I really need more sleep :frowning: I had the items in the wrong file. Sorry for wasting your time!

Not sure where I’m going wrong, I used @ptmuldoon 's code from Nov 17 for my Yale lock. Here’s my code.

My Yale lock alarm raw status uses “type 21, value 2” when locked with the touch buttons on the front and “Type 22, value 2” when unlocking.

Here’s the rule:

rule "Lock: Update lock states after alarm_raw event"
when
    Item Lock_SideGarage_Alarm_Raw received update
then
    val actionItem = gLock.members.findFirst[ item | item.name.toString == triggeringItem.name.toString.replace("_Alarm_Raw","") ]
   
    logDebug("lock rule triggered")
    
    logDebug("Rules", "Lock: Alarm events: {}=[{}]",actionItem.name,triggeringItem.state.toString)
            switch (transform("JSONPATH", "$.type", triggeringItem.state.toString)) {
                case "21" : {
                    actionItem.postUpdate(ON)
                    logDebug("Rules", "Lock: Alarm events: {} updated to ON (locked)",actionItem.getName)
                }
                case "22" : {
                    actionItem.postUpdate(OFF)
                    logDebug("Rules", "Lock: Alarm events: {} updated to OFF (unlocked)",actionItem.getName)
                }
                case "19" : {
                    switch (transform("JSONPATH", "$.value", lockAlarmRaw.state.toString)) {
                        case "1" : {
				actionItem.postUpdate(OFF)
                        }
                        case "2" : {
				actionItem.postUpdate(OFF)
                        }
                    }
                }
            }
end

Here’s my items

Switch 	               	Lock_SideGarage			"Lock (Garage Side Door) [MAP(lock.map):%s]"	<lock>      	(gLock)	{channel="zwave:device:512:node4:lock_door"}
String 	              	Lock_SideGarage_Alarm_Raw    	"Lock (Garage Side Door): Alarm Raw [%s]"	<shield>        (glock) {channel="zwave:device:512:node4:alarm_raw"}

When the lock updates, it triggers the rule but I just get an error with not very much info in it and not sure how to troubleshoot from here:

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Lock: Update lock states after alarm_raw event': An error occurred during the script execution: index=1, size=1

I have JSON Path Transformation installed

Hope someone can point out an obvious mistake I’m making… I’m stumped.

What is lockAlarmRaw? If this isn’t the cause of the error, add debug lines between every line to see where the script fails. Everything else looks OK, but I’d use the name attribute rather than the getName method. Also, be careful with the group names. You have gLock and glock. Maybe use gLockRaw for one of them?

Good question. Looks like it was a remnant of my copy/paste from other examples. Changed that to “triggeringItem.state.toString”

I commented out all the lines and started to turn them on in small chunks. Looks like the problem was with “logDebug”. As soon as I commented out all the “logDebug” lines, it seemed to work fine. If I change the “logDebug” with “logInfo” as I’ve used in other rules, it seemed to work. Not sure why logDebug doesn’t work. At least the script seems to run now without errors.

Moving my code to Jython.

with my limited knowledge, and looking at code examples (@5iver) managed to convert.
It may help if someone looking to make a move to Jython.

> from core.rules import rule
from core.triggers import when
from core.log import logging, LOG_PREFIX, log_traceback
from org.slf4j import LoggerFactory
from org.joda.time import DateTime
from core.items import itemRegistry
from core.utils import sendCommandCheckFirst        # Required for checking the state of the items
from core.actions import ScriptExecution            # Required for Timers DSL/Extend format
from core.actions import Pushover                   # Required for pushover Action
from core.actions import Transformation             # Required for transformation
import json

> log = LoggerFactory.getLogger("{}.RULE-Auto Lights Porchwall".format(LOG_PREFIX))
> 
> @rule(name="Main door Alarm Decode",description="Decode the main door lock alarms")
> @when("Item Lock_Maindoor_AlarmRaw received update")
> def main_Door_Alarm_Decode(event):
>     '''
>     Decode Z wave lock on Main door as it sends 
>     json parameters for various Options
>     '''
>     lock_json_data = {"21":{"1":"Main Door Locked Manually by Key Cylinder","2":"Main Door Locked Manually by Touch function","3":"Main Door Locked Manually by Inside button"},
>                         "22":{"1":"Main Door Unlocked Manually"},
>                         "24":{"1":"Main Door Locked with Z wave"},
>                         "25":{"1":"Main Door Unlocked with Z wave"},
>                         "27":{"1":"Auto relock completed"},
>                         "161":{"1":"Main Door Tamper, Attempts exceeded","2":"Main Door Tamper, Front cover removed","3":"Main Door Tamper, Attempts exceeded # Pressed"},
>                         "0":{"0":"Default State"}}
>     lock_json_user_data = {"18":"Keypad locked by USER :",
>                             "19":"Keypad unlocked by USER :",
>                             "33":"User deleted :",
>                             "38":"Non access Code USER:",
>                             "96":"Daily schedule Set USER :",
>                             "97":"Daily Schedule enabled USER :",
>                             "100":"Scheduled types erased USER :",
>                             "101":"Scheduled types enabled USER :",
>                             "112":"User Added :",
>                             "113":"Duplicate PIN CODE ERROR USER :",
>                             "131":"Disabled user code entered USER :",
>                             "132":"Valid user Outside Schedule USER :",
>                             "176":"Mobile access used to unlock USER"}
> 
>     message = str(event.itemState)
>     #log.info("Lock Alarm Message : {}",message)
>     key_data = Transformation.transform("JSONPATH", "$.type", message)
>     key_value = Transformation.transform("JSONPATH", "$.value", message)
>     #log.info("Lock Alarm Message : {}, key_data : {}, key_value : {}".format(message,key_data,key_value))
>     if key_data != "0":
>         if key_data in lock_json_user_data:
>             result = lock_json_user_data.get(key_data)
>             result += key_value
>             Pushover.sendPushoverMessage(Pushover.pushoverBuilder(result))
>             #log.info("Lock Alarm Message : {}",result)
>         else:
>             result = lock_json_data[key_data][key_value]
>             Pushover.sendPushoverMessage(Pushover.pushoverBuilder(result))
>             #log.info("Lock Alarm Message : {}",result)
>     else:
>         return

When a function is fed through the rule decorator, I add a log attribute to it, so that you do not need these imports or the constant. You’d use it like this…

main_Door_Alarm_Decode.log.info("Lock Alarm Message : {}",message)

Since JSONPATH has some issues/limitations, you may also want to consider using the json module, which is much more powerful. Let me know if you’d like some help with it.

It looks like you had some trouble with code fences… try just using three ticks before and three after…

```
code or log goes here
```

Thanks! will check it out.