mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 14:27:07 +00:00
Add Home Connect sensors for fridge door states and alarms (#125490)
* New sensors for Fridge door states and alarms * Move 2 option entities to binary_sensor, tests * Change state translations * Fix stale docstring
This commit is contained in:
parent
ba7ca84899
commit
85aa32338e
@ -1,14 +1,21 @@
|
|||||||
"""Provides a binary sensor for Home Connect."""
|
"""Provides a binary sensor for Home Connect."""
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
from homeassistant.components.binary_sensor import (
|
||||||
|
BinarySensorDeviceClass,
|
||||||
|
BinarySensorEntity,
|
||||||
|
BinarySensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ENTITIES
|
from homeassistant.const import CONF_ENTITIES
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from .api import HomeConnectDevice
|
||||||
from .const import (
|
from .const import (
|
||||||
|
ATTR_DEVICE,
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
BSH_DOOR_STATE,
|
BSH_DOOR_STATE,
|
||||||
BSH_DOOR_STATE_CLOSED,
|
BSH_DOOR_STATE_CLOSED,
|
||||||
@ -17,12 +24,47 @@ from .const import (
|
|||||||
BSH_REMOTE_CONTROL_ACTIVATION_STATE,
|
BSH_REMOTE_CONTROL_ACTIVATION_STATE,
|
||||||
BSH_REMOTE_START_ALLOWANCE_STATE,
|
BSH_REMOTE_START_ALLOWANCE_STATE,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
REFRIGERATION_STATUS_DOOR_CHILLER,
|
||||||
|
REFRIGERATION_STATUS_DOOR_CLOSED,
|
||||||
|
REFRIGERATION_STATUS_DOOR_FREEZER,
|
||||||
|
REFRIGERATION_STATUS_DOOR_OPEN,
|
||||||
|
REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
)
|
)
|
||||||
from .entity import HomeConnectEntity
|
from .entity import HomeConnectEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class HomeConnectBinarySensorEntityDescription(BinarySensorEntityDescription):
|
||||||
|
"""Entity Description class for binary sensors."""
|
||||||
|
|
||||||
|
state_key: str | None
|
||||||
|
device_class: BinarySensorDeviceClass | None = BinarySensorDeviceClass.DOOR
|
||||||
|
boolean_map: dict[str, bool] = field(
|
||||||
|
default_factory=lambda: {
|
||||||
|
REFRIGERATION_STATUS_DOOR_CLOSED: False,
|
||||||
|
REFRIGERATION_STATUS_DOOR_OPEN: True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
BINARY_SENSORS: tuple[HomeConnectBinarySensorEntityDescription, ...] = (
|
||||||
|
HomeConnectBinarySensorEntityDescription(
|
||||||
|
key="Chiller Door",
|
||||||
|
state_key=REFRIGERATION_STATUS_DOOR_CHILLER,
|
||||||
|
),
|
||||||
|
HomeConnectBinarySensorEntityDescription(
|
||||||
|
key="Freezer Door",
|
||||||
|
state_key=REFRIGERATION_STATUS_DOOR_FREEZER,
|
||||||
|
),
|
||||||
|
HomeConnectBinarySensorEntityDescription(
|
||||||
|
key="Refrigerator Door",
|
||||||
|
state_key=REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
@ -36,6 +78,15 @@ async def async_setup_entry(
|
|||||||
for device_dict in hc_api.devices:
|
for device_dict in hc_api.devices:
|
||||||
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("binary_sensor", [])
|
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("binary_sensor", [])
|
||||||
entities += [HomeConnectBinarySensor(**d) for d in entity_dicts]
|
entities += [HomeConnectBinarySensor(**d) for d in entity_dicts]
|
||||||
|
device: HomeConnectDevice = device_dict[ATTR_DEVICE]
|
||||||
|
# Auto-discover entities
|
||||||
|
entities.extend(
|
||||||
|
HomeConnectFridgeDoorBinarySensor(
|
||||||
|
device=device, entity_description=description
|
||||||
|
)
|
||||||
|
for description in BINARY_SENSORS
|
||||||
|
if description.state_key in device.appliance.status
|
||||||
|
)
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
||||||
@ -93,3 +144,37 @@ class HomeConnectBinarySensor(HomeConnectEntity, BinarySensorEntity):
|
|||||||
def device_class(self):
|
def device_class(self):
|
||||||
"""Return the device class."""
|
"""Return the device class."""
|
||||||
return self._device_class
|
return self._device_class
|
||||||
|
|
||||||
|
|
||||||
|
class HomeConnectFridgeDoorBinarySensor(HomeConnectEntity, BinarySensorEntity):
|
||||||
|
"""Binary sensor for Home Connect Fridge Doors."""
|
||||||
|
|
||||||
|
entity_description: HomeConnectBinarySensorEntityDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: HomeConnectDevice,
|
||||||
|
entity_description: HomeConnectBinarySensorEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the entity."""
|
||||||
|
self.entity_description = entity_description
|
||||||
|
super().__init__(device, entity_description.key)
|
||||||
|
|
||||||
|
async def async_update(self) -> None:
|
||||||
|
"""Update the binary sensor's status."""
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updating: %s, cur state: %s",
|
||||||
|
self._attr_unique_id,
|
||||||
|
self.state,
|
||||||
|
)
|
||||||
|
self._attr_is_on = self.entity_description.boolean_map.get(
|
||||||
|
self.device.appliance.status.get(self.entity_description.state_key, {}).get(
|
||||||
|
ATTR_VALUE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._attr_available = self._attr_is_on is not None
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updated: %s, new state: %s",
|
||||||
|
self._attr_unique_id,
|
||||||
|
self.state,
|
||||||
|
)
|
||||||
|
@ -14,6 +14,9 @@ BSH_REMOTE_CONTROL_ACTIVATION_STATE = "BSH.Common.Status.RemoteControlActive"
|
|||||||
BSH_REMOTE_START_ALLOWANCE_STATE = "BSH.Common.Status.RemoteControlStartAllowed"
|
BSH_REMOTE_START_ALLOWANCE_STATE = "BSH.Common.Status.RemoteControlStartAllowed"
|
||||||
BSH_CHILD_LOCK_STATE = "BSH.Common.Setting.ChildLock"
|
BSH_CHILD_LOCK_STATE = "BSH.Common.Setting.ChildLock"
|
||||||
|
|
||||||
|
BSH_EVENT_PRESENT_STATE_PRESENT = "BSH.Common.EnumType.EventPresentState.Present"
|
||||||
|
BSH_EVENT_PRESENT_STATE_CONFIRMED = "BSH.Common.EnumType.EventPresentState.Confirmed"
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF = "BSH.Common.EnumType.EventPresentState.Off"
|
||||||
|
|
||||||
BSH_OPERATION_STATE = "BSH.Common.Status.OperationState"
|
BSH_OPERATION_STATE = "BSH.Common.Status.OperationState"
|
||||||
BSH_OPERATION_STATE_RUN = "BSH.Common.EnumType.OperationState.Run"
|
BSH_OPERATION_STATE_RUN = "BSH.Common.EnumType.OperationState.Run"
|
||||||
@ -23,6 +26,11 @@ BSH_OPERATION_STATE_FINISHED = "BSH.Common.EnumType.OperationState.Finished"
|
|||||||
COOKING_LIGHTING = "Cooking.Common.Setting.Lighting"
|
COOKING_LIGHTING = "Cooking.Common.Setting.Lighting"
|
||||||
COOKING_LIGHTING_BRIGHTNESS = "Cooking.Common.Setting.LightingBrightness"
|
COOKING_LIGHTING_BRIGHTNESS = "Cooking.Common.Setting.LightingBrightness"
|
||||||
|
|
||||||
|
COFFEE_EVENT_BEAN_CONTAINER_EMPTY = (
|
||||||
|
"ConsumerProducts.CoffeeMaker.Event.BeanContainerEmpty"
|
||||||
|
)
|
||||||
|
COFFEE_EVENT_WATER_TANK_EMPTY = "ConsumerProducts.CoffeeMaker.Event.WaterTankEmpty"
|
||||||
|
COFFEE_EVENT_DRIP_TRAY_FULL = "ConsumerProducts.CoffeeMaker.Event.DripTrayFull"
|
||||||
|
|
||||||
REFRIGERATION_SUPERMODEFREEZER = "Refrigeration.FridgeFreezer.Setting.SuperModeFreezer"
|
REFRIGERATION_SUPERMODEFREEZER = "Refrigeration.FridgeFreezer.Setting.SuperModeFreezer"
|
||||||
REFRIGERATION_SUPERMODEREFRIGERATOR = (
|
REFRIGERATION_SUPERMODEREFRIGERATOR = (
|
||||||
@ -30,6 +38,24 @@ REFRIGERATION_SUPERMODEREFRIGERATOR = (
|
|||||||
)
|
)
|
||||||
REFRIGERATION_DISPENSER = "Refrigeration.Common.Setting.Dispenser.Enabled"
|
REFRIGERATION_DISPENSER = "Refrigeration.Common.Setting.Dispenser.Enabled"
|
||||||
|
|
||||||
|
REFRIGERATION_STATUS_DOOR_CHILLER = "Refrigeration.Common.Status.Door.ChillerCommon"
|
||||||
|
REFRIGERATION_STATUS_DOOR_FREEZER = "Refrigeration.Common.Status.Door.Freezer"
|
||||||
|
REFRIGERATION_STATUS_DOOR_REFRIGERATOR = "Refrigeration.Common.Status.Door.Refrigerator"
|
||||||
|
|
||||||
|
REFRIGERATION_STATUS_DOOR_CLOSED = "Refrigeration.Common.EnumType.Door.States.Closed"
|
||||||
|
REFRIGERATION_STATUS_DOOR_OPEN = "Refrigeration.Common.EnumType.Door.States.Open"
|
||||||
|
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_REFRIGERATOR = (
|
||||||
|
"Refrigeration.FridgeFreezer.Event.DoorAlarmRefrigerator"
|
||||||
|
)
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_FREEZER = (
|
||||||
|
"Refrigeration.FridgeFreezer.Event.DoorAlarmFreezer"
|
||||||
|
)
|
||||||
|
REFRIGERATION_EVENT_TEMP_ALARM_FREEZER = (
|
||||||
|
"Refrigeration.FridgeFreezer.Event.TemperatureAlarmFreezer"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
BSH_AMBIENT_LIGHT_ENABLED = "BSH.Common.Setting.AmbientLightEnabled"
|
BSH_AMBIENT_LIGHT_ENABLED = "BSH.Common.Setting.AmbientLightEnabled"
|
||||||
BSH_AMBIENT_LIGHT_BRIGHTNESS = "BSH.Common.Setting.AmbientLightBrightness"
|
BSH_AMBIENT_LIGHT_BRIGHTNESS = "BSH.Common.Setting.AmbientLightBrightness"
|
||||||
BSH_AMBIENT_LIGHT_COLOR = "BSH.Common.Setting.AmbientLightColor"
|
BSH_AMBIENT_LIGHT_COLOR = "BSH.Common.Setting.AmbientLightColor"
|
||||||
|
@ -23,6 +23,50 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"entity": {
|
"entity": {
|
||||||
|
"sensor": {
|
||||||
|
"alarm_sensor_fridge": {
|
||||||
|
"default": "mdi:fridge",
|
||||||
|
"state": {
|
||||||
|
"confirmed": "mdi:fridge-alert-outline",
|
||||||
|
"present": "mdi:fridge-alert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_freezer": {
|
||||||
|
"default": "mdi:snowflake",
|
||||||
|
"state": {
|
||||||
|
"confirmed": "mdi:snowflake-check",
|
||||||
|
"present": "mdi:snowflake-alert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_temp": {
|
||||||
|
"default": "mdi:thermometer",
|
||||||
|
"state": {
|
||||||
|
"confirmed": "mdi:thermometer-check",
|
||||||
|
"present": "mdi:thermometer-alert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_coffee_bean_container": {
|
||||||
|
"default": "mdi:coffee-maker",
|
||||||
|
"state": {
|
||||||
|
"confirmed": "mdi:coffee-maker-check",
|
||||||
|
"present": "mdi:coffee-maker-outline"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_coffee_water_tank": {
|
||||||
|
"default": "mdi:water",
|
||||||
|
"state": {
|
||||||
|
"confirmed": "mdi:water-check",
|
||||||
|
"present": "mdi:water-alert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_coffee_drip_tray": {
|
||||||
|
"default": "mdi:tray",
|
||||||
|
"state": {
|
||||||
|
"confirmed": "mdi:tray-full",
|
||||||
|
"present": "mdi:tray-alert"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
"refrigeration_dispenser": {
|
"refrigeration_dispenser": {
|
||||||
"default": "mdi:snowflake",
|
"default": "mdi:snowflake",
|
||||||
|
@ -1,29 +1,95 @@
|
|||||||
"""Provides a sensor for Home Connect."""
|
"""Provides a sensor for Home Connect."""
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
from homeassistant.components.sensor import (
|
||||||
|
SensorDeviceClass,
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ENTITIES
|
from homeassistant.const import CONF_ENTITIES
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
|
from .api import ConfigEntryAuth, HomeConnectDevice
|
||||||
from .const import (
|
from .const import (
|
||||||
|
ATTR_DEVICE,
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF,
|
||||||
BSH_OPERATION_STATE,
|
BSH_OPERATION_STATE,
|
||||||
BSH_OPERATION_STATE_FINISHED,
|
BSH_OPERATION_STATE_FINISHED,
|
||||||
BSH_OPERATION_STATE_PAUSE,
|
BSH_OPERATION_STATE_PAUSE,
|
||||||
BSH_OPERATION_STATE_RUN,
|
BSH_OPERATION_STATE_RUN,
|
||||||
|
COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
COFFEE_EVENT_DRIP_TRAY_FULL,
|
||||||
|
COFFEE_EVENT_WATER_TANK_EMPTY,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_REFRIGERATOR,
|
||||||
|
REFRIGERATION_EVENT_TEMP_ALARM_FREEZER,
|
||||||
)
|
)
|
||||||
from .entity import HomeConnectEntity
|
from .entity import HomeConnectEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class HomeConnectSensorEntityDescription(SensorEntityDescription):
|
||||||
|
"""Entity Description class for sensors."""
|
||||||
|
|
||||||
|
device_class: SensorDeviceClass | None = SensorDeviceClass.ENUM
|
||||||
|
options: list[str] | None = field(
|
||||||
|
default_factory=lambda: ["confirmed", "off", "present"]
|
||||||
|
)
|
||||||
|
state_key: str
|
||||||
|
appliance_types: tuple[str, ...]
|
||||||
|
|
||||||
|
|
||||||
|
SENSORS: tuple[HomeConnectSensorEntityDescription, ...] = (
|
||||||
|
HomeConnectSensorEntityDescription(
|
||||||
|
key="Door Alarm Freezer",
|
||||||
|
translation_key="alarm_sensor_freezer",
|
||||||
|
state_key=REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
appliance_types=("FridgeFreezer", "Freezer"),
|
||||||
|
),
|
||||||
|
HomeConnectSensorEntityDescription(
|
||||||
|
key="Door Alarm Refrigerator",
|
||||||
|
translation_key="alarm_sensor_fridge",
|
||||||
|
state_key=REFRIGERATION_EVENT_DOOR_ALARM_REFRIGERATOR,
|
||||||
|
appliance_types=("FridgeFreezer", "Refrigerator"),
|
||||||
|
),
|
||||||
|
HomeConnectSensorEntityDescription(
|
||||||
|
key="Temperature Alarm Freezer",
|
||||||
|
translation_key="alarm_sensor_temp",
|
||||||
|
state_key=REFRIGERATION_EVENT_TEMP_ALARM_FREEZER,
|
||||||
|
appliance_types=("FridgeFreezer", "Freezer"),
|
||||||
|
),
|
||||||
|
HomeConnectSensorEntityDescription(
|
||||||
|
key="Bean Container Empty",
|
||||||
|
translation_key="alarm_sensor_coffee_bean_container",
|
||||||
|
state_key=COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
appliance_types=("CoffeeMaker",),
|
||||||
|
),
|
||||||
|
HomeConnectSensorEntityDescription(
|
||||||
|
key="Water Tank Empty",
|
||||||
|
translation_key="alarm_sensor_coffee_water_tank",
|
||||||
|
state_key=COFFEE_EVENT_WATER_TANK_EMPTY,
|
||||||
|
appliance_types=("CoffeeMaker",),
|
||||||
|
),
|
||||||
|
HomeConnectSensorEntityDescription(
|
||||||
|
key="Drip Tray Full",
|
||||||
|
translation_key="alarm_sensor_coffee_drip_tray",
|
||||||
|
state_key=COFFEE_EVENT_DRIP_TRAY_FULL,
|
||||||
|
appliance_types=("CoffeeMaker",),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
@ -34,10 +100,20 @@ async def async_setup_entry(
|
|||||||
def get_entities():
|
def get_entities():
|
||||||
"""Get a list of entities."""
|
"""Get a list of entities."""
|
||||||
entities = []
|
entities = []
|
||||||
hc_api = hass.data[DOMAIN][config_entry.entry_id]
|
hc_api: ConfigEntryAuth = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
for device_dict in hc_api.devices:
|
for device_dict in hc_api.devices:
|
||||||
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("sensor", [])
|
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("sensor", [])
|
||||||
entities += [HomeConnectSensor(**d) for d in entity_dicts]
|
entities += [HomeConnectSensor(**d) for d in entity_dicts]
|
||||||
|
device: HomeConnectDevice = device_dict[ATTR_DEVICE]
|
||||||
|
# Auto-discover entities
|
||||||
|
entities.extend(
|
||||||
|
HomeConnectAlarmSensor(
|
||||||
|
device,
|
||||||
|
entity_description=description,
|
||||||
|
)
|
||||||
|
for description in SENSORS
|
||||||
|
if device.appliance.type in description.appliance_types
|
||||||
|
)
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
||||||
@ -101,3 +177,37 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
-1
|
-1
|
||||||
]
|
]
|
||||||
_LOGGER.debug("Updated, new state: %s", self._attr_native_value)
|
_LOGGER.debug("Updated, new state: %s", self._attr_native_value)
|
||||||
|
|
||||||
|
|
||||||
|
class HomeConnectAlarmSensor(HomeConnectEntity, SensorEntity):
|
||||||
|
"""Sensor entity setup using SensorEntityDescription."""
|
||||||
|
|
||||||
|
entity_description: HomeConnectSensorEntityDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: HomeConnectDevice,
|
||||||
|
entity_description: HomeConnectSensorEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the entity."""
|
||||||
|
self.entity_description = entity_description
|
||||||
|
super().__init__(device, self.entity_description.key)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return true if the sensor is available."""
|
||||||
|
return self._attr_native_value is not None
|
||||||
|
|
||||||
|
async def async_update(self) -> None:
|
||||||
|
"""Update the sensor's status."""
|
||||||
|
self._attr_native_value = (
|
||||||
|
self.device.appliance.status.get(self.entity_description.state_key, {})
|
||||||
|
.get(ATTR_VALUE, BSH_EVENT_PRESENT_STATE_OFF)
|
||||||
|
.rsplit(".", maxsplit=1)[-1]
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Updated: %s, new state: %s",
|
||||||
|
self._attr_unique_id,
|
||||||
|
self._attr_native_value,
|
||||||
|
)
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
{
|
{
|
||||||
|
"common": {
|
||||||
|
"confirmed": "Confirmed",
|
||||||
|
"present": "Present"
|
||||||
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"step": {
|
"step": {
|
||||||
"pick_implementation": {
|
"pick_implementation": {
|
||||||
@ -129,5 +133,45 @@
|
|||||||
"value": { "name": "Value", "description": "Value of the setting." }
|
"value": { "name": "Value", "description": "Value of the setting." }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"entity": {
|
||||||
|
"sensor": {
|
||||||
|
"alarm_sensor_fridge": {
|
||||||
|
"state": {
|
||||||
|
"confirmed": "[%key:component::home_connect::common::confirmed%]",
|
||||||
|
"present": "[%key:component::home_connect::common::present%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_freezer": {
|
||||||
|
"state": {
|
||||||
|
"confirmed": "[%key:component::home_connect::common::confirmed%]",
|
||||||
|
"present": "[%key:component::home_connect::common::present%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_temp": {
|
||||||
|
"state": {
|
||||||
|
"confirmed": "[%key:component::home_connect::common::confirmed%]",
|
||||||
|
"present": "[%key:component::home_connect::common::present%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_coffee_bean_container": {
|
||||||
|
"state": {
|
||||||
|
"confirmed": "[%key:component::home_connect::common::confirmed%]",
|
||||||
|
"present": "[%key:component::home_connect::common::present%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_coffee_water_tank": {
|
||||||
|
"state": {
|
||||||
|
"confirmed": "[%key:component::home_connect::common::confirmed%]",
|
||||||
|
"present": "[%key:component::home_connect::common::present%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alarm_sensor_coffee_drip_tray": {
|
||||||
|
"state": {
|
||||||
|
"confirmed": "[%key:component::home_connect::common::confirmed%]",
|
||||||
|
"present": "[%key:component::home_connect::common::present%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
{
|
{
|
||||||
"key": "BSH.Common.Status.DoorState",
|
"key": "BSH.Common.Status.DoorState",
|
||||||
"value": "BSH.Common.EnumType.DoorState.Closed"
|
"value": "BSH.Common.EnumType.DoorState.Closed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Refrigeration.Common.Status.Door.Refrigerator",
|
||||||
|
"value": "BSH.Common.EnumType.DoorState.Open"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Awaitable, Callable
|
||||||
from unittest.mock import MagicMock, Mock
|
from unittest.mock import MagicMock, Mock
|
||||||
|
|
||||||
|
from homeconnect.api import HomeConnectAPI
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.home_connect.const import (
|
from homeassistant.components.home_connect.const import (
|
||||||
@ -10,13 +11,16 @@ from homeassistant.components.home_connect.const import (
|
|||||||
BSH_DOOR_STATE_CLOSED,
|
BSH_DOOR_STATE_CLOSED,
|
||||||
BSH_DOOR_STATE_LOCKED,
|
BSH_DOOR_STATE_LOCKED,
|
||||||
BSH_DOOR_STATE_OPEN,
|
BSH_DOOR_STATE_OPEN,
|
||||||
|
REFRIGERATION_STATUS_DOOR_CLOSED,
|
||||||
|
REFRIGERATION_STATUS_DOOR_OPEN,
|
||||||
|
REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_component import async_update_entity
|
from homeassistant.helpers.entity_component import async_update_entity
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry, load_json_object_fixture
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -70,3 +74,59 @@ async def test_binary_sensors_door_states(
|
|||||||
await async_update_entity(hass, entity_id)
|
await async_update_entity(hass, entity_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.is_state(entity_id, expected)
|
assert hass.states.is_state(entity_id, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("entity_id", "status_key", "event_value_update", "expected", "appliance"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"binary_sensor.fridgefreezer_refrigerator_door",
|
||||||
|
REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
|
REFRIGERATION_STATUS_DOOR_CLOSED,
|
||||||
|
STATE_OFF,
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"binary_sensor.fridgefreezer_refrigerator_door",
|
||||||
|
REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
|
REFRIGERATION_STATUS_DOOR_OPEN,
|
||||||
|
STATE_ON,
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"binary_sensor.fridgefreezer_refrigerator_door",
|
||||||
|
REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
|
"",
|
||||||
|
STATE_UNAVAILABLE,
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
indirect=["appliance"],
|
||||||
|
)
|
||||||
|
@pytest.mark.usefixtures("bypass_throttle")
|
||||||
|
async def test_bianry_sensors_fridge_door_states(
|
||||||
|
entity_id: str,
|
||||||
|
status_key: str,
|
||||||
|
event_value_update: str,
|
||||||
|
appliance: Mock,
|
||||||
|
expected: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
integration_setup: Callable[[], Awaitable[bool]],
|
||||||
|
setup_credentials: None,
|
||||||
|
get_appliances: MagicMock,
|
||||||
|
) -> None:
|
||||||
|
"""Tests for Home Connect Fridge appliance door states."""
|
||||||
|
appliance.status.update(
|
||||||
|
HomeConnectAPI.json2dict(
|
||||||
|
load_json_object_fixture("home_connect/status.json")["data"]["status"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
get_appliances.return_value = [appliance]
|
||||||
|
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||||
|
assert await integration_setup()
|
||||||
|
assert config_entry.state == ConfigEntryState.LOADED
|
||||||
|
appliance.status.update({status_key: {"value": event_value_update}})
|
||||||
|
await async_update_entity(hass, entity_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.is_state(entity_id, expected)
|
||||||
|
@ -4,14 +4,22 @@ from collections.abc import Awaitable, Callable
|
|||||||
from unittest.mock import MagicMock, Mock
|
from unittest.mock import MagicMock, Mock
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
|
from homeconnect.api import HomeConnectAPI
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.home_connect.const import (
|
||||||
|
BSH_EVENT_PRESENT_STATE_CONFIRMED,
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF,
|
||||||
|
BSH_EVENT_PRESENT_STATE_PRESENT,
|
||||||
|
COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_component import async_update_entity
|
from homeassistant.helpers.entity_component import async_update_entity
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry, load_json_object_fixture
|
||||||
|
|
||||||
TEST_HC_APP = "Dishwasher"
|
TEST_HC_APP = "Dishwasher"
|
||||||
|
|
||||||
@ -207,3 +215,94 @@ async def test_remaining_prog_time_edge_cases(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
freezer.tick()
|
freezer.tick()
|
||||||
assert hass.states.is_state(entity_id, expected_state)
|
assert hass.states.is_state(entity_id, expected_state)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("entity_id", "status_key", "event_value_update", "expected", "appliance"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_door_alarm_freezer",
|
||||||
|
"EVENT_NOT_IN_STATUS_YET_SO_SET_TO_OFF",
|
||||||
|
"",
|
||||||
|
"off",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_door_alarm_freezer",
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF,
|
||||||
|
"off",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_door_alarm_freezer",
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
BSH_EVENT_PRESENT_STATE_PRESENT,
|
||||||
|
"present",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_door_alarm_freezer",
|
||||||
|
REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
BSH_EVENT_PRESENT_STATE_CONFIRMED,
|
||||||
|
"confirmed",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
"EVENT_NOT_IN_STATUS_YET_SO_SET_TO_OFF",
|
||||||
|
"",
|
||||||
|
"off",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF,
|
||||||
|
"off",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
BSH_EVENT_PRESENT_STATE_PRESENT,
|
||||||
|
"present",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
BSH_EVENT_PRESENT_STATE_CONFIRMED,
|
||||||
|
"confirmed",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
indirect=["appliance"],
|
||||||
|
)
|
||||||
|
@pytest.mark.usefixtures("bypass_throttle")
|
||||||
|
async def test_sensors_states(
|
||||||
|
entity_id: str,
|
||||||
|
status_key: str,
|
||||||
|
event_value_update: str,
|
||||||
|
appliance: Mock,
|
||||||
|
expected: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
integration_setup: Callable[[], Awaitable[bool]],
|
||||||
|
setup_credentials: None,
|
||||||
|
get_appliances: MagicMock,
|
||||||
|
) -> None:
|
||||||
|
"""Tests for Appliance alarm sensors."""
|
||||||
|
appliance.status.update(
|
||||||
|
HomeConnectAPI.json2dict(
|
||||||
|
load_json_object_fixture("home_connect/status.json")["data"]["status"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
get_appliances.return_value = [appliance]
|
||||||
|
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||||
|
assert await integration_setup()
|
||||||
|
assert config_entry.state == ConfigEntryState.LOADED
|
||||||
|
appliance.status.update({status_key: {"value": event_value_update}})
|
||||||
|
await async_update_entity(hass, entity_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.is_state(entity_id, expected)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user