KeyMaster Z-Wave lock manager and scheduler

Lock-Manager is now named KeyMaster

NOTE: This thread has been renamed from Simplified Lock Manager.

Please be aware that this package supports both the native Zwave network interface included in Home Assistant and the OpenZWave Beta project, aka ozw. While we are supporting both implementations, if and when HA switches to ozw, we will drop the (current) zwave.

When asking for support, please indicate if you’re using zwave or ozw.

What this package does is fairly simple. It lets you define sensors for when a lock-code should be active. A lock-code is a “user slot” for a specific lock. When a lock-code sensor turns true/false the code should be entered/deleted from the lock. Then through the setup script, it will configure a lock with as many code slots as you define in the .ini file, in addition to generating the lovelace for that lock.

I pushed out a significant update to the first release of this project. It’s still very much a work in progress and this release should still be viewed as a beta.

So what’s different between this release and the prior? Besides bug fixes, it boils down to support for multiple locks and the setup procedure.

For a simple experience, please Install via HACS.

Setup procedure

1. Place the files from github into a directory called packages/lock-manager. From a command prompt, modify the script so that it is executable.

chmod +x

2. Edit FrontDoor.ini and replace the values in the file to be used to configure your lock. For example, specify the number of PIN slots you want for this lock. Make sure you have modified your lock’s entities so that you have appended _FrontDoor (or whatever you are naming your lock) after every entity for that lock. Also make sure you’ve specified the “base” name for the lock in the ini file.
3. Repeat step 2 for each additional lock you have. So you if you have another lock in the back, copy FrontDoor.ini to BackDoor.ini and modify those values accordingly.
4. Run ./ and this will take each ini file in the directory and create a subfolder for each lock. So if you have two ini files and one had a lock named FrontDoor and the other a lock named BackDoor you will end up with two directories named accordingly. Restart Home Assistant.
5. In each subdirectory created in step 4, there will be a lovelace file which contains a new view representing that lock. So for the example in step 4, you should have the following two files:

  • packages/lock-manager/FrontDoor/FrontDoor_lovelace
  • packages/lock-manager/BackDoor/BackDoor_lovelace

If you are using the GUI lovelace design, open the “raw source” and paste the contents of each file at the end of the raw source YAML. Save the code and exit the GUI editor and you will see two new views representing the two locks.

Feedback, as always is welcome.


This integration requires you to create an input boolean named input_boolean.allow_automation_execution. This “variable” is used extensively throughout the integration to prevent most code execution from happening unless this value is true. This is because we don’t want the code running when Home Assistant is starting up. So you will need to create some automations to control this input boolean.

Regardless if you are using ozw or the native zwave implementation, you need to make sure the network has started before allowing automations. These automations should handle this.

Add to your automations

# This automation ensures that input_boolean.allow_automation_execution
# is turned off when the system starts loading.  You can also use this automation
# to handle other startup functions.
- alias: homeassistant start-up
  initial_state: true
    platform: homeassistant
    event: start
    - service: input_boolean.turn_off
      entity_id: 'input_boolean.allow_automation_execution'
    - service: input_boolean.turn_off
      entity_id: input_boolean.system_ready
    - service: timer.cancel
        - timer.litterbox
        - timer.fireplace
    - service: google_assistant.request_sync
        agent_user_id: !secret GAagent_user_i
    - service: system_startup_cleanup

# When either z-wave network stops, disable the automation boolean	
- alias: open_zwave_network_down
  initial_state: true
    - platform: state
      entity_id: binary_sensor.ozw_network_status
      to: "off"
    - platform: event
      event_type: zwave.network_stop	  
    - service: homeassistant.turn_off
      entity_id: input_boolean.allow_automation_execution

# When either z-wave network starts up, call the cleanup code
- alias: zwave_ozw_network_up
  initial_state: true
    - platform: state
      entity_id: binary_sensor.ozw_network_status
      to: "on"
    - platform: event
      event_type: zwave.network_ready
    - platform: event
      event_type: zwave.network_complete	  
    - service: script.system_startup_cleanup

Add to your binary_sensors

  - platform: mqtt
    name: ozw_network_status
    state_topic: OpenZWave/1/status/
    value_template: >
      {{ "ON" if value_json.Status in ["driverAwakeNodesQueried", "driverAllNodesQueriedSomeDead", "driverAllNodesQueried"] else "OFF" }}
    json_attributes_topic: OpenZWave/1/status/
    device_class: "connectivity"

Add to your scripts.

# If you are not using HomeKit, you should remove the service call.
# If you are, this ensures it will only start after zwave/ozw Network has started
# Note the last call turns on input_boolean.allow_automation_execution
    - service: homekit.start
    - service: input_boolean.turn_on
      entity_id: input_boolean.system_ready
    - service: input_boolean.turn_on
      entity_id: 'input_boolean.allow_automation_execution'

Just installed this and having a few issues. Currently just running with one lock. After running everything looks good. I add the lovelace to the RAW editor. Everything shows up, however the Status shows as Disconnected. If I look at my home assistant logs I get these errors for each code/day combo.

Mon Jan 27 2020 09:15:28 GMT-0800 (Pacific Standard Time)
Could not render template wed_frontdoor_3: UndefinedError: 'str object' has no attribute 'strftime'

Not sure where to look to troubleshoot.

What does your ini file look like?

Here is FrontDoor.ini. The badges at the top all show values.

#See README for more information.

#number of PINS to setup in lovelace

#the name or location of the lock you are setting up (no spaces)

#the "lowest common denominator" of the factory lock name.  

#The name of the (optional) door sensor.

#the "lowest common denominator" of the factory door sensor name.  

#the Home Assistant EntityID of your (optional) garage door

Here is a link to my lock names:

Make sure you have the latest code pulled from the repo. The latest commit is 29b8d8d6c347f670345a652c2d4cb30fbe44d2a0 If that’s what you have, I’ll run it locally and see what I get

1 Like

Pulled this morning with git clone, and just verified with: git rev-parse HEAD

Did you modify your lock name to remove the base name?

I have


Which is what you should have gotten after adding _frontdoor. Meaning your original should look like:


I suggest excluding your lock, deleting anything that is leftover and including your lock again, which should give you the entity immediately above

And this in your ini is wrong:


That should have the “base name” something like


All my devices are renamed. I have over 150 zwave devices, so everything needs to be named clean. The latest version of HA allows for easy rename of all device base names. I will remove and readd to see if that fixes things, but my basename is lock_deadbolt. I have nothing that has the original basename. With tons of light switches/sensors/etc. they start showing up as basename(1) basename(2) etc.

In that case you might need to modify the txt files accordingly.

Look in the frontdoor/yaml to see if wed_frontdoor_3 exists anywhere.

@crzykidd paste this into your template editor and paste the results

        - sensor.time
        - input_datetime.mon_start_date_frontdoor_1
        - input_datetime.mon_end_date_frontdoor_1
      value_template: "{{ ((is_state('input_boolean.mon_frontdoor_1', 'on'))) and (strptime(states(''), '%Y-%m-%d').strftime('%A') == 'Monday') and ((states.input_datetime.mon_start_date_frontdoor_1.state  == states.input_datetime.mon_end_date_frontdoor_1.state) or ((states('sensor.time') >= states('input_datetime.mon_start_date_frontdoor_1')[0:5]) and (states('sensor.time') <= states('input_datetime.mon_end_date_frontdoor_1')[0:5]))) }}"
      Date: {{ states('') }}
Error rendering template: UndefinedError: 'str object' has no attribute 'strftime'

Also I completely removed the package, removed the left behind entities in HA, removed my doorlock and re added it. So now my naming is identical to your, and have the same issue.

Think I found the problem. Do a pull then run the script again. Then check the template. If there is no error you should be good. It’s totally weird how I found this error doing something else

Ok way farther now. No errors in the log file. However now when I add a username and pinn and click enable the status changes to connected but nothing happens. I don’t see any communication with the lock in my zwave logs. Not sure where to troubleshoot.

Test the lock.set_usercode function in dev services.

Works as expected. When I hit the enable button on the lock page, it doesn’t send anything out to the ZWave network.

Does the status show connected and change color to yellow?

Yes it does. I expected that as soon as I select enabled, and the status turned to yellow that I would see it send the set message out via Zwave. It is almost like a automation is broken somewhere…

hang on. I’ll test mine

1 Like