diff --git a/README.md b/README.md index 0c9c89e..e9881b3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Your state stays on your LAN: HA talks to the appliance over a direct DTLS sessi | Air purifier | `by_type/air_purifier.py` | | Dehumidifier | `by_type/dehumidifier.py` | | Dryer | `by_type/dryer.py` | -| Oven | `by_type/oven.py` | +| Oven (including combi microwaves) | `by_type/oven.py` | | Gas cooktop (read-only burner status) | `by_type/cooktop.py` | | Range hood | `by_type/range_hood.py` | | Range | `by_type/range.py` | @@ -33,6 +33,7 @@ Your state stays on your LAN: HA talks to the appliance over a direct DTLS sessi | Refrigerator | `by_type/refrigerator.py` | | Washer | `by_type/washer.py` | | Water purifier | `by_type/water_purifier.py` | +| Vacuum clean/auto-empty station | `by_type/vacuum_station.py` | Each registry composes shared and family-specific `Capability` objects from `registry/capabilities/`; those modules document the individual resources/entities in more depth than a README table can stay current with. diff --git a/custom_components/localthings/registry/capabilities/common.py b/custom_components/localthings/registry/capabilities/common.py index 9d519ff..cd03a91 100644 --- a/custom_components/localthings/registry/capabilities/common.py +++ b/custom_components/localthings/registry/capabilities/common.py @@ -10,6 +10,8 @@ against live device dumps: /water/consumption/vs/0 -> x.com.samsung.da.cumulativeWater /filter/waterfilter/vs/0 -> x.com.samsung.da.filterUsage / filterStatus """ +from datetime import datetime, timezone + from ..capability import Capability from ..entities import ( BinarySensorDesc, ButtonDesc, SelectDesc, SensorDesc, SwitchDesc, @@ -40,6 +42,22 @@ def wh_to_kwh(v): return round(n / 1000.0, 2) if n is not None else None +def parse_iso_utc(raw): + """ISO datetime defaulting to UTC when the string carries no timezone + of its own (this integration's convention for other bare ISO datetime + fields -- see washer.py's drum-clean-log comment). A few boards do + ship a 'Z'/offset suffix (fromisoformat parses that natively since + Python 3.11) -- only fill in UTC when parsing left the result naive, + rather than unconditionally overwriting whatever offset was parsed.""" + if not raw: + return None + try: + dt = datetime.fromisoformat(raw) + except ValueError: + return None + return dt if dt.tzinfo is not None else dt.replace(tzinfo=timezone.utc) + + def filter_usage_percent(rep): """Filter usage as a percentage of rated capacity. Several families (AC, air purifier) report `filterUsage` as a raw count in diff --git a/custom_components/localthings/registry/capabilities/vacuum_station.py b/custom_components/localthings/registry/capabilities/vacuum_station.py index d4b5287..090ed88 100644 --- a/custom_components/localthings/registry/capabilities/vacuum_station.py +++ b/custom_components/localthings/registry/capabilities/vacuum_station.py @@ -15,23 +15,9 @@ docstring for that rule). Resources verified against the issue #131 diagnostics dump. """ -from datetime import datetime, timezone - from ..capability import Capability from ..entities import BinarySensorDesc, SelectDesc, SensorDesc, SwitchDesc -from .common import int_or_none - - -def _parse_iso_utc(raw): - """Bare ISO datetime with no timezone field alongside it -- treated as - UTC, matching this integration's convention for other bare ISO datetime - fields (see water_purifier.py's own _parse_iso_utc).""" - if not raw: - return None - try: - return datetime.fromisoformat(raw).replace(tzinfo=timezone.utc) - except ValueError: - return None +from .common import int_or_none, parse_iso_utc as _parse_iso_utc DUSTBAG = Capability( diff --git a/custom_components/localthings/registry/capabilities/water_purifier.py b/custom_components/localthings/registry/capabilities/water_purifier.py index ef287cb..953cd3d 100644 --- a/custom_components/localthings/registry/capabilities/water_purifier.py +++ b/custom_components/localthings/registry/capabilities/water_purifier.py @@ -3,23 +3,9 @@ issue #90, model TP2X_WATERPURIFIER_20K). Resources verified against the issue #90 diagnostics dump. """ -from datetime import datetime, timezone - from ..capability import Capability from ..entities import BinarySensorDesc, NumberDesc, SelectDesc, SensorDesc, SwitchDesc -from .common import int_or_none - - -def _parse_iso_utc(raw): - """Bare ISO datetime with no timezone field alongside it -- treated as - UTC, matching this integration's convention for other bare ISO datetime - fields (see washer.py's drum-clean-log comment).""" - if not raw: - return None - try: - return datetime.fromisoformat(raw).replace(tzinfo=timezone.utc) - except ValueError: - return None +from .common import int_or_none, parse_iso_utc as _parse_iso_utc DISPENSE = Capability(