mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 07:37:34 +00:00
Add entity descriptions to sensors of Rituals Perfume Genie (#92527)
This commit is contained in:
parent
a72bcfde4a
commit
80e9219546
@ -1,7 +1,16 @@
|
|||||||
"""Support for Rituals Perfume Genie sensors."""
|
"""Support for Rituals Perfume Genie sensors."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
from collections.abc import Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from pyrituals import Diffuser
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import (
|
||||||
|
SensorDeviceClass,
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import PERCENTAGE, EntityCategory
|
from homeassistant.const import PERCENTAGE, EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -12,6 +21,53 @@ from .coordinator import RitualsDataUpdateCoordinator
|
|||||||
from .entity import DiffuserEntity
|
from .entity import DiffuserEntity
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RitualsEntityDescriptionMixin:
|
||||||
|
"""Mixin values for Rituals entities."""
|
||||||
|
|
||||||
|
value_fn: Callable[[Diffuser], int | str]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RitualsSensorEntityDescription(
|
||||||
|
SensorEntityDescription, RitualsEntityDescriptionMixin
|
||||||
|
):
|
||||||
|
"""Class describing Rituals sensor entities."""
|
||||||
|
|
||||||
|
has_fn: Callable[[Diffuser], bool] = lambda _: True
|
||||||
|
|
||||||
|
|
||||||
|
ENTITY_DESCRIPTIONS = (
|
||||||
|
RitualsSensorEntityDescription(
|
||||||
|
key="battery_percentage",
|
||||||
|
name="Battery",
|
||||||
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
|
device_class=SensorDeviceClass.BATTERY,
|
||||||
|
value_fn=lambda diffuser: diffuser.battery_percentage,
|
||||||
|
has_fn=lambda diffuser: diffuser.has_battery,
|
||||||
|
),
|
||||||
|
RitualsSensorEntityDescription(
|
||||||
|
key="fill",
|
||||||
|
name="Fill",
|
||||||
|
icon="mdi:beaker",
|
||||||
|
value_fn=lambda diffuser: diffuser.fill,
|
||||||
|
),
|
||||||
|
RitualsSensorEntityDescription(
|
||||||
|
key="perfume",
|
||||||
|
name="Perfume",
|
||||||
|
icon="mdi:tag",
|
||||||
|
value_fn=lambda diffuser: diffuser.perfume,
|
||||||
|
),
|
||||||
|
RitualsSensorEntityDescription(
|
||||||
|
key="wifi_percentage",
|
||||||
|
name="Wifi",
|
||||||
|
icon="mdi:wifi",
|
||||||
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
|
value_fn=lambda diffuser: diffuser.wifi_percentage,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
@ -22,97 +78,32 @@ async def async_setup_entry(
|
|||||||
config_entry.entry_id
|
config_entry.entry_id
|
||||||
]
|
]
|
||||||
|
|
||||||
entities: list[DiffuserEntity] = []
|
async_add_entities(
|
||||||
for coordinator in coordinators.values():
|
RitualsSensorEntity(coordinator, description)
|
||||||
entities.extend(
|
for coordinator in coordinators.values()
|
||||||
[
|
for description in ENTITY_DESCRIPTIONS
|
||||||
DiffuserPerfumeSensor(coordinator),
|
if description.has_fn(coordinator.diffuser)
|
||||||
DiffuserFillSensor(coordinator),
|
|
||||||
DiffuserWifiSensor(coordinator),
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
if coordinator.diffuser.has_battery:
|
|
||||||
entities.append(DiffuserBatterySensor(coordinator))
|
|
||||||
|
|
||||||
async_add_entities(entities)
|
|
||||||
|
|
||||||
|
|
||||||
class DiffuserPerfumeSensor(DiffuserEntity, SensorEntity):
|
class RitualsSensorEntity(DiffuserEntity, SensorEntity):
|
||||||
"""Representation of a diffuser perfume sensor."""
|
"""Representation of a diffuser sensor."""
|
||||||
|
|
||||||
def __init__(self, coordinator: RitualsDataUpdateCoordinator) -> None:
|
entity_description: RitualsSensorEntityDescription
|
||||||
"""Initialize the perfume sensor."""
|
|
||||||
super().__init__(coordinator)
|
|
||||||
self._attr_unique_id = f"{coordinator.diffuser.hublot}-perfume"
|
|
||||||
self._attr_name = f"{coordinator.diffuser.name} Perfume"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self) -> str:
|
|
||||||
"""Return the perfume sensor icon."""
|
|
||||||
if self.coordinator.diffuser.has_cartridge:
|
|
||||||
return "mdi:tag-text"
|
|
||||||
return "mdi:tag-remove"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> str:
|
|
||||||
"""Return the state of the perfume sensor."""
|
|
||||||
return self.coordinator.diffuser.perfume
|
|
||||||
|
|
||||||
|
|
||||||
class DiffuserFillSensor(DiffuserEntity, SensorEntity):
|
|
||||||
"""Representation of a diffuser fill sensor."""
|
|
||||||
|
|
||||||
def __init__(self, coordinator: RitualsDataUpdateCoordinator) -> None:
|
|
||||||
"""Initialize the fill sensor."""
|
|
||||||
super().__init__(coordinator)
|
|
||||||
self._attr_unique_id = f"{coordinator.diffuser.hublot}-fill"
|
|
||||||
self._attr_name = f"{coordinator.diffuser.name} Fill"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self) -> str:
|
|
||||||
"""Return the fill sensor icon."""
|
|
||||||
if self.coordinator.diffuser.has_cartridge:
|
|
||||||
return "mdi:beaker"
|
|
||||||
return "mdi:beaker-question"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> str:
|
|
||||||
"""Return the state of the fill sensor."""
|
|
||||||
return self.coordinator.diffuser.fill
|
|
||||||
|
|
||||||
|
|
||||||
class DiffuserBatterySensor(DiffuserEntity, SensorEntity):
|
|
||||||
"""Representation of a diffuser battery sensor."""
|
|
||||||
|
|
||||||
_attr_device_class = SensorDeviceClass.BATTERY
|
|
||||||
_attr_native_unit_of_measurement = PERCENTAGE
|
|
||||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||||
|
|
||||||
def __init__(self, coordinator: RitualsDataUpdateCoordinator) -> None:
|
def __init__(
|
||||||
"""Initialize the battery sensor."""
|
self,
|
||||||
|
coordinator: RitualsDataUpdateCoordinator,
|
||||||
|
description: RitualsSensorEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the diffuser sensor."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._attr_unique_id = f"{coordinator.diffuser.hublot}-battery_percentage"
|
self.entity_description = description
|
||||||
self._attr_name = f"{coordinator.diffuser.name} Battery"
|
self._attr_unique_id = f"{coordinator.diffuser.hublot}-{description.key}"
|
||||||
|
self._attr_name = f"{coordinator.diffuser.name} {description.name}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> int:
|
def native_value(self) -> str | int:
|
||||||
"""Return the state of the battery sensor."""
|
"""Return the sensor value."""
|
||||||
return self.coordinator.diffuser.battery_percentage
|
return self.entity_description.value_fn(self.coordinator.diffuser)
|
||||||
|
|
||||||
|
|
||||||
class DiffuserWifiSensor(DiffuserEntity, SensorEntity):
|
|
||||||
"""Representation of a diffuser wifi sensor."""
|
|
||||||
|
|
||||||
_attr_native_unit_of_measurement = PERCENTAGE
|
|
||||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
|
||||||
|
|
||||||
def __init__(self, coordinator: RitualsDataUpdateCoordinator) -> None:
|
|
||||||
"""Initialize the wifi sensor."""
|
|
||||||
super().__init__(coordinator)
|
|
||||||
self._attr_unique_id = f"{coordinator.diffuser.hublot}-wifi_percentage"
|
|
||||||
self._attr_name = f"{coordinator.diffuser.name} Wifi"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> int:
|
|
||||||
"""Return the state of the wifi sensor."""
|
|
||||||
return self.coordinator.diffuser.wifi_percentage
|
|
||||||
|
@ -14,7 +14,6 @@ from .common import (
|
|||||||
init_integration,
|
init_integration,
|
||||||
mock_config_entry,
|
mock_config_entry,
|
||||||
mock_diffuser_v1_battery_cartridge,
|
mock_diffuser_v1_battery_cartridge,
|
||||||
mock_diffuser_v2_no_battery_no_cartridge,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ async def test_sensors_diffuser_v1_battery_cartridge(
|
|||||||
state = hass.states.get("sensor.genie_perfume")
|
state = hass.states.get("sensor.genie_perfume")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == diffuser.perfume
|
assert state.state == diffuser.perfume
|
||||||
assert state.attributes.get(ATTR_ICON) == "mdi:tag-text"
|
assert state.attributes.get(ATTR_ICON) == "mdi:tag"
|
||||||
|
|
||||||
entry = entity_registry.async_get("sensor.genie_perfume")
|
entry = entity_registry.async_get("sensor.genie_perfume")
|
||||||
assert entry
|
assert entry
|
||||||
@ -66,20 +65,3 @@ async def test_sensors_diffuser_v1_battery_cartridge(
|
|||||||
assert entry
|
assert entry
|
||||||
assert entry.unique_id == f"{hublot}-wifi_percentage"
|
assert entry.unique_id == f"{hublot}-wifi_percentage"
|
||||||
assert entry.entity_category == EntityCategory.DIAGNOSTIC
|
assert entry.entity_category == EntityCategory.DIAGNOSTIC
|
||||||
|
|
||||||
|
|
||||||
async def test_sensors_diffuser_v2_no_battery_no_cartridge(hass: HomeAssistant) -> None:
|
|
||||||
"""Test the creation and values of the Rituals Perfume Genie sensors."""
|
|
||||||
config_entry = mock_config_entry(unique_id="id_123_sensor_test_diffuser_v2")
|
|
||||||
|
|
||||||
await init_integration(
|
|
||||||
hass, config_entry, [mock_diffuser_v2_no_battery_no_cartridge()]
|
|
||||||
)
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.genie_v2_perfume")
|
|
||||||
assert state
|
|
||||||
assert state.attributes.get(ATTR_ICON) == "mdi:tag-remove"
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.genie_v2_fill")
|
|
||||||
assert state
|
|
||||||
assert state.attributes.get(ATTR_ICON) == "mdi:beaker-question"
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user