diff --git a/kasa/smart/modules/devicemodule.py b/kasa/smart/modules/devicemodule.py index 1d2b64f2..89c87c20 100644 --- a/kasa/smart/modules/devicemodule.py +++ b/kasa/smart/modules/devicemodule.py @@ -23,7 +23,8 @@ class DeviceModule(SmartModule): "get_device_info": None, } # Device usage is not available on older firmware versions - if self.supported_version >= 2: + # or child devices of hubs + if self.supported_version >= 2 and not self._device._is_hub_child: query["get_device_usage"] = None return query diff --git a/kasa/smart/modules/time.py b/kasa/smart/modules/time.py index c182b8af..cac01d73 100644 --- a/kasa/smart/modules/time.py +++ b/kasa/smart/modules/time.py @@ -83,3 +83,12 @@ class Time(SmartModule, TimeInterface): if region: params["region"] = region return await self.call("set_device_time", params) + + async def _check_supported(self): + """Additional check to see if the module is supported by the device. + + Hub attached sensors report the time module but do return device time. + """ + if self._device._is_hub_child: + return False + return await super()._check_supported() diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 095156e3..0a8c136c 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -457,6 +457,11 @@ class SmartDevice(Device): for child in self._children.values(): await child._initialize_features() + @property + def _is_hub_child(self) -> bool: + """Returns true if the device is a child of a hub.""" + return self.parent is not None and self.parent.device_type is DeviceType.Hub + @property def is_cloud_connected(self) -> bool: """Returns if the device is connected to the cloud.""" @@ -485,8 +490,8 @@ class SmartDevice(Device): @property def time(self) -> datetime: """Return the time.""" - if (self._parent and (time_mod := self._parent.modules.get(Module.Time))) or ( - time_mod := self.modules.get(Module.Time) + if (time_mod := self.modules.get(Module.Time)) or ( + self._parent and (time_mod := self._parent.modules.get(Module.Time)) ): return time_mod.time diff --git a/kasa/tests/test_childdevice.py b/kasa/tests/test_childdevice.py index 251af878..797e8dff 100644 --- a/kasa/tests/test_childdevice.py +++ b/kasa/tests/test_childdevice.py @@ -1,7 +1,9 @@ import inspect import sys +from datetime import datetime, timezone import pytest +from freezegun.api import FrozenDateTimeFactory from kasa import Device from kasa.device_type import DeviceType @@ -120,3 +122,15 @@ async def test_parent_property(dev: Device): assert dev.parent is None for child in dev.children: assert child.parent == dev + + +@has_children_smart +async def test_child_time(dev: Device, freezer: FrozenDateTimeFactory): + """Test a child device gets the time from it's parent module.""" + if not dev.children: + pytest.skip(f"Device {dev} fixture does not have any children") + + fallback_time = datetime.now(timezone.utc).astimezone().replace(microsecond=0) + assert dev.parent is None + for child in dev.children: + assert child.time != fallback_time