KeyMaster Z-Wave lock manager and scheduler

If you have battery powered nodes they may not have checked in yet. You can try waking them up or just let them check in on their own (note this excludes locks they’re a special battery node).

1 Like

I have a bunch of these warnings gunking up my log:

sensor_cleanup_keypad_10: Already running
[time] - Automation (WARNING)

I have one for each 1-10. Is that supposed to happen?

Yup that’s the automation firing off.

Thanks! How can I suppress those? I tried this and it didn’t work:

logger:
  default: info
  logs:
    homeassistant.integrations.lock_manager: error

Got it, I just checked the details on the log and it included homeassistant.components.automation so I used that instead.

this worked a treat thank you! I was so scared I was going to have to reprogram all my devices! I think I got everything in open zwave and working all stuff renamed in automations and them all working dashboards etc Im kinda tired though now so tomorrow Ill read the open zwave parts of the instructions and see if we can get the lock manager going. as for devices that weren’t showing up its one secure included door contact and a couple secure included smoke detectors that maybe just haven’t checked on yet… Weird just the secure stuff didn’t transfer except the lock which transferred fine…

They’re there but they’re battery devices so you have to either wake them up per the manual’s instructions (yes RTFM) or wait for them to wake up on their own.

Okay came back to it after eating dinner. With being switched over open zwave I went and reinstalled lock code manager in hacs, rebooted, enabled disabled entities in my lock, installed the integration, added the lovelace card, did the easy additional steps for ozw, and rebooted. I’m happy to report the lock manager is up and running and functioning perfectly now! Thanks for all your help I most definitely owe you a beer @firstof9

1 Like

I just have a bunch of custom arduino type devices that all communicate with my old mosquitto server I had long before I got into home assistant.

You should look into the ESPHome project. If you are already running containers it’s fairly easy to get up and running. You can convert your arduino code to work with ESPHome without too much trouble. Just follow the examples for the use case that matches your functionality. And as a huge win, you can take advantage of OTA updates. No more pulling USB cables and messing with the annoying arduino editor. Once you get one OTA update running, you can hack your firmware without getting off your ass.

Yeah I have esp home on a couple devices it’s pretty awesome way to get a straight forward sensor into home assistant but I have a bunch of projects for instance one example is I’ve made to control my pool. Fill Level detection, temperature, ph, orp, acid injection, chlorine injection, pump speed control, return valve actuators, and water valves. A little bit much customization wise to program with esp home I’d think so I just wrote the code haha plus it was before esp home existed that I made it and it works. I just added Mqtt to it to make it talk to home assistant too. That’s just one example of custom inventions I’ve got around the house i made lol that said a lot of my devices are particle photon based so I can OTA firmware those from anywhere with a browser and internet connection. I also enabled ota on a lot of my node mcu or wemos d1 mini devices. It’s not bad to upgrade the firmware ota using the arduino ide either. I’m just glad I didn’t have to change the firmware on all those devices even if it was ota lol much easier to set up that Mqtt forwarding in the config of my existing mosquitto config haha.

For BE469 w/ OZW

I am not sure what exactly did it, but I removed the integration, deleted all of the helpers, and updated openzwave to the latest. When I re-added the integration, everything seems to now be working as it should. The log is showing that it is “Utilizing BE469 work around code.” Thanks for all the work on this.

2 Likes

I think the instructions might need to be updated. When I added the mqtt binary sensor I received an error because I was missing the off_delay parameter even though the MQTT documentation says that is optional. So I added it and set it to zero to make it effectively do nothing as far as I can tell.

I’m sorry for such a long delay. I’ve tested your latest package with both my be469 and my fe599, and want to report that they both work great!! I found one issue that I could not figure out. Nothing directly to do with your packages, but my allow automation would never turn on. I kept looking at it and realized this was happening.
Restart HA - It would be off as expected
Home assistant start I’d see the input boolean turn on and immediately turn off. I watched it through several reboots, always on and then immediatly off. Maybe others dont have this problem, not sure. Was weird because system ready would not have this behavior.

Anyway I added this condition to the recommended automation, and I’m working now!!

- alias: HA Automations Homeassistant start-up
  initial_state: true
  trigger:
    platform: homeassistant
    event: start
  condition:
    - condition: not
      conditions:
        - condition: state
          entity_id: binary_sensor.ozw_network_status
          state: "on"
  action:
    - service: input_boolean.turn_off
      entity_id: input_boolean.system_ready
    - service: input_boolean.turn_off
      entity_id: 'input_boolean.allow_automation_execution'

do you see any issues with this added condition??

I believe that has been my issue quite often during testing in the past. Anyway as stated in the begining. For me with the old legacy b469 and fe599 (not zwave plus), Everything seems to be working. Will test more later to verify the scheduleing,and lock counts but I’m sure they’ll work fine.

If I had one “feature request” it would be to sync codes across multiple locks. That was one of the things keeping me on my package vs yours, but this has surpassed mine with the latest features, I can hack other ways to “sync across locks” if I want.

Thanks for your hard work!!! this is great!

You’re in luck, @FutureTense is working on that already :wink:

So the original code:

- alias: open_zwave_network_up
  initial_state: true
  trigger:
    - platform: homeassistant
      event: start
    - platform: state
      entity_id: binary_sensor.ozw_network_status
      to: "on"
  condition:
    - condition: state
      entity_id: binary_sensor.ozw_network_status
      state: "on"
  action:
    - service: homeassistant.turn_on
      entity_id: input_boolean.allow_automation_execution

Triggers on HA startup OR the binary_sensor switching to “on”, as long as the binary_sensor has the state of “on”. This is supposed to guard against the network being down at HA start up for some reason and I’ve personally never experienced issues with it.

This of course means you have to have included the binary_sensor template as well:

binary_sensor:
  - 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"

My issue seemed to be the turning off of input booleans with this

- alias: homeassistant start-up
  initial_state: true
  trigger:
    platform: homeassistant
    event: start
  action:
    - service: input_boolean.turn_off
      entity_id: input_boolean.system_ready
    - service: input_boolean.turn_off
      entity_id: 'input_boolean.allow_automation_execution'

also triggering was

- alias: open_zwave_network_up
  initial_state: true
  trigger:
    - platform: homeassistant
      event: start
    - platform: state
      entity_id: binary_sensor.ozw_network_status
      to: "on"
  condition:
    - condition: state
      entity_id: binary_sensor.ozw_network_status
      state: "on"

I think they were both running. Do I still need both? Adding the condition solved the issue, and sync across locks is AWESOME!!
Thanks

Hi All. First time post here and relatively new user moving over from Smartthings and Webcore. I followed the instructions in the README on git and got through most of it. A missing piece I picked up from the previous posts was a need to add to my configuration.yaml:

   homeassistant:
       packages: !include_dir_merge_named packages

Unfortunately a config check with packages feature turned on throws a bunch of errors:

config $ ha core check
Processing... Done.

Error: Testing configuration at /config
Failed config
  homeassistant: 
    - expected a dictionary for dictionary value @ data['packages']['automation']
    - packages: [source /config/configuration.yaml:1]
        automation: [source /config/packages/lock-manager/frontdoor/frontdoor_lock_manager_common.yaml:129]
          - action: [source /config/packages/lock-manager/frontdoor/frontdoor_lock_manager_common.yaml:140]
              - service: script.frontdoor_refreshnodeinfo

Any thoughts or pointers? I’m having trouble as a newbie deciphering the error message.

Thanks!

No just the ozwave network up automation will do.

1 Like

Post your configuration.yaml and redact any personal info like usernames and passwords.

Here is my configuration.yaml:

#homeassistant:
#  packages: !include_dir_merge_named packages

logger:
  default: info
  logs:
    homeassistant.components: info

frontend:
  themes: !include_dir_merge_named themes

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Text to speech
tts:
  - platform: google_translate

input_boolean:
  allow_automation_execution:
    name: 'Allow Automation'
    initial: off
  system_ready:
    name: 'System Ready'
    initial: off

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml


binary_sensor:
  - platform: template
    sensors:
      allow_automation:
        friendly_name: "Allow Automation"
        value_template: "{{ is_state('input_boolean.allow_automation_execution', 'on') }}"
  - platform: template
    sensors:
      system_ready:
        friendly_name: "System ready"
        value_template: "{{ is_state('input_boolean.system_ready', 'on') }}"
        device_class: moving
  - platform: template
    sensors:
      occupancy_mf_ki_fr:
        friendly_name: 'Kitchen & Family Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_ki_ls_burglar",'0') or is_state("sensor.mf_ki_ls_burglar",'254') %}
            {% if is_state("sensor.mf_ki_ls_island_burglar",'0') or is_state("sensor.mf_ki_ls_island_burglar",'254') %}
              {% if is_state("sensor.mf_ki_ls_table_burglar",'0') or is_state("sensor.mf_ki_ls_table_burglar",'254') %}
                {% if is_state("sensor.mf_fr_ls_burglar",'0') or is_state("sensor.mf_fr_ls_burglar",'254') %}
                  {% if is_state("sensor.mf_fr_ls_outlet_burglar",'0') or is_state("sensor.mf_fr_ls_outlet_burglar",'254') %}
                    False
                  {% else %}
                    True
                  {% endif %}
                {% else %}
                  True
                {% endif %}
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_mf_lr_dr:
        friendly_name: 'Living & Dining Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_dr_ls_dummy_burglar",'0') or is_state("sensor.mf_dr_ls_dummy_burglar",'254') %}
            {% if is_state("sensor.mf_dr_ls_burglar",'0') or is_state("sensor.mf_dr_ls_burglar",'254') %}
              {% if is_state("sensor.mf_lr_ls_burglar",'0') or is_state("sensor.mf_lr_ls_burglar",'254') %}
                False
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_ba_sa:
        friendly_name: 'Basement Storage Area Occupancy'
        value_template: >-
          {% if is_state("sensor.ba_sa_ls_burglar",'0') or is_state("sensor.ba_sa_ls_burglar",'254') %}
            {% if is_state("sensor.ba_sa_ls_furnace_burglar",'0') or is_state("sensor.ba_sa_ls_furnace_burglar",'254') %}
                False
              {% else %}
                True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_2f_mb:
        friendly_name: 'Master Bedroom Occupancy'
        value_template: >-
          {% if is_state("sensor.2f_mb_ls_desk_burglar",'0') or is_state("sensor.2f_mb_ls_desk_burglar",'254') %}
            {% if is_state("sensor.2f_mb_ms_desk_burglar",'0') %}
                False
              {% else %}
                True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_ba_st:
        friendly_name: 'Basement Stairs Occupancy'
        value_template: >-
          {% if is_state("sensor.ba_st_ls_burglar",'0') or is_state("sensor.ba_st_ls_burglar",'254') %}
            {% if is_state("sensor.ba_oa_ls_burglar",'0') or is_state("sensor.ba_oa_ls_burglar",'254') %}
                False
              {% else %}
                True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_ex_fd:
        friendly_name: 'Front Door Occupancy'
        value_template: >-
          {% if is_state("sensor.ex_fd_ms_burglar",'0') %}
            False
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_mf_mr_hw:
        friendly_name: 'Mud Room and Hallway Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_ga_ls_burglar",'0') or is_state("sensor.mf_ga_ls_burglar",'254') %}
            {% if is_state("sensor.mf_mr_ls_buglar",'0') or is_state("sensor.mf_mr_ls_burglar",'254') %}
              {% if is_state("sensor.mf_mr_dummy_ls_buglar",'0') or is_state("sensor.mf_mr_dummy_ls_burglar",'254') %}
                False
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_mf_mr:
        friendly_name: 'Mud Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_ga_ls_burglar",'0') or is_state("sensor.mf_ga_ls_burglar",'254') %}
            {% if is_state("sensor.mf_mr_dummy_ls_buglar",'0') or is_state("sensor.mf_mr_dummy_ls_burglar",'254') %}
              False
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_mf_ef:
        friendly_name: 'Entry Way Occupancy'
        value_template: >-
          {% if is_state("sensor.ex_fd_ls_burglar",'0') or is_state("sensor.ex_fd_ls_burglar",'254') %}
            {% if is_state("sensor.ex_dw_ls_buglar",'0') or is_state("sensor.ex_dw_ls_burglar",'254') %}
              {% if is_state("sensor.2f_hw_ls_buglar",'0') or is_state("sensor.2f_hw_ls_burglar",'254') %}
                {% if is_state("sensor.mf_ew_ls_buglar",'0') or is_state("sensor.mf_ew_ls_burglar",'254') %}
                  False
                {% else %}
                  True
                {% endif %}
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_ba_oa:
        friendly_name: 'Basement Open Area Occupancy'
        value_template: >-
          {% if is_state("sensor.ba_oa_ls_burglar",'0') or is_state("sensor.ba_oa_ls_burglar",'254') %}
            False
          {% else %}
            True
          {% endif %}
  - platform: template
    sensors:
      occupancy_mf_rr:
        friendly_name: 'Reading Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_rr_ls_burglar",'0') or is_state("sensor.mf_rr_ls_burglar",'254') %}
            False
          {% else %}
            True
          {% endif %}

# Webserver
http:
  server_port: 80

And here is scripts.yaml:

# feel free to add post startup calls here
system_startup_cleanup:
  sequence:
    - condition: state
      entity_id: 'input_boolean.system_ready'
      state: 'off'
    - service: input_boolean.turn_on
      entity_id: 'input_boolean.allow_automation_execution'
    - service: input_boolean.turn_on
      entity_id: input_boolean.system_ready
#    - service: homekit.start

Your config’s a mess…

homeassistant:
  packages: !include_dir_named packages

# Webserver
http:
  server_port: 80

logger:
  default: info
  logs:
    homeassistant.components: info

frontend:
  themes: !include_dir_merge_named themes

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Text to speech
tts:
  - platform: google_translate

input_boolean:
  allow_automation_execution:
    name: 'Allow Automation'
    initial: off
  system_ready:
    name: 'System Ready'
    initial: off

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml


binary_sensor:
  - platform: template
    sensors:
      allow_automation:
        friendly_name: "Allow Automation"
        value_template: "{{ is_state('input_boolean.allow_automation_execution', 'on') }}"

      system_ready:
        friendly_name: "System ready"
        value_template: "{{ is_state('input_boolean.system_ready', 'on') }}"
        device_class: moving

      occupancy_mf_ki_fr:
        friendly_name: 'Kitchen & Family Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_ki_ls_burglar",'0') or is_state("sensor.mf_ki_ls_burglar",'254') %}
            {% if is_state("sensor.mf_ki_ls_island_burglar",'0') or is_state("sensor.mf_ki_ls_island_burglar",'254') %}
              {% if is_state("sensor.mf_ki_ls_table_burglar",'0') or is_state("sensor.mf_ki_ls_table_burglar",'254') %}
                {% if is_state("sensor.mf_fr_ls_burglar",'0') or is_state("sensor.mf_fr_ls_burglar",'254') %}
                  {% if is_state("sensor.mf_fr_ls_outlet_burglar",'0') or is_state("sensor.mf_fr_ls_outlet_burglar",'254') %}
                    False
                  {% else %}
                    True
                  {% endif %}
                {% else %}
                  True
                {% endif %}
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_mf_lr_dr:
        friendly_name: 'Living & Dining Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_dr_ls_dummy_burglar",'0') or is_state("sensor.mf_dr_ls_dummy_burglar",'254') %}
            {% if is_state("sensor.mf_dr_ls_burglar",'0') or is_state("sensor.mf_dr_ls_burglar",'254') %}
              {% if is_state("sensor.mf_lr_ls_burglar",'0') or is_state("sensor.mf_lr_ls_burglar",'254') %}
                False
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_ba_sa:
        friendly_name: 'Basement Storage Area Occupancy'
        value_template: >-
          {% if is_state("sensor.ba_sa_ls_burglar",'0') or is_state("sensor.ba_sa_ls_burglar",'254') %}
            {% if is_state("sensor.ba_sa_ls_furnace_burglar",'0') or is_state("sensor.ba_sa_ls_furnace_burglar",'254') %}
                False
              {% else %}
                True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_2f_mb:
        friendly_name: 'Master Bedroom Occupancy'
        value_template: >-
          {% if is_state("sensor.2f_mb_ls_desk_burglar",'0') or is_state("sensor.2f_mb_ls_desk_burglar",'254') %}
            {% if is_state("sensor.2f_mb_ms_desk_burglar",'0') %}
                False
              {% else %}
                True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_ba_st:
        friendly_name: 'Basement Stairs Occupancy'
        value_template: >-
          {% if is_state("sensor.ba_st_ls_burglar",'0') or is_state("sensor.ba_st_ls_burglar",'254') %}
            {% if is_state("sensor.ba_oa_ls_burglar",'0') or is_state("sensor.ba_oa_ls_burglar",'254') %}
                False
              {% else %}
                True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_ex_fd:
        friendly_name: 'Front Door Occupancy'
        value_template: >-
          {% if is_state("sensor.ex_fd_ms_burglar",'0') %}
            False
          {% else %}
            True
          {% endif %}

      occupancy_mf_mr_hw:
        friendly_name: 'Mud Room and Hallway Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_ga_ls_burglar",'0') or is_state("sensor.mf_ga_ls_burglar",'254') %}
            {% if is_state("sensor.mf_mr_ls_buglar",'0') or is_state("sensor.mf_mr_ls_burglar",'254') %}
              {% if is_state("sensor.mf_mr_dummy_ls_buglar",'0') or is_state("sensor.mf_mr_dummy_ls_burglar",'254') %}
                False
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_mf_mr:
        friendly_name: 'Mud Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_ga_ls_burglar",'0') or is_state("sensor.mf_ga_ls_burglar",'254') %}
            {% if is_state("sensor.mf_mr_dummy_ls_buglar",'0') or is_state("sensor.mf_mr_dummy_ls_burglar",'254') %}
              False
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_mf_ef:
        friendly_name: 'Entry Way Occupancy'
        value_template: >-
          {% if is_state("sensor.ex_fd_ls_burglar",'0') or is_state("sensor.ex_fd_ls_burglar",'254') %}
            {% if is_state("sensor.ex_dw_ls_buglar",'0') or is_state("sensor.ex_dw_ls_burglar",'254') %}
              {% if is_state("sensor.2f_hw_ls_buglar",'0') or is_state("sensor.2f_hw_ls_burglar",'254') %}
                {% if is_state("sensor.mf_ew_ls_buglar",'0') or is_state("sensor.mf_ew_ls_burglar",'254') %}
                  False
                {% else %}
                  True
                {% endif %}
              {% else %}
                True
              {% endif %}
            {% else %}
              True
            {% endif %}
          {% else %}
            True
          {% endif %}

      occupancy_ba_oa:
        friendly_name: 'Basement Open Area Occupancy'
        value_template: >-
          {% if is_state("sensor.ba_oa_ls_burglar",'0') or is_state("sensor.ba_oa_ls_burglar",'254') %}
            False
          {% else %}
            True
          {% endif %}

      occupancy_mf_rr:
        friendly_name: 'Reading Room Occupancy'
        value_template: >-
          {% if is_state("sensor.mf_rr_ls_burglar",'0') or is_state("sensor.mf_rr_ls_burglar",'254') %}
            False
          {% else %}
            True
          {% endif %}

also you don’t need the script stuff.

Yeah. Still learning the lay of the land and hacking up config as I go. Thanks for taking a look and cleaning up! I gave your mods a try and I’m still getting the same error.

config $ ha core check
Processing... Done.

Error: Testing configuration at /config
Failed config
  homeassistant: 
    - expected a dictionary for dictionary value @ data['packages']['automation']
    - packages: [source /config/configuration.yaml:1]
        automation: [source /config/packages/lock-manager/frontdoor/frontdoor_lock_manager_common.yaml:129]
          - action: [source /config/packages/lock-manager/frontdoor/frontdoor_lock_manager_common.yaml:140]
              - service: script.frontdoor_refreshnodeinfo
            alias: frontdoor_refresh_lock_node_finished
            condition: [source /config/packages/lock-manager/frontdoor/frontdoor_lock_manager_common.yaml:136]
              - condition: state
...

Here is the frontdoor_lock_manager_common.yaml generated by Lock-Manager:

## WARNING ##
# This file is auotmaticly generated, any changes
# will be overwritten.

##################################################
################  COMMON ENTITIES  ###############
##################################################

############  timer:  #####################  
timer:

  frontdoor_refresh_lock_node:
    duration: '00:15:00'

###############  input_text:  #################
input_text:
  frontdoor_status_report:
    name: frontdoor Status report

###############  input_number:  #################
input_number:
  frontdoor_lock_command:
    name: frontdoor Lock command
    min: 0
    max: 999

  frontdoor_lock_user:
    name: frontdoor Lock user
    min: 0
    max: 999

###############  input_boolean:  #################
input_boolean:
  frontdoor_lock_notifications:
    name: frontdoor Lock Notifications
  frontdoor_dooraccess_notifications:
    name: frontdoor Door Notifications
  frontdoor_garageacess_notifications:
    name: frontdoor Garage Notifications
  frontdoor_reset_lock:
    name: frontdoor reset lock

###################  sensor:  ####################
sensor:
  - platform: time_date
    display_options:
      - "time"
      - "date"
      - "date_time"
      - "date_time_iso"
      - "time_date"
      - "time_utc"
      - "beat"

  - platform: template
    sensors:
      frontdoor_ac_last_changed:
        friendly_name: frontdoor AC Last Changed From Present
        unit_of_measurement: "seconds"
        value_template: >-
          {% set CONTROL = 'input_number.frontdoor_lock_command' %}
          {% set CONTROLlc = states.input_number[CONTROL.split('.')[-1]].last_changed %}
          {{ (as_timestamp(now()) - as_timestamp(CONTROLlc)) | float }}

      frontdoor_uc_last_changed:
        friendly_name: frontdoor UC Last Changed From Present
        unit_of_measurement: "seconds"
        value_template: >-
          {% set CONTROL = 'input_number.frontdoor_lock_user' %}
          {% set CONTROLlc = states.input_number[CONTROL.split('.')[-1]].last_changed %}
          {{ (as_timestamp(now()) - as_timestamp(CONTROLlc)) | float }}

###################  script    :  ####################
script:
  frontdoor_reset_lock:
    sequence:
      - service: script.frontdoor_manual_notify
        data_template:
          title: "reset"
          message: "frontdoor"

  frontdoor_conditional_notify:
    sequence:
      - condition: template
        value_template: >-
          {% set inputbool = boolean %}
          {% if states(inputbool) == 'on'%}
            true
          {% else %}
            false
          {% endif %}
      - service: script.frontdoor_manual_notify
        data_template:
          title: "{{title}}"
          message: "{{message}}"

  frontdoor_refreshnodeinfo:
    description:  'Send MQTT RefreshNodeInfo command'
    sequence:
      - service: system_log.write
        data_template:
          message: "frontdoor_TEMPLATENUM started noderefreshinfo: {{ now() }}"
          level: debug  
      - service: mqtt.publish
        data:
          topic: 'OpenZWave/1/command/refreshnodeinfo/'
          payload: >-
            {% set node_id = state_attr('lock.mf_ew_dl_locked_frontdoor','node_id') %}
            { "node": {{ node_id }} }
          retain: true
          
  frontdoor_refresh_codes:
    description:  'Refreshes lock user codes'
    sequence:
      - service: system_log.write
        data_template:
          message: "refresh user codes: {{ now() }}"
          level: debug
      # - service: mqtt.publish
      #   data:
      #     topic: 'OpenZWave/1/command/refreshnodeinfo/'
      #     payload: >-
      #       {% set node_id = state_attr('lock.mf_ew_dl_locked_frontdoor','node_id') %}
      #       { "node": {{ node_id }} }
      #     retain: true

###################  automation:  ####################
automation:
          
  - alias: frontdoor_refresh_lock_node_finished
    trigger:
      platform: event
      event_type: timer.finished
      event_data:
        entity_id: timer.frontdoor_refresh_lock_node
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
    action:
      - service: script.frontdoor_refreshnodeinfo

  - alias: frontdoor Lock Command
    trigger:
      platform: state
      entity_id: sensor.mf_ew_dl_access_control_frontdoor
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.frontdoor_lock_command
          value: >-
            {{ states('sensor.mf_ew_dl_access_control_frontdoor') | int}}

  - alias: frontdoor User Command
    trigger:
      platform: state
      entity_id: sensor.mf_ew_dl_alarm_level_frontdoor
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.frontdoor_lock_user
          value: >-
            {{ states.sensor.mf_ew_dl_alarm_level_frontdoor.state | int}}

  - alias: frontdoor RF Locked State Changed
    trigger:
      platform: state
      entity_id: lock.mf_ew_dl_locked_frontdoor
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
      - condition: template
        value_template: >-
          {% set lockuser =  states.sensor.mf_ew_dl_alarm_level_frontdoor.state | int %}
          {% set lockcmd = states.sensor.mf_ew_dl_access_control_frontdoor.state | int %}
          {% set timediff = (as_timestamp(now()) - as_timestamp(states.sensor.mf_ew_dl_access_control_frontdoor.last_changed)) | float %}
          {{ lockuser | int == 0 and timediff > 2 }}
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.frontdoor_lock_command
          value: >-
            {% set lockcmd = states.sensor.mf_ew_dl_access_control_frontdoor.state | int %}
            {% set lockstate = states.lock.mf_ew_dl_locked_frontdoor.state %}
            {% if (lockstate == 'locked') %}
               66
            {% elif (lockstate == 'unlocked') %}
               67
            {% else %}
               {{ lockcmd | int}}
            {% endif %}


  # {% set doordiff = as_timestamp(now()) - as_timestamp(states.lock.be666zp_connect_smart_deadbolt_locked.last_changed) %}
  # {% set contdiff = as_timestamp(now()) - as_timestamp(states.sensor.be666zp_connect_smart_deadbolt_access_control.last_changed) %}
  # {% set atv = 24 if (doordiff) < 15 and (contdiff) > 15 and (states.lock.be666zp_connect_smart_deadbolt_locked.state) == 'locked' else alarm_type_value %}
  # {% set atv = 25 if (doordiff) < 15 and (contdiff) > 15 and (states.lock.be666zp_connect_smart_deadbolt_locked.state) == 'unlocked' else alarm_type_value %}

  - alias: frontdoor Status Report
    trigger:
      platform: state
      entity_id: input_number.frontdoor_lock_command, input_number.frontdoor_lock_user
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
      - condition: template
        value_template: "{{ states('sensor.mf_ew_dl_access_control_frontdoor') != 0 }}"
    action:
      - service: input_text.set_value
        data_template:
          entity_id: input_text.frontdoor_status_report
          value: >-
            {% set UC = 'sensor.mf_ew_dl_alarm_level_frontdoor' %}
            {% set AC = 'sensor.mf_ew_dl_access_control_frontdoor' %}
            {% set UClc = states.sensor[UC.split('.')[-1]].last_changed %}
            {% set AClc = states.sensor[AC.split('.')[-1]].last_changed %}

            {% set usercode_value = states.input_number.frontdoor_lock_user.state | int | string  %}
            {% set alarm_type_value = states.input_number.frontdoor_lock_command.state | int | string %}

            {% set atv = 0 %}
            {% if (alarm_type_value | int == 66 or alarm_type_value | int == 67) %}
              {% if 'alarm_type' in AC %}
                 {% set atv = alarm_type_value | int - 42 %}
              {% elif 'access_control' in AC %}
                 {% set atv = alarm_type_value | int - 63 %}
              {% endif %}
            {% endif %}
            {% if atv != 0 %}
               {% set alarm_type_value = atv %}
            {% endif %}

            {% set alarm_type_value = alarm_type_value | string %}

            {% if 'alarm_type' in AC %}
              {% set alarm_type_general_actions = {
                '999':'Kwikset',
                '0':'No Status Reported',
                '9':'Lock Jammed',
                '17':'Keypad Lock Jammed',
                '21':'Manual Lock',
                '22':'Manual Unlock',
                '23':'RF Lock Jammed',
                '24':'RF Lock',
                '25':'RF Unlock',
                '26':'Auto Lock Jammed',
                '27':'Auto Lock',
                '32':'All Codes Deleted',
                '161':'Bad Code Entered',
                '167':'Battery Low',
                '168':'Battery Critical',
                '169':'Battery Too Low To Operate Lock' } %}
              {% set alarm_type_lock_actions = {
                '16':'Keypad Unlock',
                '18':'Keypad Lock',
                '19':'Keypad Unlock',
                '162':'Lock Code Attempt Outside of Schedule' } %}
              {% set alarm_type_code_actions = {
                '33':'Code Deleted',
                '112':'Code Changed',
                '113':'Duplicate Code' } %}
            {% elif 'access_control' in AC %}
              {% set alarm_type_general_actions = {
                '999':'Schlage',
                '1':'Manual Lock',
                '2':'Manual Unlock',
                '3':'RF Lock',
                '4':'RF Unlock',
                '7':'Manual not fully locked',
                '8':'RF not fully locked',
                '9':'Auto Lock locked',
                '10':'Auto Lock not fully locked',
                '11':'Lock Jammed',
                '16':'Keypad temporary disabled',
                '17':'Keypad busy' } %}
              {% set alarm_type_lock_actions = {
                '5':'Keypad Lock',
                '6':'Keypad Unlock' } %}
              {% set alarm_type_code_actions = {
                '12':'All User Codes Deleted',
                '13':'Single Code Deleted',
                '14':'New User Code Added',
                '18':'New Program Code Entered',
                '15':'Duplicate Code' } %}
            {% endif %}
            {% if alarm_type_value in alarm_type_code_actions %}
              {{alarm_type_value}};{{ alarm_type_code_actions[alarm_type_value] }};{{usercode_value}}
            {% elif alarm_type_value in alarm_type_lock_actions  %}
              {{alarm_type_value}};{{ alarm_type_lock_actions[alarm_type_value] }};{{usercode_value}}
            {% elif alarm_type_value in alarm_type_general_actions %}
              {{alarm_type_value}};{{ alarm_type_general_actions[alarm_type_value] }};{{usercode_value}}
            {% else %}
              {{alarm_type_value}};{{alarm_type_value}}-Unknown Alarm Type Value;{{usercode_value}}
            {% endif %}

  - alias: frontdoor Lock Notifications
    trigger:
      platform: state
      entity_id: input_text.frontdoor_status_report
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
      - condition: template
        value_template: >-
          {% set report = states.input_text.frontdoor_status_report.state %}
          {% set a = report.split(';') %}
          {% if (a|length) != 3 or (a[2] == "0") %} 
            {{ true }}
          {% else %}
            {{ true }}
          {% endif %}
    action:
      - service: script.frontdoor_conditional_notify
        data_template:
          boolean: input_boolean.frontdoor_lock_notifications
          title: frontdoor
          message: >-
            {% set report = states.input_text.frontdoor_status_report.state %}
            {% set a = report.split(';') %}
            {{ a[1] }}

  - alias: frontdoor User Notifications
    trigger:
      platform: state
      entity_id: input_text.frontdoor_status_report
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
      - condition: template
        value_template: >-
          {% set report = states.input_text.frontdoor_status_report.state %}
          {% set a = report.split(';') %}
          {% if (a|length) == 3 and (a[2] | int > 0) %} 
            {{ true }}
          {% else %}
            {{ false }}
          {% endif %}
      - condition: template
        value_template: >-
          {% set report = states.input_text.frontdoor_status_report.state %}
          {% set a = report.split(';') %}
          {% set entity_id = 'notify_frontdoor_' + a[2] %}
          {% set notify = states['input_boolean'][entity_id].state %}
          {{ notify == "on" }}
    action:
      - service: script.frontdoor_manual_notify
        data_template:
          title: >-
            {% set report = states.input_text.frontdoor_status_report.state %}
            {% set a = report.split(';') %}
            {{ a[1] }}
          message: >-
            {% set report = states.input_text.frontdoor_status_report.state %}
            {% set a = report.split(';') %}
            {% set entity_id = 'input_text.frontdoor_name_' + a[2] %}
            {% set user = states(entity_id) %}
            {{ user }}

  - alias: frontdoor Sensor Close
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
    trigger:
      entity_id: binary_sensor.mf_ew_ds_sensor_frontdoor
      platform: state
      to: "off"
    action:
      - service: script.frontdoor_conditional_notify
        data_template:
          boolean: input_boolean.frontdoor_dooraccess_notifications
          title: frontdoor
          message: "Closed"

  - alias: frontdoor Sensor Opened
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
    trigger:
      entity_id: binary_sensor.mf_ew_ds_sensor_frontdoor
      platform: state
      to: "on"
    action:
      - service: script.frontdoor_conditional_notify
        data_template:
          boolean: input_boolean.frontdoor_dooraccess_notifications
          title: frontdoor
          message: "Opened"

  # - alias: frontdoor Add Code
  #   trigger:
  #     entity_id: binary_sensor.active_frontdoor_1
  #     platform: state
  #     to: "on"
  #   condition:
  #     - condition: state
  #       entity_id: "binary_sensor.allow_automation"
  #       state: "on"
  #   action:
  #     - choose:
  #         - conditions: >
  #             {{ True }}
  #         # this comment preserves formating
  #           sequence:
  #             - service: ozw.set_usercode
  #               data_template:
  #                 entity_id: lock.mf_ew_dl_locked_frontdoor
  #                 code_slot: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}
  #                   {{ code_slot  }}
  #                 usercode: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}    
  #                   {% set codetext = 'frontdoor_pin_' + code_slot | string %}
  #                   {% set code = states['input_text'][codetext].state %}
  #                   {{ code | string }}
  #         - conditions: >
  #             {{ True == False }}
  #         # this comment preserves formating
  #           sequence:
  #             - service: lock.set_usercode
  #               data_template:
  #                 node_id: >-
  #                   {{ state_attr('lock.mf_ew_dl_locked_frontdoor','node_id') }}
  #                 code_slot: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}
  #                   {{ code_slot  }}
  #                 usercode: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}    
  #                   {% set codetext = 'frontdoor_pin_' + code_slot | string %}
  #                   {% set code = states['input_text'][codetext].state %}
  #                   {{ code | string }}

  - alias: frontdoor Update Code
    trigger:
      entity_id: input_text.frontdoor_pin_1
      platform: state
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
      - condition: template
        value_template: >-
          {% set object_id = trigger.to_state.object_id %}
          {% set index = object_id.rfind('_') + 1 %}
          {% set code_slot = object_id[index:] %}
          {% set b = 'input_boolean.enabled_frontdoor_' + code_slot | string %}
          {{ is_state(b, 'on') and (trigger.from_state.state != trigger.to_state.state)}}
    action:
      - service: persistent_notification.create
        data_template:
          title: frontdoor LOCK MANAGER
          message: >-
            {% set object_id = trigger.to_state.object_id %}
            {% set index = object_id.rfind('_') + 1 %}
            {% set code_slot = object_id[index:] %}
            {{ 'You changed the PIN for code  ' + code_slot | string + '. Please enable it in order to make it active.'}}
      - service: input_boolean.turn_off
        data_template:
          entity_id: >-
            {% set object_id = trigger.to_state.object_id %}
            {% set index = object_id.rfind('_') + 1 %}
            {% set code_slot = object_id[index:] %}
            {{ 'input_boolean.enabled_frontdoor_' + code_slot | string }}

  - alias: frontdoor Reset
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
    trigger:
      entity_id: input_boolean.frontdoor_reset_lock
      platform: state
      from: "off"
      to: "on"
    action:
      - service: script.frontdoor_reset_lock
      - service: input_boolean.turn_off
        entity_id: input_boolean.frontdoor_reset_lock

  # - alias: frontdoor Clear Code
  #   trigger:
  #     entity_id: binary_sensor.active_frontdoor_1
  #     platform: state
  #     to: "off"
  #   condition:
  #     - condition: state
  #       entity_id: "binary_sensor.allow_automation"
  #       state: "on"
  #   action:
  #     - choose:
  #         - conditions: >
  #             {{ True }}
  #         # this comment preserves formating
  #           sequence:
  #             - service: ozw.clear_usercode
  #               data_template:
  #                 entity_id: lock.mf_ew_dl_locked_frontdoor
  #                 code_slot: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}
  #                   {{ code_slot  }}
  #         - conditions: >
  #             {{ True == False }}
  #         # this comment preserves formating
  #           sequence:
  #             - service: lock.set_usercode
  #               data_template:
  #                 node_id: >-
  #                   {{ state_attr('lock.mf_ew_dl_locked_frontdoor','node_id') }}
  #                 code_slot: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}
  #                   {{ code_slot  }}
  #                 usercode: >-
  #                   {{ range(1000, 9999) | random | int }}
  #             - service: lock.clear_usercode
  #               data_template:
  #                 node_id: >-
  #                   {{ state_attr('lock.mf_ew_dl_locked_frontdoor','node_id') }}
  #                 code_slot: >-
  #                   {% set object_id = trigger.to_state.object_id %}
  #                   {% set index = object_id.rfind('_') + 1 %}
  #                   {% set code_slot = object_id[index:] %}
  #                   {{ code_slot  }}

  - alias: frontdoor Decrement Access Count
    trigger:
      platform: state
      entity_id: input_text.frontdoor_status_report
    condition:
      - condition: state
        entity_id: "binary_sensor.allow_automation"
        state: "on"
      - condition: template
        # Check for Keypad Unlock code
        value_template: >-
          {% set report = states.input_text.frontdoor_status_report.state %}
          {% set a = report.split(';') %}
          {% if (a|length) == 3 and (a[2] | int > 0) %} 
             {{ (a[0] | int == 19) or (a[0] | int == 6)  }}
          {% else %}
            {{ false }}
          {% endif %}
    action:
      - service: input_number.decrement
        data_template:
          entity_id: >-
            {% set report = states.input_text.frontdoor_status_report.state %}
            {% set a = report.split(';') %}
            {{ 'input_number.accesscount_frontdoor_' + a[2] }}