I started migrating from OH 4. to OH 5.1. I decided to try the zwave-js-ui binding. I installed zwavejs on a separate RPI and upgraded to a zoos 800 usb stick. I finally got a schlage be469zp lock paired using S2 security and created the lock thing in OpenHAB. In the previous binding there was a switch channel for locking and unlocking the lock. In the Zwavejs implementation, the lock/unlock channel wants a number, 0 for unlock, 255 for lock. I’m having trouble figuring out a simple transformation on the link to a switch to accomplish the task. It seems overly painful to have to write a rule for every lock item to perform the most basic function of locking and unlocking the lock. Any help would be appreciated.
the datamodel for zwave js ui is allowing multiple values for this kind of binary data.
The binding has a mechanism to map these to binary (switch), but there are cases like this that have not yet been mapped.
If you put the binding into trace logging, a large json message is dumped in the log files at bridge start. If you provide that log I can add the mapping.
I set the debug mode to TRACE on the zwave-js bridge thing. Then I stopped the bridge thing using the disable button on the thing. I started a “tail -f openhab.log > schlage.log” in the /var/log/openhab folder in an ssh session. The following trace is what was written when I enabled the bridge. The lock item is Node 23, so I removed everything else because the file was too large to include otherwise. The channel of interest is “door-lock-mode”. The values listed as options in the zwave-js-ui interface are 0, 1, 16, 17, 32, 33, 254, and 255, but it seems like only 0 (unsecured) and 255 (secured) of the most interest.
be469zp.log (19.7 KB)
I found there are only 3 channels I found useful, 1. door-lock-mode, which is a number channel that can be set to lock/unlock the door, 255 to lock, 0 to unlock, 2. door-lock-bolt-status, which can be used in rules, and 3. battery-level.
I put all of the door-lock-mode items in a group, and then used that in a custom widget to generate a list of locks with label list items that can lock or unlock the doors.
The door icon can be clicked on to lock all of the doors. The door and the lock icons change based on whether a door is locked or unlocked.
Thanks to JustinG for his widget tutorial and rikoshak for his repeater examples.
uid: schlage_lock_list
tags:
- Door Locks
- Group
- Repeater
props:
parameters:
- default: Door Locks
description: Title of list
label: Label
name: label
required: false
type: TEXT
- context: item
description: Group that holds the Lock Mode Number Items
label: Lock Mode Group Item
name: modeItem
required: false
type: TEXT
timestamp: Jan 17, 2026, 9:48:15 PM
component: f7-card
config:
title: =props.label
style:
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: var(--f7-card-expandable-box-shadow)
margin: 5px
font-size: 30px
slots:
default:
- component: f7-card-content
slots:
default:
- component: f7-block
config:
style:
font-size: 20px
text-align: center
resizable: true
slots:
default:
- component: Label
config:
text: All Doors Status
- component: oh-icon
config:
icon: '=(@@props.modeItem == "255") ? "oh:door-closed" : "oh:door-open"'
width: 60px
action: command
actionCommand: "255"
actionItem: =props.modeItem
- component: f7-row
slots:
default:
- component: f7-col
slots:
default:
- component: oh-list
config:
style:
font-size: 18px
slots:
default:
- component: oh-repeater
config:
for: item
sourceType: itemsInGroup
groupItem: =props.modeItem
fragment: true
slots:
default:
- component: oh-list-item
config:
action: toggle
actionCommand: "255"
actionCommandAlt: "0"
actionItem: =loop.item.name
badge: '=(@@loop.item.name == 255) ? "Locked" : "Unlocked"'
badgeColor: '=(@@loop.item.name == 255) ? "green" : "orange"'
icon: '=(@@loop.item.name == 255) ? "oh:lock-closed" : "oh:lock-open"'
style:
padding-right: calc(var(--f7-list-item-padding-horizontal) +
var(--f7-safe-area-right))
title: =loop.item.label
You do not need a rule for this. Just use a MAP transformation on the Switch channel.
Create a map like lock.map with ON=255 and OFF=0, then apply it to the channel link. That way the Switch behaves normally while zwave-js gets the numeric values it expects.
I did try using a MAP transformation but couldn’t get it to work. I concluded that the issue was that the channel is a number channel, not a switch. I was just trying it again in my test setup, and when I try to link a switch, either existing, or creating a new one, MAP isn’t an option under the profile options in my test instance. It is in the production instance, so that is a curiosity. Although, in the production instance, I imported my configuration from my previous version. The test instance is a clean install in which I’ve only created a few things and items. Both instances are version 5.1, the test box is an RPI 4 and the production box is an RPI 5. I don’t know if that makes any difference.
The rules I put in place are for conditions like when the door is locked or unlocked after dark, then turn the porch lights on or off. Another rule locks all of the doors in the evening.
I also found the notification-virtual channel to be useful if you want to see the raw json showing operations on the lock. I use this to text me who is locking/unlocking the door using the keypad. For example:
{"commandClass":0,"endpoint":0,"event":6,"type":6,"label":"Access Control","eventLabel":"Keypad unlock operation","parameters":{"userId":1}}
{"commandClass":0,"endpoint":0,"event":1,"type":6,"label":"Access Control","eventLabel":"Manual lock operation"}
As an aside, I found the communication with the lock much more reliable when I re-included it with S2.
One thing I found curious, and this is not in any way related to OpenHAB, but when I added the locks in the zwave-js-ui there is a channel section labeled v1 which lists the user code slots. Out of my 5 locks, one lock generated 2 pairs of slots, and one generated 30 pairs. The others were somewhere in between. On two of the locks I did a factory reset before including them (all with S2 security), and they show the least number of slots. For the remaining locks, I finally dug into simplicity studio and found out how to remove them from the existing nortek husbzb stick and then included them to he zooz 800 stick without doing a factory reset on them. Also, when including them, I had better luck when I located the zwave stick close to the lock, and checked the box next to “increase the node report timeout” parameter in zwave-js. I located the stick close to the locks by moving the zwavejs RPI near each door and restarting it.
Super interesting! I’ve had a problem with my ID lock 150 where I could never get the user codes in Zwave-JS-UI, however enabling the “increase node report timeout” seems to fix this. Now every code is reported back (just not the master-pin, maybe a security reason?)
