From 7b3bbe1c0650e79f6774f5f7afe254fb15a841e3 Mon Sep 17 00:00:00 2001 From: Shaun Tarves Date: Sun, 2 May 2021 12:03:46 -0400 Subject: [PATCH] Fixed issue with lock state reporting, fixed issue with vacuum battery reporting [Closes #9], added debug logging --- wyze_sdk/models/devices/base.py | 17 ++++++++--- wyze_sdk/models/devices/locks.py | 51 +++++++++++++++++++++++++------ wyze_sdk/models/devices/scales.py | 2 +- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/wyze_sdk/models/devices/base.py b/wyze_sdk/models/devices/base.py index f42d96f..c25b1e7 100644 --- a/wyze_sdk/models/devices/base.py +++ b/wyze_sdk/models/devices/base.py @@ -119,6 +119,8 @@ def __init__( self._ts = ts elif ts is not None: self._ts = epoch_to_datetime(ts, ms=True) + else: + self._ts = None if value is not None and not isinstance(value, self._definition.type): try: value = bool(distutils.util.strtobool(str(value))) if self._definition.type == bool else self._definition._type(value) @@ -321,20 +323,25 @@ def _extract_property(self, prop_def: Union[str, PropDef], others: Union[dict, S if isinstance(others, dict): if 'data' in others and 'property_list' in others['data']: + self.logger.debug("found non-empty data property_list") return self._extract_property(prop_def=prop_def, others=others['data']) - if 'props' in others: + if 'props' in others and others['props']: + self.logger.debug("found non-empty props") return self._extract_property(prop_def=prop_def, others=others['props']) - if 'property_list' in others: + if 'property_list' in others and others['property_list']: + self.logger.debug("found non-empty property_list") return self._extract_property(prop_def=prop_def, others=others['property_list']) - if 'device_params' in others: + if 'device_params' in others and others['device_params']: + self.logger.debug("found non-empty device_params") return self._extract_property(prop_def=prop_def, others=others['device_params']) - self.logger.debug(prop_def.pid) + self.logger.debug(f"extracting property {prop_def.pid} from dict {others}") for key, value in others.items(): self.logger.debug(f"key: {key}, value: {value}") if key == prop_def.pid: self.logger.debug(f"returning new DeviceProp with value {value}") return DeviceProp(definition=prop_def, value=value) else: + self.logger.debug(f"extracting property {prop_def.pid} from {others.__class__} {others}") for value in others: self.logger.debug(f"value {value}") if "pid" in value and prop_def.pid == value["pid"]: @@ -365,6 +372,8 @@ def __init__( ): super().__init__(type=type, **others) self._ip = ip if ip else super()._extract_attribute('ip', others) + if not self._ip: + super()._extract_attribute('ipaddr', others) @property def ip(self) -> str: diff --git a/wyze_sdk/models/devices/locks.py b/wyze_sdk/models/devices/locks.py index c755dea..9311540 100644 --- a/wyze_sdk/models/devices/locks.py +++ b/wyze_sdk/models/devices/locks.py @@ -8,7 +8,7 @@ show_unknown_key_warning) from .base import (AbstractWirelessNetworkedDevice, ContactMixin, Device, - DeviceModels, LockableMixin) + DeviceModels, DeviceProp, LockableMixin, VoltageMixin) class LockProps(object): @@ -16,6 +16,14 @@ class LockProps(object): :meta private: """ + @classmethod + def locker_lock_state(cls) -> PropDef: + return PropDef("hardlock", bool, int) + + @classmethod + def locker_open_close_state(cls) -> PropDef: + return PropDef("door", bool, int) + @classmethod def lock_state(cls) -> PropDef: return PropDef("switch_state", bool, int) @@ -24,6 +32,10 @@ def lock_state(cls) -> PropDef: def open_close_state(cls) -> PropDef: return PropDef("open_close_state", bool, int) + @classmethod + def voltage(cls) -> PropDef: + return PropDef("power", int) + class LockEventType(Enum): """ @@ -237,7 +249,7 @@ def type(self, value: Union[int, LockEventType]): self._type = value -class Lock(LockableMixin, ContactMixin, Device): +class Lock(LockableMixin, ContactMixin, VoltageMixin, Device): type = "Lock" @@ -267,12 +279,38 @@ def __init__( super().__init__(type=self.type, **others) if self.mac is not None: self._uuid = Lock.parse_uuid(self.mac) - self.lock_state = super()._extract_property(LockProps.lock_state(), others) - self.open_close_state = super()._extract_property(LockProps.open_close_state(), others) + self.lock_state = self._extract_lock_state(others) + self.open_close_state = self._extract_open_close_state(others) + self.voltage = self._extract_property(prop_def=LockProps.voltage(), others=others) self._parent = parent if parent is not None else super()._extract_attribute("parent", others) self._record_count = record_count if record_count is not None else super()._extract_attribute("record_count", others) show_unknown_key_warning(self, others) + def _extract_lock_state(self, others: Union[dict, Sequence[dict]]) -> DeviceProp: + if "device_params" in others and "locker_status" in others["device_params"]: + self.logger.debug("found non-empty locker_status") + prop_def = LockProps.locker_lock_state() + value = super()._extract_property(prop_def=prop_def, others=others["device_params"]["locker_status"]) + ts = super()._extract_attribute(name=prop_def.pid + "_refreshtime", others=others["device_params"]["locker_status"]) + self.logger.debug(f"returning new DeviceProp with {value}") + return DeviceProp(definition=prop_def, ts=ts, value=value.value) + # if switch_state == 1, device is UNlocked so we have to flip the bit + prop = super()._extract_property(prop_def=LockProps.lock_state(), others=others) + return DeviceProp(definition=prop.definition, ts=prop.ts, value=not prop.value) + + def _extract_open_close_state(self, others: Union[dict, Sequence[dict]]) -> DeviceProp: + if "device_params" in others and "locker_status" in others["device_params"]: + self.logger.debug("found non-empty locker_status") + prop_def = LockProps.locker_open_close_state() + value = super()._extract_property(prop_def=prop_def, others=others["device_params"]["locker_status"]) + ts = super()._extract_attribute(name=prop_def.pid + "_refreshtime", others=others["device_params"]["locker_status"]) + self.logger.debug(f"returning new DeviceProp with {value}") + # door: 1 = open, 2 = closed, 255 = some unknown value + return DeviceProp(definition=prop_def, ts=ts, value=value == 1) + # open_close_state: 1 = closed 0 = open + prop = super()._extract_property(prop_def=LockProps.open_close_state(), others=others) + return DeviceProp(definition=prop.definition, ts=prop.ts, value=not prop.value) + @property def parent(self) -> str: return self._parent @@ -281,11 +319,6 @@ def parent(self) -> str: def record_count(self) -> int: return self._record_count - @property - def is_locked(self) -> bool: - # locks use switch_state = 0 to indicate locked - return not self.lock_state - class LockGateway(AbstractWirelessNetworkedDevice): diff --git a/wyze_sdk/models/devices/scales.py b/wyze_sdk/models/devices/scales.py index f55e13f..fd280b8 100644 --- a/wyze_sdk/models/devices/scales.py +++ b/wyze_sdk/models/devices/scales.py @@ -158,7 +158,7 @@ def __init__( class Scale(AbstractWirelessNetworkedDevice): - type = "Scale" + type = "WyzeScale" @property def attributes(self) -> Set[str]: