KeyMaster Z-Wave lock manager and scheduler

Funny you asked. I literally started messing with this a few hours ago.
So far it is self explanatory. I had not updated in a while so I’ve verifying other automations I had set up outside of keymaster, but… So far it’s working as expected. I did have to turn on and off a slot or two to get everything synced up the first time, but other than that it’s been smooth. I’ll pay special attention to the FE599 lock I have, it always seems to be the one that has a bit of trouble with notifications

EDIT: Just wanted to report that the FE599 lock is the same as before. The issue with notifications is that the alarm level does not change if the same code is used. So If I unlock with slot 1 code, then later unlock with slot 1 code the alarm type never changes, so it does not trigger

Here is what zwave.js shows for an unlock operation at the keypad

2021-06-16 18:42:45.825 INFO ZWAVE: Node 140: value updated: 113-0-alarmType 16 => 16
2021-06-16 18:42:45.827 INFO ZWAVE: Node 140: value updated: 113-0-alarmLevel 1 => 1
2021-06-16 18:42:45.852 INFO ZWAVE: Node 140: value updated: 32-0-currentValue 255 => 255

It’s been like this forever, with legacy zwave, OZW and zwave.js. The lock is pretty basic. I have a few automations that I’ve used to work around the issue. I think they need a little updating, but might give you some insight to how I worked around the issue. Maybe there is a better way to handle these

automation:
  - alias: "Garage Door Lock Remote Activity"
    initial_state: true
    # Any change in lock state, lock or unlock
    trigger:
      - platform: state
        entity_id: lock.garage_door
    # Ensure user code has not been entered
    condition:
      condition: state
      entity_id: sensor.garage_door_code_entered
      state: '0'
    # input_select is used for tracking
    action:
      - service: input_select.select_option
        data_template:
          entity_id: input_select.hass_status_for_garage_door_lock
          option: >
            {% if is_state("lock.garage_door", "locked") %}
              HA Lock
            {% else %}
              HA Unlock
            {% endif %}

  - alias: Notify on Unlock (Garage Door)
    initial_state: true
    trigger:
      - platform: state
        entity_id: sensor.garage_door_code_entered
        from: '0'
    condition:
      - condition: state
        entity_id: binary_sensor.keymaster_zwave_network_ready
        state: 'on'  
    action:
    - service: input_select.select_option
      data:
        entity_id: input_select.hass_status_for_garage_door_lock
        option: Unlocked with Code
## This  will just set a a friendly name of whoever unlocked the door to input_text.garage_door_code,  Use for other automations if you want.
    - service: input_text.set_value
      data_template:
        entity_id: input_text.garage_door_code
        value: >
          {% set number = states('sensor.garage_door_lock_alarm_level') %}
          {% set entity_id = 'input_text.frontdoor_name_' + number  %}
          {% set user = 'Master' if number == '0' else states(entity_id) %}
          {{ user }}
    - delay:
        seconds: 1
    - condition: template
      value_template: >-
        {% set alarm_level_object_id = 'garage_door_lock_alarm_level' %}
        {% set code_used = states['sensor'][alarm_level_object_id].state %}
        {% set notify_input_object_id = 'notify_garagedoor_' ~ code_used ~ '' %}
        {{ states['input_boolean'][notify_input_object_id].state == 'on' }}
    - service: notify.pushover
      data_template:
        title: "Garage Door Unlocked"
        message: >-
           by {{ states.input_text.garage_door_code.state }} at {{ as_timestamp (now()) | timestamp_custom('%I:%M %p') }} 

input_select:
  hass_status_for_garage_door_lock:
    name: Garage Door Lock HASS Status
    icon: mdi:lock
    options:
      - HA Lock
      - HA Unlock
      - Unlocked with Code
      - Other

sensor:
# These settings are for a Schlage FE599 which is a bit different.
      garage_door_code_entered:
        value_template: >-
          {% if ((as_timestamp(states.lock.garage_door.last_changed) - as_timestamp(states.sensor.garage_door_lock_alarm_level.last_changed)) < 1) %}
            {{ states.sensor.garage_door_lock_alarm_level.state }}
          {% else %}
            0
          {% endif %}

# These settings are for a Schlage FE599 which is a bit different.
      garage_door_report:
        friendly_name: 'Garage Door'
        value_template: >
            {% set number = states('sensor.garage_door_lock_alarm_level') %}
            {% set alarm_type_value = states('sensor.garage_door_lock_alarm_type') %}
            {% set entity_id = 'input_text.garagedoor_name_' + number  %}
            {% set user = 'Master' if number == '0' else states(entity_id) %}
            {% if is_state('input_select.hass_status_for_garage_door_lock', 'HA Unlock') %}
              3;RF Unlock;1
            {% elif is_state('input_select.hass_status_for_garage_door_lock', 'HA Lock') %}
              3;RF Lock;1
            {% elif is_state('sensor.garage_door_code_entered', '0') %}
              {% if is_state('lock.garage_door', 'locked') %}
                3;Auto Re-Locked;{{ number }}
              {% else %}
                {{alarm_type_value}};Keypad Unlock;{{ number }}
              {% endif %}
            {% elif is_state('sensor.garage_door_lock_alarm_type', '16') %}
                {{alarm_type_value}};Keypad Unlock;{{ number }}
            {% else %}
              {{ states.lock_garage_door_lock.attributes.lock_status }}
            {% endif %}

      garagedoor_code:
        friendly_name: 'Last Person to unlock with Keypad (Garage Door)'
        value_template: >
          {% set number = states('sensor.garage_door_lock_alarm_level') %}
          {% set entity_id = 'input_text.garagedoor_name_' + number  %}
          {% set user = 'Master' if number == '0' else states(entity_id) %}
          {{ user }}

This can be fixed, I believe, with the zwavejs alarm mappings, @blhoward2 would be the guy to ping about that.

I just had this issue where all code slots are unavailable. My first lock was working fine but I couldn’t get the second to work. What my issue ended up being is that Z-Wave JS did not have the user code configuration available on the second lock.

The fix was to re-interview the node. I actually had to do it twice before it started working correctly (the first time it didn’t seem to get all of the previous codes in the interview). Look in Zwave JS to make sure you can see the user code option and that it starts at code 1 and all of the codes you have previously stored in your lock are populated.

Also, child locks are now working great for me! Thanks dev team

1 Like

Interesting. I also had to reinterview and actually ended up just removing and readding my lock after moving to this version. I feel like I had to do that once in the past too. Not sure if it was a combination of flooding the lock with a lot of codes at once, and maybe restarting HA and Z-Wave a few times. But like you once I got it all back and healthy it all worked fine.

1 Like

For the record, the second lock that I had issues with hadn’t been set up correctly with keymaster and Zwave JS yet, I was waiting on the child lock functionality. So it could have just not been interviewed fully on one of my Zwave JS updates or even my transition to Zwave JS.

1 Like

A couple more things after using the child locks some more.

  1. If you have existing code slots in your parent lock the child lock doesn’t seem to automatically sync once its set up. You will need to reset the code slot then enter the info and the child lock should sync.

  2. I accidently changed one parameter (use date range) in the child lock rather than the parent lock. After that the child lock would only say ‘Connecting’. Eventually I reset the code slot and re-entered the info and it synced correctly and Connected on both locks. Is there a way to lock down the child lock unless you’ve clicked override parent lock? That might help prevent that problem.

Anyways thanks for the great lock manager, I’ve been using it for a few months now and love the functionality! You’ve made great progress in making it feel seamless and intuitive (and much easier to set up).

In case you didn’t get this worked out, or anyone else wanting to do this in Node Red, this is what worked for me:

I’ve been struggling with this for far longer than I care to admit, and I finally wrestled it into submission today…

My use case is wanting to know which code had been used so I know WHO unlocked the door. I’m using it for the kids so I can send a note to me and my wife (if we’re not home), mark them as home, announce who unlocked it on the echos, and change the state of the house.

  1. I used an all events node and look for the “keymaster_lock_state_changed” event type

  2. Feed that into a switch node looking at the property “payload.event.code_slot_name” and create a condition for each code slot. You could use code slot id instead if you watch a different property, but I was looking for a bit more flexibility going forward in case I move things around.
    -This same node would alternately be possible to select on different events if you just want unlocked/locked/etc, just need to watch a different property.

Where you go from there depends on your use case.

I hope that’s helpful to others looking to do this through Node Red. I’m barely out of rookie phase, but I’ll help if I can.

1 Like

That’s overkill. Just toggle the notification button for each kid’s PIN.

Agreed. I get notifications from each PIN straight out of the box.

I did have that setup and coming to our phones, but it was just a notification. I centralize all my automations in node red and wanted to leverage it to do alexa announcements/etc utilizing the rest of my logic flows. Is there a way I can drive off from something else in Node Red to simplify things?

I’ve not used Node Red, so I can only speculate that you can monitor the automations of the slots with Node Red and catch when a slot unlocks the door.

I went a completely different route. And to the others yes I made this complex but there really was no other choice. AND, it is very flexible for my needs. :slight_smile:

I thank @rlgrimes for working through some of this with me. We used some of his logic from his appdaemon but then also leveraged incredible code from here.

Node-Red code for announcements, alarm and pushover messages:

[{"id":"eaff848c.6faa18","type":"server-events","z":"56cbb45a.6e811c","name":"Keymaster Lock State Change","server":"f4c3f22d.c5133","version":1,"event_type":"keymaster_lock_state_changed","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"waitForRunning":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"},{"property":"event_type","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"}],"x":160,"y":100,"wires":[["783f7217.a09a0c"]]},{"id":"783f7217.a09a0c","type":"switch","z":"56cbb45a.6e811c","name":"","property":"payload.event.code_slot_name","propertyType":"msg","rules":[{"t":"eq","v":"Natalie","vt":"str"},{"t":"neq","v":"Natalie","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":260,"y":240,"wires":[["26024376.2fccfc"],["a9047395.fd204"]]},{"id":"26024376.2fccfc","type":"function","z":"56cbb45a.6e811c","name":"Custom Actions/Announcements","func":"var states = global.get('homeassistant.homeAssistant.states');\n\n//Define Variable\nconst user_code = msg.payload.event.code_slot;\nconst user_string = msg.payload.event.code_slot_name;\nconst entity = msg.payload.event.lockname;\nconst action_type = msg.payload.event.action_text;\nlet friendly_name;\nlet greeting;\nlet entity_name;\n\n\n//Message Return Variables\nlet ntf_msg = {};\nlet voice_msg = {};\nlet alarm_action = {};\nlet cleaning_msg = {};\n\n//Greetings\nlet cleaning_options = [\"Welcome to our home!  We have missed you %name%\", \"I am so glad you are here %name%!  These people have been making me look messy!\",\"Welcome %name%!  We are excited that you are here!\",\"Welcome to our home %name%.\"];\n\n// Lock Names\nif (entity == \"frontdoor\") { entity_name = \"Front Door\"; }\nelse if (entity == \"garagedoor\") {entity_name = \"Garage Door\";}\nelse { entity_name = entity; }\n\nfriendly_name = \"Miss Natalie\"\ngreeting = cleaning_options[Math.floor(Math.random() * cleaning_options.length)];\ngreeting = greeting.replace('%name%', friendly_name);\nalarm_action.payload = \"alarm_disarm\";\nntf_msg.topic = entity_name + \" Lock Notification\";\nntf_msg.payload = \"The \" + entity_name + \" was unlocked by \" + user_string + \".\";\nvoice_msg.topic = entity;\nvoice_msg.payload = greeting;\ncleaning_msg.payload = \"cleaning\";\n\nreturn [ntf_msg, voice_msg, alarm_action, cleaning_msg];\n","outputs":4,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":120,"wires":[["6a27d715.3af5b8"],["15697fed.36a0e"],["2ce09e2c.fa4a72"],["93a1c5ad.e0aef8","a1be577a.3952b8"]]},{"id":"a9047395.fd204","type":"function","z":"56cbb45a.6e811c","name":"Keymaster Actions","func":"var states = global.get('homeassistant.homeAssistant.states');\n\nvar trackedpersons = [\"Aaron\", \"Krissy\", \"Amaya\", \"Karen\"];\n//Define Variable\nconst user_code = msg.payload.event.code_slot;\nconst user_string = msg.payload.event.code_slot_name;\nconst entity = msg.payload.event.lockname;\nconst action_type = msg.payload.event.action_text;\nlet friendly_name;\nlet greeting;\nlet entity_name;\nvar people = [];\n\n//Message Return Variables\nlet ntf_msg = {};\nlet voice_msg = {};\nlet alarm_action = {};\nlet reset_home = {};\n\n//Greetings\nlet greeting_options = [\"Be our Guest! Be our Guest! Put my service to the test. Welcome home %name%\",\"Chereo %name%. Glad you are home!\",\"%name%. Not much to report besides snoring dogs.\",\"Nice to have you back. %name%\",\"%greeting%, %name%\",\"%greeting%. Your virtual butler is here to serve. Welcome home %name%\",\"Please to see you, %name%\",\"%greeting%. Anything I can do for you. %name%\",\"Cheers. %name%. Do you need to use the looo?\",\"%greeting% %name%. The dogs have been patiently waiting for your presence.\",\"Konnichiwa, %name%. Just practicing my Japanese this %greeting%.\",\"G'Day %name%. Glad you are home!\",\"Well, look at you %name%. Aren't you absolutely adorable?\",\"Welcome home %name%. I was wondering while you were out, how much wood, can a woodchuck chuck, if a woodchuck chucked some wood?\",\"Welcome home %name%. Oh the places you go, while I sit here and watch the dogs.\",\"%name% can I tell you a secret? We all missed you!\"];\n\n// Lock Names\nif (entity == \"frontdoor\") { entity_name = \"Front Door\"; }\nelse if (entity == \"garagedoor\") {entity_name = \"Garage Door\";}\nelse { entity_name = entity; }\n\n//Build who has arrived\nif (states['input_select.aaron'].state === \"Arrived\") { people.push(\"Aaron\"); }\nif (states['input_select.krissy'].state === \"Arrived\") { people.push(\"Krissy\"); }\n//if (states['input_select.aiden'].state === \"Arrived\") { people.push(\"Aiden\"); }\nif (states['input_select.amaya'].state === \"Arrived\") { people.push(\"Amaya\"); }\nif (states['input_select.evelyn'].state === \"Arrived\") { people.push(\"Evelyn\"); }\nif (states['input_select.karen'].state === \"Arrived\") { people.push(\"MaMaw\"); }\nif (trackedpersons.includes(user_string) === false) { people.push(user_string); }\n\nif(people.length > 0) {\n  friendly_name = people.join(\", \");\n  friendly_name = friendly_name.replace(/,(?=[^,]*$)/, ' and');\n\n  //Set time\n  var now  = new Date(),\n      hour = now.getHours();\n\n  var greeting_time   = \"Good \";\n      greeting_time  += (hour >= 4  && hour <= 11) ? \"morning\" : \"\",\n      greeting_time  += (hour >= 12 && hour <= 16) ? \"afternoon\" : \"\",\n      greeting_time  += (hour >= 17 && hour <= 20) ? \"evening\" : \"\",\n      greeting_time  += (hour >= 21 || hour <= 3) ?  \"night\" : \"\";\n\n\n  //Set Greeting\n  greeting = greeting_options[Math.floor(Math.random() * greeting_options.length)];\n  greeting = greeting.replace('%name%', friendly_name);\n  greeting = greeting.replace('%greeting%', greeting_time);\n  \n  //Lock Actions\n  if (action_type == \"Keypad unlock operation\") {\n      alarm_action.payload = \"alarm_disarm\";\n      ntf_msg.topic = entity_name + \" Lock Notification\";\n      ntf_msg.payload = \"The \" + entity_name + \" was unlocked by \" + user_string + \".\";\n      voice_msg.topic = entity;\n      voice_msg.payload = greeting;\n      if(user_string===\"Aiden\") { \n          reset_home.msg = user_string.toLowerCase();\n      }\n      return [ntf_msg, voice_msg, alarm_action, reset_home];\n  }\n}\n\n\n","outputs":4,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":280,"wires":[["911e6da6.3a586","6a27d715.3af5b8"],["53c360d8.5f023","15697fed.36a0e"],["1ed65bb8.f79904","2ce09e2c.fa4a72"],["5f885682.5b9758"]]},{"id":"6a27d715.3af5b8","type":"pushover","z":"56cbb45a.6e811c","name":"","device":"","title":"","priority":0,"sound":"","url":"","url_title":"","html":false,"x":820,"y":80,"wires":[]},{"id":"15697fed.36a0e","type":"switch","z":"56cbb45a.6e811c","name":"Which Door?","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"frontdoor","vt":"str"},{"t":"eq","v":"garagedoor","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":830,"y":180,"wires":[["40ef86de.8216c8"],["4e80e3b5.b86cdc"]]},{"id":"2ce09e2c.fa4a72","type":"switch","z":"56cbb45a.6e811c","name":"Set Alarm","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"alarm_disarm","vt":"str"},{"t":"eq","v":"alarm_arm","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":820,"y":280,"wires":[["fc01dfe1.6b527"],["526bbdc4.44b4e4"]]},{"id":"93a1c5ad.e0aef8","type":"switch","z":"56cbb45a.6e811c","name":"Cleaning","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"cleaning","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":820,"y":420,"wires":[["2b47e156.3447fe","f02df292.60039"]]},{"id":"a1be577a.3952b8","type":"debug","z":"56cbb45a.6e811c","name":"Cleaning Action","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":440,"y":560,"wires":[]},{"id":"911e6da6.3a586","type":"debug","z":"56cbb45a.6e811c","name":"Notify Message","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":440,"y":440,"wires":[]},{"id":"53c360d8.5f023","type":"debug","z":"56cbb45a.6e811c","name":"Voice Message","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":440,"y":480,"wires":[]},{"id":"1ed65bb8.f79904","type":"debug","z":"56cbb45a.6e811c","name":"Alarm Action","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":430,"y":520,"wires":[]},{"id":"5f885682.5b9758","type":"api-call-service","z":"56cbb45a.6e811c","name":"Home","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"input_select","service":"select_option","entityId":"","data":"{\"entity_id\":\"input_select.{{payload}}\",\"option\":\"Home\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":810,"y":560,"wires":[[]]},{"id":"40ef86de.8216c8","type":"time-range-switch","z":"56cbb45a.6e811c","name":"7:00am-9:00pm","lat":"-33.96041","lon":"151.02968","startTime":"07:00","endTime":"21:00","startOffset":0,"endOffset":0,"x":1040,"y":80,"wires":[["61e4ea28.1e5e74"],["23fa95bb.e10c9a"]]},{"id":"4e80e3b5.b86cdc","type":"time-range-switch","z":"56cbb45a.6e811c","name":"7:00am-9:00pm","lat":"-33.96041","lon":"151.02968","startTime":"07:00","endTime":"21:00","startOffset":0,"endOffset":0,"x":1040,"y":180,"wires":[["fb02a8d9.49d748"],["8b3a6a41.7a9b48"]]},{"id":"fc01dfe1.6b527","type":"api-call-service","z":"56cbb45a.6e811c","name":"Alexa Guard Disarm","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"alarm_control_panel","service":"alarm_disarm","entityId":"alarm_control_panel.alexa_guard","data":"","dataType":"jsonata","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1060,"y":280,"wires":[[]]},{"id":"526bbdc4.44b4e4","type":"api-call-service","z":"56cbb45a.6e811c","name":"Alexa Guard Arm Home","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"alarm_control_panel","service":"alarm_arm_home","entityId":"alarm_control_panel.alexa_guard","data":"","dataType":"jsonata","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1070,"y":340,"wires":[[]]},{"id":"2b47e156.3447fe","type":"trigger","z":"56cbb45a.6e811c","name":"8 hours","op1":"","op2":"{\"payload\":{\"data\":{\"option\":\"\"}}}","op1type":"nul","op2type":"json","duration":"8","extend":false,"overrideDelay":false,"units":"hr","reset":"home","bytopic":"topic","topic":"topic","outputs":1,"x":1000,"y":420,"wires":[["8acc8d9d.54609"]]},{"id":"f02df292.60039","type":"api-call-service","z":"56cbb45a.6e811c","name":"Reset Cleaning","server":"f4c3f22d.c5133","version":3,"debugenabled":true,"service_domain":"input_select","service":"select_option","entityId":"input_select.natalie","data":"{\"option\":\"Cleaning\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1020,"y":480,"wires":[[]]},{"id":"61e4ea28.1e5e74","type":"api-call-service","z":"56cbb45a.6e811c","name":"Increase Vol. to 70%","server":"bcca64cb.debed8","version":3,"debugenabled":false,"service_domain":"media_player","service":"volume_set","entityId":"media_player.dining_room","data":"{\"volume_level\":\"0.7\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1240,"y":40,"wires":[["6dc08ecb.5f3de"]]},{"id":"23fa95bb.e10c9a","type":"api-call-service","z":"56cbb45a.6e811c","name":"Whisper Dinning Room Alexa","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"notify","service":"alexa_media","entityId":"","data":"{\"data\":{\"type\":\"announce\",\"method\":\"all\"},\"message\":\"<amazon:effect name='whispered'>{{payload}}</voice></amazon:effect>\",\"target\":[\"media_player.dining_room\"]}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"data"}],"queue":"none","x":1320,"y":100,"wires":[[]]},{"id":"fb02a8d9.49d748","type":"api-call-service","z":"56cbb45a.6e811c","name":"Increase Vol. to 70%","server":"bcca64cb.debed8","version":3,"debugenabled":false,"service_domain":"media_player","service":"volume_set","entityId":"media_player.kitchen_echo_show","data":"{\"volume_level\":\"0.7\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1280,"y":160,"wires":[["99d1a254.13b4c"]]},{"id":"8b3a6a41.7a9b48","type":"api-call-service","z":"56cbb45a.6e811c","name":"Whisper Kitchen Show Alexa","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"notify","service":"alexa_media","entityId":"","data":"{\"data\":{\"type\":\"announce\",\"method\":\"all\"},\"message\":\"<amazon:effect name='whispered'>{{payload}}</voice></amazon:effect>\",\"target\":[\"media_player.kitchen_echo_show\"]}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"data"}],"queue":"none","x":1320,"y":220,"wires":[[]]},{"id":"8acc8d9d.54609","type":"api-call-service","z":"56cbb45a.6e811c","name":"Reset Away","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"input_select","service":"select_option","entityId":"input_select.natalie","data":"{\"option\":\"Away\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1170,"y":420,"wires":[[]]},{"id":"6dc08ecb.5f3de","type":"api-call-service","z":"56cbb45a.6e811c","name":"Dinning Room Alexa","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"notify","service":"alexa_media","entityId":"","data":"{\"data\":{\"type\":\"announce\",\"method\":\"all\",\"volume_level\":\"0.8\"},\"message\":\"<voice name='Brian'>{{payload}}</voice>\",\"target\":[\"media_player.dining_room\"]}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"data"}],"queue":"none","x":1480,"y":40,"wires":[[]]},{"id":"99d1a254.13b4c","type":"api-call-service","z":"56cbb45a.6e811c","name":"Kitchen Show Alexa","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"notify","service":"alexa_media","entityId":"","data":"{\"data\":{\"type\":\"announce\",\"method\":\"all\",\"volume_level\":\"0.8\"},\"message\":\"<voice name='Brian'>{{payload}}</voice>\",\"target\":[\"media_player.kitchen_echo_show\"]}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"data"}],"queue":"none","x":1520,"y":160,"wires":[[]]},{"id":"f4c3f22d.c5133","type":"server","name":"Home Assistant","version":1,"legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true},{"id":"bcca64cb.debed8","type":"server","name":"Home Assistant","version":1,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Presence detection Node:

[{"id":"cbdf3bf9.002f08","type":"trigger-state","z":"fa321c11.6a27e","name":"Person","server":"f4c3f22d.c5133","version":0,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"^person\\..*$","entityidfiltertype":"regex","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"current_state","comparatorType":"is_not","comparatorValueDatatype":"prevEntity","comparatorValue":"state","propertyValue":"new_state.state"}],"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","x":120,"y":2180,"wires":[["7ef3549c.0a3a3c"],[]]},{"id":"7ef3549c.0a3a3c","type":"change","z":"fa321c11.6a27e","name":"Change","rules":[{"t":"change","p":"topic","pt":"msg","from":"person.","fromt":"str","to":"","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"payload = \"home\" ? \"home\" : \"not_home\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":235,"y":2180,"wires":[["a291742f.d7f208"]],"l":false},{"id":"a291742f.d7f208","type":"rbe","z":"fa321c11.6a27e","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":285,"y":2180,"wires":[["e2cf5c7d.77564"]],"l":false},{"id":"e2cf5c7d.77564","type":"switch","z":"fa321c11.6a27e","name":"Home?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"home","vt":"str"},{"t":"eq","v":"not_home","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":380,"y":2180,"wires":[["9d73e1ba.be601","2f660aa2.85ab26"],["72c2b74a.d9c2a8","ed906ccf.b283e"]]},{"id":"9d73e1ba.be601","type":"api-current-state","z":"fa321c11.6a27e","name":"Status?","server":"f4c3f22d.c5133","version":2,"outputs":2,"halt_if":"Leaving","halt_if_type":"str","halt_if_compare":"is_not","entity_id":"input_select.{{topic}}","state_type":"str","blockInputOverrides":false,"outputProperties":[],"x":520,"y":2120,"wires":[["ef7f94e0.6a8248"],["ebc219d2.6fff48"]]},{"id":"2f660aa2.85ab26","type":"trigger","z":"fa321c11.6a27e","name":"5min","op1":"","op2":"{\"payload\":{\"data\":{\"option\":\"\"}}}","op1type":"nul","op2type":"json","duration":"5","extend":false,"overrideDelay":false,"units":"min","reset":"home","bytopic":"topic","topic":"topic","outputs":1,"x":890,"y":2220,"wires":[["9714d557.7341d8"]]},{"id":"72c2b74a.d9c2a8","type":"api-current-state","z":"fa321c11.6a27e","name":"Status?","server":"f4c3f22d.c5133","version":2,"outputs":2,"halt_if":"Leaving,Away","halt_if_type":"str","halt_if_compare":"does_not_include","entity_id":"input_select.{{topic}}","state_type":"str","blockInputOverrides":false,"outputProperties":[],"x":520,"y":2220,"wires":[["d753f9a8.0599e8"],[]]},{"id":"ed906ccf.b283e","type":"trigger","z":"fa321c11.6a27e","name":"5min","op1":"","op2":"{\"payload\":{\"data\":{\"option\":\"\"}}}","op1type":"nul","op2type":"json","duration":"5","extend":false,"overrideDelay":false,"units":"min","reset":"not_home","bytopic":"topic","topic":"topic","outputs":1,"x":890,"y":2160,"wires":[["ebc219d2.6fff48"]]},{"id":"ef7f94e0.6a8248","type":"api-call-service","z":"fa321c11.6a27e","name":"Just Arrived","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"input_select","service":"select_option","entityId":"","data":"{\"entity_id\":\"input_select.{{topic}}\",\"option\":\"Arrived\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":690,"y":2100,"wires":[["ed906ccf.b283e"]]},{"id":"ebc219d2.6fff48","type":"api-call-service","z":"fa321c11.6a27e","name":"Home","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"input_select","service":"select_option","entityId":"","data":"{\"entity_id\":\"input_select.{{topic}}\",\"option\":\"Home\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1130,"y":2120,"wires":[[]]},{"id":"d753f9a8.0599e8","type":"api-call-service","z":"fa321c11.6a27e","name":"Just Left","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"input_select","service":"select_option","entityId":"","data":"{\"entity_id\":\"input_select.{{topic}}\",\"option\":\"Leaving\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":680,"y":2240,"wires":[["2f660aa2.85ab26"]]},{"id":"9714d557.7341d8","type":"api-call-service","z":"fa321c11.6a27e","name":"Away","server":"f4c3f22d.c5133","version":3,"debugenabled":false,"service_domain":"input_select","service":"select_option","entityId":"","data":"{\"entity_id\":\"input_select.{{topic}}\",\"option\":\"Away\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1130,"y":2200,"wires":[[]]},{"id":"90bde2d9.09419","type":"comment","z":"fa321c11.6a27e","name":"Presence Tracking","info":"","x":160,"y":2100,"wires":[]},{"id":"f4c3f22d.c5133","type":"server","name":"Home Assistant","version":1,"legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Input Select Fields you add (edit to your needs):

aaron:
  options:
    - Home
    - Arrived
    - Leaving
    - Away
krissy:
  options:
    - Home
    - Arrived
    - Leaving
    - Away
aiden:
  options:
    - Home
    - Arrived
    - Leaving
    - Away
amaya:
  options:
    - Home
    - Arrived
    - Leaving
    - Away
evelyn:
  options:
    - Home
    - Arrived
    - Leaving
    - Away
karen:
  options:
    - Home
    - Arrived
    - Leaving
    - Away
natalie:
   options:
     - Cleaning
     - Away

Works flawlessly and provides incredible flexibility and creativity to your home automation announcements.

1 Like

I’m new to basically all the coding the HA uses, but I’m a fast learner, good at troubleshooting, and I have two Yale Assure smart locks complete with Z-Wave smart modules to play with :slight_smile:

I just need some friendly guidance to let me know where to get started bc I’m a complete noob to open-source collaboration! (but I already have Visual Studio Code and a GitHub account that I’m just itching to use)

Start with the Wiki. Install a zwave integration, preferably Z-Wave JS. Then you can install keymaster and add an integration for each lock.

1 Like

Sorry @FutureTense, I should have mentioned. I’ve been using your integration since May. Originally I had my Z-Wave network setup with Zwave JS, but I have since moved to the Zwavejs2MQTT add-on because I needed the advanced control panel to modify the wake interval to save the tiny battery on my door sensor. Since it is not the “official” Home Assistant integration, will that be a problem?

Also, the way I have been using your integration is I went through the main lock configuration process twice, so I have separate views for my front and back door. It has been a pain to keep them synchronized, though, especially when I have been using that sweet date & time configuration that is specific to each user code. I nearly pulled my hair out when I saw the Path to child locks field in the setup UI, but couldn’t find anything about it the documentation on GitHub. Has that been updated with instructions on how to get child locks setup?

Many thanks on your work thus far by the way!!!

No

This field no longer exists, if you are seeing this, you need to update the integration.

1 Like

I upgraded to ZWaveJS2MQTT yesterday, and started messing with the child locks today I have my two locks mostly in sync (I had to basically wipe them), great job!

I’m now messing with the time limited codes, but the code never seems to be removed from the lock… (I’m mucking around in the automations/etc to see if I can figure out why)…

It seems to be just a delay in ZWave_JS - I can see keymaster removing the code at the appointed time, but it takes about a minute before I see the ZwaveJS logs remove/reset the codes. My locks are the only thing that has become slower with ZWaveJS vs OZW 1.4…

Yesterday I deleted my second lock’s lovelace view (which was my front door), edited the integration for it selecting my back door lock as the parent lock, then copy-pasted the config file into the raw editor for lovelace. Everything appears to be working swell so far! I haven’t tried adding or editing any of the existing codes yet, but the “override” switch now appears on all the code slots for my front door lock. I will update you with any new information once I need to change a code or access date/time setting.

Thanks again @FutureTense and @firstof9 for implementing this badly needed feature!

2 Likes

I currently have an issue with my 2nd user code. No matter what I do it just sits on “adding” for Pin Status. I’ve changed the config to only use 1 pin, then back to two, and also tried rebooting HA between the change. I verified that Allow Automations is on. At one point I even manually cleared the Pins from the lock to try and reset it. Any suggestions?