|
@@ -16,15 +16,28 @@ from ..const import (
|
|
|
SwitchbotAccountConnectionError,
|
|
|
SwitchbotApiError,
|
|
|
SwitchbotAuthenticationError,
|
|
|
+ SwitchbotModel,
|
|
|
)
|
|
|
from .device import SwitchbotDevice, SwitchbotOperationError
|
|
|
|
|
|
COMMAND_HEADER = "57"
|
|
|
COMMAND_GET_CK_IV = f"{COMMAND_HEADER}0f2103"
|
|
|
-COMMAND_LOCK_INFO = f"{COMMAND_HEADER}0f4f8101"
|
|
|
-COMMAND_UNLOCK = f"{COMMAND_HEADER}0f4e01011080"
|
|
|
-COMMAND_UNLOCK_WITHOUT_UNLATCH = f"{COMMAND_HEADER}0f4e010110a0"
|
|
|
-COMMAND_LOCK = f"{COMMAND_HEADER}0f4e01011000"
|
|
|
+COMMAND_LOCK_INFO = {
|
|
|
+ SwitchbotModel.LOCK: f"{COMMAND_HEADER}0f4f8101",
|
|
|
+ SwitchbotModel.LOCK_PRO: f"{COMMAND_HEADER}0f4f8102",
|
|
|
+}
|
|
|
+COMMAND_UNLOCK = {
|
|
|
+ SwitchbotModel.LOCK: f"{COMMAND_HEADER}0f4e01011080",
|
|
|
+ SwitchbotModel.LOCK_PRO: f"{COMMAND_HEADER}0f4e0101000080",
|
|
|
+}
|
|
|
+COMMAND_UNLOCK_WITHOUT_UNLATCH = {
|
|
|
+ SwitchbotModel.LOCK: f"{COMMAND_HEADER}0f4e010110a0",
|
|
|
+ SwitchbotModel.LOCK_PRO: f"{COMMAND_HEADER}0f4e01010000a0",
|
|
|
+}
|
|
|
+COMMAND_LOCK = {
|
|
|
+ SwitchbotModel.LOCK: f"{COMMAND_HEADER}0f4e01011000",
|
|
|
+ SwitchbotModel.LOCK_PRO: f"{COMMAND_HEADER}0f4e0101000000",
|
|
|
+}
|
|
|
COMMAND_ENABLE_NOTIFICATIONS = f"{COMMAND_HEADER}0e01001e00008101"
|
|
|
COMMAND_DISABLE_NOTIFICATIONS = f"{COMMAND_HEADER}0e00"
|
|
|
|
|
@@ -49,6 +62,7 @@ class SwitchbotLock(SwitchbotDevice):
|
|
|
key_id: str,
|
|
|
encryption_key: str,
|
|
|
interface: int = 0,
|
|
|
+ model: SwitchbotModel = SwitchbotModel.LOCK,
|
|
|
**kwargs: Any,
|
|
|
) -> None:
|
|
|
if len(key_id) == 0:
|
|
@@ -59,20 +73,27 @@ class SwitchbotLock(SwitchbotDevice):
|
|
|
raise ValueError("encryption_key is missing")
|
|
|
elif len(encryption_key) != 32:
|
|
|
raise ValueError("encryption_key is invalid")
|
|
|
+ if model not in (SwitchbotModel.LOCK, SwitchbotModel.LOCK_PRO):
|
|
|
+ raise ValueError("initializing SwitchbotLock with a non-lock model")
|
|
|
self._iv = None
|
|
|
self._cipher = None
|
|
|
self._key_id = key_id
|
|
|
self._encryption_key = bytearray.fromhex(encryption_key)
|
|
|
self._notifications_enabled: bool = False
|
|
|
+ self._model: SwitchbotModel = model
|
|
|
super().__init__(device, None, interface, **kwargs)
|
|
|
|
|
|
@staticmethod
|
|
|
async def verify_encryption_key(
|
|
|
- device: BLEDevice, key_id: str, encryption_key: str
|
|
|
+ device: BLEDevice,
|
|
|
+ key_id: str,
|
|
|
+ encryption_key: str,
|
|
|
+ model: SwitchbotModel = SwitchbotModel.LOCK,
|
|
|
+ **kwargs: Any,
|
|
|
) -> bool:
|
|
|
try:
|
|
|
lock = SwitchbotLock(
|
|
|
- device=device, key_id=key_id, encryption_key=encryption_key
|
|
|
+ device, key_id=key_id, encryption_key=encryption_key, model=model
|
|
|
)
|
|
|
except ValueError:
|
|
|
return False
|
|
@@ -183,19 +204,19 @@ class SwitchbotLock(SwitchbotDevice):
|
|
|
async def lock(self) -> bool:
|
|
|
"""Send lock command."""
|
|
|
return await self._lock_unlock(
|
|
|
- COMMAND_LOCK, {LockStatus.LOCKED, LockStatus.LOCKING}
|
|
|
+ COMMAND_LOCK[self._model], {LockStatus.LOCKED, LockStatus.LOCKING}
|
|
|
)
|
|
|
|
|
|
async def unlock(self) -> bool:
|
|
|
"""Send unlock command. If unlatch feature is enabled in EU firmware, also unlatches door"""
|
|
|
return await self._lock_unlock(
|
|
|
- COMMAND_UNLOCK, {LockStatus.UNLOCKED, LockStatus.UNLOCKING}
|
|
|
+ COMMAND_UNLOCK[self._model], {LockStatus.UNLOCKED, LockStatus.UNLOCKING}
|
|
|
)
|
|
|
|
|
|
async def unlock_without_unlatch(self) -> bool:
|
|
|
"""Send unlock command. This command will not unlatch the door."""
|
|
|
return await self._lock_unlock(
|
|
|
- COMMAND_UNLOCK_WITHOUT_UNLATCH,
|
|
|
+ COMMAND_UNLOCK_WITHOUT_UNLATCH[self._model],
|
|
|
{LockStatus.UNLOCKED, LockStatus.UNLOCKING, LockStatus.NOT_FULLY_LOCKED},
|
|
|
)
|
|
|
|
|
@@ -275,7 +296,9 @@ class SwitchbotLock(SwitchbotDevice):
|
|
|
|
|
|
async def _get_lock_info(self) -> bytes | None:
|
|
|
"""Return lock info of device."""
|
|
|
- _data = await self._send_command(key=COMMAND_LOCK_INFO, retry=self._retry_count)
|
|
|
+ _data = await self._send_command(
|
|
|
+ key=COMMAND_LOCK_INFO[self._model], retry=self._retry_count
|
|
|
+ )
|
|
|
|
|
|
if not self._check_command_result(_data, 0, COMMAND_RESULT_EXPECTED_VALUES):
|
|
|
_LOGGER.error("Unsuccessful, please try again")
|