1
0
mirror of https://github.com/home-assistant/core.git synced 2026-07-13 01:27:57 +01:00

Move Xiaomi Miio services to async_setup (#175484)

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
Erwin Douna
2026-07-06 13:23:03 +02:00
committed by GitHub
parent 793da3e37f
commit 2b690a3a82
5 changed files with 233 additions and 225 deletions
@@ -276,6 +276,16 @@ SERVICE_SET_EXTRA_FEATURES = "fan_set_extra_features"
SERVICE_SET_DRY = "set_dry"
SERVICE_SET_MOTOR_SPEED = "fan_set_motor_speed"
# Fan/Humidifier data
FAN_DATA_KEY = "fan.xiaomi_miio"
# Light data
LIGHT_DATA_KEY = "light.xiaomi_miio"
ATTR_SCENE = "scene"
# Switch data
SWITCH_DATA_KEY = "switch.xiaomi_miio"
# Light Services
SERVICE_SET_SCENE = "light_set_scene"
SERVICE_SET_DELAYED_TURN_OFF = "light_set_delayed_turn_off"
+4 -60
View File
@@ -1,7 +1,6 @@
"""Support for Xiaomi Mi Air Purifier and Xiaomi Mi Air Humidifier."""
from abc import abstractmethod
import asyncio
import logging
import math
from typing import Any, override
@@ -28,12 +27,10 @@ from miio.integrations.fan.dmaker.fan_miot import FanStatusMiot
from miio.integrations.fan.zhimi.zhimi_miot import (
OperationModeFanZA5 as FanZA5OperationMode,
)
import voluptuous as vol
from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICE, CONF_MODEL
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.const import CONF_DEVICE, CONF_MODEL
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.util.percentage import (
@@ -43,7 +40,7 @@ from homeassistant.util.percentage import (
from .const import (
CONF_FLOW_TYPE,
DOMAIN,
FAN_DATA_KEY as DATA_KEY,
FEATURE_FLAGS_AIRFRESH,
FEATURE_FLAGS_AIRFRESH_A1,
FEATURE_FLAGS_AIRFRESH_T2017,
@@ -89,16 +86,12 @@ from .const import (
MODELS_FAN_MIIO,
MODELS_FAN_MIOT,
MODELS_PURIFIER_MIOT,
SERVICE_RESET_FILTER,
SERVICE_SET_EXTRA_FEATURES,
)
from .entity import XiaomiCoordinatedMiioEntity
from .typing import ServiceMethodDetails, XiaomiMiioConfigEntry
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__)
DATA_KEY = "fan.xiaomi_miio"
ATTR_MODE_NATURE = "nature"
ATTR_MODE_NORMAL = "normal"
@@ -108,7 +101,6 @@ ATTR_FAN_LEVEL = "fan_level"
ATTR_SLEEP_TIME = "sleep_time"
ATTR_SLEEP_LEARN_COUNT = "sleep_mode_learn_count"
ATTR_EXTRA_FEATURES = "extra_features"
ATTR_FEATURES = "features"
ATTR_TURBO_MODE_SUPPORTED = "turbo_mode_supported"
ATTR_SLEEP_MODE = "sleep_mode"
ATTR_USE_TIME = "use_time"
@@ -181,20 +173,6 @@ PRESET_MODES_AIRPURIFIER_V3 = [
PRESET_MODES_AIRFRESH = ["Auto", "Interval"]
PRESET_MODES_AIRFRESH_A1 = ["Auto", "Sleep", "Favorite"]
AIRPURIFIER_SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids})
SERVICE_SCHEMA_EXTRA_FEATURES = AIRPURIFIER_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_FEATURES): cv.positive_int}
)
SERVICE_TO_METHOD = {
SERVICE_RESET_FILTER: ServiceMethodDetails(method="async_reset_filter"),
SERVICE_SET_EXTRA_FEATURES: ServiceMethodDetails(
method="async_set_extra_features",
schema=SERVICE_SCHEMA_EXTRA_FEATURES,
),
}
FAN_DIRECTIONS_MAP = {
"forward": "right",
"reverse": "left",
@@ -259,40 +237,6 @@ async def async_setup_entry(
entities.append(entity)
async def async_service_handler(service: ServiceCall) -> None:
"""Map services to methods on XiaomiAirPurifier."""
method = SERVICE_TO_METHOD[service.service]
params = {
key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID
}
if entity_ids := service.data.get(ATTR_ENTITY_ID):
filtered_entities = [
entity
for entity in hass.data[DATA_KEY].values()
if entity.entity_id in entity_ids
]
else:
filtered_entities = hass.data[DATA_KEY].values()
update_tasks = []
for entity in filtered_entities:
entity_method = getattr(entity, method.method, None)
if not entity_method:
continue
await entity_method(**params)
update_tasks.append(asyncio.create_task(entity.async_update_ha_state(True)))
if update_tasks:
await asyncio.wait(update_tasks)
for air_purifier_service, method in SERVICE_TO_METHOD.items():
schema = method.schema or AIRPURIFIER_SERVICE_SCHEMA
# pylint: disable-next=home-assistant-service-registered-in-setup-entry
hass.services.async_register(
DOMAIN, air_purifier_service, async_service_handler, schema=schema
)
async_add_entities(entities)
+5 -90
View File
@@ -1,6 +1,5 @@
"""Support for Xiaomi Philips Lights."""
import asyncio
import datetime
from datetime import timedelta
from functools import partial
@@ -23,7 +22,6 @@ from miio.gateway.gateway import (
GATEWAY_MODEL_AC_V3,
GatewayException,
)
import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
@@ -32,44 +30,30 @@ from homeassistant.components.light import (
ColorMode,
LightEntity,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_DEVICE,
CONF_HOST,
CONF_MODEL,
CONF_TOKEN,
)
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers import config_validation as cv
from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_MODEL, CONF_TOKEN
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.util import color as color_util, dt as dt_util
from .const import (
ATTR_SCENE,
CONF_FLOW_TYPE,
CONF_GATEWAY,
DOMAIN,
LIGHT_DATA_KEY as DATA_KEY,
MODELS_LIGHT_BULB,
MODELS_LIGHT_CEILING,
MODELS_LIGHT_EYECARE,
MODELS_LIGHT_MONO,
MODELS_LIGHT_MOON,
SERVICE_EYECARE_MODE_OFF,
SERVICE_EYECARE_MODE_ON,
SERVICE_NIGHT_LIGHT_MODE_OFF,
SERVICE_NIGHT_LIGHT_MODE_ON,
SERVICE_REMINDER_OFF,
SERVICE_REMINDER_ON,
SERVICE_SET_DELAYED_TURN_OFF,
SERVICE_SET_SCENE,
)
from .entity import XiaomiGatewayDevice, XiaomiMiioEntity
from .typing import ServiceMethodDetails, XiaomiMiioConfigEntry
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "Xiaomi Philips Light"
DATA_KEY = "light.xiaomi_miio"
# The light does not accept cct values < 1
CCT_MIN = 1
@@ -79,9 +63,7 @@ DELAYED_TURN_OFF_MAX_DEVIATION_SECONDS = 4
DELAYED_TURN_OFF_MAX_DEVIATION_MINUTES = 1
SUCCESS = ["ok"]
ATTR_SCENE = "scene"
ATTR_DELAYED_TURN_OFF = "delayed_turn_off"
ATTR_TIME_PERIOD = "time_period"
ATTR_NIGHT_LIGHT_MODE = "night_light_mode"
ATTR_AUTOMATIC_COLOR_TEMPERATURE = "automatic_color_temperature"
ATTR_REMINDER = "reminder"
@@ -94,37 +76,6 @@ ATTR_TOTAL_ASSISTANT_SLEEP_TIME = "total_assistant_sleep_time"
ATTR_BAND_SLEEP = "band_sleep"
ATTR_BAND = "band"
XIAOMI_MIIO_SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids})
SERVICE_SCHEMA_SET_SCENE = XIAOMI_MIIO_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_SCENE): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=6))}
)
SERVICE_SCHEMA_SET_DELAYED_TURN_OFF = XIAOMI_MIIO_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_TIME_PERIOD): cv.positive_time_period}
)
SERVICE_TO_METHOD = {
SERVICE_SET_DELAYED_TURN_OFF: ServiceMethodDetails(
method="async_set_delayed_turn_off",
schema=SERVICE_SCHEMA_SET_DELAYED_TURN_OFF,
),
SERVICE_SET_SCENE: ServiceMethodDetails(
method="async_set_scene",
schema=SERVICE_SCHEMA_SET_SCENE,
),
SERVICE_REMINDER_ON: ServiceMethodDetails(method="async_reminder_on"),
SERVICE_REMINDER_OFF: ServiceMethodDetails(method="async_reminder_off"),
SERVICE_NIGHT_LIGHT_MODE_ON: ServiceMethodDetails(
method="async_night_light_mode_on"
),
SERVICE_NIGHT_LIGHT_MODE_OFF: ServiceMethodDetails(
method="async_night_light_mode_off"
),
SERVICE_EYECARE_MODE_ON: ServiceMethodDetails(method="async_eyecare_mode_on"),
SERVICE_EYECARE_MODE_OFF: ServiceMethodDetails(method="async_eyecare_mode_off"),
}
async def async_setup_entry(
hass: HomeAssistant,
@@ -212,42 +163,6 @@ async def async_setup_entry(
)
return
async def async_service_handler(service: ServiceCall) -> None:
"""Map services to methods on Xiaomi Philips Lights."""
method = SERVICE_TO_METHOD[service.service]
params = {
key: value
for key, value in service.data.items()
if key != ATTR_ENTITY_ID
}
if entity_ids := service.data.get(ATTR_ENTITY_ID):
target_devices = [
dev
for dev in hass.data[DATA_KEY].values()
if dev.entity_id in entity_ids
]
else:
target_devices = hass.data[DATA_KEY].values()
update_tasks = []
for target_device in target_devices:
if not hasattr(target_device, method.method):
continue
await getattr(target_device, method.method)(**params)
update_tasks.append(
asyncio.create_task(target_device.async_update_ha_state(True))
)
if update_tasks:
await asyncio.wait(update_tasks)
for xiaomi_miio_service, method in SERVICE_TO_METHOD.items():
schema = method.schema or XIAOMI_MIIO_SERVICE_SCHEMA
# pylint: disable-next=home-assistant-service-registered-in-setup-entry
hass.services.async_register(
DOMAIN, xiaomi_miio_service, async_service_handler, schema=schema
)
async_add_entities(entities, update_before_add=True)
@@ -1,12 +1,39 @@
"""Xiaomi services."""
import asyncio
import logging
import voluptuous as vol
from homeassistant.components.vacuum import DOMAIN as VACUUM_DOMAIN
from homeassistant.core import HomeAssistant, callback
from homeassistant.const import ATTR_ENTITY_ID, ATTR_MODE
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_validation as cv, service
from .const import DOMAIN
from .const import (
ATTR_SCENE,
DOMAIN,
FAN_DATA_KEY,
LIGHT_DATA_KEY,
SERVICE_EYECARE_MODE_OFF,
SERVICE_EYECARE_MODE_ON,
SERVICE_NIGHT_LIGHT_MODE_OFF,
SERVICE_NIGHT_LIGHT_MODE_ON,
SERVICE_REMINDER_OFF,
SERVICE_REMINDER_ON,
SERVICE_RESET_FILTER,
SERVICE_SET_DELAYED_TURN_OFF,
SERVICE_SET_EXTRA_FEATURES,
SERVICE_SET_POWER_MODE,
SERVICE_SET_POWER_PRICE,
SERVICE_SET_SCENE,
SERVICE_SET_WIFI_LED_OFF,
SERVICE_SET_WIFI_LED_ON,
SWITCH_DATA_KEY,
)
from .typing import ServiceMethodDetails
_LOGGER = logging.getLogger(__name__)
ATTR_RC_DURATION = "duration"
ATTR_RC_ROTATION = "rotation"
@@ -23,11 +50,81 @@ SERVICE_CLEAN_SEGMENT = "vacuum_clean_segment"
SERVICE_CLEAN_ZONE = "vacuum_clean_zone"
SERVICE_GOTO = "vacuum_goto"
# Light Services
ATTR_TIME_PERIOD = "time_period"
XIAOMI_MIIO_SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids})
SERVICE_SCHEMA_SET_SCENE = XIAOMI_MIIO_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_SCENE): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=6))}
)
SERVICE_SCHEMA_SET_DELAYED_TURN_OFF = XIAOMI_MIIO_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_TIME_PERIOD): cv.positive_time_period}
)
LIGHT_SERVICE_TO_METHOD = {
SERVICE_SET_DELAYED_TURN_OFF: ServiceMethodDetails(
method="async_set_delayed_turn_off",
schema=SERVICE_SCHEMA_SET_DELAYED_TURN_OFF,
),
SERVICE_SET_SCENE: ServiceMethodDetails(
method="async_set_scene",
schema=SERVICE_SCHEMA_SET_SCENE,
),
SERVICE_REMINDER_ON: ServiceMethodDetails(method="async_reminder_on"),
SERVICE_REMINDER_OFF: ServiceMethodDetails(method="async_reminder_off"),
SERVICE_NIGHT_LIGHT_MODE_ON: ServiceMethodDetails(
method="async_night_light_mode_on"
),
SERVICE_NIGHT_LIGHT_MODE_OFF: ServiceMethodDetails(
method="async_night_light_mode_off"
),
SERVICE_EYECARE_MODE_ON: ServiceMethodDetails(method="async_eyecare_mode_on"),
SERVICE_EYECARE_MODE_OFF: ServiceMethodDetails(method="async_eyecare_mode_off"),
}
# Switch Services
ATTR_PRICE = "price"
SWITCH_SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids})
SWITCH_SERVICE_SCHEMA_POWER_MODE = SWITCH_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_MODE): vol.All(vol.In(["green", "normal"]))}
)
SWITCH_SERVICE_SCHEMA_POWER_PRICE = SWITCH_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_PRICE): cv.positive_float}
)
SWITCH_SERVICE_TO_METHOD = {
SERVICE_SET_WIFI_LED_ON: ServiceMethodDetails(method="async_set_wifi_led_on"),
SERVICE_SET_WIFI_LED_OFF: ServiceMethodDetails(method="async_set_wifi_led_off"),
SERVICE_SET_POWER_MODE: ServiceMethodDetails(
method="async_set_power_mode",
schema=SWITCH_SERVICE_SCHEMA_POWER_MODE,
),
SERVICE_SET_POWER_PRICE: ServiceMethodDetails(
method="async_set_power_price",
schema=SWITCH_SERVICE_SCHEMA_POWER_PRICE,
),
}
# Fan Services
ATTR_FEATURES = "features"
FAN_SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids})
FAN_SERVICE_SCHEMA_EXTRA_FEATURES = FAN_SERVICE_SCHEMA.extend(
{vol.Required(ATTR_FEATURES): cv.positive_int}
)
FAN_SERVICE_TO_METHOD = {
SERVICE_RESET_FILTER: ServiceMethodDetails(method="async_reset_filter"),
SERVICE_SET_EXTRA_FEATURES: ServiceMethodDetails(
method="async_set_extra_features",
schema=FAN_SERVICE_SCHEMA_EXTRA_FEATURES,
),
}
@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Set up services."""
_async_setup_fan_services(hass)
_async_setup_light_services(hass)
_async_setup_switch_services(hass)
# Vacuum Services
service.async_register_platform_entity_service(
hass,
@@ -126,3 +223,115 @@ def async_setup_services(hass: HomeAssistant) -> None:
schema={vol.Required("segments"): vol.Any(vol.Coerce(int), [vol.Coerce(int)])},
func="async_clean_segment",
)
def _async_setup_light_services(hass: HomeAssistant) -> None:
"""Set up Xiaomi Miio light services."""
hass.data.setdefault(LIGHT_DATA_KEY, {})
async def async_service_handler(call: ServiceCall) -> None:
"""Map services to methods on Xiaomi Philips Lights."""
method = LIGHT_SERVICE_TO_METHOD[call.service]
params = {
key: value for key, value in call.data.items() if key != ATTR_ENTITY_ID
}
if entity_ids := call.data.get(ATTR_ENTITY_ID):
target_devices = [
dev
for dev in hass.data[LIGHT_DATA_KEY].values()
if dev.entity_id in entity_ids
]
else:
target_devices = hass.data[LIGHT_DATA_KEY].values()
update_tasks = []
for target_device in target_devices:
if not hasattr(target_device, method.method):
continue
await getattr(target_device, method.method)(**params)
update_tasks.append(
asyncio.create_task(target_device.async_update_ha_state(True))
)
if update_tasks:
await asyncio.wait(update_tasks)
for xiaomi_miio_service, method in LIGHT_SERVICE_TO_METHOD.items():
schema = method.schema or XIAOMI_MIIO_SERVICE_SCHEMA
hass.services.async_register(
DOMAIN, xiaomi_miio_service, async_service_handler, schema=schema
)
def _async_setup_switch_services(hass: HomeAssistant) -> None:
"""Set up Xiaomi Miio switch services."""
hass.data.setdefault(SWITCH_DATA_KEY, {})
async def async_service_handler(call: ServiceCall) -> None:
"""Map services to methods on XiaomiPlugGenericSwitch."""
method = SWITCH_SERVICE_TO_METHOD[call.service]
params = {
key: value for key, value in call.data.items() if key != ATTR_ENTITY_ID
}
if entity_ids := call.data.get(ATTR_ENTITY_ID):
devices = [
device
for device in hass.data[SWITCH_DATA_KEY].values()
if device.entity_id in entity_ids
]
else:
devices = hass.data[SWITCH_DATA_KEY].values()
update_tasks = []
for device in devices:
if not hasattr(device, method.method):
continue
await getattr(device, method.method)(**params)
update_tasks.append(asyncio.create_task(device.async_update_ha_state(True)))
if update_tasks:
await asyncio.wait(update_tasks)
for plug_service, method in SWITCH_SERVICE_TO_METHOD.items():
schema = method.schema or SWITCH_SERVICE_SCHEMA
hass.services.async_register(
DOMAIN, plug_service, async_service_handler, schema=schema
)
def _async_setup_fan_services(hass: HomeAssistant) -> None:
"""Set up Xiaomi Miio fan services."""
hass.data.setdefault(FAN_DATA_KEY, {})
async def async_service_handler(call: ServiceCall) -> None:
"""Map services to methods on XiaomiAirPurifier."""
method = FAN_SERVICE_TO_METHOD[call.service]
params = {
key: value for key, value in call.data.items() if key != ATTR_ENTITY_ID
}
if entity_ids := call.data.get(ATTR_ENTITY_ID):
filtered_entities = [
entity
for entity in hass.data[FAN_DATA_KEY].values()
if entity.entity_id in entity_ids
]
else:
filtered_entities = hass.data[FAN_DATA_KEY].values()
update_tasks = []
for entity in filtered_entities:
entity_method = getattr(entity, method.method, None)
if not entity_method:
continue
await entity_method(**params)
update_tasks.append(asyncio.create_task(entity.async_update_ha_state(True)))
if update_tasks:
await asyncio.wait(update_tasks)
for air_purifier_service, method in FAN_SERVICE_TO_METHOD.items():
schema = method.schema or FAN_SERVICE_SCHEMA
hass.services.async_register(
DOMAIN, air_purifier_service, async_service_handler, schema=schema
)
+3 -73
View File
@@ -1,6 +1,5 @@
"""Support for Xiaomi Smart WiFi Socket and Smart Power Strip."""
import asyncio
from dataclasses import dataclass
from functools import partial
import logging
@@ -15,7 +14,6 @@ from miio import (
)
from miio.gateway.devices.switch import Switch
from miio.powerstrip import PowerMode
import voluptuous as vol
from homeassistant.components.switch import (
SwitchDeviceClass,
@@ -23,8 +21,6 @@ from homeassistant.components.switch import (
SwitchEntityDescription,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_MODE,
ATTR_MODEL,
ATTR_TEMPERATURE,
CONF_DEVICE,
@@ -33,15 +29,13 @@ from homeassistant.const import (
CONF_TOKEN,
EntityCategory,
)
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import (
CONF_FLOW_TYPE,
CONF_GATEWAY,
DOMAIN,
FEATURE_FLAGS_AIRFRESH,
FEATURE_FLAGS_AIRFRESH_A1,
FEATURE_FLAGS_AIRFRESH_T2017,
@@ -113,20 +107,16 @@ from .const import (
MODELS_HUMIDIFIER_MJJSQ,
MODELS_PURIFIER_MIIO,
MODELS_PURIFIER_MIOT,
SERVICE_SET_POWER_MODE,
SERVICE_SET_POWER_PRICE,
SERVICE_SET_WIFI_LED_OFF,
SERVICE_SET_WIFI_LED_ON,
SUCCESS,
SWITCH_DATA_KEY as DATA_KEY,
)
from .coordinator import GatewayDeviceCoordinator
from .entity import XiaomiCoordinatedMiioEntity, XiaomiGatewayDevice, XiaomiMiioEntity
from .typing import ServiceMethodDetails, XiaomiMiioConfigEntry
from .typing import XiaomiMiioConfigEntry
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "Xiaomi Miio Switch"
DATA_KEY = "switch.xiaomi_miio"
MODEL_POWER_STRIP_V2 = "zimi.powerstrip.v2"
MODEL_PLUG_V3 = "chuangmi.plug.v3"
@@ -153,7 +143,6 @@ ATTR_LOAD_POWER = "load_power"
ATTR_POWER = "power"
ATTR_POWER_MODE = "power_mode"
ATTR_POWER_PRICE = "power_price"
ATTR_PRICE = "price"
ATTR_PTC = "ptc"
ATTR_WIFI_LED = "wifi_led"
@@ -171,29 +160,6 @@ FEATURE_FLAGS_POWER_STRIP_V2 = FEATURE_SET_WIFI_LED | FEATURE_SET_POWER_PRICE
FEATURE_FLAGS_PLUG_V3 = FEATURE_SET_WIFI_LED
SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids})
SERVICE_SCHEMA_POWER_MODE = SERVICE_SCHEMA.extend(
{vol.Required(ATTR_MODE): vol.All(vol.In(["green", "normal"]))}
)
SERVICE_SCHEMA_POWER_PRICE = SERVICE_SCHEMA.extend(
{vol.Required(ATTR_PRICE): cv.positive_float}
)
SERVICE_TO_METHOD = {
SERVICE_SET_WIFI_LED_ON: ServiceMethodDetails(method="async_set_wifi_led_on"),
SERVICE_SET_WIFI_LED_OFF: ServiceMethodDetails(method="async_set_wifi_led_off"),
SERVICE_SET_POWER_MODE: ServiceMethodDetails(
method="async_set_power_mode",
schema=SERVICE_SCHEMA_POWER_MODE,
),
SERVICE_SET_POWER_PRICE: ServiceMethodDetails(
method="async_set_power_price",
schema=SERVICE_SCHEMA_POWER_PRICE,
),
}
MODEL_TO_FEATURES_MAP = {
MODEL_AIRFRESH_A1: FEATURE_FLAGS_AIRFRESH_A1,
MODEL_AIRFRESH_VA2: FEATURE_FLAGS_AIRFRESH,
@@ -486,42 +452,6 @@ async def async_setup_other_entry(
model,
)
async def async_service_handler(service: ServiceCall) -> None:
"""Map services to methods on XiaomiPlugGenericSwitch."""
method = SERVICE_TO_METHOD[service.service]
params = {
key: value
for key, value in service.data.items()
if key != ATTR_ENTITY_ID
}
if entity_ids := service.data.get(ATTR_ENTITY_ID):
devices = [
device
for device in hass.data[DATA_KEY].values()
if device.entity_id in entity_ids
]
else:
devices = hass.data[DATA_KEY].values()
update_tasks = []
for device in devices:
if not hasattr(device, method.method):
continue
await getattr(device, method.method)(**params)
update_tasks.append(
asyncio.create_task(device.async_update_ha_state(True))
)
if update_tasks:
await asyncio.wait(update_tasks)
for plug_service, method in SERVICE_TO_METHOD.items():
schema = method.schema or SERVICE_SCHEMA
# pylint: disable-next=home-assistant-service-registered-in-setup-entry
hass.services.async_register(
DOMAIN, plug_service, async_service_handler, schema=schema
)
async_add_entities(entities)