Please help me understand zwave lock inclusion/exclusion and secure install

Thank you for all the responses, I have door lock that I can control for BasicUI but something strange has happened. I seam to have a duplicate lock and not sure how it got there or how to fix it. Both seem to operate the lock but only one updates at a time.


Here are my items

Switch Z_Wave_Front_Door_Lock "Front Door Lock" ["Switchable"] { channel="zwave$
Number Z_Wave_Front_Door_Lock_Battery "Battery [%.0f%%]" <battery> { channel="z$

And here is my sitemap

Switch item=Z_Wave_Front_Door_Lock

Text item=Z_Wave_Front_Door_Lock_Battery label="Front Door"

And my BasicUI

Does it matter that this duplication of the lock and battery show up in HABmin? If so what caused it and how do I fix it?

Do you have Simple Mode enabled? Check in Paper UI under System->Configuration on the Item Linking panel.

Simple mode is enabled, yes.

Simple mode will create items automatically. That explains where those other items are coming from. If you don’t want those items created automatically, you can disable simple mode.

Will having both items in HABmin and only one physical item cause problems? It seams to function fine for now. Is it possible to remove the item that was automatcly populated?

No, it won’t cause a problem.

I don’t know. I’ve never used this feature.

Thank you evrryone for the help. The lock is working as I had hoped!

So… The lock works almost as expected. It does not update openhab when manually locked or unlocked. Looking into it shows that I need to some coding with the Alarm_raw. This also means that I need to use a transform.
I have been following the wright up, but do not fully under stand:

I have used PaperUI to install JSONPATH and MAP Transformation. I am confused by what the: MAP (lock.map) is and what I need to do to create it.
I have create an Item that looks like this

Group:Switch:OR(OFF,ON)    gLock    "Locks [MAP(lock.map):%s]"    <lock>
Group    gLockRaw    "Locks (raw) [%s]"    <lock>
Switch    Z_Wave_Front_Door_Lock    "Lock (Front Entrance) [MAP(lock.map):%s]"    <lock>    (gLock)    {channel="zwave:device:Zstick:node6:lock_door"}
String 	  Z_Wave_Front_Door_Lock_Alarm_Raw    "Lock (Front Entrance): Alarm Raw [%s]"    <shield>    (gLockRaw)    {channel="zwave:device:Zstick:node6:alarm_raw"}

The wright up also talks about an import org.eclipse.smarthome.model.script.ScriptServiceUtil being at the top the rules. Does this mean the to of all the rules or the top of my lock rules? What is this import, why do I need it and how do I get it?
Also I have a list of alrarm_raw events, but I do not know where to place them.

And always, any help or advise is appreciated.

Create a file in your ${OPENHAB_CONF} (depends on how you installed OH) named lock.map and put in the contents from my post.

You don’t need to get it… just import it at the top of the rule file (above all rules).

Those are just for reference. You lock may report something different, so you’ll need to change the lambda.

I typed quick… hopefully this is what you need!

I think I understand. I have copied your rule and added my values to it. It looks like this:

import org.eclipse.smarthome.model.script.ScriptServiceUtil

rule "Lock: Update lock states after alarm_raw event"
when
    Member of gLockRaw received update
then
    val actionItem = ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.toString.replace("_Alarm_Raw",""))
    logInfo("Rules", "Lock: Alarm events: {}=[{}]",actionItem.name,triggeringItem.state.toString)
    val StringBuilder message = new StringBuilder(actionItem.name)
    switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
        case "ACCESS_CONTROL" : {
            switch (transform("JSONPATH", "$.event", triggeringItem.state.toString)) {
                case "21", case "18", case "24" : {
                    actionItem.postUpdate(ON)
                    message.append(" updated to ON (locked)")
                }
                case "22", case "19" : {
                    actionItem.postUpdate(OFF)
                    message.append(" updated to OFF (unlocked)")
                }
//                case "6" : {
//                    actionItem.postUpdate(OFF)
//                   message.append(" was unlocked with")
//                    switch (transform("JSONPATH", "$.code", triggeringItem.state.toString)) {
//                        case "1" : {
//                            message.append(" Scott's code")
//                        }
//                        case "2" : {
//                            message.append(" Lisa's code")
//                        }
//                    }
//                }
                case "26", case "17", case "23" : {
                    actionItem.postUpdate(OFF)// jammed could mean unlocked, so I do this for safety... you may want to send an alert here too
                    message.append(" is jammed, so setting lock to OFF (unlocked)")
                }
//                case "26", case "17", case "23" : {
//                    message.append(" keypad is disabled due to too many failed codes")
//                }
                default : {
                    message.append(" unknown door lock Event, ").append(triggeringItem.state.toString)
                }
            }
            if (transform("JSONPATH", "$.event", triggeringItem.previousState(true).state.toString) == "26" && transform("JSONPATH", "$.event", triggeringItem.state.toString) != "26") {
                message.append(" and is no longer jammed")
            }
        }
//        case "BURGLAR" : {
//            //gSiren.sendCommand(ON)
//            message.append(" has detected an intruder")
//        }
        case "POWER_MANAGEMENT" : {
            message.append(" received a Power Management alarm, ").append(triggeringItem.state.toString)
        }
        default : {
            message.append(" received and unknown Type in alarmRawParser, ").append(triggeringItem.state.toString)
        }
    }
    logInfo("Rules", "Lock: Alarm events: {}", message.toString)
end

I turned the code I feel I don’t need into text.

I then created a lock.map under /etc/openhab2/transform, and copied

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

into it. The lock still ill does not update with manual activation. Any thoughts?

Put the binding into debug mode so we can see what the lock is sending (if anything) when manually operated. Enable debug logging as described in the post below, then operate the lock. If the lock is reporting its status when manually operated, you will see activity in the log file. Report back what you see in the log.

The 914TRL reports different events than the BE469, so you’ll need to adjust the switch/case statements. Here is an example…

Thank you, all of you, for help and patience. I am really trying to understand all of this. I am more of a nuts and bolts kind of guy and this stuff, though very cool, has me feeling over my head.

I looked at doc about turning on the debug. It says to enter the console, which I am guessing is the process of SSH into openhabian. I paste

log:set DEBUG org.openhab.binding.zwave

But get an error -bash: log:set: command not found
So I am guessing I am not something correctly.

I did see that activity seems to be captured in the log viewer anyway. This is what it shows.

2019-06-29 20:57:17.211 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3520 to 3521

2019-06-29 20:57:17.244 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_ack changed from 1273 to 1274

2019-06-29 20:57:17.251 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3521 to 3522

2019-06-29 20:57:17.271 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3522 to 3523

2019-06-29 20:57:17.291 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3523 to 3524

2019-06-29 20:57:17.321 [vent.ItemStateChangedEvent] - zwave_device_Zstick_node6_alarm_number changed from 0 to 21

2019-06-29 20:57:17.326 [vent.ItemStateChangedEvent] - zwave_device_Zstick_node6_alarm_raw changed from {"type":"0","value":"0"} to {"type":"21","value":"1"}

2019-06-29 20:57:31.720 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3524 to 3525

2019-06-29 20:57:31.758 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_ack changed from 1274 to 1275

2019-06-29 20:57:31.762 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3525 to 3526

2019-06-29 20:57:31.784 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3526 to 3527

2019-06-29 20:57:31.794 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 3527 to 3528

2019-06-29 20:57:31.831 [vent.ItemStateChangedEvent] - zwave_device_Zstick_node6_alarm_number changed from 21 to 22

2019-06-29 20:57:31.834 [vent.ItemStateChangedEvent] - zwave_device_Zstick_node6_alarm_raw changed from {"type":"21","value":"1"} to {"type":"22","value":"1"}

I am pretty sure I changed the case values correctly for my lock.

switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
        case "ACCESS_CONTROL" : {
            switch (transform("JSONPATH", "$.event", triggeringItem.state.toString)) {
                case "18", case "21", case "24" : {
                    actionItem.postUpdate(ON)
                    message.append(" updated to ON (locked)")
                }
                case "19", case "21" : {
                    actionItem.postUpdate(OFF)
                    message.append(" updated to OFF (unlocked)")
                }

Thank you again, and let me know what to do to help

You were at a shell prompt, not the console.

This doesn’t look right.

                case "18", case "21", case "24" : {
...
                case "19", case "21" : {

One of those should be “22”.

You are correct, I changed it to

 case "19", case "22" : {

I went back and relized I had not saved my updated items. Now my items look like this:

Group:Switch:OR(OFF,ON)    gLock    "Locks [MAP(lock.map):%s]"    <lock>
Group    gLockRaw    "Locks (raw) [%s]"    <lock>
Switch    Z_Wave_Front_Door_Lock    "Lock (Front Entrance) [MAP(lock.map):%s]"    <lock>    (gLock)    {channel="zwave:device:Zstick:node6:lock_door"}
String 	  Z_Wave_Front_Door_Lock_Alarm_Raw    "Lock (Front Entrance): Alarm Raw [%s]"    <shield>    (gLockRaw)    {channel="zwave:device:Zstick:node6:alarm_raw"}

And my log gives me this:

2019-06-30 08:32:25.157 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 417 to 418

2019-06-30 08:32:25.176 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_ack changed from 145 to 146

2019-06-30 08:32:25.180 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 418 to 419

2019-06-30 08:32:25.195 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 419 to 420

2019-06-30 08:32:25.217 [vent.ItemStateChangedEvent] - zwave_serial_zstick_Zstick_serial_sof changed from 420 to 421

2019-06-30 08:32:25.254 [vent.ItemStateChangedEvent] - zwave_device_Zstick_node6_alarm_number changed from 21 to 22

2019-06-30 08:32:25.257 [vent.ItemStateChangedEvent] - Z_Wave_Front_Door_Lock_Alarm_Raw changed from {"type":"21","value":"1"} to {"type":"22","value":"1"}

2019-06-30 08:32:25.261 [vent.ItemStateChangedEvent] - zwave_device_Zstick_node6_alarm_raw changed from {"type":"21","value":"1"} to {"type":"22","value":"1"}

==> /var/log/openhab2/openhab.log <==

2019-06-30 08:32:25.266 [INFO ] [eclipse.smarthome.model.script.Rules] - Lock: Alarm events: Z_Wave_Front_Door_Lock=[{"type":"22","value":"1"}]

2019-06-30 08:32:25.282 [INFO ] [eclipse.smarthome.model.script.Rules] - Lock: Alarm events: Z_Wave_Front_Door_Lock received and unknown Type in alarmRawParser, {"type":"22","value":"1"}

I am guessing that this last line means that I have wrong in my lock.map file or something is not reading from my lock.map?

Hmm. Looking at this bit of code in the rule you posted earlier…

    switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
        case "ACCESS_CONTROL" : {
        [snip]
        case "POWER_MANAGEMENT" : {
        [snip]
        default : {

Isn’t this the value of triggeringItem.state?

{"type":"21","value":"1"}

If so, I think you need to get rid of those case statements, as well as the inner switch statement. For example:

switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
    case "18", case "21", case "24" : {
        actionItem.postUpdate(ON)
        message.append(" updated to ON (locked)")
    }
    case "19", case "22" : {
        actionItem.postUpdate(OFF)
        message.append(" updated to OFF (unlocked)")
    }
    ...
    default : {
        message.append(" unknown door lock Event, ").append(triggeringItem.state.toString)
    }
}

I tried removing that line as you suggested, then I noticed I got some errors in my log. I put the rule back to the way I had it and I got even more errors. Here they are:

2019-06-30 20:36:44.156 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'home.rules' has errors, therefore ignoring it: [37,17]: missing '}' at 'case'

[44,17]: mismatched input 'default' expecting 'end'

Is [37,17] the column then line? What exactly does this error mean, there should be a } in column 37? What does the next error mean? In case it helps, here is what I am currently using for my rule:

rule "Lock: Update lock states after alarm_raw event"
when
    Member of gLockRaw received update
then
    val actionItem = ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.toString.replace("_Alarm_Raw",""))
    logInfo("Rules", "Lock: Alarm events: {}=[{}]",actionItem.name,triggeringItem.state.toString)
    val StringBuilder message = new StringBuilder(actionItem.name)
    switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
        case "ACCESS_CONTROL" : {
            switch (transform("JSONPATH", "$.event", triggeringItem.state.toString)) {
                case "18", case "21", case "24" : {
                    actionItem.postUpdate(ON)
                    message.append(" updated to ON (locked)")
                }
                case "19", case "22" : {
                    actionItem.postUpdate(OFF)
                    message.append(" updated to OFF (unlocked)")
                }
/*                case "6" : {
                    actionItem.postUpdate(OFF)
                   message.append(" was unlocked with")
                    switch (transform("JSONPATH", "$.code", triggeringItem.state.toString)) {
                        case "1" : {
                            message.append(" Scott's code")
                        }
                        case "2" : {
                            message.append(" Lisa's code")
                        }
                    }
                }
                case "26", case "17", case "23" : {
                    actionItem.postUpdate(OFF)// jammed could mean unlocked, so I do this for safety... you may want to send an alert here too
                    message.append(" is jammed, so setting lock to OFF (unlocked)")
                }
               case "26", case "17", case "23" : {
                    message.append(" keypad is disabled due to too many failed codes")
                }
                default : {
                    message.append(" unknown door lock Event, ").append(triggeringItem.state.toString)
                }
            }
            if (transform("JSONPATH", "$.event", triggeringItem.previousState(true).state.toString) == "26" && transform("JSONPATH", "$.event", triggeringItem.state.toString) != "26") {
                message.append(" and is no longer jammed")
            }
        }
        case "BURGLAR" : {
            //gSiren.sendCommand(ON)
            message.append(" has detected an intruder")
        }
        case "POWER_MANAGEMENT" : {
            message.append(" received a Power Management alarm, ").append(triggeringItem.state.toString)
        }*/
        default : {
            message.append(" received and unknown Type in alarmRawParser, ").append(triggeringItem.state.toString)
        }
    }
    logInfo("Rules", "Lock: Alarm events: {}", message.toString)
end

If your device is reporting json strings of the following form, please follow the guidance I provided above. Your rule will never work the way you have it defined with the json strings below.

{"type":"21","value":"1"}

mhilbush, thank you, thank you, thank you!!!

I modified my rule like said and now it works. It now looks like this:

rule "Lock: Update lock states after alarm_raw event"
when
    Member of gLockRaw received update
then
    val actionItem = ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.toString.replace("_Alarm_Raw",""))
    logInfo("Rules", "Lock: Alarm events: {}=[{}]",actionItem.name,triggeringItem.state.toString)
    val StringBuilder message = new StringBuilder(actionItem.name)
    switch (transform("JSONPATH","$.type",triggeringItem.state.toString)) {
                case "18", case "21", case "24" : {
                    actionItem.postUpdate(ON)
                    message.append(" updated to ON (locked)")
                }
                case "19", case "22" : {
                    actionItem.postUpdate(OFF)
                    message.append(" updated to OFF (unlocked)")
                }
 }
    logInfo("Rules", "Lock: Alarm events: {}", message.toString)
end

Your patience has been much appreciated. I would love to understand why this change fixed the issue. I have read what I could find JSON and don’t really understand it. If you are willing to direct me to any helpful informaiton, or just willing to share whatever knowledge you I would be love to try and learn from it.

Oh by the way, I like your BMW

The original rule was expecting a JSON document that probably looked something like this.

{ "type":  "ACCESS_CONTROL", "event": "18" }

That’s why the original rule used transform("JSONPATH","$.type",triggeringItem.state.toString) in the first switch statement, then transform("JSONPATH", "$.event", triggeringItem.state.toString) in the second switch statement once it determined it was of type ACCESS_CONTROL.

The first JSONPATH transform call basically says give me the value associated with the name type. The $ says to look in the root of the JSON document. The second call says give me the value associated with the name event, also in the root of the document.

I hope this makes sense.

There are a bunch of evaluators on the web where you can test your ideas independently of putting them in a rule. For example, https://jsonpath.com/.

Try putting $.type and {"type":"21","value":"1"} in that tool and you’ll see how it evaluates. Then compare it to $.type and { "type": "ACCESS_CONTROL", "event": "18" } and you’ll see the difference.

Thanks. The E30 M3 was one of the best cars ever made, IMO. I restored it back to stock condition, and don’t drive it on the track anymore. With 58,000 miles (93,000 km) on the clock, it spends way too much time in the garage, unfortunately. :frowning_face:

1 Like