Add miele binary_sensor platform (#142903)

* Add binary_sensor platform

* Address review comments

* Adjust icons and names.

* Change Info to Notification active

* Trigger CI

* Trig CI

* Adjust tests

* Update strings.json

* Update strings.json
This commit is contained in:
Åke Strandberg 2025-04-25 19:32:08 +02:00 committed by GitHub
parent 94b0800989
commit a057effad5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1432 additions and 0 deletions

View File

@ -18,6 +18,7 @@ from .const import DOMAIN
from .coordinator import MieleConfigEntry, MieleDataUpdateCoordinator
PLATFORMS: list[Platform] = [
Platform.BINARY_SENSOR,
Platform.BUTTON,
Platform.CLIMATE,
Platform.LIGHT,

View File

@ -0,0 +1,283 @@
"""Binary sensor platform for Miele integration."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import logging
from typing import Final, cast
from pymiele import MieleDevice
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import MieleAppliance
from .coordinator import MieleConfigEntry
from .entity import MieleEntity
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class MieleBinarySensorDescription(BinarySensorEntityDescription):
"""Class describing Miele binary sensor entities."""
value_fn: Callable[[MieleDevice], StateType]
@dataclass
class MieleBinarySensorDefinition:
"""Class for defining binary sensor entities."""
types: tuple[MieleAppliance, ...]
description: MieleBinarySensorDescription
BINARY_SENSOR_TYPES: Final[tuple[MieleBinarySensorDefinition, ...]] = (
MieleBinarySensorDefinition(
types=(
MieleAppliance.DISH_WARMER,
MieleAppliance.DISHWASHER,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
MieleAppliance.FRIDGE,
MieleAppliance.MICROWAVE,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.OVEN,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.STEAM_OVEN_MK2,
MieleAppliance.STEAM_OVEN,
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.TUMBLE_DRYER,
MieleAppliance.WASHER_DRYER,
MieleAppliance.WASHING_MACHINE_SEMI_PROFESSIONAL,
MieleAppliance.WASHING_MACHINE,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
),
description=MieleBinarySensorDescription(
key="state_signal_door",
value_fn=lambda value: value.state_signal_door,
device_class=BinarySensorDeviceClass.DOOR,
),
),
MieleBinarySensorDefinition(
types=(
MieleAppliance.WASHING_MACHINE,
MieleAppliance.WASHING_MACHINE_SEMI_PROFESSIONAL,
MieleAppliance.TUMBLE_DRYER,
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.DISHWASHER,
MieleAppliance.OVEN,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.STEAM_OVEN,
MieleAppliance.MICROWAVE,
MieleAppliance.COFFEE_SYSTEM,
MieleAppliance.HOOD,
MieleAppliance.FRIDGE,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
MieleAppliance.ROBOT_VACUUM_CLEANER,
MieleAppliance.WASHER_DRYER,
MieleAppliance.DISH_WARMER,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.DIALOG_OVEN,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.STEAM_OVEN_MK2,
),
description=MieleBinarySensorDescription(
key="state_signal_info",
value_fn=lambda value: value.state_signal_info,
device_class=BinarySensorDeviceClass.PROBLEM,
translation_key="notification_active",
entity_category=EntityCategory.DIAGNOSTIC,
),
),
MieleBinarySensorDefinition(
types=(
MieleAppliance.COFFEE_SYSTEM,
MieleAppliance.DIALOG_OVEN,
MieleAppliance.DISH_WARMER,
MieleAppliance.DISHWASHER,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
MieleAppliance.FRIDGE,
MieleAppliance.HOB_HIGHLIGHT,
MieleAppliance.HOB_INDUCT_EXTR,
MieleAppliance.HOB_INDUCTION,
MieleAppliance.HOOD,
MieleAppliance.MICROWAVE,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.OVEN,
MieleAppliance.ROBOT_VACUUM_CLEANER,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.STEAM_OVEN_MK2,
MieleAppliance.STEAM_OVEN,
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.TUMBLE_DRYER,
MieleAppliance.WASHER_DRYER,
MieleAppliance.WASHING_MACHINE_SEMI_PROFESSIONAL,
MieleAppliance.WASHING_MACHINE,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
),
description=MieleBinarySensorDescription(
key="state_signal_failure",
value_fn=lambda value: value.state_signal_failure,
device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC,
),
),
MieleBinarySensorDefinition(
types=(
MieleAppliance.WASHING_MACHINE,
MieleAppliance.WASHING_MACHINE_SEMI_PROFESSIONAL,
MieleAppliance.TUMBLE_DRYER,
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.DISHWASHER,
MieleAppliance.DISH_WARMER,
MieleAppliance.OVEN,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.STEAM_OVEN,
MieleAppliance.MICROWAVE,
MieleAppliance.COFFEE_SYSTEM,
MieleAppliance.HOOD,
MieleAppliance.FRIDGE,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
MieleAppliance.ROBOT_VACUUM_CLEANER,
MieleAppliance.WASHER_DRYER,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.DIALOG_OVEN,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.STEAM_OVEN_MK2,
MieleAppliance.HOB_INDUCT_EXTR,
),
description=MieleBinarySensorDescription(
key="state_full_remote_control",
translation_key="remote_control",
value_fn=lambda value: value.state_full_remote_control,
entity_category=EntityCategory.DIAGNOSTIC,
),
),
MieleBinarySensorDefinition(
types=(
MieleAppliance.WASHING_MACHINE,
MieleAppliance.WASHING_MACHINE_SEMI_PROFESSIONAL,
MieleAppliance.TUMBLE_DRYER,
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.DISHWASHER,
MieleAppliance.OVEN,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.STEAM_OVEN,
MieleAppliance.MICROWAVE,
MieleAppliance.COFFEE_SYSTEM,
MieleAppliance.HOOD,
MieleAppliance.FRIDGE,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
MieleAppliance.ROBOT_VACUUM_CLEANER,
MieleAppliance.WASHER_DRYER,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.DIALOG_OVEN,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.STEAM_OVEN_MK2,
MieleAppliance.HOB_INDUCT_EXTR,
),
description=MieleBinarySensorDescription(
key="state_smart_grid",
value_fn=lambda value: value.state_smart_grid,
translation_key="smart_grid",
entity_category=EntityCategory.DIAGNOSTIC,
),
),
MieleBinarySensorDefinition(
types=(
MieleAppliance.WASHING_MACHINE,
MieleAppliance.WASHING_MACHINE_SEMI_PROFESSIONAL,
MieleAppliance.TUMBLE_DRYER,
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.DISHWASHER,
MieleAppliance.DISH_WARMER,
MieleAppliance.OVEN,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.STEAM_OVEN,
MieleAppliance.MICROWAVE,
MieleAppliance.COFFEE_SYSTEM,
MieleAppliance.HOOD,
MieleAppliance.FRIDGE,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
MieleAppliance.ROBOT_VACUUM_CLEANER,
MieleAppliance.WASHER_DRYER,
MieleAppliance.STEAM_OVEN_COMBI,
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
MieleAppliance.STEAM_OVEN_MICRO,
MieleAppliance.DIALOG_OVEN,
MieleAppliance.WINE_CABINET_FREEZER,
MieleAppliance.STEAM_OVEN_MK2,
MieleAppliance.HOB_INDUCT_EXTR,
),
description=MieleBinarySensorDescription(
key="state_mobile_start",
value_fn=lambda value: value.state_mobile_start,
translation_key="mobile_start",
entity_category=EntityCategory.DIAGNOSTIC,
),
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: MieleConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the binary sensor platform."""
coordinator = config_entry.runtime_data
async_add_entities(
MieleBinarySensor(coordinator, device_id, definition.description)
for device_id, device in coordinator.data.devices.items()
for definition in BINARY_SENSOR_TYPES
if device.device_type in definition.types
)
class MieleBinarySensor(MieleEntity, BinarySensorEntity):
"""Representation of a Binary Sensor."""
entity_description: MieleBinarySensorDescription
@property
def is_on(self) -> bool | None:
"""Return the state of the binary sensor."""
return cast(bool, self.entity_description.value_fn(self.device))

View File

@ -1,5 +1,19 @@
{
"entity": {
"binary_sensor": {
"notification_active": {
"default": "mdi:information"
},
"mobile_start": {
"default": "mdi:cellphone-wireless"
},
"remote_control": {
"default": "mdi:remote"
},
"smart_grid": {
"default": "mdi:view-grid-plus-outline"
}
},
"button": {
"start": {
"default": "mdi:play"

View File

@ -114,6 +114,20 @@
}
},
"entity": {
"binary_sensor": {
"notification_active": {
"name": "Notification active"
},
"mobile_start": {
"name": "Mobile start"
},
"remote_control": {
"name": "Remote control"
},
"smart_grid": {
"name": "Smart grid"
}
},
"button": {
"start": {
"name": "[%key:common::action::start%]"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
"""Tests for miele binary sensor module."""
from unittest.mock import MagicMock
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.parametrize("platforms", [(BINARY_SENSOR_DOMAIN,)])
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_binary_sensor_states(
hass: HomeAssistant,
mock_miele_client: MagicMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
setup_platform: None,
) -> None:
"""Test binary sensor state."""
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)