mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Don't add dynamically Home Connect event sensors and disable them by default (#144757)
* Don't add dynamically Home Connect sensors and disable them by default * Fix test * Check for None --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
9e6de48a22
commit
a938001805
@ -5,7 +5,6 @@ from __future__ import annotations
|
|||||||
from asyncio import sleep as asyncio_sleep
|
from asyncio import sleep as asyncio_sleep
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from contextlib import suppress
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
@ -137,9 +136,6 @@ class HomeConnectCoordinator(
|
|||||||
self.__dict__.pop("context_listeners", None)
|
self.__dict__.pop("context_listeners", None)
|
||||||
|
|
||||||
def remove_listener_and_invalidate_context_listeners() -> None:
|
def remove_listener_and_invalidate_context_listeners() -> None:
|
||||||
# There are cases where the remove_listener will be called
|
|
||||||
# although it has been already removed somewhere else
|
|
||||||
with suppress(KeyError):
|
|
||||||
remove_listener()
|
remove_listener()
|
||||||
self.__dict__.pop("context_listeners", None)
|
self.__dict__.pop("context_listeners", None)
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
"""Provides a sensor for Home Connect."""
|
"""Provides a sensor for Home Connect."""
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
from collections.abc import Callable
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from functools import partial
|
|
||||||
import logging
|
import logging
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
@ -17,7 +14,7 @@ from homeassistant.components.sensor import (
|
|||||||
SensorStateClass,
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfVolume
|
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfVolume
|
||||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
from homeassistant.util import dt as dt_util, slugify
|
from homeassistant.util import dt as dt_util, slugify
|
||||||
|
|
||||||
@ -45,6 +42,7 @@ class HomeConnectSensorEntityDescription(
|
|||||||
):
|
):
|
||||||
"""Entity Description class for sensors."""
|
"""Entity Description class for sensors."""
|
||||||
|
|
||||||
|
default_value: str | None = None
|
||||||
appliance_types: tuple[str, ...] | None = None
|
appliance_types: tuple[str, ...] | None = None
|
||||||
fetch_unit: bool = False
|
fetch_unit: bool = False
|
||||||
|
|
||||||
@ -199,6 +197,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.BSH_COMMON_EVENT_PROGRAM_ABORTED,
|
key=EventKey.BSH_COMMON_EVENT_PROGRAM_ABORTED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="program_aborted",
|
translation_key="program_aborted",
|
||||||
appliance_types=("Dishwasher", "CleaningRobot", "CookProcessor"),
|
appliance_types=("Dishwasher", "CleaningRobot", "CookProcessor"),
|
||||||
),
|
),
|
||||||
@ -206,6 +205,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.BSH_COMMON_EVENT_PROGRAM_FINISHED,
|
key=EventKey.BSH_COMMON_EVENT_PROGRAM_FINISHED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="program_finished",
|
translation_key="program_finished",
|
||||||
appliance_types=(
|
appliance_types=(
|
||||||
"Oven",
|
"Oven",
|
||||||
@ -221,6 +221,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.BSH_COMMON_EVENT_ALARM_CLOCK_ELAPSED,
|
key=EventKey.BSH_COMMON_EVENT_ALARM_CLOCK_ELAPSED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="alarm_clock_elapsed",
|
translation_key="alarm_clock_elapsed",
|
||||||
appliance_types=("Oven", "Cooktop"),
|
appliance_types=("Oven", "Cooktop"),
|
||||||
),
|
),
|
||||||
@ -228,6 +229,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.COOKING_OVEN_EVENT_PREHEAT_FINISHED,
|
key=EventKey.COOKING_OVEN_EVENT_PREHEAT_FINISHED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="preheat_finished",
|
translation_key="preheat_finished",
|
||||||
appliance_types=("Oven", "Cooktop"),
|
appliance_types=("Oven", "Cooktop"),
|
||||||
),
|
),
|
||||||
@ -235,6 +237,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.COOKING_OVEN_EVENT_REGULAR_PREHEAT_FINISHED,
|
key=EventKey.COOKING_OVEN_EVENT_REGULAR_PREHEAT_FINISHED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="regular_preheat_finished",
|
translation_key="regular_preheat_finished",
|
||||||
appliance_types=("Oven",),
|
appliance_types=("Oven",),
|
||||||
),
|
),
|
||||||
@ -242,6 +245,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.LAUNDRY_CARE_DRYER_EVENT_DRYING_PROCESS_FINISHED,
|
key=EventKey.LAUNDRY_CARE_DRYER_EVENT_DRYING_PROCESS_FINISHED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="drying_process_finished",
|
translation_key="drying_process_finished",
|
||||||
appliance_types=("Dryer",),
|
appliance_types=("Dryer",),
|
||||||
),
|
),
|
||||||
@ -249,6 +253,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.DISHCARE_DISHWASHER_EVENT_SALT_NEARLY_EMPTY,
|
key=EventKey.DISHCARE_DISHWASHER_EVENT_SALT_NEARLY_EMPTY,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="salt_nearly_empty",
|
translation_key="salt_nearly_empty",
|
||||||
appliance_types=("Dishwasher",),
|
appliance_types=("Dishwasher",),
|
||||||
),
|
),
|
||||||
@ -256,6 +261,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.DISHCARE_DISHWASHER_EVENT_RINSE_AID_NEARLY_EMPTY,
|
key=EventKey.DISHCARE_DISHWASHER_EVENT_RINSE_AID_NEARLY_EMPTY,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="rinse_aid_nearly_empty",
|
translation_key="rinse_aid_nearly_empty",
|
||||||
appliance_types=("Dishwasher",),
|
appliance_types=("Dishwasher",),
|
||||||
),
|
),
|
||||||
@ -263,6 +269,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_BEAN_CONTAINER_EMPTY,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="bean_container_empty",
|
translation_key="bean_container_empty",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -270,6 +277,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_WATER_TANK_EMPTY,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_WATER_TANK_EMPTY,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="water_tank_empty",
|
translation_key="water_tank_empty",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -277,6 +285,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DRIP_TRAY_FULL,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DRIP_TRAY_FULL,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="drip_tray_full",
|
translation_key="drip_tray_full",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -284,6 +293,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_KEEP_MILK_TANK_COOL,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_KEEP_MILK_TANK_COOL,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="keep_milk_tank_cool",
|
translation_key="keep_milk_tank_cool",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -291,6 +301,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_20_CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_20_CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="descaling_in_20_cups",
|
translation_key="descaling_in_20_cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -298,6 +309,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_15_CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_15_CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="descaling_in_15_cups",
|
translation_key="descaling_in_15_cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -305,6 +317,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_10_CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_10_CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="descaling_in_10_cups",
|
translation_key="descaling_in_10_cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -312,6 +325,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_5_CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DESCALING_IN_5_CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="descaling_in_5_cups",
|
translation_key="descaling_in_5_cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -319,6 +333,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_SHOULD_BE_DESCALED,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_SHOULD_BE_DESCALED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_should_be_descaled",
|
translation_key="device_should_be_descaled",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -326,6 +341,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_DESCALING_OVERDUE,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_DESCALING_OVERDUE,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_descaling_overdue",
|
translation_key="device_descaling_overdue",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -333,6 +349,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_DESCALING_BLOCKAGE,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_DESCALING_BLOCKAGE,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_descaling_blockage",
|
translation_key="device_descaling_blockage",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -340,6 +357,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_SHOULD_BE_CLEANED,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_SHOULD_BE_CLEANED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_should_be_cleaned",
|
translation_key="device_should_be_cleaned",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -347,6 +365,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_CLEANING_OVERDUE,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_CLEANING_OVERDUE,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_cleaning_overdue",
|
translation_key="device_cleaning_overdue",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -354,6 +373,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN20CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN20CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="calc_n_clean_in20cups",
|
translation_key="calc_n_clean_in20cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -361,6 +381,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN15CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN15CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="calc_n_clean_in15cups",
|
translation_key="calc_n_clean_in15cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -368,6 +389,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN10CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN10CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="calc_n_clean_in10cups",
|
translation_key="calc_n_clean_in10cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -375,6 +397,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN5CUPS,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_CALC_N_CLEAN_IN5CUPS,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="calc_n_clean_in5cups",
|
translation_key="calc_n_clean_in5cups",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -382,6 +405,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_SHOULD_BE_CALC_N_CLEANED,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_SHOULD_BE_CALC_N_CLEANED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_should_be_calc_n_cleaned",
|
translation_key="device_should_be_calc_n_cleaned",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -389,6 +413,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_CALC_N_CLEAN_OVERDUE,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_CALC_N_CLEAN_OVERDUE,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_calc_n_clean_overdue",
|
translation_key="device_calc_n_clean_overdue",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -396,6 +421,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_CALC_N_CLEAN_BLOCKAGE,
|
key=EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_DEVICE_CALC_N_CLEAN_BLOCKAGE,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="device_calc_n_clean_blockage",
|
translation_key="device_calc_n_clean_blockage",
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
@ -403,6 +429,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_FREEZER,
|
key=EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_FREEZER,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="freezer_door_alarm",
|
translation_key="freezer_door_alarm",
|
||||||
appliance_types=("FridgeFreezer", "Freezer"),
|
appliance_types=("FridgeFreezer", "Freezer"),
|
||||||
),
|
),
|
||||||
@ -410,6 +437,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_REFRIGERATOR,
|
key=EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_REFRIGERATOR,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="refrigerator_door_alarm",
|
translation_key="refrigerator_door_alarm",
|
||||||
appliance_types=("FridgeFreezer", "Refrigerator"),
|
appliance_types=("FridgeFreezer", "Refrigerator"),
|
||||||
),
|
),
|
||||||
@ -417,6 +445,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_TEMPERATURE_ALARM_FREEZER,
|
key=EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_TEMPERATURE_ALARM_FREEZER,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="freezer_temperature_alarm",
|
translation_key="freezer_temperature_alarm",
|
||||||
appliance_types=("FridgeFreezer", "Freezer"),
|
appliance_types=("FridgeFreezer", "Freezer"),
|
||||||
),
|
),
|
||||||
@ -424,6 +453,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_CLEANING_ROBOT_EVENT_EMPTY_DUST_BOX_AND_CLEAN_FILTER,
|
key=EventKey.CONSUMER_PRODUCTS_CLEANING_ROBOT_EVENT_EMPTY_DUST_BOX_AND_CLEAN_FILTER,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="empty_dust_box_and_clean_filter",
|
translation_key="empty_dust_box_and_clean_filter",
|
||||||
appliance_types=("CleaningRobot",),
|
appliance_types=("CleaningRobot",),
|
||||||
),
|
),
|
||||||
@ -431,6 +461,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_CLEANING_ROBOT_EVENT_ROBOT_IS_STUCK,
|
key=EventKey.CONSUMER_PRODUCTS_CLEANING_ROBOT_EVENT_ROBOT_IS_STUCK,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="robot_is_stuck",
|
translation_key="robot_is_stuck",
|
||||||
appliance_types=("CleaningRobot",),
|
appliance_types=("CleaningRobot",),
|
||||||
),
|
),
|
||||||
@ -438,6 +469,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.CONSUMER_PRODUCTS_CLEANING_ROBOT_EVENT_DOCKING_STATION_NOT_FOUND,
|
key=EventKey.CONSUMER_PRODUCTS_CLEANING_ROBOT_EVENT_DOCKING_STATION_NOT_FOUND,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="docking_station_not_found",
|
translation_key="docking_station_not_found",
|
||||||
appliance_types=("CleaningRobot",),
|
appliance_types=("CleaningRobot",),
|
||||||
),
|
),
|
||||||
@ -445,6 +477,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.LAUNDRY_CARE_WASHER_EVENT_I_DOS_1_FILL_LEVEL_POOR,
|
key=EventKey.LAUNDRY_CARE_WASHER_EVENT_I_DOS_1_FILL_LEVEL_POOR,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="poor_i_dos_1_fill_level",
|
translation_key="poor_i_dos_1_fill_level",
|
||||||
appliance_types=("Washer", "WasherDryer"),
|
appliance_types=("Washer", "WasherDryer"),
|
||||||
),
|
),
|
||||||
@ -452,6 +485,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.LAUNDRY_CARE_WASHER_EVENT_I_DOS_2_FILL_LEVEL_POOR,
|
key=EventKey.LAUNDRY_CARE_WASHER_EVENT_I_DOS_2_FILL_LEVEL_POOR,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="poor_i_dos_2_fill_level",
|
translation_key="poor_i_dos_2_fill_level",
|
||||||
appliance_types=("Washer", "WasherDryer"),
|
appliance_types=("Washer", "WasherDryer"),
|
||||||
),
|
),
|
||||||
@ -459,6 +493,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.COOKING_COMMON_EVENT_HOOD_GREASE_FILTER_MAX_SATURATION_NEARLY_REACHED,
|
key=EventKey.COOKING_COMMON_EVENT_HOOD_GREASE_FILTER_MAX_SATURATION_NEARLY_REACHED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="grease_filter_max_saturation_nearly_reached",
|
translation_key="grease_filter_max_saturation_nearly_reached",
|
||||||
appliance_types=("Hood",),
|
appliance_types=("Hood",),
|
||||||
),
|
),
|
||||||
@ -466,6 +501,7 @@ EVENT_SENSORS = (
|
|||||||
key=EventKey.COOKING_COMMON_EVENT_HOOD_GREASE_FILTER_MAX_SATURATION_REACHED,
|
key=EventKey.COOKING_COMMON_EVENT_HOOD_GREASE_FILTER_MAX_SATURATION_REACHED,
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=EVENT_OPTIONS,
|
options=EVENT_OPTIONS,
|
||||||
|
default_value="off",
|
||||||
translation_key="grease_filter_max_saturation_reached",
|
translation_key="grease_filter_max_saturation_reached",
|
||||||
appliance_types=("Hood",),
|
appliance_types=("Hood",),
|
||||||
),
|
),
|
||||||
@ -478,6 +514,12 @@ def _get_entities_for_appliance(
|
|||||||
) -> list[HomeConnectEntity]:
|
) -> list[HomeConnectEntity]:
|
||||||
"""Get a list of entities."""
|
"""Get a list of entities."""
|
||||||
return [
|
return [
|
||||||
|
*[
|
||||||
|
HomeConnectEventSensor(entry.runtime_data, appliance, description)
|
||||||
|
for description in EVENT_SENSORS
|
||||||
|
if description.appliance_types
|
||||||
|
and appliance.info.type in description.appliance_types
|
||||||
|
],
|
||||||
*[
|
*[
|
||||||
HomeConnectProgramSensor(entry.runtime_data, appliance, desc)
|
HomeConnectProgramSensor(entry.runtime_data, appliance, desc)
|
||||||
for desc in BSH_PROGRAM_SENSORS
|
for desc in BSH_PROGRAM_SENSORS
|
||||||
@ -491,72 +533,6 @@ def _get_entities_for_appliance(
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _add_event_sensor_entity(
|
|
||||||
entry: HomeConnectConfigEntry,
|
|
||||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
||||||
appliance: HomeConnectApplianceData,
|
|
||||||
description: HomeConnectSensorEntityDescription,
|
|
||||||
remove_event_sensor_listener_list: list[Callable[[], None]],
|
|
||||||
) -> None:
|
|
||||||
"""Add an event sensor entity."""
|
|
||||||
if (
|
|
||||||
(appliance_data := entry.runtime_data.data.get(appliance.info.ha_id)) is None
|
|
||||||
) or description.key not in appliance_data.events:
|
|
||||||
return
|
|
||||||
|
|
||||||
for remove_listener in remove_event_sensor_listener_list:
|
|
||||||
remove_listener()
|
|
||||||
async_add_entities(
|
|
||||||
[
|
|
||||||
HomeConnectEventSensor(entry.runtime_data, appliance, description),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _add_event_sensor_listeners(
|
|
||||||
entry: HomeConnectConfigEntry,
|
|
||||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
||||||
remove_event_sensor_listener_dict: dict[str, list[CALLBACK_TYPE]],
|
|
||||||
) -> None:
|
|
||||||
for appliance in entry.runtime_data.data.values():
|
|
||||||
if appliance.info.ha_id in remove_event_sensor_listener_dict:
|
|
||||||
continue
|
|
||||||
for event_sensor_description in EVENT_SENSORS:
|
|
||||||
if appliance.info.type not in cast(
|
|
||||||
tuple[str, ...], event_sensor_description.appliance_types
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
# We use a list as a kind of lazy initializer, as we can use the
|
|
||||||
# remove_listener while we are initializing it.
|
|
||||||
remove_event_sensor_listener_list = remove_event_sensor_listener_dict[
|
|
||||||
appliance.info.ha_id
|
|
||||||
]
|
|
||||||
remove_listener = entry.runtime_data.async_add_listener(
|
|
||||||
partial(
|
|
||||||
_add_event_sensor_entity,
|
|
||||||
entry,
|
|
||||||
async_add_entities,
|
|
||||||
appliance,
|
|
||||||
event_sensor_description,
|
|
||||||
remove_event_sensor_listener_list,
|
|
||||||
),
|
|
||||||
(appliance.info.ha_id, event_sensor_description.key),
|
|
||||||
)
|
|
||||||
remove_event_sensor_listener_list.append(remove_listener)
|
|
||||||
entry.async_on_unload(remove_listener)
|
|
||||||
|
|
||||||
|
|
||||||
def _remove_event_sensor_listeners_on_depaired(
|
|
||||||
entry: HomeConnectConfigEntry,
|
|
||||||
remove_event_sensor_listener_dict: dict[str, list[CALLBACK_TYPE]],
|
|
||||||
) -> None:
|
|
||||||
registered_listeners_ha_id = set(remove_event_sensor_listener_dict)
|
|
||||||
actual_appliances = set(entry.runtime_data.data)
|
|
||||||
for appliance_ha_id in registered_listeners_ha_id - actual_appliances:
|
|
||||||
for listener in remove_event_sensor_listener_dict.pop(appliance_ha_id):
|
|
||||||
listener()
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: HomeConnectConfigEntry,
|
entry: HomeConnectConfigEntry,
|
||||||
@ -569,32 +545,6 @@ async def async_setup_entry(
|
|||||||
async_add_entities,
|
async_add_entities,
|
||||||
)
|
)
|
||||||
|
|
||||||
remove_event_sensor_listener_dict: dict[str, list[CALLBACK_TYPE]] = defaultdict(
|
|
||||||
list
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.async_on_unload(
|
|
||||||
entry.runtime_data.async_add_special_listener(
|
|
||||||
partial(
|
|
||||||
_add_event_sensor_listeners,
|
|
||||||
entry,
|
|
||||||
async_add_entities,
|
|
||||||
remove_event_sensor_listener_dict,
|
|
||||||
),
|
|
||||||
(EventKey.BSH_COMMON_APPLIANCE_PAIRED,),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
entry.async_on_unload(
|
|
||||||
entry.runtime_data.async_add_special_listener(
|
|
||||||
partial(
|
|
||||||
_remove_event_sensor_listeners_on_depaired,
|
|
||||||
entry,
|
|
||||||
remove_event_sensor_listener_dict,
|
|
||||||
),
|
|
||||||
(EventKey.BSH_COMMON_APPLIANCE_DEPAIRED,),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
||||||
"""Sensor class for Home Connect."""
|
"""Sensor class for Home Connect."""
|
||||||
@ -697,7 +647,12 @@ class HomeConnectProgramSensor(HomeConnectSensor):
|
|||||||
class HomeConnectEventSensor(HomeConnectSensor):
|
class HomeConnectEventSensor(HomeConnectSensor):
|
||||||
"""Sensor class for Home Connect events."""
|
"""Sensor class for Home Connect events."""
|
||||||
|
|
||||||
|
_attr_entity_registry_enabled_default = False
|
||||||
|
|
||||||
def update_native_value(self) -> None:
|
def update_native_value(self) -> None:
|
||||||
"""Update the sensor's status."""
|
"""Update the sensor's status."""
|
||||||
event = self.appliance.events[cast(EventKey, self.bsh_key)]
|
event = self.appliance.events.get(cast(EventKey, self.bsh_key))
|
||||||
|
if event:
|
||||||
self._update_native_value(event.value)
|
self._update_native_value(event.value)
|
||||||
|
elif self._attr_native_value is None:
|
||||||
|
self._attr_native_value = self.entity_description.default_value
|
||||||
|
@ -247,6 +247,7 @@ async def test_coordinator_update_failing(
|
|||||||
getattr(client, mock_method).assert_called()
|
getattr(client, mock_method).assert_called()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
@pytest.mark.parametrize("appliance", ["Dishwasher"], indirect=True)
|
@pytest.mark.parametrize("appliance", ["Dishwasher"], indirect=True)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("event_type", "event_key", "event_value", ATTR_ENTITY_ID),
|
("event_type", "event_key", "event_value", ATTR_ENTITY_ID),
|
||||||
@ -288,7 +289,7 @@ async def test_event_listener(
|
|||||||
assert config_entry.state is ConfigEntryState.LOADED
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
|
assert state
|
||||||
event_message = EventMessage(
|
event_message = EventMessage(
|
||||||
appliance.ha_id,
|
appliance.ha_id,
|
||||||
event_type,
|
event_type,
|
||||||
@ -310,7 +311,6 @@ async def test_event_listener(
|
|||||||
|
|
||||||
new_state = hass.states.get(entity_id)
|
new_state = hass.states.get(entity_id)
|
||||||
assert new_state
|
assert new_state
|
||||||
if state is not None:
|
|
||||||
assert new_state.state != state.state
|
assert new_state.state != state.state
|
||||||
|
|
||||||
# Following, we are gonna check that the listeners are clean up correctly
|
# Following, we are gonna check that the listeners are clean up correctly
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""Tests for home_connect sensor entities."""
|
"""Tests for home_connect sensor entities."""
|
||||||
|
|
||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Awaitable, Callable
|
||||||
import logging
|
|
||||||
from unittest.mock import AsyncMock, MagicMock
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
from aiohomeconnect.model import (
|
from aiohomeconnect.model import (
|
||||||
@ -140,29 +139,6 @@ async def test_paired_depaired_devices_flow(
|
|||||||
for entity_entry in entity_entries:
|
for entity_entry in entity_entries:
|
||||||
assert entity_registry.async_get(entity_entry.entity_id)
|
assert entity_registry.async_get(entity_entry.entity_id)
|
||||||
|
|
||||||
await client.add_events(
|
|
||||||
[
|
|
||||||
EventMessage(
|
|
||||||
appliance.ha_id,
|
|
||||||
EventType.EVENT,
|
|
||||||
ArrayOfEvents(
|
|
||||||
[
|
|
||||||
Event(
|
|
||||||
key=EventKey.LAUNDRY_CARE_WASHER_EVENT_I_DOS_1_FILL_LEVEL_POOR,
|
|
||||||
raw_key=EventKey.LAUNDRY_CARE_WASHER_EVENT_I_DOS_1_FILL_LEVEL_POOR.value,
|
|
||||||
timestamp=0,
|
|
||||||
level="",
|
|
||||||
handling="",
|
|
||||||
value=BSH_EVENT_PRESENT_STATE_PRESENT,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.is_state("sensor.washer_poor_i_dos_1_fill_level", "present")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("appliance", "keys_to_check"),
|
("appliance", "keys_to_check"),
|
||||||
@ -231,6 +207,7 @@ async def test_connected_devices(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
@pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
|
@pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
|
||||||
async def test_sensor_entity_availability(
|
async def test_sensor_entity_availability(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -247,28 +224,6 @@ async def test_sensor_entity_availability(
|
|||||||
assert await integration_setup(client)
|
assert await integration_setup(client)
|
||||||
assert config_entry.state is ConfigEntryState.LOADED
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
await client.add_events(
|
|
||||||
[
|
|
||||||
EventMessage(
|
|
||||||
appliance.ha_id,
|
|
||||||
EventType.EVENT,
|
|
||||||
ArrayOfEvents(
|
|
||||||
[
|
|
||||||
Event(
|
|
||||||
key=EventKey.DISHCARE_DISHWASHER_EVENT_SALT_NEARLY_EMPTY,
|
|
||||||
raw_key=EventKey.DISHCARE_DISHWASHER_EVENT_SALT_NEARLY_EMPTY.value,
|
|
||||||
timestamp=0,
|
|
||||||
level="",
|
|
||||||
handling="",
|
|
||||||
value=BSH_EVENT_PRESENT_STATE_OFF,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
for entity_id in entity_ids:
|
for entity_id in entity_ids:
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
@ -545,33 +500,105 @@ async def test_remaining_prog_time_edge_cases(
|
|||||||
assert hass.states.is_state(entity_id, expected_state)
|
assert hass.states.is_state(entity_id, expected_state)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
(
|
(
|
||||||
"entity_id",
|
"entity_id",
|
||||||
"event_key",
|
"event_key",
|
||||||
"value_expected_state",
|
"event_type",
|
||||||
|
"event_value_update",
|
||||||
|
"expected",
|
||||||
"appliance",
|
"appliance",
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"sensor.dishwasher_door",
|
"sensor.dishwasher_door",
|
||||||
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
|
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
|
||||||
[
|
EventType.STATUS,
|
||||||
(
|
|
||||||
BSH_DOOR_STATE_LOCKED,
|
BSH_DOOR_STATE_LOCKED,
|
||||||
"locked",
|
"locked",
|
||||||
|
"Dishwasher",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
"sensor.dishwasher_door",
|
||||||
|
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
|
||||||
|
EventType.STATUS,
|
||||||
BSH_DOOR_STATE_CLOSED,
|
BSH_DOOR_STATE_CLOSED,
|
||||||
"closed",
|
"closed",
|
||||||
|
"Dishwasher",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
"sensor.dishwasher_door",
|
||||||
|
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
|
||||||
|
EventType.STATUS,
|
||||||
BSH_DOOR_STATE_OPEN,
|
BSH_DOOR_STATE_OPEN,
|
||||||
"open",
|
"open",
|
||||||
),
|
|
||||||
],
|
|
||||||
"Dishwasher",
|
"Dishwasher",
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_freezer_door_alarm",
|
||||||
|
"EVENT_NOT_IN_STATUS_YET_SO_SET_TO_OFF",
|
||||||
|
EventType.EVENT,
|
||||||
|
"",
|
||||||
|
"off",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_freezer_door_alarm",
|
||||||
|
EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
EventType.EVENT,
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF,
|
||||||
|
"off",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_freezer_door_alarm",
|
||||||
|
EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
EventType.EVENT,
|
||||||
|
BSH_EVENT_PRESENT_STATE_PRESENT,
|
||||||
|
"present",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.fridgefreezer_freezer_door_alarm",
|
||||||
|
EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
EventType.EVENT,
|
||||||
|
BSH_EVENT_PRESENT_STATE_CONFIRMED,
|
||||||
|
"confirmed",
|
||||||
|
"FridgeFreezer",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
EventType.EVENT,
|
||||||
|
"EVENT_NOT_IN_STATUS_YET_SO_SET_TO_OFF",
|
||||||
|
"",
|
||||||
|
"off",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
EventType.EVENT,
|
||||||
|
BSH_EVENT_PRESENT_STATE_OFF,
|
||||||
|
"off",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
EventType.EVENT,
|
||||||
|
BSH_EVENT_PRESENT_STATE_PRESENT,
|
||||||
|
"present",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sensor.coffeemaker_bean_container_empty",
|
||||||
|
EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
EventType.EVENT,
|
||||||
|
BSH_EVENT_PRESENT_STATE_CONFIRMED,
|
||||||
|
"confirmed",
|
||||||
|
"CoffeeMaker",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
indirect=["appliance"],
|
indirect=["appliance"],
|
||||||
)
|
)
|
||||||
@ -582,19 +609,20 @@ async def test_sensors_states(
|
|||||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||||
entity_id: str,
|
entity_id: str,
|
||||||
event_key: EventKey,
|
event_key: EventKey,
|
||||||
value_expected_state: list[tuple[str, str]],
|
event_type: EventType,
|
||||||
|
event_value_update: str,
|
||||||
appliance: HomeAppliance,
|
appliance: HomeAppliance,
|
||||||
|
expected: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests for appliance sensors."""
|
"""Tests for appliance alarm sensors."""
|
||||||
assert await integration_setup(client)
|
assert await integration_setup(client)
|
||||||
assert config_entry.state is ConfigEntryState.LOADED
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
for value, expected_state in value_expected_state:
|
|
||||||
await client.add_events(
|
await client.add_events(
|
||||||
[
|
[
|
||||||
EventMessage(
|
EventMessage(
|
||||||
appliance.ha_id,
|
appliance.ha_id,
|
||||||
EventType.STATUS,
|
event_type,
|
||||||
ArrayOfEvents(
|
ArrayOfEvents(
|
||||||
[
|
[
|
||||||
Event(
|
Event(
|
||||||
@ -603,7 +631,7 @@ async def test_sensors_states(
|
|||||||
timestamp=0,
|
timestamp=0,
|
||||||
level="",
|
level="",
|
||||||
handling="",
|
handling="",
|
||||||
value=value,
|
value=event_value_update,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -611,82 +639,7 @@ async def test_sensors_states(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert hass.states.is_state(entity_id, expected_state)
|
assert hass.states.is_state(entity_id, expected)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
(
|
|
||||||
"entity_id",
|
|
||||||
"event_key",
|
|
||||||
"appliance",
|
|
||||||
),
|
|
||||||
[
|
|
||||||
(
|
|
||||||
"sensor.fridgefreezer_freezer_door_alarm",
|
|
||||||
EventKey.REFRIGERATION_FRIDGE_FREEZER_EVENT_DOOR_ALARM_FREEZER,
|
|
||||||
"FridgeFreezer",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"sensor.coffeemaker_bean_container_empty",
|
|
||||||
EventKey.CONSUMER_PRODUCTS_COFFEE_MAKER_EVENT_BEAN_CONTAINER_EMPTY,
|
|
||||||
"CoffeeMaker",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
indirect=["appliance"],
|
|
||||||
)
|
|
||||||
async def test_event_sensors_states(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
caplog: pytest.LogCaptureFixture,
|
|
||||||
entity_registry: er.EntityRegistry,
|
|
||||||
client: MagicMock,
|
|
||||||
config_entry: MockConfigEntry,
|
|
||||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
|
||||||
entity_id: str,
|
|
||||||
event_key: EventKey,
|
|
||||||
appliance: HomeAppliance,
|
|
||||||
) -> None:
|
|
||||||
"""Tests for appliance event sensors."""
|
|
||||||
caplog.set_level(logging.ERROR)
|
|
||||||
assert await integration_setup(client)
|
|
||||||
assert config_entry.state is ConfigEntryState.LOADED
|
|
||||||
|
|
||||||
assert not hass.states.get(entity_id)
|
|
||||||
|
|
||||||
for value, expected_state in (
|
|
||||||
(BSH_EVENT_PRESENT_STATE_OFF, "off"),
|
|
||||||
(BSH_EVENT_PRESENT_STATE_PRESENT, "present"),
|
|
||||||
(BSH_EVENT_PRESENT_STATE_CONFIRMED, "confirmed"),
|
|
||||||
):
|
|
||||||
await client.add_events(
|
|
||||||
[
|
|
||||||
EventMessage(
|
|
||||||
appliance.ha_id,
|
|
||||||
EventType.EVENT,
|
|
||||||
ArrayOfEvents(
|
|
||||||
[
|
|
||||||
Event(
|
|
||||||
key=event_key,
|
|
||||||
raw_key=str(event_key),
|
|
||||||
timestamp=0,
|
|
||||||
level="",
|
|
||||||
handling="",
|
|
||||||
value=value,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert hass.states.is_state(entity_id, expected_state)
|
|
||||||
|
|
||||||
# Verify that the integration doesn't attempt to add the event sensors more than once
|
|
||||||
# If that happens, the EntityPlatform logs an error with the entity's unique ID.
|
|
||||||
assert "exists" not in caplog.text
|
|
||||||
assert entity_id not in caplog.text
|
|
||||||
entity_entry = entity_registry.async_get(entity_id)
|
|
||||||
assert entity_entry
|
|
||||||
assert entity_entry.unique_id not in caplog.text
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user