Discovery of Miele temperature sensors (#144585)

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Andrea Turri 2025-07-15 12:50:28 +02:00 committed by GitHub
parent ee4325a927
commit 7d06aec8da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 4015 additions and 80 deletions

View File

@ -16,6 +16,11 @@ class MieleEntity(CoordinatorEntity[MieleDataUpdateCoordinator]):
_attr_has_entity_name = True
@staticmethod
def get_unique_id(device_id: str, description: EntityDescription) -> str:
"""Generate a unique ID for the entity."""
return f"{device_id}-{description.key}"
def __init__(
self,
coordinator: MieleDataUpdateCoordinator,
@ -26,7 +31,7 @@ class MieleEntity(CoordinatorEntity[MieleDataUpdateCoordinator]):
super().__init__(coordinator)
self._device_id = device_id
self.entity_description = description
self._attr_unique_id = f"{device_id}-{description.key}"
self._attr_unique_id = MieleEntity.get_unique_id(device_id, description)
device = self.device
appliance_type = DEVICE_TYPE_TAGS.get(MieleAppliance(device.device_type))

View File

@ -7,7 +7,7 @@ from dataclasses import dataclass
import logging
from typing import Final, cast
from pymiele import MieleDevice
from pymiele import MieleDevice, MieleTemperature
from homeassistant.components.sensor import (
SensorDeviceClass,
@ -25,10 +25,13 @@ from homeassistant.const import (
UnitOfVolume,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import (
DISABLED_TEMP_ENTITIES,
DOMAIN,
STATE_PROGRAM_ID,
STATE_PROGRAM_PHASE,
STATE_STATUS_TAGS,
@ -45,8 +48,6 @@ PARALLEL_UPDATES = 0
_LOGGER = logging.getLogger(__name__)
DISABLED_TEMPERATURE = -32768
DEFAULT_PLATE_COUNT = 4
PLATE_COUNT = {
@ -75,12 +76,25 @@ def _convert_duration(value_list: list[int]) -> int | None:
return value_list[0] * 60 + value_list[1] if value_list else None
def _convert_temperature(
value_list: list[MieleTemperature], index: int
) -> float | None:
"""Convert temperature object to readable value."""
if index >= len(value_list):
return None
raw_value = cast(int, value_list[index].temperature) / 100.0
if raw_value in DISABLED_TEMP_ENTITIES:
return None
return raw_value
@dataclass(frozen=True, kw_only=True)
class MieleSensorDescription(SensorEntityDescription):
"""Class describing Miele sensor entities."""
value_fn: Callable[[MieleDevice], StateType]
zone: int = 1
zone: int | None = None
unique_id_fn: Callable[[str, MieleSensorDescription], str] | None = None
@dataclass
@ -404,32 +418,20 @@ SENSOR_TYPES: Final[tuple[MieleSensorDefinition, ...]] = (
),
description=MieleSensorDescription(
key="state_temperature_1",
zone=1,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda value: cast(int, value.state_temperatures[0].temperature)
/ 100.0,
value_fn=lambda value: _convert_temperature(value.state_temperatures, 0),
),
),
MieleSensorDefinition(
types=(
MieleAppliance.TUMBLE_DRYER_SEMI_PROFESSIONAL,
MieleAppliance.OVEN,
MieleAppliance.OVEN_MICROWAVE,
MieleAppliance.DISH_WARMER,
MieleAppliance.STEAM_OVEN,
MieleAppliance.MICROWAVE,
MieleAppliance.FRIDGE,
MieleAppliance.FREEZER,
MieleAppliance.FRIDGE_FREEZER,
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=MieleSensorDescription(
key="state_temperature_2",
@ -438,7 +440,24 @@ SENSOR_TYPES: Final[tuple[MieleSensorDefinition, ...]] = (
translation_key="temperature_zone_2",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda value: value.state_temperatures[1].temperature / 100.0, # type: ignore [operator]
value_fn=lambda value: _convert_temperature(value.state_temperatures, 1),
),
),
MieleSensorDefinition(
types=(
MieleAppliance.WINE_CABINET,
MieleAppliance.WINE_CONDITIONING_UNIT,
MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
MieleAppliance.WINE_CABINET_FREEZER,
),
description=MieleSensorDescription(
key="state_temperature_3",
zone=3,
device_class=SensorDeviceClass.TEMPERATURE,
translation_key="temperature_zone_3",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda value: _convert_temperature(value.state_temperatures, 2),
),
),
MieleSensorDefinition(
@ -454,11 +473,8 @@ SENSOR_TYPES: Final[tuple[MieleSensorDefinition, ...]] = (
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=(
lambda value: cast(
int, value.state_core_target_temperature[0].temperature
)
/ 100.0
value_fn=lambda value: _convert_temperature(
value.state_core_target_temperature, 0
),
),
),
@ -479,9 +495,8 @@ SENSOR_TYPES: Final[tuple[MieleSensorDefinition, ...]] = (
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=(
lambda value: cast(int, value.state_target_temperature[0].temperature)
/ 100.0
value_fn=lambda value: _convert_temperature(
value.state_target_temperature, 0
),
),
),
@ -497,9 +512,8 @@ SENSOR_TYPES: Final[tuple[MieleSensorDefinition, ...]] = (
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=(
lambda value: cast(int, value.state_core_temperature[0].temperature)
/ 100.0
value_fn=lambda value: _convert_temperature(
value.state_core_temperature, 0
),
),
),
@ -518,6 +532,8 @@ SENSOR_TYPES: Final[tuple[MieleSensorDefinition, ...]] = (
device_class=SensorDeviceClass.ENUM,
options=sorted(PlatePowerStep.keys()),
value_fn=lambda value: None,
unique_id_fn=lambda device_id,
description: f"{device_id}-{description.key}-{description.zone}",
),
)
for i in range(1, 7)
@ -559,10 +575,52 @@ async def async_setup_entry(
) -> None:
"""Set up the sensor platform."""
coordinator = config_entry.runtime_data
added_devices: set[str] = set()
added_devices: set[str] = set() # device_id
added_entities: set[str] = set() # unique_id
def _async_add_new_devices() -> None:
nonlocal added_devices
def _get_entity_class(definition: MieleSensorDefinition) -> type[MieleSensor]:
"""Get the entity class for the sensor."""
return {
"state_status": MieleStatusSensor,
"state_program_id": MieleProgramIdSensor,
"state_program_phase": MielePhaseSensor,
"state_plate_step": MielePlateSensor,
}.get(definition.description.key, MieleSensor)
def _is_entity_registered(unique_id: str) -> bool:
"""Check if the entity is already registered."""
entity_registry = er.async_get(hass)
return any(
entry.platform == DOMAIN and entry.unique_id == unique_id
for entry in entity_registry.entities.values()
)
def _is_sensor_enabled(
definition: MieleSensorDefinition,
device: MieleDevice,
unique_id: str,
) -> bool:
"""Check if the sensor is enabled."""
if (
definition.description.device_class == SensorDeviceClass.TEMPERATURE
and definition.description.value_fn(device) is None
and definition.description.zone != 1
):
# all appliances supporting temperature have at least zone 1, for other zones
# don't create entity if API signals that datapoint is disabled, unless the sensor
# already appeared in the past (= it provided a valid value)
return _is_entity_registered(unique_id)
if (
definition.description.key == "state_plate_step"
and definition.description.zone is not None
and definition.description.zone > _get_plate_count(device.tech_type)
):
# don't create plate entity if not expected by the appliance tech type
return False
return True
def _async_add_devices() -> None:
nonlocal added_devices, added_entities
entities: list = []
entity_class: type[MieleSensor]
new_devices_set, current_devices = coordinator.async_add_devices(added_devices)
@ -570,40 +628,35 @@ async def async_setup_entry(
for device_id, device in coordinator.data.devices.items():
for definition in SENSOR_TYPES:
if (
device_id in new_devices_set
and device.device_type in definition.types
):
match definition.description.key:
case "state_status":
entity_class = MieleStatusSensor
case "state_program_id":
entity_class = MieleProgramIdSensor
case "state_program_phase":
entity_class = MielePhaseSensor
case "state_plate_step":
entity_class = MielePlateSensor
case _:
entity_class = MieleSensor
if (
definition.description.device_class
== SensorDeviceClass.TEMPERATURE
and definition.description.value_fn(device)
== DISABLED_TEMPERATURE / 100
) or (
definition.description.key == "state_plate_step"
and definition.description.zone
> _get_plate_count(device.tech_type)
):
# Don't create entity if API signals that datapoint is disabled
# device is not supported, skip
if device.device_type not in definition.types:
continue
entity_class = _get_entity_class(definition)
unique_id = (
definition.description.unique_id_fn(
device_id, definition.description
)
if definition.description.unique_id_fn is not None
else MieleEntity.get_unique_id(device_id, definition.description)
)
# entity was already added, skip
if device_id not in new_devices_set and unique_id in added_entities:
continue
# sensors is not enabled, skip
if not _is_sensor_enabled(definition, device, unique_id):
continue
added_entities.add(unique_id)
entities.append(
entity_class(coordinator, device_id, definition.description)
)
async_add_entities(entities)
config_entry.async_on_unload(coordinator.async_add_listener(_async_add_new_devices))
_async_add_new_devices()
config_entry.async_on_unload(coordinator.async_add_listener(_async_add_devices))
_async_add_devices()
APPLIANCE_ICONS = {
@ -641,6 +694,17 @@ class MieleSensor(MieleEntity, SensorEntity):
entity_description: MieleSensorDescription
def __init__(
self,
coordinator: MieleDataUpdateCoordinator,
device_id: str,
description: MieleSensorDescription,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator, device_id, description)
if description.unique_id_fn is not None:
self._attr_unique_id = description.unique_id_fn(device_id, description)
@property
def native_value(self) -> StateType:
"""Return the state of the sensor."""
@ -652,16 +716,6 @@ class MielePlateSensor(MieleSensor):
entity_description: MieleSensorDescription
def __init__(
self,
coordinator: MieleDataUpdateCoordinator,
device_id: str,
description: MieleSensorDescription,
) -> None:
"""Initialize the plate sensor."""
super().__init__(coordinator, device_id, description)
self._attr_unique_id = f"{device_id}-{description.key}-{description.zone}"
@property
def native_value(self) -> StateType:
"""Return the state of the plate sensor."""
@ -672,7 +726,7 @@ class MielePlateSensor(MieleSensor):
cast(
int,
self.device.state_plate_step[
self.entity_description.zone - 1
cast(int, self.entity_description.zone) - 1
].value_raw,
)
).name

View File

@ -82,5 +82,20 @@
"colors": [],
"modes": [],
"runOnTime": []
},
"DummyAppliance_12": {
"processAction": [],
"light": [2],
"ambientLight": [],
"startTime": [],
"ventilationStep": [],
"programId": [],
"targetTemperature": [],
"deviceName": true,
"powerOn": false,
"powerOff": true,
"colors": [],
"modes": [],
"runOnTime": []
}
}

View File

@ -466,5 +466,129 @@
"ecoFeedback": null,
"batteryLevel": null
}
},
"DummyAppliance_12": {
"ident": {
"type": {
"key_localized": "Device type",
"value_raw": 12,
"value_localized": "Oven"
},
"deviceName": "",
"protocolVersion": 4,
"deviceIdentLabel": {
"fabNumber": "**REDACTED**",
"fabIndex": "16",
"techType": "H7660BP",
"matNumber": "11120960",
"swids": []
},
"xkmIdentLabel": {
"techType": "EK057",
"releaseVersion": "08.32"
}
},
"state": {
"ProgramID": {
"value_raw": 356,
"value_localized": "Defrost",
"key_localized": "Program name"
},
"status": {
"value_raw": 5,
"value_localized": "In use",
"key_localized": "status"
},
"programType": {
"value_raw": 1,
"value_localized": "Program",
"key_localized": "Program type"
},
"programPhase": {
"value_raw": 3073,
"value_localized": "Heating-up phase",
"key_localized": "Program phase"
},
"remainingTime": [0, 5],
"startTime": [0, 0],
"targetTemperature": [
{
"value_raw": 2500,
"value_localized": 25.0,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"coreTargetTemperature": [
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"temperature": [
{
"value_raw": 1954,
"value_localized": 19.54,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"coreTemperature": [
{
"value_raw": 2200,
"value_localized": 22.0,
"unit": "Celsius"
}
],
"signalInfo": false,
"signalFailure": false,
"signalDoor": false,
"remoteEnable": {
"fullRemoteControl": true,
"smartGrid": false,
"mobileStart": true
},
"ambientLight": null,
"light": 1,
"elapsedTime": [0, 0],
"spinningSpeed": {
"unit": "rpm",
"value_raw": null,
"value_localized": null,
"key_localized": "Spin speed"
},
"dryingStep": {
"value_raw": null,
"value_localized": "",
"key_localized": "Drying level"
},
"ventilationStep": {
"value_raw": null,
"value_localized": "",
"key_localized": "Fan level"
},
"plateStep": [],
"ecoFeedback": null,
"batteryLevel": null
}
}
}

View File

@ -0,0 +1,109 @@
{
"DummyAppliance_Fridge_Freezer": {
"ident": {
"type": {
"key_localized": "Device type",
"value_raw": 21,
"value_localized": "Fridge freezer"
},
"deviceName": "",
"protocolVersion": 203,
"deviceIdentLabel": {
"fabNumber": "**REDACTED**",
"fabIndex": "00",
"techType": "KFN 7734 C",
"matNumber": "12336150",
"swids": []
},
"xkmIdentLabel": {
"techType": "EK037LHBM",
"releaseVersion": "32.33"
}
},
"state": {
"ProgramID": {
"value_raw": 0,
"value_localized": "",
"key_localized": "Program name"
},
"status": {
"value_raw": 5,
"value_localized": "In use",
"key_localized": "status"
},
"programType": {
"value_raw": 0,
"value_localized": "",
"key_localized": "Program type"
},
"programPhase": {
"value_raw": 0,
"value_localized": "",
"key_localized": "Program phase"
},
"remainingTime": [0, 0],
"startTime": [0, 0],
"targetTemperature": [
{
"value_raw": 400,
"value_localized": 4.0,
"unit": "Celsius"
},
{
"value_raw": -1800,
"value_localized": -18.0,
"unit": "Celsius"
}
],
"coreTargetTemperature": [],
"temperature": [
{
"value_raw": 400,
"value_localized": 4.0,
"unit": "Celsius"
},
{
"value_raw": -1800,
"value_localized": -18.0,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"coreTemperature": [],
"signalInfo": false,
"signalFailure": false,
"signalDoor": false,
"remoteEnable": {
"fullRemoteControl": true,
"smartGrid": false,
"mobileStart": false
},
"ambientLight": null,
"light": null,
"elapsedTime": [],
"spinningSpeed": {
"unit": "rpm",
"value_raw": null,
"value_localized": null,
"key_localized": "Spin speed"
},
"dryingStep": {
"value_raw": null,
"value_localized": "",
"key_localized": "Drying level"
},
"ventilationStep": {
"value_raw": null,
"value_localized": "",
"key_localized": "Fan level"
},
"plateStep": [],
"ecoFeedback": null,
"batteryLevel": null
}
}
}

View File

@ -0,0 +1,142 @@
{
"DummyOven": {
"ident": {
"type": {
"key_localized": "Device type",
"value_raw": 12,
"value_localized": "Oven"
},
"deviceName": "",
"protocolVersion": 4,
"deviceIdentLabel": {
"fabNumber": "**REDACTED**",
"fabIndex": "16",
"techType": "H7660BP",
"matNumber": "11120960",
"swids": [
"6166",
"25211",
"25210",
"4860",
"25245",
"6153",
"6050",
"25300",
"25307",
"25247",
"20570",
"25223",
"5640",
"20366",
"20462"
]
},
"xkmIdentLabel": {
"techType": "EK057",
"releaseVersion": "08.32"
}
},
"state": {
"ProgramID": {
"value_raw": 0,
"value_localized": "",
"key_localized": "Program name"
},
"status": {
"value_raw": 1,
"value_localized": "Off",
"key_localized": "status"
},
"programType": {
"value_raw": 0,
"value_localized": "",
"key_localized": "Program type"
},
"programPhase": {
"value_raw": 0,
"value_localized": "",
"key_localized": "Program phase"
},
"remainingTime": [0, 0],
"startTime": [0, 0],
"targetTemperature": [
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"coreTargetTemperature": [
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"temperature": [
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
},
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"coreTemperature": [
{
"value_raw": -32768,
"value_localized": null,
"unit": "Celsius"
}
],
"signalInfo": false,
"signalFailure": false,
"signalDoor": false,
"remoteEnable": {
"fullRemoteControl": true,
"smartGrid": false,
"mobileStart": false
},
"ambientLight": null,
"light": null,
"elapsedTime": [0, 0],
"spinningSpeed": {
"unit": "rpm",
"value_raw": null,
"value_localized": null,
"key_localized": "Spin speed"
},
"dryingStep": {
"value_raw": null,
"value_localized": "",
"key_localized": "Drying level"
},
"ventilationStep": {
"value_raw": null,
"value_localized": "",
"key_localized": "Fan level"
},
"plateStep": [],
"ecoFeedback": null,
"batteryLevel": null
}
}
}

View File

@ -532,6 +532,297 @@
'state': 'off',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_door-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.oven_door',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
'original_icon': None,
'original_name': 'Door',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'DummyAppliance_12-state_signal_door',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_door-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'door',
'friendly_name': 'Oven Door',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_door',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_mobile_start-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_mobile_start',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Mobile start',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'mobile_start',
'unique_id': 'DummyAppliance_12-state_mobile_start',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_mobile_start-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Mobile start',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_mobile_start',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_notification_active-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_notification_active',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
'original_icon': None,
'original_name': 'Notification active',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'notification_active',
'unique_id': 'DummyAppliance_12-state_signal_info',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_notification_active-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'problem',
'friendly_name': 'Oven Notification active',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_notification_active',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_problem-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_problem',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
'original_icon': None,
'original_name': 'Problem',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'DummyAppliance_12-state_signal_failure',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_problem-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'problem',
'friendly_name': 'Oven Problem',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_problem',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_remote_control-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_remote_control',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Remote control',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'remote_control',
'unique_id': 'DummyAppliance_12-state_full_remote_control',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_remote_control-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Remote control',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_remote_control',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_smart_grid-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_smart_grid',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Smart grid',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'smart_grid',
'unique_id': 'DummyAppliance_12-state_smart_grid',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.oven_smart_grid-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Smart grid',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_smart_grid',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states[platforms0][binary_sensor.refrigerator_door-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -1647,6 +1938,297 @@
'state': 'off',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_door-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.oven_door',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.DOOR: 'door'>,
'original_icon': None,
'original_name': 'Door',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'DummyAppliance_12-state_signal_door',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_door-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'door',
'friendly_name': 'Oven Door',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_door',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_mobile_start-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_mobile_start',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Mobile start',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'mobile_start',
'unique_id': 'DummyAppliance_12-state_mobile_start',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_mobile_start-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Mobile start',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_mobile_start',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_notification_active-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_notification_active',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
'original_icon': None,
'original_name': 'Notification active',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'notification_active',
'unique_id': 'DummyAppliance_12-state_signal_info',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_notification_active-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'problem',
'friendly_name': 'Oven Notification active',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_notification_active',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_problem-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_problem',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PROBLEM: 'problem'>,
'original_icon': None,
'original_name': 'Problem',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'DummyAppliance_12-state_signal_failure',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_problem-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'problem',
'friendly_name': 'Oven Problem',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_problem',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_remote_control-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_remote_control',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Remote control',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'remote_control',
'unique_id': 'DummyAppliance_12-state_full_remote_control',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_remote_control-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Remote control',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_remote_control',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_smart_grid-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.oven_smart_grid',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Smart grid',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'smart_grid',
'unique_id': 'DummyAppliance_12-state_smart_grid',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.oven_smart_grid-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Smart grid',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.oven_smart_grid',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_states_api_push[platforms0][binary_sensor.refrigerator_door-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@ -47,6 +47,102 @@
'state': 'unknown',
})
# ---
# name: test_button_states[platforms0][button.oven_start-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'button',
'entity_category': None,
'entity_id': 'button.oven_start',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Start',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'start',
'unique_id': 'DummyAppliance_12-start',
'unit_of_measurement': None,
})
# ---
# name: test_button_states[platforms0][button.oven_start-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Start',
}),
'context': <ANY>,
'entity_id': 'button.oven_start',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_button_states[platforms0][button.oven_stop-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'button',
'entity_category': None,
'entity_id': 'button.oven_stop',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Stop',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'stop',
'unique_id': 'DummyAppliance_12-stop',
'unit_of_measurement': None,
})
# ---
# name: test_button_states[platforms0][button.oven_stop-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Stop',
}),
'context': <ANY>,
'entity_id': 'button.oven_stop',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_button_states[platforms0][button.washing_machine_pause-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -239,6 +335,102 @@
'state': 'unavailable',
})
# ---
# name: test_button_states_api_push[platforms0][button.oven_start-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'button',
'entity_category': None,
'entity_id': 'button.oven_start',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Start',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'start',
'unique_id': 'DummyAppliance_12-start',
'unit_of_measurement': None,
})
# ---
# name: test_button_states_api_push[platforms0][button.oven_start-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Start',
}),
'context': <ANY>,
'entity_id': 'button.oven_start',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_button_states_api_push[platforms0][button.oven_stop-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'button',
'entity_category': None,
'entity_id': 'button.oven_stop',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Stop',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'stop',
'unique_id': 'DummyAppliance_12-stop',
'unit_of_measurement': None,
})
# ---
# name: test_button_states_api_push[platforms0][button.oven_stop-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Stop',
}),
'context': <ANY>,
'entity_id': 'button.oven_stop',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_button_states_api_push[platforms0][button.washing_machine_pause-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@ -144,6 +144,39 @@
'ventilationStep': list([
]),
}),
'**REDACTED_e7bc6793e305bf53': dict({
'ambientLight': list([
]),
'colors': list([
]),
'deviceName': True,
'light': list([
]),
'modes': list([
]),
'powerOff': False,
'powerOn': True,
'processAction': list([
1,
2,
3,
]),
'programId': list([
]),
'runOnTime': list([
]),
'startTime': list([
]),
'targetTemperature': list([
dict({
'max': 28,
'min': -28,
'zone': 1,
}),
]),
'ventilationStep': list([
]),
}),
}),
'devices': dict({
'**REDACTED_019aa577ad1c330d': dict({
@ -661,6 +694,141 @@
}),
}),
}),
'**REDACTED_e7bc6793e305bf53': dict({
'ident': dict({
'deviceIdentLabel': dict({
'fabIndex': '16',
'fabNumber': '**REDACTED**',
'matNumber': '11120960',
'swids': list([
]),
'techType': 'H7660BP',
}),
'deviceName': '',
'protocolVersion': 4,
'type': dict({
'key_localized': 'Device type',
'value_localized': 'Oven',
'value_raw': 12,
}),
'xkmIdentLabel': dict({
'releaseVersion': '08.32',
'techType': 'EK057',
}),
}),
'state': dict({
'ProgramID': dict({
'key_localized': 'Program name',
'value_localized': 'Defrost',
'value_raw': 356,
}),
'ambientLight': None,
'batteryLevel': None,
'coreTargetTemperature': list([
dict({
'unit': 'Celsius',
'value_localized': None,
'value_raw': -32768,
}),
]),
'coreTemperature': list([
dict({
'unit': 'Celsius',
'value_localized': 22.0,
'value_raw': 2200,
}),
]),
'dryingStep': dict({
'key_localized': 'Drying level',
'value_localized': '',
'value_raw': None,
}),
'ecoFeedback': None,
'elapsedTime': list([
0,
0,
]),
'light': 1,
'plateStep': list([
]),
'programPhase': dict({
'key_localized': 'Program phase',
'value_localized': 'Heating-up phase',
'value_raw': 3073,
}),
'programType': dict({
'key_localized': 'Program type',
'value_localized': 'Program',
'value_raw': 1,
}),
'remainingTime': list([
0,
5,
]),
'remoteEnable': dict({
'fullRemoteControl': True,
'mobileStart': True,
'smartGrid': False,
}),
'signalDoor': False,
'signalFailure': False,
'signalInfo': False,
'spinningSpeed': dict({
'key_localized': 'Spin speed',
'unit': 'rpm',
'value_localized': None,
'value_raw': None,
}),
'startTime': list([
0,
0,
]),
'status': dict({
'key_localized': 'status',
'value_localized': 'In use',
'value_raw': 5,
}),
'targetTemperature': list([
dict({
'unit': 'Celsius',
'value_localized': 25.0,
'value_raw': 2500,
}),
dict({
'unit': 'Celsius',
'value_localized': None,
'value_raw': -32768,
}),
dict({
'unit': 'Celsius',
'value_localized': None,
'value_raw': -32768,
}),
]),
'temperature': list([
dict({
'unit': 'Celsius',
'value_localized': 19.54,
'value_raw': 1954,
}),
dict({
'unit': 'Celsius',
'value_localized': None,
'value_raw': -32768,
}),
dict({
'unit': 'Celsius',
'value_localized': None,
'value_raw': -32768,
}),
]),
'ventilationStep': dict({
'key_localized': 'Fan level',
'value_localized': '',
'value_raw': None,
}),
}),
}),
}),
'missing_code_warnings': list([
'None',

View File

@ -113,6 +113,63 @@
'state': 'on',
})
# ---
# name: test_light_states[platforms0][light.oven_light-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'supported_color_modes': list([
<ColorMode.ONOFF: 'onoff'>,
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.oven_light',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Light',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'light',
'unique_id': 'DummyAppliance_12-light',
'unit_of_measurement': None,
})
# ---
# name: test_light_states[platforms0][light.oven_light-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'color_mode': <ColorMode.ONOFF: 'onoff'>,
'friendly_name': 'Oven Light',
'supported_color_modes': list([
<ColorMode.ONOFF: 'onoff'>,
]),
'supported_features': <LightEntityFeature: 0>,
}),
'context': <ANY>,
'entity_id': 'light.oven_light',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_light_states_api_push[platforms0][light.hood_ambient_light-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -227,3 +284,60 @@
'state': 'on',
})
# ---
# name: test_light_states_api_push[platforms0][light.oven_light-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'supported_color_modes': list([
<ColorMode.ONOFF: 'onoff'>,
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'light',
'entity_category': None,
'entity_id': 'light.oven_light',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Light',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'light',
'unique_id': 'DummyAppliance_12-light',
'unit_of_measurement': None,
})
# ---
# name: test_light_states_api_push[platforms0][light.oven_light-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'color_mode': <ColorMode.ONOFF: 'onoff'>,
'friendly_name': 'Oven Light',
'supported_color_modes': list([
<ColorMode.ONOFF: 'onoff'>,
]),
'supported_features': <LightEntityFeature: 0>,
}),
'context': <ANY>,
'entity_id': 'light.oven_light',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---

File diff suppressed because it is too large Load Diff

View File

@ -95,6 +95,54 @@
'state': 'off',
})
# ---
# name: test_switch_states[platforms0][switch.oven_power-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.oven_power',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Power',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'power',
'unique_id': 'DummyAppliance_12-poweronoff',
'unit_of_measurement': None,
})
# ---
# name: test_switch_states[platforms0][switch.oven_power-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Power',
}),
'context': <ANY>,
'entity_id': 'switch.oven_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_switch_states[platforms0][switch.refrigerator_supercooling-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -287,6 +335,54 @@
'state': 'off',
})
# ---
# name: test_switch_states_api_push[platforms0][switch.oven_power-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.oven_power',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Power',
'platform': 'miele',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'power',
'unique_id': 'DummyAppliance_12-poweronoff',
'unit_of_measurement': None,
})
# ---
# name: test_switch_states_api_push[platforms0][switch.oven_power-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Oven Power',
}),
'context': <ANY>,
'entity_id': 'switch.oven_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switch_states_api_push[platforms0][switch.refrigerator_supercooling-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@ -109,7 +109,7 @@ async def test_devices_multiple_created_count(
"""Test that multiple devices are created."""
await setup_integration(hass, mock_config_entry)
assert len(device_registry.devices) == 4
assert len(device_registry.devices) == 5
async def test_device_info(
@ -200,11 +200,13 @@ async def test_setup_all_platforms(
)
freezer.tick(timedelta(seconds=130))
prev_devices = len(device_registry.devices)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert len(device_registry.devices) == 6
assert len(device_registry.devices) == prev_devices + 2
# Check a sample sensor for each new device
assert hass.states.get("sensor.dishwasher").state == "in_use"
assert hass.states.get("sensor.oven_temperature").state == "175.0"
assert hass.states.get("sensor.oven_temperature_2").state == "175.0"

View File

@ -1,15 +1,24 @@
"""Tests for miele sensor module."""
from datetime import timedelta
from unittest.mock import MagicMock
from freezegun.api import FrozenDateTimeFactory
from pymiele import MieleDevices
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.miele.const import DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry, snapshot_platform
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
async_load_json_object_fixture,
snapshot_platform,
)
@pytest.mark.parametrize("platforms", [(SENSOR_DOMAIN,)])
@ -56,6 +65,184 @@ async def test_hob_sensor_states(
await snapshot_platform(hass, entity_registry, snapshot, setup_platform.entry_id)
@pytest.mark.parametrize("load_device_file", ["fridge_freezer.json"])
@pytest.mark.parametrize("platforms", [(SENSOR_DOMAIN,)])
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_fridge_freezer_sensor_states(
hass: HomeAssistant,
mock_miele_client: MagicMock,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
setup_platform: None,
) -> None:
"""Test sensor state."""
await snapshot_platform(hass, entity_registry, snapshot, setup_platform.entry_id)
@pytest.mark.parametrize("load_device_file", ["oven.json"])
@pytest.mark.parametrize("platforms", [(SENSOR_DOMAIN,)])
async def test_oven_temperatures_scenario(
hass: HomeAssistant,
mock_miele_client: MagicMock,
setup_platform: None,
mock_config_entry: MockConfigEntry,
device_fixture: MieleDevices,
freezer: FrozenDateTimeFactory,
) -> None:
"""Parametrized test for verifying temperature sensors for oven devices."""
# Initial state when the oven is and created for the first time - don't know if it supports core temperature (probe)
check_sensor_state(hass, "sensor.oven_temperature", "unknown", 0)
check_sensor_state(hass, "sensor.oven_target_temperature", "unknown", 0)
check_sensor_state(hass, "sensor.oven_core_temperature", None, 0)
check_sensor_state(hass, "sensor.oven_core_target_temperature", None, 0)
# Simulate temperature settings, no probe temperature
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_raw"] = 8000
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_localized"] = (
80.0
)
device_fixture["DummyOven"]["state"]["temperature"][0]["value_raw"] = 2150
device_fixture["DummyOven"]["state"]["temperature"][0]["value_localized"] = 21.5
freezer.tick(timedelta(seconds=130))
async_fire_time_changed(hass)
await hass.async_block_till_done()
check_sensor_state(hass, "sensor.oven_temperature", "21.5", 1)
check_sensor_state(hass, "sensor.oven_target_temperature", "80.0", 1)
check_sensor_state(hass, "sensor.oven_core_temperature", None, 1)
check_sensor_state(hass, "sensor.oven_core_target_temperature", None, 1)
# Simulate unsetting temperature
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_raw"] = -32768
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_localized"] = (
None
)
device_fixture["DummyOven"]["state"]["temperature"][0]["value_raw"] = -32768
device_fixture["DummyOven"]["state"]["temperature"][0]["value_localized"] = None
freezer.tick(timedelta(seconds=130))
async_fire_time_changed(hass)
await hass.async_block_till_done()
check_sensor_state(hass, "sensor.oven_temperature", "unknown", 2)
check_sensor_state(hass, "sensor.oven_target_temperature", "unknown", 2)
check_sensor_state(hass, "sensor.oven_core_temperature", None, 2)
check_sensor_state(hass, "sensor.oven_core_target_temperature", None, 2)
# Simulate temperature settings with probe temperature
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_raw"] = 8000
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_localized"] = (
80.0
)
device_fixture["DummyOven"]["state"]["coreTargetTemperature"][0]["value_raw"] = 3000
device_fixture["DummyOven"]["state"]["coreTargetTemperature"][0][
"value_localized"
] = 30.0
device_fixture["DummyOven"]["state"]["temperature"][0]["value_raw"] = 2183
device_fixture["DummyOven"]["state"]["temperature"][0]["value_localized"] = 21.83
device_fixture["DummyOven"]["state"]["coreTemperature"][0]["value_raw"] = 2200
device_fixture["DummyOven"]["state"]["coreTemperature"][0]["value_localized"] = 22.0
freezer.tick(timedelta(seconds=130))
async_fire_time_changed(hass)
await hass.async_block_till_done()
check_sensor_state(hass, "sensor.oven_temperature", "21.83", 3)
check_sensor_state(hass, "sensor.oven_target_temperature", "80.0", 3)
check_sensor_state(hass, "sensor.oven_core_temperature", "22.0", 2)
check_sensor_state(hass, "sensor.oven_core_target_temperature", "30.0", 3)
# Simulate unsetting temperature
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_raw"] = -32768
device_fixture["DummyOven"]["state"]["targetTemperature"][0]["value_localized"] = (
None
)
device_fixture["DummyOven"]["state"]["coreTargetTemperature"][0][
"value_raw"
] = -32768
device_fixture["DummyOven"]["state"]["coreTargetTemperature"][0][
"value_localized"
] = None
device_fixture["DummyOven"]["state"]["temperature"][0]["value_raw"] = -32768
device_fixture["DummyOven"]["state"]["temperature"][0]["value_localized"] = None
device_fixture["DummyOven"]["state"]["coreTemperature"][0]["value_raw"] = -32768
device_fixture["DummyOven"]["state"]["coreTemperature"][0]["value_localized"] = None
freezer.tick(timedelta(seconds=130))
async_fire_time_changed(hass)
await hass.async_block_till_done()
check_sensor_state(hass, "sensor.oven_temperature", "unknown", 4)
check_sensor_state(hass, "sensor.oven_target_temperature", "unknown", 4)
check_sensor_state(hass, "sensor.oven_core_temperature", "unknown", 4)
check_sensor_state(hass, "sensor.oven_core_target_temperature", "unknown", 4)
def check_sensor_state(
hass: HomeAssistant,
sensor_entity: str,
expected: str,
step: int,
):
"""Check the state of sensor matches the expected state."""
state = hass.states.get(sensor_entity)
if expected is None:
assert state is None, (
f"[{sensor_entity}] Step {step + 1}: got {state.state}, expected nothing"
)
else:
assert state is not None, f"Missing entity: {sensor_entity}"
assert state.state == expected, (
f"[{sensor_entity}] Step {step + 1}: got {state.state}, expected {expected}"
)
@pytest.mark.parametrize("load_device_file", ["oven.json"])
@pytest.mark.parametrize("platforms", [(SENSOR_DOMAIN,)])
async def test_temperature_sensor_registry_lookup(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_miele_client: MagicMock,
setup_platform: None,
device_fixture: MieleDevices,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that core temperature sensor is provided by the integration after looking up in entity registry."""
# Initial state, the oven is showing core temperature (probe)
freezer.tick(timedelta(seconds=130))
device_fixture["DummyOven"]["state"]["coreTemperature"][0]["value_raw"] = 2200
device_fixture["DummyOven"]["state"]["coreTemperature"][0]["value_localized"] = 22.0
async_fire_time_changed(hass)
await hass.async_block_till_done()
entity_id = "sensor.oven_core_temperature"
assert hass.states.get(entity_id) is not None
assert hass.states.get(entity_id).state == "22.0"
# reload device when turned off, reporting the invalid value
mock_miele_client.get_devices.return_value = await async_load_json_object_fixture(
hass, "oven.json", DOMAIN
)
# unload config entry and reload to make sure that the entity is still provided
await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == "unavailable"
await hass.config_entries.async_reload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == "unknown"
@pytest.mark.parametrize("load_device_file", ["vacuum_device.json"])
@pytest.mark.parametrize("platforms", [(SENSOR_DOMAIN,)])
@pytest.mark.usefixtures("entity_registry_enabled_by_default")