Summary
I’ve migrated my Z-Wave setup a few different times. I started with SmartThings, tried using Home Assistant’s Z-Wave implementation a few years back, switched back to SmartThings, and finally settled on something I’m happy with: zwave2mqtt running in Docker. It’s on a separate Pi with an AEON Z-Stick, so I can restart Home Assistant without impacting the Z-Wave network.
Everything was pretty quick and painless to migrate over from SmartThings, minus the Schlage BE469. It’s an older model and has been a pain in the ass. The pairing was easy enough, i.e. reset to factory defaults and do a secure pair. The locking and unlocking was easy enough. However, getting the lock to correctly report if it was locked or unlocked was driving me nuts. The Z-Wave value will show a “True” or “False” for if the lock was engaged, but that’s only for Z-Wave. Manually unlocking it will report a “Manual Unlock” event, but the lock still shows that it’s locked.
The TL;DR is that a used a Node-RED automation to update an input_boolean based on the last Z-Wave or physical lock status, and then a lock template is used on top of that.
Implementation
The first part is the MQTT integration. You’ll end up with two entities that are used, although the names might vary depending on how you have them saved in zwave2mqtt:
lock.lock_front_door_zwave
sensor.lock_front_door_alarm_access_control
The top is the actual Z-Wave entity for the lock. The bottom is the status when something changes. If you look at the values sensor.lock_front_door_alarm_access_control
you’ll see the following:
Clear
Manual Lock Operation
Manual Unlock Operation
Keypad Lock Operation
Keypad Unlock Operation
Auto Lock
Lock Jammed
Keypad Disabled
New Program Code Entered
Basically, when any of those happen, it’ll send the corresponding event and then go back to the Clear
status. The only ones I care about are the Lock
and Unlock
events.
The first step is to create the input_boolean that will act as the lock state:
input_boolean:
lock_front_door_switch:
name: "Lock Front Door Virtual Switch"
Easy enough. Restart Home Assistant and it’ll show up in your entities. The next step is to create a Node-RED flow that flips the input_boolean based on the last lock event. For example, if it’s locked via Z-Wave then the input is “True”. If you then manually unlock it, that event will flip it to “False” even though the lock still reports “True”. Here’s a screenshot for reference:
And here’s the Node-RED flow that you can import:
[{"id":"43493c42.9ae3d4","type":"comment","z":"bc59819c.4843c","name":"Virtual Switch for Front Door","info":"","x":260,"y":460,"wires":[]},{"id":"a2443d88.8f0e8","type":"server-state-changed","z":"bc59819c.4843c","name":"Front Lock Physical","server":"744f1fa7.a5248","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.lock_front_door_alarm_access_control","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":110,"y":520,"wires":[["7fa5288f.93bea8"]]},{"id":"7fa5288f.93bea8","type":"switch","z":"bc59819c.4843c","name":"Status","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"\\b(Locked|Manual Lock Operation|Keypad Lock Operation)\\b","vt":"str","case":true},{"t":"regex","v":"\\b(Unlocked|Manual Unlock Operation|Keypad Unlock Operation)\\b","vt":"str","case":true}],"checkall":"false","repair":false,"outputs":2,"x":290,"y":520,"wires":[["ff125c26.dce92"],["10171d2e.f85b63"]]},{"id":"ff125c26.dce92","type":"api-call-service","z":"bc59819c.4843c","name":"Locked","server":"744f1fa7.a5248","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_on","entityId":"input_boolean.lock_front_door_switch","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":440,"y":520,"wires":[[]]},{"id":"10171d2e.f85b63","type":"api-call-service","z":"bc59819c.4843c","name":"Unlocked","server":"744f1fa7.a5248","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.lock_front_door_switch","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":440,"y":580,"wires":[[]]},{"id":"b8a3dc21.11046","type":"server-state-changed","z":"bc59819c.4843c","name":"Front Lock Zwave","server":"744f1fa7.a5248","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"lock.lock_front_door_zwave","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":110,"y":580,"wires":[["8d9efd09.a37db"]]},{"id":"8d9efd09.a37db","type":"function","z":"bc59819c.4843c","name":"Status","func":"var lockState = msg.data.new_state.attributes.value;\n\nif (lockState == \"true\") {\n msg.payload = \"Locked\";\n}\n\nelse if (lockState == \"false\") {\n msg.payload = \"Unlocked\";\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":580,"wires":[["7fa5288f.93bea8"]]},{"id":"744f1fa7.a5248","type":"server","z":"","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false}]
The next step is to create the lock template that leverages the input_boolean for the status, and the Z-Wave lock for control:
lock:
- platform: template
name: 'Lock Front Door'
value_template: "{{ is_state('input_boolean.lock_front_door_switch', 'on') }}"
lock:
service: lock.lock
data:
entity_id: lock.lock_front_door_zwave
unlock:
service: lock.unlock
data:
entity_id: lock.lock_front_door_zwave
Once again, restart Home Assistant for it to appear. You should end up with this assuming everything was configured correctly:
Hope this helps!