mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 11:43:34 +00:00
a01247d48f
Python 3.11 ships with latest Debian Bookworm. pypy is not that widely used with this library based on statistics. It could be added back when pypy supports python 3.11.
91 lines
3.0 KiB
Python
91 lines
3.0 KiB
Python
"""Implementation of time module."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime, tzinfo
|
|
from typing import cast
|
|
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
|
|
from ...cachedzoneinfo import CachedZoneInfo
|
|
from ...feature import Feature
|
|
from ...interfaces import Time as TimeInterface
|
|
from ..smartcameramodule import SmartCameraModule
|
|
|
|
|
|
class Time(SmartCameraModule, TimeInterface):
|
|
"""Implementation of device_local_time."""
|
|
|
|
QUERY_GETTER_NAME = "getTimezone"
|
|
QUERY_MODULE_NAME = "system"
|
|
QUERY_SECTION_NAMES = "basic"
|
|
|
|
_timezone: tzinfo = UTC
|
|
_time: datetime
|
|
|
|
def _initialize_features(self) -> None:
|
|
"""Initialize features after the initial update."""
|
|
self._add_feature(
|
|
Feature(
|
|
device=self._device,
|
|
id="device_time",
|
|
name="Device time",
|
|
attribute_getter="time",
|
|
container=self,
|
|
category=Feature.Category.Debug,
|
|
type=Feature.Type.Sensor,
|
|
)
|
|
)
|
|
|
|
def query(self) -> dict:
|
|
"""Query to execute during the update cycle."""
|
|
q = super().query()
|
|
q["getClockStatus"] = {self.QUERY_MODULE_NAME: {"name": "clock_status"}}
|
|
|
|
return q
|
|
|
|
async def _post_update_hook(self) -> None:
|
|
"""Perform actions after a device update."""
|
|
time_data = self.data["getClockStatus"]["system"]["clock_status"]
|
|
timezone_data = self.data["getTimezone"]["system"]["basic"]
|
|
zone_id = timezone_data["zone_id"]
|
|
timestamp = time_data["seconds_from_1970"]
|
|
try:
|
|
# Zoneinfo will return a DST aware object
|
|
tz: tzinfo = await CachedZoneInfo.get_cached_zone_info(zone_id)
|
|
except ZoneInfoNotFoundError:
|
|
# timezone string like: UTC+10:00
|
|
timezone_str = timezone_data["timezone"]
|
|
tz = cast(tzinfo, datetime.strptime(timezone_str[-6:], "%z").tzinfo)
|
|
|
|
self._timezone = tz
|
|
self._time = datetime.fromtimestamp(
|
|
cast(float, timestamp),
|
|
tz=tz,
|
|
)
|
|
|
|
@property
|
|
def timezone(self) -> tzinfo:
|
|
"""Return current timezone."""
|
|
return self._timezone
|
|
|
|
@property
|
|
def time(self) -> datetime:
|
|
"""Return device's current datetime."""
|
|
return self._time
|
|
|
|
async def set_time(self, dt: datetime) -> dict:
|
|
"""Set device time."""
|
|
if not dt.tzinfo:
|
|
timestamp = dt.replace(tzinfo=self.timezone).timestamp()
|
|
else:
|
|
timestamp = dt.timestamp()
|
|
|
|
lt = datetime.fromtimestamp(timestamp).isoformat().replace("T", " ")
|
|
params = {"seconds_from_1970": int(timestamp), "local_time": lt}
|
|
# Doesn't seem to update the time, perhaps because timing_mode is ntp
|
|
res = await self.call("setTimezone", {"system": {"clock_status": params}})
|
|
if (zinfo := dt.tzinfo) and isinstance(zinfo, ZoneInfo):
|
|
tz_params = {"zone_id": zinfo.key}
|
|
res = await self.call("setTimezone", {"system": {"basic": tz_params}})
|
|
return res
|