Add Tractive `sleep` and `activity` sensors (#98575)
* Add sleep and activity sensors * Use device class ENUM * Default value for value_fnpull/98682/head
parent
8a6bde1191
commit
66c10facfa
|
@ -23,6 +23,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from .const import (
|
||||
ATTR_ACTIVITY_LABEL,
|
||||
ATTR_BUZZER,
|
||||
ATTR_CALORIES,
|
||||
ATTR_DAILY_GOAL,
|
||||
|
@ -32,6 +33,7 @@ from .const import (
|
|||
ATTR_MINUTES_DAY_SLEEP,
|
||||
ATTR_MINUTES_NIGHT_SLEEP,
|
||||
ATTR_MINUTES_REST,
|
||||
ATTR_SLEEP_LABEL,
|
||||
ATTR_TRACKER_STATE,
|
||||
CLIENT,
|
||||
CLIENT_ID,
|
||||
|
@ -281,10 +283,12 @@ class TractiveClient:
|
|||
|
||||
def _send_wellness_update(self, event: dict[str, Any]) -> None:
|
||||
payload = {
|
||||
ATTR_ACTIVITY_LABEL: event["wellness"]["activity_label"],
|
||||
ATTR_CALORIES: event["activity"]["calories"],
|
||||
ATTR_MINUTES_DAY_SLEEP: event["sleep"]["minutes_day_sleep"],
|
||||
ATTR_MINUTES_NIGHT_SLEEP: event["sleep"]["minutes_night_sleep"],
|
||||
ATTR_MINUTES_REST: event["activity"]["minutes_rest"],
|
||||
ATTR_SLEEP_LABEL: event["wellness"]["sleep_label"],
|
||||
}
|
||||
self._dispatch_tracker_event(
|
||||
TRACKER_WELLNESS_STATUS_UPDATED, event["pet_id"], payload
|
||||
|
|
|
@ -6,6 +6,7 @@ DOMAIN = "tractive"
|
|||
|
||||
RECONNECT_INTERVAL = timedelta(seconds=10)
|
||||
|
||||
ATTR_ACTIVITY_LABEL = "activity_label"
|
||||
ATTR_BUZZER = "buzzer"
|
||||
ATTR_CALORIES = "calories"
|
||||
ATTR_DAILY_GOAL = "daily_goal"
|
||||
|
@ -15,6 +16,7 @@ ATTR_MINUTES_ACTIVE = "minutes_active"
|
|||
ATTR_MINUTES_DAY_SLEEP = "minutes_day_sleep"
|
||||
ATTR_MINUTES_NIGHT_SLEEP = "minutes_night_sleep"
|
||||
ATTR_MINUTES_REST = "minutes_rest"
|
||||
ATTR_SLEEP_LABEL = "sleep_label"
|
||||
ATTR_TRACKER_STATE = "tracker_state"
|
||||
|
||||
# This client ID was issued by Tractive specifically for Home Assistant.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Support for Tractive sensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
@ -19,15 +20,18 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from . import Trackables, TractiveClient
|
||||
from .const import (
|
||||
ATTR_ACTIVITY_LABEL,
|
||||
ATTR_CALORIES,
|
||||
ATTR_DAILY_GOAL,
|
||||
ATTR_MINUTES_ACTIVE,
|
||||
ATTR_MINUTES_DAY_SLEEP,
|
||||
ATTR_MINUTES_NIGHT_SLEEP,
|
||||
ATTR_MINUTES_REST,
|
||||
ATTR_SLEEP_LABEL,
|
||||
ATTR_TRACKER_STATE,
|
||||
CLIENT,
|
||||
DOMAIN,
|
||||
|
@ -53,11 +57,14 @@ class TractiveSensorEntityDescription(
|
|||
"""Class describing Tractive sensor entities."""
|
||||
|
||||
hardware_sensor: bool = False
|
||||
value_fn: Callable[[StateType], StateType] = lambda state: state
|
||||
|
||||
|
||||
class TractiveSensor(TractiveEntity, SensorEntity):
|
||||
"""Tractive sensor."""
|
||||
|
||||
entity_description: TractiveSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
client: TractiveClient,
|
||||
|
@ -82,7 +89,9 @@ class TractiveSensor(TractiveEntity, SensorEntity):
|
|||
@callback
|
||||
def handle_status_update(self, event: dict[str, Any]) -> None:
|
||||
"""Handle status update."""
|
||||
self._attr_native_value = event[self.entity_description.key]
|
||||
self._attr_native_value = self.entity_description.value_fn(
|
||||
event[self.entity_description.key]
|
||||
)
|
||||
|
||||
super().handle_status_update(event)
|
||||
|
||||
|
@ -159,6 +168,30 @@ SENSOR_TYPES: tuple[TractiveSensorEntityDescription, ...] = (
|
|||
signal_prefix=TRACKER_WELLNESS_STATUS_UPDATED,
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
),
|
||||
TractiveSensorEntityDescription(
|
||||
key=ATTR_SLEEP_LABEL,
|
||||
translation_key="sleep",
|
||||
icon="mdi:sleep",
|
||||
signal_prefix=TRACKER_WELLNESS_STATUS_UPDATED,
|
||||
value_fn=lambda state: state.lower() if isinstance(state, str) else state,
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=[
|
||||
"ok",
|
||||
"good",
|
||||
],
|
||||
),
|
||||
TractiveSensorEntityDescription(
|
||||
key=ATTR_ACTIVITY_LABEL,
|
||||
translation_key="activity",
|
||||
icon="mdi:run",
|
||||
signal_prefix=TRACKER_WELLNESS_STATUS_UPDATED,
|
||||
value_fn=lambda state: state.lower() if isinstance(state, str) else state,
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=[
|
||||
"ok",
|
||||
"good",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -30,15 +30,22 @@
|
|||
}
|
||||
},
|
||||
"sensor": {
|
||||
"activity": {
|
||||
"name": "Activity",
|
||||
"state": {
|
||||
"ok": "OK",
|
||||
"good": "Good"
|
||||
}
|
||||
},
|
||||
"activity_time": {
|
||||
"name": "Activity time"
|
||||
},
|
||||
"calories": {
|
||||
"name": "Calories burned"
|
||||
},
|
||||
"daily_goal": {
|
||||
"name": "Daily goal"
|
||||
},
|
||||
"activity_time": {
|
||||
"name": "Activity time"
|
||||
},
|
||||
"minutes_day_sleep": {
|
||||
"name": "Day sleep"
|
||||
},
|
||||
|
@ -48,6 +55,13 @@
|
|||
"rest_time": {
|
||||
"name": "Rest time"
|
||||
},
|
||||
"sleep": {
|
||||
"name": "Sleep",
|
||||
"state": {
|
||||
"ok": "OK",
|
||||
"good": "Good"
|
||||
}
|
||||
},
|
||||
"tracker_battery_level": {
|
||||
"name": "Tracker battery"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue