From dfaeb382da1b64dd47abe6a0f708f2af3cbcdcfa Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Wed, 26 Nov 2025 21:53:56 +0000 Subject: [PATCH] Add an additional last updated diagnostic sensor for devices --- .../oasis_mini/pyoasiscontrol/device.py | 7 +++++++ custom_components/oasis_mini/sensor.py | 12 +++++++++++- custom_components/oasis_mini/strings.json | 3 +++ custom_components/oasis_mini/translations/en.json | 3 +++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/custom_components/oasis_mini/pyoasiscontrol/device.py b/custom_components/oasis_mini/pyoasiscontrol/device.py index 65bd6c2..d032671 100644 --- a/custom_components/oasis_mini/pyoasiscontrol/device.py +++ b/custom_components/oasis_mini/pyoasiscontrol/device.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +from datetime import datetime import logging from typing import TYPE_CHECKING, Any, Callable, Final, Iterable @@ -21,6 +22,7 @@ from .utils import ( create_svg, decrypt_svg_content, get_image_url_from_track, + now, ) if TYPE_CHECKING: # avoid runtime circular imports @@ -140,6 +142,9 @@ class OasisDevice: self._track: dict | None = None self._track_task: asyncio.Task | None = None + # Diagnostic metadata + self.last_updated: datetime | None = None + @property def brightness(self) -> int: """ @@ -259,6 +264,8 @@ class OasisDevice: if changed: self._notify_listeners() + self.last_updated = now() + def parse_status_string(self, raw_status: str) -> dict[str, Any] | None: """ Parse a semicolon-separated device status string into a structured state dictionary. diff --git a/custom_components/oasis_mini/sensor.py b/custom_components/oasis_mini/sensor.py index 1a1ec57..a773dbf 100644 --- a/custom_components/oasis_mini/sensor.py +++ b/custom_components/oasis_mini/sensor.py @@ -2,7 +2,10 @@ from __future__ import annotations +from datetime import datetime + from homeassistant.components.sensor import ( + SensorDeviceClass, SensorEntity, SensorEntityDescription, SensorStateClass, @@ -68,6 +71,13 @@ DESCRIPTORS = [ state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, ), + SensorEntityDescription( + key="last_updated", + translation_key="last_updated", + device_class=SensorDeviceClass.TIMESTAMP, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), ] DESCRIPTORS.extend( SensorEntityDescription( @@ -84,7 +94,7 @@ class OasisDeviceSensorEntity(OasisDeviceEntity, SensorEntity): """Oasis device sensor entity.""" @property - def native_value(self) -> str | None: + def native_value(self) -> str | int | float | datetime | None: """ Provide the current sensor value from the underlying device. diff --git a/custom_components/oasis_mini/strings.json b/custom_components/oasis_mini/strings.json index 36a0bec..ee0ceb5 100755 --- a/custom_components/oasis_mini/strings.json +++ b/custom_components/oasis_mini/strings.json @@ -125,6 +125,9 @@ "18": "Error while downloading the job file" } }, + "last_updated": { + "name": "Last updated" + }, "led_color_id": { "name": "LED color ID" }, diff --git a/custom_components/oasis_mini/translations/en.json b/custom_components/oasis_mini/translations/en.json index b0450f9..074bf7a 100755 --- a/custom_components/oasis_mini/translations/en.json +++ b/custom_components/oasis_mini/translations/en.json @@ -125,6 +125,9 @@ "18": "Error while downloading the job file" } }, + "last_updated": { + "name": "Last updated" + }, "led_color_id": { "name": "LED color ID" },