From b5c40e34f9ad62b69acd0b73beb0f7af5a8c64dd Mon Sep 17 00:00:00 2001 From: Alone Date: Fri, 25 Dec 2020 20:26:59 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=84=20fix=20services?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/xiaomi_miot/__init__.py | 72 ++++++++++++++++----- custom_components/xiaomi_miot/climate.py | 21 +++--- custom_components/xiaomi_miot/services.yaml | 2 +- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/custom_components/xiaomi_miot/__init__.py b/custom_components/xiaomi_miot/__init__.py index d13a455aa..0e870300b 100644 --- a/custom_components/xiaomi_miot/__init__.py +++ b/custom_components/xiaomi_miot/__init__.py @@ -1,5 +1,6 @@ """Support for Xiaomi Miot.""" import logging +import asyncio from math import ceil from datetime import timedelta from functools import partial @@ -47,32 +48,35 @@ }, ) - -async def async_setup(hass, config: dict): - hass.data.setdefault(DOMAIN, {}) - component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) - hass.data[DOMAIN]['component'] = component - await component.async_setup(config) - component.async_register_entity_service( - 'send_command', - XIAOMI_MIIO_SERVICE_SCHEMA.extend( +SERVICE_TO_METHOD_BASE = { + 'send_command': { + 'method': 'async_command', + 'schema': XIAOMI_MIIO_SERVICE_SCHEMA.extend( { vol.Required('method'): cv.string, vol.Optional('params', default = []): cv.ensure_list, }, ), - 'async_command' - ) - component.async_register_entity_service( - 'set_property', - XIAOMI_MIIO_SERVICE_SCHEMA.extend( + }, + 'set_property': { + 'method': 'async_set_property', + 'schema': XIAOMI_MIIO_SERVICE_SCHEMA.extend( { vol.Required('field'): cv.string, vol.Required('value'): cv.match_all, }, ), - 'async_set_property' - ) + }, +} + + +async def async_setup(hass, config: dict): + hass.data.setdefault(DOMAIN, {}) + hass.data[DOMAIN].setdefault('entities', {}) + component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) + hass.data[DOMAIN]['component'] = component + await component.async_setup(config) + bind_services_to_entries(hass, SERVICE_TO_METHOD_BASE) return True async def async_setup_entry(hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry): @@ -110,6 +114,42 @@ async def async_setup_entry(hass: core.HomeAssistant, config_entry: config_entri return True +def bind_services_to_entries(hass, services): + async def async_service_handler(service): + method = services.get(service.service) + fun = method['method'] + params = { + key: value + for key, value in service.data.items() + if key != ATTR_ENTITY_ID + } + target_devices = [] + entity_ids = service.data.get(ATTR_ENTITY_ID) + if entity_ids: + target_devices = [ + dvc + for dvc in hass.data[DOMAIN]['entities'].values() + if dvc.entity_id in entity_ids + ] + _LOGGER.debug('Xiaomi Miot async_service_handler %s', { + 'targets' : [ dvc.entity_id for dvc in target_devices ], + 'method' : fun, + 'params' : params, + }) + update_tasks = [] + for dvc in target_devices: + if not hasattr(dvc, fun): + _LOGGER.info('%s have no method: %s', dvc.entity_id, fun) + continue + await getattr(dvc, fun)(**params) + update_tasks.append(dvc.async_update_ha_state(True)) + if update_tasks: + await asyncio.wait(update_tasks) + for srv, obj in services.items(): + schema = obj.get('schema', XIAOMI_MIIO_SERVICE_SCHEMA) + hass.services.async_register(DOMAIN, srv, async_service_handler, schema = schema) + + class MiioEntity(ToggleEntity): def __init__(self, name, device): self._device = device diff --git a/custom_components/xiaomi_miot/climate.py b/custom_components/xiaomi_miot/climate.py index 8a43e77f9..c10de10cb 100644 --- a/custom_components/xiaomi_miot/climate.py +++ b/custom_components/xiaomi_miot/climate.py @@ -1,6 +1,5 @@ """Support for Xiaomi Aircondition.""" import logging -import asyncio import voluptuous as vol from enum import Enum from functools import partial @@ -21,6 +20,7 @@ PLATFORM_SCHEMA, XIAOMI_MIIO_SERVICE_SCHEMA, MiotEntity, + bind_services_to_entries, ) _LOGGER = logging.getLogger(__name__) @@ -29,7 +29,13 @@ DEFAULT_MIN_TEMP = 16.0 DEFAULT_MAX_TEMP = 31.0 -async def async_add_entities_from_config(hass, config, async_add_entities): +SERVICE_TO_METHOD = {} + +async def async_setup_entry(hass, config_entry, async_add_entities): + config = hass.data[DOMAIN]['configs'].get(config_entry.entry_id,config_entry.data) + await async_setup_platform(hass, config, async_add_entities) + +async def async_setup_platform(hass, config, async_add_entities, discovery_info = None): if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config[CONF_HOST] @@ -38,15 +44,10 @@ async def async_add_entities_from_config(hass, config, async_add_entities): if 1: entity = MiotClimateEntity(config) entities.append(entity) - hass.data[DATA_KEY][host] = entity + for entity in entities: + hass.data[DOMAIN]['entities'][entity.unique_id] = entity async_add_entities(entities, update_before_add = True) - -async def async_setup_entry(hass, config_entry, async_add_entities): - config = hass.data[DOMAIN]['configs'].get(config_entry.entry_id,config_entry.data) - await async_add_entities_from_config(hass, config, async_add_entities) - -async def async_setup_platform(hass, config, async_add_entities, discovery_info = None): - await async_add_entities_from_config(hass, config, async_add_entities) + bind_services_to_entries(hass, SERVICE_TO_METHOD) HvacModes = Enum('HvacModes',{ diff --git a/custom_components/xiaomi_miot/services.yaml b/custom_components/xiaomi_miot/services.yaml index 665a58fcf..5d9fec60d 100644 --- a/custom_components/xiaomi_miot/services.yaml +++ b/custom_components/xiaomi_miot/services.yaml @@ -16,7 +16,7 @@ set_property: fields: entity_id: description: Name of the entity. - example: "xiaomi.aircondition.mt5" + example: "climate.xiaomi_mc5_374e" field: description: Field of property. example: power