Schlage Connect ZWave Locks

I did just get an Apple TV. Haha. I have not set it up at all in HA yet. No worries. Thanks. I think i understand enough to get a bit further along.

1 Like

Looking at this a bit further, it seems that it possibly better to use the Alarm Access Control sensor instead to derive the state. It appears to have all the information needed for this to replace:

enum Alarm_Access_Control_Event {
	Alarm_Access_Control_Manual_Lock = 0x01,
	Alarm_Access_Control_Manual_Unlock = 0x02,
	Alarm_Access_Control_RF_Lock = 0x03,
	Alarm_Access_Control_RF_Unlock = 0x04,
	Alarm_Access_Control_KeyPad_Lock = 0x05,
	Alarm_Access_Control_KeyPad_Unlock = 0x06,
	Alarm_Access_Control_Unknown_Event = 0xFE,
};

So looking at the HA code, it already appears to have code to process the lock status from the access_control sensor. I guess for some reason this isn’t working…

if self.values.access_control:
           notification_data = self.values.access_control.data
            self._notification = LOCK_NOTIFICATION.get(str(notification_data))

            if self._v2btze:
                if self.values.v2btze_advanced and \
                        self.values.v2btze_advanced.data == CONFIG_ADVANCED:
                    self._state = LOCK_STATUS.get(str(notification_data))
                    _LOGGER.debug(
                        "Lock state set from Access Control value and is %s, "
                        "get=%s", str(notification_data), self.state)

I will debug further.

2 Likes

I have not had a chance to use your forked code, but I will say that this does work for me already. Like you show I get keypad lock, unlock, manual lock, unlock events. It updates in realtime, almost instantly. It does not update the lock.lock device though to locked, unlocked right away though. So if I unlock with keypad, the UI still shows locked.

Additionally, index 200 (usercode), does report the last value “code slot” used to unlock the door, but only updates when I restart HA or save config via openzave UI in HA.

EDIT: I have not tested the other sensors (burglar, or power managment), but they may work. I’d need to test by triggering a “Burglar event”. Like trying to force the door.
Also the “System sensor, reports as “hardware failure” for me for both my deadbolts, I just assume it reporting a value that’s not listed in the code”, not a huge deal.

I feel like the intent was to use index 200 to report usercode slot, but it’s just not quite working,

1 Like

I just added a 2nd Schlage Connect Deadbolt Lock (BE469NX CAM 619). Everything went much smoother this time. Added as a secure node through the zwave gui, and the lock paired right away. All 8 sensors showed up right away. Much better than my previous experience.

1 Like

Does anyone have an issue with this lock stopping responding after some period of time. I have 2 locks, and one will work ok, but then all associated entries just disappear in the zwave control panel. Pushing a refresh of the node brings everything back up again for another random period of time.

I’m connected via a HUSBZB-1

I can say that although I had the issues related to the dev branch, so far I’ve never had any issues with HA being unable to lock/unlock (or losing connection) the doors at all. I even have a FE599 lock as well, it’s been flawless for more than a month.

1 Like

Yeah I’m having problems with the ha process dying. I believe something in the openzwave stack crashing.

Does anyone know how to debug openzwave? It is crashing periodically but I don’t see any crash log or such.

@Matthew_Noecker, are you still trying to get alarm level to “reset” back to 0? I created a template sensor to give me this functionality and can share it if you are still looking to do this.

I’d love to see that as well. :slight_smile:

As we’ve seen, alarm_level stays constant until a different value of alarm_level is set. So it is useful for seeing the last code that was entered, but not useful for triggering new automations each time a code is entered, if it is the same code as what was previously entered.

A template sensor works around this. First, you must create a time_date sensor if you don’t already have one.

sensor:

  - platform: time_date
          display_options:
            - 'date_time'

Then your template sensor can look like this:

  - platform: template
    sensors:
      template_door_code_entered:
        value_template: >-
          {% if ((as_timestamp(strptime(states.sensor.date__time.state, "%Y-%m-%d, %H:%M")) - as_timestamp(states.sensor.schlage_fe599gr_wireless_door_lock_alarm_level.last_changed)) < 1) %}
            {{ states.sensor.schlage_fe599gr_wireless_door_lock_alarm_level.state }}
          {% else %}
            0
          {% endif %}

The template_door_code_entered will update to the alarm_level for the code just entered and stay that way for up to a minute, until the date__time sensor updates again. At that time the template_door_code_entered returns to 0. So you can trigger automations by looking for when template_door_code_entered is a valid code (valid codes are 1-254 or whatever upper limit for the number of codes a Schlage can store) and trigger automations for “wrong code entered” when template_door_code_entered goes to 255.

Note: I don’t know why sensor.date__time has a double underscore but that is the correct syntax for it to work in hass.

4 Likes

That is a great code snippet @kap! Thanks. I have a Schlage FE599 Z-Wave lock and the following seems to be working for me. The lock is on my garage door and the “template_door_code_entered” shown above was the missing link for me. This allows detection of user codes when the same code is used multiple times in a row.

The following code is in my automations.yaml file:

  - id: garage_remote_actvity_detection
    alias: "Garage Door Lock Remote Activity"
    # Any change in lock state, lock or unlock
    trigger:
      - platform: state
        entity_id: lock.garage_entry_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.lock_hass_status_for_garage_entry_door_lock
          option: >
            {% if is_state("lock.garage_entry_door", "locked") %}
              Locked by Home Assistant
            {% else %}
              Unlocked by Home Assistant
            {% endif %}
            
  ## When door is locked and set to Auto Re-Lock, the lock state doesn't toggle when user codes are entered
  - id: garage_code_used
    alias: "Garage Lock Code Used"
    ## leaving a value of zero indicates a user code was entered
    trigger:
      - platform: state
        entity_id: sensor.garage_door_code_entered
        from: '0'
    action:
      - service: input_select.select_option
        data:
          entity_id: input_select.lock_hass_status_for_garage_entry_door_lock
          option: Unlocked At Door

The following code is in my configuration.yaml file:

The input select is used to track operations performed by home assistant. It is used by a template sensor.

input_select:
  lock_hass_status_for_garage_entry_door_lock:
    name: Garage Door Lock HASS Status
    icon: mdi:lock
    options:
      - Locked by Home Assistant
      - Unlocked by Home Assistant
      - Unlocked At Door
      - Other

This is based on the code from @kap that detects when a user code is entered.

- platform: template
  sensors:
    garage_door_code_entered:
      value_template: >-
        {% if ((as_timestamp(strptime(states.sensor.date__time.state, "%Y-%m-%d, %H:%M")) - as_timestamp(states.sensor.garage_entry_door_alarm_level.last_changed)) < 1) %}
          {{ states.sensor.garage_entry_door_alarm_level.state }}
        {% else %}
          0
        {% endif %} 

The sensor below is what I use to display the locks current status and is used for automation triggers:

- platform: template
  sensors:
    garage_entry_door_last_action:
      friendly_name: 'Garage Entry Door Last Action'
      value_template: > 
                        {% if is_state('input_select.lock_hass_status_for_garage_entry_door_lock', 'Unlocked by Home Assistant') %}
                          Remotely Unlocked
                        {% elif is_state('input_select.lock_hass_status_for_garage_entry_door_lock', 'Locked by Home Assistant') %}
                          Remotely Locked
                        {% elif is_state('sensor.garage_door_code_entered', '0') %}
                          {% if is_state('lock.garage_entry_door', 'locked') %}
                            Auto Re-Locked
                          {% else %}
                            Unlocked by Ghost
                          {% endif %}
                        {% elif is_state('sensor.garage_entry_door_alarm_type', '16') %}
                          {% if is_state('sensor.garage_entry_door_alarm_level', '3') %}
                              Unlocked: Family Code
                          {% elif is_state('sensor.garage_entry_door_alarm_level', '4') %}
                              Unlocked: Friend Code
                          {% else %}
                            Unlocked: User Code {{states('sensor.garage_entry_door_alarm_level')}}
                          {% endif %}
                        {% else %}
                          {{ states.lock.garage_entry_door.attributes.lock_status }}
                        {% endif %}

I have a slightly different implementation for a Schlage Deadbolt Lock (BE469 Camelot)

      front_door_deadbolt_last_action:
        friendly_name: 'Front Door Last Action'
        value_template: >- 
                          {% if is_state('input_select.lock_hass_status_for_front_door_lock', 'Unlocked by Home Assistant') %}
                            Remotely Unlocked
                          {% elif is_state('input_select.lock_hass_status_for_front_door_lock', 'Locked by Home Assistant') %}
                            Remotely Locked
                          {% elif is_state('sensor.front_door_deadbolt_access_control', '6') and is_state('sensor.front_door_deadbolt_alarm_type', '19') %}
                            {% set door_lock_state = states('lock.front_door_deadbolt') %}
                            {% set alarm_level = states('sensor.front_door_deadbolt_alarm_level') %}
                            {% if is_state('sensor.front_door_deadbolt_alarm_level', '1') %}
                              {{ door_lock_state }} : Family Code
                            {% else %}
                              {{ door_lock_state }} : User Code {{ alarm_level }}
                            {% endif %}
                          {% else %}
                            {{ states.lock.front_door_deadbolt.attributes.notification }}
                          {% endif %}

How do you remove node 1 from the 1st group? I don’t see a way to do that.

this sorta confused me as well, but it actually made sense once I figured it out. Select your zwave node that you want to change the association on, select group1, then select the node1 (presumably your zwave stick), then you’ll see an option for ‘Remove from group’

1 Like

Thank you so much for the ultra fast response. That worked exactly as you described.

haha, np - the only reason why I responded so quickly was because I literally was on this thread doing this exact same thing.

I have the FE599 and the BE469 as well. I’ve always found the 599 to be problematic. Are you saying you are able to determine which code was used to unlock the 599 even if it is the same person each time. That was always my issue with the lock, so I ended up just giving up and moving on since most the time I automate the unlocking of this lock anyway.

I did add the lock a while back to group 2, but never removed it from group 1 is that the “trick”

Nevermind: I missed the previous post with the template. Great Idea, definitely gonna implement this in my config.

I have started a new thread that is specific to the FE599 lock and issues that I am experiencing.

Thank you for sharing this info on how to get the BE369 and FE599 Schlage locks working properly with Home Assistant and reporting their state. This was the last bit of info I needed to completely retire my old vera2.