1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-31 12:44:04 +01:00
Files
core/homeassistant/components/squeezebox/sensor.py
T
2026-04-30 21:14:48 +02:00

161 lines
5.0 KiB
Python

"""Platform for sensor integration for squeezebox."""
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
import logging
from typing import cast
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import UnitOfTime
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from . import SqueezeboxConfigEntry
from .const import (
PLAYER_SENSOR_NEXT_ALARM,
SIGNAL_PLAYER_DISCOVERED,
STATUS_SENSOR_INFO_TOTAL_ALBUMS,
STATUS_SENSOR_INFO_TOTAL_ARTISTS,
STATUS_SENSOR_INFO_TOTAL_DURATION,
STATUS_SENSOR_INFO_TOTAL_GENRES,
STATUS_SENSOR_INFO_TOTAL_SONGS,
STATUS_SENSOR_LASTSCAN,
STATUS_SENSOR_OTHER_PLAYER_COUNT,
STATUS_SENSOR_PLAYER_COUNT,
)
from .entity import LMSStatusEntity, SqueezeboxEntity, SqueezeBoxPlayerUpdateCoordinator
# Coordinator is used to centralize the data updates
PARALLEL_UPDATES = 0
SERVER_STATUS_SENSORS: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key=STATUS_SENSOR_INFO_TOTAL_ALBUMS,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=STATUS_SENSOR_INFO_TOTAL_ARTISTS,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=STATUS_SENSOR_INFO_TOTAL_DURATION,
state_class=SensorStateClass.TOTAL,
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_unit_of_measurement=UnitOfTime.HOURS,
),
SensorEntityDescription(
key=STATUS_SENSOR_INFO_TOTAL_GENRES,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=STATUS_SENSOR_INFO_TOTAL_SONGS,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=STATUS_SENSOR_LASTSCAN,
device_class=SensorDeviceClass.TIMESTAMP,
),
SensorEntityDescription(
key=STATUS_SENSOR_PLAYER_COUNT,
state_class=SensorStateClass.TOTAL,
),
SensorEntityDescription(
key=STATUS_SENSOR_OTHER_PLAYER_COUNT,
state_class=SensorStateClass.TOTAL,
entity_registry_visible_default=False,
),
)
@dataclass(frozen=True, kw_only=True)
class PlayerSensorEntityDescription(SensorEntityDescription):
"""Describes player sensor entity."""
value_fn: Callable[[SqueezeboxSensorEntity], datetime | None]
PLAYER_SENSORS: tuple[PlayerSensorEntityDescription, ...] = (
PlayerSensorEntityDescription(
key=PLAYER_SENSOR_NEXT_ALARM,
translation_key=PLAYER_SENSOR_NEXT_ALARM,
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=lambda sensor: sensor.coordinator.player.alarm_next,
),
)
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
entry: SqueezeboxConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Platform setup using common elements."""
# Add player sensor entities when player discovered
async def _player_discovered(
player_coordinator: SqueezeBoxPlayerUpdateCoordinator,
) -> None:
_LOGGER.debug(
"Setting up sensor entities for player %s, model %s",
player_coordinator.player.name,
player_coordinator.player.model,
)
async_add_entities(
SqueezeboxSensorEntity(player_coordinator, description)
for description in PLAYER_SENSORS
)
entry.async_on_unload(
async_dispatcher_connect(
hass, f"{SIGNAL_PLAYER_DISCOVERED}{entry.entry_id}", _player_discovered
)
)
async_add_entities(
ServerStatusSensor(entry.runtime_data.coordinator, description)
for description in SERVER_STATUS_SENSORS
)
class ServerStatusSensor(LMSStatusEntity, SensorEntity):
"""LMS Status based sensor from LMS via coordinator."""
@property
def native_value(self) -> StateType:
"""LMS Status directly from coordinator data."""
return cast(StateType, self.coordinator.data[self.entity_description.key])
class SqueezeboxSensorEntity(SqueezeboxEntity, SensorEntity):
"""Representation of player based sensors."""
entity_description: PlayerSensorEntityDescription
def __init__(
self,
coordinator: SqueezeBoxPlayerUpdateCoordinator,
description: PlayerSensorEntityDescription,
) -> None:
"""Initialize the SqueezeBox sensor."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{format_mac(self._player.player_id)}_{description.key}"
@property
def native_value(self) -> datetime | None:
"""Sensor value directly from player coordinator."""
return self.entity_description.value_fn(self)