Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix adv_parser for Switchbot Lock Pro #243

Merged
merged 9 commits into from
Jul 11, 2024

Conversation

szclsya
Copy link
Contributor

@szclsya szclsya commented Jul 6, 2024

Turns out the lock pro indeed has a different passive mode data format (duh), and we will need a separate parser for it.

Currently only these fields are tested to work:

  • battery
  • calibration
  • status
  • door_open
  • unclosed_alarm
  • unlocked_alarm
  • auto_lock_pause

And these are taken directly from the original lock, thus needs more testing on appropriate hardware:

  • update_from_secondary_lock
  • double_lock_mode
  • night_latch

Put it in adv_parsers/lock.py since code for lock pro active mode also lives side by side with the original lock at devices/lock.py.

szclsya added 3 commits July 4, 2024 19:27
- because of course they are different, why didn't I caught it earlier?!
- also add notes on which fields are still pending
@Michal4K
Copy link
Contributor

Michal4K commented Jul 6, 2024

#233 (comment)
It looks night_latch work with this changes too as @jsprotky post his testing...

@szclsya
Copy link
Contributor Author

szclsya commented Jul 6, 2024

Yup, I'll remove the "haven't been tested" comment real quick.

@codecov-commenter
Copy link

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 58.78%. Comparing base (45bf527) to head (5877a77).
Report is 14 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #243      +/-   ##
==========================================
+ Coverage   58.59%   58.78%   +0.19%     
==========================================
  Files          34       35       +1     
  Lines        1495     1536      +41     
==========================================
+ Hits          876      903      +27     
- Misses        619      633      +14     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jsprotky
Copy link

jsprotky commented Jul 6, 2024

Yup, I'll remove the "haven't been tested" comment real quick.

Let me know how I can help with checking update_from_secondary_lock and double_lock_mode. I see update_from_secondary_lock changes when unlatching the lock for some statuses but I don't know where it is used at all. Don't have a clue what double_lock_mode is tbh.

@szclsya
Copy link
Contributor Author

szclsya commented Jul 6, 2024

Let me know how I can help with checking update_from_secondary_lock and double_lock_mode. I see update_from_secondary_lock changes when unlatching the lock for some statuses but I don't know where it is used at all. Don't have a clue what double_lock_mode is tbh.

According to switchbot's documentation it's used when you group two locks together.

@jsprotky
Copy link

jsprotky commented Jul 6, 2024

Let me know how I can help with checking update_from_secondary_lock and double_lock_mode. I see update_from_secondary_lock changes when unlatching the lock for some statuses but I don't know where it is used at all. Don't have a clue what double_lock_mode is tbh.

According to switchbot's documentation it's used when you group two locks together.

Can not help here. Only have 1 lock.

@szclsya
Copy link
Contributor Author

szclsya commented Jul 6, 2024

Can not help here. Only have 1 lock.

Yeah me neither lol.

I guess we can just return False for both of them for now? As these features are kinda niche and I believe people really want the other part to work. We can always reintroduce these fields later, when proper data shows up.

@jsprotky
Copy link

jsprotky commented Jul 7, 2024

@szclsya I'm still unsure if we really should ignore update_from_secondary_lock. It changes in my setup (although I still don't know which secondary lock this would be). Please check the logs from my unlatching, locking and unlocking w/o unlatching actions.

When unlatching and when unlocking w/o unlatching the status is bouncing between unlocking->unlocked->not_fully_locked instead of straight forward going from unlocking->not_fully_locked. I think this should be debounced to not show up weirdly in the logs (also shows up this way in HA logs). You'll see in the logs that the unlocked state in this bouncy behavior ALWAYS comes with update_from_secondary_lock.

I trigger unlatching, then the status changes as follows:

  • unlocking (with update_from_secondary_lock = true)
  • unlocking (with update_from_secondary_lock = true)
  • unlocked (with update_from_secondary_lock = true)
  • not_fully_locked (with update_from_secondary_lock = false)

I trigger unlocking w/o unlatching, then the status changes as follows:

  • unlocking (with update_from_secondary_lock = true)
  • unlocked (with update_from_secondary_lock = true)
  • not_fully_locked (with update_from_secondary_lock = false)

I trigger locking, then the status changes straight forward:

  • locking (with update_from_secondary_lock = false)
  • locked (with update_from_secondary_lock = false)

@szclsya
Copy link
Contributor Author

szclsya commented Jul 7, 2024

@jsprotky That's because the old update_from_secondary_lock bit is now used by lock status. Check the changelog, and you can see the lock status now uses 3-5 bits of the 7th byte in mfr_data, while the existing update_from_secondary_lock parser uses the 5th bit of the 7th byte too, thus the confusion.

I was confused by it too, but since it seems that 3-5 bits do correctly parsed into lock status it should be just a rearrange.

@schummar
Copy link

schummar commented Jul 8, 2024

According to the website, the Pro does not support Dual Lock (yet?): https://support.switch-bot.com/hc/en-us/articles/22917404813207-Can-Two-SwitchBot-Lock-Pro-Devices-Be-Set-up-for-Dual-Lock
I have two EU Lock Pros and there is indeed no option in the app.

I have found two issues with the current state, which might be solved by this PR, or maybe there is something else missing:

I'm happy to assist with testing or might try a fix myself, if I have the time.

@jsprotky
Copy link

jsprotky commented Jul 8, 2024

When the lock is not locked, but not unlatched either, it's always displaying as "Unlocking" in HA.

Had the same issue and this is now solved with this PR.

@jsprotky
Copy link

jsprotky commented Jul 8, 2024

The lock is not displayed as having the unlock without unlatch option in HA. Apparently for that the device has to have the LockEntityFeature.OPEN flag set.

I had this as well but it got fixed at some point. My lock did not have the door sensor attached at first. Once I added that and ran a re-calibration, HA picked up the lock as being a European lock with latch. This was prior to this PR.

- thus mark both field as False at all time
@jsprotky
Copy link

jsprotky commented Jul 8, 2024

@szclsya So I guess this PR is not a draft anymore but rather finalized.

res = {
"battery": data[2] & 0b01111111 if data else None,
"calibration": bool(mfr_data[7] & 0b10000000),
"status": LockStatus(int(mfr_data[7] & 0b00111000) / 8),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't >> 3 instead of / 8 more clearly convey what is happening here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah it was some leftover of debugging to see if they changed how the lock status is encoded (thankfully they didn't). I'll change it to >>3.

@szclsya szclsya marked this pull request as ready for review July 8, 2024 23:54
@szclsya
Copy link
Contributor Author

szclsya commented Jul 9, 2024

The new manual field seems to be either bugged or I misunderstood the flag, as it shows true even if the lock is locked by auto lock. Should we still keep it there?

@mwolter805
Copy link

@szclsya do you know if the integration can detect the state of both batteries when using the rechargeable Dual Power Pack? The app does report each separately. Please let me know if you need any info.
IMG_0458

@szclsya
Copy link
Contributor Author

szclsya commented Jul 9, 2024

@mwolter805 As mentioned in the issue please provide passive scan data.

But I doubt this data is actually sent passively. It's more likely to be a response of a active mode command.

@ollo69
Copy link

ollo69 commented Jul 9, 2024

do you know if the integration can detect the state of both batteries when using the rechargeable Dual Power Pack? The app does report each separately. Please let me know if you need any info.

I already tried to search this info in the passive data but I didn't find any related information as I reported here. Obviously would be great if I'm wrong 😉

@mwolter805
Copy link

mwolter805 commented Jul 10, 2024

@szclsya Please forgive my ignorance, can I create and run that python script in the home assistant container?

Edit: I believe I was able to grab the logs through the debug command in the HA integration

Battery A 100%, Battery B Removed

Locked from App

2024-07-09 18:45:32.079 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 079200640000
2024-07-09 18:45:32.079 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248064
2024-07-09 18:45:32.079 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 100, 'calibration': True, 'status': <LockStatus.LOCKED: 0>, 'update_from_secondary_lock': True, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': False, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}
2024-07-09 18:45:33.876 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 088200640000
2024-07-09 18:45:33.876 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248064
2024-07-09 18:45:33.876 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 100, 'calibration': True, 'status': <LockStatus.UNLOCKED: 1>, 'update_from_secondary_lock': False, 'door_open': False, 'double_lock_mode': False, 'unclosed_alarm': False, 'unlocked_alarm': False, 'auto_lock_paused': False, 'night_latch': False, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}

Unlocked from App

2024-07-09 18:46:02.020 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 099a00640000
2024-07-09 18:46:02.020 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248064
2024-07-09 18:46:02.020 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 100, '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': False, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}
2024-07-09 18:46:02.144 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 0a9a00640000
2024-07-09 18:46:02.144 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248064
2024-07-09 18:46:02.144 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 100, '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': False, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}

Battery B 99%, Battery A removed

Locked from App

2024-07-09 18:56:32.178 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 099200630000
2024-07-09 18:56:32.178 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 18:56:32.178 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, 'calibration': True, 'status': <LockStatus.LOCKED: 0>, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}
2024-07-09 18:56:33.460 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 0a8200630000
2024-07-09 18:56:33.460 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 18:56:33.460 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, 'calibration': True, 'status': <LockStatus.UNLOCKED: 1>, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}

Unlocked from App

2024-07-09 18:57:02.049 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 0b9a00630000
2024-07-09 18:57:02.049 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 18:57:02.049 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}
2024-07-09 18:57:03.583 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 0c8a00630000
2024-07-09 18:57:03.583 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 18:57:03.583 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC: Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}

Battery A 100%, Battery B 99%

Locked from App

2024-07-09 19:07:02.004 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 0e9200630000
2024-07-09 19:07:02.004 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 19:07:02.004 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC : Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, 'calibration': True, 'status': <LockStatus.LOCKED: 0>, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}
2024-07-09 19:07:03.519 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 0f8200630000
2024-07-09 19:07:03.519 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 19:07:03.519 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC : Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, 'calibration': True, 'status': <LockStatus.UNLOCKED: 1>, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}

Unlocked from App

2024-07-09 19:07:32.041 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 109a00630000
2024-07-09 19:07:32.041 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 19:07:32.041 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC : Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}
2024-07-09 19:07:33.266 DEBUG (MainThread) [switchbot.adv_parsers.lock] mfr_data: MAC 118a00630000
2024-07-09 19:07:33.266 DEBUG (MainThread) [switchbot.adv_parsers.lock] data: 248063
2024-07-09 19:07:33.267 DEBUG (MainThread) [homeassistant.components.switchbot.coordinator] MAC : Switchbot data: {'rawAdvData': b'$\x80d', 'data': {'battery': 99, '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, 'firmware': 1.9}, 'model': '$', 'isEncrypted': False, 'modelFriendlyName': 'Lock Pro', 'modelName': <SwitchbotModel.LOCK_PRO: 'WoLockPro'>}

@szclsya
Copy link
Contributor Author

szclsya commented Jul 10, 2024

@mwolter805 Just as @ollo69 speculated the detailed battery info is indeed not sent in passive mode, so I'd assume there's a separate active mode command to check these information.

Anyhow it will be out of scope of this PR (since it's about paring passive mode data). Maybe open a separate issue or asking in the general Lock Pro issue?

@bdraco
Copy link
Member

bdraco commented Jul 10, 2024

Any more changes, or is this ready to merge?

@szclsya
Copy link
Contributor Author

szclsya commented Jul 11, 2024

@bdraco Not sure if we should add the manual field (it's incorrect when locked by auto lock) but other than that we should be good.

@bdraco
Copy link
Member

bdraco commented Jul 11, 2024

@bdraco Not sure if we should add the manual field (it's incorrect when locked by auto lock) but other than that we should be good.

I'd keep it out for now unless its strictly needed for HA

- as it's not needed by HA for now and is actually inaccurate
@szclsya
Copy link
Contributor Author

szclsya commented Jul 11, 2024

@bdraco All good now then.

@bdraco bdraco merged commit 40f58c3 into sblibs:master Jul 11, 2024
3 checks passed
@bdraco
Copy link
Member

bdraco commented Jul 11, 2024

0.48.0...0.48.1

@bdraco
Copy link
Member

bdraco commented Jul 11, 2024

This could also use a test with a few different advertisements so we know it won't break in the future.

@szclsya
Copy link
Contributor Author

szclsya commented Jul 11, 2024

@bdraco True. Will add some in another PR when I have time.

@ollo69
Copy link

ollo69 commented Jul 11, 2024

@szclsya,

if you don't have time I can create bump PR in HA for you, let me know.?

@szclsya
Copy link
Contributor Author

szclsya commented Jul 11, 2024

@ollo69 Yeah sure, go ahead!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants