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:
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user