mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 10:17:51 +00:00
Add additional select for dmaker.airfresh.t2017 to xiaomi_miio (#67058)
This commit is contained in:
parent
d50b5cebee
commit
65f86ce44f
@ -1478,7 +1478,6 @@ omit =
|
|||||||
homeassistant/components/xiaomi_miio/light.py
|
homeassistant/components/xiaomi_miio/light.py
|
||||||
homeassistant/components/xiaomi_miio/number.py
|
homeassistant/components/xiaomi_miio/number.py
|
||||||
homeassistant/components/xiaomi_miio/remote.py
|
homeassistant/components/xiaomi_miio/remote.py
|
||||||
homeassistant/components/xiaomi_miio/select.py
|
|
||||||
homeassistant/components/xiaomi_miio/sensor.py
|
homeassistant/components/xiaomi_miio/sensor.py
|
||||||
homeassistant/components/xiaomi_miio/switch.py
|
homeassistant/components/xiaomi_miio/switch.py
|
||||||
homeassistant/components/xiaomi_tv/media_player.py
|
homeassistant/components/xiaomi_tv/media_player.py
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
"""Support led_brightness for Mi Air Humidifier."""
|
"""Support led_brightness for Mi Air Humidifier."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
|
from typing import NamedTuple
|
||||||
|
|
||||||
from miio.fan_common import LedBrightness as FanLedBrightness
|
from miio.fan_common import LedBrightness as FanLedBrightness
|
||||||
|
from miio.integrations.airpurifier.dmaker.airfresh_t2017 import (
|
||||||
|
DisplayOrientation as AirfreshT2017DisplayOrientation,
|
||||||
|
PtcLevel as AirfreshT2017PtcLevel,
|
||||||
|
)
|
||||||
from miio.integrations.airpurifier.zhimi.airfresh import (
|
from miio.integrations.airpurifier.zhimi.airfresh import (
|
||||||
LedBrightness as AirfreshLedBrightness,
|
LedBrightness as AirfreshLedBrightness,
|
||||||
)
|
)
|
||||||
@ -31,53 +36,134 @@ from .const import (
|
|||||||
CONF_DEVICE,
|
CONF_DEVICE,
|
||||||
CONF_FLOW_TYPE,
|
CONF_FLOW_TYPE,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
FEATURE_SET_LED_BRIGHTNESS,
|
|
||||||
KEY_COORDINATOR,
|
KEY_COORDINATOR,
|
||||||
KEY_DEVICE,
|
KEY_DEVICE,
|
||||||
|
MODEL_AIRFRESH_T2017,
|
||||||
MODEL_AIRFRESH_VA2,
|
MODEL_AIRFRESH_VA2,
|
||||||
MODEL_AIRPURIFIER_3C,
|
MODEL_AIRHUMIDIFIER_CA1,
|
||||||
|
MODEL_AIRHUMIDIFIER_CA4,
|
||||||
|
MODEL_AIRHUMIDIFIER_CB1,
|
||||||
|
MODEL_AIRHUMIDIFIER_V1,
|
||||||
|
MODEL_AIRPURIFIER_3,
|
||||||
|
MODEL_AIRPURIFIER_3H,
|
||||||
MODEL_AIRPURIFIER_M1,
|
MODEL_AIRPURIFIER_M1,
|
||||||
MODEL_AIRPURIFIER_M2,
|
MODEL_AIRPURIFIER_M2,
|
||||||
|
MODEL_AIRPURIFIER_PROH,
|
||||||
MODEL_FAN_SA1,
|
MODEL_FAN_SA1,
|
||||||
MODEL_FAN_V2,
|
MODEL_FAN_V2,
|
||||||
MODEL_FAN_V3,
|
MODEL_FAN_V3,
|
||||||
MODEL_FAN_ZA1,
|
MODEL_FAN_ZA1,
|
||||||
MODEL_FAN_ZA3,
|
MODEL_FAN_ZA3,
|
||||||
MODEL_FAN_ZA4,
|
MODEL_FAN_ZA4,
|
||||||
MODELS_HUMIDIFIER_MIIO,
|
|
||||||
MODELS_HUMIDIFIER_MIOT,
|
|
||||||
MODELS_PURIFIER_MIOT,
|
|
||||||
)
|
)
|
||||||
from .device import XiaomiCoordinatedMiioEntity
|
from .device import XiaomiCoordinatedMiioEntity
|
||||||
|
|
||||||
|
ATTR_DISPLAY_ORIENTATION = "display_orientation"
|
||||||
ATTR_LED_BRIGHTNESS = "led_brightness"
|
ATTR_LED_BRIGHTNESS = "led_brightness"
|
||||||
|
ATTR_PTC_LEVEL = "ptc_level"
|
||||||
|
|
||||||
LED_BRIGHTNESS_MAP = {"Bright": 0, "Dim": 1, "Off": 2}
|
|
||||||
LED_BRIGHTNESS_MAP_HUMIDIFIER_MIOT = {"Bright": 2, "Dim": 1, "Off": 0}
|
|
||||||
LED_BRIGHTNESS_REVERSE_MAP = {val: key for key, val in LED_BRIGHTNESS_MAP.items()}
|
|
||||||
LED_BRIGHTNESS_REVERSE_MAP_HUMIDIFIER_MIOT = {
|
|
||||||
val: key for key, val in LED_BRIGHTNESS_MAP_HUMIDIFIER_MIOT.items()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class XiaomiMiioSelectDescription(SelectEntityDescription):
|
class XiaomiMiioSelectDescription(SelectEntityDescription):
|
||||||
"""A class that describes select entities."""
|
"""A class that describes select entities."""
|
||||||
|
|
||||||
|
attr_name: str = ""
|
||||||
|
options_map: dict = field(default_factory=dict)
|
||||||
|
set_method: str = ""
|
||||||
|
set_method_error_message: str = ""
|
||||||
options: tuple = ()
|
options: tuple = ()
|
||||||
|
|
||||||
|
|
||||||
SELECTOR_TYPES = {
|
class AttributeEnumMapping(NamedTuple):
|
||||||
FEATURE_SET_LED_BRIGHTNESS: XiaomiMiioSelectDescription(
|
"""Class to mapping Attribute to Enum Class."""
|
||||||
|
|
||||||
|
attr_name: str
|
||||||
|
enum_class: type
|
||||||
|
|
||||||
|
|
||||||
|
MODEL_TO_ATTR_MAP: dict[str, list] = {
|
||||||
|
MODEL_AIRFRESH_T2017: [
|
||||||
|
AttributeEnumMapping(ATTR_DISPLAY_ORIENTATION, AirfreshT2017DisplayOrientation),
|
||||||
|
AttributeEnumMapping(ATTR_PTC_LEVEL, AirfreshT2017PtcLevel),
|
||||||
|
],
|
||||||
|
MODEL_AIRFRESH_VA2: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirfreshLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRHUMIDIFIER_CA1: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirhumidifierLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRHUMIDIFIER_CA4: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirhumidifierMiotLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRHUMIDIFIER_CB1: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirhumidifierLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRHUMIDIFIER_V1: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirhumidifierLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRPURIFIER_3: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirpurifierMiotLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRPURIFIER_3H: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirpurifierMiotLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRPURIFIER_M1: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirpurifierLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRPURIFIER_M2: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirpurifierLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_AIRPURIFIER_PROH: [
|
||||||
|
AttributeEnumMapping(ATTR_LED_BRIGHTNESS, AirpurifierMiotLedBrightness)
|
||||||
|
],
|
||||||
|
MODEL_FAN_SA1: [AttributeEnumMapping(ATTR_LED_BRIGHTNESS, FanLedBrightness)],
|
||||||
|
MODEL_FAN_V2: [AttributeEnumMapping(ATTR_LED_BRIGHTNESS, FanLedBrightness)],
|
||||||
|
MODEL_FAN_V3: [AttributeEnumMapping(ATTR_LED_BRIGHTNESS, FanLedBrightness)],
|
||||||
|
MODEL_FAN_ZA1: [AttributeEnumMapping(ATTR_LED_BRIGHTNESS, FanLedBrightness)],
|
||||||
|
MODEL_FAN_ZA3: [AttributeEnumMapping(ATTR_LED_BRIGHTNESS, FanLedBrightness)],
|
||||||
|
MODEL_FAN_ZA4: [AttributeEnumMapping(ATTR_LED_BRIGHTNESS, FanLedBrightness)],
|
||||||
|
}
|
||||||
|
|
||||||
|
SELECTOR_TYPES = (
|
||||||
|
XiaomiMiioSelectDescription(
|
||||||
|
key=ATTR_DISPLAY_ORIENTATION,
|
||||||
|
attr_name=ATTR_DISPLAY_ORIENTATION,
|
||||||
|
name="Display Orientation",
|
||||||
|
options_map={
|
||||||
|
"Portrait": "Forward",
|
||||||
|
"LandscapeLeft": "Left",
|
||||||
|
"LandscapeRight": "Right",
|
||||||
|
},
|
||||||
|
set_method="set_display_orientation",
|
||||||
|
set_method_error_message="Setting the display orientation failed.",
|
||||||
|
icon="mdi:tablet",
|
||||||
|
device_class="xiaomi_miio__display_orientation",
|
||||||
|
options=("forward", "left", "right"),
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
XiaomiMiioSelectDescription(
|
||||||
key=ATTR_LED_BRIGHTNESS,
|
key=ATTR_LED_BRIGHTNESS,
|
||||||
|
attr_name=ATTR_LED_BRIGHTNESS,
|
||||||
name="Led Brightness",
|
name="Led Brightness",
|
||||||
|
set_method="set_led_brightness",
|
||||||
|
set_method_error_message="Setting the led brightness failed.",
|
||||||
icon="mdi:brightness-6",
|
icon="mdi:brightness-6",
|
||||||
device_class="xiaomi_miio__led_brightness",
|
device_class="xiaomi_miio__led_brightness",
|
||||||
options=("bright", "dim", "off"),
|
options=("bright", "dim", "off"),
|
||||||
entity_category=EntityCategory.CONFIG,
|
entity_category=EntityCategory.CONFIG,
|
||||||
),
|
),
|
||||||
}
|
XiaomiMiioSelectDescription(
|
||||||
|
key=ATTR_PTC_LEVEL,
|
||||||
|
attr_name=ATTR_PTC_LEVEL,
|
||||||
|
name="Auxiliary Heat Level",
|
||||||
|
set_method="set_ptc_level",
|
||||||
|
set_method_error_message="Setting the ptc level failed.",
|
||||||
|
icon="mdi:fire-circle",
|
||||||
|
device_class="xiaomi_miio__ptc_level",
|
||||||
|
options=("low", "medium", "high"),
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -89,42 +175,27 @@ async def async_setup_entry(
|
|||||||
if not config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE:
|
if not config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE:
|
||||||
return
|
return
|
||||||
|
|
||||||
entities = []
|
|
||||||
model = config_entry.data[CONF_MODEL]
|
model = config_entry.data[CONF_MODEL]
|
||||||
|
if model not in MODEL_TO_ATTR_MAP:
|
||||||
|
return
|
||||||
|
|
||||||
|
entities = []
|
||||||
|
unique_id = config_entry.unique_id
|
||||||
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
|
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
|
||||||
|
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR]
|
||||||
|
attributes = MODEL_TO_ATTR_MAP[model]
|
||||||
|
|
||||||
if model == MODEL_AIRPURIFIER_3C:
|
for description in SELECTOR_TYPES:
|
||||||
return
|
for attribute in attributes:
|
||||||
if model in MODELS_HUMIDIFIER_MIIO:
|
if description.key == attribute.attr_name:
|
||||||
entity_class = XiaomiAirHumidifierSelector
|
|
||||||
elif model in MODELS_HUMIDIFIER_MIOT:
|
|
||||||
entity_class = XiaomiAirHumidifierMiotSelector
|
|
||||||
elif model in [MODEL_AIRPURIFIER_M1, MODEL_AIRPURIFIER_M2]:
|
|
||||||
entity_class = XiaomiAirPurifierSelector
|
|
||||||
elif model in MODELS_PURIFIER_MIOT:
|
|
||||||
entity_class = XiaomiAirPurifierMiotSelector
|
|
||||||
elif model == MODEL_AIRFRESH_VA2:
|
|
||||||
entity_class = XiaomiAirFreshSelector
|
|
||||||
elif model in (
|
|
||||||
MODEL_FAN_ZA1,
|
|
||||||
MODEL_FAN_ZA3,
|
|
||||||
MODEL_FAN_ZA4,
|
|
||||||
MODEL_FAN_SA1,
|
|
||||||
MODEL_FAN_V2,
|
|
||||||
MODEL_FAN_V3,
|
|
||||||
):
|
|
||||||
entity_class = XiaomiFanSelector
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
description = SELECTOR_TYPES[FEATURE_SET_LED_BRIGHTNESS]
|
|
||||||
entities.append(
|
entities.append(
|
||||||
entity_class(
|
XiaomiGenericSelector(
|
||||||
device,
|
device,
|
||||||
config_entry,
|
config_entry,
|
||||||
f"{description.key}_{config_entry.unique_id}",
|
f"{description.key}_{unique_id}",
|
||||||
hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR],
|
coordinator,
|
||||||
description,
|
description,
|
||||||
|
attribute.enum_class,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -141,129 +212,60 @@ class XiaomiSelector(XiaomiCoordinatedMiioEntity, SelectEntity):
|
|||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
|
||||||
|
|
||||||
class XiaomiAirHumidifierSelector(XiaomiSelector):
|
class XiaomiGenericSelector(XiaomiSelector):
|
||||||
"""Representation of a Xiaomi Air Humidifier selector."""
|
"""Representation of a Xiaomi generic selector."""
|
||||||
|
|
||||||
def __init__(self, device, entry, unique_id, coordinator, description):
|
entity_description: XiaomiMiioSelectDescription
|
||||||
"""Initialize the plug switch."""
|
|
||||||
|
def __init__(self, device, entry, unique_id, coordinator, description, enum_class):
|
||||||
|
"""Initialize the generic Xiaomi attribute selector."""
|
||||||
super().__init__(device, entry, unique_id, coordinator, description)
|
super().__init__(device, entry, unique_id, coordinator, description)
|
||||||
self._current_led_brightness = self._extract_value_from_attribute(
|
self._current_attr = enum_class(
|
||||||
self.coordinator.data, self.entity_description.key
|
self._extract_value_from_attribute(
|
||||||
|
self.coordinator.data, self.entity_description.attr_name
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if description.options_map:
|
||||||
|
self._options_map = {}
|
||||||
|
for key, val in enum_class._member_map_.items():
|
||||||
|
self._options_map[description.options_map[key]] = val
|
||||||
|
else:
|
||||||
|
self._options_map = enum_class._member_map_
|
||||||
|
self._reverse_map = {val: key for key, val in self._options_map.items()}
|
||||||
|
self._enum_class = enum_class
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _handle_coordinator_update(self):
|
def _handle_coordinator_update(self):
|
||||||
"""Fetch state from the device."""
|
"""Fetch state from the device."""
|
||||||
led_brightness = self._extract_value_from_attribute(
|
attr = self._enum_class(
|
||||||
self.coordinator.data, self.entity_description.key
|
self._extract_value_from_attribute(
|
||||||
|
self.coordinator.data, self.entity_description.attr_name
|
||||||
)
|
)
|
||||||
# Sometimes (quite rarely) the device returns None as the LED brightness so we
|
)
|
||||||
# check that the value is not None before updating the state.
|
if attr is not None:
|
||||||
if led_brightness is not None:
|
self._current_attr = attr
|
||||||
self._current_led_brightness = led_brightness
|
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_option(self) -> str:
|
def current_option(self) -> str | None:
|
||||||
"""Return the current option."""
|
"""Return the current option."""
|
||||||
return self.led_brightness.lower()
|
option = self._reverse_map.get(self._current_attr)
|
||||||
|
if option is not None:
|
||||||
|
return option.lower()
|
||||||
|
return None
|
||||||
|
|
||||||
async def async_select_option(self, option: str) -> None:
|
async def async_select_option(self, option: str) -> None:
|
||||||
"""Set an option of the miio device."""
|
"""Set an option of the miio device."""
|
||||||
await self.async_set_led_brightness(option.title())
|
await self.async_set_attr(option.title())
|
||||||
|
|
||||||
@property
|
async def async_set_attr(self, attr_value: str):
|
||||||
def led_brightness(self):
|
"""Set attr."""
|
||||||
"""Return the current led brightness."""
|
method = getattr(self._device, self.entity_description.set_method)
|
||||||
return LED_BRIGHTNESS_REVERSE_MAP.get(self._current_led_brightness)
|
|
||||||
|
|
||||||
async def async_set_led_brightness(self, brightness: str):
|
|
||||||
"""Set the led brightness."""
|
|
||||||
if await self._try_command(
|
if await self._try_command(
|
||||||
"Setting the led brightness of the miio device failed.",
|
self.entity_description.set_method_error_message,
|
||||||
self._device.set_led_brightness,
|
method,
|
||||||
AirhumidifierLedBrightness(LED_BRIGHTNESS_MAP[brightness]),
|
self._enum_class(self._options_map[attr_value]),
|
||||||
):
|
):
|
||||||
self._current_led_brightness = LED_BRIGHTNESS_MAP[brightness]
|
self._current_attr = self._options_map[attr_value]
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
|
|
||||||
class XiaomiAirHumidifierMiotSelector(XiaomiAirHumidifierSelector):
|
|
||||||
"""Representation of a Xiaomi Air Humidifier (MiOT protocol) selector."""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def led_brightness(self):
|
|
||||||
"""Return the current led brightness."""
|
|
||||||
return LED_BRIGHTNESS_REVERSE_MAP_HUMIDIFIER_MIOT.get(
|
|
||||||
self._current_led_brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_set_led_brightness(self, brightness: str) -> None:
|
|
||||||
"""Set the led brightness."""
|
|
||||||
if await self._try_command(
|
|
||||||
"Setting the led brightness of the miio device failed.",
|
|
||||||
self._device.set_led_brightness,
|
|
||||||
AirhumidifierMiotLedBrightness(
|
|
||||||
LED_BRIGHTNESS_MAP_HUMIDIFIER_MIOT[brightness]
|
|
||||||
),
|
|
||||||
):
|
|
||||||
self._current_led_brightness = LED_BRIGHTNESS_MAP_HUMIDIFIER_MIOT[
|
|
||||||
brightness
|
|
||||||
]
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
|
|
||||||
class XiaomiAirPurifierSelector(XiaomiAirHumidifierSelector):
|
|
||||||
"""Representation of a Xiaomi Air Purifier (MIIO protocol) selector."""
|
|
||||||
|
|
||||||
async def async_set_led_brightness(self, brightness: str) -> None:
|
|
||||||
"""Set the led brightness."""
|
|
||||||
if await self._try_command(
|
|
||||||
"Setting the led brightness of the miio device failed.",
|
|
||||||
self._device.set_led_brightness,
|
|
||||||
AirpurifierLedBrightness(LED_BRIGHTNESS_MAP[brightness]),
|
|
||||||
):
|
|
||||||
self._current_led_brightness = LED_BRIGHTNESS_MAP[brightness]
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
|
|
||||||
class XiaomiAirPurifierMiotSelector(XiaomiAirHumidifierSelector):
|
|
||||||
"""Representation of a Xiaomi Air Purifier (MiOT protocol) selector."""
|
|
||||||
|
|
||||||
async def async_set_led_brightness(self, brightness: str) -> None:
|
|
||||||
"""Set the led brightness."""
|
|
||||||
if await self._try_command(
|
|
||||||
"Setting the led brightness of the miio device failed.",
|
|
||||||
self._device.set_led_brightness,
|
|
||||||
AirpurifierMiotLedBrightness(LED_BRIGHTNESS_MAP[brightness]),
|
|
||||||
):
|
|
||||||
self._current_led_brightness = LED_BRIGHTNESS_MAP[brightness]
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
|
|
||||||
class XiaomiFanSelector(XiaomiAirHumidifierSelector):
|
|
||||||
"""Representation of a Xiaomi Fan (MIIO protocol) selector."""
|
|
||||||
|
|
||||||
async def async_set_led_brightness(self, brightness: str) -> None:
|
|
||||||
"""Set the led brightness."""
|
|
||||||
if await self._try_command(
|
|
||||||
"Setting the led brightness of the miio device failed.",
|
|
||||||
self._device.set_led_brightness,
|
|
||||||
FanLedBrightness(LED_BRIGHTNESS_MAP[brightness]),
|
|
||||||
):
|
|
||||||
self._current_led_brightness = LED_BRIGHTNESS_MAP[brightness]
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
|
|
||||||
class XiaomiAirFreshSelector(XiaomiAirHumidifierSelector):
|
|
||||||
"""Representation of a Xiaomi Air Fresh selector."""
|
|
||||||
|
|
||||||
async def async_set_led_brightness(self, brightness: str) -> None:
|
|
||||||
"""Set the led brightness."""
|
|
||||||
if await self._try_command(
|
|
||||||
"Setting the led brightness of the miio device failed.",
|
|
||||||
self._device.set_led_brightness,
|
|
||||||
AirfreshLedBrightness(LED_BRIGHTNESS_MAP[brightness]),
|
|
||||||
):
|
|
||||||
self._current_led_brightness = LED_BRIGHTNESS_MAP[brightness]
|
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -4,6 +4,16 @@
|
|||||||
"bright": "Bright",
|
"bright": "Bright",
|
||||||
"dim": "Dim",
|
"dim": "Dim",
|
||||||
"off": "Off"
|
"off": "Off"
|
||||||
|
},
|
||||||
|
"xiaomi_miio__display_orientation": {
|
||||||
|
"forward": "Forward",
|
||||||
|
"left": "Left",
|
||||||
|
"right": "Right"
|
||||||
|
},
|
||||||
|
"xiaomi_miio__ptc_level": {
|
||||||
|
"low": "Low",
|
||||||
|
"medium": "Medium",
|
||||||
|
"high": "High"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
158
tests/components/xiaomi_miio/test_select.py
Normal file
158
tests/components/xiaomi_miio/test_select.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
"""The tests for the xiaomi_miio select component."""
|
||||||
|
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from arrow import utcnow
|
||||||
|
from miio.integrations.airpurifier.dmaker.airfresh_t2017 import (
|
||||||
|
DisplayOrientation,
|
||||||
|
PtcLevel,
|
||||||
|
)
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.select import DOMAIN
|
||||||
|
from homeassistant.components.select.const import (
|
||||||
|
ATTR_OPTION,
|
||||||
|
ATTR_OPTIONS,
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
)
|
||||||
|
from homeassistant.components.xiaomi_miio import UPDATE_INTERVAL
|
||||||
|
from homeassistant.components.xiaomi_miio.const import (
|
||||||
|
CONF_DEVICE,
|
||||||
|
CONF_FLOW_TYPE,
|
||||||
|
CONF_MAC,
|
||||||
|
DOMAIN as XIAOMI_DOMAIN,
|
||||||
|
MODEL_AIRFRESH_T2017,
|
||||||
|
)
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID,
|
||||||
|
CONF_HOST,
|
||||||
|
CONF_MODEL,
|
||||||
|
CONF_TOKEN,
|
||||||
|
Platform,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
|
from tests.components.xiaomi_miio import TEST_MAC
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
async def setup_test(hass: HomeAssistant):
|
||||||
|
"""Initialize test xiaomi_miio for select entity."""
|
||||||
|
|
||||||
|
mock_airfresh = MagicMock()
|
||||||
|
mock_airfresh.status().display_orientation = DisplayOrientation.Portrait
|
||||||
|
mock_airfresh.status().ptc_level = PtcLevel.Low
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.xiaomi_miio.get_platforms",
|
||||||
|
return_value=[
|
||||||
|
Platform.SELECT,
|
||||||
|
],
|
||||||
|
), patch("homeassistant.components.xiaomi_miio.AirFreshT2017") as mock_airfresh_cls:
|
||||||
|
mock_airfresh_cls.return_value = mock_airfresh
|
||||||
|
yield mock_airfresh
|
||||||
|
|
||||||
|
|
||||||
|
async def test_select_params(hass: HomeAssistant) -> None:
|
||||||
|
"""Test the initial parameters."""
|
||||||
|
|
||||||
|
entity_name = "test_airfresh_select"
|
||||||
|
entity_id = await setup_component(hass, entity_name)
|
||||||
|
|
||||||
|
select_entity = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert select_entity
|
||||||
|
assert select_entity.state == "forward"
|
||||||
|
assert select_entity.attributes.get(ATTR_OPTIONS) == ["forward", "left", "right"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_select_bad_attr(hass: HomeAssistant) -> None:
|
||||||
|
"""Test selecting a different option with invalid option value."""
|
||||||
|
|
||||||
|
entity_name = "test_airfresh_select"
|
||||||
|
entity_id = await setup_component(hass, entity_name)
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert state
|
||||||
|
assert state.state == "forward"
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
"select",
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
{ATTR_OPTION: "up", ATTR_ENTITY_ID: entity_id + "_display_orientation"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert state
|
||||||
|
assert state.state == "forward"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_select_option(hass: HomeAssistant) -> None:
|
||||||
|
"""Test selecting of a option."""
|
||||||
|
|
||||||
|
entity_name = "test_airfresh_select"
|
||||||
|
entity_id = await setup_component(hass, entity_name)
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert state
|
||||||
|
assert state.state == "forward"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"select",
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
{ATTR_OPTION: "left", ATTR_ENTITY_ID: entity_id + "_display_orientation"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert state
|
||||||
|
assert state.state == "left"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_select_coordinator_update(hass: HomeAssistant, setup_test) -> None:
|
||||||
|
"""Test coordinator update of a option."""
|
||||||
|
|
||||||
|
entity_name = "test_airfresh_select"
|
||||||
|
entity_id = await setup_component(hass, entity_name)
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert state
|
||||||
|
assert state.state == "forward"
|
||||||
|
|
||||||
|
# emulate someone change state from device maybe used app
|
||||||
|
setup_test.status().display_orientation = DisplayOrientation.LandscapeLeft
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, utcnow() + UPDATE_INTERVAL)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id + "_display_orientation")
|
||||||
|
assert state
|
||||||
|
assert state.state == "left"
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_component(hass, entity_name):
|
||||||
|
"""Set up component."""
|
||||||
|
entity_id = f"{DOMAIN}.{entity_name}"
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=XIAOMI_DOMAIN,
|
||||||
|
unique_id="123456",
|
||||||
|
title=entity_name,
|
||||||
|
data={
|
||||||
|
CONF_FLOW_TYPE: CONF_DEVICE,
|
||||||
|
CONF_HOST: "0.0.0.0",
|
||||||
|
CONF_TOKEN: "12345678901234567890123456789012",
|
||||||
|
CONF_MODEL: MODEL_AIRFRESH_T2017,
|
||||||
|
CONF_MAC: TEST_MAC,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
return entity_id
|
Loading…
x
Reference in New Issue
Block a user