Danielhiversen / pySwitchbot

Library to control Switchbot
MIT License
102 stars 47 forks source link

feature request: Switchbot Lock Pro #233

Open chrismelba opened 7 months ago

chrismelba commented 7 months ago

Hi,

I've just bought two of the newly released Switchbot Lock Pros. Would it be possible to add them to this repo? Unsure how much they differ from the standard locks.

-Chris

wunderbaum commented 5 months ago

Would like that, too as I have such a lock. How can I support that?

ynsgnr commented 5 months ago

I looked into adding the lock pro and it is discoverable with model $: After making this change you can connect to it by fetching keys with /scripts/get_encryption_key.py :

    async def get_locks(self) -> dict[str, SwitchBotAdvertisement]:
        """Return all WoLock/Locks devices with services data."""
        locks = await self._get_devices_by_model("o")
        lock_pros = await self._get_devices_by_model("$")
        return {**locks, **lock_pros}

To get basic data COMMAND_LOCK_INFO needs to be increased by one from 0f4f8101 to 0f4f8102. I assume that part of the command is the API Version or model number.

However after applying same byte flips to UNLOCK commands (from 0f4e01011080 to 0f4e02011080) it didn't work. Most unlock commands I tried just worked as lock command with different resources. I tried to brute force it and the logs shows "Locked By X" X being a different service on each command bit increase. Ex: "Unlocked By Google Home"

I'm not familiar with switchbots BLE API though, any help would be appreciated

Michal4K commented 5 months ago

@ynsgnr There is no documentation of this commands. The easiest to find right command would be sniff the communication with the android app. You can use android developer function Bluetooth HCI snoop for this. I used this technique to find command for opening the door without unlatching on previous model. Unfortunately bluetooth snooping not work on all android phones i was forced to borrow samsung from family member for this, because on Nothing phone 1 the records was always empty.

szclsya commented 5 months ago

Did some bluetooth snooping and tl;dr:

Tested with my own (North American firmware) Lock Pro.

While we are at it, here's all the commands I found:

> 0e01002000008104
> 0f4f8104
> 0f4f0501
> 0f4f0502
> 000501000000006662657a
> 0f4f0401
> 0e01002000008104
> 0f4e0101000100
> 0f4e0101000180

Edit: See pull request at #241

varyamereon commented 5 months ago

Would very much appreciate if the night latch feature would be supported too! This is already a feature of the original switchbot lock.

szclsya commented 5 months ago

@varyamereon Looks like my model don't have night latch support, so I can't test such feature here. Feel free to snoop it yourself though, I can share the script I use to decrypt the communication.

varyamereon commented 5 months ago

I think it's supported on all models, though I may be wrong. It's an option during the calibration process. If we don't set it up like that, the door opens every time we unlock which was a bit of a surprise the first time we found the front door wide open 😅

If it's not something you can do I'm happy to help where I can, though I am not familiar with Bluetooth/python at all 🫣

szclsya commented 5 months ago

Just re-calibrated my lock pro and there were no option for night latch, and since the code implies the original Lock's night latch feature is limited to EU region I'd assume it's indeed still region locked (for some reason).

However since the command for lock/unlock shares a pattern between two generations (i.e lock command both ends in 80), it would be fair to assume unlock with night latch would also use this pattern (so 0f4e010110a0 -> 0f4e01010000a0). I can create a different branch for you to test if you wish.

varyamereon commented 5 months ago

I can give it a go next week at the earliest. It's not my area of expertise but I should be able to get it working.

Michal4K commented 5 months ago

It would be also helpful if you can post your lock Advertisement Data from Home Assistant debug log. So we can check if night latch detection works for new model. I assume it will work... but just to be sure

schummar commented 5 months ago

@szclsya I have the EU lock and logged my bluetooth traffic. COMMAND_UNLOCK_WITHOUT_UNLATCH should be 0f4e01010001a0

szclsya commented 5 months ago

@schummar Nice! That proves our theory. I'll add that to the pull request.

varyamereon commented 5 months ago

Thanks, I appreciate that!

chrismelba commented 5 months ago

You can contact switchbot support directly if you want to change your main account over to email. Not sure if this will help your problem though.

On Mon, 10 June 2024, 7:16 pm incre77, @.***> wrote:

Thank you very much for your work. Im have been testing but in my case in not fully working. I made a guest user and i got the encryption key for that user (cis i began with the main account in google third party mode and its imposible to me to reset password or get the encryption key for that account).

I tried this code: ` async def main(): wolock = await GetSwitchbotDevices().get_locks() print(wolock) l = lock.SwitchbotLock(wolock['FF:02:53:A3:BB:11'].device,"13", "XXXXXXXXXXXXXXXXX","$") await l.get_basic_info() await l.unlock()

asyncio.run(main()) ` And the lock only "locks". I the lock is unlocked the lock locks whenever i send lock or unlock command but if the lock is locked the lock make a "beep" but nothing happens. the result of get_basic_info is alwais = bytearray(b'\x05') = "Unsuccessful, please try again" and the result of self._send_command(command) when lock or unlock is = bytearray(b'\x01\x82L\x00m\x00') or bytearray(b'\x01\x82Z\x00m\x00') when do nothing and bytearray(b'\x01\x90Z\x00m\x00') when locks.

i have an european lock pro with the latest firmware.

— Reply to this email directly, view it on GitHub https://github.com/Danielhiversen/pySwitchbot/issues/233#issuecomment-2157804569, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHW5SLDUGE3DMF4QPXZ3SLZGVVHBAVCNFSM6AAAAABGG2JNOWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJXHAYDINJWHE . You are receiving this because you authored the thread.Message ID: @.***>

incre77 commented 5 months ago

very thanks @chrismelba. I did that and now i have my account correct. But i discovered what if i create a guest user in the app with an different email and i use that account to get the pass with the script i get the same ble-key as the main account.

Im trying to send unlock command from an esp32 after a nfc reading... i tried to port a part of the code to c++ but im stucked in the cipher part. Anyone knows something about this?.I didnt found any related code for esp32 neither the non pro lock.

Anyway. thanks you very much to every body who made this locks working out of the web-api. :)

varyamereon commented 4 months ago

Thanks for your hard work everyone! I haven't had a chance to test mine yet as I can't get it to authorise for some reason, but I noticed someone posted in the HA repo that night latch isn't working for them.

chrismelba commented 4 months ago

Great to have it in HA! However my lock isn't showing state in HA if I manually change it? Ideally I'd like the lock to automatically lock at night or when i leave the house, however if I've opened it manually that won't work, as HA will think it's already locked

mwolter805 commented 4 months ago

I am having the same issue as @chrismelba when using the Lock Pro with Home Assistant (HA), plus one more issue. I have the North American version of the lock, not sure this makes a difference. Please note, none of these issues are present in the SwitchBot app, the app works perfectly.

  1. Often HA becomes out of sync with the lock’s state when the lock is manually operated. When Home Assistant and the lock out of sync, HA will issue the command it thinks is correct for the state, when in actuality the lock is already in that state. It appears from that time forward the lock and HA are in sync until the lock is manually operated.
  2. When the door is closed, the lock state changes to locked in HA, when in actuality the lock is not locked.
ollo69 commented 4 months ago

Just opened issue #121254 in HA, seems to be the same issue descripted here. Available for any debug to help to fix this, I have EU model with firmware V1.8 and battery pack

szclsya commented 4 months ago

So turns out the lock pro indeed has a different passive mode data format (duh), and the old parser happened to work with the data I used for testing and align with the expected result when I wrote the first PR...

Anyways, after some trail and error I've written a new parser (szclsya/pySwitchbot/lock-pro-adv-parser). Currently I've only verified these to be correctly parsed:

So we will still need to verify these:

As a bonus, we can now determine if the lock is opened by hand by the manual field.

If anyone want to contribute you can run the following script (and grep switchbot.adv_parsers.lock as it's very verbose) to watch all events from the lock pro, so that we can test the features that are not on my lock pro model and/or verify other features work as intended:

#!/usr/bin/env python3

import switchbot
import asyncio
import logging

async def main():
    while True:
        getdevices = switchbot.discovery.GetSwitchbotDevices()
        await getdevices.discover()

if __name__ == '__main__':
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Note that mfr_data will contain the MAC address of your lock, so remove the first 12 characters if you don't want to leak it. (shouldn't be a huge deal tho)

Edit: see PR at #243

ollo69 commented 4 months ago

For me the parser from @szclsya fork (the one from his last commit) is working properly. I tried to find information about battery pack in the returned raw data but I found nothing (nothing change removing and adding 1 battery pack at time).

Sorry but I don't have a secondary lock or night_latch to test this feature.

Thanks!!!

chrismelba commented 4 months ago

I've just updated ha to 2024.7.1

Now if I have the device open and manually trigger it I can see it change state, but if I don't have HA open and manually press the lock then ha hadn't updated after 5 minutes.

Does there need to be some kind of trigger to retrieve state or something?

I'm connecting via esphome Bluetooth gateway if that matters

ollo69 commented 4 months ago

I've just updated ha to 2024.7.1

Now if I have the device open and manually trigger it I can see it change state, but if I don't have HA open and manually press the lock then ha hadn't updated after 5 minutes.

Does there need to be some kind of trigger to retrieve state or something?

I'm connecting via esphome Bluetooth gateway if that matters

At this moment status for Lock Pro is not properly reported. You must wait for new PR on this repository with the fix from @szclsya and for a new release of HA that include a PR that bump new version of this library in HA Switchbot integration.

jsprotky commented 4 months ago

If anyone want to contribute you can run the following script (and grep switchbot.adv_parsers.lock as it's very verbose) to watch all events from the lock pro, so that we can test the features that are not on my lock pro model and/or verify other features work as intended

This is what I got for a Switchbot Lock Pro, EU version with night latch. The lock was latched but not unlocked.

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX0eb200550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.NOT_FULLY_LOCKED: 6>, 'update_from_secondary_lock': False, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

Then in the Switchbot app I triggered unlatching which auto-latches again after some seconds. I did not open the door in that time.

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX129a00550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.UNLOCKING: 3>, 'update_from_secondary_lock': True, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX139a00550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.UNLOCKING: 3>, 'update_from_secondary_lock': True, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX148a00550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.UNLOCKED: 1>, 'update_from_secondary_lock': True, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX15b200550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.NOT_FULLY_LOCKED: 6>, 'update_from_secondary_lock': False, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

Then from the Switchbot app I triggered locking the lock.

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX1e9200550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.LOCKING: 2>, 'update_from_secondary_lock': False, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX1f8200550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.LOCKED: 0>, 'update_from_secondary_lock': False, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

Then from the Switchbot app I triggered unlocking the lock (without unlatching!).

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX219a00550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.UNLOCKING: 3>, 'update_from_secondary_lock': True, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX228a00550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.UNLOCKED: 1>, 'update_from_secondary_lock': True, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}

DEBUG:switchbot.adv_parsers.lock:mfr_data: XXXXXXXXXXXX23b200550000
DEBUG:switchbot.adv_parsers.lock:data: 248055
DEBUG:switchbot.adv_parsers.lock:{'battery': 85, 'calibration': True, 'status': <LockStatus.NOT_FULLY_LOCKED: 6>, 'update_from_secondary_lock': False, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': True, 'manual': False}
mwolter805 commented 4 months ago

If possible, can someone help with adding the ability to see the charge level of both batteries in the rechargeable Dual Power Pack?

As noted here https://github.com/Danielhiversen/pySwitchbot/issues/233#issuecomment-2211182237 and https://github.com/Danielhiversen/pySwitchbot/pull/243#issuecomment-2221491972 the detailed battery info is not sent in passive mode.

Please let me know if I can provide any info.

jensweimann commented 3 months ago

Now that this feature is in the release of Home Assistant 2024.7.3 I tried it and at first, the night latch feature didn't show up.

In the debug logs was this: [switchbot.adv_parsers.lock] {'battery': 84, 'calibration': True, 'status': <LockStatus.NOT_FULLY_LOCKED: 6>, 'door_open': False, 'update_from_secondary_lock': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': False}

Then I locked and unlatched in the app and the night_latch flag became True. Then I tried it with home assistant a couple of times. Then I checked the log again and to my surprise the night_latch flag was false again.

It seems that the flag gets disabled when unlatching trough home assistant. What about this comment?

@szclsya I have the EU lock and logged my bluetooth traffic. COMMAND_UNLOCK_WITHOUT_UNLATCH should be 0f4e01010001a0

In the code is this currently: SwitchbotModel.LOCK_PRO: f"{COMMAND_HEADER}0f4e01010000a0",

Michal4K commented 3 months ago

@jensweimann That nibble just indicate source of the action as described here - https://github.com/Danielhiversen/pySwitchbot/pull/241#issuecomment-2155066260.

jsprotky commented 3 months ago

Have the same issue as @jensweimann. After updating to HA 2024.7.3 my lock is not recognized as night latch lock anymore. Have not tried to get it back working though and currently just live with it.

schummar commented 3 months ago

I have two locks, both with night latch. After the latest update one of them shows with the option to open, the other does not. Both bought together and same firmware version, so I would expect them to behave the same way.

What about owners of the non-night-latch version? Do some of you also see the "open" option? That might show that we have the wrong bit and it's indeed random chance. 😉

Michal4K commented 3 months ago

@schummar You could be right.

@mwolter805 Are you using night latch feature? You post your ADV where some indicates night latch turned off and some on. https://github.com/Danielhiversen/pySwitchbot/pull/243#issuecomment-2219101334

mwolter805 commented 3 months ago

@Michal4K I am not using the night latch feature.

Michal4K commented 3 months ago

Then I think the night latch indicating bit was shifted up for few bits and the right one could be this one.

"night_latch": bool(mfr_data[9] & 0b00010000)

Michal4K commented 3 months ago

@jsprotky For everyone who would like to use nightlatch feature and they don't see it in Home Assistant now, because of the issue with the adv parser. There is a way to manually overwrite entity feature set.

By customizing entity in HA configuration file:

homeassistant:
  customize:
    lock.<<your_lock_entity>>:
      supported_features: 1

Or you can also change this in developer tool -> States, but it will last only until switchbot integration reload.

jsprotky commented 3 months ago

@jsprotky For everyone who would like to use nightlatch feature and they don't see it in Home Assistant now, because of the issue with the adv parser. There is a way to manually overwrite entity feature set.

By customizing entity in HA configuration file:

homeassistant:
  customize:
    lock.<<your_lock_entity>>:
      supported_features: 1

Or you can also change this in developer tool -> States, but it will last only until switchbot integration reload.

I get "entity does not support this service" when I change the supported_features attribute and try to unlatch the lock. The button to unlatch the lock is there but not working. Are you sure that pyswitchbot will unlatch just because HA sent the unlatch request?

csmale commented 3 months ago

@jsprotky For everyone who would like to use nightlatch feature and they don't see it in Home Assistant now, because of the issue with the adv parser. There is a way to manually overwrite entity feature set. By customizing entity in HA configuration file:

homeassistant:
  customize:
    lock.<<your_lock_entity>>:
      supported_features: 1

Or you can also change this in developer tool -> States, but it will last only until switchbot integration reload.

I get "entity does not support this service" when I change the supported_features attribute and try to unlatch the lock. The button to unlatch the lock is there but not working. Are you sure that pyswitchbot will unlatch just because HA sent the unlatch request?

I have the same. The UI includes the right buttons but a call to lock.open on lock.* gives "Failed to call service lock.open. Entity lock.lock_pro_xxxx does not support this service."

A call to lock.unlock is accepted but it goes too far and opens the door as well.

Michal4K commented 3 months ago

You are right. It does not work. Only way to make it work will be change ADV parse to return always True for night latch feature. But this require going inside your HA finding the switchbot library and it will be overwrite with every update. Sorry for not working advice.

balu79 commented 3 months ago

I just changed my batteries (replaced normally batteries by battery pack) and seems that caused my previous night latch support to stop working (and supported_features was updated from 1 to now 0).

chrismelba commented 3 months ago

I'm also having an odd problem. I have 2 locks, which I'm pretty sure I set up the same. One of them will only unlock by using lock.open if I use lock.unlock then it tries to lock itself again and fails? The other one is working fine with lock.unlock and doesn't even have the lock.open visible in the GUI

Pascal4Games commented 3 months ago

You are right. It does not work. Only way to make it work will be change ADV parse to return always True for night latch feature. But this require going inside your HA finding the switchbot library and it will be overwrite with every update. Sorry for not working advice.

Another workarround for the moment would be to download the switchbot integration and add it as a custom integration. Downsite of the ajustment is that when you have multiple locks and not all need unlatch it doesn't work and if the issue get fix it doesn't auto update.

You do have to change to files to get it to work: manifest.json

add don't forgot the "," at the end of the last line.
"version": "1.0.8"

and in lock.py

By "def __init__" after change looks like this
        """Initialize the entity."""
        super().__init__(coordinator)
        self._async_update_attrs()
        #if self._device.is_night_latch_enabled():
        self._attr_supported_features = LockEntityFeature.OPEN

and by "async def async_unlock" after change looks like this:
        """Unlock the lock."""
        #if self._device.is_night_latch_enabled():
        self._last_run_success = await self._device.unlock_without_unlatch()
        #else:
        #    self._last_run_success = await self._device.unlock()
        self.async_write_ha_state()

Hopefully this is useful.

Xyz00777 commented 2 months ago

@Pascal4Games do you have possibly time to do an little step by step guide because at least i am a little bit helpless how to do it..? or is the fix near to be released?

balu79 commented 2 months ago

@Pascal4Games do you have possibly time to do an little step by step guide because at least i am a little bit helpless how to do it..? or is the fix near to be released?

This is how I did it. Probably the step to download the switchbot integration is not the best, but I couldn't figure out another way. 1.) Went to the switchbot bluetooth integration on github (https://github.com/home-assistant/core/tree/dev/homeassistant/components/switchbot) and downloaded all the 14 python and json files manually one by one 2.) Modified the 2 above mentioned python and json files according to the instructions from Pascal4Games 3.) Created a folder called "switchbot" on my PC to which I moved all 14 downloaded and modified files 4.) Uploaded that switchbot folder with the files to config\custom_components 5.) Restarted home assistant and checked that there are no errors in the logs of home assistant related to the switchbot (bluetooth) integration as well that within the integrations page the switchbot integration now shows a yellow icon for custom integration 6.) Test functionality and be happy ;-)

Pascal4Games commented 2 months ago

Sorry, I hadn't seen your response yet, but I'm glad you managed to do it yourself. To download the integration I used https://download-directory.github.io/ It's not a fix for everyone, but only for people who have the lock-pro, want to use the latch function, don't have a lock that doesn't need the latch function and don't want to wait until the problem is solved.

Michal4K commented 2 months ago

I opened a PR in HA to which allow forcing night latch operation. https://github.com/home-assistant/core/pull/124326

It simply adds checkbox to option configuration which force lock to operate as night latch was detected. 20240820_21h51m41s_grim

Pascal4Games commented 2 months ago

I opened a PR in HA to which allow forcing night latch operation. home-assistant/core#124326

It simply adds checkbox to option configuration which force lock to operate as night latch was detected. 20240820_21h51m41s_grim

That is indeed a better solution. Thanks just tested and works.

jsprotky commented 2 months ago

I opened a PR in HA to which allow forcing night latch operation. https://github.com/home-assistant/core/pull/124326

It simply adds checkbox to option configuration which force lock to operate as night latch was detected. 20240820_21h51m41s_grim

It got merged to dev a week ago but it's still not part of 2024.9.0, 2024.9.1 or 2024.9.2 (not assigned to the current milestone). @bdraco can you assign it to the next milestone? For us mere mortals comments are closed on the merged PR so no way to communicate the urgency.