Schlage Encode Wifi

I have not updated code since I initially installed the mcnutter1’s code. As you can see in the discussion history, both this code and dknowles2’s code had bad delays for me. Not sure what has changed but I gave both another try last week and the lock seems to be plenty responsive now without degrading over time.

It seems to work well. Some delay in lock / unlock status, under 15sec. Does the job of telling me if my doors are unlocked and controlling them via HA.

So just after my post 2 weeks ago, I changed the password on my Schlage account. I didn’t see a way to update the password in the integration, so I removed and reinstalled the integration. At the same time, I happened to turn off the UPnP in my router (Google Wifi, previous generation). I broke the rule by making two changes at once but, perhaps coincidentally, the wifi connection has not dropped since. [knock_on_wood.gif]

Status updates also seem responsive with little delay at this point.

Edit: someone else asked, so I figured I’d update here that I used @dknowles2’s fork:

@mcnutter1 @dknowles2 is it possible to have the integration pass the info for how the device was unlocked (e.g. thumbturn, keypad, Schlage App, or HA integration? I’d like to have unlocks trigger my Alarmo integration to disarm, but thumbturn unlocks would need to be excluded from that automation for security purposes.

1 Like

I could probably add this. We’d just need to read the logs from Schlage on every refresh and then look for the last log message and hope it matches the current state. (Presumably it would)

The “changed_by” would look be one of {“thumbturn”, “keypad”, “mobile app”}, because that’s what the logs return.

1 Like

That’s amazing! Thanks so much David

1 Like

If you ever use the physical key to unlock, that will register as a thumbturn. Just FYI, might not be applicable in your use case.

I just published a new version that populates the changed_by field. Should be available in HACS the next time it polls for updates.

Feel free to file FRs and bugs: Issues · dknowles2/ha-schlage · GitHub

And PRs are always welcome! :slight_smile:

4 Likes

First off, thank you so much for taking the time and effort to get this working. I have several of these Encode locks as the last holdover from my IFTT/Alexa mishmash setup. As you said, they work very well and reliably - just missing from Home Assistant.

The value for me in not being cloud dependent is continuity in the event of a down connection. That, and a Dale Gribble-esque distrust of the cloud.

Amazing! AAA+ 10+…congratulations!

Wow @dknowles2, thank you so much! My jaw is dropped right now and I’m struggling to come up with the words for how grateful I am. This whole community just continues to amaze me. What a time to be alive!

I haven’t played around with attributes before and am struggling to code the trigger for my automation. So far I have the following and have tried a number of variations to the attribute syntax, but to no avail. Any idea where I’ve gone wrong?

trigger:
  - platform: state
    entity_id:
      - lock.front_door_lock
    attribute: Changed by mobile device
    to: unlocked

I think you want:

trigger:
  - platform: state
    entity_id:
      - lock.front_door_lock
    to: unlocked
condition:
  - condition: state
    entity_id: lock.front_door_lock
    attribute: changed_by
    state: mobile device

The reason is that the entity has a state for its platform (e.g. it’s a lock, so it’s “locked”, “unlocked”, “jammed”, etc), as well as state for its attributes (in this case, the changed_by attribute). You want to first check that the platform state changed to the value you want (that’s the “trigger”), and then you want to filter those events against the attribute state (changed_by).

Related: I realized that I could also include additional information from the log in the changed_by state–each event in the log also includes the access code or virtual key that was used to initiate the change. For example, a keypad-initiated change can include the name of the access code used, and a mobile-device-initiated change can include the user (a.k.a. virtual key) name. I just pushed a 2023.3.0 that includes this change.

5 Likes

I’m tracking Bluetooth support here: FR: Bluetooth support · Issue #28 · dknowles2/pyschlage · GitHub

As mentioned elsewhere in the thread, tracing the Bluetooth code from the decompiled Android app is a bit off a nightmare. I’ve at least figured out the data transport, but there’s still a lot left to go. I’ll keep hacking at it when I have time, but I’ve got a few other projects I’d like to finish up first. (I want my sprinklers and smoker working in HA before spring rolls around :slight_smile:)

2 Likes

is anyone else getting an error with HA 2023.3.1?
Any time I try to lock or unlock, I get the error below. If I revert back to my backup from 2023.3.0, then it works fine.
my lock is a Schlage Sense with WiFi adapter, I’m running HA OS 9.5 on a generic x86 device.
I also tried a fresh install on a Hyper-V VM and it shows the same error. Restoring from backup works there too.


[140499180271312] 'Auth' object has no attribute 'user_id'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 198, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1808, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1845, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service
    await service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 686, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 961, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 726, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/lock/__init__.py", line 106, in _async_unlock
    await entity.async_unlock(**remove_entity_service_fields(service_call))
  File "/config/custom_components/schlage/lock.py", line 108, in async_unlock
    await self.hass.async_add_executor_job(self._lock.unlock)
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.10/site-packages/pyschlage/lock.py", line 129, in unlock
    self._toggle(0)
  File "/usr/local/lib/python3.10/site-packages/pyschlage/lock.py", line 109, in _toggle
    "userId": self._auth.user_id,
AttributeError: 'Auth' object has no attribute 'user_id' 
```

Whoops. I know what the problem is. I’ll try and get a fix in tonight. Sorry about that!

I was finally able to install this integration this weekend, and it has worked seamlessly so far. Thanks to @dknowles2 and for everyone else who has contributed to getting this to work!

I tried out the recent update that included the changed_by attribute. So far I have observed the following states for the changed_by attribute:

  • keypad - Name – when using a code
  • mobile app - Name – when triggered by HA or mobile app
  • thumbturn – when physically turning the thumbturn or key
  • Schlage button – when locking with the keypad button

I used these to pull together this basic door unlock greeting automation, that welcomes the name of the person with a Nabu Casa TTS announcement. So far it seems to work! This should work with the automation visual editor, if you’d like to try it out:

alias: Door unlock greeting
description: Play a greeting when the front door is unlocked
trigger:
  - platform: state
    entity_id:
      - lock.front_door_lock
    to: unlocked
condition: []
action:
  - if:
      - condition: state
        entity_id: lock.front_door_lock
        attribute: changed_by
        state: keypad - Person1
    then:
      - service: media_player.play_media
        target:
          entity_id: media_player.speaker_pair
        data:
          media_content_id: >-
            media-source://tts/cloud?message=Welcome+home+Person1%21&language=en-US&gender=female
          media_content_type: provider
        metadata:
          title: Welcome home Person1!
          thumbnail: https://brands.home-assistant.io/_/cloud/logo.png
          media_class: app
          children_media_class: null
          navigateIds:
            - {}
            - media_content_type: app
              media_content_id: media-source://tts
            - media_content_type: provider
              media_content_id: >-
                media-source://tts/cloud?message=Welcome+home+Person1%21&language=en-US&gender=female
mode: single
2 Likes

I just pushed 2023.3.1 to fix this.

Context: I accidentally broke the underlying library for Sense locks. (I had forgotten why that user_id attribute was being saved! D’oh!) I have Encode locks in my house so I didn’t notice that I broke it. I also fixed up the tests to catch this case so it won’t happen again in the future.

Again, sorry about that! Thanks for letting me know, as I probably wouldn’t have noticed if you hadn’t said something!

2 Likes

Thanks again @dknowles2, that worked flawlessly. I really appreciate you explaining how the states work as well. Do you have a “buy me a coffee” link by chance? I’d love to give back.

4 Likes

Has anyone tried this with the Schlage Encode Plus yet? I would imagine it’s probably the same if not virtually the same in operation over WiFi.

Right now I’m trying to get it paired via HomeKit Controller but it keeps failing when trying to add it in Home Assistant.

I did setup with Encode Plus with the Apple Home Key support.

While setting up I did the normal Wifi setup with Schlage app and then did the home kit setup.
I think so this addon supports the former Schlage API not the homekit api.

It works fine for me, just my current iPhone X doesn’t support Home Key in Apple Wallet for seamless door locking/unlocking.