mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add wellness sensors to Tractive integration (#96719)
* Add sleep sensors * Add minutes rest sensor * Add calories sensor * Add state_class to entity descriptions
This commit is contained in:
parent
085eebc903
commit
79bcca2853
@ -24,10 +24,14 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_BUZZER,
|
ATTR_BUZZER,
|
||||||
|
ATTR_CALORIES,
|
||||||
ATTR_DAILY_GOAL,
|
ATTR_DAILY_GOAL,
|
||||||
ATTR_LED,
|
ATTR_LED,
|
||||||
ATTR_LIVE_TRACKING,
|
ATTR_LIVE_TRACKING,
|
||||||
ATTR_MINUTES_ACTIVE,
|
ATTR_MINUTES_ACTIVE,
|
||||||
|
ATTR_MINUTES_DAY_SLEEP,
|
||||||
|
ATTR_MINUTES_NIGHT_SLEEP,
|
||||||
|
ATTR_MINUTES_REST,
|
||||||
ATTR_TRACKER_STATE,
|
ATTR_TRACKER_STATE,
|
||||||
CLIENT,
|
CLIENT,
|
||||||
CLIENT_ID,
|
CLIENT_ID,
|
||||||
@ -38,6 +42,7 @@ from .const import (
|
|||||||
TRACKER_ACTIVITY_STATUS_UPDATED,
|
TRACKER_ACTIVITY_STATUS_UPDATED,
|
||||||
TRACKER_HARDWARE_STATUS_UPDATED,
|
TRACKER_HARDWARE_STATUS_UPDATED,
|
||||||
TRACKER_POSITION_UPDATED,
|
TRACKER_POSITION_UPDATED,
|
||||||
|
TRACKER_WELLNESS_STATUS_UPDATED,
|
||||||
)
|
)
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
@ -202,6 +207,9 @@ class TractiveClient:
|
|||||||
if event["message"] == "activity_update":
|
if event["message"] == "activity_update":
|
||||||
self._send_activity_update(event)
|
self._send_activity_update(event)
|
||||||
continue
|
continue
|
||||||
|
if event["message"] == "wellness_overview":
|
||||||
|
self._send_wellness_update(event)
|
||||||
|
continue
|
||||||
if (
|
if (
|
||||||
"hardware" in event
|
"hardware" in event
|
||||||
and self._last_hw_time != event["hardware"]["time"]
|
and self._last_hw_time != event["hardware"]["time"]
|
||||||
@ -264,6 +272,17 @@ class TractiveClient:
|
|||||||
TRACKER_ACTIVITY_STATUS_UPDATED, event["pet_id"], payload
|
TRACKER_ACTIVITY_STATUS_UPDATED, event["pet_id"], payload
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _send_wellness_update(self, event: dict[str, Any]) -> None:
|
||||||
|
payload = {
|
||||||
|
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"],
|
||||||
|
}
|
||||||
|
self._dispatch_tracker_event(
|
||||||
|
TRACKER_WELLNESS_STATUS_UPDATED, event["pet_id"], payload
|
||||||
|
)
|
||||||
|
|
||||||
def _send_position_update(self, event: dict[str, Any]) -> None:
|
def _send_position_update(self, event: dict[str, Any]) -> None:
|
||||||
payload = {
|
payload = {
|
||||||
"latitude": event["position"]["latlong"][0],
|
"latitude": event["position"]["latlong"][0],
|
||||||
|
@ -6,11 +6,15 @@ DOMAIN = "tractive"
|
|||||||
|
|
||||||
RECONNECT_INTERVAL = timedelta(seconds=10)
|
RECONNECT_INTERVAL = timedelta(seconds=10)
|
||||||
|
|
||||||
ATTR_DAILY_GOAL = "daily_goal"
|
|
||||||
ATTR_BUZZER = "buzzer"
|
ATTR_BUZZER = "buzzer"
|
||||||
|
ATTR_CALORIES = "calories"
|
||||||
|
ATTR_DAILY_GOAL = "daily_goal"
|
||||||
ATTR_LED = "led"
|
ATTR_LED = "led"
|
||||||
ATTR_LIVE_TRACKING = "live_tracking"
|
ATTR_LIVE_TRACKING = "live_tracking"
|
||||||
ATTR_MINUTES_ACTIVE = "minutes_active"
|
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_TRACKER_STATE = "tracker_state"
|
ATTR_TRACKER_STATE = "tracker_state"
|
||||||
|
|
||||||
# This client ID was issued by Tractive specifically for Home Assistant.
|
# This client ID was issued by Tractive specifically for Home Assistant.
|
||||||
@ -23,5 +27,6 @@ TRACKABLES = "trackables"
|
|||||||
TRACKER_HARDWARE_STATUS_UPDATED = f"{DOMAIN}_tracker_hardware_status_updated"
|
TRACKER_HARDWARE_STATUS_UPDATED = f"{DOMAIN}_tracker_hardware_status_updated"
|
||||||
TRACKER_POSITION_UPDATED = f"{DOMAIN}_tracker_position_updated"
|
TRACKER_POSITION_UPDATED = f"{DOMAIN}_tracker_position_updated"
|
||||||
TRACKER_ACTIVITY_STATUS_UPDATED = f"{DOMAIN}_tracker_activity_updated"
|
TRACKER_ACTIVITY_STATUS_UPDATED = f"{DOMAIN}_tracker_activity_updated"
|
||||||
|
TRACKER_WELLNESS_STATUS_UPDATED = f"{DOMAIN}_tracker_wellness_updated"
|
||||||
|
|
||||||
SERVER_UNAVAILABLE = f"{DOMAIN}_server_unavailable"
|
SERVER_UNAVAILABLE = f"{DOMAIN}_server_unavailable"
|
||||||
|
@ -8,6 +8,7 @@ from homeassistant.components.sensor import (
|
|||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -22,8 +23,12 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
|
|
||||||
from . import Trackables
|
from . import Trackables
|
||||||
from .const import (
|
from .const import (
|
||||||
|
ATTR_CALORIES,
|
||||||
ATTR_DAILY_GOAL,
|
ATTR_DAILY_GOAL,
|
||||||
ATTR_MINUTES_ACTIVE,
|
ATTR_MINUTES_ACTIVE,
|
||||||
|
ATTR_MINUTES_DAY_SLEEP,
|
||||||
|
ATTR_MINUTES_NIGHT_SLEEP,
|
||||||
|
ATTR_MINUTES_REST,
|
||||||
ATTR_TRACKER_STATE,
|
ATTR_TRACKER_STATE,
|
||||||
CLIENT,
|
CLIENT,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -31,6 +36,7 @@ from .const import (
|
|||||||
TRACKABLES,
|
TRACKABLES,
|
||||||
TRACKER_ACTIVITY_STATUS_UPDATED,
|
TRACKER_ACTIVITY_STATUS_UPDATED,
|
||||||
TRACKER_HARDWARE_STATUS_UPDATED,
|
TRACKER_HARDWARE_STATUS_UPDATED,
|
||||||
|
TRACKER_WELLNESS_STATUS_UPDATED,
|
||||||
)
|
)
|
||||||
from .entity import TractiveEntity
|
from .entity import TractiveEntity
|
||||||
|
|
||||||
@ -107,8 +113,8 @@ class TractiveActivitySensor(TractiveSensor):
|
|||||||
"""Tractive active sensor."""
|
"""Tractive active sensor."""
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_activity_status_update(self, event: dict[str, Any]) -> None:
|
def handle_status_update(self, event: dict[str, Any]) -> None:
|
||||||
"""Handle activity status update."""
|
"""Handle status update."""
|
||||||
self._attr_native_value = event[self.entity_description.key]
|
self._attr_native_value = event[self.entity_description.key]
|
||||||
self._attr_available = True
|
self._attr_available = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
@ -120,7 +126,30 @@ class TractiveActivitySensor(TractiveSensor):
|
|||||||
async_dispatcher_connect(
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
f"{TRACKER_ACTIVITY_STATUS_UPDATED}-{self._trackable['_id']}",
|
f"{TRACKER_ACTIVITY_STATUS_UPDATED}-{self._trackable['_id']}",
|
||||||
self.handle_activity_status_update,
|
self.handle_status_update,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
|
self.hass,
|
||||||
|
f"{SERVER_UNAVAILABLE}-{self._user_id}",
|
||||||
|
self.handle_server_unavailable,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TractiveWellnessSensor(TractiveActivitySensor):
|
||||||
|
"""Tractive wellness sensor."""
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Handle entity which will be added."""
|
||||||
|
|
||||||
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
|
self.hass,
|
||||||
|
f"{TRACKER_WELLNESS_STATUS_UPDATED}-{self._trackable['_id']}",
|
||||||
|
self.handle_status_update,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -155,6 +184,23 @@ SENSOR_TYPES: tuple[TractiveSensorEntityDescription, ...] = (
|
|||||||
icon="mdi:clock-time-eight-outline",
|
icon="mdi:clock-time-eight-outline",
|
||||||
native_unit_of_measurement=UnitOfTime.MINUTES,
|
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||||
entity_class=TractiveActivitySensor,
|
entity_class=TractiveActivitySensor,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
),
|
||||||
|
TractiveSensorEntityDescription(
|
||||||
|
key=ATTR_MINUTES_REST,
|
||||||
|
translation_key="minutes_rest",
|
||||||
|
icon="mdi:clock-time-eight-outline",
|
||||||
|
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||||
|
entity_class=TractiveWellnessSensor,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
),
|
||||||
|
TractiveSensorEntityDescription(
|
||||||
|
key=ATTR_CALORIES,
|
||||||
|
translation_key="calories",
|
||||||
|
icon="mdi:fire",
|
||||||
|
native_unit_of_measurement="kcal",
|
||||||
|
entity_class=TractiveWellnessSensor,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
),
|
),
|
||||||
TractiveSensorEntityDescription(
|
TractiveSensorEntityDescription(
|
||||||
key=ATTR_DAILY_GOAL,
|
key=ATTR_DAILY_GOAL,
|
||||||
@ -163,6 +209,22 @@ SENSOR_TYPES: tuple[TractiveSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfTime.MINUTES,
|
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||||
entity_class=TractiveActivitySensor,
|
entity_class=TractiveActivitySensor,
|
||||||
),
|
),
|
||||||
|
TractiveSensorEntityDescription(
|
||||||
|
key=ATTR_MINUTES_DAY_SLEEP,
|
||||||
|
translation_key="minutes_day_sleep",
|
||||||
|
icon="mdi:sleep",
|
||||||
|
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||||
|
entity_class=TractiveWellnessSensor,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
),
|
||||||
|
TractiveSensorEntityDescription(
|
||||||
|
key=ATTR_MINUTES_NIGHT_SLEEP,
|
||||||
|
translation_key="minutes_night_sleep",
|
||||||
|
icon="mdi:sleep",
|
||||||
|
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||||
|
entity_class=TractiveWellnessSensor,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,12 +30,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
|
"calories": {
|
||||||
|
"name": "Calories burned"
|
||||||
|
},
|
||||||
"daily_goal": {
|
"daily_goal": {
|
||||||
"name": "Daily goal"
|
"name": "Daily goal"
|
||||||
},
|
},
|
||||||
"minutes_active": {
|
"minutes_active": {
|
||||||
"name": "Minutes active"
|
"name": "Minutes active"
|
||||||
},
|
},
|
||||||
|
"minutes_day_sleep": {
|
||||||
|
"name": "Day sleep"
|
||||||
|
},
|
||||||
|
"minutes_night_sleep": {
|
||||||
|
"name": "Night sleep"
|
||||||
|
},
|
||||||
|
"minutes_rest": {
|
||||||
|
"name": "Minutes rest"
|
||||||
|
},
|
||||||
"tracker_battery_level": {
|
"tracker_battery_level": {
|
||||||
"name": "Tracker battery"
|
"name": "Tracker battery"
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user