From 006a445e3aa0beb044337301a43d38ba033d5a38 Mon Sep 17 00:00:00 2001 From: GavinIves Date: Wed, 4 Jun 2025 08:19:00 +0000 Subject: [PATCH 1/5] Added command sending mode for lights to optimize the lighting effect --- custom_components/xiaomi_home/light.py | 216 +++++++++++++++--- .../xiaomi_home/miot/miot_client.py | 80 ++++++- .../xiaomi_home/miot/miot_cloud.py | 16 ++ .../xiaomi_home/miot/miot_device.py | 44 +++- .../xiaomi_home/miot/miot_lan.py | 25 +- .../xiaomi_home/miot/miot_mips.py | 39 +++- custom_components/xiaomi_home/select.py | 48 ++++ 7 files changed, 426 insertions(+), 42 deletions(-) diff --git a/custom_components/xiaomi_home/light.py b/custom_components/xiaomi_home/light.py index 26ed208..ec47607 100644 --- a/custom_components/xiaomi_home/light.py +++ b/custom_components/xiaomi_home/light.py @@ -47,11 +47,12 @@ Light entities for Xiaomi Home. """ from __future__ import annotations import logging -from typing import Any, Optional +from typing import Any, Optional, List, Dict from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.entity_registry import async_get as async_get_entity_registry from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP_KELVIN, @@ -86,7 +87,7 @@ async def async_setup_entry( for miot_device in device_list: for data in miot_device.entity_list.get('light', []): new_entities.append( - Light(miot_device=miot_device, entity_data=data)) + Light(miot_device=miot_device, entity_data=data, hass=hass)) if new_entities: async_add_entities(new_entities) @@ -106,10 +107,13 @@ class Light(MIoTServiceEntity, LightEntity): _mode_map: Optional[dict[Any, Any]] def __init__( - self, miot_device: MIoTDevice, entity_data: MIoTEntityData + self, miot_device: MIoTDevice, entity_data: MIoTEntityData,hass: HomeAssistant ) -> None: """Initialize the Light.""" super().__init__(miot_device=miot_device, entity_data=entity_data) + self.hass = hass + self.miot_device = miot_device + self._command_send_mode_entity_id = None self._attr_color_mode = None self._attr_supported_color_modes = set() self._attr_supported_features = LightEntityFeature(0) @@ -252,42 +256,178 @@ class Light(MIoTServiceEntity, LightEntity): """ # on # Dirty logic for lumi.gateway.mgl03 indicator light - if self._prop_on: - value_on = True if self._prop_on.format_ == bool else 1 - await self.set_property_async( - prop=self._prop_on, value=value_on) - # brightness + # Determine whether the device sends the light-on properties in batches or one by one + # Search entityid through unique_id to avoid the user modifying entityid and causing command_send_mode to not match + # 获取开灯模式 + if self._command_send_mode_entity_id is None: + entity_registry = async_get_entity_registry(self.hass) + device_id = list( + self.miot_device.device_info.get("identifiers"))[0][1] + self._command_send_mode_entity_id = entity_registry.async_get_entity_id( + "select", DOMAIN, f"select.light_{device_id}_command_send_mode") + if self._command_send_mode_entity_id is None: + _LOGGER.error( + "light command_send_mode not found, %s", + self.entity_id, + ) + return + command_send_mode = self.hass.states.get( + self._command_send_mode_entity_id) + + # 判断是先发送亮度还是先发送色温 + send_brightness_first = False if ATTR_BRIGHTNESS in kwargs: - brightness = brightness_to_value( - self._brightness_scale, kwargs[ATTR_BRIGHTNESS]) - await self.set_property_async( - prop=self._prop_brightness, value=brightness, - write_ha_state=False) - # color-temperature - if ATTR_COLOR_TEMP_KELVIN in kwargs: - await self.set_property_async( - prop=self._prop_color_temp, - value=kwargs[ATTR_COLOR_TEMP_KELVIN], - write_ha_state=False) - self._attr_color_mode = ColorMode.COLOR_TEMP - # rgb color - if ATTR_RGB_COLOR in kwargs: - r = kwargs[ATTR_RGB_COLOR][0] - g = kwargs[ATTR_RGB_COLOR][1] - b = kwargs[ATTR_RGB_COLOR][2] - rgb = (r << 16) | (g << 8) | b - await self.set_property_async( - prop=self._prop_color, value=rgb, - write_ha_state=False) - self._attr_color_mode = ColorMode.RGB - # mode - if ATTR_EFFECT in kwargs: - await self.set_property_async( - prop=self._prop_mode, - value=self.get_map_key( - map_=self._mode_map, value=kwargs[ATTR_EFFECT]), - write_ha_state=False) - self.async_write_ha_state() + brightness_new = kwargs[ATTR_BRIGHTNESS] + brightness_old = self.brightness + if brightness_old and brightness_new <= brightness_old: + send_brightness_first = True + + # 开始发送开灯命令 + if command_send_mode and command_send_mode.state == "Send Together": + set_properties_list: List[Dict[str, Any]] = [] + # mode + if ATTR_EFFECT in kwargs: + set_properties_list.append({ + "prop":self._prop_mode, + "value":self.get_map_key( + map_=self._mode_map,value=kwargs[ATTR_EFFECT]), + }) + # brightness + if send_brightness_first and ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value( + self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) + set_properties_list.append({ + "prop": self._prop_brightness, + "value": brightness + }) + # color-temperature + if ATTR_COLOR_TEMP_KELVIN in kwargs: + set_properties_list.append({ + "prop": self._prop_color_temp, + "value": kwargs[ATTR_COLOR_TEMP_KELVIN], + }) + self._attr_color_mode = ColorMode.COLOR_TEMP + # rgb color + if ATTR_RGB_COLOR in kwargs: + r = kwargs[ATTR_RGB_COLOR][0] + g = kwargs[ATTR_RGB_COLOR][1] + b = kwargs[ATTR_RGB_COLOR][2] + rgb = (r << 16) | (g << 8) | b + set_properties_list.append({ + "prop": self._prop_color, + "value": rgb + }) + self._attr_color_mode = ColorMode.RGB + # brightness + if not send_brightness_first and ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value( + self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) + set_properties_list.append({ + "prop": self._prop_brightness, + "value": brightness + }) + + if self._prop_on: + value_on = True if self._prop_on.format_ == bool else 1 + set_properties_list.append({ + "prop": self._prop_on, + "value": value_on + }) + await self.set_properties_async(set_properties_list,write_ha_state=False) + self.async_write_ha_state() + + elif command_send_mode and command_send_mode.state == "Send Turn On First": + set_properties_list: List[Dict[str, Any]] = [] + if self._prop_on: + value_on = True if self._prop_on.format_ == bool else 1 + set_properties_list.append({ + "prop": self._prop_on, + "value": value_on + }) + # mode + if ATTR_EFFECT in kwargs: + set_properties_list.append({ + "prop": + self._prop_mode, + "value": + self.get_map_key( + map_=self._mode_map,value=kwargs[ATTR_EFFECT]), + }) + # brightness + if send_brightness_first and ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value( + self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) + set_properties_list.append({ + "prop": self._prop_brightness, + "value": brightness + }) + # color-temperature + if ATTR_COLOR_TEMP_KELVIN in kwargs: + set_properties_list.append({ + "prop": self._prop_color_temp, + "value": kwargs[ATTR_COLOR_TEMP_KELVIN], + }) + self._attr_color_mode = ColorMode.COLOR_TEMP + # rgb color + if ATTR_RGB_COLOR in kwargs: + r = kwargs[ATTR_RGB_COLOR][0] + g = kwargs[ATTR_RGB_COLOR][1] + b = kwargs[ATTR_RGB_COLOR][2] + rgb = (r << 16) | (g << 8) | b + set_properties_list.append({ + "prop": self._prop_color, + "value": rgb + }) + self._attr_color_mode = ColorMode.RGB + # brightness + if not send_brightness_first and ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value( + self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) + set_properties_list.append({ + "prop": self._prop_brightness, + "value": brightness + }) + + await self.set_properties_async(set_properties_list,write_ha_state=False) + self.async_write_ha_state() + + else: + if self._prop_on: + value_on = True if self._prop_on.format_ == bool else 1 + await self.set_property_async( + prop=self._prop_on, value=value_on) + # brightness + if ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value( + self._brightness_scale, kwargs[ATTR_BRIGHTNESS]) + await self.set_property_async( + prop=self._prop_brightness, value=brightness, + write_ha_state=False) + # color-temperature + if ATTR_COLOR_TEMP_KELVIN in kwargs: + await self.set_property_async( + prop=self._prop_color_temp, + value=kwargs[ATTR_COLOR_TEMP_KELVIN], + write_ha_state=False) + self._attr_color_mode = ColorMode.COLOR_TEMP + # rgb color + if ATTR_RGB_COLOR in kwargs: + r = kwargs[ATTR_RGB_COLOR][0] + g = kwargs[ATTR_RGB_COLOR][1] + b = kwargs[ATTR_RGB_COLOR][2] + rgb = (r << 16) | (g << 8) | b + await self.set_property_async( + prop=self._prop_color, value=rgb, + write_ha_state=False) + self._attr_color_mode = ColorMode.RGB + # mode + if ATTR_EFFECT in kwargs: + await self.set_property_async( + prop=self._prop_mode, + value=self.get_map_key( + map_=self._mode_map, value=kwargs[ATTR_EFFECT]), + write_ha_state=False) + self.async_write_ha_state() async def async_turn_off(self, **kwargs) -> None: """Turn the light off.""" diff --git a/custom_components/xiaomi_home/miot/miot_client.py b/custom_components/xiaomi_home/miot/miot_client.py index cc6520c..194b7e3 100644 --- a/custom_components/xiaomi_home/miot/miot_client.py +++ b/custom_components/xiaomi_home/miot/miot_client.py @@ -46,7 +46,7 @@ off Xiaomi or its affiliates' products. MIoT client instance. """ from copy import deepcopy -from typing import Any, Callable, Optional, final +from typing import Any, Callable, Optional, final, Dict, List import asyncio import json import logging @@ -710,6 +710,84 @@ class MIoTClient: f'{self._i18n.translate("miot.client.device_exec_error")}, ' f'{self._i18n.translate("error.common.-10007")}') + async def set_props_async( + self, props_list: List[Dict[str, Any]], + ) -> bool: + # props_list = [{'did': str, 'siid': int, 'piid': int, 'value': Any}......] + # 判断是不是只有一个did + did_set = {prop["did"] for prop in props_list} + if len(did_set) == 1: + raise MIoTClientError(f"more than one or no did once, {did_set}") + did = did_set.pop() + + if did not in self._device_list_cache: + raise MIoTClientError(f"did not exist, {did}") + # Priority local control + if self._ctrl_mode == CtrlMode.AUTO: + # Gateway control + device_gw = self._device_list_gateway.get(did, None) + if ( + device_gw and device_gw.get("online", False) + and device_gw.get("specv2_access", False) and "group_id" in device_gw + ): + mips = self._mips_local.get(device_gw["group_id"], None) + if mips is None: + _LOGGER.error( + "no gateway route, %s, try control through cloud", + device_gw) + else: + result = await mips.set_props_async( + did=did,props_list=props_list) + _LOGGER.debug("gateway set props, %s -> %s", props_list, result) + rc = [(r or {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) + for r in result] + if all(t in [0, 1] for t in rc): + return True + else: + raise MIoTClientError( + self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) + # Lan control + device_lan = self._device_list_lan.get(did, None) + if device_lan and device_lan.get("online", False): + result = await self._miot_lan.set_props_async( + did=did, props_list=props_list) + _LOGGER.debug("lan set props, %s -> %s", props_list, result) + rc = [(r or {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) + for r in result] + if all(t in [0, 1] for t in rc): + return True + else: + raise MIoTClientError( + self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) + # Cloud control + device_cloud = self._device_list_cloud.get(did, None) + if device_cloud and device_cloud.get("online", False): + result = await self._http.set_props_async(params=props_list) + _LOGGER.debug( + "cloud set props, %s, result, %s", + props_list, result) + if result and len(result) == len(props_list): + rc = [(r or {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) + for r in result] + if all(t in [0, 1] for t in rc): + return True + if any(t in [-704010000, -704042011] for t in rc): + # Device remove or offline + _LOGGER.error("device may be removed or offline, %s", did) + self._main_loop.create_task( + await + self.__refresh_cloud_device_with_dids_async(dids=[did])) + raise MIoTClientError( + self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) + + # Show error message + raise MIoTClientError( + f'{self._i18n.translate("miot.client.device_exec_error")}, ' + f'{self._i18n.translate("error.common.-10007")}') + def request_refresh_prop( self, did: str, siid: int, piid: int ) -> None: diff --git a/custom_components/xiaomi_home/miot/miot_cloud.py b/custom_components/xiaomi_home/miot/miot_cloud.py index ed672a0..d9acd5c 100644 --- a/custom_components/xiaomi_home/miot/miot_cloud.py +++ b/custom_components/xiaomi_home/miot/miot_cloud.py @@ -825,6 +825,22 @@ class MIoTHttpClient: return res_obj['result'] + async def set_props_async(self, params: list) -> list: + """ + params = [{"did": "xxxx", "siid": 2, "piid": 1, "value": False}] + """ + res_obj = await self.__mihome_api_post_async( + url_path='/app/v2/miotspec/prop/set', + data={ + 'params': params + }, + timeout=15 + ) + if 'result' not in res_obj: + raise MIoTHttpError('invalid response result') + + return res_obj['result'] + async def action_async( self, did: str, siid: int, aiid: int, in_list: list[dict] ) -> dict: diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index 011676c..a8e2e48 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -47,7 +47,7 @@ MIoT device instance. """ import asyncio from abc import abstractmethod -from typing import Any, Callable, Optional +from typing import Any, Callable, Optional, Dict, List import logging from homeassistant.helpers.entity import Entity @@ -1082,6 +1082,48 @@ class MIoTServiceEntity(Entity): self.async_write_ha_state() return True + async def set_properties_async( + self, set_properties_list: List[Dict[str, Any]], + update_value: bool = True, write_ha_state: bool = True, + ) -> bool: + # set_properties_list = [{'prop': Optional[MIoTSpecProperty], + # 'value': Any}....] + for set_property in set_properties_list: + prop = set_property.get("prop") + value = set_property.get("value") + if not prop: + raise RuntimeError( + f'set property failed, property is None, ' + f'{self.entity_id}, {self.name}') + value = prop.value_format(value) + value = prop.value_precision(value) + # 因为下面还有判断在这个循环里 所以这里要赋值回去 + set_property["value"] = value + if prop not in self.entity_data.props: + raise RuntimeError( + f'set property failed, unknown property, ' + f'{self.entity_id}, {self.name}, {prop.name}') + if not prop.writable: + raise RuntimeError( + f'set property failed, not writable, ' + f'{self.entity_id}, {self.name}, {prop.name}') + try: + await self.miot_device.miot_client.set_props_async([{ + "did": self.miot_device.did, + "siid": set_property["prop"].service.iid, + "piid": set_property["prop"].iid, + "value": set_property["value"], + } for set_property in set_properties_list]) + except MIoTClientError as e: + raise RuntimeError( + f"{e}, {self.entity_id}, {self.name}, {'&'.join([set_property['prop'].name for set_property in set_properties_list])}") from e + if update_value: + for set_property in set_properties_list: + self._prop_value_map[set_property["prop"]] = set_property["value"] + if write_ha_state: + self.async_write_ha_state() + return True + async def get_property_async(self, prop: MIoTSpecProperty) -> Any: if not prop: _LOGGER.error( diff --git a/custom_components/xiaomi_home/miot/miot_lan.py b/custom_components/xiaomi_home/miot/miot_lan.py index 5c56a55..8e95b32 100644 --- a/custom_components/xiaomi_home/miot/miot_lan.py +++ b/custom_components/xiaomi_home/miot/miot_lan.py @@ -58,7 +58,7 @@ import secrets import socket import struct import threading -from typing import Any, Callable, Coroutine, Optional, final +from typing import Any, Callable, Coroutine, Optional, final, Dict, List from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding from cryptography.hazmat.backends import default_backend @@ -857,6 +857,29 @@ class MIoTLan: return result_obj raise MIoTError('Invalid result', MIoTErrorCode.CODE_INTERNAL_ERROR) + @final + async def set_props_async( + self,did: str,props_list: List[Dict[str, Any]], + timeout_ms: int = 10000) -> dict: + # props_list = [{'did': did, 'siid': siid, 'piid': piid, 'value': value}......] + self.__assert_service_ready() + result_obj = await self.__call_api_async( + did=did, msg={ + 'method': 'set_properties', + 'params': props_list, + }, timeout_ms=timeout_ms) + if result_obj: + if ( + 'result' in result_obj and + len(result_obj['result']) == len(props_list) + and result_obj['result'][0].get('did') == did + and all('code' in item for item in result_obj['result']) + ): + return result_obj['result'] + if 'code' in result_obj: + return result_obj + raise MIoTError('Invalid result', MIoTErrorCode.CODE_INTERNAL_ERROR) + @final async def action_async( self, did: str, siid: int, aiid: int, in_list: list, diff --git a/custom_components/xiaomi_home/miot/miot_mips.py b/custom_components/xiaomi_home/miot/miot_mips.py index f4305c7..99499b2 100644 --- a/custom_components/xiaomi_home/miot/miot_mips.py +++ b/custom_components/xiaomi_home/miot/miot_mips.py @@ -56,7 +56,7 @@ import threading from abc import ABC, abstractmethod from dataclasses import dataclass from enum import Enum, auto -from typing import Any, Callable, Optional, final, Coroutine +from typing import Any, Callable, Optional, final, Coroutine, Dict, List from paho.mqtt.client import ( MQTT_ERR_SUCCESS, @@ -1342,6 +1342,43 @@ class MipsLocalClient(_MipsClient): 'code': MIoTErrorCode.CODE_INTERNAL_ERROR.value, 'message': 'Invalid result'} + @final + async def set_props_async( + self, did: str, props_list: List[Dict[str, Any]], + timeout_ms: int = 10000 + ) -> dict: + # props_list= [{ + # 'did': did, + # 'siid': siid, + # 'piid': piid, + # 'value': value + # }] + payload_obj: dict = { + "did": did, + "rpc": { + "id": self.__gen_mips_id, + "method": "set_properties", + "params": props_list, + } + } + result_obj = await self.__request_async( + topic="proxy/rpcReq", + payload=json.dumps(payload_obj), + timeout_ms=timeout_ms) + if result_obj: + if ( + "result" in result_obj + and len(result_obj["result"]) == len(props_list) + and result_obj["result"][0].get("did") == did + and all("code" in item for item in result_obj["result"]) + ): + return result_obj["result"] + if "error" in result_obj: + return result_obj["error"] + return { + 'code': MIoTErrorCode.CODE_INTERNAL_ERROR.value, + 'message': 'Invalid result'} + @final async def action_async( self, did: str, siid: int, aiid: int, in_list: list, diff --git a/custom_components/xiaomi_home/select.py b/custom_components/xiaomi_home/select.py index 21b5e78..3804d63 100644 --- a/custom_components/xiaomi_home/select.py +++ b/custom_components/xiaomi_home/select.py @@ -52,6 +52,8 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.components.select import SelectEntity +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.restore_state import RestoreEntity from .miot.const import DOMAIN from .miot.miot_device import MIoTDevice, MIoTPropertyEntity @@ -75,6 +77,17 @@ async def async_setup_entry( if new_entities: async_add_entities(new_entities) + # create select for light + new_light_select_entities = [] + for miot_device in device_list: + # Add it to all devices with light entities, because some bathroom heaters and clothes drying racks also have lights. + # if "device:light" in miot_device.spec_instance.urn: + if miot_device.entity_list.get("light", []): + device_id = list(miot_device.device_info.get("identifiers"))[0][1] + new_light_select_entities.append( + LightCommandSendMode(hass=hass, device_id=device_id)) + if new_light_select_entities: + async_add_entities(new_light_select_entities) class Select(MIoTPropertyEntity, SelectEntity): """Select entities for Xiaomi Home.""" @@ -94,3 +107,38 @@ class Select(MIoTPropertyEntity, SelectEntity): def current_option(self) -> Optional[str]: """Return the current selected option.""" return self.get_vlist_description(value=self._value) + + +class LightCommandSendMode(SelectEntity, RestoreEntity): + """To control whether to turn on the light, you need to send the light-on command first and + then send other color temperatures and brightness or send them all at the same time. + The default is to send one by one.""" + + def __init__(self, hass: HomeAssistant, device_id: str): + super().__init__() + self.hass = hass + self._device_id = device_id + self._attr_name = "Command Send Mode" + self.entity_id = f"select.light_{device_id}_command_send_mode" + self._attr_unique_id = self.entity_id + self._attr_options = [ + "Send One by One", "Send Turn On First", "Send Together" + ] + self._attr_device_info = {"identifiers": {(DOMAIN, device_id)}} + self._attr_current_option = self._attr_options[0] + self._attr_entity_category = EntityCategory.CONFIG + + async def async_select_option(self, option: str): + if option in self._attr_options: + self._attr_current_option = option + self.async_write_ha_state() + + async def async_added_to_hass(self): + await super().async_added_to_hass() + if (last_state := await self.async_get_last_state() + ) and last_state.state in self._attr_options: + self._attr_current_option = last_state.state + + @property + def current_option(self): + return self._attr_current_option From 5dc6f400c2741d8bfb5fed04cdf17c368c948919 Mon Sep 17 00:00:00 2001 From: GavinIves Date: Wed, 4 Jun 2025 08:52:48 +0000 Subject: [PATCH 2/5] fomatted code --- custom_components/xiaomi_home/light.py | 109 ++ .../xiaomi_home/miot/miot_client.py | 970 +++++++++++++++++- .../xiaomi_home/miot/miot_cloud.py | 400 +++++++- .../xiaomi_home/miot/miot_device.py | 476 ++++++++- .../xiaomi_home/miot/miot_lan.py | 513 ++++++++- .../xiaomi_home/miot/miot_mips.py | 628 +++++++++++- custom_components/xiaomi_home/select.py | 37 + 7 files changed, 3051 insertions(+), 82 deletions(-) diff --git a/custom_components/xiaomi_home/light.py b/custom_components/xiaomi_home/light.py index ec47607..50350ad 100644 --- a/custom_components/xiaomi_home/light.py +++ b/custom_components/xiaomi_home/light.py @@ -80,7 +80,11 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up a config entry.""" +<<<<<<< HEAD device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][ +======= + device_list: list[MIoTDevice] = hass.data[DOMAIN]["devices"][ +>>>>>>> 83899f8 (fomatted code) config_entry.entry_id] new_entities = [] @@ -106,9 +110,14 @@ class Light(MIoTServiceEntity, LightEntity): _brightness_scale: Optional[tuple[int, int]] _mode_map: Optional[dict[Any, Any]] +<<<<<<< HEAD def __init__( self, miot_device: MIoTDevice, entity_data: MIoTEntityData,hass: HomeAssistant ) -> None: +======= + def __init__(self, miot_device: MIoTDevice, entity_data: MIoTEntityData, + hass: HomeAssistant) -> None: +>>>>>>> 83899f8 (fomatted code) """Initialize the Light.""" super().__init__(miot_device=miot_device, entity_data=entity_data) self.hass = hass @@ -149,8 +158,13 @@ class Light(MIoTServiceEntity, LightEntity): self._attr_supported_features |= LightEntityFeature.EFFECT self._prop_mode = prop else: +<<<<<<< HEAD _LOGGER.info( 'invalid brightness format, %s', self.entity_id) +======= + _LOGGER.info("invalid brightness format, %s", + self.entity_id) +>>>>>>> 83899f8 (fomatted code) continue # color-temperature if prop.name == 'color-temperature': @@ -176,6 +190,7 @@ class Light(MIoTServiceEntity, LightEntity): mode_list = prop.value_list.to_map() elif prop.value_range: mode_list = {} +<<<<<<< HEAD if ( int(( prop.value_range.max_ @@ -183,6 +198,11 @@ class Light(MIoTServiceEntity, LightEntity): ) / prop.value_range.step) > self._VALUE_RANGE_MODE_COUNT_MAX ): +======= + if (int((prop.value_range.max_ - prop.value_range.min_) / + prop.value_range.step) + > self._VALUE_RANGE_MODE_COUNT_MAX): +>>>>>>> 83899f8 (fomatted code) _LOGGER.error( 'too many mode values, %s, %s, %s', self.entity_id, prop.name, prop.value_range) @@ -190,8 +210,14 @@ class Light(MIoTServiceEntity, LightEntity): for value in range( prop.value_range.min_, prop.value_range.max_, +<<<<<<< HEAD prop.value_range.step): mode_list[value] = f'mode {value}' +======= + prop.value_range.step, + ): + mode_list[value] = f"mode {value}" +>>>>>>> 83899f8 (fomatted code) if mode_list: self._mode_map = mode_list self._attr_effect_list = list(self._mode_map.values()) @@ -245,9 +271,14 @@ class Light(MIoTServiceEntity, LightEntity): @property def effect(self) -> Optional[str]: """Return the current mode.""" +<<<<<<< HEAD return self.get_map_value( map_=self._mode_map, key=self.get_prop_value(prop=self._prop_mode)) +======= + return self.get_map_value(map_=self._mode_map, + key=self.get_prop_value(prop=self._prop_mode)) +>>>>>>> 83899f8 (fomatted code) async def async_turn_on(self, **kwargs) -> None: """Turn the light on. @@ -285,6 +316,7 @@ class Light(MIoTServiceEntity, LightEntity): # 开始发送开灯命令 if command_send_mode and command_send_mode.state == "Send Together": set_properties_list: List[Dict[str, Any]] = [] +<<<<<<< HEAD # mode if ATTR_EFFECT in kwargs: set_properties_list.append({ @@ -296,6 +328,18 @@ class Light(MIoTServiceEntity, LightEntity): if send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) +======= + if self._prop_on: + value_on = True if self._prop_on.format_ == bool else 1 # noqa: E721 + set_properties_list.append({ + "prop": self._prop_on, + "value": value_on + }) + # brightness + if ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value(self._brightness_scale, + kwargs[ATTR_BRIGHTNESS]) +>>>>>>> 83899f8 (fomatted code) set_properties_list.append({ "prop": self._prop_brightness, "value": brightness @@ -318,6 +362,7 @@ class Light(MIoTServiceEntity, LightEntity): "value": rgb }) self._attr_color_mode = ColorMode.RGB +<<<<<<< HEAD # brightness if not send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( @@ -334,16 +379,33 @@ class Light(MIoTServiceEntity, LightEntity): "value": value_on }) await self.set_properties_async(set_properties_list,write_ha_state=False) +======= + # mode + if ATTR_EFFECT in kwargs: + set_properties_list.append({ + "prop": + self._prop_mode, + "value": + self.get_map_key(map_=self._mode_map, + value=kwargs[ATTR_EFFECT]), + }) + await self.set_properties_async(set_properties_list) +>>>>>>> 83899f8 (fomatted code) self.async_write_ha_state() elif command_send_mode and command_send_mode.state == "Send Turn On First": set_properties_list: List[Dict[str, Any]] = [] if self._prop_on: +<<<<<<< HEAD value_on = True if self._prop_on.format_ == bool else 1 +======= + value_on = True if self._prop_on.format_ == bool else 1 # noqa: E721 +>>>>>>> 83899f8 (fomatted code) set_properties_list.append({ "prop": self._prop_on, "value": value_on }) +<<<<<<< HEAD # mode if ATTR_EFFECT in kwargs: set_properties_list.append({ @@ -357,6 +419,14 @@ class Light(MIoTServiceEntity, LightEntity): if send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) +======= + await self.set_property_async(prop=self._prop_on, + value=value_on) + # brightness + if ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value(self._brightness_scale, + kwargs[ATTR_BRIGHTNESS]) +>>>>>>> 83899f8 (fomatted code) set_properties_list.append({ "prop": self._prop_brightness, "value": brightness @@ -379,6 +449,7 @@ class Light(MIoTServiceEntity, LightEntity): "value": rgb }) self._attr_color_mode = ColorMode.RGB +<<<<<<< HEAD # brightness if not send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( @@ -389,10 +460,23 @@ class Light(MIoTServiceEntity, LightEntity): }) await self.set_properties_async(set_properties_list,write_ha_state=False) +======= + # mode + if ATTR_EFFECT in kwargs: + set_properties_list.append({ + "prop": + self._prop_mode, + "value": + self.get_map_key(map_=self._mode_map, + value=kwargs[ATTR_EFFECT]), + }) + await self.set_properties_async(set_properties_list) +>>>>>>> 83899f8 (fomatted code) self.async_write_ha_state() else: if self._prop_on: +<<<<<<< HEAD value_on = True if self._prop_on.format_ == bool else 1 await self.set_property_async( prop=self._prop_on, value=value_on) @@ -403,6 +487,18 @@ class Light(MIoTServiceEntity, LightEntity): await self.set_property_async( prop=self._prop_brightness, value=brightness, write_ha_state=False) +======= + value_on = True if self._prop_on.format_ == bool else 1 # noqa: E721 + await self.set_property_async(prop=self._prop_on, + value=value_on) + # brightness + if ATTR_BRIGHTNESS in kwargs: + brightness = brightness_to_value(self._brightness_scale, + kwargs[ATTR_BRIGHTNESS]) + await self.set_property_async(prop=self._prop_brightness, + value=brightness, + write_ha_state=False) +>>>>>>> 83899f8 (fomatted code) # color-temperature if ATTR_COLOR_TEMP_KELVIN in kwargs: await self.set_property_async( @@ -416,17 +512,30 @@ class Light(MIoTServiceEntity, LightEntity): g = kwargs[ATTR_RGB_COLOR][1] b = kwargs[ATTR_RGB_COLOR][2] rgb = (r << 16) | (g << 8) | b +<<<<<<< HEAD await self.set_property_async( prop=self._prop_color, value=rgb, write_ha_state=False) +======= + await self.set_property_async(prop=self._prop_color, + value=rgb, + write_ha_state=False) +>>>>>>> 83899f8 (fomatted code) self._attr_color_mode = ColorMode.RGB # mode if ATTR_EFFECT in kwargs: await self.set_property_async( prop=self._prop_mode, +<<<<<<< HEAD value=self.get_map_key( map_=self._mode_map, value=kwargs[ATTR_EFFECT]), write_ha_state=False) +======= + value=self.get_map_key(map_=self._mode_map, + value=kwargs[ATTR_EFFECT]), + write_ha_state=False, + ) +>>>>>>> 83899f8 (fomatted code) self.async_write_ha_state() async def async_turn_off(self, **kwargs) -> None: diff --git a/custom_components/xiaomi_home/miot/miot_client.py b/custom_components/xiaomi_home/miot/miot_client.py index 194b7e3..01f89eb 100644 --- a/custom_components/xiaomi_home/miot/miot_client.py +++ b/custom_components/xiaomi_home/miot/miot_client.py @@ -205,10 +205,17 @@ class MIoTClient: raise MIoTClientError('invalid mips service') self._entry_id = entry_id self._entry_data = entry_data +<<<<<<< HEAD self._uid = entry_data['uid'] self._cloud_server = entry_data['cloud_server'] self._ctrl_mode = CtrlMode.load( entry_data.get('ctrl_mode', DEFAULT_CTRL_MODE)) +======= + self._uid = entry_data["uid"] + self._cloud_server = entry_data["cloud_server"] + self._ctrl_mode = CtrlMode.load( + entry_data.get("ctrl_mode", DEFAULT_CTRL_MODE)) +>>>>>>> 83899f8 (fomatted code) self._network = network self._storage = storage self._mips_service = mips_service @@ -245,12 +252,21 @@ class MIoTClient: self._show_devices_changed_notify_timer = None self._display_devs_notify = entry_data.get( +<<<<<<< HEAD 'display_devices_changed_notify', ['add', 'del', 'offline']) self._display_notify_content_hash = None self._display_binary_text = 'text' in entry_data.get( 'display_binary_mode', ['text']) self._display_binary_bool = 'bool' in entry_data.get( 'display_binary_mode', ['text']) +======= + "display_devices_changed_notify", ["add", "del", "offline"]) + self._display_notify_content_hash = None + self._display_binary_text = "text" in entry_data.get( + "display_binary_mode", ["text"]) + self._display_binary_bool = "bool" in entry_data.get( + "display_binary_mode", ["text"]) +>>>>>>> 83899f8 (fomatted code) async def init_async(self) -> None: # Load user config and check @@ -273,9 +289,16 @@ class MIoTClient: _LOGGER.debug('user config, %s', json.dumps(p_user_config)) # MIoT i18n client self._i18n = MIoTI18n( +<<<<<<< HEAD lang=self._entry_data.get( 'integration_language', DEFAULT_INTEGRATION_LANGUAGE), loop=self._main_loop) +======= + lang=self._entry_data.get("integration_language", + DEFAULT_INTEGRATION_LANGUAGE), + loop=self._main_loop, + ) +>>>>>>> 83899f8 (fomatted code) await self._i18n.init_async() # Load cache device list await self.__load_cache_device_async() @@ -293,10 +316,16 @@ class MIoTClient: access_token=self._user_config['auth_info']['access_token'], loop=self._main_loop) # MIoT cert client +<<<<<<< HEAD self._cert = MIoTCert( storage=self._storage, uid=self._uid, cloud_server=self.cloud_server) +======= + self._cert = MIoTCert(storage=self._storage, + uid=self._uid, + cloud_server=self.cloud_server) +>>>>>>> 83899f8 (fomatted code) # MIoT cloud mips client self._mips_cloud = MipsCloudClient( uuid=self._entry_data['uuid'], @@ -310,8 +339,14 @@ class MIoTClient: handler=self.__on_mips_cloud_state_changed) # Subscribe network status self._network.sub_network_status( +<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}', handler=self.__on_network_status_changed) +======= + key=f"{self._uid}-{self._cloud_server}", + handler=self.__on_network_status_changed, + ) +>>>>>>> 83899f8 (fomatted code) await self.__on_network_status_changed( status=self._network.network_status) # Create multi mips local client instance according to the @@ -326,6 +361,7 @@ class MIoTClient: group_id=info['group_id'], handler=self.__on_mips_service_state_change) service_data = self._mips_service.get_services( +<<<<<<< HEAD group_id=info['group_id']).get(info['group_id'], None) if not service_data: _LOGGER.info( @@ -334,6 +370,15 @@ class MIoTClient: _LOGGER.info( 'central mips service scanned, %s, %s', home_id, service_data) +======= + group_id=info["group_id"]).get(info["group_id"], None) + if not service_data: + _LOGGER.info("central mips service not scanned, %s", + home_id) + continue + _LOGGER.info("central mips service scanned, %s, %s", + home_id, service_data) +>>>>>>> 83899f8 (fomatted code) mips = MipsLocalClient( did=self._entry_data['virtual_did'], group_id=info['group_id'], @@ -348,12 +393,20 @@ class MIoTClient: mips.enable_logger(logger=_LOGGER) mips.on_dev_list_changed = self.__on_gw_device_list_changed mips.sub_mips_state( +<<<<<<< HEAD key=info['group_id'], +======= + key=info["group_id"], +>>>>>>> 83899f8 (fomatted code) handler=self.__on_mips_local_state_changed) mips.connect() # Lan ctrl await self._miot_lan.vote_for_lan_ctrl_async( +<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}', vote=True) +======= + key=f"{self._uid}-{self._cloud_server}", vote=True) +>>>>>>> 83899f8 (fomatted code) self._miot_lan.sub_lan_state( key=f'{self._uid}-{self._cloud_server}', handler=self.__on_miot_lan_state_change) @@ -361,6 +414,7 @@ class MIoTClient: await self.__on_miot_lan_state_change(True) else: self._miot_lan.unsub_lan_state( +<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') if self._miot_lan.init_done: self._miot_lan.unsub_device_state( @@ -369,12 +423,26 @@ class MIoTClient: devices=list(self._device_list_cache.keys())) await self._miot_lan.vote_for_lan_ctrl_async( key=f'{self._uid}-{self._cloud_server}', vote=False) +======= + key=f"{self._uid}-{self._cloud_server}") + if self._miot_lan.init_done: + self._miot_lan.unsub_device_state( + key=f"{self._uid}-{self._cloud_server}") + self._miot_lan.delete_devices( + devices=list(self._device_list_cache.keys())) + await self._miot_lan.vote_for_lan_ctrl_async( + key=f"{self._uid}-{self._cloud_server}", vote=False) +>>>>>>> 83899f8 (fomatted code) _LOGGER.info('init_async, %s, %s', self._uid, self._cloud_server) async def deinit_async(self) -> None: self._network.unsub_network_status( +<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') +======= + key=f"{self._uid}-{self._cloud_server}") +>>>>>>> 83899f8 (fomatted code) # Cancel refresh props if self._refresh_props_timer: self._refresh_props_timer.cancel() @@ -383,7 +451,11 @@ class MIoTClient: self._refresh_props_retry_count = 0 # Cloud mips self._mips_cloud.unsub_mips_state( +<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') +======= + key=f"{self._uid}-{self._cloud_server}") +>>>>>>> 83899f8 (fomatted code) self._mips_cloud.deinit() # Cancel refresh cloud devices if self._refresh_cloud_devices_timer: @@ -393,12 +465,17 @@ class MIoTClient: # Central hub gateway mips if self._cloud_server in SUPPORT_CENTRAL_GATEWAY_CTRL: self._mips_service.unsub_service_change( +<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') +======= + key=f"{self._uid}-{self._cloud_server}") +>>>>>>> 83899f8 (fomatted code) for mips in self._mips_local.values(): mips.on_dev_list_changed = None mips.unsub_mips_state(key=mips.group_id) mips.deinit() if self._mips_local_state_changed_timers: +<<<<<<< HEAD for timer_item in ( self._mips_local_state_changed_timers.values()): timer_item.cancel() @@ -412,6 +489,21 @@ class MIoTClient: devices=list(self._device_list_cache.keys())) await self._miot_lan.vote_for_lan_ctrl_async( key=f'{self._uid}-{self._cloud_server}', vote=False) +======= + for timer_item in self._mips_local_state_changed_timers.values( + ): + timer_item.cancel() + self._mips_local_state_changed_timers.clear() + self._miot_lan.unsub_lan_state( + key=f"{self._uid}-{self._cloud_server}") + if self._miot_lan.init_done: + self._miot_lan.unsub_device_state( + key=f"{self._uid}-{self._cloud_server}") + self._miot_lan.delete_devices( + devices=list(self._device_list_cache.keys())) + await self._miot_lan.vote_for_lan_ctrl_async( + key=f"{self._uid}-{self._cloud_server}", vote=False) +>>>>>>> 83899f8 (fomatted code) # Cancel refresh auth info if self._refresh_token_timer: self._refresh_token_timer.cancel() @@ -426,6 +518,7 @@ class MIoTClient: await self._oauth.deinit_async() await self._http.deinit_async() # Remove notify +<<<<<<< HEAD self._persistence_notify( self.__gen_notify_key('dev_list_changed'), None, None) self.__show_client_error_notify( @@ -436,6 +529,14 @@ class MIoTClient: message=None, notify_key='device_cache') self.__show_client_error_notify( message=None, notify_key='device_cloud') +======= + self._persistence_notify(self.__gen_notify_key("dev_list_changed"), + None, None) + self.__show_client_error_notify(message=None, notify_key="oauth_info") + self.__show_client_error_notify(message=None, notify_key="user_cert") + self.__show_client_error_notify(message=None, notify_key="device_cache") + self.__show_client_error_notify(message=None, notify_key="device_cloud") +>>>>>>> 83899f8 (fomatted code) _LOGGER.info('deinit_async, %s', self._uid) @@ -517,8 +618,13 @@ class MIoTClient: if value: self.__request_show_devices_changed_notify() else: +<<<<<<< HEAD self._persistence_notify( self.__gen_notify_key('dev_list_changed'), None, None) +======= + self._persistence_notify(self.__gen_notify_key("dev_list_changed"), + None, None) +>>>>>>> 83899f8 (fomatted code) @property def device_list(self) -> dict: @@ -538,6 +644,7 @@ class MIoTClient: # Load auth info auth_info: Optional[dict] = None user_config: dict = await self._storage.load_user_config_async( +<<<<<<< HEAD uid=self._uid, cloud_server=self._cloud_server, keys=['auth_info']) if ( @@ -551,10 +658,23 @@ class MIoTClient: or 'refresh_token' not in auth_info ): raise MIoTClientError('invalid auth info') +======= + uid=self._uid, + cloud_server=self._cloud_server, + keys=["auth_info"]) + if (not user_config or + (auth_info := user_config.get("auth_info", None)) is None): + raise MIoTClientError("load_user_config_async error") + if ("expires_ts" not in auth_info or + "access_token" not in auth_info or + "refresh_token" not in auth_info): + raise MIoTClientError("invalid auth info") +>>>>>>> 83899f8 (fomatted code) # Determine whether to update token refresh_time = int(auth_info['expires_ts'] - time.time()) if refresh_time <= 60: valid_auth_info = await self._oauth.refresh_access_token_async( +<<<<<<< HEAD refresh_token=auth_info['refresh_token']) auth_info = valid_auth_info # Update http token @@ -572,6 +692,26 @@ class MIoTClient: 'refresh oauth info, get new access_token, %s', auth_info) refresh_time = int(auth_info['expires_ts'] - time.time()) +======= + refresh_token=auth_info["refresh_token"]) + auth_info = valid_auth_info + # Update http token + self._http.update_http_header( + access_token=valid_auth_info["access_token"]) + # Update mips cloud token + self._mips_cloud.update_access_token( + access_token=valid_auth_info["access_token"]) + # Update storage + if not await self._storage.update_user_config_async( + uid=self._uid, + cloud_server=self._cloud_server, + config={"auth_info": auth_info}, + ): + raise MIoTClientError("update_user_config_async error") + _LOGGER.info("refresh oauth info, get new access_token, %s", + auth_info) + refresh_time = int(auth_info["expires_ts"] - time.time()) +>>>>>>> 83899f8 (fomatted code) if refresh_time <= 0: raise MIoTClientError('invalid expires time') self.__show_client_error_notify(None, 'oauth_info') @@ -584,8 +724,14 @@ class MIoTClient: except Exception as err: self.__show_client_error_notify( message=self._i18n.translate( +<<<<<<< HEAD 'miot.client.invalid_oauth_info'), # type: ignore notify_key='oauth_info') +======= + "miot.client.invalid_oauth_info"), # type: ignore + notify_key="oauth_info", + ) +>>>>>>> 83899f8 (fomatted code) _LOGGER.error( 'refresh oauth info error (%s, %s), %s, %s', self._uid, self._cloud_server, err, traceback.format_exc()) @@ -596,10 +742,16 @@ class MIoTClient: if self._cloud_server not in SUPPORT_CENTRAL_GATEWAY_CTRL: return True if not await self._cert.verify_ca_cert_async(): +<<<<<<< HEAD raise MIoTClientError('ca cert is not ready') refresh_time = ( await self._cert.user_cert_remaining_time_async() - MIHOME_CERT_EXPIRE_MARGIN) +======= + raise MIoTClientError("ca cert is not ready") + refresh_time = (await self._cert.user_cert_remaining_time_async() - + MIHOME_CERT_EXPIRE_MARGIN) +>>>>>>> 83899f8 (fomatted code) if refresh_time <= 60: user_key = await self._cert.load_user_key_async() if not user_key: @@ -607,7 +759,11 @@ class MIoTClient: if not await self._cert.update_user_key_async(key=user_key): raise MIoTClientError('update_user_key_async failed') csr_str = self._cert.gen_user_csr( +<<<<<<< HEAD user_key=user_key, did=self._entry_data['virtual_did']) +======= + user_key=user_key, did=self._entry_data["virtual_did"]) +>>>>>>> 83899f8 (fomatted code) crt_str = await self.miot_http.get_central_cert_async(csr_str) if not await self._cert.update_user_cert_async(cert=crt_str): raise MIoTClientError('update user cert error') @@ -628,6 +784,7 @@ class MIoTClient: except MIoTClientError as error: self.__show_client_error_notify( message=self._i18n.translate( +<<<<<<< HEAD 'miot.client.invalid_cert_info'), # type: ignore notify_key='user_cert') _LOGGER.error( @@ -638,12 +795,24 @@ class MIoTClient: async def set_prop_async( self, did: str, siid: int, piid: int, value: Any ) -> bool: +======= + "miot.client.invalid_cert_info"), # type: ignore + notify_key="user_cert", + ) + _LOGGER.error("refresh user cert error, %s, %s", error, + traceback.format_exc()) + return False + + async def set_prop_async(self, did: str, siid: int, piid: int, + value: Any) -> bool: +>>>>>>> 83899f8 (fomatted code) if did not in self._device_list_cache: raise MIoTClientError(f'did not exist, {did}') # Priority local control if self._ctrl_mode == CtrlMode.AUTO: # Gateway control device_gw = self._device_list_gateway.get(did, None) +<<<<<<< HEAD if ( device_gw and device_gw.get('online', False) and device_gw.get('specv2_access', False) @@ -662,12 +831,30 @@ class MIoTClient: did, siid, piid, value, result) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +======= + if (device_gw and device_gw.get("online", False) and + device_gw.get("specv2_access", False) and + "group_id" in device_gw): + mips = self._mips_local.get(device_gw["group_id"], None) + if mips is None: + _LOGGER.error("no gw route, %s, try control throw cloud", + device_gw) + else: + result = await mips.set_prop_async(did=did, + siid=siid, + piid=piid, + value=value) + rc = (result or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +>>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return True raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) # Lan control device_lan = self._device_list_lan.get(did, None) +<<<<<<< HEAD if device_lan and device_lan.get('online', False): result = await self._miot_lan.set_prop_async( did=did, siid=siid, piid=piid, value=value) @@ -676,6 +863,18 @@ class MIoTClient: did, siid, piid, value, result) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +======= + if device_lan and device_lan.get("online", False): + result = await self._miot_lan.set_prop_async(did=did, + siid=siid, + piid=piid, + value=value) + _LOGGER.debug("lan set prop, %s.%d.%d, %s -> %s", did, siid, + piid, value, result) + rc = (result or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +>>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return True raise MIoTClientError( @@ -683,23 +882,39 @@ class MIoTClient: # Cloud control device_cloud = self._device_list_cloud.get(did, None) +<<<<<<< HEAD if device_cloud and device_cloud.get('online', False): result = await self._http.set_prop_async( params=[ {'did': did, 'siid': siid, 'piid': piid, 'value': value} ]) +======= + if device_cloud and device_cloud.get("online", False): + result = await self._http.set_prop_async(params=[{ + "did": did, + "siid": siid, + "piid": piid, + "value": value + }]) +>>>>>>> 83899f8 (fomatted code) _LOGGER.debug( 'cloud set prop, %s.%d.%d, %s -> %s', did, siid, piid, value, result) if result and len(result) == 1: +<<<<<<< HEAD rc = result[0].get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +======= + rc = result[0].get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +>>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return True if rc in [-704010000, -704042011]: # Device remove or offline _LOGGER.error('device may be removed or offline, %s', did) self._main_loop.create_task( +<<<<<<< HEAD await self.__refresh_cloud_device_with_dids_async( dids=[did])) raise MIoTClientError( @@ -709,6 +924,16 @@ class MIoTClient: raise MIoTClientError( f'{self._i18n.translate("miot.client.device_exec_error")}, ' f'{self._i18n.translate("error.common.-10007")}') +======= + await + self.__refresh_cloud_device_with_dids_async(dids=[did])) + raise MIoTClientError(self.__get_exec_error_with_rc(rc=rc)) + + # Show error message + raise MIoTClientError( + f"{self._i18n.translate('miot.client.device_exec_error')}, " + f"{self._i18n.translate('error.common.-10007')}") +>>>>>>> 83899f8 (fomatted code) async def set_props_async( self, props_list: List[Dict[str, Any]], @@ -726,6 +951,7 @@ class MIoTClient: if self._ctrl_mode == CtrlMode.AUTO: # Gateway control device_gw = self._device_list_gateway.get(did, None) +<<<<<<< HEAD if ( device_gw and device_gw.get("online", False) and device_gw.get("specv2_access", False) and "group_id" in device_gw @@ -742,25 +968,57 @@ class MIoTClient: rc = [(r or {}).get("code", MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) for r in result] +======= + if (device_gw and device_gw.get("online", False) and + device_gw.get("specv2_access", False) and + "group_id" in device_gw): + mips = self._mips_local.get(device_gw["group_id"], None) + if mips is None: + _LOGGER.error("no gw route, %s, try control throw cloud", + device_gw) + else: + result = await mips.set_props_async(did=did, + props_list=props_list) + rc = {(r or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) + for r in result} +>>>>>>> 83899f8 (fomatted code) if all(t in [0, 1] for t in rc): return True else: raise MIoTClientError( +<<<<<<< HEAD self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) +======= + self.__get_exec_error_with_rc(rc=(rc - {0, 1})[0])) +>>>>>>> 83899f8 (fomatted code) # Lan control device_lan = self._device_list_lan.get(did, None) if device_lan and device_lan.get("online", False): result = await self._miot_lan.set_props_async( did=did, props_list=props_list) +<<<<<<< HEAD _LOGGER.debug("lan set props, %s -> %s", props_list, result) rc = [(r or {}).get("code", MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) for r in result] +======= + _LOGGER.debug("lan set prop, %s -> %s", props_list, result) + rc = {(r or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) + for r in result} +>>>>>>> 83899f8 (fomatted code) if all(t in [0, 1] for t in rc): return True else: raise MIoTClientError( +<<<<<<< HEAD self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) +======= + self.__get_exec_error_with_rc(rc=(rc - {0, 1})[0])) +>>>>>>> 83899f8 (fomatted code) # Cloud control device_cloud = self._device_list_cloud.get(did, None) if device_cloud and device_cloud.get("online", False): @@ -769,9 +1027,16 @@ class MIoTClient: "cloud set props, %s, result, %s", props_list, result) if result and len(result) == len(props_list): +<<<<<<< HEAD rc = [(r or {}).get("code", MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) for r in result] +======= + rc = {(r or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) + for r in result} +>>>>>>> 83899f8 (fomatted code) if all(t in [0, 1] for t in rc): return True if any(t in [-704010000, -704042011] for t in rc): @@ -780,6 +1045,7 @@ class MIoTClient: self._main_loop.create_task( await self.__refresh_cloud_device_with_dids_async(dids=[did])) +<<<<<<< HEAD raise MIoTClientError( self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) @@ -787,6 +1053,16 @@ class MIoTClient: raise MIoTClientError( f'{self._i18n.translate("miot.client.device_exec_error")}, ' f'{self._i18n.translate("error.common.-10007")}') +======= + else: + raise MIoTClientError( + self.__get_exec_error_with_rc(rc=(rc - {0, 1})[0])) + + # Show error message + raise MIoTClientError( + f"{self._i18n.translate('miot.client.device_exec_error')}, " + f"{self._i18n.translate('error.common.-10007')}") +>>>>>>> 83899f8 (fomatted code) def request_refresh_prop( self, did: str, siid: int, piid: int @@ -801,8 +1077,13 @@ class MIoTClient: if self._refresh_props_timer: return self._refresh_props_timer = self._main_loop.call_later( +<<<<<<< HEAD REFRESH_PROPS_DELAY, lambda: self._main_loop.create_task( self.__refresh_props_handler())) +======= + 0.2, + lambda: self._main_loop.create_task(self.__refresh_props_handler())) +>>>>>>> 83899f8 (fomatted code) async def get_prop_async(self, did: str, siid: int, piid: int) -> Any: if did not in self._device_list_cache: @@ -813,12 +1094,19 @@ class MIoTClient: # so obtaining the cache from the cloud is the priority here. try: if self._network.network_status: +<<<<<<< HEAD result = await self._http.get_prop_async( did=did, siid=siid, piid=piid) +======= + result = await self._http.get_prop_async(did=did, + siid=siid, + piid=piid) +>>>>>>> 83899f8 (fomatted code) if result: return result except Exception as err: # pylint: disable=broad-exception-caught # Catch all exceptions +<<<<<<< HEAD _LOGGER.error( 'client get prop from cloud error, %s, %s', err, traceback.format_exc()) @@ -831,9 +1119,21 @@ class MIoTClient: and 'group_id' in device_gw ): mips = self._mips_local.get(device_gw['group_id'], None) +======= + _LOGGER.error("client get prop from cloud error, %s, %s", err, + traceback.format_exc()) + if self._ctrl_mode == CtrlMode.AUTO: + # Central hub gateway + device_gw = self._device_list_gateway.get(did, None) + if (device_gw and device_gw.get("online", False) and + device_gw.get("specv2_access", False) and + "group_id" in device_gw): + mips = self._mips_local.get(device_gw["group_id"], None) +>>>>>>> 83899f8 (fomatted code) if mips is None: _LOGGER.error('no gw route, %s', device_gw) else: +<<<<<<< HEAD return await mips.get_prop_async( did=did, siid=siid, piid=piid) # Lan @@ -841,19 +1141,36 @@ class MIoTClient: if device_lan and device_lan.get('online', False): return await self._miot_lan.get_prop_async( did=did, siid=siid, piid=piid) +======= + return await mips.get_prop_async(did=did, + siid=siid, + piid=piid) + # Lan + device_lan = self._device_list_lan.get(did, None) + if device_lan and device_lan.get("online", False): + return await self._miot_lan.get_prop_async(did=did, + siid=siid, + piid=piid) +>>>>>>> 83899f8 (fomatted code) # _LOGGER.error( # 'client get prop failed, no-link, %s.%d.%d', did, siid, piid) return None +<<<<<<< HEAD async def action_async( self, did: str, siid: int, aiid: int, in_list: list ) -> list: +======= + async def action_async(self, did: str, siid: int, aiid: int, + in_list: list) -> list: +>>>>>>> 83899f8 (fomatted code) if did not in self._device_list_cache: raise MIoTClientError(f'did not exist, {did}') device_gw = self._device_list_gateway.get(did, None) # Priority local control if self._ctrl_mode == CtrlMode.AUTO: +<<<<<<< HEAD if ( device_gw and device_gw.get('online', False) and device_gw.get('specv2_access', False) @@ -861,19 +1178,36 @@ class MIoTClient: ): mips = self._mips_local.get( device_gw['group_id'], None) +======= + if (device_gw and device_gw.get("online", False) and + device_gw.get("specv2_access", False) and + "group_id" in device_gw): + mips = self._mips_local.get(device_gw["group_id"], None) +>>>>>>> 83899f8 (fomatted code) if mips is None: _LOGGER.error('no gw route, %s', device_gw) else: +<<<<<<< HEAD result = await mips.action_async( did=did, siid=siid, aiid=aiid, in_list=in_list) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +======= + result = await mips.action_async(did=did, + siid=siid, + aiid=aiid, + in_list=in_list) + rc = (result or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +>>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return result.get('out', []) raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) # Lan control device_lan = self._device_list_lan.get(did, None) +<<<<<<< HEAD if device_lan and device_lan.get('online', False): result = await self._miot_lan.action_async( did=did, siid=siid, aiid=aiid, in_list=in_list) @@ -881,28 +1215,57 @@ class MIoTClient: 'lan action, %s, %s, %s -> %s', did, siid, aiid, result) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +======= + if device_lan and device_lan.get("online", False): + result = await self._miot_lan.action_async(did=did, + siid=siid, + aiid=aiid, + in_list=in_list) + _LOGGER.debug("lan action, %s, %s, %s -> %s", did, siid, aiid, + result) + rc = (result or + {}).get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +>>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return result.get('out', []) raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) # Cloud control device_cloud = self._device_list_cloud.get(did, None) +<<<<<<< HEAD if device_cloud and device_cloud.get('online', False): result: dict = await self._http.action_async( did=did, siid=siid, aiid=aiid, in_list=in_list) if result: rc = result.get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +======= + if device_cloud and device_cloud.get("online", False): + result: dict = await self._http.action_async(did=did, + siid=siid, + aiid=aiid, + in_list=in_list) + if result: + rc = result.get("code", + MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) +>>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return result.get('out', []) if rc in [-704010000, -704042011]: # Device remove or offline _LOGGER.error('device removed or offline, %s', did) self._main_loop.create_task( +<<<<<<< HEAD await self.__refresh_cloud_device_with_dids_async( dids=[did])) raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) +======= + await + self.__refresh_cloud_device_with_dids_async(dids=[did])) + raise MIoTClientError(self.__get_exec_error_with_rc(rc=rc)) +>>>>>>> 83899f8 (fomatted code) # TODO: Show error message _LOGGER.error( 'client action failed, %s.%d.%d', did, siid, aiid) @@ -916,6 +1279,7 @@ class MIoTClient: if did not in self._device_list_cache: raise MIoTClientError(f'did not exist, {did}') +<<<<<<< HEAD topic = ( f'{did}/p/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') @@ -930,6 +1294,20 @@ class MIoTClient: topic = ( f'{did}/p/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') +======= + topic = f"{did}/p/{'#' if siid is None or piid is None else f'{siid}/{piid}'}" + self._sub_tree[topic] = MIoTClientSub(topic=topic, + handler=handler, + handler_ctx=handler_ctx) + _LOGGER.debug("client sub prop, %s", topic) + return True + + def unsub_prop(self, + did: str, + siid: Optional[int] = None, + piid: Optional[int] = None) -> bool: + topic = f"{did}/p/{'#' if siid is None or piid is None else f'{siid}/{piid}'}" +>>>>>>> 83899f8 (fomatted code) if self._sub_tree.get(topic=topic): del self._sub_tree[topic] _LOGGER.debug('client unsub prop, %s', topic) @@ -941,6 +1319,7 @@ class MIoTClient: handler_ctx: Any = None ) -> bool: if did not in self._device_list_cache: +<<<<<<< HEAD raise MIoTClientError(f'did not exist, {did}') topic = ( f'{did}/e/' @@ -956,6 +1335,21 @@ class MIoTClient: topic = ( f'{did}/e/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') +======= + raise MIoTClientError(f"did not exist, {did}") + topic = f"{did}/e/{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}" + self._sub_tree[topic] = MIoTClientSub(topic=topic, + handler=handler, + handler_ctx=handler_ctx) + _LOGGER.debug("client sub event, %s", topic) + return True + + def unsub_event(self, + did: str, + siid: Optional[int] = None, + eiid: Optional[int] = None) -> bool: + topic = f"{did}/e/{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}" +>>>>>>> 83899f8 (fomatted code) if self._sub_tree.get(topic=topic): del self._sub_tree[topic] _LOGGER.debug('client unsub event, %s', topic) @@ -967,10 +1361,18 @@ class MIoTClient: ) -> bool: """Call callback handler in main loop""" if did not in self._device_list_cache: +<<<<<<< HEAD raise MIoTClientError(f'did not exist, {did}') self._sub_device_state[did] = MipsDeviceState( did=did, handler=handler, handler_ctx=handler_ctx) _LOGGER.debug('client sub device state, %s', did) +======= + raise MIoTClientError(f"did not exist, {did}") + self._sub_device_state[did] = MipsDeviceState(did=did, + handler=handler, + handler_ctx=handler_ctx) + _LOGGER.debug("client sub device state, %s", did) +>>>>>>> 83899f8 (fomatted code) return True def unsub_device_state(self, did: str) -> bool: @@ -1002,13 +1404,22 @@ class MIoTClient: def __get_exec_error_with_rc(self, rc: int) -> str: err_msg: str = self._i18n.translate( +<<<<<<< HEAD key=f'error.common.{rc}') # type: ignore +======= + key=f"error.common.{rc}") # type: ignore +>>>>>>> 83899f8 (fomatted code) if not err_msg: err_msg = f'{self._i18n.translate(key="error.common.-10000")}, ' err_msg += f'code={rc}' return ( +<<<<<<< HEAD f'{self._i18n.translate(key="miot.client.device_exec_error")}, ' + err_msg) +======= + f"{self._i18n.translate(key='miot.client.device_exec_error')}, " + + err_msg) +>>>>>>> 83899f8 (fomatted code) @final def __gen_notify_key(self, name: str) -> str: @@ -1020,8 +1431,15 @@ class MIoTClient: self._refresh_token_timer.cancel() self._refresh_token_timer = None self._refresh_token_timer = self._main_loop.call_later( +<<<<<<< HEAD delay_sec, lambda: self._main_loop.create_task( self.refresh_oauth_info_async())) +======= + delay_sec, + lambda: self._main_loop.create_task(self.refresh_oauth_info_async() + ), + ) +>>>>>>> 83899f8 (fomatted code) @final def __request_refresh_user_cert(self, delay_sec: int) -> None: @@ -1072,6 +1490,7 @@ class MIoTClient: from_old: Optional[str] = self._sub_source_list.get(did, None) from_new: Optional[str] = None if self._ctrl_mode == CtrlMode.AUTO: +<<<<<<< HEAD if ( did in self._device_list_gateway and self._device_list_gateway[did].get('online', False) @@ -1092,6 +1511,22 @@ class MIoTClient: ): from_new = 'cloud' if (from_new == from_old) and (from_new=='cloud' or from_new=='lan'): +======= + if (did in self._device_list_gateway and + self._device_list_gateway[did].get("online", False) and + self._device_list_gateway[did].get("push_available", + False)): + from_new = self._device_list_gateway[did]["group_id"] + elif (did in self._device_list_lan and + self._device_list_lan[did].get("online", False) and + self._device_list_lan[did].get("push_available", False)): + from_new = "lan" + + if (from_new is None and did in self._device_list_cloud and + self._device_list_cloud[did].get("online", False)): + from_new = "cloud" + if from_new == from_old: +>>>>>>> 83899f8 (fomatted code) # No need to update return # Unsub old @@ -1100,8 +1535,13 @@ class MIoTClient: # Sub new self.__sub_from(from_new, did) self._sub_source_list[did] = from_new +<<<<<<< HEAD _LOGGER.info( 'device sub changed, %s, from %s to %s', did, from_old, from_new) +======= + _LOGGER.info("device sub changed, %s, from %s to %s", did, from_old, + from_new) +>>>>>>> 83899f8 (fomatted code) @final async def __on_network_status_changed(self, status: bool) -> None: @@ -1124,6 +1564,7 @@ class MIoTClient: self._mips_cloud.disconnect() @final +<<<<<<< HEAD async def __on_mips_service_state_change( self, group_id: str, state: MipsServiceState, data: dict ) -> None: @@ -1141,6 +1582,23 @@ class MIoTClient: and mips.host == data['addresses'][0] and mips.port == data['port'] ): +======= + async def __on_mips_service_state_change(self, group_id: str, + state: MipsServiceState, + data: dict) -> None: + _LOGGER.info("mips service state changed, %s, %s, %s", group_id, state, + data) + + mips = self._mips_local.get(group_id, None) + if mips: + if state == MipsServiceState.REMOVED: + mips.disconnect() + self._mips_local.pop(group_id, None) + return + if (mips.client_id == self._entry_data["virtual_did"] and + mips.host == data["addresses"][0] and + mips.port == data["port"]): +>>>>>>> 83899f8 (fomatted code) return mips.disconnect() self._mips_local.pop(group_id, None) @@ -1161,6 +1619,7 @@ class MIoTClient: self._mips_local[group_id] = mips mips.enable_logger(logger=_LOGGER) mips.on_dev_list_changed = self.__on_gw_device_list_changed +<<<<<<< HEAD mips.sub_mips_state( key=group_id, handler=self.__on_mips_local_state_changed) mips.connect() @@ -1170,6 +1629,16 @@ class MIoTClient: self, key: str, state: bool ) -> None: _LOGGER.info('cloud mips state changed, %s, %s', key, state) +======= + mips.sub_mips_state(key=group_id, + handler=self.__on_mips_local_state_changed) + mips.connect() + + @final + async def __on_mips_cloud_state_changed(self, key: str, + state: bool) -> None: + _LOGGER.info("cloud mips state changed, %s, %s", key, state) +>>>>>>> 83899f8 (fomatted code) if state: # Connect self.__request_refresh_cloud_devices(immediately=True) @@ -1189,7 +1658,11 @@ class MIoTClient: continue self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache[did].get( +<<<<<<< HEAD 'online', None) +======= + "online", None) +>>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( False, self._device_list_gateway.get( @@ -1204,6 +1677,7 @@ class MIoTClient: self.__request_show_devices_changed_notify() @final +<<<<<<< HEAD async def __on_mips_local_state_changed( self, group_id: str, state: bool ) -> None: @@ -1214,6 +1688,15 @@ class MIoTClient: 'local mips state changed, mips not exist, %s', group_id) # The connection to the central hub gateway is definitely broken. self.__show_central_state_changed_notify(False) +======= + async def __on_mips_local_state_changed(self, group_id: str, + state: bool) -> None: + _LOGGER.info("local mips state changed, %s, %s", group_id, state) + mips = self._mips_local.get(group_id, None) + if not mips: + _LOGGER.error("local mips state changed, mips not exist, %s", + group_id) +>>>>>>> 83899f8 (fomatted code) return if state: # Connected @@ -1235,7 +1718,11 @@ class MIoTClient: continue self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache.get( +<<<<<<< HEAD did, {}).get('online', None) +======= + did, {}).get("online", None) +>>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), False, @@ -1251,6 +1738,7 @@ class MIoTClient: @final async def __on_miot_lan_state_change(self, state: bool) -> None: +<<<<<<< HEAD _LOGGER.info( 'miot lan state changed, %s, %s, %s', self._uid, self._cloud_server, state) @@ -1273,6 +1761,33 @@ class MIoTClient: if 'token' in info and 'connect_type' in info and info['connect_type'] in [0, 8, 12, 23] }) +======= + _LOGGER.info("miot lan state changed, %s, %s, %s", self._uid, + self._cloud_server, state) + if state: + # Update device + self._miot_lan.sub_device_state( + key=f"{self._uid}-{self._cloud_server}", + handler=self.__on_lan_device_state_changed, + ) + for did, info in (await + self._miot_lan.get_dev_list_async()).items(): + await self.__on_lan_device_state_changed(did=did, + state=info, + ctx=None) + _LOGGER.info("lan device list, %s", self._device_list_lan) + self._miot_lan.update_devices( + devices={ + did: { + "token": info["token"], + "model": info["model"], + "connect_type": info["connect_type"], + } + for did, info in self._device_list_cache.items() + if "token" in info and "connect_type" in info and + info["connect_type"] in [0, 8, 12, 23] + }) +>>>>>>> 83899f8 (fomatted code) else: for did, info in self._device_list_lan.items(): if not info.get('online', False): @@ -1282,7 +1797,11 @@ class MIoTClient: info['push_available'] = False self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache.get( +<<<<<<< HEAD did, {}).get('online', None) +======= + did, {}).get("online", None) +>>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), self._device_list_gateway.get( @@ -1298,10 +1817,16 @@ class MIoTClient: self.__request_show_devices_changed_notify() @final +<<<<<<< HEAD def __on_cloud_device_state_changed( self, did: str, state: MIoTDeviceState, ctx: Any ) -> None: _LOGGER.info('cloud device state changed, %s, %s', did, state) +======= + def __on_cloud_device_state_changed(self, did: str, state: MIoTDeviceState, + ctx: Any) -> None: + _LOGGER.info("cloud device state changed, %s, %s", did, state) +>>>>>>> 83899f8 (fomatted code) cloud_device = self._device_list_cloud.get(did, None) if not cloud_device: return @@ -1313,7 +1838,11 @@ class MIoTClient: return self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache[did].get( +<<<<<<< HEAD 'online', None) +======= + "online", None) +>>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( cloud_state_new, self._device_list_gateway.get(did, {}).get('online', False), @@ -1324,6 +1853,7 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( +<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) self.__request_show_devices_changed_notify() @@ -1345,10 +1875,27 @@ class MIoTClient: } gw_list = await mips.get_dev_list_async( payload=json.dumps(payload)) +======= + did, + MIoTDeviceState.ONLINE + if state_new else MIoTDeviceState.OFFLINE, + sub.handler_ctx, + ) + self.__request_show_devices_changed_notify() + + @final + async def __on_gw_device_list_changed(self, mips: MipsLocalClient, + did_list: list[str]) -> None: + _LOGGER.info("gateway devices list changed, %s, %s", mips.group_id, + did_list) + payload: dict = {"filter": {"did": did_list}} + gw_list = await mips.get_dev_list_async(payload=json.dumps(payload)) +>>>>>>> 83899f8 (fomatted code) if gw_list is None: _LOGGER.error('local mips get_dev_list_async failed, %s', did_list) return await self.__update_devices_from_gw_async( +<<<<<<< HEAD gw_list=gw_list, group_id=mips.group_id, filter_dids=[ did for did in did_list if self._device_list_gateway.get(did, {}).get( @@ -1368,6 +1915,28 @@ class MIoTClient: and lan_sub_new == self._device_list_lan[did].get( 'push_available', False) ): +======= + gw_list=gw_list, + group_id=mips.group_id, + filter_dids=[ + did for did in did_list if self._device_list_gateway.get( + did, {}).get("group_id", None) == mips.group_id + ], + ) + self.__request_show_devices_changed_notify() + + @final + async def __on_lan_device_state_changed(self, did: str, state: dict, + ctx: Any) -> None: + _LOGGER.info("lan device state changed, %s, %s", did, state) + lan_state_new: bool = state.get("online", False) + lan_sub_new: bool = state.get("push_available", False) + self._device_list_lan.setdefault(did, {}) + if lan_state_new == self._device_list_lan[did].get( + "online", + False) and lan_sub_new == self._device_list_lan[did].get( + "push_available", False): +>>>>>>> 83899f8 (fomatted code) return self._device_list_lan[did]['online'] = lan_state_new self._device_list_lan[did]['push_available'] = lan_sub_new @@ -1377,7 +1946,11 @@ class MIoTClient: if lan_state_new == self._device_list_cache[did].get('online', False): return state_old: Optional[bool] = self._device_list_cache[did].get( +<<<<<<< HEAD 'online', None) +======= + "online", None) +>>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), self._device_list_gateway.get(did, {}).get('online', False), @@ -1388,8 +1961,16 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( +<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) +======= + did, + MIoTDeviceState.ONLINE + if state_new else MIoTDeviceState.OFFLINE, + sub.handler_ctx, + ) +>>>>>>> 83899f8 (fomatted code) self.__request_show_devices_changed_notify() @final @@ -1397,8 +1978,14 @@ class MIoTClient: """params MUST contain did, siid, piid, value""" # BLE device has no online/offline msg try: +<<<<<<< HEAD subs: list[MIoTClientSub] = list(self._sub_tree.iter_match( f'{params["did"]}/p/{params["siid"]}/{params["piid"]}')) +======= + subs: list[MIoTClientSub] = list( + self._sub_tree.iter_match( + f"{params['did']}/p/{params['siid']}/{params['piid']}")) +>>>>>>> 83899f8 (fomatted code) for sub in subs: sub.handler(params, sub.handler_ctx) except Exception as err: # pylint: disable=broad-exception-caught @@ -1407,17 +1994,22 @@ class MIoTClient: @final def __on_event_msg(self, params: dict, ctx: Any) -> None: try: +<<<<<<< HEAD subs: list[MIoTClientSub] = list(self._sub_tree.iter_match( f'{params["did"]}/e/{params["siid"]}/{params["eiid"]}')) +======= + subs: list[MIoTClientSub] = list( + self._sub_tree.iter_match( + f"{params['did']}/e/{params['siid']}/{params['eiid']}")) +>>>>>>> 83899f8 (fomatted code) for sub in subs: sub.handler(params, sub.handler_ctx) except Exception as err: # pylint: disable=broad-exception-caught _LOGGER.error('on event msg error, %s, %s', params, err) @final - def __check_device_state( - self, cloud_state: Optional[bool], gw_state: bool, lan_state: bool - ) -> Optional[bool]: + def __check_device_state(self, cloud_state: Optional[bool], gw_state: bool, + lan_state: bool) -> Optional[bool]: if cloud_state is None and not gw_state and not lan_state: # Device remove return None @@ -1429,17 +2021,32 @@ class MIoTClient: async def __load_cache_device_async(self) -> None: """Load device list from cache.""" cache_list: Optional[dict[str, dict]] = await self._storage.load_async( +<<<<<<< HEAD domain='miot_devices', name=f'{self._uid}_{self._cloud_server}', +======= + domain="miot_devices", + name=f"{self._uid}_{self._cloud_server}", +>>>>>>> 83899f8 (fomatted code) type_=dict) # type: ignore if not cache_list: self.__show_client_error_notify( message=self._i18n.translate( +<<<<<<< HEAD 'miot.client.invalid_device_cache'), # type: ignore notify_key='device_cache') raise MIoTClientError('load device list from cache error') else: self.__show_client_error_notify( message=None, notify_key='device_cache') +======= + "miot.client.invalid_device_cache"), # type: ignore + notify_key="device_cache", + ) + raise MIoTClientError("load device list from cache error") + else: + self.__show_client_error_notify(message=None, + notify_key="device_cache") +>>>>>>> 83899f8 (fomatted code) # Set default online status = False self._device_list_cache = {} for did, info in cache_list.items(): @@ -1451,6 +2058,7 @@ class MIoTClient: self._device_list_cloud = deepcopy(self._device_list_cache) self._device_list_gateway = { did: { +<<<<<<< HEAD 'did': did, 'name': info.get('name', None), 'group_id': info.get('group_id', None), @@ -1463,6 +2071,21 @@ class MIoTClient: self, cloud_list: dict[str, dict], filter_dids: Optional[list[str]] = None ) -> None: +======= + "did": did, + "name": info.get("name", None), + "group_id": info.get("group_id", None), + "online": False, + "push_available": False, + } for did, info in self._device_list_cache.items() + } + + @final + async def __update_devices_from_cloud_async( + self, + cloud_list: dict[str, dict], + filter_dids: Optional[list[str]] = None) -> None: +>>>>>>> 83899f8 (fomatted code) """Update cloud devices. NOTICE: This function will operate the cloud_list """ @@ -1477,9 +2100,15 @@ class MIoTClient: for did, info in self._device_list_cache.items(): if filter_dids and did not in filter_dids: continue +<<<<<<< HEAD state_old: Optional[bool] = info.get('online', None) cloud_state_old: Optional[bool] = self._device_list_cloud.get( did, {}).get('online', None) +======= + state_old: Optional[bool] = info.get("online", None) + cloud_state_old: Optional[bool] = self._device_list_cloud.get( + did, {}).get("online", None) +>>>>>>> 83899f8 (fomatted code) cloud_state_new: Optional[bool] = None device_new = cloud_list.pop(did, None) if device_new: @@ -1509,20 +2138,35 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( +<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) +======= + did, + MIoTDeviceState.ONLINE + if state_new else MIoTDeviceState.OFFLINE, + sub.handler_ctx, + ) +>>>>>>> 83899f8 (fomatted code) # New devices self._device_list_cloud.update(cloud_list) # Update storage if not await self._storage.save_async( +<<<<<<< HEAD domain='miot_devices', name=f'{self._uid}_{self._cloud_server}', data=self._device_list_cache +======= + domain="miot_devices", + name=f"{self._uid}_{self._cloud_server}", + data=self._device_list_cache, +>>>>>>> 83899f8 (fomatted code) ): _LOGGER.error('save device list to cache failed') @final async def __refresh_cloud_devices_async(self) -> None: +<<<<<<< HEAD _LOGGER.debug( 'refresh cloud devices, %s, %s', self._uid, self._cloud_server) if self._refresh_cloud_devices_timer: @@ -1563,18 +2207,57 @@ class MIoTClient: if 'token' in info and 'connect_type' in info and info['connect_type'] in [0, 8, 12, 23] }) +======= + _LOGGER.debug("refresh cloud devices, %s, %s", self._uid, + self._cloud_server) + self._refresh_cloud_devices_timer = None + result = await self._http.get_devices_async( + home_ids=list(self._entry_data.get("home_selected", {}).keys())) + if not result and "devices" not in result: + self.__show_client_error_notify( + message=self._i18n.translate( + "miot.client.device_cloud_error"), # type: ignore + notify_key="device_cloud", + ) + return + else: + self.__show_client_error_notify(message=None, + notify_key="device_cloud") + cloud_list: dict[str, dict] = result["devices"] + await self.__update_devices_from_cloud_async(cloud_list=cloud_list) + # Update lan device + if self._ctrl_mode == CtrlMode.AUTO and self._miot_lan.init_done: + self._miot_lan.update_devices( + devices={ + did: { + "token": info["token"], + "model": info["model"], + "connect_type": info["connect_type"], + } + for did, info in self._device_list_cache.items() + if "token" in info and "connect_type" in info and + info["connect_type"] in [0, 8, 12, 23] + }) +>>>>>>> 83899f8 (fomatted code) self.__request_show_devices_changed_notify() @final +<<<<<<< HEAD async def __refresh_cloud_device_with_dids_async( self, dids: list[str] ) -> None: _LOGGER.debug('refresh cloud device with dids, %s', dids) +======= + async def __refresh_cloud_device_with_dids_async(self, + dids: list[str]) -> None: + _LOGGER.debug("refresh cloud device with dids, %s", dids) +>>>>>>> 83899f8 (fomatted code) cloud_list = await self._http.get_devices_with_dids_async(dids=dids) if cloud_list is None: _LOGGER.error('cloud http get_dev_list_async failed, %s', dids) return +<<<<<<< HEAD await self.__update_devices_from_cloud_async( cloud_list=cloud_list, filter_dids=dids) self.__request_show_devices_changed_notify() @@ -1584,10 +2267,32 @@ class MIoTClient: 'request refresh cloud devices, %s, %s', self._uid, self._cloud_server) delay_sec : int = 0 if immediately else REFRESH_CLOUD_DEVICES_DELAY +======= + await self.__update_devices_from_cloud_async(cloud_list=cloud_list, + filter_dids=dids) + self.__request_show_devices_changed_notify() + + def __request_refresh_cloud_devices(self, immediately=False) -> None: + _LOGGER.debug("request refresh cloud devices, %s, %s", self._uid, + self._cloud_server) + if immediately: + if self._refresh_cloud_devices_timer: + self._refresh_cloud_devices_timer.cancel() + self._refresh_cloud_devices_timer = self._main_loop.call_later( + 0, + lambda: self._main_loop.create_task( + self.__refresh_cloud_devices_async()), + ) + return +>>>>>>> 83899f8 (fomatted code) if self._refresh_cloud_devices_timer: self._refresh_cloud_devices_timer.cancel() self._refresh_cloud_devices_timer = self._main_loop.call_later( +<<<<<<< HEAD delay_sec, lambda: self._main_loop.create_task( +======= + 6, lambda: self._main_loop.create_task( +>>>>>>> 83899f8 (fomatted code) self.__refresh_cloud_devices_async())) @final @@ -1605,13 +2310,24 @@ class MIoTClient: if did not in filter_dids: continue device_old = self._device_list_gateway.get(did, None) +<<<<<<< HEAD +======= + gw_state_old = device_old.get("online", + False) if device_old else False +>>>>>>> 83899f8 (fomatted code) gw_state_new: bool = False device_new = gw_list.pop(did, None) if device_new: # Update gateway device info self._device_list_gateway[did] = { +<<<<<<< HEAD **device_new, 'group_id': group_id} gw_state_new = device_new.get('online', False) +======= + **device_new, "group_id": group_id + } + gw_state_new = device_new.get("online", False) +>>>>>>> 83899f8 (fomatted code) else: # Device offline if device_old: @@ -1632,14 +2348,23 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( +<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) +======= + did, + MIoTDeviceState.ONLINE + if state_new else MIoTDeviceState.OFFLINE, + sub.handler_ctx, + ) +>>>>>>> 83899f8 (fomatted code) # New devices or device home info changed for did, info in gw_list.items(): self._device_list_gateway[did] = {**info, 'group_id': group_id} if did not in self._device_list_cache: continue group_id_old: str = self._device_list_cache[did].get( +<<<<<<< HEAD 'group_id', None) self._device_list_cache[did]['group_id'] = group_id _LOGGER.info( @@ -1647,6 +2372,15 @@ class MIoTClient: self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache[did].get( 'online', None) +======= + "group_id", None) + self._device_list_cache[did]["group_id"] = group_id + _LOGGER.info("move device %s from %s to %s", did, group_id_old, + group_id) + self.__update_device_msg_sub(did=did) + state_old: Optional[bool] = self._device_list_cache[did].get( + "online", None) +>>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), info.get('online', False), @@ -1657,6 +2391,7 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( +<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) @@ -1664,6 +2399,17 @@ class MIoTClient: async def __refresh_gw_devices_with_group_id_async( self, group_id: str ) -> None: +======= + did, + MIoTDeviceState.ONLINE + if state_new else MIoTDeviceState.OFFLINE, + sub.handler_ctx, + ) + + @final + async def __refresh_gw_devices_with_group_id_async(self, + group_id: str) -> None: +>>>>>>> 83899f8 (fomatted code) """Refresh gateway devices by group_id""" _LOGGER.debug( 'refresh gw devices with group_id, %s', group_id) @@ -1685,23 +2431,39 @@ class MIoTClient: gw_list: dict = await mips.get_dev_list_async( payload=json.dumps(payload)) if gw_list is None: +<<<<<<< HEAD _LOGGER.error( 'refresh gw devices with group_id failed, %s, %s', self._uid, group_id) +======= + _LOGGER.error("refresh gw devices with group_id failed, %s, %s", + self._uid, group_id) +>>>>>>> 83899f8 (fomatted code) # Retry until success self.__request_refresh_gw_devices_by_group_id( group_id=group_id) return await self.__update_devices_from_gw_async( +<<<<<<< HEAD gw_list=gw_list, group_id=group_id, filter_dids=[ did for did, info in self._device_list_gateway.items() if info.get('group_id', None) == group_id]) +======= + gw_list=gw_list, + group_id=group_id, + filter_dids=[ + did for did, info in self._device_list_gateway.items() + if info.get("group_id", None) == group_id + ], + ) +>>>>>>> 83899f8 (fomatted code) self.__request_show_devices_changed_notify() @final - def __request_refresh_gw_devices_by_group_id( - self, group_id: str, immediately: bool = False - ) -> None: + def __request_refresh_gw_devices_by_group_id(self, + group_id: str, + immediately: bool = False + ) -> None: """Request refresh gateway devices by group_id""" refresh_timer = self._mips_local_state_changed_timers.get( group_id, None) @@ -1711,6 +2473,7 @@ class MIoTClient: refresh_timer.cancel() self._mips_local_state_changed_timers[group_id] = ( self._main_loop.call_later( +<<<<<<< HEAD 0, lambda: self._main_loop.create_task( self.__refresh_gw_devices_with_group_id_async( group_id=group_id)))) @@ -1722,6 +2485,22 @@ class MIoTClient: lambda: self._main_loop.create_task( self.__refresh_gw_devices_with_group_id_async( group_id=group_id)))) +======= + 0, + lambda: self._main_loop.create_task( + self.__refresh_gw_devices_with_group_id_async( + group_id=group_id)), + )) + if refresh_timer: + return + self._mips_local_state_changed_timers[ + group_id] = self._main_loop.call_later( + 3, + lambda: self._main_loop.create_task( + self.__refresh_gw_devices_with_group_id_async(group_id= + group_id)), + ) +>>>>>>> 83899f8 (fomatted code) @final async def __refresh_props_from_cloud(self, patch_len: int = 150) -> bool: @@ -1743,6 +2522,7 @@ class MIoTClient: if not results: raise MIoTClientError('get_props_async failed') for result in results: +<<<<<<< HEAD if ( 'did' not in result or 'siid' not in result @@ -1764,6 +2544,22 @@ class MIoTClient: _LOGGER.error( 'refresh props error, cloud, %s, %s', err, traceback.format_exc()) +======= + if ("did" not in result or "siid" not in result or + "piid" not in result or "value" not in result): + continue + request_list.pop( + f"{result['did']}|{result['siid']}|{result['piid']}", None) + self.__on_prop_msg(params=result, ctx=None) + if request_list: + _LOGGER.info("refresh props failed, cloud, %s", + list(request_list.keys())) + request_list = None + return True + except Exception as err: # pylint:disable=broad-exception-caught + _LOGGER.error("refresh props error, cloud, %s, %s", err, + traceback.format_exc()) +>>>>>>> 83899f8 (fomatted code) # Add failed request back to the list self._refresh_props_list.update(request_list) return False @@ -1791,11 +2587,22 @@ class MIoTClient: continue request_list[did] = { **params, +<<<<<<< HEAD 'fut': mips_gw.get_prop_async( did=did, siid=params['siid'], piid=params['piid'], timeout_ms=6000)} results = await asyncio.gather( *[v['fut'] for v in request_list.values()]) +======= + "fut": + mips_gw.get_prop_async(did=did, + siid=params["siid"], + piid=params["piid"], + timeout_ms=6000), + } + results = await asyncio.gather( + *[v["fut"] for v in request_list.values()]) +>>>>>>> 83899f8 (fomatted code) for (did, param), result in zip(request_list.items(), results): if result is None: # Don't use "not result", it will be skipped when result @@ -1834,11 +2641,22 @@ class MIoTClient: continue request_list[did] = { **params, +<<<<<<< HEAD 'fut': self._miot_lan.get_prop_async( did=did, siid=params['siid'], piid=params['piid'], timeout_ms=6000)} results = await asyncio.gather( *[v['fut'] for v in request_list.values()]) +======= + "fut": + self._miot_lan.get_prop_async(did=did, + siid=params["siid"], + piid=params["piid"], + timeout_ms=6000), + } + results = await asyncio.gather( + *[v["fut"] for v in request_list.values()]) +>>>>>>> 83899f8 (fomatted code) for (did, param), result in zip(request_list.items(), results): if result is None: # Don't use "not result", it will be skipped when result @@ -1865,16 +2683,21 @@ class MIoTClient: if not self._refresh_props_list: return # Cloud, Central hub gateway, Lan control - if ( - await self.__refresh_props_from_cloud() - or await self.__refresh_props_from_gw() - or await self.__refresh_props_from_lan() - ): + if (await self.__refresh_props_from_cloud() or + await self.__refresh_props_from_gw() or + await self.__refresh_props_from_lan()): self._refresh_props_retry_count = 0 if self._refresh_props_list: self._refresh_props_timer = self._main_loop.call_later( +<<<<<<< HEAD REFRESH_PROPS_DELAY, lambda: self._main_loop.create_task( self.__refresh_props_handler())) +======= + 0.2, + lambda: self._main_loop.create_task( + self.__refresh_props_handler()), + ) +>>>>>>> 83899f8 (fomatted code) else: self._refresh_props_timer = None return @@ -1889,6 +2712,7 @@ class MIoTClient: _LOGGER.info('refresh props failed, retry count exceed') return self._refresh_props_retry_count += 1 +<<<<<<< HEAD _LOGGER.info( 'refresh props failed, retry, %s', self._refresh_props_retry_count) self._refresh_props_timer = self._main_loop.call_later( @@ -1899,15 +2723,34 @@ class MIoTClient: def __show_client_error_notify( self, message: Optional[str], notify_key: str = '' ) -> None: +======= + _LOGGER.info("refresh props failed, retry, %s", + self._refresh_props_retry_count) + self._refresh_props_timer = self._main_loop.call_later( + 3, + lambda: self._main_loop.create_task(self.__refresh_props_handler())) + + @final + def __show_client_error_notify(self, + message: Optional[str], + notify_key: str = "") -> None: +>>>>>>> 83899f8 (fomatted code) if message: self._persistence_notify( +<<<<<<< HEAD f'{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error', +======= + f"{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error", + self._i18n.translate( + key="miot.client.xiaomi_home_error_title"), # type: ignore +>>>>>>> 83899f8 (fomatted code) self._i18n.translate( key='miot.client.xiaomi_home_error_title'), # type: ignore self._i18n.translate( key='miot.client.xiaomi_home_error', replace={ +<<<<<<< HEAD 'nick_name': self._entry_data.get( 'nick_name', DEFAULT_NICK_NAME), 'uid': self._uid, @@ -1916,6 +2759,23 @@ class MIoTClient: else: self._persistence_notify( f'{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error', +======= + "nick_name": + self._entry_data.get("nick_name", + DEFAULT_NICK_NAME), + "uid": + self._uid, + "cloud_server": + self._cloud_server, + "message": + message, + }, + ), + ) # type: ignore + else: + self._persistence_notify( + f"{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error", +>>>>>>> 83899f8 (fomatted code) None, None) @final @@ -1935,14 +2795,24 @@ class MIoTClient: # New devices if 'add' in self._display_devs_notify: for did, info in { +<<<<<<< HEAD **self._device_list_gateway, **self._device_list_cloud +======= + **self._device_list_gateway, + **self._device_list_cloud, +>>>>>>> 83899f8 (fomatted code) }.items(): if did in self._device_list_cache: continue count_add += 1 +<<<<<<< HEAD message_add += ( f'- {info.get("name", "unknown")} ({did}, ' f'{info.get("model", "unknown")})\n') +======= + message_add += (f"- {info.get('name', 'unknown')} ({did}, " + f"{info.get('model', 'unknown')})\n") +>>>>>>> 83899f8 (fomatted code) # Get unavailable and offline devices home_name_del: Optional[str] = None home_name_offline: Optional[str] = None @@ -1958,9 +2828,14 @@ class MIoTClient: message_del += f'\n[{home_name_new}]\n' home_name_del = home_name_new count_del += 1 +<<<<<<< HEAD message_del += ( f'- {info.get("name", "unknown")} ({did}, ' f'{info.get("room_name", "unknown")})\n') +======= + message_del += (f"- {info.get('name', 'unknown')} ({did}, " + f"{info.get('room_name', 'unknown')})\n") +>>>>>>> 83899f8 (fomatted code) continue if 'offline' in self._display_devs_notify: # Device offline @@ -1968,13 +2843,19 @@ class MIoTClient: message_offline += f'\n[{home_name_new}]\n' home_name_offline = home_name_new count_offline += 1 +<<<<<<< HEAD message_offline += ( f'- {info.get("name", "unknown")} ({did}, ' f'{info.get("room_name", "unknown")})\n') +======= + message_offline += (f"- {info.get('name', 'unknown')} ({did}, " + f"{info.get('room_name', 'unknown')})\n") +>>>>>>> 83899f8 (fomatted code) message = '' if 'add' in self._display_devs_notify and count_add: message += self._i18n.translate( +<<<<<<< HEAD key='miot.client.device_list_add', replace={ 'count': count_add, @@ -1992,10 +2873,36 @@ class MIoTClient: 'count': count_offline, 'message': message_offline}) # type: ignore if message != '': +======= + key="miot.client.device_list_add", + replace={ + "count": count_add, + "message": message_add + }, + ) # type: ignore + if "del" in self._display_devs_notify and count_del: + message += self._i18n.translate( + key="miot.client.device_list_del", + replace={ + "count": count_del, + "message": message_del + }, + ) # type: ignore + if "offline" in self._display_devs_notify and count_offline: + message += self._i18n.translate( + key="miot.client.device_list_offline", + replace={ + "count": count_offline, + "message": message_offline + }, + ) # type: ignore + if message != "": +>>>>>>> 83899f8 (fomatted code) msg_hash = hash(message) if msg_hash == self._display_notify_content_hash: # Notify content no change, return _LOGGER.debug( +<<<<<<< HEAD 'device list changed notify content no change, return') return network_status = self._i18n.translate( @@ -2004,22 +2911,51 @@ class MIoTClient: else 'miot.client.network_status_offline') self._persistence_notify( self.__gen_notify_key('dev_list_changed'), +======= + "device list changed notify content no change, return") + return + network_status = self._i18n.translate( + key="miot.client.network_status_online" if self._network. + network_status else "miot.client.network_status_offline") + self._persistence_notify( + self.__gen_notify_key("dev_list_changed"), + self._i18n.translate( + "miot.client.device_list_changed_title"), # type: ignore +>>>>>>> 83899f8 (fomatted code) self._i18n.translate( 'miot.client.device_list_changed_title'), # type: ignore self._i18n.translate( key='miot.client.device_list_changed', replace={ +<<<<<<< HEAD 'nick_name': self._entry_data.get( 'nick_name', DEFAULT_NICK_NAME), 'uid': self._uid, 'cloud_server': self._cloud_server, 'network_status': network_status, 'message': message})) # type: ignore +======= + "nick_name": + self._entry_data.get("nick_name", + DEFAULT_NICK_NAME), + "uid": + self._uid, + "cloud_server": + self._cloud_server, + "network_status": + network_status, + "message": + message, + }, + ), + ) # type: ignore +>>>>>>> 83899f8 (fomatted code) self._display_notify_content_hash = msg_hash _LOGGER.debug( 'show device list changed notify, add %s, del %s, offline %s', count_add, count_del, count_offline) else: +<<<<<<< HEAD self._persistence_notify( self.__gen_notify_key('dev_list_changed'), None, None) @@ -2027,6 +2963,14 @@ class MIoTClient: def __request_show_devices_changed_notify( self, delay_sec: float = 6 ) -> None: +======= + self._persistence_notify(self.__gen_notify_key("dev_list_changed"), + None, None) + + @final + def __request_show_devices_changed_notify(self, + delay_sec: float = 6) -> None: +>>>>>>> 83899f8 (fomatted code) if not self._display_devs_notify: return if not self._mips_cloud and not self._mips_local and not self._miot_lan: @@ -2098,7 +3042,11 @@ async def get_miot_instance_async( _LOGGER.info('create miot_network instance') # MIoT service mips_service: Optional[MipsService] = hass.data[DOMAIN].get( +<<<<<<< HEAD 'mips_service', None) +======= + "mips_service", None) +>>>>>>> 83899f8 (fomatted code) if not mips_service: aiozc = await zeroconf.async_get_async_instance(hass) mips_service = MipsService(aiozc=aiozc, loop=loop) diff --git a/custom_components/xiaomi_home/miot/miot_cloud.py b/custom_components/xiaomi_home/miot/miot_cloud.py index d9acd5c..717d343 100644 --- a/custom_components/xiaomi_home/miot/miot_cloud.py +++ b/custom_components/xiaomi_home/miot/miot_cloud.py @@ -99,10 +99,17 @@ class MIoTOauthClient: if cloud_server == 'cn': self._oauth_host = DEFAULT_OAUTH2_API_HOST else: +<<<<<<< HEAD self._oauth_host = f'{cloud_server}.{DEFAULT_OAUTH2_API_HOST}' self._device_id = f'ha.{uuid}' self._state = hashlib.sha1( f'd={self._device_id}'.encode('utf-8')).hexdigest() +======= + self._oauth_host = f"{cloud_server}.{DEFAULT_OAUTH2_API_HOST}" + self._device_id = f"ha.{uuid}" + self._state = hashlib.sha1( + f"d={self._device_id}".encode("utf-8")).hexdigest() +>>>>>>> 83899f8 (fomatted code) self._session = aiohttp.ClientSession(loop=self._main_loop) @property @@ -165,14 +172,20 @@ class MIoTOauthClient: timeout=MIHOME_HTTP_API_TIMEOUT ) if http_res.status == 401: +<<<<<<< HEAD raise MIoTOauthError( 'unauthorized(401)', MIoTErrorCode.CODE_OAUTH_UNAUTHORIZED) +======= + raise MIoTOauthError("unauthorized(401)", + MIoTErrorCode.CODE_OAUTH_UNAUTHORIZED) +>>>>>>> 83899f8 (fomatted code) if http_res.status != 200: raise MIoTOauthError( f'invalid http status code, {http_res.status}') res_str = await http_res.text() res_obj = json.loads(res_str) +<<<<<<< HEAD if ( not res_obj or res_obj.get('code', None) != 0 @@ -188,6 +201,19 @@ class MIoTOauthClient: 'expires_ts': int( time.time() + (res_obj['result'].get('expires_in', 0)*TOKEN_EXPIRES_TS_RATIO)) +======= + if (not res_obj or res_obj.get("code", None) != 0 or + "result" not in res_obj or + not all(key in res_obj["result"] for key in + ["access_token", "refresh_token", "expires_in"])): + raise MIoTOauthError(f"invalid http response, {res_str}") + + return { + **res_obj["result"], + "expires_ts": + int(time.time() + (res_obj["result"].get("expires_in", 0) * + TOKEN_EXPIRES_TS_RATIO)), +>>>>>>> 83899f8 (fomatted code) } async def get_access_token_async(self, code: str) -> dict: @@ -202,12 +228,22 @@ class MIoTOauthClient: if not isinstance(code, str): raise MIoTOauthError('invalid code') +<<<<<<< HEAD return await self.__get_token_async(data={ 'client_id': self._client_id, 'redirect_uri': self._redirect_url, 'code': code, 'device_id': self._device_id }) +======= + return await self.__get_token_async( + data={ + "client_id": self._client_id, + "redirect_uri": self._redirect_url, + "code": code, + "device_id": self._device_id, + }) +>>>>>>> 83899f8 (fomatted code) async def refresh_access_token_async(self, refresh_token: str) -> dict: """get access token by refresh token. @@ -221,11 +257,20 @@ class MIoTOauthClient: if not isinstance(refresh_token, str): raise MIoTOauthError('invalid refresh_token') +<<<<<<< HEAD return await self.__get_token_async(data={ 'client_id': self._client_id, 'redirect_uri': self._redirect_url, 'refresh_token': refresh_token, }) +======= + return await self.__get_token_async( + data={ + "client_id": self._client_id, + "redirect_uri": self._redirect_url, + "refresh_token": refresh_token, + }) +>>>>>>> 83899f8 (fomatted code) class MIoTHttpClient: @@ -256,6 +301,7 @@ class MIoTHttpClient: self._get_prop_timer = None self._get_prop_list = {} +<<<<<<< HEAD if ( not isinstance(cloud_server, str) or not isinstance(client_id, str) @@ -266,6 +312,16 @@ class MIoTHttpClient: self.update_http_header( cloud_server=cloud_server, client_id=client_id, access_token=access_token) +======= + if (not isinstance(cloud_server, str) or + not isinstance(client_id, str) or + not isinstance(access_token, str)): + raise MIoTHttpError("invalid params") + + self.update_http_header(cloud_server=cloud_server, + client_id=client_id, + access_token=access_token) +>>>>>>> 83899f8 (fomatted code) self._session = aiohttp.ClientSession(loop=self._main_loop) @@ -307,9 +363,16 @@ class MIoTHttpClient: # pylint: disable=unused-private-member async def __mihome_api_get_async( +<<<<<<< HEAD self, url_path: str, params: dict, timeout: int = MIHOME_HTTP_API_TIMEOUT ) -> dict: +======= + self, + url_path: str, + params: dict, + timeout: int = MIHOME_HTTP_API_TIMEOUT) -> dict: +>>>>>>> 83899f8 (fomatted code) http_res = await self._session.get( url=f'{self._base_url}{url_path}', params=params, @@ -327,6 +390,7 @@ class MIoTHttpClient: res_obj: dict = json.loads(res_str) if res_obj.get('code', None) != 0: raise MIoTHttpError( +<<<<<<< HEAD f'invalid response code, {res_obj.get("code",None)}, ' f'{res_obj.get("message","")}') _LOGGER.debug( @@ -338,6 +402,19 @@ class MIoTHttpClient: self, url_path: str, data: dict, timeout: int = MIHOME_HTTP_API_TIMEOUT ) -> dict: +======= + f"invalid response code, {res_obj.get('code', None)}, " + f"{res_obj.get('message', '')}") + _LOGGER.debug("mihome api get, %s%s, %s -> %s", self._base_url, + url_path, params, res_obj) + return res_obj + + async def __mihome_api_post_async( + self, + url_path: str, + data: dict, + timeout: int = MIHOME_HTTP_API_TIMEOUT) -> dict: +>>>>>>> 83899f8 (fomatted code) http_res = await self._session.post( url=f'{self._base_url}{url_path}', json=data, @@ -355,24 +432,42 @@ class MIoTHttpClient: res_obj: dict = json.loads(res_str) if res_obj.get('code', None) != 0: raise MIoTHttpError( +<<<<<<< HEAD f'invalid response code, {res_obj.get("code",None)}, ' f'{res_obj.get("message","")}') _LOGGER.debug( 'mihome api post, %s%s, %s -> %s', self._base_url, url_path, data, res_obj) +======= + f"invalid response code, {res_obj.get('code', None)}, " + f"{res_obj.get('message', '')}") + _LOGGER.debug("mihome api post, %s%s, %s -> %s", self._base_url, + url_path, data, res_obj) +>>>>>>> 83899f8 (fomatted code) return res_obj async def get_user_info_async(self) -> dict: http_res = await self._session.get( +<<<<<<< HEAD url='https://open.account.xiaomi.com/user/profile', params={ 'clientId': self._client_id, 'token': self._access_token}, headers={'content-type': 'application/x-www-form-urlencoded'}, timeout=MIHOME_HTTP_API_TIMEOUT +======= + url="https://open.account.xiaomi.com/user/profile", + params={ + "clientId": self._client_id, + "token": self._access_token + }, + headers={"content-type": "application/x-www-form-urlencoded"}, + timeout=MIHOME_HTTP_API_TIMEOUT, +>>>>>>> 83899f8 (fomatted code) ) res_str = await http_res.text() res_obj = json.loads(res_str) +<<<<<<< HEAD if ( not res_obj or res_obj.get('code', None) != 0 @@ -380,6 +475,11 @@ class MIoTHttpClient: or 'miliaoNick' not in res_obj['data'] ): raise MIoTOauthError(f'invalid http response, {http_res.text}') +======= + if (not res_obj or res_obj.get("code", None) != 0 or + "data" not in res_obj or "miliaoNick" not in res_obj["data"]): + raise MIoTOauthError(f"invalid http response, {http_res.text}") +>>>>>>> 83899f8 (fomatted code) return res_obj['data'] @@ -401,9 +501,14 @@ class MIoTHttpClient: return cert +<<<<<<< HEAD async def __get_dev_room_page_async( self, max_id: Optional[str] = None ) -> dict: +======= + async def __get_dev_room_page_async(self, + max_id: Optional[str] = None) -> dict: +>>>>>>> 83899f8 (fomatted code) res_obj = await self.__mihome_api_post_async( url_path='/app/v2/homeroom/get_dev_room_page', data={ @@ -419,6 +524,7 @@ class MIoTHttpClient: _LOGGER.error( 'get dev room page error, invalid home, %s', home) continue +<<<<<<< HEAD home_list[str(home['id'])] = {'dids': home.get( 'dids', None) or [], 'room_info': {}} for room in home.get('roomlist', []): @@ -442,6 +548,32 @@ class MIoTHttpClient: room_id, {'dids': []}) home_list[home_id]['room_info'][room_id]['dids'].extend( info['dids']) +======= + home_list[str(home["id"])] = { + "dids": home.get("dids", None) or [], + "room_info": {}, + } + for room in home.get("roomlist", []): + if "id" not in room: + _LOGGER.error("get dev room page error, invalid room, %s", + room) + continue + home_list[str(home["id"])]["room_info"][str(room["id"])] = { + "dids": room.get("dids", None) or [] + } + if res_obj["result"].get("has_more", False) and isinstance( + res_obj["result"].get("max_id", None), str): + next_list = await self.__get_dev_room_page_async( + max_id=res_obj["result"]["max_id"]) + for home_id, info in next_list.items(): + home_list.setdefault(home_id, {"dids": [], "room_info": {}}) + home_list[home_id]["dids"].extend(info["dids"]) + for room_id, info in info["room_info"].items(): + home_list[home_id]["room_info"].setdefault( + room_id, {"dids": []}) + home_list[home_id]["room_info"][room_id]["dids"].extend( + info["dids"]) +>>>>>>> 83899f8 (fomatted code) return home_list @@ -450,10 +582,16 @@ class MIoTHttpClient: device_list: dict[str, dict] = await self.__get_device_list_page_async( dids=[], start_did=None) for did, value in device_list.items(): +<<<<<<< HEAD if value['owner'] is not None and ('userid' in value['owner']) and ( 'nickname' in value['owner'] ): separated_shared_devices.setdefault(did, value['owner']) +======= + if (value["owner"] is not None and ("userid" in value["owner"]) and + ("nickname" in value["owner"])): + separated_shared_devices.setdefault(did, value["owner"]) +>>>>>>> 83899f8 (fomatted code) return separated_shared_devices async def get_homeinfos_async(self) -> dict: @@ -481,6 +619,7 @@ class MIoTHttpClient: or 'roomlist' not in home ): continue +<<<<<<< HEAD if uid is None and device_source == 'homelist': uid = str(home['uid']) home_infos[device_source][home['id']] = { @@ -512,10 +651,48 @@ class MIoTHttpClient: more_list = await self.__get_dev_room_page_async( max_id=res_obj['result']['max_id']) for device_source in ['homelist', 'share_home_list']: +======= + if uid is None and device_source == "homelist": + uid = str(home["uid"]) + home_infos[device_source][home["id"]] = { + "home_id": + home["id"], + "home_name": + home["name"], + "city_id": + home.get("city_id", None), + "longitude": + home.get("longitude", None), + "latitude": + home.get("latitude", None), + "address": + home.get("address", None), + "dids": + home.get("dids", []), + "room_info": { + room["id"]: { + "room_id": room["id"], + "room_name": room["name"], + "dids": room.get("dids", []), + } for room in home.get("roomlist", []) if "id" in room + }, + "group_id": + calc_group_id(uid=home["uid"], home_id=home["id"]), + "uid": + str(home["uid"]), + } + home_infos["uid"] = uid + if res_obj["result"].get("has_more", False) and isinstance( + res_obj["result"].get("max_id", None), str): + more_list = await self.__get_dev_room_page_async( + max_id=res_obj["result"]["max_id"]) + for device_source in ["homelist", "share_home_list"]: +>>>>>>> 83899f8 (fomatted code) for home_id, info in more_list.items(): if home_id not in home_infos[device_source]: _LOGGER.info('unknown home, %s, %s', home_id, info) continue +<<<<<<< HEAD home_infos[device_source][home_id]['dids'].extend( info['dids']) for room_id, info in info['room_info'].items(): @@ -527,6 +704,19 @@ class MIoTHttpClient: 'dids': []}) home_infos[device_source][home_id]['room_info'][ room_id]['dids'].extend(info['dids']) +======= + home_infos[device_source][home_id]["dids"].extend( + info["dids"]) + for room_id, info in info["room_info"].items(): + home_infos[device_source][home_id][ + "room_info"].setdefault(room_id, { + "room_id": room_id, + "room_name": "", + "dids": [] + }) + home_infos[device_source][home_id]["room_info"][ + room_id]["dids"].extend(info["dids"]) +>>>>>>> 83899f8 (fomatted code) return { 'uid': uid, @@ -538,6 +728,7 @@ class MIoTHttpClient: return (await self.get_homeinfos_async()).get('uid', None) async def __get_device_list_page_async( +<<<<<<< HEAD self, dids: list[str], start_did: Optional[str] = None ) -> dict[str, dict]: req_data: dict = { @@ -546,16 +737,29 @@ class MIoTHttpClient: 'get_third_device': True, 'dids': dids } +======= + self, + dids: list[str], + start_did: Optional[str] = None) -> dict[str, dict]: + req_data: dict = {"limit": 200, "get_split_device": True, "dids": dids} +>>>>>>> 83899f8 (fomatted code) if start_did: req_data['start_did'] = start_did device_infos: dict = {} res_obj = await self.__mihome_api_post_async( +<<<<<<< HEAD url_path='/app/v2/home/device_list_page', data=req_data ) if 'result' not in res_obj: raise MIoTHttpError('invalid response result') res_obj = res_obj['result'] +======= + url_path="/app/v2/home/device_list_page", data=req_data) + if "result" not in res_obj: + raise MIoTHttpError("invalid response result") + res_obj = res_obj["result"] +>>>>>>> 83899f8 (fomatted code) for device in res_obj.get('list', []) or []: did = device.get('did', None) @@ -580,6 +784,7 @@ class MIoTHttpClient: model, did) continue device_infos[did] = { +<<<<<<< HEAD 'did': did, 'uid': device.get('uid', None), 'name': name, @@ -606,17 +811,79 @@ class MIoTHttpClient: next_start_did = res_obj.get('next_start_did', None) if res_obj.get('has_more', False) and next_start_did: +======= + "did": + did, + "uid": + device.get("uid", None), + "name": + name, + "urn": + urn, + "model": + model, + "connect_type": + device.get("pid", -1), + "token": + device.get("token", None), + "online": + device.get("isOnline", False), + "icon": + device.get("icon", None), + "parent_id": + device.get("parent_id", None), + "manufacturer": + model.split(".")[0], + # 2: xiao-ai, 1: general speaker + "voice_ctrl": + device.get("voice_ctrl", 0), + "rssi": + device.get("rssi", None), + "owner": + device.get("owner", None), + "pid": + device.get("pid", None), + "local_ip": + device.get("local_ip", None), + "ssid": + device.get("ssid", None), + "bssid": + device.get("bssid", None), + "order_time": + device.get("orderTime", 0), + "fw_version": + device.get("extra", {}).get("fw_version", "unknown"), + } + if isinstance(device.get("extra", None), dict) and device["extra"]: + device_infos[did]["fw_version"] = device["extra"].get( + "fw_version", None) + device_infos[did]["mcu_version"] = device["extra"].get( + "mcu_version", None) + device_infos[did]["platform"] = device["extra"].get( + "platform", None) + + next_start_did = res_obj.get("next_start_did", None) + if res_obj.get("has_more", False) and next_start_did: +>>>>>>> 83899f8 (fomatted code) device_infos.update(await self.__get_device_list_page_async( dids=dids, start_did=next_start_did)) return device_infos async def get_devices_with_dids_async( +<<<<<<< HEAD self, dids: list[str] ) -> Optional[dict[str, dict]]: results: list[dict[str, dict]] = await asyncio.gather( *[self.__get_device_list_page_async(dids=dids[index:index+150]) for index in range(0, len(dids), 150)]) +======= + self, dids: list[str]) -> Optional[dict[str, dict]]: + results: list[dict[str, dict]] = await asyncio.gather(*[ + self.__get_device_list_page_async(dids=dids[index:index + 150]) + for index in range(0, len(dids), 150) + ]) +>>>>>>> 83899f8 (fomatted code) devices = {} for result in results: if result is None: @@ -624,21 +891,27 @@ class MIoTHttpClient: devices.update(result) return devices - async def get_devices_async( - self, home_ids: Optional[list[str]] = None - ) -> dict[str, dict]: + async def get_devices_async(self, + home_ids: Optional[list[str]] = None + ) -> dict[str, dict]: homeinfos = await self.get_homeinfos_async() homes: dict[str, dict[str, Any]] = {} devices: dict[str, dict] = {} for device_type in ['home_list', 'share_home_list']: homes.setdefault(device_type, {}) +<<<<<<< HEAD for home_id, home_info in (homeinfos.get( device_type, None) or {}).items(): +======= + for home_id, home_info in (homeinfos.get(device_type, None) or + {}).items(): +>>>>>>> 83899f8 (fomatted code) if isinstance(home_ids, list) and home_id not in home_ids: continue home_name: str = home_info['home_name'] group_id: str = home_info['group_id'] homes[device_type].setdefault( +<<<<<<< HEAD home_id, { 'home_name': home_name, 'uid': home_info['uid'], @@ -666,9 +939,44 @@ class MIoTHttpClient: } for did in room_info.get('dids', [])}) separated_shared_devices: dict = ( await self.get_separated_shared_devices_async()) +======= + home_id, + { + "home_name": home_name, + "uid": home_info["uid"], + "group_id": group_id, + "room_info": {}, + }, + ) + devices.update({ + did: { + "home_id": home_id, + "home_name": home_name, + "room_id": home_id, + "room_name": home_name, + "group_id": group_id, + } for did in home_info.get("dids", []) + }) + for room_id, room_info in home_info.get("room_info").items(): + room_name: str = room_info.get("room_name", "") + homes[device_type][home_id]["room_info"][ + room_id] = room_name + devices.update({ + did: { + "home_id": home_id, + "home_name": home_name, + "room_id": room_id, + "room_name": room_name, + "group_id": group_id, + } for did in room_info.get("dids", []) + }) + separated_shared_devices: dict = await self.get_separated_shared_devices_async( + ) +>>>>>>> 83899f8 (fomatted code) if separated_shared_devices: homes.setdefault('separated_shared_list', {}) for did, owner in separated_shared_devices.items(): +<<<<<<< HEAD owner_id = str(owner['userid']) homes['separated_shared_list'].setdefault(owner_id,{ 'home_name': owner['nickname'], @@ -683,6 +991,29 @@ class MIoTHttpClient: 'room_name': 'shared_device', 'group_id': 'NotSupport' }}) +======= + owner_id = str(owner["userid"]) + homes["separated_shared_list"].setdefault( + owner_id, + { + "home_name": owner["nickname"], + "uid": owner_id, + "group_id": "NotSupport", + "room_info": { + "shared_device": "shared_device" + }, + }, + ) + devices.update({ + did: { + "home_id": owner_id, + "home_name": owner["nickname"], + "room_id": "shared_device", + "room_name": "shared_device", + "group_id": "NotSupport", + } + }) +>>>>>>> 83899f8 (fomatted code) dids = sorted(list(devices.keys())) results = await self.get_devices_with_dids_async(dids=dids) if results is None: @@ -700,9 +1031,15 @@ class MIoTHttpClient: device = devices.pop(did, None) parent_did = did.replace(match_str.group(), '') if parent_did in devices: +<<<<<<< HEAD devices[parent_did].setdefault('sub_devices', {}) devices[parent_did]['sub_devices'][match_str.group()[ 1:]] = device +======= + devices[parent_did].setdefault("sub_devices", {}) + devices[parent_did]["sub_devices"][match_str.group() + [1:]] = device +>>>>>>> 83899f8 (fomatted code) else: _LOGGER.error( 'unknown sub devices, %s, %s', did, parent_did) @@ -718,10 +1055,17 @@ class MIoTHttpClient: {"did": "xxxxxx", "siid": 2, "piid": 2}] """ res_obj = await self.__mihome_api_post_async( +<<<<<<< HEAD url_path='/app/v2/miotspec/prop/get', data={ 'datasource': 1, 'params': params +======= + url_path="/app/v2/miotspec/prop/get", + data={ + "datasource": 1, + "params": params +>>>>>>> 83899f8 (fomatted code) }, ) if 'result' not in res_obj: @@ -729,8 +1073,16 @@ class MIoTHttpClient: return res_obj['result'] async def __get_prop_async(self, did: str, siid: int, piid: int) -> Any: +<<<<<<< HEAD results = await self.get_props_async( params=[{'did': did, 'siid': siid, 'piid': piid}]) +======= + results = await self.get_props_async(params=[{ + "did": did, + "siid": siid, + "piid": piid + }]) +>>>>>>> 83899f8 (fomatted code) if not results: return None result = results[0] @@ -759,7 +1111,11 @@ class MIoTHttpClient: for result in results: if not all( +<<<<<<< HEAD key in result for key in ['did', 'siid', 'piid', 'value']): +======= + key in result for key in ["did", "siid", "piid", "value"]): +>>>>>>> 83899f8 (fomatted code) continue key = f'{result["did"]}.{result["siid"]}.{result["piid"]}' prop_obj = self._get_prop_list.pop(key, None) @@ -787,9 +1143,11 @@ class MIoTHttpClient: self._get_prop_timer = None return True - async def get_prop_async( - self, did: str, siid: int, piid: int, immediately: bool = False - ) -> Any: + async def get_prop_async(self, + did: str, + siid: int, + piid: int, + immediately: bool = False) -> Any: if immediately: return await self.__get_prop_async(did, siid, piid) key: str = f'{did}.{siid}.{piid}' @@ -798,8 +1156,17 @@ class MIoTHttpClient: return await prop_obj['fut'] fut = self._main_loop.create_future() self._get_prop_list[key] = { +<<<<<<< HEAD 'param': {'did': did, 'siid': siid, 'piid': piid}, 'fut': fut +======= + "param": { + "did": did, + "siid": siid, + "piid": piid + }, + "fut": fut, +>>>>>>> 83899f8 (fomatted code) } if self._get_prop_timer is None: self._get_prop_timer = self._main_loop.call_later( @@ -814,6 +1181,7 @@ class MIoTHttpClient: params = [{"did": "xxxx", "siid": 2, "piid": 1, "value": False}] """ res_obj = await self.__mihome_api_post_async( +<<<<<<< HEAD url_path='/app/v2/miotspec/prop/set', data={ 'params': params @@ -822,6 +1190,13 @@ class MIoTHttpClient: ) if 'result' not in res_obj: raise MIoTHttpError('invalid response result') +======= + url_path="/app/v2/miotspec/prop/set", + data={"params": params}, + timeout=15) + if "result" not in res_obj: + raise MIoTHttpError("invalid response result") +>>>>>>> 83899f8 (fomatted code) return res_obj['result'] @@ -830,6 +1205,7 @@ class MIoTHttpClient: params = [{"did": "xxxx", "siid": 2, "piid": 1, "value": False}] """ res_obj = await self.__mihome_api_post_async( +<<<<<<< HEAD url_path='/app/v2/miotspec/prop/set', data={ 'params': params @@ -838,12 +1214,18 @@ class MIoTHttpClient: ) if 'result' not in res_obj: raise MIoTHttpError('invalid response result') +======= + url_path="/app/v2/miotspec/prop/set", + data={"params": params}, + timeout=15) + if "result" not in res_obj: + raise MIoTHttpError("invalid response result") +>>>>>>> 83899f8 (fomatted code) return res_obj['result'] - async def action_async( - self, did: str, siid: int, aiid: int, in_list: list[dict] - ) -> dict: + async def action_async(self, did: str, siid: int, aiid: int, + in_list: list[dict]) -> dict: """ params = {"did": "xxxx", "siid": 2, "aiid": 1, "in": []} """ diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index a8e2e48..0b06044 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -78,7 +78,6 @@ from homeassistant.const import ( from homeassistant.helpers.entity import DeviceInfo from homeassistant.components.switch import SwitchDeviceClass - # pylint: disable=relative-beyond-top-level from .specs.specv2entity import ( SPEC_ACTION_TRANS_MAP, @@ -115,9 +114,14 @@ class MIoTEntityData: events: set[MIoTSpecEvent] actions: set[MIoTSpecAction] +<<<<<<< HEAD def __init__( self, platform: str, spec: MIoTSpecInstance | MIoTSpecService ) -> None: +======= + def __init__(self, platform: str, + spec: MIoTSpecInstance | MIoTSpecService) -> None: +>>>>>>> 83899f8 (fomatted code) self.platform = platform self.spec = spec self.device_class = None @@ -150,8 +154,13 @@ class MIoTDevice: _suggested_area: Optional[str] _sub_id: int +<<<<<<< HEAD _device_state_sub_list: dict[str, dict[ str, Callable[[str, MIoTDeviceState], None]]] +======= + _device_state_sub_list: dict[str, dict[str, Callable[[str, MIoTDeviceState], + None]]] +>>>>>>> 83899f8 (fomatted code) _value_sub_list: dict[str, dict[str, Callable[[dict, Any], None]]] _entity_list: dict[str, list[MIoTEntityData]] @@ -181,10 +190,17 @@ class MIoTDevice: self._room_id = device_info.get('room_id', None) self._room_name = device_info.get('room_name', None) match self.miot_client.area_name_rule: +<<<<<<< HEAD case 'home_room': self._suggested_area = ( f'{self._home_name} {self._room_name}'.strip()) case 'home': +======= + case "home_room": + self._suggested_area = f"{self._home_name} {self._room_name}".strip( + ) + case "home": +>>>>>>> 83899f8 (fomatted code) self._suggested_area = self._home_name.strip() case 'room': self._suggested_area = self._room_name.strip() @@ -206,6 +222,7 @@ class MIoTDevice: sub_info = sub_devices.get(f's{service.iid}', None) if sub_info is None: continue +<<<<<<< HEAD _LOGGER.debug( 'miot device, update service sub info, %s, %s', self.did, sub_info) @@ -215,6 +232,16 @@ class MIoTDevice: # Sub device state self.miot_client.sub_device_state( self._did, self.__on_device_state_changed) +======= + _LOGGER.debug("miot device, update service sub info, %s, %s", + self.did, sub_info) + service.description_trans = sub_info.get( + "name", service.description_trans) + + # Sub device state + self.miot_client.sub_device_state(self._did, + self.__on_device_state_changed) +>>>>>>> 83899f8 (fomatted code) _LOGGER.debug('miot device init %s', device_info) @@ -239,12 +266,19 @@ class MIoTDevice: return self._action_list async def action_async(self, siid: int, aiid: int, in_list: list) -> list: +<<<<<<< HEAD return await self.miot_client.action_async( did=self._did, siid=siid, aiid=aiid, in_list=in_list) +======= + return await self.miot_client.action_async(did=self._did, + siid=siid, + aiid=aiid, + in_list=in_list) +>>>>>>> 83899f8 (fomatted code) def sub_device_state( - self, key: str, handler: Callable[[str, MIoTDeviceState], None] - ) -> int: + self, key: str, handler: Callable[[str, MIoTDeviceState], + None]) -> int: sub_id = self.__gen_sub_id() if key in self._device_state_sub_list: self._device_state_sub_list[key][str(sub_id)] = handler @@ -259,10 +293,16 @@ class MIoTDevice: if not sub_list: self._device_state_sub_list.pop(key, None) +<<<<<<< HEAD def sub_property( self, handler: Callable[[dict, Any], None], siid: int, piid: int ) -> int: key: str = f'p.{siid}.{piid}' +======= + def sub_property(self, handler: Callable[[dict, Any], None], siid: int, + piid: int) -> int: + key: str = f"p.{siid}.{piid}" +>>>>>>> 83899f8 (fomatted code) def _on_prop_changed(params: dict, ctx: Any) -> None: for handler in self._value_sub_list[key].values(): @@ -273,8 +313,15 @@ class MIoTDevice: self._value_sub_list[key][str(sub_id)] = handler else: self._value_sub_list[key] = {str(sub_id): handler} +<<<<<<< HEAD self.miot_client.sub_prop( did=self._did, handler=_on_prop_changed, siid=siid, piid=piid) +======= + self.miot_client.sub_prop(did=self._did, + handler=_on_prop_changed, + siid=siid, + piid=piid) +>>>>>>> 83899f8 (fomatted code) return sub_id def unsub_property(self, siid: int, piid: int, sub_id: int) -> None: @@ -287,10 +334,16 @@ class MIoTDevice: self.miot_client.unsub_prop(did=self._did, siid=siid, piid=piid) self._value_sub_list.pop(key, None) +<<<<<<< HEAD def sub_event( self, handler: Callable[[dict, Any], None], siid: int, eiid: int ) -> int: key: str = f'e.{siid}.{eiid}' +======= + def sub_event(self, handler: Callable[[dict, Any], None], siid: int, + eiid: int) -> int: + key: str = f"e.{siid}.{eiid}" +>>>>>>> 83899f8 (fomatted code) def _on_event_occurred(params: dict, ctx: Any) -> None: for handler in self._value_sub_list[key].values(): @@ -301,8 +354,15 @@ class MIoTDevice: self._value_sub_list[key][str(sub_id)] = handler else: self._value_sub_list[key] = {str(sub_id): handler} +<<<<<<< HEAD self.miot_client.sub_event( did=self._did, handler=_on_event_occurred, siid=siid, eiid=eiid) +======= + self.miot_client.sub_event(did=self._did, + handler=_on_event_occurred, + siid=siid, + eiid=eiid) +>>>>>>> 83899f8 (fomatted code) return sub_id def unsub_event(self, siid: int, eiid: int, sub_id: int) -> None: @@ -326,8 +386,13 @@ class MIoTDevice: manufacturer=self._manufacturer, suggested_area=self._suggested_area, configuration_url=( +<<<<<<< HEAD f'https://home.mi.com/webapp/content/baike/product/index.html?' f'model={self._model}') +======= + f"https://home.mi.com/webapp/content/baike/product/index.html?" + f"model={self._model}"), +>>>>>>> 83899f8 (fomatted code) ) @property @@ -337,6 +402,7 @@ class MIoTDevice: @property def did_tag(self) -> str: +<<<<<<< HEAD return slugify_did( cloud_server=self.miot_client.cloud_server, did=self._did) @@ -374,6 +440,37 @@ class MIoTDevice: f'{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_' f'{self._model_strs[-1][:20]}_{slugify_name(spec_name)}' f'_a_{siid}_{aiid}') +======= + return slugify_did(cloud_server=self.miot_client.cloud_server, + did=self._did) + + def gen_device_entity_id(self, ha_domain: str) -> str: + return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" + f"{self._model_strs[-1][:20]}") + + def gen_service_entity_id(self, ha_domain: str, siid: int, + description: str) -> str: + return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" + f"{self._model_strs[-1][:20]}_s_{siid}_{description}") + + def gen_prop_entity_id(self, ha_domain: str, spec_name: str, siid: int, + piid: int) -> str: + return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" + f"{self._model_strs[-1][:20]}_{slugify_name(spec_name)}" + f"_p_{siid}_{piid}") + + def gen_event_entity_id(self, ha_domain: str, spec_name: str, siid: int, + eiid: int) -> str: + return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" + f"{self._model_strs[-1][:20]}_{slugify_name(spec_name)}" + f"_e_{siid}_{eiid}") + + def gen_action_entity_id(self, ha_domain: str, spec_name: str, siid: int, + aiid: int) -> str: + return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" + f"{self._model_strs[-1][:20]}_{slugify_name(spec_name)}" + f"_a_{siid}_{aiid}") +>>>>>>> 83899f8 (fomatted code) @property def name(self) -> str: @@ -410,8 +507,7 @@ class MIoTDevice: self._action_list[action.platform].append(action) def parse_miot_device_entity( - self, spec_instance: MIoTSpecInstance - ) -> Optional[MIoTEntityData]: + self, spec_instance: MIoTSpecInstance) -> Optional[MIoTEntityData]: if spec_instance.name not in SPEC_DEVICE_TRANS_MAP: return None spec_name: str = spec_instance.name @@ -420,10 +516,16 @@ class MIoTDevice: if 'required' not in SPEC_DEVICE_TRANS_MAP[spec_name]: return None # 1. The device shall have all required services. +<<<<<<< HEAD required_services = SPEC_DEVICE_TRANS_MAP[spec_name]['required'].keys() if not { service.name for service in spec_instance.services }.issuperset(required_services): +======= + required_services = SPEC_DEVICE_TRANS_MAP[spec_name]["required"].keys() + if not {service.name for service in spec_instance.services + }.issuperset(required_services): +>>>>>>> 83899f8 (fomatted code) return None optional_services = SPEC_DEVICE_TRANS_MAP[spec_name]['optional'].keys() @@ -439,6 +541,7 @@ class MIoTDevice: # 2. The required service shall have all required properties # and actions. if service.name in required_services: +<<<<<<< HEAD required_properties = SPEC_DEVICE_TRANS_MAP[spec_name][ 'required'].get( service.name, {} @@ -510,6 +613,59 @@ class MIoTDevice: for prop in service.properties: if prop.name in set.union( set(required_properties.keys()), optional_properties): +======= + required_properties = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( + service.name, {}).get("required", + {}).get("properties", {})) + optional_properties = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( + service.name, {}).get("optional", + {}).get("properties", set({}))) + required_actions = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( + service.name, {}).get("required", + {}).get("actions", set({}))) + optional_actions = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( + service.name, {}).get("optional", + {}).get("actions", set({}))) + elif service.name in optional_services: + required_properties = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( + service.name, {}).get("required", + {}).get("properties", {})) + optional_properties = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( + service.name, {}).get("optional", + {}).get("properties", set({}))) + required_actions = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( + service.name, {}).get("required", + {}).get("actions", set({}))) + optional_actions = ( + SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( + service.name, {}).get("optional", + {}).get("actions", set({}))) + else: + continue + if not {prop.name for prop in service.properties if prop.access + }.issuperset(set(required_properties.keys())): + return None + if not {action.name for action in service.actions + }.issuperset(required_actions): + return None + # 3. The required property shall have all required access mode. + for prop in service.properties: + if prop.name in required_properties: + if not set(prop.access).issuperset( + required_properties[prop.name]): + return None + # property + for prop in service.properties: + if prop.name in set.union(set(required_properties.keys()), + optional_properties): +>>>>>>> 83899f8 (fomatted code) if prop.unit: prop.external_unit = self.unit_convert(prop.unit) # prop.icon = self.icon_convert(prop.unit) @@ -527,12 +683,17 @@ class MIoTDevice: return entity_data def parse_miot_service_entity( +<<<<<<< HEAD self, miot_service: MIoTSpecService ) -> Optional[MIoTEntityData]: if ( miot_service.platform or miot_service.name not in SPEC_SERVICE_TRANS_MAP ): +======= + self, miot_service: MIoTSpecService) -> Optional[MIoTEntityData]: + if miot_service.platform or miot_service.name not in SPEC_SERVICE_TRANS_MAP: +>>>>>>> 83899f8 (fomatted code) return None service_name = miot_service.name if isinstance(SPEC_SERVICE_TRANS_MAP[service_name], str): @@ -541,10 +702,16 @@ class MIoTDevice: return None # Required properties, required access mode required_properties: dict = SPEC_SERVICE_TRANS_MAP[service_name][ +<<<<<<< HEAD 'required'].get('properties', {}) if not { prop.name for prop in miot_service.properties if prop.access }.issuperset(set(required_properties.keys())): +======= + "required"].get("properties", {}) + if not {prop.name for prop in miot_service.properties if prop.access + }.issuperset(set(required_properties.keys())): +>>>>>>> 83899f8 (fomatted code) return None for prop in miot_service.properties: if prop.name in required_properties: @@ -557,10 +724,17 @@ class MIoTDevice: entity_data = MIoTEntityData(platform=platform, spec=miot_service) # Optional properties optional_properties = SPEC_SERVICE_TRANS_MAP[service_name][ +<<<<<<< HEAD 'optional'].get('properties', set({})) for prop in miot_service.properties: if prop.name in set.union( set(required_properties.keys()), optional_properties): +======= + "optional"].get("properties", set({})) + for prop in miot_service.properties: + if prop.name in set.union(set(required_properties.keys()), + optional_properties): +>>>>>>> 83899f8 (fomatted code) if prop.unit: prop.external_unit = self.unit_convert(prop.unit) # prop.icon = self.icon_convert(prop.unit) @@ -571,15 +745,24 @@ class MIoTDevice: miot_service.platform = platform # entity_category if entity_category := SPEC_SERVICE_TRANS_MAP[service_name].get( +<<<<<<< HEAD 'entity_category', None): +======= + "entity_category", None): +>>>>>>> 83899f8 (fomatted code) miot_service.entity_category = entity_category return entity_data def parse_miot_property_entity(self, miot_prop: MIoTSpecProperty) -> bool: +<<<<<<< HEAD if ( miot_prop.platform or miot_prop.name not in SPEC_PROP_TRANS_MAP['properties'] ): +======= + if (miot_prop.platform or + miot_prop.name not in SPEC_PROP_TRANS_MAP["properties"]): +>>>>>>> 83899f8 (fomatted code) return False prop_name = miot_prop.name if isinstance(SPEC_PROP_TRANS_MAP['properties'][prop_name], str): @@ -594,6 +777,7 @@ class MIoTDevice: if prop_access != (SPEC_PROP_TRANS_MAP[ 'entities'][platform]['access']): return False +<<<<<<< HEAD if miot_prop.format_.__name__ not in SPEC_PROP_TRANS_MAP[ 'entities'][platform]['format']: return False @@ -611,6 +795,22 @@ class MIoTDevice: # Priority: spec_modify.unit > unit_convert > specv2entity.unit miot_prop.external_unit = SPEC_PROP_TRANS_MAP['properties'][ prop_name]['unit_of_measurement'] +======= + if (miot_prop.format_.__name__ + not in SPEC_PROP_TRANS_MAP["entities"][platform]["format"]): + return False + miot_prop.device_class = SPEC_PROP_TRANS_MAP["properties"][prop_name][ + "device_class"] + # Optional params + if "state_class" in SPEC_PROP_TRANS_MAP["properties"][prop_name]: + miot_prop.state_class = SPEC_PROP_TRANS_MAP["properties"][ + prop_name]["state_class"] + if (not miot_prop.external_unit and "unit_of_measurement" + in SPEC_PROP_TRANS_MAP["properties"][prop_name]): + # Priority: spec_modify.unit > unit_convert > specv2entity.unit + miot_prop.external_unit = SPEC_PROP_TRANS_MAP["properties"][ + prop_name]["unit_of_measurement"] +>>>>>>> 83899f8 (fomatted code) # Priority: default.icon when device_class is set > spec_modify.icon # > icon_convert miot_prop.platform = platform @@ -811,7 +1011,18 @@ class MIoTDevice: if spec_unit in {'percentage'}: return 'mdi:percent' if spec_unit in { +<<<<<<< HEAD 'weeks', 'days', 'hour', 'hours', 'minutes', 'seconds', 'ms', 'μs' +======= + "weeks", + "days", + "hour", + "hours", + "minutes", + "seconds", + "ms", + "μs", +>>>>>>> 83899f8 (fomatted code) }: return 'mdi:clock' if spec_unit in {'celsius'}: @@ -868,9 +1079,8 @@ class MIoTDevice: self._sub_id += 1 return self._sub_id - def __on_device_state_changed( - self, did: str, state: MIoTDeviceState, ctx: Any - ) -> None: + def __on_device_state_changed(self, did: str, state: MIoTDeviceState, + ctx: Any) -> None: self._online = state == MIoTDeviceState.ONLINE for key, sub_list in self._device_state_sub_list.items(): for handler in sub_list.values(): @@ -890,6 +1100,7 @@ class MIoTServiceEntity(Entity): _state_sub_id: int _value_sub_ids: dict[str, int] +<<<<<<< HEAD _event_occurred_handler: Optional[ Callable[[MIoTSpecEvent, dict], None]] _prop_changed_subs: dict[ @@ -906,6 +1117,18 @@ class MIoTServiceEntity(Entity): or entity_data.spec is None ): raise MIoTDeviceError('init error, invalid params') +======= + _event_occurred_handler: Optional[Callable[[MIoTSpecEvent, dict], None]] + _prop_changed_subs: dict[MIoTSpecProperty, Callable[[MIoTSpecProperty, Any], + None]] + + _pending_write_ha_state_timer: Optional[asyncio.TimerHandle] + + def __init__(self, miot_device: MIoTDevice, + entity_data: MIoTEntityData) -> None: + if miot_device is None or entity_data is None or entity_data.spec is None: + raise MIoTDeviceError("init error, invalid params") +>>>>>>> 83899f8 (fomatted code) self.miot_device = miot_device self.entity_data = entity_data self._main_loop = miot_device.miot_client.main_loop @@ -921,8 +1144,13 @@ class MIoTServiceEntity(Entity): DOMAIN, siid=self.entity_data.spec.iid, description=self.entity_data.spec.description) self._attr_name = ( +<<<<<<< HEAD f'{"* "if self.entity_data.spec.proprietary else " "}' f'{self.entity_data.spec.description_trans}') +======= + f"{'* ' if self.entity_data.spec.proprietary else ' '}" + f"{self.entity_data.spec.description_trans}") +>>>>>>> 83899f8 (fomatted code) self._attr_entity_category = entity_data.spec.entity_category # Set entity attr self._attr_unique_id = self.entity_id @@ -940,8 +1168,12 @@ class MIoTServiceEntity(Entity): @property def event_occurred_handler( +<<<<<<< HEAD self ) -> Optional[Callable[[MIoTSpecEvent, dict], None]]: +======= + self) -> Optional[Callable[[MIoTSpecEvent, dict], None]]: +>>>>>>> 83899f8 (fomatted code) return self._event_occurred_handler @event_occurred_handler.setter @@ -949,9 +1181,14 @@ class MIoTServiceEntity(Entity): self._event_occurred_handler = func def sub_prop_changed( +<<<<<<< HEAD self, prop: MIoTSpecProperty, handler: Callable[[MIoTSpecProperty, Any], None] ) -> None: +======= + self, prop: MIoTSpecProperty, + handler: Callable[[MIoTSpecProperty, Any], None]) -> None: +>>>>>>> 83899f8 (fomatted code) if not prop or not handler: _LOGGER.error( 'sub_prop_changed error, invalid prop/handler') @@ -984,7 +1221,12 @@ class MIoTServiceEntity(Entity): key = f'e.{event.service.iid}.{event.iid}' self._value_sub_ids[key] = self.miot_device.sub_event( handler=self.__on_event_occurred, +<<<<<<< HEAD siid=event.service.iid, eiid=event.iid) +======= + siid=event.service.iid, + eiid=event.iid) +>>>>>>> 83899f8 (fomatted code) # Refresh value if self._attr_available: @@ -996,13 +1238,20 @@ class MIoTServiceEntity(Entity): self._pending_write_ha_state_timer = None state_id = 's.0' if isinstance(self.entity_data.spec, MIoTSpecService): +<<<<<<< HEAD state_id = f's.{self.entity_data.spec.iid}' self.miot_device.unsub_device_state( key=state_id, sub_id=self._state_sub_id) +======= + state_id = f"s.{self.entity_data.spec.iid}" + self.miot_device.unsub_device_state(key=state_id, + sub_id=self._state_sub_id) +>>>>>>> 83899f8 (fomatted code) # Unsub prop for prop in self.entity_data.props: if not prop.notifiable and not prop.readable: continue +<<<<<<< HEAD sub_id = self._value_sub_ids.pop( f'p.{prop.service.iid}.{prop.iid}', None) if sub_id: @@ -1015,6 +1264,22 @@ class MIoTServiceEntity(Entity): if sub_id: self.miot_device.unsub_event( siid=event.service.iid, eiid=event.iid, sub_id=sub_id) +======= + sub_id = self._value_sub_ids.pop(f"p.{prop.service.iid}.{prop.iid}", + None) + if sub_id: + self.miot_device.unsub_property(siid=prop.service.iid, + piid=prop.iid, + sub_id=sub_id) + # Unsub event + for event in self.entity_data.events: + sub_id = self._value_sub_ids.pop( + f"e.{event.service.iid}.{event.iid}", None) + if sub_id: + self.miot_device.unsub_event(siid=event.service.iid, + eiid=event.iid, + sub_id=sub_id) +>>>>>>> 83899f8 (fomatted code) def get_map_value( self, map_: Optional[dict[int, Any]], key: int @@ -1023,9 +1288,14 @@ class MIoTServiceEntity(Entity): return None return map_.get(key, None) +<<<<<<< HEAD def get_map_key( self, map_: Optional[dict[int, Any]], value: Any ) -> Optional[int]: +======= + def get_map_key(self, map_: Optional[dict[int, Any]], + value: Any) -> Optional[int]: +>>>>>>> 83899f8 (fomatted code) if map_ is None: return None for key, value_ in map_.items(): @@ -1041,9 +1311,14 @@ class MIoTServiceEntity(Entity): return None return self._prop_value_map.get(prop, None) +<<<<<<< HEAD def set_prop_value( self, prop: Optional[MIoTSpecProperty], value: Any ) -> None: +======= + def set_prop_value(self, prop: Optional[MIoTSpecProperty], + value: Any) -> None: +>>>>>>> 83899f8 (fomatted code) if not prop: _LOGGER.error( 'set_prop_value error, property is None, %s, %s', @@ -1062,6 +1337,7 @@ class MIoTServiceEntity(Entity): value = prop.value_format(value) value = prop.value_precision(value) if prop not in self.entity_data.props: +<<<<<<< HEAD raise RuntimeError( f'set property failed, unknown property, ' f'{self.entity_id}, {self.name}, {prop.name}') @@ -1069,13 +1345,24 @@ class MIoTServiceEntity(Entity): raise RuntimeError( f'set property failed, not writable, ' f'{self.entity_id}, {self.name}, {prop.name}') +======= + raise RuntimeError(f"set property failed, unknown property, " + f"{self.entity_id}, {self.name}, {prop.name}") + if not prop.writable: + raise RuntimeError(f"set property failed, not writable, " + f"{self.entity_id}, {self.name}, {prop.name}") +>>>>>>> 83899f8 (fomatted code) try: await self.miot_device.miot_client.set_prop_async( did=self.miot_device.did, siid=prop.service.iid, piid=prop.iid, value=value) except MIoTClientError as e: raise RuntimeError( +<<<<<<< HEAD f'{e}, {self.entity_id}, {self.name}, {prop.name}') from e +======= + f"{e}, {self.entity_id}, {self.name}, {prop.name}") from e +>>>>>>> 83899f8 (fomatted code) if update_value: self._prop_value_map[prop] = value if write_ha_state: @@ -1092,6 +1379,7 @@ class MIoTServiceEntity(Entity): prop = set_property.get("prop") value = set_property.get("value") if not prop: +<<<<<<< HEAD raise RuntimeError( f'set property failed, property is None, ' f'{self.entity_id}, {self.name}') @@ -1107,6 +1395,19 @@ class MIoTServiceEntity(Entity): raise RuntimeError( f'set property failed, not writable, ' f'{self.entity_id}, {self.name}, {prop.name}') +======= + raise RuntimeError(f"set property failed, property is None, " + f"{self.entity_id}, {self.name}") + set_property["value"] = prop.value_format(value) + if prop not in self.entity_data.props: + raise RuntimeError( + f"set property failed, unknown property, " + f"{self.entity_id}, {self.name}, {prop.name}") + if not prop.writable: + raise RuntimeError( + f"set property failed, not writable, " + f"{self.entity_id}, {self.name}, {prop.name}") +>>>>>>> 83899f8 (fomatted code) try: await self.miot_device.miot_client.set_props_async([{ "did": self.miot_device.did, @@ -1119,7 +1420,8 @@ class MIoTServiceEntity(Entity): f"{e}, {self.entity_id}, {self.name}, {'&'.join([set_property['prop'].name for set_property in set_properties_list])}") from e if update_value: for set_property in set_properties_list: - self._prop_value_map[set_property["prop"]] = set_property["value"] + self._prop_value_map[ + set_property["prop"]] = set_property["value"] if write_ha_state: self.async_write_ha_state() return True @@ -1140,29 +1442,45 @@ class MIoTServiceEntity(Entity): 'get property failed, not readable, %s, %s, %s', self.entity_id, self.name, prop.name) return None +<<<<<<< HEAD value: Any = prop.value_format( await self.miot_device.miot_client.get_prop_async( did=self.miot_device.did, siid=prop.service.iid, piid=prop.iid)) value = prop.eval_expr(value) result = prop.value_precision(value) +======= + result = prop.value_format(await + self.miot_device.miot_client.get_prop_async( + did=self.miot_device.did, + siid=prop.service.iid, + piid=prop.iid)) +>>>>>>> 83899f8 (fomatted code) if result != self._prop_value_map[prop]: self._prop_value_map[prop] = result self.async_write_ha_state() return result - async def action_async( - self, action: MIoTSpecAction, in_list: Optional[list] = None - ) -> bool: + async def action_async(self, + action: MIoTSpecAction, + in_list: Optional[list] = None) -> bool: if not action: raise RuntimeError( +<<<<<<< HEAD f'action failed, action is None, {self.entity_id}, {self.name}') +======= + f"action failed, action is None, {self.entity_id}, {self.name}") +>>>>>>> 83899f8 (fomatted code) try: await self.miot_device.miot_client.action_async( did=self.miot_device.did, siid=action.service.iid, aiid=action.iid, in_list=in_list or []) except MIoTClientError as e: raise RuntimeError( +<<<<<<< HEAD f'{e}, {self.entity_id}, {self.name}, {action.name}') from e +======= + f"{e}, {self.entity_id}, {self.name}, {action.name}") from e +>>>>>>> 83899f8 (fomatted code) return True def __on_properties_changed(self, params: dict, ctx: Any) -> None: @@ -1188,10 +1506,15 @@ class MIoTServiceEntity(Entity): if self._event_occurred_handler is None: return for event in self.entity_data.events: +<<<<<<< HEAD if ( event.iid != params['eiid'] or event.service.iid != params['siid'] ): +======= + if event.iid != params["eiid"] or event.service.iid != params[ + "siid"]: +>>>>>>> 83899f8 (fomatted code) continue trans_arg = {} for item in params['arguments']: @@ -1202,9 +1525,14 @@ class MIoTServiceEntity(Entity): self._event_occurred_handler(event, trans_arg) break +<<<<<<< HEAD def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: +======= + def __on_device_state_changed(self, key: str, + state: MIoTDeviceState) -> None: +>>>>>>> 83899f8 (fomatted code) state_new = state == MIoTDeviceState.ONLINE if state_new == self._attr_available: return @@ -1263,15 +1591,27 @@ class MIoTPropertyEntity(Entity): self._pending_write_ha_state_timer = None # Gen entity_id self.entity_id = self.miot_device.gen_prop_entity_id( +<<<<<<< HEAD ha_domain=DOMAIN, spec_name=spec.name, siid=spec.service.iid, piid=spec.iid) +======= + ha_domain=DOMAIN, + spec_name=spec.name, + siid=spec.service.iid, + piid=spec.iid) +>>>>>>> 83899f8 (fomatted code) # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False self._attr_has_entity_name = True self._attr_name = ( +<<<<<<< HEAD f'{"* "if self.spec.proprietary else " "}' f'{self.service.description_trans} {spec.description_trans}') +======= + f"{'* ' if self.spec.proprietary else ' '}" + f"{self.service.description_trans} {spec.description_trans}") +>>>>>>> 83899f8 (fomatted code) self._attr_available = miot_device.online _LOGGER.info( @@ -1291,7 +1631,12 @@ class MIoTPropertyEntity(Entity): # Sub value changed self._value_sub_id = self.miot_device.sub_property( handler=self.__on_value_changed, +<<<<<<< HEAD siid=self.service.iid, piid=self.spec.iid) +======= + siid=self.service.iid, + piid=self.spec.iid) +>>>>>>> 83899f8 (fomatted code) # Refresh value if self._attr_available: self.__request_refresh_prop() @@ -1301,11 +1646,19 @@ class MIoTPropertyEntity(Entity): self._pending_write_ha_state_timer.cancel() self._pending_write_ha_state_timer = None self.miot_device.unsub_device_state( +<<<<<<< HEAD key=f'{ self.service.iid}.{self.spec.iid}', sub_id=self._state_sub_id) self.miot_device.unsub_property( siid=self.service.iid, piid=self.spec.iid, sub_id=self._value_sub_id) +======= + key=f"{self.service.iid}.{self.spec.iid}", + sub_id=self._state_sub_id) + self.miot_device.unsub_property(siid=self.service.iid, + piid=self.spec.iid, + sub_id=self._value_sub_id) +>>>>>>> 83899f8 (fomatted code) def get_vlist_description(self, value: Any) -> Optional[str]: if not self._value_list: @@ -1337,17 +1690,28 @@ class MIoTPropertyEntity(Entity): async def get_property_async(self) -> Any: if not self.spec.readable: +<<<<<<< HEAD _LOGGER.error( 'get property failed, not readable, %s, %s', self.entity_id, self.name) +======= + _LOGGER.error("get property failed, not readable, %s, %s", + self.entity_id, self.name) +>>>>>>> 83899f8 (fomatted code) return None value: Any = self.spec.value_format( await self.miot_device.miot_client.get_prop_async( +<<<<<<< HEAD did=self.miot_device.did, siid=self.spec.service.iid, piid=self.spec.iid)) value = self.spec.eval_expr(value) result = self.spec.value_precision(value) return result +======= + did=self.miot_device.did, + siid=self.spec.service.iid, + piid=self.spec.iid)) +>>>>>>> 83899f8 (fomatted code) def __on_value_changed(self, params: dict, ctx: Any) -> None: _LOGGER.debug('property changed, %s', params) @@ -1357,9 +1721,14 @@ class MIoTPropertyEntity(Entity): if not self._pending_write_ha_state_timer: self.async_write_ha_state() +<<<<<<< HEAD def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: +======= + def __on_device_state_changed(self, key: str, + state: MIoTDeviceState) -> None: +>>>>>>> 83899f8 (fomatted code) self._attr_available = state == MIoTDeviceState.ONLINE if not self._attr_available: self.async_write_ha_state() @@ -1370,7 +1739,12 @@ class MIoTPropertyEntity(Entity): def __request_refresh_prop(self) -> None: if self.spec.readable: self.miot_device.miot_client.request_refresh_prop( +<<<<<<< HEAD did=self.miot_device.did, siid=self.service.iid, +======= + did=self.miot_device.did, + siid=self.service.iid, +>>>>>>> 83899f8 (fomatted code) piid=self.spec.iid) if self._pending_write_ha_state_timer: self._pending_write_ha_state_timer.cancel() @@ -1405,15 +1779,27 @@ class MIoTEventEntity(Entity): self._main_loop = miot_device.miot_client.main_loop # Gen entity_id self.entity_id = self.miot_device.gen_event_entity_id( +<<<<<<< HEAD ha_domain=DOMAIN, spec_name=spec.name, siid=spec.service.iid, eiid=spec.iid) +======= + ha_domain=DOMAIN, + spec_name=spec.name, + siid=spec.service.iid, + eiid=spec.iid) +>>>>>>> 83899f8 (fomatted code) # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False self._attr_has_entity_name = True self._attr_name = ( +<<<<<<< HEAD f'{"* "if self.spec.proprietary else " "}' f'{self.service.description_trans} {spec.description_trans}') +======= + f"{'* ' if self.spec.proprietary else ' '}" + f"{self.service.description_trans} {spec.description_trans}") +>>>>>>> 83899f8 (fomatted code) self._attr_available = miot_device.online self._attr_event_types = [spec.description_trans] @@ -1440,6 +1826,7 @@ class MIoTEventEntity(Entity): # Sub value changed self._value_sub_id = self.miot_device.sub_event( handler=self.__on_event_occurred, +<<<<<<< HEAD siid=self.service.iid, eiid=self.spec.iid) async def async_will_remove_from_hass(self) -> None: @@ -1449,11 +1836,24 @@ class MIoTEventEntity(Entity): self.miot_device.unsub_event( siid=self.service.iid, eiid=self.spec.iid, sub_id=self._value_sub_id) +======= + siid=self.service.iid, + eiid=self.spec.iid) + + async def async_will_remove_from_hass(self) -> None: + self.miot_device.unsub_device_state( + key=f"event.{self.service.iid}.{self.spec.iid}", + sub_id=self._state_sub_id) + self.miot_device.unsub_event(siid=self.service.iid, + eiid=self.spec.iid, + sub_id=self._value_sub_id) +>>>>>>> 83899f8 (fomatted code) @abstractmethod - def on_event_occurred( - self, name: str, arguments: dict[str, Any] | None = None - ) -> None: ... + def on_event_occurred(self, + name: str, + arguments: dict[str, Any] | None = None) -> None: + ... def __on_event_occurred(self, params: dict, ctx: Any) -> None: _LOGGER.debug('event occurred, %s', params) @@ -1462,6 +1862,7 @@ class MIoTEventEntity(Entity): try: if 'value' not in item: continue +<<<<<<< HEAD if 'piid' in item: trans_arg[self._arguments_map[item['piid']]] = item[ 'value'] @@ -1469,6 +1870,12 @@ class MIoTEventEntity(Entity): isinstance(item['value'], list) and len(item['value']) == len(self.spec.argument) ): +======= + if "piid" in item: + trans_arg[self._arguments_map[item["piid"]]] = item["value"] + elif isinstance(item["value"], list) and len( + item["value"]) == len(self.spec.argument): +>>>>>>> 83899f8 (fomatted code) # Dirty fix for cloud multi-arguments trans_arg = { prop.description_trans: item['value'][index] @@ -1477,6 +1884,7 @@ class MIoTEventEntity(Entity): break except KeyError as error: _LOGGER.debug( +<<<<<<< HEAD 'on event msg, invalid args, %s, %s, %s', self.entity_id, params, error) self.on_event_occurred( @@ -1486,6 +1894,19 @@ class MIoTEventEntity(Entity): def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: +======= + "on event msg, invalid args, %s, %s, %s", + self.entity_id, + params, + error, + ) + self.on_event_occurred(name=self.spec.description_trans, + arguments=trans_arg) + self.async_write_ha_state() + + def __on_device_state_changed(self, key: str, + state: MIoTDeviceState) -> None: +>>>>>>> 83899f8 (fomatted code) state_new = state == MIoTDeviceState.ONLINE if state_new == self._attr_available: return @@ -1516,15 +1937,27 @@ class MIoTActionEntity(Entity): self._state_sub_id = 0 # Gen entity_id self.entity_id = self.miot_device.gen_action_entity_id( +<<<<<<< HEAD ha_domain=DOMAIN, spec_name=spec.name, siid=spec.service.iid, aiid=spec.iid) +======= + ha_domain=DOMAIN, + spec_name=spec.name, + siid=spec.service.iid, + aiid=spec.iid) +>>>>>>> 83899f8 (fomatted code) # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False self._attr_has_entity_name = True self._attr_name = ( +<<<<<<< HEAD f'{"* "if self.spec.proprietary else " "}' f'{self.service.description_trans} {spec.description_trans}') +======= + f"{'* ' if self.spec.proprietary else ' '}" + f"{self.service.description_trans} {spec.description_trans}") +>>>>>>> 83899f8 (fomatted code) self._attr_available = miot_device.online _LOGGER.debug( @@ -1543,12 +1976,20 @@ class MIoTActionEntity(Entity): async def async_will_remove_from_hass(self) -> None: self.miot_device.unsub_device_state( +<<<<<<< HEAD key=f'a.{ self.service.iid}.{self.spec.iid}', sub_id=self._state_sub_id) async def action_async( self, in_list: Optional[list] = None ) -> Optional[list]: +======= + key=f"a.{self.service.iid}.{self.spec.iid}", + sub_id=self._state_sub_id) + + async def action_async(self, + in_list: Optional[list] = None) -> Optional[list]: +>>>>>>> 83899f8 (fomatted code) try: return await self.miot_device.miot_client.action_async( did=self.miot_device.did, @@ -1558,9 +1999,14 @@ class MIoTActionEntity(Entity): except MIoTClientError as e: raise RuntimeError(f'{e}, {self.entity_id}, {self.name}') from e +<<<<<<< HEAD def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: +======= + def __on_device_state_changed(self, key: str, + state: MIoTDeviceState) -> None: +>>>>>>> 83899f8 (fomatted code) state_new = state == MIoTDeviceState.ONLINE if state_new == self._attr_available: return diff --git a/custom_components/xiaomi_home/miot/miot_lan.py b/custom_components/xiaomi_home/miot/miot_lan.py index 8e95b32..48a5e2d 100644 --- a/custom_components/xiaomi_home/miot/miot_lan.py +++ b/custom_components/xiaomi_home/miot/miot_lan.py @@ -71,7 +71,6 @@ from .miot_mdns import MipsService, MipsServiceState from .common import ( randomize_float, load_yaml_file, gen_absolute_path, MIoTMatcher) - _LOGGER = logging.getLogger(__name__) @@ -164,6 +163,7 @@ class _MIoTLanDevice: # All functions SHOULD be called from the internal loop +<<<<<<< HEAD def __init__( self, manager: 'MIoTLan', @@ -171,13 +171,25 @@ class _MIoTLanDevice: token: str, ip: Optional[str] = None ) -> None: +======= + def __init__(self, + manager: "MIoTLan", + did: str, + token: str, + ip: Optional[str] = None) -> None: +>>>>>>> 83899f8 (fomatted code) self._manager: MIoTLan = manager self.did = did self.token = bytes.fromhex(token) aes_key: bytes = self.__md5(self.token) aex_iv: bytes = self.__md5(aes_key + self.token) +<<<<<<< HEAD self.cipher = Cipher( algorithms.AES128(aes_key), modes.CBC(aex_iv), default_backend()) +======= + self.cipher = Cipher(algorithms.AES128(aes_key), modes.CBC(aex_iv), + default_backend()) +>>>>>>> 83899f8 (fomatted code) self.ip = ip self.offset = 0 self.subscribed = False @@ -202,8 +214,13 @@ class _MIoTLanDevice: self.ip = ip if self._if_name != if_name: self._if_name = if_name +<<<<<<< HEAD _LOGGER.info( 'device if_name change, %s, %s', self._if_name, self.did) +======= + _LOGGER.info("device if_name change, %s, %s", self._if_name, + self.did) +>>>>>>> 83899f8 (fomatted code) self.__update_keep_alive(state=_MIoTLanDeviceState.FRESH) @property @@ -216,27 +233,48 @@ class _MIoTLanDevice: return self._online = online self._manager.broadcast_device_state( +<<<<<<< HEAD did=self.did, state={ 'online': self._online, 'push_available': self.subscribed}) +======= + did=self.did, + state={ + "online": self._online, + "push_available": self.subscribed + }, + ) +>>>>>>> 83899f8 (fomatted code) @property def if_name(self) -> Optional[str]: return self._if_name +<<<<<<< HEAD def gen_packet( self, out_buffer: bytearray, clear_data: dict, did: str, offset: int ) -> int: clear_bytes = json.dumps(clear_data, ensure_ascii=False).encode('utf-8') +======= + def gen_packet(self, out_buffer: bytearray, clear_data: dict, did: str, + offset: int) -> int: + clear_bytes = json.dumps(clear_data, ensure_ascii=False).encode("utf-8") +>>>>>>> 83899f8 (fomatted code) padder = padding.PKCS7(algorithms.AES128.block_size).padder() padded_data = padder.update(clear_bytes) + padder.finalize() if len(padded_data) + self.OT_HEADER_LEN > len(out_buffer): raise ValueError('rpc too long') encryptor = self.cipher.encryptor() encrypted_data = encryptor.update(padded_data) + encryptor.finalize() +<<<<<<< HEAD data_len: int = len(encrypted_data)+self.OT_HEADER_LEN out_buffer[:32] = struct.pack( '>HHQI16s', self.OT_HEADER, data_len, int(did), offset, self.token) +======= + data_len: int = len(encrypted_data) + self.OT_HEADER_LEN + out_buffer[:32] = struct.pack(">HHQI16s", self.OT_HEADER, data_len, + int(did), offset, self.token) +>>>>>>> 83899f8 (fomatted code) out_buffer[32:data_len] = encrypted_data msg_md5: bytes = self.__md5(out_buffer[0:data_len]) out_buffer[16:32] = msg_md5 @@ -250,8 +288,13 @@ class _MIoTLanDevice: if md5_orig != md5_calc: raise ValueError(f'invalid md5, {md5_orig}, {md5_calc}') decryptor = self.cipher.decryptor() +<<<<<<< HEAD decrypted_padded_data = decryptor.update( encrypted_data[32:data_len]) + decryptor.finalize() +======= + decrypted_padded_data = (decryptor.update(encrypted_data[32:data_len]) + + decryptor.finalize()) +>>>>>>> 83899f8 (fomatted code) unpadder = padding.PKCS7(algorithms.AES128.block_size).unpadder() decrypted_data = unpadder.update( decrypted_padded_data) + unpadder.finalize() @@ -302,8 +345,17 @@ class _MIoTLanDevice: timeout_ms=5000) self.subscribed = False self._manager.broadcast_device_state( +<<<<<<< HEAD did=self.did, state={ 'online': self._online, 'push_available': self.subscribed}) +======= + did=self.did, + state={ + "online": self._online, + "push_available": self.subscribed + }, + ) +>>>>>>> 83899f8 (fomatted code) def on_delete(self) -> None: if self._ka_timer: @@ -315,15 +367,21 @@ class _MIoTLanDevice: _LOGGER.debug('miot lan device delete, %s', self.did) def update_info(self, info: dict) -> None: +<<<<<<< HEAD if ( 'token' in info and len(info['token']) == 32 and info['token'].upper() != self.token.hex().upper() ): +======= + if ("token" in info and len(info["token"]) == 32 and + info["token"].upper() != self.token.hex().upper()): +>>>>>>> 83899f8 (fomatted code) # Update token self.token = bytes.fromhex(info['token']) aes_key: bytes = self.__md5(self.token) aex_iv: bytes = self.__md5(aes_key + self.token) +<<<<<<< HEAD self.cipher = Cipher( algorithms.AES128(aes_key), modes.CBC(aex_iv), default_backend()) @@ -336,10 +394,21 @@ class _MIoTLanDevice: or msg['result']['code'] != 0 ): _LOGGER.error('subscribe device error, %s, %s', self.did, msg) +======= + self.cipher = Cipher(algorithms.AES128(aes_key), modes.CBC(aex_iv), + default_backend()) + _LOGGER.debug("update token, %s", self.did) + + def __subscribe_handler(self, msg: dict, sub_ts: int) -> None: + if ("result" not in msg or "code" not in msg["result"] or + msg["result"]["code"] != 0): + _LOGGER.error("subscribe device error, %s, %s", self.did, msg) +>>>>>>> 83899f8 (fomatted code) return self.subscribed = True self.sub_ts = sub_ts self._manager.broadcast_device_state( +<<<<<<< HEAD did=self.did, state={ 'online': self._online, 'push_available': self.subscribed}) _LOGGER.info('subscribe success, %s, %s', self._if_name, self.did) @@ -351,6 +420,20 @@ class _MIoTLanDevice: or msg['result']['code'] != 0 ): _LOGGER.error('unsubscribe device error, %s, %s', self.did, msg) +======= + did=self.did, + state={ + "online": self._online, + "push_available": self.subscribed + }, + ) + _LOGGER.info("subscribe success, %s, %s", self._if_name, self.did) + + def __unsubscribe_handler(self, msg: dict, ctx: Any) -> None: + if ("result" not in msg or "code" not in msg["result"] or + msg["result"]["code"] != 0): + _LOGGER.error("unsubscribe device error, %s, %s", self.did, msg) +>>>>>>> 83899f8 (fomatted code) return _LOGGER.info('unsubscribe success, %s, %s', self._if_name, self.did) @@ -368,6 +451,7 @@ class _MIoTLanDevice: self._ka_internal = self.KA_INTERVAL_MIN self.__change_online(True) self._ka_timer = self._manager.internal_loop.call_later( +<<<<<<< HEAD self.__get_next_ka_timeout(), self.__update_keep_alive, _MIoTLanDeviceState.PING1) case ( @@ -375,6 +459,14 @@ class _MIoTLanDevice: | _MIoTLanDeviceState.PING2 | _MIoTLanDeviceState.PING3 ): +======= + self.__get_next_ka_timeout(), + self.__update_keep_alive, + _MIoTLanDeviceState.PING1, + ) + case (_MIoTLanDeviceState.PING1 | _MIoTLanDeviceState.PING2 | + _MIoTLanDeviceState.PING3): +>>>>>>> 83899f8 (fomatted code) # Set the timer first to avoid Any early returns self._ka_timer = self._manager.internal_loop.call_later( self.FAST_PING_INTERVAL, self.__update_keep_alive, @@ -411,6 +503,7 @@ class _MIoTLanDevice: if not online: self.online = False else: +<<<<<<< HEAD if ( len(self._online_offline_history) < self.NETWORK_UNSTABLE_CNT_TH or ( @@ -424,6 +517,18 @@ class _MIoTLanDevice: self._manager.internal_loop.call_later( self.NETWORK_UNSTABLE_RESUME_TH, self.__online_resume_handler)) +======= + if len(self._online_offline_history + ) < self.NETWORK_UNSTABLE_CNT_TH or ( + ts_now - self._online_offline_history[0]["ts"] + > self.NETWORK_UNSTABLE_TIME_TH): + self.online = True + else: + _LOGGER.info("unstable device detected, %s", self.did) + self._online_offline_timer = self._manager.internal_loop.call_later( + self.NETWORK_UNSTABLE_RESUME_TH, + self.__online_resume_handler) +>>>>>>> 83899f8 (fomatted code) def __online_resume_handler(self) -> None: _LOGGER.info('unstable resume threshold past, %s', self.did) @@ -502,6 +607,7 @@ class MIoTLan: self._net_ifs = set(net_ifs) self._network = network self._network.sub_network_info( +<<<<<<< HEAD key='miot_lan', handler=self.__on_network_info_change_external_async) self._mips_service = mips_service @@ -518,6 +624,23 @@ class MIoTLan: b'!1\x00\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFMDID') probe_bytes[20:28] = struct.pack('>Q', int(self._virtual_did)) probe_bytes[28:32] = b'\x00\x00\x00\x00' +======= + key="miot_lan", + handler=self.__on_network_info_change_external_async) + self._mips_service = mips_service + self._mips_service.sub_service_change( + key="miot_lan", group_id="*", handler=self.__on_mips_service_change) + self._enable_subscribe = enable_subscribe + self._virtual_did = (str(virtual_did) if + (virtual_did is not None) else str( + secrets.randbits(64))) + # Init socket probe message + probe_bytes = bytearray(self.OT_PROBE_LEN) + probe_bytes[:20] = ( + b"!1\x00\x20\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffMDID") + probe_bytes[20:28] = struct.pack(">Q", int(self._virtual_did)) + probe_bytes[28:32] = b"\x00\x00\x00\x00" +>>>>>>> 83899f8 (fomatted code) self._probe_msg = bytes(probe_bytes) self._read_buffer = bytearray(self.OT_MSG_LEN) self._write_buffer = bytearray(self.OT_MSG_LEN) @@ -540,6 +663,7 @@ class MIoTLan: self._init_lock = asyncio.Lock() self._init_done = False +<<<<<<< HEAD if ( len(self._mips_service.get_services()) == 0 and len(self._net_ifs) > 0 @@ -554,6 +678,18 @@ class MIoTLan: raise MIoTLanError( 'MIoT lan is not ready', MIoTErrorCode.CODE_LAN_UNAVAILABLE) +======= + if len(self._mips_service.get_services()) == 0 and len( + self._net_ifs) > 0: + _LOGGER.info("no central hub gateway service, init miot lan") + self._main_loop.call_later( + 0, lambda: self._main_loop.create_task(self.init_async())) + + def __assert_service_ready(self) -> None: + if not self._init_done: + raise MIoTLanError("MIoT lan is not ready", + MIoTErrorCode.CODE_LAN_UNAVAILABLE) +>>>>>>> 83899f8 (fomatted code) @property def virtual_did(self) -> str: @@ -606,14 +742,23 @@ class MIoTLan: self._init_done = True for handler in list(self._lan_state_sub_map.values()): self._main_loop.create_task(handler(True)) +<<<<<<< HEAD _LOGGER.info( 'miot lan init, %s ,%s', self._net_ifs, self._available_net_ifs) +======= + _LOGGER.info("miot lan init, %s ,%s", self._net_ifs, + self._available_net_ifs) +>>>>>>> 83899f8 (fomatted code) def __internal_loop_thread(self) -> None: _LOGGER.info('miot lan thread start') self.__init_socket() self._scan_timer = self._internal_loop.call_later( +<<<<<<< HEAD int(3*random.random()), self.__scan_devices) +======= + int(3 * random.random()), self.__scan_devices) +>>>>>>> 83899f8 (fomatted code) self._internal_loop.run_forever() _LOGGER.info('miot lan thread exit') @@ -683,7 +828,11 @@ class MIoTLan: return self._internal_loop.call_soon_threadsafe( self.__update_subscribe_option, +<<<<<<< HEAD {'enable_subscribe': enable_subscribe}) +======= + {"enable_subscribe": enable_subscribe}) +>>>>>>> 83899f8 (fomatted code) def update_devices(self, devices: dict[str, dict]) -> bool: _LOGGER.info('update devices, %s', devices) @@ -701,9 +850,14 @@ class MIoTLan: self.__delete_devices, devices) return True +<<<<<<< HEAD def sub_lan_state( self, key: str, handler: Callable[[bool], Coroutine] ) -> None: +======= + def sub_lan_state(self, key: str, handler: Callable[[bool], + Coroutine]) -> None: +>>>>>>> 83899f8 (fomatted code) self._lan_state_sub_map[key] = handler def unsub_lan_state(self, key: str) -> None: @@ -718,8 +872,15 @@ class MIoTLan: return False self._internal_loop.call_soon_threadsafe( self.__sub_device_state, +<<<<<<< HEAD _MIoTLanSubDeviceData( key=key, handler=handler, handler_ctx=handler_ctx)) +======= + _MIoTLanSubDeviceData(key=key, + handler=handler, + handler_ctx=handler_ctx), + ) +>>>>>>> 83899f8 (fomatted code) return True @final @@ -748,6 +909,7 @@ class MIoTLan: f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') self._internal_loop.call_soon_threadsafe( self.__sub_broadcast, +<<<<<<< HEAD _MIoTLanRegisterBroadcastData( key=key, handler=handler, handler_ctx=handler_ctx)) return True @@ -759,6 +921,19 @@ class MIoTLan: siid: Optional[int] = None, piid: Optional[int] = None ) -> bool: +======= + _MIoTLanRegisterBroadcastData(key=key, + handler=handler, + handler_ctx=handler_ctx), + ) + return True + + @final + def unsub_prop(self, + did: str, + siid: Optional[int] = None, + piid: Optional[int] = None) -> bool: +>>>>>>> 83899f8 (fomatted code) if not self._init_done: return False if not self._enable_subscribe: @@ -767,8 +942,12 @@ class MIoTLan: f'{did}/p/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') self._internal_loop.call_soon_threadsafe( +<<<<<<< HEAD self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) +======= + self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) +>>>>>>> 83899f8 (fomatted code) return True @final @@ -789,6 +968,7 @@ class MIoTLan: f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') self._internal_loop.call_soon_threadsafe( self.__sub_broadcast, +<<<<<<< HEAD _MIoTLanRegisterBroadcastData( key=key, handler=handler, handler_ctx=handler_ctx)) return True @@ -800,6 +980,19 @@ class MIoTLan: siid: Optional[int] = None, eiid: Optional[int] = None ) -> bool: +======= + _MIoTLanRegisterBroadcastData(key=key, + handler=handler, + handler_ctx=handler_ctx), + ) + return True + + @final + def unsub_event(self, + did: str, + siid: Optional[int] = None, + eiid: Optional[int] = None) -> bool: +>>>>>>> 83899f8 (fomatted code) if not self._init_done: return False if not self._enable_subscribe: @@ -808,16 +1001,23 @@ class MIoTLan: f'{did}/e/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') self._internal_loop.call_soon_threadsafe( +<<<<<<< HEAD self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) +======= + self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) +>>>>>>> 83899f8 (fomatted code) return True @final - async def get_prop_async( - self, did: str, siid: int, piid: int, timeout_ms: int = 10000 - ) -> Any: + async def get_prop_async(self, + did: str, + siid: int, + piid: int, + timeout_ms: int = 10000) -> Any: self.__assert_service_ready() result_obj = await self.__call_api_async( +<<<<<<< HEAD did=did, msg={ 'method': 'get_properties', 'params': [{'did': did, 'siid': siid, 'piid': piid}] @@ -854,14 +1054,71 @@ class MIoTLan: ): return result_obj['result'][0] if 'code' in result_obj: +======= + did=did, + msg={ + "method": "get_properties", + "params": [{ + "did": did, + "siid": siid, + "piid": piid + }], + }, + timeout_ms=timeout_ms, + ) + + if (result_obj and "result" in result_obj and + len(result_obj["result"]) == 1 and + "did" in result_obj["result"][0] and + result_obj["result"][0]["did"] == did): + return result_obj["result"][0].get("value", None) + return None + + @final + async def set_prop_async(self, + did: str, + siid: int, + piid: int, + value: Any, + timeout_ms: int = 10000) -> dict: + self.__assert_service_ready() + result_obj = await self.__call_api_async( + did=did, + msg={ + "method": + "set_properties", + "params": [{ + "did": did, + "siid": siid, + "piid": piid, + "value": value + }], + }, + timeout_ms=timeout_ms, + ) + if result_obj: + if ("result" in result_obj and len(result_obj["result"]) == 1 and + "did" in result_obj["result"][0] and + result_obj["result"][0]["did"] == did and + "code" in result_obj["result"][0]): + return result_obj["result"][0] + if "code" in result_obj: +>>>>>>> 83899f8 (fomatted code) return result_obj raise MIoTError('Invalid result', MIoTErrorCode.CODE_INTERNAL_ERROR) @final +<<<<<<< HEAD async def set_props_async( self,did: str,props_list: List[Dict[str, Any]], timeout_ms: int = 10000) -> dict: # props_list = [{'did': did, 'siid': siid, 'piid': piid, 'value': value}......] +======= + async def set_props_async(self, + did: str, + props_list: List[Dict[str, Any]], + timeout_ms: int = 10000) -> dict: +>>>>>>> 83899f8 (fomatted code) self.__assert_service_ready() result_obj = await self.__call_api_async( did=did, msg={ @@ -869,6 +1126,7 @@ class MIoTLan: 'params': props_list, }, timeout_ms=timeout_ms) if result_obj: +<<<<<<< HEAD if ( 'result' in result_obj and len(result_obj['result']) == len(props_list) @@ -892,6 +1150,41 @@ class MIoTLan: 'params': { 'did': did, 'siid': siid, 'aiid': aiid, 'in': in_list} }, timeout_ms=timeout_ms) +======= + if ("result" in result_obj and + len(result_obj["result"]) == len(props_list) and + result_obj["result"][0].get("did") == did and + all("code" in item for item in result_obj["result"])): + return result_obj["result"] + if "error" in result_obj: + return result_obj["error"] + return { + "code": MIoTErrorCode.CODE_INTERNAL_ERROR.value, + "message": "Invalid result", + } + + @final + async def action_async(self, + did: str, + siid: int, + aiid: int, + in_list: list, + timeout_ms: int = 10000) -> dict: + self.__assert_service_ready() + result_obj = await self.__call_api_async( + did=did, + msg={ + "method": "action", + "params": { + "did": did, + "siid": siid, + "aiid": aiid, + "in": in_list + }, + }, + timeout_ms=timeout_ms, + ) +>>>>>>> 83899f8 (fomatted code) if result_obj: if 'result' in result_obj and 'code' in result_obj['result']: return result_obj['result'] @@ -900,9 +1193,14 @@ class MIoTLan: raise MIoTError('Invalid result', MIoTErrorCode.CODE_INTERNAL_ERROR) @final +<<<<<<< HEAD async def get_dev_list_async( self, timeout_ms: int = 10000 ) -> dict[str, dict]: +======= + async def get_dev_list_async(self, + timeout_ms: int = 10000) -> dict[str, dict]: +>>>>>>> 83899f8 (fomatted code) if not self._init_done: return {} @@ -913,20 +1211,30 @@ class MIoTLan: fut: asyncio.Future = self._main_loop.create_future() self._internal_loop.call_soon_threadsafe( self.__get_dev_list, +<<<<<<< HEAD _MIoTLanGetDevListData( handler=get_device_list_handler, handler_ctx=fut, timeout_ms=timeout_ms)) +======= + _MIoTLanGetDevListData(handler=get_device_list_handler, + handler_ctx=fut, + timeout_ms=timeout_ms), + ) +>>>>>>> 83899f8 (fomatted code) return await fut - async def __call_api_async( - self, did: str, msg: dict, timeout_ms: int = 10000 - ) -> dict: + async def __call_api_async(self, + did: str, + msg: dict, + timeout_ms: int = 10000) -> dict: + def call_api_handler(msg: dict, fut: asyncio.Future): self._main_loop.call_soon_threadsafe( fut.set_result, msg) fut: asyncio.Future = self._main_loop.create_future() +<<<<<<< HEAD self._internal_loop.call_soon_threadsafe( self.__call_api, did, msg, call_api_handler, fut, timeout_ms) return await fut @@ -938,6 +1246,17 @@ class MIoTLan: ) -> None: _LOGGER.info( 'on network info change, status: %s, info: %s', status, info) +======= + self._internal_loop.call_soon_threadsafe(self.__call_api, did, msg, + call_api_handler, fut, + timeout_ms) + return await fut + + async def __on_network_info_change_external_async( + self, status: InterfaceStatus, info: NetworkInfo) -> None: + _LOGGER.info("on network info change, status: %s, info: %s", status, + info) +>>>>>>> 83899f8 (fomatted code) available_net_ifs = set() for if_name in list(self._network.network_info.keys()): available_net_ifs.add(if_name) @@ -958,11 +1277,19 @@ class MIoTLan: self.__on_network_info_change, _MIoTLanNetworkUpdateData(status=status, if_name=info.name)) +<<<<<<< HEAD async def __on_mips_service_change( self, group_id: str, state: MipsServiceState, data: dict ) -> None: _LOGGER.info( 'on mips service change, %s, %s, %s', group_id, state, data) +======= + async def __on_mips_service_change(self, group_id: str, + state: MipsServiceState, + data: dict) -> None: + _LOGGER.info("on mips service change, %s, %s, %s", group_id, state, + data) +>>>>>>> 83899f8 (fomatted code) if len(self._mips_service.get_services()) > 0: _LOGGER.info('find central service, deinit miot lan') await self.deinit_async() @@ -975,9 +1302,16 @@ class MIoTLan: def ping(self, if_name: Optional[str], target_ip: str) -> None: if not target_ip: return +<<<<<<< HEAD self.__sendto( if_name=if_name, data=self._probe_msg, address=target_ip, port=self.OT_PORT) +======= + self.__sendto(if_name=if_name, + data=self._probe_msg, + address=target_ip, + port=self.OT_PORT) +>>>>>>> 83899f8 (fomatted code) def send2device( self, did: str, @@ -1023,9 +1357,11 @@ class MIoTLan: handler_ctx: Any = None, timeout_ms: Optional[int] = None ) -> None: + def request_timeout_handler(req_data: _MIoTLanRequestData): self._pending_requests.pop(req_data.msg_id, None) if req_data and req_data.handler: +<<<<<<< HEAD req_data.handler({ 'code': MIoTErrorCode.CODE_TIMEOUT.value, 'error': 'timeout'}, @@ -1040,6 +1376,25 @@ class MIoTLan: if timeout_ms: timer = self._internal_loop.call_later( timeout_ms/1000, request_timeout_handler, request_data) +======= + req_data.handler( + { + "code": MIoTErrorCode.CODE_TIMEOUT.value, + "error": "timeout" + }, + req_data.handler_ctx, + ) + + timer: Optional[asyncio.TimerHandle] = None + request_data = _MIoTLanRequestData(msg_id=msg_id, + handler=handler, + handler_ctx=handler_ctx, + timeout=timer) + if timeout_ms: + timer = self._internal_loop.call_later(timeout_ms / 1000, + request_timeout_handler, + request_data) +>>>>>>> 83899f8 (fomatted code) request_data.timeout = timer self._pending_requests[msg_id] = request_data self.__sendto(if_name=if_name, data=msg, address=ip, port=self.OT_PORT) @@ -1069,16 +1424,34 @@ class MIoTLan: try: self.send2device( did=did, +<<<<<<< HEAD msg={'from': 'ha.xiaomi_home', **msg}, +======= + msg={ + "from": "ha.xiaomi_home", + **msg + }, +>>>>>>> 83899f8 (fomatted code) handler=handler, handler_ctx=handler_ctx, timeout_ms=timeout_ms) except Exception as err: # pylint: disable=broad-exception-caught +<<<<<<< HEAD _LOGGER.error('send2device error, %s', err) handler({ 'code': MIoTErrorCode.CODE_INTERNAL_ERROR.value, 'error': str(err)}, handler_ctx) +======= + _LOGGER.error("send2device error, %s", err) + handler( + { + "code": MIoTErrorCode.CODE_INTERNAL_ERROR.value, + "error": str(err) + }, + handler_ctx, + ) +>>>>>>> 83899f8 (fomatted code) def __sub_device_state(self, data: _MIoTLanSubDeviceData) -> None: self._device_state_sub_map[data.key] = data @@ -1098,6 +1471,7 @@ class MIoTLan: def __get_dev_list(self, data: _MIoTLanGetDevListData) -> None: dev_list = { device.did: { +<<<<<<< HEAD 'online': device.online, 'push_available': device.subscribed } @@ -1105,6 +1479,13 @@ class MIoTLan: if device.online} data.handler( dev_list, data.handler_ctx) +======= + "online": device.online, + "push_available": device.subscribed + } for device in self._lan_devices.values() if device.online + } + data.handler(dev_list, data.handler_ctx) +>>>>>>> 83899f8 (fomatted code) def __update_devices(self, devices: dict[str, dict]) -> None: for did, info in devices.items(): @@ -1117,9 +1498,14 @@ class MIoTLan: or info['model'] in self._profile_models): # Do not support the local control of # Profile device for the time being +<<<<<<< HEAD _LOGGER.info( 'model not support local ctrl, %s, %s', did, info.get('model')) +======= + _LOGGER.info("model not support local ctrl, %s, %s", did, + info.get("model")) +>>>>>>> 83899f8 (fomatted code) continue if did not in self._lan_devices: if 'token' not in info: @@ -1130,9 +1516,16 @@ class MIoTLan: _LOGGER.error( 'invalid device token, %s, %s', did, info) continue +<<<<<<< HEAD self._lan_devices[did] = _MIoTLanDevice( manager=self, did=did, token=info['token'], ip=info.get('ip', None)) +======= + self._lan_devices[did] = _MIoTLanDevice(manager=self, + did=did, + token=info["token"], + ip=info.get("ip", None)) +>>>>>>> 83899f8 (fomatted code) else: self._lan_devices[did].update_info(info) @@ -1203,6 +1596,7 @@ class MIoTLan: return # Create socket try: +<<<<<<< HEAD sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) @@ -1213,6 +1607,19 @@ class MIoTLan: sock.bind(('', self._local_port or 0)) self._internal_loop.add_reader( sock.fileno(), self.__socket_read_handler, (if_name, sock)) +======= + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, + socket.IPPROTO_UDP) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + # Set SO_BINDTODEVICE + sock.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, + if_name.encode()) + sock.bind(("", self._local_port or 0)) + self._internal_loop.add_reader(sock.fileno(), + self.__socket_read_handler, + (if_name, sock)) +>>>>>>> 83899f8 (fomatted code) self._broadcast_socks[if_name] = sock self._local_port = self._local_port or sock.getsockname()[1] _LOGGER.info( @@ -1235,8 +1642,14 @@ class MIoTLan: def __socket_read_handler(self, ctx: tuple[str, socket.socket]) -> None: try: +<<<<<<< HEAD data_len, addr = ctx[1].recvfrom_into( self._read_buffer, self.OT_MSG_LEN, socket.MSG_DONTWAIT) +======= + data_len, addr = ctx[1].recvfrom_into(self._read_buffer, + self.OT_MSG_LEN, + socket.MSG_DONTWAIT) +>>>>>>> 83899f8 (fomatted code) if data_len < 0: # Socket error _LOGGER.error('socket read error, %s, %s', ctx[0], data_len) @@ -1244,14 +1657,18 @@ class MIoTLan: if addr[1] != self.OT_PORT: # Not ot msg return +<<<<<<< HEAD self.__raw_message_handler( self._read_buffer[:data_len], data_len, addr[0], ctx[0]) +======= + self.__raw_message_handler(self._read_buffer[:data_len], data_len, + addr[0], ctx[0]) +>>>>>>> 83899f8 (fomatted code) except Exception as err: # pylint: disable=broad-exception-caught _LOGGER.error('socket read handler error, %s', err) - def __raw_message_handler( - self, data: bytearray, data_len: int, ip: str, if_name: str - ) -> None: + def __raw_message_handler(self, data: bytearray, data_len: int, ip: str, + if_name: str) -> None: if data[:2] != self.OT_HEADER: return # Keep alive message @@ -1265,6 +1682,7 @@ class MIoTLan: if data_len == self.OT_PROBE_LEN or device.subscribed: device.keep_alive(ip=ip, if_name=if_name) # Manage device subscribe status +<<<<<<< HEAD if ( self._enable_subscribe and data_len == self.OT_PROBE_LEN @@ -1274,12 +1692,16 @@ class MIoTLan: device.supported_wildcard_sub = ( int(data[28]) == self.OT_SUPPORT_WILDCARD_SUB) sub_ts = struct.unpack('>I', data[20:24])[0] +======= + if (self._enable_subscribe and data_len == self.OT_PROBE_LEN and + data[16:20] == b"MSUB" and data[24:27] == b"PUB"): + device.supported_wildcard_sub = (int( + data[28]) == self.OT_SUPPORT_WILDCARD_SUB) + sub_ts = struct.unpack(">I", data[20:24])[0] +>>>>>>> 83899f8 (fomatted code) sub_type = int(data[27]) - if ( - device.supported_wildcard_sub - and sub_type in [0, 1, 4] - and sub_ts != device.sub_ts - ): + if (device.supported_wildcard_sub and sub_type in [0, 1, 4] and + sub_ts != device.sub_ts): device.subscribed = False device.subscribe() if data_len > self.OT_PROBE_LEN: @@ -1296,13 +1718,19 @@ class MIoTLan: _LOGGER.warning('invalid message, no id, %s, %s', did, msg) return # Reply +<<<<<<< HEAD req: Optional[_MIoTLanRequestData] = ( self._pending_requests.pop(msg['id'], None)) +======= + req: Optional[_MIoTLanRequestData] = self._pending_requests.pop( + msg["id"], None) +>>>>>>> 83899f8 (fomatted code) if req: if req.timeout: req.timeout.cancel() req.timeout = None if req.handler is not None: +<<<<<<< HEAD self._main_loop.call_soon_threadsafe( req.handler, msg, req.handler_ctx) return @@ -1322,6 +1750,32 @@ class MIoTLan: if 'siid' not in param and 'piid' not in param: _LOGGER.debug( 'invalid message, no siid or piid, %s, %s', did, msg) +======= + self._main_loop.call_soon_threadsafe(req.handler, msg, + req.handler_ctx) + return + # Handle up link message + if "method" not in msg or "params" not in msg: + _LOGGER.debug("invalid message, no method or params, %s, %s", did, + msg) + return + # Filter dup message + if self.__filter_dup_message(did, msg["id"]): + self.send2device(did=did, + msg={ + "id": msg["id"], + "result": { + "code": 0 + } + }) + return + _LOGGER.debug("lan message, %s, %s", did, msg) + if msg["method"] == "properties_changed": + for param in msg["params"]: + if "siid" not in param and "piid" not in param: + _LOGGER.debug("invalid message, no siid or piid, %s, %s", + did, msg) +>>>>>>> 83899f8 (fomatted code) continue key = f'{did}/p/{param["siid"]}/{param["piid"]}' subs: list[_MIoTLanRegisterBroadcastData] = list( @@ -1329,6 +1783,7 @@ class MIoTLan: for sub in subs: self._main_loop.call_soon_threadsafe( sub.handler, param, sub.handler_ctx) +<<<<<<< HEAD elif ( msg['method'] == 'event_occured' and 'siid' in msg['params'] @@ -1340,6 +1795,16 @@ class MIoTLan: for sub in subs: self._main_loop.call_soon_threadsafe( sub.handler, msg['params'], sub.handler_ctx) +======= + elif (msg["method"] == "event_occured" and "siid" in msg["params"] and + "eiid" in msg["params"]): + key = f"{did}/e/{msg['params']['siid']}/{msg['params']['eiid']}" + subs: list[_MIoTLanRegisterBroadcastData] = list( + self._device_msg_matcher.iter_match(key)) + for sub in subs: + self._main_loop.call_soon_threadsafe(sub.handler, msg["params"], + sub.handler_ctx) +>>>>>>> 83899f8 (fomatted code) else: _LOGGER.debug( 'invalid message, unknown method, %s, %s', did, msg) @@ -1352,14 +1817,17 @@ class MIoTLan: if filter_id in self._reply_msg_buffer: return True self._reply_msg_buffer[filter_id] = self._internal_loop.call_later( +<<<<<<< HEAD 5, lambda filter_id: self._reply_msg_buffer.pop(filter_id, None), +======= + 5, lambda filter_id: self._reply_msg_buffer.pop(filter_id, None), +>>>>>>> 83899f8 (fomatted code) filter_id) return False - def __sendto( - self, if_name: Optional[str], data: bytes, address: str, port: int - ) -> None: + def __sendto(self, if_name: Optional[str], data: bytes, address: str, + port: int) -> None: if if_name is None: # Broadcast for if_n, sock in self._broadcast_socks.items(): @@ -1387,11 +1855,20 @@ class MIoTLan: scan_time = self.__get_next_scan_time() self._scan_timer = self._internal_loop.call_later( scan_time, self.__scan_devices) +<<<<<<< HEAD _LOGGER.debug('next scan time: %ss', scan_time) +======= + _LOGGER.debug("next scan time: %ss", scan_time) +>>>>>>> 83899f8 (fomatted code) def __get_next_scan_time(self) -> float: if not self._last_scan_interval: self._last_scan_interval = self.OT_PROBE_INTERVAL_MIN +<<<<<<< HEAD self._last_scan_interval = min( self._last_scan_interval*2, self.OT_PROBE_INTERVAL_MAX) +======= + self._last_scan_interval = min(self._last_scan_interval * 2, + self.OT_PROBE_INTERVAL_MAX) +>>>>>>> 83899f8 (fomatted code) return self._last_scan_interval diff --git a/custom_components/xiaomi_home/miot/miot_mips.py b/custom_components/xiaomi_home/miot/miot_mips.py index 99499b2..5c39089 100644 --- a/custom_components/xiaomi_home/miot/miot_mips.py +++ b/custom_components/xiaomi_home/miot/miot_mips.py @@ -101,6 +101,7 @@ class _MipsMessage: data_start = 0 data_end = 0 while data_start < data_len: +<<<<<<< HEAD data_end = data_start+5 unpack_len, unpack_type = struct.unpack( '>>>>>> 83899f8 (fomatted code) case _MipsMsgTypeOptions.PAYLOAD.value: mips_msg.payload = str(unpack_data.strip(b'\x00'), 'utf-8') case _MipsMsgTypeOptions.FROM.value: @@ -386,8 +401,13 @@ class _MipsClient(ABC): def update_mqtt_password(self, password: str) -> None: self._password = password if self._mqtt: +<<<<<<< HEAD self._mqtt.username_pw_set( username=self._username, password=self._password) +======= + self._mqtt.username_pw_set(username=self._username, + password=self._password) +>>>>>>> 83899f8 (fomatted code) def log_debug(self, msg, *args, **kwargs) -> None: if self._logger: @@ -404,9 +424,14 @@ class _MipsClient(ABC): def enable_logger(self, logger: Optional[logging.Logger] = None) -> None: self._logger = logger +<<<<<<< HEAD def enable_mqtt_logger( self, logger: Optional[logging.Logger] = None ) -> None: +======= + def enable_mqtt_logger(self, + logger: Optional[logging.Logger] = None) -> None: +>>>>>>> 83899f8 (fomatted code) self._mqtt_logger = logger if self._mqtt: if logger: @@ -415,9 +440,8 @@ class _MipsClient(ABC): self._mqtt.disable_logger() @final - def sub_mips_state( - self, key: str, handler: Callable[[str, bool], Coroutine] - ) -> bool: + def sub_mips_state(self, key: str, handler: Callable[[str, bool], + Coroutine]) -> bool: """Subscribe mips state. NOTICE: callback to main loop thread This will be called before the client is connected. @@ -448,6 +472,7 @@ class _MipsClient(ABC): handler: Callable[[dict, Any], None], siid: Optional[int] = None, piid: Optional[int] = None, +<<<<<<< HEAD handler_ctx: Any = None ) -> bool: ... @@ -458,6 +483,18 @@ class _MipsClient(ABC): siid: Optional[int] = None, piid: Optional[int] = None ) -> bool: ... +======= + handler_ctx: Any = None, + ) -> bool: + ... + + @abstractmethod + def unsub_prop(self, + did: str, + siid: Optional[int] = None, + piid: Optional[int] = None) -> bool: + ... +>>>>>>> 83899f8 (fomatted code) @abstractmethod def sub_event( @@ -466,6 +503,7 @@ class _MipsClient(ABC): handler: Callable[[dict, Any], None], siid: Optional[int] = None, eiid: Optional[int] = None, +<<<<<<< HEAD handler_ctx: Any = None ) -> bool: ... @@ -483,13 +521,35 @@ class _MipsClient(ABC): payload: Optional[str] = None, timeout_ms: int = 10000 ) -> dict[str, dict]: ... +======= + handler_ctx: Any = None, + ) -> bool: + ... @abstractmethod - async def get_prop_async( - self, did: str, siid: int, piid: int, timeout_ms: int = 10000 - ) -> Any: ... + def unsub_event(self, + did: str, + siid: Optional[int] = None, + eiid: Optional[int] = None) -> bool: + ... @abstractmethod + async def get_dev_list_async(self, + payload: Optional[str] = None, + timeout_ms: int = 10000) -> dict[str, dict]: + ... +>>>>>>> 83899f8 (fomatted code) + + @abstractmethod + async def get_prop_async(self, + did: str, + siid: int, + piid: int, + timeout_ms: int = 10000) -> Any: + ... + + @abstractmethod +<<<<<<< HEAD async def set_prop_async( self, did: str, siid: int, piid: int, value: Any, timeout_ms: int = 10000 @@ -500,15 +560,36 @@ class _MipsClient(ABC): self, did: str, siid: int, aiid: int, in_list: list, timeout_ms: int = 10000 ) -> dict: ... +======= + async def set_prop_async(self, + did: str, + siid: int, + piid: int, + value: Any, + timeout_ms: int = 10000) -> dict: + ... @abstractmethod - def _on_mips_message(self, topic: str, payload: bytes) -> None: ... + async def action_async(self, + did: str, + siid: int, + aiid: int, + in_list: list, + timeout_ms: int = 10000) -> dict: + ... +>>>>>>> 83899f8 (fomatted code) @abstractmethod - def _on_mips_connect(self, rc: int, props: dict) -> None: ... + def _on_mips_message(self, topic: str, payload: bytes) -> None: + ... @abstractmethod - def _on_mips_disconnect(self, rc: int, props: dict) -> None: ... + def _on_mips_connect(self, rc: int, props: dict) -> None: + ... + + @abstractmethod + def _on_mips_disconnect(self, rc: int, props: dict) -> None: + ... @final def _mips_sub_internal(self, topic: str) -> None: @@ -519,12 +600,24 @@ class _MipsClient(ABC): if not self._mqtt or not self._mqtt.is_connected(): self.log_error(f'mips sub when not connected, {topic}') return +<<<<<<< HEAD if topic not in self._mips_sub_pending_map: self._mips_sub_pending_map[topic] = 0 if not self._mips_sub_pending_timer: self._mips_sub_pending_timer = self._internal_loop.call_later( 0.01, self.__mips_sub_internal_pending_handler, topic) +======= + try: + if topic not in self._mips_sub_pending_map: + self._mips_sub_pending_map[topic] = 0 + if not self._mips_sub_pending_timer: + self._mips_sub_pending_timer = self._internal_loop.call_later( + 0.01, self.__mips_sub_internal_pending_handler, topic) + except Exception as err: # pylint: disable=broad-exception-caught + # Catch all exception + self.log_error(f"mips sub internal error, {topic}. {err}") +>>>>>>> 83899f8 (fomatted code) @final def _mips_unsub_internal(self, topic: str) -> None: @@ -537,12 +630,21 @@ class _MipsClient(ABC): return try: result, mid = self._mqtt.unsubscribe(topic=topic) +<<<<<<< HEAD if (result == MQTT_ERR_SUCCESS) or (result == MQTT_ERR_NO_CONN): self.log_debug( f'mips unsub internal success, {result}, {mid}, {topic}') return self.log_error( f'mips unsub internal error, {result}, {mid}, {topic}') +======= + if result == MQTT_ERR_SUCCESS: + self.log_debug( + f"mips unsub internal success, {result}, {mid}, {topic}") + return + self.log_error( + f"mips unsub internal error, {result}, {mid}, {topic}") +>>>>>>> 83899f8 (fomatted code) except Exception as err: # pylint: disable=broad-exception-caught # Catch all exception self.log_error(f'mips unsub internal error, {topic}, {err}') @@ -560,8 +662,14 @@ class _MipsClient(ABC): if not self._mqtt or not self._mqtt.is_connected(): return False try: +<<<<<<< HEAD handle = self._mqtt.publish( topic=topic, payload=payload, qos=self.MIPS_QOS) +======= + handle = self._mqtt.publish(topic=topic, + payload=payload, + qos=self.MIPS_QOS) +>>>>>>> 83899f8 (fomatted code) # self.log_debug(f'_mips_publish_internal, {topic}, {payload}') if wait_for_publish is True: handle.wait_for_publish(timeout_ms/1000.0) @@ -604,8 +712,13 @@ class _MipsClient(ABC): if self._mqtt: self._mqtt.loop_misc() if self._mqtt and self._mqtt.want_write(): +<<<<<<< HEAD self._internal_loop.add_writer( self._mqtt_fd, self.__mqtt_write_handler) +======= + self._internal_loop.add_writer(self._mqtt_fd, + self.__mqtt_write_handler) +>>>>>>> 83899f8 (fomatted code) except Exception as err: # pylint: disable=broad-exception-caught # Catch all exception self.log_error(f'__mqtt_loop_handler, {err}') @@ -619,6 +732,7 @@ class _MipsClient(ABC): self._mqtt.enable_logger(logger=self._mqtt_logger) # Set mqtt config if self._username: +<<<<<<< HEAD self._mqtt.username_pw_set( username=self._username, password=self._password) if ( @@ -626,6 +740,11 @@ class _MipsClient(ABC): and self._cert_file and self._key_file ): +======= + self._mqtt.username_pw_set(username=self._username, + password=self._password) + if self._ca_file and self._cert_file and self._key_file: +>>>>>>> 83899f8 (fomatted code) self._mqtt.tls_set( tls_version=ssl.PROTOCOL_TLS_CLIENT, ca_certs=self._ca_file, @@ -661,8 +780,12 @@ class _MipsClient(ABC): if item.handler is None: continue self.main_loop.call_soon_threadsafe( +<<<<<<< HEAD self.main_loop.create_task, item.handler(item.key, True)) +======= + self.main_loop.create_task, item.handler(item.key, True)) +>>>>>>> 83899f8 (fomatted code) # Resolve future self.main_loop.call_soon_threadsafe( self._event_connect.set) @@ -676,8 +799,13 @@ class _MipsClient(ABC): def __on_disconnect(self, client, user_data, rc, props) -> None: if self._mqtt_state: +<<<<<<< HEAD (self.log_info if rc == 0 else self.log_error)( f'mips disconnect, {rc}, {props}') +======= + (self.log_info + if rc == 0 else self.log_error)(f"mips disconnect, {rc}, {props}") +>>>>>>> 83899f8 (fomatted code) self._mqtt_state = False if self._mqtt_timer: self._mqtt_timer.cancel() @@ -710,18 +838,27 @@ class _MipsClient(ABC): self.main_loop.call_soon_threadsafe( self._event_connect.clear) +<<<<<<< HEAD def __on_message( self, client: Client, user_data: Any, msg: MQTTMessage ) -> None: +======= + def __on_message(self, client: Client, user_data: Any, + msg: MQTTMessage) -> None: +>>>>>>> 83899f8 (fomatted code) self._on_mips_message(topic=msg.topic, payload=msg.payload) def __mips_sub_internal_pending_handler(self, ctx: Any) -> None: if not self._mqtt or not self._mqtt.is_connected(): _LOGGER.error( +<<<<<<< HEAD 'mips sub internal pending, but mqtt is None or disconnected') +======= + "mips sub internal pending, but mqtt is None or disconnected") +>>>>>>> 83899f8 (fomatted code) return subbed_count = 1 for topic in list(self._mips_sub_pending_map.keys()): @@ -745,7 +882,11 @@ class _MipsClient(ABC): self.log_error(f'mips sub internal error, {topic}. {err}') self._mips_sub_pending_map[topic] = count+1 self.log_error( +<<<<<<< HEAD f'retry mips sub internal, {count}, {topic}, {result}, {mid}') +======= + f"retry mips sub internal, {count}, {topic}, {result}, {mid}") +>>>>>>> 83899f8 (fomatted code) if len(self._mips_sub_pending_map): self._mips_sub_pending_timer = self._internal_loop.call_later( @@ -782,6 +923,7 @@ class _MipsClient(ABC): socket = self._mqtt.socket() if socket is None: self.log_error( +<<<<<<< HEAD '__mips_connect, connect success, but socket is None') self.__mips_try_reconnect() return @@ -792,6 +934,18 @@ class _MipsClient(ABC): if self._mqtt.want_write(): self._internal_loop.add_writer( self._mqtt_fd, self.__mqtt_write_handler) +======= + "__mips_connect, connect success, but socket is None") + self.__mips_try_reconnect() + return + self._mqtt_fd = socket.fileno() + self.log_debug(f"__mips_connect, _mqtt_fd, {self._mqtt_fd}") + self._internal_loop.add_reader(self._mqtt_fd, + self.__mqtt_read_handler) + if self._mqtt.want_write(): + self._internal_loop.add_writer(self._mqtt_fd, + self.__mqtt_write_handler) +>>>>>>> 83899f8 (fomatted code) self._mqtt_timer = self._internal_loop.call_later( self.MQTT_INTERVAL_S, self.__mqtt_timer_handler) else: @@ -843,7 +997,11 @@ class _MipsClient(ABC): self._mips_reconnect_interval = self.MIPS_RECONNECT_INTERVAL_MIN else: self._mips_reconnect_interval = min( +<<<<<<< HEAD self._mips_reconnect_interval*2, +======= + self._mips_reconnect_interval * 2, +>>>>>>> 83899f8 (fomatted code) self.MIPS_RECONNECT_INTERVAL_MAX) return self._mips_reconnect_interval @@ -892,8 +1050,13 @@ class MipsCloudClient(_MipsClient): raise MIoTMipsError('invalid params') topic: str = ( +<<<<<<< HEAD f'device/{did}/up/properties_changed/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') +======= + f"device/{did}/up/properties_changed/" + f"{'#' if siid is None or piid is None else f'{siid}/{piid}'}") +>>>>>>> 83899f8 (fomatted code) def on_prop_msg(topic: str, payload: str, ctx: Any) -> None: try: @@ -902,6 +1065,7 @@ class MipsCloudClient(_MipsClient): self.log_error( f'on_prop_msg, invalid msg, {topic}, {payload}') return +<<<<<<< HEAD if ( not isinstance(msg.get('params', None), dict) or 'siid' not in msg['params'] @@ -924,11 +1088,37 @@ class MipsCloudClient(_MipsClient): siid: Optional[int] = None, piid: Optional[int] = None ) -> bool: +======= + if (not isinstance(msg.get("params", None), dict) or + "siid" not in msg["params"] or + "piid" not in msg["params"] or + "value" not in msg["params"]): + self.log_error(f"on_prop_msg, invalid msg, {topic}, {payload}") + return + if handler: + self.log_debug("on properties_changed, %s", payload) + handler(msg["params"], ctx) + + return self.__reg_broadcast_external(topic=topic, + handler=on_prop_msg, + handler_ctx=handler_ctx) + + @final + def unsub_prop(self, + did: str, + siid: Optional[int] = None, + piid: Optional[int] = None) -> bool: +>>>>>>> 83899f8 (fomatted code) if not isinstance(did, str): raise MIoTMipsError('invalid params') topic: str = ( +<<<<<<< HEAD f'device/{did}/up/properties_changed/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') +======= + f"device/{did}/up/properties_changed/" + f"{'#' if siid is None or piid is None else f'{siid}/{piid}'}") +>>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -944,8 +1134,13 @@ class MipsCloudClient(_MipsClient): raise MIoTMipsError('invalid params') # Spelling error: event_occured topic: str = ( +<<<<<<< HEAD f'device/{did}/up/event_occured/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') +======= + f"device/{did}/up/event_occured/" + f"{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}") +>>>>>>> 83899f8 (fomatted code) def on_event_msg(topic: str, payload: str, ctx: Any) -> None: try: @@ -954,6 +1149,7 @@ class MipsCloudClient(_MipsClient): self.log_error( f'on_event_msg, invalid msg, {topic}, {payload}') return +<<<<<<< HEAD if ( not isinstance(msg.get('params', None), dict) or 'siid' not in msg['params'] @@ -977,12 +1173,39 @@ class MipsCloudClient(_MipsClient): siid: Optional[int] = None, eiid: Optional[int] = None ) -> bool: +======= + if (not isinstance(msg.get("params", None), dict) or + "siid" not in msg["params"] or + "eiid" not in msg["params"] or + "arguments" not in msg["params"]): + self.log_error(f"on_event_msg, invalid msg, {topic}, {payload}") + return + if handler: + self.log_debug("on on_event_msg, %s", payload) + msg["params"]["from"] = "cloud" + handler(msg["params"], ctx) + + return self.__reg_broadcast_external(topic=topic, + handler=on_event_msg, + handler_ctx=handler_ctx) + + @final + def unsub_event(self, + did: str, + siid: Optional[int] = None, + eiid: Optional[int] = None) -> bool: +>>>>>>> 83899f8 (fomatted code) if not isinstance(did, str): raise MIoTMipsError('invalid params') # Spelling error: event_occured topic: str = ( +<<<<<<< HEAD f'device/{did}/up/event_occured/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') +======= + f"device/{did}/up/event_occured/" + f"{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}") +>>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -1002,13 +1225,20 @@ class MipsCloudClient(_MipsClient): if msg is None or 'device_id' not in msg or 'event' not in msg: self.log_error(f'on_state_msg, recv unknown msg, {payload}') return +<<<<<<< HEAD if msg['device_id'] != did: self.log_error( f'on_state_msg, err msg, {did}!={msg["device_id"]}') +======= + if msg["device_id"] != did: + self.log_error( + f"on_state_msg, err msg, {did}!={msg['device_id']}") +>>>>>>> 83899f8 (fomatted code) return if handler: self.log_debug('cloud, device state changed, %s', payload) handler( +<<<<<<< HEAD did, MIoTDeviceState.ONLINE if msg['event'] == 'online' else MIoTDeviceState.OFFLINE, ctx) @@ -1020,6 +1250,17 @@ class MipsCloudClient(_MipsClient): return True return self.__reg_broadcast_external( topic=topic, handler=on_state_msg, handler_ctx=handler_ctx) +======= + did, + MIoTDeviceState.ONLINE + if msg["event"] == "online" else MIoTDeviceState.OFFLINE, + ctx, + ) + + return self.__reg_broadcast_external(topic=topic, + handler=on_state_msg, + handler_ctx=handler_ctx) +>>>>>>> 83899f8 (fomatted code) @final def unsub_device_state(self, did: str) -> bool: @@ -1028,6 +1269,7 @@ class MipsCloudClient(_MipsClient): topic: str = f'device/{did}/state/#' return self.__unreg_broadcast_external(topic=topic) +<<<<<<< HEAD async def get_dev_list_async( self, payload: Optional[str] = None, timeout_ms: int = 10000 ) -> dict[str, dict]: @@ -1049,13 +1291,47 @@ class MipsCloudClient(_MipsClient): timeout_ms: int = 10000 ) -> dict: raise NotImplementedError('please call in http client') +======= + async def get_dev_list_async(self, + payload: Optional[str] = None, + timeout_ms: int = 10000) -> dict[str, dict]: + raise NotImplementedError("please call in http client") + + async def get_prop_async(self, + did: str, + siid: int, + piid: int, + timeout_ms: int = 10000) -> Any: + raise NotImplementedError("please call in http client") + + async def set_prop_async(self, + did: str, + siid: int, + piid: int, + value: Any, + timeout_ms: int = 10000) -> dict: + raise NotImplementedError("please call in http client") + + async def action_async(self, + did: str, + siid: int, + aiid: int, + in_list: list, + timeout_ms: int = 10000) -> dict: + raise NotImplementedError("please call in http client") +>>>>>>> 83899f8 (fomatted code) def __reg_broadcast_external( self, topic: str, handler: Callable[[str, str, Any], None], handler_ctx: Any = None ) -> bool: +<<<<<<< HEAD self._internal_loop.call_soon_threadsafe( self.__reg_broadcast, topic, handler, handler_ctx) +======= + self._internal_loop.call_soon_threadsafe(self.__reg_broadcast, topic, + handler, handler_ctx) +>>>>>>> 83899f8 (fomatted code) return True def __unreg_broadcast_external(self, topic: str) -> bool: @@ -1068,9 +1344,15 @@ class MipsCloudClient(_MipsClient): handler_ctx: Any = None ) -> None: if not self._msg_matcher.get(topic=topic): +<<<<<<< HEAD sub_bc: _MipsBroadcast = _MipsBroadcast( topic=topic, handler=handler, handler_ctx=handler_ctx) +======= + sub_bc: _MipsBroadcast = _MipsBroadcast(topic=topic, + handler=handler, + handler_ctx=handler_ctx) +>>>>>>> 83899f8 (fomatted code) self._msg_matcher[topic] = sub_bc self._mips_sub_internal(topic=topic) else: @@ -1107,8 +1389,13 @@ class MipsCloudClient(_MipsClient): if item.handler is None: continue # NOTICE: call threadsafe +<<<<<<< HEAD self.main_loop.call_soon_threadsafe( item.handler, topic, payload_str, item.handler_ctx) +======= + self.main_loop.call_soon_threadsafe(item.handler, topic, + payload_str, item.handler_ctx) +>>>>>>> 83899f8 (fomatted code) class MipsLocalClient(_MipsClient): @@ -1190,6 +1477,7 @@ class MipsLocalClient(_MipsClient): handler_ctx: Any = None ) -> bool: topic: str = ( +<<<<<<< HEAD f'appMsg/notify/iot/{did}/property/' f'{"#" if siid is None or piid is None else f"{siid}.{piid}"}') @@ -1203,10 +1491,21 @@ class MipsLocalClient(_MipsClient): or 'value' not in msg ): self.log_info('unknown prop msg, %s', payload) +======= + f"appMsg/notify/iot/{did}/property/" + f"{'#' if siid is None or piid is None else f'{siid}.{piid}'}") + + def on_prop_msg(topic: str, payload: str, ctx: Any): + msg: dict = json.loads(payload) + if (msg is None or "did" not in msg or "siid" not in msg or + "piid" not in msg or "value" not in msg): + # self.log_error(f'on_prop_msg, recv unknown msg, {payload}') +>>>>>>> 83899f8 (fomatted code) return if handler: self.log_debug('local, on properties_changed, %s', payload) handler(msg, ctx) +<<<<<<< HEAD return self.__reg_broadcast_external( topic=topic, handler=on_prop_msg, handler_ctx=handler_ctx) @@ -1220,6 +1519,21 @@ class MipsLocalClient(_MipsClient): topic: str = ( f'appMsg/notify/iot/{did}/property/' f'{"#" if siid is None or piid is None else f"{siid}.{piid}"}') +======= + + return self.__reg_broadcast_external(topic=topic, + handler=on_prop_msg, + handler_ctx=handler_ctx) + + @final + def unsub_prop(self, + did: str, + siid: Optional[int] = None, + piid: Optional[int] = None) -> bool: + topic: str = ( + f"appMsg/notify/iot/{did}/property/" + f"{'#' if siid is None or piid is None else f'{siid}.{piid}'}") +>>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -1232,6 +1546,7 @@ class MipsLocalClient(_MipsClient): handler_ctx: Any = None ) -> bool: topic: str = ( +<<<<<<< HEAD f'appMsg/notify/iot/{did}/event/' f'{"#" if siid is None or eiid is None else f"{siid}.{eiid}"}') @@ -1245,6 +1560,18 @@ class MipsLocalClient(_MipsClient): # or 'arguments' not in msg ): self.log_info('unknown event msg, %s', payload) +======= + f"appMsg/notify/iot/{did}/event/" + f"{'#' if siid is None or eiid is None else f'{siid}.{eiid}'}") + + def on_event_msg(topic: str, payload: str, ctx: Any): + msg: dict = json.loads(payload) + if (msg is None or "did" not in msg or "siid" not in msg or + "eiid" not in msg + # or 'arguments' not in msg + ): + self.log_info("unknown event msg, %s", payload) +>>>>>>> 83899f8 (fomatted code) return if 'arguments' not in msg: self.log_info('wrong event msg, %s', payload) @@ -1252,6 +1579,7 @@ class MipsLocalClient(_MipsClient): if handler: self.log_debug('local, on event_occurred, %s', payload) handler(msg, ctx) +<<<<<<< HEAD return self.__reg_broadcast_external( topic=topic, handler=on_event_msg, handler_ctx=handler_ctx) @@ -1265,15 +1593,33 @@ class MipsLocalClient(_MipsClient): topic: str = ( f'appMsg/notify/iot/{did}/event/' f'{"#" if siid is None or eiid is None else f"{siid}.{eiid}"}') +======= + + return self.__reg_broadcast_external(topic=topic, + handler=on_event_msg, + handler_ctx=handler_ctx) + + @final + def unsub_event(self, + did: str, + siid: Optional[int] = None, + eiid: Optional[int] = None) -> bool: + topic: str = ( + f"appMsg/notify/iot/{did}/event/" + f"{'#' if siid is None or eiid is None else f'{siid}.{eiid}'}") +>>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final - async def get_prop_safe_async( - self, did: str, siid: int, piid: int, timeout_ms: int = 10000 - ) -> Any: + async def get_prop_safe_async(self, + did: str, + siid: int, + piid: int, + timeout_ms: int = 10000) -> Any: self._get_prop_queue.setdefault(did, []) fut: asyncio.Future = self.main_loop.create_future() self._get_prop_queue[did].append({ +<<<<<<< HEAD 'param': json.dumps({ 'did': did, 'siid': siid, @@ -1287,13 +1633,29 @@ class MipsLocalClient(_MipsClient): 0.1, self.main_loop.create_task, self.__get_prop_timer_handle()) +======= + "param": json.dumps({ + "did": did, + "siid": siid, + "piid": piid + }), + "fut": fut, + "timeout_ms": timeout_ms, + }) + if self._get_prop_timer is None: + self._get_prop_timer = self.main_loop.call_later( + 0.1, self.main_loop.create_task, self.__get_prop_timer_handle()) +>>>>>>> 83899f8 (fomatted code) return await fut @final - async def get_prop_async( - self, did: str, siid: int, piid: int, timeout_ms: int = 10000 - ) -> Any: + async def get_prop_async(self, + did: str, + siid: int, + piid: int, + timeout_ms: int = 10000) -> Any: result_obj = await self.__request_async( +<<<<<<< HEAD topic='proxy/get', payload=json.dumps({ 'did': did, @@ -1302,10 +1664,22 @@ class MipsLocalClient(_MipsClient): }), timeout_ms=timeout_ms) if not isinstance(result_obj, dict) or 'value' not in result_obj: +======= + topic="proxy/get", + payload=json.dumps({ + "did": did, + "siid": siid, + "piid": piid + }), + timeout_ms=timeout_ms, + ) + if not isinstance(result_obj, dict) or "value" not in result_obj: +>>>>>>> 83899f8 (fomatted code) return None return result_obj['value'] @final +<<<<<<< HEAD async def set_prop_async( self, did: str, siid: int, piid: int, value: Any, timeout_ms: int = 10000 @@ -1338,11 +1712,46 @@ class MipsLocalClient(_MipsClient): return result_obj['result'][0] if 'error' in result_obj: return result_obj['error'] +======= + async def set_prop_async(self, + did: str, + siid: int, + piid: int, + value: Any, + timeout_ms: int = 10000) -> dict: + payload_obj: dict = { + "did": did, + "rpc": { + "id": + self.__gen_mips_id, + "method": + "set_properties", + "params": [{ + "did": did, + "siid": siid, + "piid": piid, + "value": value + }], + }, + } + result_obj = await self.__request_async(topic="proxy/rpcReq", + payload=json.dumps(payload_obj), + timeout_ms=timeout_ms) + if result_obj: + if ("result" in result_obj and len(result_obj["result"]) == 1 and + "did" in result_obj["result"][0] and + result_obj["result"][0]["did"] == did and + "code" in result_obj["result"][0]): + return result_obj["result"][0] + if "error" in result_obj: + return result_obj["error"] +>>>>>>> 83899f8 (fomatted code) return { 'code': MIoTErrorCode.CODE_INTERNAL_ERROR.value, 'message': 'Invalid result'} @final +<<<<<<< HEAD async def set_props_async( self, did: str, props_list: List[Dict[str, Any]], timeout_ms: int = 10000 @@ -1353,6 +1762,12 @@ class MipsLocalClient(_MipsClient): # 'piid': piid, # 'value': value # }] +======= + async def set_props_async(self, + did: str, + props_list: List[Dict[str, Any]], + timeout_ms: int = 10000) -> dict: +>>>>>>> 83899f8 (fomatted code) payload_obj: dict = { "did": did, "rpc": { @@ -1361,17 +1776,21 @@ class MipsLocalClient(_MipsClient): "params": props_list, } } +<<<<<<< HEAD result_obj = await self.__request_async( topic="proxy/rpcReq", payload=json.dumps(payload_obj), timeout_ms=timeout_ms) +======= + result_obj = await self.__request_async(topic="proxy/rpcReq", + payload=json.dumps(payload_obj), + timeout_ms=timeout_ms) +>>>>>>> 83899f8 (fomatted code) if result_obj: - if ( - "result" in result_obj - and len(result_obj["result"]) == len(props_list) - and result_obj["result"][0].get("did") == did - and all("code" in item for item in result_obj["result"]) - ): + if ("result" in result_obj and + len(result_obj["result"]) == len(props_list) and + result_obj["result"][0].get("did") == did and + all("code" in item for item in result_obj["result"])): return result_obj["result"] if "error" in result_obj: return result_obj["error"] @@ -1380,6 +1799,7 @@ class MipsLocalClient(_MipsClient): 'message': 'Invalid result'} @final +<<<<<<< HEAD async def action_async( self, did: str, siid: int, aiid: int, in_list: list, timeout_ms: int = 10000 @@ -1400,6 +1820,30 @@ class MipsLocalClient(_MipsClient): result_obj = await self.__request_async( topic='proxy/rpcReq', payload=json.dumps(payload_obj), timeout_ms=timeout_ms) +======= + async def action_async(self, + did: str, + siid: int, + aiid: int, + in_list: list, + timeout_ms: int = 10000) -> dict: + payload_obj: dict = { + "did": did, + "rpc": { + "id": self.__gen_mips_id, + "method": "action", + "params": { + "did": did, + "siid": siid, + "aiid": aiid, + "in": in_list + }, + }, + } + result_obj = await self.__request_async(topic="proxy/rpcReq", + payload=json.dumps(payload_obj), + timeout_ms=timeout_ms) +>>>>>>> 83899f8 (fomatted code) if result_obj: if 'result' in result_obj and 'code' in result_obj['result']: return result_obj['result'] @@ -1410,6 +1854,7 @@ class MipsLocalClient(_MipsClient): 'message': 'Invalid result'} @final +<<<<<<< HEAD async def get_dev_list_async( self, payload: Optional[str] = None, timeout_ms: int = 10000 ) -> dict[str, dict]: @@ -1418,6 +1863,16 @@ class MipsLocalClient(_MipsClient): timeout_ms=timeout_ms) if not result_obj or 'devList' not in result_obj: raise MIoTMipsError('invalid result') +======= + async def get_dev_list_async(self, + payload: Optional[str] = None, + timeout_ms: int = 10000) -> dict[str, dict]: + result_obj = await self.__request_async(topic="proxy/getDevList", + payload=payload or "{}", + timeout_ms=timeout_ms) + if not result_obj or "devList" not in result_obj: + raise MIoTMipsError("invalid result") +>>>>>>> 83899f8 (fomatted code) device_list = {} for did, info in result_obj['devList'].items(): name: str = info.get('name', None) @@ -1438,6 +1893,7 @@ class MipsLocalClient(_MipsClient): return device_list @final +<<<<<<< HEAD async def get_action_group_list_async( self, timeout_ms: int = 10000 ) -> list[str]: @@ -1448,11 +1904,22 @@ class MipsLocalClient(_MipsClient): if not result_obj or 'result' not in result_obj: raise MIoTMipsError('invalid result') return result_obj['result'] +======= + async def get_action_group_list_async(self, + timeout_ms: int = 10000) -> list[str]: + result_obj = await self.__request_async( + topic="proxy/getMijiaActionGroupList", + payload="{}", + timeout_ms=timeout_ms) + if not result_obj or "result" not in result_obj: + raise MIoTMipsError("invalid result") + return result_obj["result"] +>>>>>>> 83899f8 (fomatted code) @final - async def exec_action_group_list_async( - self, ag_id: str, timeout_ms: int = 10000 - ) -> dict: + async def exec_action_group_list_async(self, + ag_id: str, + timeout_ms: int = 10000) -> dict: result_obj = await self.__request_async( topic='proxy/execMijiaActionGroup', payload=f'{{"id":"{ag_id}"}}', @@ -1469,15 +1936,19 @@ class MipsLocalClient(_MipsClient): @final @property def on_dev_list_changed( +<<<<<<< HEAD self ) -> Optional[Callable[[Any, list[str]], Coroutine]]: +======= + self) -> Optional[Callable[[Any, list[str]], Coroutine]]: +>>>>>>> 83899f8 (fomatted code) return self._on_dev_list_changed @final @on_dev_list_changed.setter def on_dev_list_changed( - self, func: Optional[Callable[[Any, list[str]], Coroutine]] - ) -> None: + self, func: Optional[Callable[[Any, list[str]], + Coroutine]]) -> None: """run in main loop.""" self._on_dev_list_changed = func @@ -1490,6 +1961,7 @@ class MipsLocalClient(_MipsClient): mid=self.__gen_mips_id, on_reply=on_reply, on_reply_ctx=on_reply_ctx, +<<<<<<< HEAD timer=None) pub_topic: str = f'master/{topic}' result = self.__mips_publish( @@ -1520,6 +1992,37 @@ class MipsLocalClient(_MipsClient): sub_bc: _MipsBroadcast = _MipsBroadcast( topic=sub_topic, handler=handler, handler_ctx=handler_ctx) +======= + timer=None, + ) + pub_topic: str = f"master/{topic}" + result = self.__mips_publish(topic=pub_topic, + payload=payload, + mid=req.mid, + ret_topic=self._reply_topic) + self.log_debug( + f"mips local call api, {result}, {req.mid}, {pub_topic}, {payload}") + + def on_request_timeout(req: _MipsRequest): + self.log_error( + f"on mips request timeout, {req.mid}, {pub_topic}, {payload}") + self._request_map.pop(str(req.mid), None) + req.on_reply('{"error":{"code":-10006, "message":"timeout"}}', + req.on_reply_ctx) + + req.timer = self._internal_loop.call_later(timeout_ms / 1000, + on_request_timeout, req) + self._request_map[str(req.mid)] = req + + def __reg_broadcast(self, topic: str, handler: Callable[[str, str, Any], + None], + handler_ctx: Any) -> None: + sub_topic: str = f"{self._did}/{topic}" + if not self._msg_matcher.get(sub_topic): + sub_bc: _MipsBroadcast = _MipsBroadcast(topic=sub_topic, + handler=handler, + handler_ctx=handler_ctx) +>>>>>>> 83899f8 (fomatted code) self._msg_matcher[sub_topic] = sub_bc self._mips_sub_internal(topic=f'master/{topic}') else: @@ -1531,7 +2034,11 @@ class MipsLocalClient(_MipsClient): if self._msg_matcher.get(unsub_topic): del self._msg_matcher[unsub_topic] self._mips_unsub_internal( +<<<<<<< HEAD topic=re.sub(f'^{self._did}', 'master', unsub_topic)) +======= + topic=re.sub(f"^{self._did}", "master", unsub_topic)) +>>>>>>> 83899f8 (fomatted code) @final def _on_mips_connect(self, rc: int, props: dict) -> None: @@ -1545,7 +2052,11 @@ class MipsLocalClient(_MipsClient): # Sub broadcast topic for topic, _ in list(self._msg_matcher.iter_all_nodes()): self._mips_sub_internal( +<<<<<<< HEAD topic=re.sub(f'^{self._did}', 'master', topic)) +======= + topic=re.sub(f"^{self._did}", "master", topic)) +>>>>>>> 83899f8 (fomatted code) @final def _on_mips_disconnect(self, rc: int, props: dict) -> None: @@ -1558,7 +2069,11 @@ class MipsLocalClient(_MipsClient): # f"mips local client, on_message, {topic} -> {mips_msg}") # Reply if topic == self._reply_topic: +<<<<<<< HEAD self.log_debug(f'on request reply, {mips_msg}') +======= + self.log_debug(f"on request reply, {mips_msg}") +>>>>>>> 83899f8 (fomatted code) req: Optional[_MipsRequest] = self._request_map.pop( str(mips_msg.mid), None) if req: @@ -1567,20 +2082,37 @@ class MipsLocalClient(_MipsClient): req.timer.cancel() if req.on_reply: self.main_loop.call_soon_threadsafe( +<<<<<<< HEAD req.on_reply, mips_msg.payload or '{}', req.on_reply_ctx) return # Broadcast bc_list: list[_MipsBroadcast] = list(self._msg_matcher.iter_match( topic=topic)) +======= + req.on_reply, mips_msg.payload or "{}", + req.on_reply_ctx) + return + # Broadcast + bc_list: list[_MipsBroadcast] = list( + self._msg_matcher.iter_match(topic=topic)) +>>>>>>> 83899f8 (fomatted code) if bc_list: self.log_debug(f'on broadcast, {topic}, {mips_msg}') for item in bc_list or []: if item.handler is None: continue self.main_loop.call_soon_threadsafe( +<<<<<<< HEAD item.handler, topic[topic.find('/')+1:], mips_msg.payload or '{}', item.handler_ctx) +======= + item.handler, + topic[topic.find("/") + 1:], + mips_msg.payload or "{}", + item.handler_ctx, + ) +>>>>>>> 83899f8 (fomatted code) return # Device list change if topic == self._dev_list_change_topic: @@ -1600,7 +2132,11 @@ class MipsLocalClient(_MipsClient): return self.log_debug( +<<<<<<< HEAD f'mips local client, recv unknown msg, {topic} -> {mips_msg}') +======= + f"mips local client, recv unknown msg, {topic} -> {mips_msg}") +>>>>>>> 83899f8 (fomatted code) @property def __gen_mips_id(self) -> int: @@ -1630,6 +2166,7 @@ class MipsLocalClient(_MipsClient): on_reply_ctx: Any = None, timeout_ms: int = 10000 ) -> bool: if topic is None or payload is None or on_reply is None: +<<<<<<< HEAD raise MIoTMipsError('invalid params') self._internal_loop.call_soon_threadsafe( self.__request, topic, payload, on_reply, on_reply_ctx, timeout_ms) @@ -1642,6 +2179,19 @@ class MipsLocalClient(_MipsClient): self._internal_loop.call_soon_threadsafe( self.__reg_broadcast, topic, handler, handler_ctx) +======= + raise MIoTMipsError("invalid params") + self._internal_loop.call_soon_threadsafe(self.__request, topic, payload, + on_reply, on_reply_ctx, + timeout_ms) + return True + + def __reg_broadcast_external(self, topic: str, + handler: Callable[[str, str, Any], None], + handler_ctx: Any) -> bool: + self._internal_loop.call_soon_threadsafe(self.__reg_broadcast, topic, + handler, handler_ctx) +>>>>>>> 83899f8 (fomatted code) return True def __unreg_broadcast_external(self, topic) -> bool: @@ -1650,9 +2200,10 @@ class MipsLocalClient(_MipsClient): return True @final - async def __request_async( - self, topic: str, payload: str, timeout_ms: int = 10000 - ) -> dict: + async def __request_async(self, + topic: str, + payload: str, + timeout_ms: int = 10000) -> dict: fut_handler: asyncio.Future = self.main_loop.create_future() def on_msg_reply(payload: str, ctx: Any): @@ -1664,7 +2215,12 @@ class MipsLocalClient(_MipsClient): payload=payload, on_reply=on_msg_reply, on_reply_ctx=fut_handler, +<<<<<<< HEAD timeout_ms=timeout_ms): +======= + timeout_ms=timeout_ms, + ): +>>>>>>> 83899f8 (fomatted code) # Request error fut_handler.set_result('internal request error') @@ -1681,11 +2237,19 @@ class MipsLocalClient(_MipsClient): item = self._get_prop_queue[did].pop() _LOGGER.debug('get prop, %s, %s', did, item) result_obj = await self.__request_async( +<<<<<<< HEAD topic='proxy/get', payload=item['param'], timeout_ms=item['timeout_ms']) if result_obj is None or 'value' not in result_obj: item['fut'].set_result(None) +======= + topic="proxy/get", + payload=item["param"], + timeout_ms=item["timeout_ms"]) + if result_obj is None or "value" not in result_obj: + item["fut"].set_result(None) +>>>>>>> 83899f8 (fomatted code) else: item['fut'].set_result(result_obj['value']) @@ -1694,7 +2258,13 @@ class MipsLocalClient(_MipsClient): if self._get_prop_queue: self._get_prop_timer = self.main_loop.call_later( +<<<<<<< HEAD 0.1, lambda: self.main_loop.create_task( self.__get_prop_timer_handle())) +======= + 0.1, + lambda: self.main_loop.create_task(self.__get_prop_timer_handle( + ))) +>>>>>>> 83899f8 (fomatted code) else: self._get_prop_timer = None diff --git a/custom_components/xiaomi_home/select.py b/custom_components/xiaomi_home/select.py index 3804d63..a49fc06 100644 --- a/custom_components/xiaomi_home/select.py +++ b/custom_components/xiaomi_home/select.py @@ -66,7 +66,11 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up a config entry.""" +<<<<<<< HEAD device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][ +======= + device_list: list[MIoTDevice] = hass.data[DOMAIN]["devices"][ +>>>>>>> 83899f8 (fomatted code) config_entry.entry_id] new_entities = [] @@ -80,12 +84,25 @@ async def async_setup_entry( # create select for light new_light_select_entities = [] for miot_device in device_list: +<<<<<<< HEAD # Add it to all devices with light entities, because some bathroom heaters and clothes drying racks also have lights. # if "device:light" in miot_device.spec_instance.urn: if miot_device.entity_list.get("light", []): device_id = list(miot_device.device_info.get("identifiers"))[0][1] new_light_select_entities.append( LightCommandSendMode(hass=hass, device_id=device_id)) +======= + if "device:light" in miot_device.spec_instance.urn: + if miot_device.entity_list.get("light", []): + device_id = list( + miot_device.device_info.get("identifiers"))[0][1] + light_entity_id = miot_device.gen_device_entity_id(DOMAIN) + new_light_select_entities.append( + LightCommandSendMode(hass=hass, + light_entity_id=light_entity_id, + device_id=device_id)) + +>>>>>>> 83899f8 (fomatted code) if new_light_select_entities: async_add_entities(new_light_select_entities) @@ -100,8 +117,13 @@ class Select(MIoTPropertyEntity, SelectEntity): async def async_select_option(self, option: str) -> None: """Change the selected option.""" +<<<<<<< HEAD await self.set_property_async( value=self.get_vlist_value(description=option)) +======= + await self.set_property_async(value=self.get_vlist_value( + description=option)) +>>>>>>> 83899f8 (fomatted code) @property def current_option(self) -> Optional[str]: @@ -114,19 +136,34 @@ class LightCommandSendMode(SelectEntity, RestoreEntity): then send other color temperatures and brightness or send them all at the same time. The default is to send one by one.""" +<<<<<<< HEAD def __init__(self, hass: HomeAssistant, device_id: str): +======= + def __init__(self, hass: HomeAssistant, light_entity_id: str, + device_id: str): +>>>>>>> 83899f8 (fomatted code) super().__init__() self.hass = hass self._device_id = device_id self._attr_name = "Command Send Mode" +<<<<<<< HEAD self.entity_id = f"select.light_{device_id}_command_send_mode" self._attr_unique_id = self.entity_id +======= + self._attr_unique_id = f"{light_entity_id}_command_send_mode" +>>>>>>> 83899f8 (fomatted code) self._attr_options = [ "Send One by One", "Send Turn On First", "Send Together" ] self._attr_device_info = {"identifiers": {(DOMAIN, device_id)}} +<<<<<<< HEAD self._attr_current_option = self._attr_options[0] self._attr_entity_category = EntityCategory.CONFIG +======= + self._attr_current_option = self._attr_options[0] # 默认选项 + self._attr_entity_category = (EntityCategory.CONFIG + ) # **重点:告诉 HA 这是配置类实体** +>>>>>>> 83899f8 (fomatted code) async def async_select_option(self, option: str): if option in self._attr_options: From b95a2c18eec4439ef4bae496411f848726cbf6ef Mon Sep 17 00:00:00 2001 From: GavinIves Date: Sun, 28 Dec 2025 14:29:55 +0000 Subject: [PATCH 3/5] review --- custom_components/xiaomi_home/light.py | 109 -- .../xiaomi_home/miot/miot_client.py | 950 ------------------ .../xiaomi_home/miot/miot_cloud.py | 381 ------- .../xiaomi_home/miot/miot_device.py | 447 -------- .../xiaomi_home/miot/miot_lan.py | 478 --------- .../xiaomi_home/miot/miot_mips.py | 562 ----------- custom_components/xiaomi_home/select.py | 37 - 7 files changed, 2964 deletions(-) diff --git a/custom_components/xiaomi_home/light.py b/custom_components/xiaomi_home/light.py index 50350ad..ec47607 100644 --- a/custom_components/xiaomi_home/light.py +++ b/custom_components/xiaomi_home/light.py @@ -80,11 +80,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up a config entry.""" -<<<<<<< HEAD device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][ -======= - device_list: list[MIoTDevice] = hass.data[DOMAIN]["devices"][ ->>>>>>> 83899f8 (fomatted code) config_entry.entry_id] new_entities = [] @@ -110,14 +106,9 @@ class Light(MIoTServiceEntity, LightEntity): _brightness_scale: Optional[tuple[int, int]] _mode_map: Optional[dict[Any, Any]] -<<<<<<< HEAD def __init__( self, miot_device: MIoTDevice, entity_data: MIoTEntityData,hass: HomeAssistant ) -> None: -======= - def __init__(self, miot_device: MIoTDevice, entity_data: MIoTEntityData, - hass: HomeAssistant) -> None: ->>>>>>> 83899f8 (fomatted code) """Initialize the Light.""" super().__init__(miot_device=miot_device, entity_data=entity_data) self.hass = hass @@ -158,13 +149,8 @@ class Light(MIoTServiceEntity, LightEntity): self._attr_supported_features |= LightEntityFeature.EFFECT self._prop_mode = prop else: -<<<<<<< HEAD _LOGGER.info( 'invalid brightness format, %s', self.entity_id) -======= - _LOGGER.info("invalid brightness format, %s", - self.entity_id) ->>>>>>> 83899f8 (fomatted code) continue # color-temperature if prop.name == 'color-temperature': @@ -190,7 +176,6 @@ class Light(MIoTServiceEntity, LightEntity): mode_list = prop.value_list.to_map() elif prop.value_range: mode_list = {} -<<<<<<< HEAD if ( int(( prop.value_range.max_ @@ -198,11 +183,6 @@ class Light(MIoTServiceEntity, LightEntity): ) / prop.value_range.step) > self._VALUE_RANGE_MODE_COUNT_MAX ): -======= - if (int((prop.value_range.max_ - prop.value_range.min_) / - prop.value_range.step) - > self._VALUE_RANGE_MODE_COUNT_MAX): ->>>>>>> 83899f8 (fomatted code) _LOGGER.error( 'too many mode values, %s, %s, %s', self.entity_id, prop.name, prop.value_range) @@ -210,14 +190,8 @@ class Light(MIoTServiceEntity, LightEntity): for value in range( prop.value_range.min_, prop.value_range.max_, -<<<<<<< HEAD prop.value_range.step): mode_list[value] = f'mode {value}' -======= - prop.value_range.step, - ): - mode_list[value] = f"mode {value}" ->>>>>>> 83899f8 (fomatted code) if mode_list: self._mode_map = mode_list self._attr_effect_list = list(self._mode_map.values()) @@ -271,14 +245,9 @@ class Light(MIoTServiceEntity, LightEntity): @property def effect(self) -> Optional[str]: """Return the current mode.""" -<<<<<<< HEAD return self.get_map_value( map_=self._mode_map, key=self.get_prop_value(prop=self._prop_mode)) -======= - return self.get_map_value(map_=self._mode_map, - key=self.get_prop_value(prop=self._prop_mode)) ->>>>>>> 83899f8 (fomatted code) async def async_turn_on(self, **kwargs) -> None: """Turn the light on. @@ -316,7 +285,6 @@ class Light(MIoTServiceEntity, LightEntity): # 开始发送开灯命令 if command_send_mode and command_send_mode.state == "Send Together": set_properties_list: List[Dict[str, Any]] = [] -<<<<<<< HEAD # mode if ATTR_EFFECT in kwargs: set_properties_list.append({ @@ -328,18 +296,6 @@ class Light(MIoTServiceEntity, LightEntity): if send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) -======= - if self._prop_on: - value_on = True if self._prop_on.format_ == bool else 1 # noqa: E721 - set_properties_list.append({ - "prop": self._prop_on, - "value": value_on - }) - # brightness - if ATTR_BRIGHTNESS in kwargs: - brightness = brightness_to_value(self._brightness_scale, - kwargs[ATTR_BRIGHTNESS]) ->>>>>>> 83899f8 (fomatted code) set_properties_list.append({ "prop": self._prop_brightness, "value": brightness @@ -362,7 +318,6 @@ class Light(MIoTServiceEntity, LightEntity): "value": rgb }) self._attr_color_mode = ColorMode.RGB -<<<<<<< HEAD # brightness if not send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( @@ -379,33 +334,16 @@ class Light(MIoTServiceEntity, LightEntity): "value": value_on }) await self.set_properties_async(set_properties_list,write_ha_state=False) -======= - # mode - if ATTR_EFFECT in kwargs: - set_properties_list.append({ - "prop": - self._prop_mode, - "value": - self.get_map_key(map_=self._mode_map, - value=kwargs[ATTR_EFFECT]), - }) - await self.set_properties_async(set_properties_list) ->>>>>>> 83899f8 (fomatted code) self.async_write_ha_state() elif command_send_mode and command_send_mode.state == "Send Turn On First": set_properties_list: List[Dict[str, Any]] = [] if self._prop_on: -<<<<<<< HEAD value_on = True if self._prop_on.format_ == bool else 1 -======= - value_on = True if self._prop_on.format_ == bool else 1 # noqa: E721 ->>>>>>> 83899f8 (fomatted code) set_properties_list.append({ "prop": self._prop_on, "value": value_on }) -<<<<<<< HEAD # mode if ATTR_EFFECT in kwargs: set_properties_list.append({ @@ -419,14 +357,6 @@ class Light(MIoTServiceEntity, LightEntity): if send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( self._brightness_scale,kwargs[ATTR_BRIGHTNESS]) -======= - await self.set_property_async(prop=self._prop_on, - value=value_on) - # brightness - if ATTR_BRIGHTNESS in kwargs: - brightness = brightness_to_value(self._brightness_scale, - kwargs[ATTR_BRIGHTNESS]) ->>>>>>> 83899f8 (fomatted code) set_properties_list.append({ "prop": self._prop_brightness, "value": brightness @@ -449,7 +379,6 @@ class Light(MIoTServiceEntity, LightEntity): "value": rgb }) self._attr_color_mode = ColorMode.RGB -<<<<<<< HEAD # brightness if not send_brightness_first and ATTR_BRIGHTNESS in kwargs: brightness = brightness_to_value( @@ -460,23 +389,10 @@ class Light(MIoTServiceEntity, LightEntity): }) await self.set_properties_async(set_properties_list,write_ha_state=False) -======= - # mode - if ATTR_EFFECT in kwargs: - set_properties_list.append({ - "prop": - self._prop_mode, - "value": - self.get_map_key(map_=self._mode_map, - value=kwargs[ATTR_EFFECT]), - }) - await self.set_properties_async(set_properties_list) ->>>>>>> 83899f8 (fomatted code) self.async_write_ha_state() else: if self._prop_on: -<<<<<<< HEAD value_on = True if self._prop_on.format_ == bool else 1 await self.set_property_async( prop=self._prop_on, value=value_on) @@ -487,18 +403,6 @@ class Light(MIoTServiceEntity, LightEntity): await self.set_property_async( prop=self._prop_brightness, value=brightness, write_ha_state=False) -======= - value_on = True if self._prop_on.format_ == bool else 1 # noqa: E721 - await self.set_property_async(prop=self._prop_on, - value=value_on) - # brightness - if ATTR_BRIGHTNESS in kwargs: - brightness = brightness_to_value(self._brightness_scale, - kwargs[ATTR_BRIGHTNESS]) - await self.set_property_async(prop=self._prop_brightness, - value=brightness, - write_ha_state=False) ->>>>>>> 83899f8 (fomatted code) # color-temperature if ATTR_COLOR_TEMP_KELVIN in kwargs: await self.set_property_async( @@ -512,30 +416,17 @@ class Light(MIoTServiceEntity, LightEntity): g = kwargs[ATTR_RGB_COLOR][1] b = kwargs[ATTR_RGB_COLOR][2] rgb = (r << 16) | (g << 8) | b -<<<<<<< HEAD await self.set_property_async( prop=self._prop_color, value=rgb, write_ha_state=False) -======= - await self.set_property_async(prop=self._prop_color, - value=rgb, - write_ha_state=False) ->>>>>>> 83899f8 (fomatted code) self._attr_color_mode = ColorMode.RGB # mode if ATTR_EFFECT in kwargs: await self.set_property_async( prop=self._prop_mode, -<<<<<<< HEAD value=self.get_map_key( map_=self._mode_map, value=kwargs[ATTR_EFFECT]), write_ha_state=False) -======= - value=self.get_map_key(map_=self._mode_map, - value=kwargs[ATTR_EFFECT]), - write_ha_state=False, - ) ->>>>>>> 83899f8 (fomatted code) self.async_write_ha_state() async def async_turn_off(self, **kwargs) -> None: diff --git a/custom_components/xiaomi_home/miot/miot_client.py b/custom_components/xiaomi_home/miot/miot_client.py index 01f89eb..c17fa62 100644 --- a/custom_components/xiaomi_home/miot/miot_client.py +++ b/custom_components/xiaomi_home/miot/miot_client.py @@ -205,17 +205,10 @@ class MIoTClient: raise MIoTClientError('invalid mips service') self._entry_id = entry_id self._entry_data = entry_data -<<<<<<< HEAD self._uid = entry_data['uid'] self._cloud_server = entry_data['cloud_server'] self._ctrl_mode = CtrlMode.load( entry_data.get('ctrl_mode', DEFAULT_CTRL_MODE)) -======= - self._uid = entry_data["uid"] - self._cloud_server = entry_data["cloud_server"] - self._ctrl_mode = CtrlMode.load( - entry_data.get("ctrl_mode", DEFAULT_CTRL_MODE)) ->>>>>>> 83899f8 (fomatted code) self._network = network self._storage = storage self._mips_service = mips_service @@ -252,21 +245,12 @@ class MIoTClient: self._show_devices_changed_notify_timer = None self._display_devs_notify = entry_data.get( -<<<<<<< HEAD 'display_devices_changed_notify', ['add', 'del', 'offline']) self._display_notify_content_hash = None self._display_binary_text = 'text' in entry_data.get( 'display_binary_mode', ['text']) self._display_binary_bool = 'bool' in entry_data.get( 'display_binary_mode', ['text']) -======= - "display_devices_changed_notify", ["add", "del", "offline"]) - self._display_notify_content_hash = None - self._display_binary_text = "text" in entry_data.get( - "display_binary_mode", ["text"]) - self._display_binary_bool = "bool" in entry_data.get( - "display_binary_mode", ["text"]) ->>>>>>> 83899f8 (fomatted code) async def init_async(self) -> None: # Load user config and check @@ -289,16 +273,9 @@ class MIoTClient: _LOGGER.debug('user config, %s', json.dumps(p_user_config)) # MIoT i18n client self._i18n = MIoTI18n( -<<<<<<< HEAD lang=self._entry_data.get( 'integration_language', DEFAULT_INTEGRATION_LANGUAGE), loop=self._main_loop) -======= - lang=self._entry_data.get("integration_language", - DEFAULT_INTEGRATION_LANGUAGE), - loop=self._main_loop, - ) ->>>>>>> 83899f8 (fomatted code) await self._i18n.init_async() # Load cache device list await self.__load_cache_device_async() @@ -316,16 +293,10 @@ class MIoTClient: access_token=self._user_config['auth_info']['access_token'], loop=self._main_loop) # MIoT cert client -<<<<<<< HEAD self._cert = MIoTCert( storage=self._storage, uid=self._uid, cloud_server=self.cloud_server) -======= - self._cert = MIoTCert(storage=self._storage, - uid=self._uid, - cloud_server=self.cloud_server) ->>>>>>> 83899f8 (fomatted code) # MIoT cloud mips client self._mips_cloud = MipsCloudClient( uuid=self._entry_data['uuid'], @@ -339,14 +310,8 @@ class MIoTClient: handler=self.__on_mips_cloud_state_changed) # Subscribe network status self._network.sub_network_status( -<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}', handler=self.__on_network_status_changed) -======= - key=f"{self._uid}-{self._cloud_server}", - handler=self.__on_network_status_changed, - ) ->>>>>>> 83899f8 (fomatted code) await self.__on_network_status_changed( status=self._network.network_status) # Create multi mips local client instance according to the @@ -361,7 +326,6 @@ class MIoTClient: group_id=info['group_id'], handler=self.__on_mips_service_state_change) service_data = self._mips_service.get_services( -<<<<<<< HEAD group_id=info['group_id']).get(info['group_id'], None) if not service_data: _LOGGER.info( @@ -370,15 +334,6 @@ class MIoTClient: _LOGGER.info( 'central mips service scanned, %s, %s', home_id, service_data) -======= - group_id=info["group_id"]).get(info["group_id"], None) - if not service_data: - _LOGGER.info("central mips service not scanned, %s", - home_id) - continue - _LOGGER.info("central mips service scanned, %s, %s", - home_id, service_data) ->>>>>>> 83899f8 (fomatted code) mips = MipsLocalClient( did=self._entry_data['virtual_did'], group_id=info['group_id'], @@ -393,20 +348,12 @@ class MIoTClient: mips.enable_logger(logger=_LOGGER) mips.on_dev_list_changed = self.__on_gw_device_list_changed mips.sub_mips_state( -<<<<<<< HEAD key=info['group_id'], -======= - key=info["group_id"], ->>>>>>> 83899f8 (fomatted code) handler=self.__on_mips_local_state_changed) mips.connect() # Lan ctrl await self._miot_lan.vote_for_lan_ctrl_async( -<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}', vote=True) -======= - key=f"{self._uid}-{self._cloud_server}", vote=True) ->>>>>>> 83899f8 (fomatted code) self._miot_lan.sub_lan_state( key=f'{self._uid}-{self._cloud_server}', handler=self.__on_miot_lan_state_change) @@ -414,7 +361,6 @@ class MIoTClient: await self.__on_miot_lan_state_change(True) else: self._miot_lan.unsub_lan_state( -<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') if self._miot_lan.init_done: self._miot_lan.unsub_device_state( @@ -423,26 +369,12 @@ class MIoTClient: devices=list(self._device_list_cache.keys())) await self._miot_lan.vote_for_lan_ctrl_async( key=f'{self._uid}-{self._cloud_server}', vote=False) -======= - key=f"{self._uid}-{self._cloud_server}") - if self._miot_lan.init_done: - self._miot_lan.unsub_device_state( - key=f"{self._uid}-{self._cloud_server}") - self._miot_lan.delete_devices( - devices=list(self._device_list_cache.keys())) - await self._miot_lan.vote_for_lan_ctrl_async( - key=f"{self._uid}-{self._cloud_server}", vote=False) ->>>>>>> 83899f8 (fomatted code) _LOGGER.info('init_async, %s, %s', self._uid, self._cloud_server) async def deinit_async(self) -> None: self._network.unsub_network_status( -<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') -======= - key=f"{self._uid}-{self._cloud_server}") ->>>>>>> 83899f8 (fomatted code) # Cancel refresh props if self._refresh_props_timer: self._refresh_props_timer.cancel() @@ -451,11 +383,7 @@ class MIoTClient: self._refresh_props_retry_count = 0 # Cloud mips self._mips_cloud.unsub_mips_state( -<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') -======= - key=f"{self._uid}-{self._cloud_server}") ->>>>>>> 83899f8 (fomatted code) self._mips_cloud.deinit() # Cancel refresh cloud devices if self._refresh_cloud_devices_timer: @@ -465,17 +393,12 @@ class MIoTClient: # Central hub gateway mips if self._cloud_server in SUPPORT_CENTRAL_GATEWAY_CTRL: self._mips_service.unsub_service_change( -<<<<<<< HEAD key=f'{self._uid}-{self._cloud_server}') -======= - key=f"{self._uid}-{self._cloud_server}") ->>>>>>> 83899f8 (fomatted code) for mips in self._mips_local.values(): mips.on_dev_list_changed = None mips.unsub_mips_state(key=mips.group_id) mips.deinit() if self._mips_local_state_changed_timers: -<<<<<<< HEAD for timer_item in ( self._mips_local_state_changed_timers.values()): timer_item.cancel() @@ -489,21 +412,6 @@ class MIoTClient: devices=list(self._device_list_cache.keys())) await self._miot_lan.vote_for_lan_ctrl_async( key=f'{self._uid}-{self._cloud_server}', vote=False) -======= - for timer_item in self._mips_local_state_changed_timers.values( - ): - timer_item.cancel() - self._mips_local_state_changed_timers.clear() - self._miot_lan.unsub_lan_state( - key=f"{self._uid}-{self._cloud_server}") - if self._miot_lan.init_done: - self._miot_lan.unsub_device_state( - key=f"{self._uid}-{self._cloud_server}") - self._miot_lan.delete_devices( - devices=list(self._device_list_cache.keys())) - await self._miot_lan.vote_for_lan_ctrl_async( - key=f"{self._uid}-{self._cloud_server}", vote=False) ->>>>>>> 83899f8 (fomatted code) # Cancel refresh auth info if self._refresh_token_timer: self._refresh_token_timer.cancel() @@ -518,7 +426,6 @@ class MIoTClient: await self._oauth.deinit_async() await self._http.deinit_async() # Remove notify -<<<<<<< HEAD self._persistence_notify( self.__gen_notify_key('dev_list_changed'), None, None) self.__show_client_error_notify( @@ -529,14 +436,6 @@ class MIoTClient: message=None, notify_key='device_cache') self.__show_client_error_notify( message=None, notify_key='device_cloud') -======= - self._persistence_notify(self.__gen_notify_key("dev_list_changed"), - None, None) - self.__show_client_error_notify(message=None, notify_key="oauth_info") - self.__show_client_error_notify(message=None, notify_key="user_cert") - self.__show_client_error_notify(message=None, notify_key="device_cache") - self.__show_client_error_notify(message=None, notify_key="device_cloud") ->>>>>>> 83899f8 (fomatted code) _LOGGER.info('deinit_async, %s', self._uid) @@ -618,13 +517,8 @@ class MIoTClient: if value: self.__request_show_devices_changed_notify() else: -<<<<<<< HEAD self._persistence_notify( self.__gen_notify_key('dev_list_changed'), None, None) -======= - self._persistence_notify(self.__gen_notify_key("dev_list_changed"), - None, None) ->>>>>>> 83899f8 (fomatted code) @property def device_list(self) -> dict: @@ -644,7 +538,6 @@ class MIoTClient: # Load auth info auth_info: Optional[dict] = None user_config: dict = await self._storage.load_user_config_async( -<<<<<<< HEAD uid=self._uid, cloud_server=self._cloud_server, keys=['auth_info']) if ( @@ -658,23 +551,10 @@ class MIoTClient: or 'refresh_token' not in auth_info ): raise MIoTClientError('invalid auth info') -======= - uid=self._uid, - cloud_server=self._cloud_server, - keys=["auth_info"]) - if (not user_config or - (auth_info := user_config.get("auth_info", None)) is None): - raise MIoTClientError("load_user_config_async error") - if ("expires_ts" not in auth_info or - "access_token" not in auth_info or - "refresh_token" not in auth_info): - raise MIoTClientError("invalid auth info") ->>>>>>> 83899f8 (fomatted code) # Determine whether to update token refresh_time = int(auth_info['expires_ts'] - time.time()) if refresh_time <= 60: valid_auth_info = await self._oauth.refresh_access_token_async( -<<<<<<< HEAD refresh_token=auth_info['refresh_token']) auth_info = valid_auth_info # Update http token @@ -692,26 +572,6 @@ class MIoTClient: 'refresh oauth info, get new access_token, %s', auth_info) refresh_time = int(auth_info['expires_ts'] - time.time()) -======= - refresh_token=auth_info["refresh_token"]) - auth_info = valid_auth_info - # Update http token - self._http.update_http_header( - access_token=valid_auth_info["access_token"]) - # Update mips cloud token - self._mips_cloud.update_access_token( - access_token=valid_auth_info["access_token"]) - # Update storage - if not await self._storage.update_user_config_async( - uid=self._uid, - cloud_server=self._cloud_server, - config={"auth_info": auth_info}, - ): - raise MIoTClientError("update_user_config_async error") - _LOGGER.info("refresh oauth info, get new access_token, %s", - auth_info) - refresh_time = int(auth_info["expires_ts"] - time.time()) ->>>>>>> 83899f8 (fomatted code) if refresh_time <= 0: raise MIoTClientError('invalid expires time') self.__show_client_error_notify(None, 'oauth_info') @@ -724,14 +584,8 @@ class MIoTClient: except Exception as err: self.__show_client_error_notify( message=self._i18n.translate( -<<<<<<< HEAD 'miot.client.invalid_oauth_info'), # type: ignore notify_key='oauth_info') -======= - "miot.client.invalid_oauth_info"), # type: ignore - notify_key="oauth_info", - ) ->>>>>>> 83899f8 (fomatted code) _LOGGER.error( 'refresh oauth info error (%s, %s), %s, %s', self._uid, self._cloud_server, err, traceback.format_exc()) @@ -742,16 +596,10 @@ class MIoTClient: if self._cloud_server not in SUPPORT_CENTRAL_GATEWAY_CTRL: return True if not await self._cert.verify_ca_cert_async(): -<<<<<<< HEAD raise MIoTClientError('ca cert is not ready') refresh_time = ( await self._cert.user_cert_remaining_time_async() - MIHOME_CERT_EXPIRE_MARGIN) -======= - raise MIoTClientError("ca cert is not ready") - refresh_time = (await self._cert.user_cert_remaining_time_async() - - MIHOME_CERT_EXPIRE_MARGIN) ->>>>>>> 83899f8 (fomatted code) if refresh_time <= 60: user_key = await self._cert.load_user_key_async() if not user_key: @@ -759,11 +607,7 @@ class MIoTClient: if not await self._cert.update_user_key_async(key=user_key): raise MIoTClientError('update_user_key_async failed') csr_str = self._cert.gen_user_csr( -<<<<<<< HEAD user_key=user_key, did=self._entry_data['virtual_did']) -======= - user_key=user_key, did=self._entry_data["virtual_did"]) ->>>>>>> 83899f8 (fomatted code) crt_str = await self.miot_http.get_central_cert_async(csr_str) if not await self._cert.update_user_cert_async(cert=crt_str): raise MIoTClientError('update user cert error') @@ -784,7 +628,6 @@ class MIoTClient: except MIoTClientError as error: self.__show_client_error_notify( message=self._i18n.translate( -<<<<<<< HEAD 'miot.client.invalid_cert_info'), # type: ignore notify_key='user_cert') _LOGGER.error( @@ -795,24 +638,12 @@ class MIoTClient: async def set_prop_async( self, did: str, siid: int, piid: int, value: Any ) -> bool: -======= - "miot.client.invalid_cert_info"), # type: ignore - notify_key="user_cert", - ) - _LOGGER.error("refresh user cert error, %s, %s", error, - traceback.format_exc()) - return False - - async def set_prop_async(self, did: str, siid: int, piid: int, - value: Any) -> bool: ->>>>>>> 83899f8 (fomatted code) if did not in self._device_list_cache: raise MIoTClientError(f'did not exist, {did}') # Priority local control if self._ctrl_mode == CtrlMode.AUTO: # Gateway control device_gw = self._device_list_gateway.get(did, None) -<<<<<<< HEAD if ( device_gw and device_gw.get('online', False) and device_gw.get('specv2_access', False) @@ -831,30 +662,12 @@ class MIoTClient: did, siid, piid, value, result) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) -======= - if (device_gw and device_gw.get("online", False) and - device_gw.get("specv2_access", False) and - "group_id" in device_gw): - mips = self._mips_local.get(device_gw["group_id"], None) - if mips is None: - _LOGGER.error("no gw route, %s, try control throw cloud", - device_gw) - else: - result = await mips.set_prop_async(did=did, - siid=siid, - piid=piid, - value=value) - rc = (result or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) ->>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return True raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) # Lan control device_lan = self._device_list_lan.get(did, None) -<<<<<<< HEAD if device_lan and device_lan.get('online', False): result = await self._miot_lan.set_prop_async( did=did, siid=siid, piid=piid, value=value) @@ -863,18 +676,6 @@ class MIoTClient: did, siid, piid, value, result) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) -======= - if device_lan and device_lan.get("online", False): - result = await self._miot_lan.set_prop_async(did=did, - siid=siid, - piid=piid, - value=value) - _LOGGER.debug("lan set prop, %s.%d.%d, %s -> %s", did, siid, - piid, value, result) - rc = (result or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) ->>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return True raise MIoTClientError( @@ -882,39 +683,23 @@ class MIoTClient: # Cloud control device_cloud = self._device_list_cloud.get(did, None) -<<<<<<< HEAD if device_cloud and device_cloud.get('online', False): result = await self._http.set_prop_async( params=[ {'did': did, 'siid': siid, 'piid': piid, 'value': value} ]) -======= - if device_cloud and device_cloud.get("online", False): - result = await self._http.set_prop_async(params=[{ - "did": did, - "siid": siid, - "piid": piid, - "value": value - }]) ->>>>>>> 83899f8 (fomatted code) _LOGGER.debug( 'cloud set prop, %s.%d.%d, %s -> %s', did, siid, piid, value, result) if result and len(result) == 1: -<<<<<<< HEAD rc = result[0].get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) -======= - rc = result[0].get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) ->>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return True if rc in [-704010000, -704042011]: # Device remove or offline _LOGGER.error('device may be removed or offline, %s', did) self._main_loop.create_task( -<<<<<<< HEAD await self.__refresh_cloud_device_with_dids_async( dids=[did])) raise MIoTClientError( @@ -924,16 +709,6 @@ class MIoTClient: raise MIoTClientError( f'{self._i18n.translate("miot.client.device_exec_error")}, ' f'{self._i18n.translate("error.common.-10007")}') -======= - await - self.__refresh_cloud_device_with_dids_async(dids=[did])) - raise MIoTClientError(self.__get_exec_error_with_rc(rc=rc)) - - # Show error message - raise MIoTClientError( - f"{self._i18n.translate('miot.client.device_exec_error')}, " - f"{self._i18n.translate('error.common.-10007')}") ->>>>>>> 83899f8 (fomatted code) async def set_props_async( self, props_list: List[Dict[str, Any]], @@ -951,7 +726,6 @@ class MIoTClient: if self._ctrl_mode == CtrlMode.AUTO: # Gateway control device_gw = self._device_list_gateway.get(did, None) -<<<<<<< HEAD if ( device_gw and device_gw.get("online", False) and device_gw.get("specv2_access", False) and "group_id" in device_gw @@ -968,57 +742,25 @@ class MIoTClient: rc = [(r or {}).get("code", MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) for r in result] -======= - if (device_gw and device_gw.get("online", False) and - device_gw.get("specv2_access", False) and - "group_id" in device_gw): - mips = self._mips_local.get(device_gw["group_id"], None) - if mips is None: - _LOGGER.error("no gw route, %s, try control throw cloud", - device_gw) - else: - result = await mips.set_props_async(did=did, - props_list=props_list) - rc = {(r or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) - for r in result} ->>>>>>> 83899f8 (fomatted code) if all(t in [0, 1] for t in rc): return True else: raise MIoTClientError( -<<<<<<< HEAD self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) -======= - self.__get_exec_error_with_rc(rc=(rc - {0, 1})[0])) ->>>>>>> 83899f8 (fomatted code) # Lan control device_lan = self._device_list_lan.get(did, None) if device_lan and device_lan.get("online", False): result = await self._miot_lan.set_props_async( did=did, props_list=props_list) -<<<<<<< HEAD _LOGGER.debug("lan set props, %s -> %s", props_list, result) rc = [(r or {}).get("code", MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) for r in result] -======= - _LOGGER.debug("lan set prop, %s -> %s", props_list, result) - rc = {(r or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) - for r in result} ->>>>>>> 83899f8 (fomatted code) if all(t in [0, 1] for t in rc): return True else: raise MIoTClientError( -<<<<<<< HEAD self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) -======= - self.__get_exec_error_with_rc(rc=(rc - {0, 1})[0])) ->>>>>>> 83899f8 (fomatted code) # Cloud control device_cloud = self._device_list_cloud.get(did, None) if device_cloud and device_cloud.get("online", False): @@ -1027,16 +769,9 @@ class MIoTClient: "cloud set props, %s, result, %s", props_list, result) if result and len(result) == len(props_list): -<<<<<<< HEAD rc = [(r or {}).get("code", MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) for r in result] -======= - rc = {(r or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) - for r in result} ->>>>>>> 83899f8 (fomatted code) if all(t in [0, 1] for t in rc): return True if any(t in [-704010000, -704042011] for t in rc): @@ -1045,7 +780,6 @@ class MIoTClient: self._main_loop.create_task( await self.__refresh_cloud_device_with_dids_async(dids=[did])) -<<<<<<< HEAD raise MIoTClientError( self.__get_exec_error_with_rc(rc=next(x for x in rc if x not in (0, 1)))) @@ -1053,16 +787,6 @@ class MIoTClient: raise MIoTClientError( f'{self._i18n.translate("miot.client.device_exec_error")}, ' f'{self._i18n.translate("error.common.-10007")}') -======= - else: - raise MIoTClientError( - self.__get_exec_error_with_rc(rc=(rc - {0, 1})[0])) - - # Show error message - raise MIoTClientError( - f"{self._i18n.translate('miot.client.device_exec_error')}, " - f"{self._i18n.translate('error.common.-10007')}") ->>>>>>> 83899f8 (fomatted code) def request_refresh_prop( self, did: str, siid: int, piid: int @@ -1077,13 +801,8 @@ class MIoTClient: if self._refresh_props_timer: return self._refresh_props_timer = self._main_loop.call_later( -<<<<<<< HEAD REFRESH_PROPS_DELAY, lambda: self._main_loop.create_task( self.__refresh_props_handler())) -======= - 0.2, - lambda: self._main_loop.create_task(self.__refresh_props_handler())) ->>>>>>> 83899f8 (fomatted code) async def get_prop_async(self, did: str, siid: int, piid: int) -> Any: if did not in self._device_list_cache: @@ -1094,19 +813,12 @@ class MIoTClient: # so obtaining the cache from the cloud is the priority here. try: if self._network.network_status: -<<<<<<< HEAD result = await self._http.get_prop_async( did=did, siid=siid, piid=piid) -======= - result = await self._http.get_prop_async(did=did, - siid=siid, - piid=piid) ->>>>>>> 83899f8 (fomatted code) if result: return result except Exception as err: # pylint: disable=broad-exception-caught # Catch all exceptions -<<<<<<< HEAD _LOGGER.error( 'client get prop from cloud error, %s, %s', err, traceback.format_exc()) @@ -1119,21 +831,9 @@ class MIoTClient: and 'group_id' in device_gw ): mips = self._mips_local.get(device_gw['group_id'], None) -======= - _LOGGER.error("client get prop from cloud error, %s, %s", err, - traceback.format_exc()) - if self._ctrl_mode == CtrlMode.AUTO: - # Central hub gateway - device_gw = self._device_list_gateway.get(did, None) - if (device_gw and device_gw.get("online", False) and - device_gw.get("specv2_access", False) and - "group_id" in device_gw): - mips = self._mips_local.get(device_gw["group_id"], None) ->>>>>>> 83899f8 (fomatted code) if mips is None: _LOGGER.error('no gw route, %s', device_gw) else: -<<<<<<< HEAD return await mips.get_prop_async( did=did, siid=siid, piid=piid) # Lan @@ -1141,36 +841,19 @@ class MIoTClient: if device_lan and device_lan.get('online', False): return await self._miot_lan.get_prop_async( did=did, siid=siid, piid=piid) -======= - return await mips.get_prop_async(did=did, - siid=siid, - piid=piid) - # Lan - device_lan = self._device_list_lan.get(did, None) - if device_lan and device_lan.get("online", False): - return await self._miot_lan.get_prop_async(did=did, - siid=siid, - piid=piid) ->>>>>>> 83899f8 (fomatted code) # _LOGGER.error( # 'client get prop failed, no-link, %s.%d.%d', did, siid, piid) return None -<<<<<<< HEAD async def action_async( self, did: str, siid: int, aiid: int, in_list: list ) -> list: -======= - async def action_async(self, did: str, siid: int, aiid: int, - in_list: list) -> list: ->>>>>>> 83899f8 (fomatted code) if did not in self._device_list_cache: raise MIoTClientError(f'did not exist, {did}') device_gw = self._device_list_gateway.get(did, None) # Priority local control if self._ctrl_mode == CtrlMode.AUTO: -<<<<<<< HEAD if ( device_gw and device_gw.get('online', False) and device_gw.get('specv2_access', False) @@ -1178,36 +861,19 @@ class MIoTClient: ): mips = self._mips_local.get( device_gw['group_id'], None) -======= - if (device_gw and device_gw.get("online", False) and - device_gw.get("specv2_access", False) and - "group_id" in device_gw): - mips = self._mips_local.get(device_gw["group_id"], None) ->>>>>>> 83899f8 (fomatted code) if mips is None: _LOGGER.error('no gw route, %s', device_gw) else: -<<<<<<< HEAD result = await mips.action_async( did=did, siid=siid, aiid=aiid, in_list=in_list) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) -======= - result = await mips.action_async(did=did, - siid=siid, - aiid=aiid, - in_list=in_list) - rc = (result or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) ->>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return result.get('out', []) raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) # Lan control device_lan = self._device_list_lan.get(did, None) -<<<<<<< HEAD if device_lan and device_lan.get('online', False): result = await self._miot_lan.action_async( did=did, siid=siid, aiid=aiid, in_list=in_list) @@ -1215,57 +881,28 @@ class MIoTClient: 'lan action, %s, %s, %s -> %s', did, siid, aiid, result) rc = (result or {}).get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) -======= - if device_lan and device_lan.get("online", False): - result = await self._miot_lan.action_async(did=did, - siid=siid, - aiid=aiid, - in_list=in_list) - _LOGGER.debug("lan action, %s, %s, %s -> %s", did, siid, aiid, - result) - rc = (result or - {}).get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) ->>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return result.get('out', []) raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) # Cloud control device_cloud = self._device_list_cloud.get(did, None) -<<<<<<< HEAD if device_cloud and device_cloud.get('online', False): result: dict = await self._http.action_async( did=did, siid=siid, aiid=aiid, in_list=in_list) if result: rc = result.get( 'code', MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) -======= - if device_cloud and device_cloud.get("online", False): - result: dict = await self._http.action_async(did=did, - siid=siid, - aiid=aiid, - in_list=in_list) - if result: - rc = result.get("code", - MIoTErrorCode.CODE_MIPS_INVALID_RESULT.value) ->>>>>>> 83899f8 (fomatted code) if rc in [0, 1]: return result.get('out', []) if rc in [-704010000, -704042011]: # Device remove or offline _LOGGER.error('device removed or offline, %s', did) self._main_loop.create_task( -<<<<<<< HEAD await self.__refresh_cloud_device_with_dids_async( dids=[did])) raise MIoTClientError( self.__get_exec_error_with_rc(rc=rc)) -======= - await - self.__refresh_cloud_device_with_dids_async(dids=[did])) - raise MIoTClientError(self.__get_exec_error_with_rc(rc=rc)) ->>>>>>> 83899f8 (fomatted code) # TODO: Show error message _LOGGER.error( 'client action failed, %s.%d.%d', did, siid, aiid) @@ -1279,7 +916,6 @@ class MIoTClient: if did not in self._device_list_cache: raise MIoTClientError(f'did not exist, {did}') -<<<<<<< HEAD topic = ( f'{did}/p/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') @@ -1294,20 +930,6 @@ class MIoTClient: topic = ( f'{did}/p/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') -======= - topic = f"{did}/p/{'#' if siid is None or piid is None else f'{siid}/{piid}'}" - self._sub_tree[topic] = MIoTClientSub(topic=topic, - handler=handler, - handler_ctx=handler_ctx) - _LOGGER.debug("client sub prop, %s", topic) - return True - - def unsub_prop(self, - did: str, - siid: Optional[int] = None, - piid: Optional[int] = None) -> bool: - topic = f"{did}/p/{'#' if siid is None or piid is None else f'{siid}/{piid}'}" ->>>>>>> 83899f8 (fomatted code) if self._sub_tree.get(topic=topic): del self._sub_tree[topic] _LOGGER.debug('client unsub prop, %s', topic) @@ -1319,7 +941,6 @@ class MIoTClient: handler_ctx: Any = None ) -> bool: if did not in self._device_list_cache: -<<<<<<< HEAD raise MIoTClientError(f'did not exist, {did}') topic = ( f'{did}/e/' @@ -1335,21 +956,6 @@ class MIoTClient: topic = ( f'{did}/e/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') -======= - raise MIoTClientError(f"did not exist, {did}") - topic = f"{did}/e/{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}" - self._sub_tree[topic] = MIoTClientSub(topic=topic, - handler=handler, - handler_ctx=handler_ctx) - _LOGGER.debug("client sub event, %s", topic) - return True - - def unsub_event(self, - did: str, - siid: Optional[int] = None, - eiid: Optional[int] = None) -> bool: - topic = f"{did}/e/{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}" ->>>>>>> 83899f8 (fomatted code) if self._sub_tree.get(topic=topic): del self._sub_tree[topic] _LOGGER.debug('client unsub event, %s', topic) @@ -1361,18 +967,10 @@ class MIoTClient: ) -> bool: """Call callback handler in main loop""" if did not in self._device_list_cache: -<<<<<<< HEAD raise MIoTClientError(f'did not exist, {did}') self._sub_device_state[did] = MipsDeviceState( did=did, handler=handler, handler_ctx=handler_ctx) _LOGGER.debug('client sub device state, %s', did) -======= - raise MIoTClientError(f"did not exist, {did}") - self._sub_device_state[did] = MipsDeviceState(did=did, - handler=handler, - handler_ctx=handler_ctx) - _LOGGER.debug("client sub device state, %s", did) ->>>>>>> 83899f8 (fomatted code) return True def unsub_device_state(self, did: str) -> bool: @@ -1404,22 +1002,13 @@ class MIoTClient: def __get_exec_error_with_rc(self, rc: int) -> str: err_msg: str = self._i18n.translate( -<<<<<<< HEAD key=f'error.common.{rc}') # type: ignore -======= - key=f"error.common.{rc}") # type: ignore ->>>>>>> 83899f8 (fomatted code) if not err_msg: err_msg = f'{self._i18n.translate(key="error.common.-10000")}, ' err_msg += f'code={rc}' return ( -<<<<<<< HEAD f'{self._i18n.translate(key="miot.client.device_exec_error")}, ' + err_msg) -======= - f"{self._i18n.translate(key='miot.client.device_exec_error')}, " + - err_msg) ->>>>>>> 83899f8 (fomatted code) @final def __gen_notify_key(self, name: str) -> str: @@ -1431,15 +1020,8 @@ class MIoTClient: self._refresh_token_timer.cancel() self._refresh_token_timer = None self._refresh_token_timer = self._main_loop.call_later( -<<<<<<< HEAD delay_sec, lambda: self._main_loop.create_task( self.refresh_oauth_info_async())) -======= - delay_sec, - lambda: self._main_loop.create_task(self.refresh_oauth_info_async() - ), - ) ->>>>>>> 83899f8 (fomatted code) @final def __request_refresh_user_cert(self, delay_sec: int) -> None: @@ -1490,7 +1072,6 @@ class MIoTClient: from_old: Optional[str] = self._sub_source_list.get(did, None) from_new: Optional[str] = None if self._ctrl_mode == CtrlMode.AUTO: -<<<<<<< HEAD if ( did in self._device_list_gateway and self._device_list_gateway[did].get('online', False) @@ -1511,22 +1092,6 @@ class MIoTClient: ): from_new = 'cloud' if (from_new == from_old) and (from_new=='cloud' or from_new=='lan'): -======= - if (did in self._device_list_gateway and - self._device_list_gateway[did].get("online", False) and - self._device_list_gateway[did].get("push_available", - False)): - from_new = self._device_list_gateway[did]["group_id"] - elif (did in self._device_list_lan and - self._device_list_lan[did].get("online", False) and - self._device_list_lan[did].get("push_available", False)): - from_new = "lan" - - if (from_new is None and did in self._device_list_cloud and - self._device_list_cloud[did].get("online", False)): - from_new = "cloud" - if from_new == from_old: ->>>>>>> 83899f8 (fomatted code) # No need to update return # Unsub old @@ -1535,13 +1100,8 @@ class MIoTClient: # Sub new self.__sub_from(from_new, did) self._sub_source_list[did] = from_new -<<<<<<< HEAD _LOGGER.info( 'device sub changed, %s, from %s to %s', did, from_old, from_new) -======= - _LOGGER.info("device sub changed, %s, from %s to %s", did, from_old, - from_new) ->>>>>>> 83899f8 (fomatted code) @final async def __on_network_status_changed(self, status: bool) -> None: @@ -1564,7 +1124,6 @@ class MIoTClient: self._mips_cloud.disconnect() @final -<<<<<<< HEAD async def __on_mips_service_state_change( self, group_id: str, state: MipsServiceState, data: dict ) -> None: @@ -1582,23 +1141,6 @@ class MIoTClient: and mips.host == data['addresses'][0] and mips.port == data['port'] ): -======= - async def __on_mips_service_state_change(self, group_id: str, - state: MipsServiceState, - data: dict) -> None: - _LOGGER.info("mips service state changed, %s, %s, %s", group_id, state, - data) - - mips = self._mips_local.get(group_id, None) - if mips: - if state == MipsServiceState.REMOVED: - mips.disconnect() - self._mips_local.pop(group_id, None) - return - if (mips.client_id == self._entry_data["virtual_did"] and - mips.host == data["addresses"][0] and - mips.port == data["port"]): ->>>>>>> 83899f8 (fomatted code) return mips.disconnect() self._mips_local.pop(group_id, None) @@ -1619,7 +1161,6 @@ class MIoTClient: self._mips_local[group_id] = mips mips.enable_logger(logger=_LOGGER) mips.on_dev_list_changed = self.__on_gw_device_list_changed -<<<<<<< HEAD mips.sub_mips_state( key=group_id, handler=self.__on_mips_local_state_changed) mips.connect() @@ -1629,16 +1170,6 @@ class MIoTClient: self, key: str, state: bool ) -> None: _LOGGER.info('cloud mips state changed, %s, %s', key, state) -======= - mips.sub_mips_state(key=group_id, - handler=self.__on_mips_local_state_changed) - mips.connect() - - @final - async def __on_mips_cloud_state_changed(self, key: str, - state: bool) -> None: - _LOGGER.info("cloud mips state changed, %s, %s", key, state) ->>>>>>> 83899f8 (fomatted code) if state: # Connect self.__request_refresh_cloud_devices(immediately=True) @@ -1658,11 +1189,7 @@ class MIoTClient: continue self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache[did].get( -<<<<<<< HEAD 'online', None) -======= - "online", None) ->>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( False, self._device_list_gateway.get( @@ -1677,7 +1204,6 @@ class MIoTClient: self.__request_show_devices_changed_notify() @final -<<<<<<< HEAD async def __on_mips_local_state_changed( self, group_id: str, state: bool ) -> None: @@ -1688,15 +1214,6 @@ class MIoTClient: 'local mips state changed, mips not exist, %s', group_id) # The connection to the central hub gateway is definitely broken. self.__show_central_state_changed_notify(False) -======= - async def __on_mips_local_state_changed(self, group_id: str, - state: bool) -> None: - _LOGGER.info("local mips state changed, %s, %s", group_id, state) - mips = self._mips_local.get(group_id, None) - if not mips: - _LOGGER.error("local mips state changed, mips not exist, %s", - group_id) ->>>>>>> 83899f8 (fomatted code) return if state: # Connected @@ -1718,11 +1235,7 @@ class MIoTClient: continue self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache.get( -<<<<<<< HEAD did, {}).get('online', None) -======= - did, {}).get("online", None) ->>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), False, @@ -1738,7 +1251,6 @@ class MIoTClient: @final async def __on_miot_lan_state_change(self, state: bool) -> None: -<<<<<<< HEAD _LOGGER.info( 'miot lan state changed, %s, %s, %s', self._uid, self._cloud_server, state) @@ -1761,33 +1273,6 @@ class MIoTClient: if 'token' in info and 'connect_type' in info and info['connect_type'] in [0, 8, 12, 23] }) -======= - _LOGGER.info("miot lan state changed, %s, %s, %s", self._uid, - self._cloud_server, state) - if state: - # Update device - self._miot_lan.sub_device_state( - key=f"{self._uid}-{self._cloud_server}", - handler=self.__on_lan_device_state_changed, - ) - for did, info in (await - self._miot_lan.get_dev_list_async()).items(): - await self.__on_lan_device_state_changed(did=did, - state=info, - ctx=None) - _LOGGER.info("lan device list, %s", self._device_list_lan) - self._miot_lan.update_devices( - devices={ - did: { - "token": info["token"], - "model": info["model"], - "connect_type": info["connect_type"], - } - for did, info in self._device_list_cache.items() - if "token" in info and "connect_type" in info and - info["connect_type"] in [0, 8, 12, 23] - }) ->>>>>>> 83899f8 (fomatted code) else: for did, info in self._device_list_lan.items(): if not info.get('online', False): @@ -1797,11 +1282,7 @@ class MIoTClient: info['push_available'] = False self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache.get( -<<<<<<< HEAD did, {}).get('online', None) -======= - did, {}).get("online", None) ->>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), self._device_list_gateway.get( @@ -1817,16 +1298,10 @@ class MIoTClient: self.__request_show_devices_changed_notify() @final -<<<<<<< HEAD def __on_cloud_device_state_changed( self, did: str, state: MIoTDeviceState, ctx: Any ) -> None: _LOGGER.info('cloud device state changed, %s, %s', did, state) -======= - def __on_cloud_device_state_changed(self, did: str, state: MIoTDeviceState, - ctx: Any) -> None: - _LOGGER.info("cloud device state changed, %s, %s", did, state) ->>>>>>> 83899f8 (fomatted code) cloud_device = self._device_list_cloud.get(did, None) if not cloud_device: return @@ -1838,11 +1313,7 @@ class MIoTClient: return self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache[did].get( -<<<<<<< HEAD 'online', None) -======= - "online", None) ->>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( cloud_state_new, self._device_list_gateway.get(did, {}).get('online', False), @@ -1853,7 +1324,6 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( -<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) self.__request_show_devices_changed_notify() @@ -1875,27 +1345,10 @@ class MIoTClient: } gw_list = await mips.get_dev_list_async( payload=json.dumps(payload)) -======= - did, - MIoTDeviceState.ONLINE - if state_new else MIoTDeviceState.OFFLINE, - sub.handler_ctx, - ) - self.__request_show_devices_changed_notify() - - @final - async def __on_gw_device_list_changed(self, mips: MipsLocalClient, - did_list: list[str]) -> None: - _LOGGER.info("gateway devices list changed, %s, %s", mips.group_id, - did_list) - payload: dict = {"filter": {"did": did_list}} - gw_list = await mips.get_dev_list_async(payload=json.dumps(payload)) ->>>>>>> 83899f8 (fomatted code) if gw_list is None: _LOGGER.error('local mips get_dev_list_async failed, %s', did_list) return await self.__update_devices_from_gw_async( -<<<<<<< HEAD gw_list=gw_list, group_id=mips.group_id, filter_dids=[ did for did in did_list if self._device_list_gateway.get(did, {}).get( @@ -1915,28 +1368,6 @@ class MIoTClient: and lan_sub_new == self._device_list_lan[did].get( 'push_available', False) ): -======= - gw_list=gw_list, - group_id=mips.group_id, - filter_dids=[ - did for did in did_list if self._device_list_gateway.get( - did, {}).get("group_id", None) == mips.group_id - ], - ) - self.__request_show_devices_changed_notify() - - @final - async def __on_lan_device_state_changed(self, did: str, state: dict, - ctx: Any) -> None: - _LOGGER.info("lan device state changed, %s, %s", did, state) - lan_state_new: bool = state.get("online", False) - lan_sub_new: bool = state.get("push_available", False) - self._device_list_lan.setdefault(did, {}) - if lan_state_new == self._device_list_lan[did].get( - "online", - False) and lan_sub_new == self._device_list_lan[did].get( - "push_available", False): ->>>>>>> 83899f8 (fomatted code) return self._device_list_lan[did]['online'] = lan_state_new self._device_list_lan[did]['push_available'] = lan_sub_new @@ -1946,11 +1377,7 @@ class MIoTClient: if lan_state_new == self._device_list_cache[did].get('online', False): return state_old: Optional[bool] = self._device_list_cache[did].get( -<<<<<<< HEAD 'online', None) -======= - "online", None) ->>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), self._device_list_gateway.get(did, {}).get('online', False), @@ -1961,16 +1388,8 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( -<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) -======= - did, - MIoTDeviceState.ONLINE - if state_new else MIoTDeviceState.OFFLINE, - sub.handler_ctx, - ) ->>>>>>> 83899f8 (fomatted code) self.__request_show_devices_changed_notify() @final @@ -1978,14 +1397,8 @@ class MIoTClient: """params MUST contain did, siid, piid, value""" # BLE device has no online/offline msg try: -<<<<<<< HEAD subs: list[MIoTClientSub] = list(self._sub_tree.iter_match( f'{params["did"]}/p/{params["siid"]}/{params["piid"]}')) -======= - subs: list[MIoTClientSub] = list( - self._sub_tree.iter_match( - f"{params['did']}/p/{params['siid']}/{params['piid']}")) ->>>>>>> 83899f8 (fomatted code) for sub in subs: sub.handler(params, sub.handler_ctx) except Exception as err: # pylint: disable=broad-exception-caught @@ -1994,14 +1407,8 @@ class MIoTClient: @final def __on_event_msg(self, params: dict, ctx: Any) -> None: try: -<<<<<<< HEAD subs: list[MIoTClientSub] = list(self._sub_tree.iter_match( f'{params["did"]}/e/{params["siid"]}/{params["eiid"]}')) -======= - subs: list[MIoTClientSub] = list( - self._sub_tree.iter_match( - f"{params['did']}/e/{params['siid']}/{params['eiid']}")) ->>>>>>> 83899f8 (fomatted code) for sub in subs: sub.handler(params, sub.handler_ctx) except Exception as err: # pylint: disable=broad-exception-caught @@ -2021,32 +1428,17 @@ class MIoTClient: async def __load_cache_device_async(self) -> None: """Load device list from cache.""" cache_list: Optional[dict[str, dict]] = await self._storage.load_async( -<<<<<<< HEAD domain='miot_devices', name=f'{self._uid}_{self._cloud_server}', -======= - domain="miot_devices", - name=f"{self._uid}_{self._cloud_server}", ->>>>>>> 83899f8 (fomatted code) type_=dict) # type: ignore if not cache_list: self.__show_client_error_notify( message=self._i18n.translate( -<<<<<<< HEAD 'miot.client.invalid_device_cache'), # type: ignore notify_key='device_cache') raise MIoTClientError('load device list from cache error') else: self.__show_client_error_notify( message=None, notify_key='device_cache') -======= - "miot.client.invalid_device_cache"), # type: ignore - notify_key="device_cache", - ) - raise MIoTClientError("load device list from cache error") - else: - self.__show_client_error_notify(message=None, - notify_key="device_cache") ->>>>>>> 83899f8 (fomatted code) # Set default online status = False self._device_list_cache = {} for did, info in cache_list.items(): @@ -2058,7 +1450,6 @@ class MIoTClient: self._device_list_cloud = deepcopy(self._device_list_cache) self._device_list_gateway = { did: { -<<<<<<< HEAD 'did': did, 'name': info.get('name', None), 'group_id': info.get('group_id', None), @@ -2071,21 +1462,6 @@ class MIoTClient: self, cloud_list: dict[str, dict], filter_dids: Optional[list[str]] = None ) -> None: -======= - "did": did, - "name": info.get("name", None), - "group_id": info.get("group_id", None), - "online": False, - "push_available": False, - } for did, info in self._device_list_cache.items() - } - - @final - async def __update_devices_from_cloud_async( - self, - cloud_list: dict[str, dict], - filter_dids: Optional[list[str]] = None) -> None: ->>>>>>> 83899f8 (fomatted code) """Update cloud devices. NOTICE: This function will operate the cloud_list """ @@ -2100,15 +1476,9 @@ class MIoTClient: for did, info in self._device_list_cache.items(): if filter_dids and did not in filter_dids: continue -<<<<<<< HEAD state_old: Optional[bool] = info.get('online', None) cloud_state_old: Optional[bool] = self._device_list_cloud.get( did, {}).get('online', None) -======= - state_old: Optional[bool] = info.get("online", None) - cloud_state_old: Optional[bool] = self._device_list_cloud.get( - did, {}).get("online", None) ->>>>>>> 83899f8 (fomatted code) cloud_state_new: Optional[bool] = None device_new = cloud_list.pop(did, None) if device_new: @@ -2138,35 +1508,20 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( -<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) -======= - did, - MIoTDeviceState.ONLINE - if state_new else MIoTDeviceState.OFFLINE, - sub.handler_ctx, - ) ->>>>>>> 83899f8 (fomatted code) # New devices self._device_list_cloud.update(cloud_list) # Update storage if not await self._storage.save_async( -<<<<<<< HEAD domain='miot_devices', name=f'{self._uid}_{self._cloud_server}', data=self._device_list_cache -======= - domain="miot_devices", - name=f"{self._uid}_{self._cloud_server}", - data=self._device_list_cache, ->>>>>>> 83899f8 (fomatted code) ): _LOGGER.error('save device list to cache failed') @final async def __refresh_cloud_devices_async(self) -> None: -<<<<<<< HEAD _LOGGER.debug( 'refresh cloud devices, %s, %s', self._uid, self._cloud_server) if self._refresh_cloud_devices_timer: @@ -2207,57 +1562,18 @@ class MIoTClient: if 'token' in info and 'connect_type' in info and info['connect_type'] in [0, 8, 12, 23] }) -======= - _LOGGER.debug("refresh cloud devices, %s, %s", self._uid, - self._cloud_server) - self._refresh_cloud_devices_timer = None - result = await self._http.get_devices_async( - home_ids=list(self._entry_data.get("home_selected", {}).keys())) - if not result and "devices" not in result: - self.__show_client_error_notify( - message=self._i18n.translate( - "miot.client.device_cloud_error"), # type: ignore - notify_key="device_cloud", - ) - return - else: - self.__show_client_error_notify(message=None, - notify_key="device_cloud") - cloud_list: dict[str, dict] = result["devices"] - await self.__update_devices_from_cloud_async(cloud_list=cloud_list) - # Update lan device - if self._ctrl_mode == CtrlMode.AUTO and self._miot_lan.init_done: - self._miot_lan.update_devices( - devices={ - did: { - "token": info["token"], - "model": info["model"], - "connect_type": info["connect_type"], - } - for did, info in self._device_list_cache.items() - if "token" in info and "connect_type" in info and - info["connect_type"] in [0, 8, 12, 23] - }) ->>>>>>> 83899f8 (fomatted code) self.__request_show_devices_changed_notify() @final -<<<<<<< HEAD async def __refresh_cloud_device_with_dids_async( self, dids: list[str] ) -> None: _LOGGER.debug('refresh cloud device with dids, %s', dids) -======= - async def __refresh_cloud_device_with_dids_async(self, - dids: list[str]) -> None: - _LOGGER.debug("refresh cloud device with dids, %s", dids) ->>>>>>> 83899f8 (fomatted code) cloud_list = await self._http.get_devices_with_dids_async(dids=dids) if cloud_list is None: _LOGGER.error('cloud http get_dev_list_async failed, %s', dids) return -<<<<<<< HEAD await self.__update_devices_from_cloud_async( cloud_list=cloud_list, filter_dids=dids) self.__request_show_devices_changed_notify() @@ -2267,32 +1583,10 @@ class MIoTClient: 'request refresh cloud devices, %s, %s', self._uid, self._cloud_server) delay_sec : int = 0 if immediately else REFRESH_CLOUD_DEVICES_DELAY -======= - await self.__update_devices_from_cloud_async(cloud_list=cloud_list, - filter_dids=dids) - self.__request_show_devices_changed_notify() - - def __request_refresh_cloud_devices(self, immediately=False) -> None: - _LOGGER.debug("request refresh cloud devices, %s, %s", self._uid, - self._cloud_server) - if immediately: - if self._refresh_cloud_devices_timer: - self._refresh_cloud_devices_timer.cancel() - self._refresh_cloud_devices_timer = self._main_loop.call_later( - 0, - lambda: self._main_loop.create_task( - self.__refresh_cloud_devices_async()), - ) - return ->>>>>>> 83899f8 (fomatted code) if self._refresh_cloud_devices_timer: self._refresh_cloud_devices_timer.cancel() self._refresh_cloud_devices_timer = self._main_loop.call_later( -<<<<<<< HEAD delay_sec, lambda: self._main_loop.create_task( -======= - 6, lambda: self._main_loop.create_task( ->>>>>>> 83899f8 (fomatted code) self.__refresh_cloud_devices_async())) @final @@ -2310,24 +1604,13 @@ class MIoTClient: if did not in filter_dids: continue device_old = self._device_list_gateway.get(did, None) -<<<<<<< HEAD -======= - gw_state_old = device_old.get("online", - False) if device_old else False ->>>>>>> 83899f8 (fomatted code) gw_state_new: bool = False device_new = gw_list.pop(did, None) if device_new: # Update gateway device info self._device_list_gateway[did] = { -<<<<<<< HEAD **device_new, 'group_id': group_id} gw_state_new = device_new.get('online', False) -======= - **device_new, "group_id": group_id - } - gw_state_new = device_new.get("online", False) ->>>>>>> 83899f8 (fomatted code) else: # Device offline if device_old: @@ -2348,23 +1631,14 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( -<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) -======= - did, - MIoTDeviceState.ONLINE - if state_new else MIoTDeviceState.OFFLINE, - sub.handler_ctx, - ) ->>>>>>> 83899f8 (fomatted code) # New devices or device home info changed for did, info in gw_list.items(): self._device_list_gateway[did] = {**info, 'group_id': group_id} if did not in self._device_list_cache: continue group_id_old: str = self._device_list_cache[did].get( -<<<<<<< HEAD 'group_id', None) self._device_list_cache[did]['group_id'] = group_id _LOGGER.info( @@ -2372,15 +1646,6 @@ class MIoTClient: self.__update_device_msg_sub(did=did) state_old: Optional[bool] = self._device_list_cache[did].get( 'online', None) -======= - "group_id", None) - self._device_list_cache[did]["group_id"] = group_id - _LOGGER.info("move device %s from %s to %s", did, group_id_old, - group_id) - self.__update_device_msg_sub(did=did) - state_old: Optional[bool] = self._device_list_cache[did].get( - "online", None) ->>>>>>> 83899f8 (fomatted code) state_new: Optional[bool] = self.__check_device_state( self._device_list_cloud.get(did, {}).get('online', None), info.get('online', False), @@ -2391,7 +1656,6 @@ class MIoTClient: sub = self._sub_device_state.get(did, None) if sub and sub.handler: sub.handler( -<<<<<<< HEAD did, MIoTDeviceState.ONLINE if state_new else MIoTDeviceState.OFFLINE, sub.handler_ctx) @@ -2399,17 +1663,6 @@ class MIoTClient: async def __refresh_gw_devices_with_group_id_async( self, group_id: str ) -> None: -======= - did, - MIoTDeviceState.ONLINE - if state_new else MIoTDeviceState.OFFLINE, - sub.handler_ctx, - ) - - @final - async def __refresh_gw_devices_with_group_id_async(self, - group_id: str) -> None: ->>>>>>> 83899f8 (fomatted code) """Refresh gateway devices by group_id""" _LOGGER.debug( 'refresh gw devices with group_id, %s', group_id) @@ -2431,32 +1684,17 @@ class MIoTClient: gw_list: dict = await mips.get_dev_list_async( payload=json.dumps(payload)) if gw_list is None: -<<<<<<< HEAD _LOGGER.error( 'refresh gw devices with group_id failed, %s, %s', self._uid, group_id) -======= - _LOGGER.error("refresh gw devices with group_id failed, %s, %s", - self._uid, group_id) ->>>>>>> 83899f8 (fomatted code) # Retry until success self.__request_refresh_gw_devices_by_group_id( group_id=group_id) return await self.__update_devices_from_gw_async( -<<<<<<< HEAD gw_list=gw_list, group_id=group_id, filter_dids=[ did for did, info in self._device_list_gateway.items() if info.get('group_id', None) == group_id]) -======= - gw_list=gw_list, - group_id=group_id, - filter_dids=[ - did for did, info in self._device_list_gateway.items() - if info.get("group_id", None) == group_id - ], - ) ->>>>>>> 83899f8 (fomatted code) self.__request_show_devices_changed_notify() @final @@ -2473,7 +1711,6 @@ class MIoTClient: refresh_timer.cancel() self._mips_local_state_changed_timers[group_id] = ( self._main_loop.call_later( -<<<<<<< HEAD 0, lambda: self._main_loop.create_task( self.__refresh_gw_devices_with_group_id_async( group_id=group_id)))) @@ -2485,22 +1722,6 @@ class MIoTClient: lambda: self._main_loop.create_task( self.__refresh_gw_devices_with_group_id_async( group_id=group_id)))) -======= - 0, - lambda: self._main_loop.create_task( - self.__refresh_gw_devices_with_group_id_async( - group_id=group_id)), - )) - if refresh_timer: - return - self._mips_local_state_changed_timers[ - group_id] = self._main_loop.call_later( - 3, - lambda: self._main_loop.create_task( - self.__refresh_gw_devices_with_group_id_async(group_id= - group_id)), - ) ->>>>>>> 83899f8 (fomatted code) @final async def __refresh_props_from_cloud(self, patch_len: int = 150) -> bool: @@ -2522,7 +1743,6 @@ class MIoTClient: if not results: raise MIoTClientError('get_props_async failed') for result in results: -<<<<<<< HEAD if ( 'did' not in result or 'siid' not in result @@ -2544,22 +1764,6 @@ class MIoTClient: _LOGGER.error( 'refresh props error, cloud, %s, %s', err, traceback.format_exc()) -======= - if ("did" not in result or "siid" not in result or - "piid" not in result or "value" not in result): - continue - request_list.pop( - f"{result['did']}|{result['siid']}|{result['piid']}", None) - self.__on_prop_msg(params=result, ctx=None) - if request_list: - _LOGGER.info("refresh props failed, cloud, %s", - list(request_list.keys())) - request_list = None - return True - except Exception as err: # pylint:disable=broad-exception-caught - _LOGGER.error("refresh props error, cloud, %s, %s", err, - traceback.format_exc()) ->>>>>>> 83899f8 (fomatted code) # Add failed request back to the list self._refresh_props_list.update(request_list) return False @@ -2587,22 +1791,11 @@ class MIoTClient: continue request_list[did] = { **params, -<<<<<<< HEAD 'fut': mips_gw.get_prop_async( did=did, siid=params['siid'], piid=params['piid'], timeout_ms=6000)} results = await asyncio.gather( *[v['fut'] for v in request_list.values()]) -======= - "fut": - mips_gw.get_prop_async(did=did, - siid=params["siid"], - piid=params["piid"], - timeout_ms=6000), - } - results = await asyncio.gather( - *[v["fut"] for v in request_list.values()]) ->>>>>>> 83899f8 (fomatted code) for (did, param), result in zip(request_list.items(), results): if result is None: # Don't use "not result", it will be skipped when result @@ -2641,22 +1834,11 @@ class MIoTClient: continue request_list[did] = { **params, -<<<<<<< HEAD 'fut': self._miot_lan.get_prop_async( did=did, siid=params['siid'], piid=params['piid'], timeout_ms=6000)} results = await asyncio.gather( *[v['fut'] for v in request_list.values()]) -======= - "fut": - self._miot_lan.get_prop_async(did=did, - siid=params["siid"], - piid=params["piid"], - timeout_ms=6000), - } - results = await asyncio.gather( - *[v["fut"] for v in request_list.values()]) ->>>>>>> 83899f8 (fomatted code) for (did, param), result in zip(request_list.items(), results): if result is None: # Don't use "not result", it will be skipped when result @@ -2689,15 +1871,8 @@ class MIoTClient: self._refresh_props_retry_count = 0 if self._refresh_props_list: self._refresh_props_timer = self._main_loop.call_later( -<<<<<<< HEAD REFRESH_PROPS_DELAY, lambda: self._main_loop.create_task( self.__refresh_props_handler())) -======= - 0.2, - lambda: self._main_loop.create_task( - self.__refresh_props_handler()), - ) ->>>>>>> 83899f8 (fomatted code) else: self._refresh_props_timer = None return @@ -2712,7 +1887,6 @@ class MIoTClient: _LOGGER.info('refresh props failed, retry count exceed') return self._refresh_props_retry_count += 1 -<<<<<<< HEAD _LOGGER.info( 'refresh props failed, retry, %s', self._refresh_props_retry_count) self._refresh_props_timer = self._main_loop.call_later( @@ -2723,34 +1897,15 @@ class MIoTClient: def __show_client_error_notify( self, message: Optional[str], notify_key: str = '' ) -> None: -======= - _LOGGER.info("refresh props failed, retry, %s", - self._refresh_props_retry_count) - self._refresh_props_timer = self._main_loop.call_later( - 3, - lambda: self._main_loop.create_task(self.__refresh_props_handler())) - - @final - def __show_client_error_notify(self, - message: Optional[str], - notify_key: str = "") -> None: ->>>>>>> 83899f8 (fomatted code) if message: self._persistence_notify( -<<<<<<< HEAD f'{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error', -======= - f"{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error", - self._i18n.translate( - key="miot.client.xiaomi_home_error_title"), # type: ignore ->>>>>>> 83899f8 (fomatted code) self._i18n.translate( key='miot.client.xiaomi_home_error_title'), # type: ignore self._i18n.translate( key='miot.client.xiaomi_home_error', replace={ -<<<<<<< HEAD 'nick_name': self._entry_data.get( 'nick_name', DEFAULT_NICK_NAME), 'uid': self._uid, @@ -2759,23 +1914,6 @@ class MIoTClient: else: self._persistence_notify( f'{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error', -======= - "nick_name": - self._entry_data.get("nick_name", - DEFAULT_NICK_NAME), - "uid": - self._uid, - "cloud_server": - self._cloud_server, - "message": - message, - }, - ), - ) # type: ignore - else: - self._persistence_notify( - f"{DOMAIN}{self._uid}{self._cloud_server}{notify_key}error", ->>>>>>> 83899f8 (fomatted code) None, None) @final @@ -2795,24 +1933,14 @@ class MIoTClient: # New devices if 'add' in self._display_devs_notify: for did, info in { -<<<<<<< HEAD **self._device_list_gateway, **self._device_list_cloud -======= - **self._device_list_gateway, - **self._device_list_cloud, ->>>>>>> 83899f8 (fomatted code) }.items(): if did in self._device_list_cache: continue count_add += 1 -<<<<<<< HEAD message_add += ( f'- {info.get("name", "unknown")} ({did}, ' f'{info.get("model", "unknown")})\n') -======= - message_add += (f"- {info.get('name', 'unknown')} ({did}, " - f"{info.get('model', 'unknown')})\n") ->>>>>>> 83899f8 (fomatted code) # Get unavailable and offline devices home_name_del: Optional[str] = None home_name_offline: Optional[str] = None @@ -2828,14 +1956,9 @@ class MIoTClient: message_del += f'\n[{home_name_new}]\n' home_name_del = home_name_new count_del += 1 -<<<<<<< HEAD message_del += ( f'- {info.get("name", "unknown")} ({did}, ' f'{info.get("room_name", "unknown")})\n') -======= - message_del += (f"- {info.get('name', 'unknown')} ({did}, " - f"{info.get('room_name', 'unknown')})\n") ->>>>>>> 83899f8 (fomatted code) continue if 'offline' in self._display_devs_notify: # Device offline @@ -2843,19 +1966,13 @@ class MIoTClient: message_offline += f'\n[{home_name_new}]\n' home_name_offline = home_name_new count_offline += 1 -<<<<<<< HEAD message_offline += ( f'- {info.get("name", "unknown")} ({did}, ' f'{info.get("room_name", "unknown")})\n') -======= - message_offline += (f"- {info.get('name', 'unknown')} ({did}, " - f"{info.get('room_name', 'unknown')})\n") ->>>>>>> 83899f8 (fomatted code) message = '' if 'add' in self._display_devs_notify and count_add: message += self._i18n.translate( -<<<<<<< HEAD key='miot.client.device_list_add', replace={ 'count': count_add, @@ -2873,36 +1990,10 @@ class MIoTClient: 'count': count_offline, 'message': message_offline}) # type: ignore if message != '': -======= - key="miot.client.device_list_add", - replace={ - "count": count_add, - "message": message_add - }, - ) # type: ignore - if "del" in self._display_devs_notify and count_del: - message += self._i18n.translate( - key="miot.client.device_list_del", - replace={ - "count": count_del, - "message": message_del - }, - ) # type: ignore - if "offline" in self._display_devs_notify and count_offline: - message += self._i18n.translate( - key="miot.client.device_list_offline", - replace={ - "count": count_offline, - "message": message_offline - }, - ) # type: ignore - if message != "": ->>>>>>> 83899f8 (fomatted code) msg_hash = hash(message) if msg_hash == self._display_notify_content_hash: # Notify content no change, return _LOGGER.debug( -<<<<<<< HEAD 'device list changed notify content no change, return') return network_status = self._i18n.translate( @@ -2911,51 +2002,22 @@ class MIoTClient: else 'miot.client.network_status_offline') self._persistence_notify( self.__gen_notify_key('dev_list_changed'), -======= - "device list changed notify content no change, return") - return - network_status = self._i18n.translate( - key="miot.client.network_status_online" if self._network. - network_status else "miot.client.network_status_offline") - self._persistence_notify( - self.__gen_notify_key("dev_list_changed"), - self._i18n.translate( - "miot.client.device_list_changed_title"), # type: ignore ->>>>>>> 83899f8 (fomatted code) self._i18n.translate( 'miot.client.device_list_changed_title'), # type: ignore self._i18n.translate( key='miot.client.device_list_changed', replace={ -<<<<<<< HEAD 'nick_name': self._entry_data.get( 'nick_name', DEFAULT_NICK_NAME), 'uid': self._uid, 'cloud_server': self._cloud_server, 'network_status': network_status, 'message': message})) # type: ignore -======= - "nick_name": - self._entry_data.get("nick_name", - DEFAULT_NICK_NAME), - "uid": - self._uid, - "cloud_server": - self._cloud_server, - "network_status": - network_status, - "message": - message, - }, - ), - ) # type: ignore ->>>>>>> 83899f8 (fomatted code) self._display_notify_content_hash = msg_hash _LOGGER.debug( 'show device list changed notify, add %s, del %s, offline %s', count_add, count_del, count_offline) else: -<<<<<<< HEAD self._persistence_notify( self.__gen_notify_key('dev_list_changed'), None, None) @@ -2963,14 +2025,6 @@ class MIoTClient: def __request_show_devices_changed_notify( self, delay_sec: float = 6 ) -> None: -======= - self._persistence_notify(self.__gen_notify_key("dev_list_changed"), - None, None) - - @final - def __request_show_devices_changed_notify(self, - delay_sec: float = 6) -> None: ->>>>>>> 83899f8 (fomatted code) if not self._display_devs_notify: return if not self._mips_cloud and not self._mips_local and not self._miot_lan: @@ -3042,11 +2096,7 @@ async def get_miot_instance_async( _LOGGER.info('create miot_network instance') # MIoT service mips_service: Optional[MipsService] = hass.data[DOMAIN].get( -<<<<<<< HEAD 'mips_service', None) -======= - "mips_service", None) ->>>>>>> 83899f8 (fomatted code) if not mips_service: aiozc = await zeroconf.async_get_async_instance(hass) mips_service = MipsService(aiozc=aiozc, loop=loop) diff --git a/custom_components/xiaomi_home/miot/miot_cloud.py b/custom_components/xiaomi_home/miot/miot_cloud.py index 717d343..2c72a6f 100644 --- a/custom_components/xiaomi_home/miot/miot_cloud.py +++ b/custom_components/xiaomi_home/miot/miot_cloud.py @@ -99,17 +99,10 @@ class MIoTOauthClient: if cloud_server == 'cn': self._oauth_host = DEFAULT_OAUTH2_API_HOST else: -<<<<<<< HEAD self._oauth_host = f'{cloud_server}.{DEFAULT_OAUTH2_API_HOST}' self._device_id = f'ha.{uuid}' self._state = hashlib.sha1( f'd={self._device_id}'.encode('utf-8')).hexdigest() -======= - self._oauth_host = f"{cloud_server}.{DEFAULT_OAUTH2_API_HOST}" - self._device_id = f"ha.{uuid}" - self._state = hashlib.sha1( - f"d={self._device_id}".encode("utf-8")).hexdigest() ->>>>>>> 83899f8 (fomatted code) self._session = aiohttp.ClientSession(loop=self._main_loop) @property @@ -172,20 +165,14 @@ class MIoTOauthClient: timeout=MIHOME_HTTP_API_TIMEOUT ) if http_res.status == 401: -<<<<<<< HEAD raise MIoTOauthError( 'unauthorized(401)', MIoTErrorCode.CODE_OAUTH_UNAUTHORIZED) -======= - raise MIoTOauthError("unauthorized(401)", - MIoTErrorCode.CODE_OAUTH_UNAUTHORIZED) ->>>>>>> 83899f8 (fomatted code) if http_res.status != 200: raise MIoTOauthError( f'invalid http status code, {http_res.status}') res_str = await http_res.text() res_obj = json.loads(res_str) -<<<<<<< HEAD if ( not res_obj or res_obj.get('code', None) != 0 @@ -201,19 +188,6 @@ class MIoTOauthClient: 'expires_ts': int( time.time() + (res_obj['result'].get('expires_in', 0)*TOKEN_EXPIRES_TS_RATIO)) -======= - if (not res_obj or res_obj.get("code", None) != 0 or - "result" not in res_obj or - not all(key in res_obj["result"] for key in - ["access_token", "refresh_token", "expires_in"])): - raise MIoTOauthError(f"invalid http response, {res_str}") - - return { - **res_obj["result"], - "expires_ts": - int(time.time() + (res_obj["result"].get("expires_in", 0) * - TOKEN_EXPIRES_TS_RATIO)), ->>>>>>> 83899f8 (fomatted code) } async def get_access_token_async(self, code: str) -> dict: @@ -228,22 +202,12 @@ class MIoTOauthClient: if not isinstance(code, str): raise MIoTOauthError('invalid code') -<<<<<<< HEAD return await self.__get_token_async(data={ 'client_id': self._client_id, 'redirect_uri': self._redirect_url, 'code': code, 'device_id': self._device_id }) -======= - return await self.__get_token_async( - data={ - "client_id": self._client_id, - "redirect_uri": self._redirect_url, - "code": code, - "device_id": self._device_id, - }) ->>>>>>> 83899f8 (fomatted code) async def refresh_access_token_async(self, refresh_token: str) -> dict: """get access token by refresh token. @@ -257,20 +221,11 @@ class MIoTOauthClient: if not isinstance(refresh_token, str): raise MIoTOauthError('invalid refresh_token') -<<<<<<< HEAD return await self.__get_token_async(data={ 'client_id': self._client_id, 'redirect_uri': self._redirect_url, 'refresh_token': refresh_token, }) -======= - return await self.__get_token_async( - data={ - "client_id": self._client_id, - "redirect_uri": self._redirect_url, - "refresh_token": refresh_token, - }) ->>>>>>> 83899f8 (fomatted code) class MIoTHttpClient: @@ -301,7 +256,6 @@ class MIoTHttpClient: self._get_prop_timer = None self._get_prop_list = {} -<<<<<<< HEAD if ( not isinstance(cloud_server, str) or not isinstance(client_id, str) @@ -312,16 +266,6 @@ class MIoTHttpClient: self.update_http_header( cloud_server=cloud_server, client_id=client_id, access_token=access_token) -======= - if (not isinstance(cloud_server, str) or - not isinstance(client_id, str) or - not isinstance(access_token, str)): - raise MIoTHttpError("invalid params") - - self.update_http_header(cloud_server=cloud_server, - client_id=client_id, - access_token=access_token) ->>>>>>> 83899f8 (fomatted code) self._session = aiohttp.ClientSession(loop=self._main_loop) @@ -363,16 +307,9 @@ class MIoTHttpClient: # pylint: disable=unused-private-member async def __mihome_api_get_async( -<<<<<<< HEAD self, url_path: str, params: dict, timeout: int = MIHOME_HTTP_API_TIMEOUT ) -> dict: -======= - self, - url_path: str, - params: dict, - timeout: int = MIHOME_HTTP_API_TIMEOUT) -> dict: ->>>>>>> 83899f8 (fomatted code) http_res = await self._session.get( url=f'{self._base_url}{url_path}', params=params, @@ -390,7 +327,6 @@ class MIoTHttpClient: res_obj: dict = json.loads(res_str) if res_obj.get('code', None) != 0: raise MIoTHttpError( -<<<<<<< HEAD f'invalid response code, {res_obj.get("code",None)}, ' f'{res_obj.get("message","")}') _LOGGER.debug( @@ -402,19 +338,6 @@ class MIoTHttpClient: self, url_path: str, data: dict, timeout: int = MIHOME_HTTP_API_TIMEOUT ) -> dict: -======= - f"invalid response code, {res_obj.get('code', None)}, " - f"{res_obj.get('message', '')}") - _LOGGER.debug("mihome api get, %s%s, %s -> %s", self._base_url, - url_path, params, res_obj) - return res_obj - - async def __mihome_api_post_async( - self, - url_path: str, - data: dict, - timeout: int = MIHOME_HTTP_API_TIMEOUT) -> dict: ->>>>>>> 83899f8 (fomatted code) http_res = await self._session.post( url=f'{self._base_url}{url_path}', json=data, @@ -432,42 +355,24 @@ class MIoTHttpClient: res_obj: dict = json.loads(res_str) if res_obj.get('code', None) != 0: raise MIoTHttpError( -<<<<<<< HEAD f'invalid response code, {res_obj.get("code",None)}, ' f'{res_obj.get("message","")}') _LOGGER.debug( 'mihome api post, %s%s, %s -> %s', self._base_url, url_path, data, res_obj) -======= - f"invalid response code, {res_obj.get('code', None)}, " - f"{res_obj.get('message', '')}") - _LOGGER.debug("mihome api post, %s%s, %s -> %s", self._base_url, - url_path, data, res_obj) ->>>>>>> 83899f8 (fomatted code) return res_obj async def get_user_info_async(self) -> dict: http_res = await self._session.get( -<<<<<<< HEAD url='https://open.account.xiaomi.com/user/profile', params={ 'clientId': self._client_id, 'token': self._access_token}, headers={'content-type': 'application/x-www-form-urlencoded'}, timeout=MIHOME_HTTP_API_TIMEOUT -======= - url="https://open.account.xiaomi.com/user/profile", - params={ - "clientId": self._client_id, - "token": self._access_token - }, - headers={"content-type": "application/x-www-form-urlencoded"}, - timeout=MIHOME_HTTP_API_TIMEOUT, ->>>>>>> 83899f8 (fomatted code) ) res_str = await http_res.text() res_obj = json.loads(res_str) -<<<<<<< HEAD if ( not res_obj or res_obj.get('code', None) != 0 @@ -475,11 +380,6 @@ class MIoTHttpClient: or 'miliaoNick' not in res_obj['data'] ): raise MIoTOauthError(f'invalid http response, {http_res.text}') -======= - if (not res_obj or res_obj.get("code", None) != 0 or - "data" not in res_obj or "miliaoNick" not in res_obj["data"]): - raise MIoTOauthError(f"invalid http response, {http_res.text}") ->>>>>>> 83899f8 (fomatted code) return res_obj['data'] @@ -501,14 +401,9 @@ class MIoTHttpClient: return cert -<<<<<<< HEAD async def __get_dev_room_page_async( self, max_id: Optional[str] = None ) -> dict: -======= - async def __get_dev_room_page_async(self, - max_id: Optional[str] = None) -> dict: ->>>>>>> 83899f8 (fomatted code) res_obj = await self.__mihome_api_post_async( url_path='/app/v2/homeroom/get_dev_room_page', data={ @@ -524,7 +419,6 @@ class MIoTHttpClient: _LOGGER.error( 'get dev room page error, invalid home, %s', home) continue -<<<<<<< HEAD home_list[str(home['id'])] = {'dids': home.get( 'dids', None) or [], 'room_info': {}} for room in home.get('roomlist', []): @@ -548,32 +442,6 @@ class MIoTHttpClient: room_id, {'dids': []}) home_list[home_id]['room_info'][room_id]['dids'].extend( info['dids']) -======= - home_list[str(home["id"])] = { - "dids": home.get("dids", None) or [], - "room_info": {}, - } - for room in home.get("roomlist", []): - if "id" not in room: - _LOGGER.error("get dev room page error, invalid room, %s", - room) - continue - home_list[str(home["id"])]["room_info"][str(room["id"])] = { - "dids": room.get("dids", None) or [] - } - if res_obj["result"].get("has_more", False) and isinstance( - res_obj["result"].get("max_id", None), str): - next_list = await self.__get_dev_room_page_async( - max_id=res_obj["result"]["max_id"]) - for home_id, info in next_list.items(): - home_list.setdefault(home_id, {"dids": [], "room_info": {}}) - home_list[home_id]["dids"].extend(info["dids"]) - for room_id, info in info["room_info"].items(): - home_list[home_id]["room_info"].setdefault( - room_id, {"dids": []}) - home_list[home_id]["room_info"][room_id]["dids"].extend( - info["dids"]) ->>>>>>> 83899f8 (fomatted code) return home_list @@ -582,16 +450,10 @@ class MIoTHttpClient: device_list: dict[str, dict] = await self.__get_device_list_page_async( dids=[], start_did=None) for did, value in device_list.items(): -<<<<<<< HEAD if value['owner'] is not None and ('userid' in value['owner']) and ( 'nickname' in value['owner'] ): separated_shared_devices.setdefault(did, value['owner']) -======= - if (value["owner"] is not None and ("userid" in value["owner"]) and - ("nickname" in value["owner"])): - separated_shared_devices.setdefault(did, value["owner"]) ->>>>>>> 83899f8 (fomatted code) return separated_shared_devices async def get_homeinfos_async(self) -> dict: @@ -619,7 +481,6 @@ class MIoTHttpClient: or 'roomlist' not in home ): continue -<<<<<<< HEAD if uid is None and device_source == 'homelist': uid = str(home['uid']) home_infos[device_source][home['id']] = { @@ -651,48 +512,10 @@ class MIoTHttpClient: more_list = await self.__get_dev_room_page_async( max_id=res_obj['result']['max_id']) for device_source in ['homelist', 'share_home_list']: -======= - if uid is None and device_source == "homelist": - uid = str(home["uid"]) - home_infos[device_source][home["id"]] = { - "home_id": - home["id"], - "home_name": - home["name"], - "city_id": - home.get("city_id", None), - "longitude": - home.get("longitude", None), - "latitude": - home.get("latitude", None), - "address": - home.get("address", None), - "dids": - home.get("dids", []), - "room_info": { - room["id"]: { - "room_id": room["id"], - "room_name": room["name"], - "dids": room.get("dids", []), - } for room in home.get("roomlist", []) if "id" in room - }, - "group_id": - calc_group_id(uid=home["uid"], home_id=home["id"]), - "uid": - str(home["uid"]), - } - home_infos["uid"] = uid - if res_obj["result"].get("has_more", False) and isinstance( - res_obj["result"].get("max_id", None), str): - more_list = await self.__get_dev_room_page_async( - max_id=res_obj["result"]["max_id"]) - for device_source in ["homelist", "share_home_list"]: ->>>>>>> 83899f8 (fomatted code) for home_id, info in more_list.items(): if home_id not in home_infos[device_source]: _LOGGER.info('unknown home, %s, %s', home_id, info) continue -<<<<<<< HEAD home_infos[device_source][home_id]['dids'].extend( info['dids']) for room_id, info in info['room_info'].items(): @@ -704,19 +527,6 @@ class MIoTHttpClient: 'dids': []}) home_infos[device_source][home_id]['room_info'][ room_id]['dids'].extend(info['dids']) -======= - home_infos[device_source][home_id]["dids"].extend( - info["dids"]) - for room_id, info in info["room_info"].items(): - home_infos[device_source][home_id][ - "room_info"].setdefault(room_id, { - "room_id": room_id, - "room_name": "", - "dids": [] - }) - home_infos[device_source][home_id]["room_info"][ - room_id]["dids"].extend(info["dids"]) ->>>>>>> 83899f8 (fomatted code) return { 'uid': uid, @@ -728,7 +538,6 @@ class MIoTHttpClient: return (await self.get_homeinfos_async()).get('uid', None) async def __get_device_list_page_async( -<<<<<<< HEAD self, dids: list[str], start_did: Optional[str] = None ) -> dict[str, dict]: req_data: dict = { @@ -737,29 +546,16 @@ class MIoTHttpClient: 'get_third_device': True, 'dids': dids } -======= - self, - dids: list[str], - start_did: Optional[str] = None) -> dict[str, dict]: - req_data: dict = {"limit": 200, "get_split_device": True, "dids": dids} ->>>>>>> 83899f8 (fomatted code) if start_did: req_data['start_did'] = start_did device_infos: dict = {} res_obj = await self.__mihome_api_post_async( -<<<<<<< HEAD url_path='/app/v2/home/device_list_page', data=req_data ) if 'result' not in res_obj: raise MIoTHttpError('invalid response result') res_obj = res_obj['result'] -======= - url_path="/app/v2/home/device_list_page", data=req_data) - if "result" not in res_obj: - raise MIoTHttpError("invalid response result") - res_obj = res_obj["result"] ->>>>>>> 83899f8 (fomatted code) for device in res_obj.get('list', []) or []: did = device.get('did', None) @@ -784,7 +580,6 @@ class MIoTHttpClient: model, did) continue device_infos[did] = { -<<<<<<< HEAD 'did': did, 'uid': device.get('uid', None), 'name': name, @@ -811,79 +606,17 @@ class MIoTHttpClient: next_start_did = res_obj.get('next_start_did', None) if res_obj.get('has_more', False) and next_start_did: -======= - "did": - did, - "uid": - device.get("uid", None), - "name": - name, - "urn": - urn, - "model": - model, - "connect_type": - device.get("pid", -1), - "token": - device.get("token", None), - "online": - device.get("isOnline", False), - "icon": - device.get("icon", None), - "parent_id": - device.get("parent_id", None), - "manufacturer": - model.split(".")[0], - # 2: xiao-ai, 1: general speaker - "voice_ctrl": - device.get("voice_ctrl", 0), - "rssi": - device.get("rssi", None), - "owner": - device.get("owner", None), - "pid": - device.get("pid", None), - "local_ip": - device.get("local_ip", None), - "ssid": - device.get("ssid", None), - "bssid": - device.get("bssid", None), - "order_time": - device.get("orderTime", 0), - "fw_version": - device.get("extra", {}).get("fw_version", "unknown"), - } - if isinstance(device.get("extra", None), dict) and device["extra"]: - device_infos[did]["fw_version"] = device["extra"].get( - "fw_version", None) - device_infos[did]["mcu_version"] = device["extra"].get( - "mcu_version", None) - device_infos[did]["platform"] = device["extra"].get( - "platform", None) - - next_start_did = res_obj.get("next_start_did", None) - if res_obj.get("has_more", False) and next_start_did: ->>>>>>> 83899f8 (fomatted code) device_infos.update(await self.__get_device_list_page_async( dids=dids, start_did=next_start_did)) return device_infos async def get_devices_with_dids_async( -<<<<<<< HEAD self, dids: list[str] ) -> Optional[dict[str, dict]]: results: list[dict[str, dict]] = await asyncio.gather( *[self.__get_device_list_page_async(dids=dids[index:index+150]) for index in range(0, len(dids), 150)]) -======= - self, dids: list[str]) -> Optional[dict[str, dict]]: - results: list[dict[str, dict]] = await asyncio.gather(*[ - self.__get_device_list_page_async(dids=dids[index:index + 150]) - for index in range(0, len(dids), 150) - ]) ->>>>>>> 83899f8 (fomatted code) devices = {} for result in results: if result is None: @@ -899,19 +632,13 @@ class MIoTHttpClient: devices: dict[str, dict] = {} for device_type in ['home_list', 'share_home_list']: homes.setdefault(device_type, {}) -<<<<<<< HEAD for home_id, home_info in (homeinfos.get( device_type, None) or {}).items(): -======= - for home_id, home_info in (homeinfos.get(device_type, None) or - {}).items(): ->>>>>>> 83899f8 (fomatted code) if isinstance(home_ids, list) and home_id not in home_ids: continue home_name: str = home_info['home_name'] group_id: str = home_info['group_id'] homes[device_type].setdefault( -<<<<<<< HEAD home_id, { 'home_name': home_name, 'uid': home_info['uid'], @@ -939,44 +666,9 @@ class MIoTHttpClient: } for did in room_info.get('dids', [])}) separated_shared_devices: dict = ( await self.get_separated_shared_devices_async()) -======= - home_id, - { - "home_name": home_name, - "uid": home_info["uid"], - "group_id": group_id, - "room_info": {}, - }, - ) - devices.update({ - did: { - "home_id": home_id, - "home_name": home_name, - "room_id": home_id, - "room_name": home_name, - "group_id": group_id, - } for did in home_info.get("dids", []) - }) - for room_id, room_info in home_info.get("room_info").items(): - room_name: str = room_info.get("room_name", "") - homes[device_type][home_id]["room_info"][ - room_id] = room_name - devices.update({ - did: { - "home_id": home_id, - "home_name": home_name, - "room_id": room_id, - "room_name": room_name, - "group_id": group_id, - } for did in room_info.get("dids", []) - }) - separated_shared_devices: dict = await self.get_separated_shared_devices_async( - ) ->>>>>>> 83899f8 (fomatted code) if separated_shared_devices: homes.setdefault('separated_shared_list', {}) for did, owner in separated_shared_devices.items(): -<<<<<<< HEAD owner_id = str(owner['userid']) homes['separated_shared_list'].setdefault(owner_id,{ 'home_name': owner['nickname'], @@ -991,29 +683,6 @@ class MIoTHttpClient: 'room_name': 'shared_device', 'group_id': 'NotSupport' }}) -======= - owner_id = str(owner["userid"]) - homes["separated_shared_list"].setdefault( - owner_id, - { - "home_name": owner["nickname"], - "uid": owner_id, - "group_id": "NotSupport", - "room_info": { - "shared_device": "shared_device" - }, - }, - ) - devices.update({ - did: { - "home_id": owner_id, - "home_name": owner["nickname"], - "room_id": "shared_device", - "room_name": "shared_device", - "group_id": "NotSupport", - } - }) ->>>>>>> 83899f8 (fomatted code) dids = sorted(list(devices.keys())) results = await self.get_devices_with_dids_async(dids=dids) if results is None: @@ -1031,15 +700,9 @@ class MIoTHttpClient: device = devices.pop(did, None) parent_did = did.replace(match_str.group(), '') if parent_did in devices: -<<<<<<< HEAD devices[parent_did].setdefault('sub_devices', {}) devices[parent_did]['sub_devices'][match_str.group()[ 1:]] = device -======= - devices[parent_did].setdefault("sub_devices", {}) - devices[parent_did]["sub_devices"][match_str.group() - [1:]] = device ->>>>>>> 83899f8 (fomatted code) else: _LOGGER.error( 'unknown sub devices, %s, %s', did, parent_did) @@ -1055,17 +718,10 @@ class MIoTHttpClient: {"did": "xxxxxx", "siid": 2, "piid": 2}] """ res_obj = await self.__mihome_api_post_async( -<<<<<<< HEAD url_path='/app/v2/miotspec/prop/get', data={ 'datasource': 1, 'params': params -======= - url_path="/app/v2/miotspec/prop/get", - data={ - "datasource": 1, - "params": params ->>>>>>> 83899f8 (fomatted code) }, ) if 'result' not in res_obj: @@ -1073,16 +729,8 @@ class MIoTHttpClient: return res_obj['result'] async def __get_prop_async(self, did: str, siid: int, piid: int) -> Any: -<<<<<<< HEAD results = await self.get_props_async( params=[{'did': did, 'siid': siid, 'piid': piid}]) -======= - results = await self.get_props_async(params=[{ - "did": did, - "siid": siid, - "piid": piid - }]) ->>>>>>> 83899f8 (fomatted code) if not results: return None result = results[0] @@ -1111,11 +759,7 @@ class MIoTHttpClient: for result in results: if not all( -<<<<<<< HEAD key in result for key in ['did', 'siid', 'piid', 'value']): -======= - key in result for key in ["did", "siid", "piid", "value"]): ->>>>>>> 83899f8 (fomatted code) continue key = f'{result["did"]}.{result["siid"]}.{result["piid"]}' prop_obj = self._get_prop_list.pop(key, None) @@ -1156,17 +800,8 @@ class MIoTHttpClient: return await prop_obj['fut'] fut = self._main_loop.create_future() self._get_prop_list[key] = { -<<<<<<< HEAD 'param': {'did': did, 'siid': siid, 'piid': piid}, 'fut': fut -======= - "param": { - "did": did, - "siid": siid, - "piid": piid - }, - "fut": fut, ->>>>>>> 83899f8 (fomatted code) } if self._get_prop_timer is None: self._get_prop_timer = self._main_loop.call_later( @@ -1181,7 +816,6 @@ class MIoTHttpClient: params = [{"did": "xxxx", "siid": 2, "piid": 1, "value": False}] """ res_obj = await self.__mihome_api_post_async( -<<<<<<< HEAD url_path='/app/v2/miotspec/prop/set', data={ 'params': params @@ -1190,13 +824,6 @@ class MIoTHttpClient: ) if 'result' not in res_obj: raise MIoTHttpError('invalid response result') -======= - url_path="/app/v2/miotspec/prop/set", - data={"params": params}, - timeout=15) - if "result" not in res_obj: - raise MIoTHttpError("invalid response result") ->>>>>>> 83899f8 (fomatted code) return res_obj['result'] @@ -1205,7 +832,6 @@ class MIoTHttpClient: params = [{"did": "xxxx", "siid": 2, "piid": 1, "value": False}] """ res_obj = await self.__mihome_api_post_async( -<<<<<<< HEAD url_path='/app/v2/miotspec/prop/set', data={ 'params': params @@ -1214,13 +840,6 @@ class MIoTHttpClient: ) if 'result' not in res_obj: raise MIoTHttpError('invalid response result') -======= - url_path="/app/v2/miotspec/prop/set", - data={"params": params}, - timeout=15) - if "result" not in res_obj: - raise MIoTHttpError("invalid response result") ->>>>>>> 83899f8 (fomatted code) return res_obj['result'] diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index 0b06044..3158caa 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -114,14 +114,9 @@ class MIoTEntityData: events: set[MIoTSpecEvent] actions: set[MIoTSpecAction] -<<<<<<< HEAD def __init__( self, platform: str, spec: MIoTSpecInstance | MIoTSpecService ) -> None: -======= - def __init__(self, platform: str, - spec: MIoTSpecInstance | MIoTSpecService) -> None: ->>>>>>> 83899f8 (fomatted code) self.platform = platform self.spec = spec self.device_class = None @@ -154,13 +149,8 @@ class MIoTDevice: _suggested_area: Optional[str] _sub_id: int -<<<<<<< HEAD _device_state_sub_list: dict[str, dict[ str, Callable[[str, MIoTDeviceState], None]]] -======= - _device_state_sub_list: dict[str, dict[str, Callable[[str, MIoTDeviceState], - None]]] ->>>>>>> 83899f8 (fomatted code) _value_sub_list: dict[str, dict[str, Callable[[dict, Any], None]]] _entity_list: dict[str, list[MIoTEntityData]] @@ -190,17 +180,10 @@ class MIoTDevice: self._room_id = device_info.get('room_id', None) self._room_name = device_info.get('room_name', None) match self.miot_client.area_name_rule: -<<<<<<< HEAD case 'home_room': self._suggested_area = ( f'{self._home_name} {self._room_name}'.strip()) case 'home': -======= - case "home_room": - self._suggested_area = f"{self._home_name} {self._room_name}".strip( - ) - case "home": ->>>>>>> 83899f8 (fomatted code) self._suggested_area = self._home_name.strip() case 'room': self._suggested_area = self._room_name.strip() @@ -222,7 +205,6 @@ class MIoTDevice: sub_info = sub_devices.get(f's{service.iid}', None) if sub_info is None: continue -<<<<<<< HEAD _LOGGER.debug( 'miot device, update service sub info, %s, %s', self.did, sub_info) @@ -232,16 +214,6 @@ class MIoTDevice: # Sub device state self.miot_client.sub_device_state( self._did, self.__on_device_state_changed) -======= - _LOGGER.debug("miot device, update service sub info, %s, %s", - self.did, sub_info) - service.description_trans = sub_info.get( - "name", service.description_trans) - - # Sub device state - self.miot_client.sub_device_state(self._did, - self.__on_device_state_changed) ->>>>>>> 83899f8 (fomatted code) _LOGGER.debug('miot device init %s', device_info) @@ -266,15 +238,8 @@ class MIoTDevice: return self._action_list async def action_async(self, siid: int, aiid: int, in_list: list) -> list: -<<<<<<< HEAD return await self.miot_client.action_async( did=self._did, siid=siid, aiid=aiid, in_list=in_list) -======= - return await self.miot_client.action_async(did=self._did, - siid=siid, - aiid=aiid, - in_list=in_list) ->>>>>>> 83899f8 (fomatted code) def sub_device_state( self, key: str, handler: Callable[[str, MIoTDeviceState], @@ -293,16 +258,10 @@ class MIoTDevice: if not sub_list: self._device_state_sub_list.pop(key, None) -<<<<<<< HEAD def sub_property( self, handler: Callable[[dict, Any], None], siid: int, piid: int ) -> int: key: str = f'p.{siid}.{piid}' -======= - def sub_property(self, handler: Callable[[dict, Any], None], siid: int, - piid: int) -> int: - key: str = f"p.{siid}.{piid}" ->>>>>>> 83899f8 (fomatted code) def _on_prop_changed(params: dict, ctx: Any) -> None: for handler in self._value_sub_list[key].values(): @@ -313,15 +272,8 @@ class MIoTDevice: self._value_sub_list[key][str(sub_id)] = handler else: self._value_sub_list[key] = {str(sub_id): handler} -<<<<<<< HEAD self.miot_client.sub_prop( did=self._did, handler=_on_prop_changed, siid=siid, piid=piid) -======= - self.miot_client.sub_prop(did=self._did, - handler=_on_prop_changed, - siid=siid, - piid=piid) ->>>>>>> 83899f8 (fomatted code) return sub_id def unsub_property(self, siid: int, piid: int, sub_id: int) -> None: @@ -334,16 +286,10 @@ class MIoTDevice: self.miot_client.unsub_prop(did=self._did, siid=siid, piid=piid) self._value_sub_list.pop(key, None) -<<<<<<< HEAD def sub_event( self, handler: Callable[[dict, Any], None], siid: int, eiid: int ) -> int: key: str = f'e.{siid}.{eiid}' -======= - def sub_event(self, handler: Callable[[dict, Any], None], siid: int, - eiid: int) -> int: - key: str = f"e.{siid}.{eiid}" ->>>>>>> 83899f8 (fomatted code) def _on_event_occurred(params: dict, ctx: Any) -> None: for handler in self._value_sub_list[key].values(): @@ -354,15 +300,8 @@ class MIoTDevice: self._value_sub_list[key][str(sub_id)] = handler else: self._value_sub_list[key] = {str(sub_id): handler} -<<<<<<< HEAD self.miot_client.sub_event( did=self._did, handler=_on_event_occurred, siid=siid, eiid=eiid) -======= - self.miot_client.sub_event(did=self._did, - handler=_on_event_occurred, - siid=siid, - eiid=eiid) ->>>>>>> 83899f8 (fomatted code) return sub_id def unsub_event(self, siid: int, eiid: int, sub_id: int) -> None: @@ -386,13 +325,8 @@ class MIoTDevice: manufacturer=self._manufacturer, suggested_area=self._suggested_area, configuration_url=( -<<<<<<< HEAD f'https://home.mi.com/webapp/content/baike/product/index.html?' f'model={self._model}') -======= - f"https://home.mi.com/webapp/content/baike/product/index.html?" - f"model={self._model}"), ->>>>>>> 83899f8 (fomatted code) ) @property @@ -402,7 +336,6 @@ class MIoTDevice: @property def did_tag(self) -> str: -<<<<<<< HEAD return slugify_did( cloud_server=self.miot_client.cloud_server, did=self._did) @@ -440,37 +373,6 @@ class MIoTDevice: f'{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_' f'{self._model_strs[-1][:20]}_{slugify_name(spec_name)}' f'_a_{siid}_{aiid}') -======= - return slugify_did(cloud_server=self.miot_client.cloud_server, - did=self._did) - - def gen_device_entity_id(self, ha_domain: str) -> str: - return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" - f"{self._model_strs[-1][:20]}") - - def gen_service_entity_id(self, ha_domain: str, siid: int, - description: str) -> str: - return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" - f"{self._model_strs[-1][:20]}_s_{siid}_{description}") - - def gen_prop_entity_id(self, ha_domain: str, spec_name: str, siid: int, - piid: int) -> str: - return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" - f"{self._model_strs[-1][:20]}_{slugify_name(spec_name)}" - f"_p_{siid}_{piid}") - - def gen_event_entity_id(self, ha_domain: str, spec_name: str, siid: int, - eiid: int) -> str: - return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" - f"{self._model_strs[-1][:20]}_{slugify_name(spec_name)}" - f"_e_{siid}_{eiid}") - - def gen_action_entity_id(self, ha_domain: str, spec_name: str, siid: int, - aiid: int) -> str: - return (f"{ha_domain}.{self._model_strs[0][:9]}_{self.did_tag}_" - f"{self._model_strs[-1][:20]}_{slugify_name(spec_name)}" - f"_a_{siid}_{aiid}") ->>>>>>> 83899f8 (fomatted code) @property def name(self) -> str: @@ -516,16 +418,10 @@ class MIoTDevice: if 'required' not in SPEC_DEVICE_TRANS_MAP[spec_name]: return None # 1. The device shall have all required services. -<<<<<<< HEAD required_services = SPEC_DEVICE_TRANS_MAP[spec_name]['required'].keys() if not { service.name for service in spec_instance.services }.issuperset(required_services): -======= - required_services = SPEC_DEVICE_TRANS_MAP[spec_name]["required"].keys() - if not {service.name for service in spec_instance.services - }.issuperset(required_services): ->>>>>>> 83899f8 (fomatted code) return None optional_services = SPEC_DEVICE_TRANS_MAP[spec_name]['optional'].keys() @@ -541,7 +437,6 @@ class MIoTDevice: # 2. The required service shall have all required properties # and actions. if service.name in required_services: -<<<<<<< HEAD required_properties = SPEC_DEVICE_TRANS_MAP[spec_name][ 'required'].get( service.name, {} @@ -613,59 +508,6 @@ class MIoTDevice: for prop in service.properties: if prop.name in set.union( set(required_properties.keys()), optional_properties): -======= - required_properties = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( - service.name, {}).get("required", - {}).get("properties", {})) - optional_properties = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( - service.name, {}).get("optional", - {}).get("properties", set({}))) - required_actions = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( - service.name, {}).get("required", - {}).get("actions", set({}))) - optional_actions = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["required"].get( - service.name, {}).get("optional", - {}).get("actions", set({}))) - elif service.name in optional_services: - required_properties = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( - service.name, {}).get("required", - {}).get("properties", {})) - optional_properties = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( - service.name, {}).get("optional", - {}).get("properties", set({}))) - required_actions = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( - service.name, {}).get("required", - {}).get("actions", set({}))) - optional_actions = ( - SPEC_DEVICE_TRANS_MAP[spec_name]["optional"].get( - service.name, {}).get("optional", - {}).get("actions", set({}))) - else: - continue - if not {prop.name for prop in service.properties if prop.access - }.issuperset(set(required_properties.keys())): - return None - if not {action.name for action in service.actions - }.issuperset(required_actions): - return None - # 3. The required property shall have all required access mode. - for prop in service.properties: - if prop.name in required_properties: - if not set(prop.access).issuperset( - required_properties[prop.name]): - return None - # property - for prop in service.properties: - if prop.name in set.union(set(required_properties.keys()), - optional_properties): ->>>>>>> 83899f8 (fomatted code) if prop.unit: prop.external_unit = self.unit_convert(prop.unit) # prop.icon = self.icon_convert(prop.unit) @@ -683,17 +525,12 @@ class MIoTDevice: return entity_data def parse_miot_service_entity( -<<<<<<< HEAD self, miot_service: MIoTSpecService ) -> Optional[MIoTEntityData]: if ( miot_service.platform or miot_service.name not in SPEC_SERVICE_TRANS_MAP ): -======= - self, miot_service: MIoTSpecService) -> Optional[MIoTEntityData]: - if miot_service.platform or miot_service.name not in SPEC_SERVICE_TRANS_MAP: ->>>>>>> 83899f8 (fomatted code) return None service_name = miot_service.name if isinstance(SPEC_SERVICE_TRANS_MAP[service_name], str): @@ -702,16 +539,10 @@ class MIoTDevice: return None # Required properties, required access mode required_properties: dict = SPEC_SERVICE_TRANS_MAP[service_name][ -<<<<<<< HEAD 'required'].get('properties', {}) if not { prop.name for prop in miot_service.properties if prop.access }.issuperset(set(required_properties.keys())): -======= - "required"].get("properties", {}) - if not {prop.name for prop in miot_service.properties if prop.access - }.issuperset(set(required_properties.keys())): ->>>>>>> 83899f8 (fomatted code) return None for prop in miot_service.properties: if prop.name in required_properties: @@ -724,17 +555,10 @@ class MIoTDevice: entity_data = MIoTEntityData(platform=platform, spec=miot_service) # Optional properties optional_properties = SPEC_SERVICE_TRANS_MAP[service_name][ -<<<<<<< HEAD 'optional'].get('properties', set({})) for prop in miot_service.properties: if prop.name in set.union( set(required_properties.keys()), optional_properties): -======= - "optional"].get("properties", set({})) - for prop in miot_service.properties: - if prop.name in set.union(set(required_properties.keys()), - optional_properties): ->>>>>>> 83899f8 (fomatted code) if prop.unit: prop.external_unit = self.unit_convert(prop.unit) # prop.icon = self.icon_convert(prop.unit) @@ -745,24 +569,15 @@ class MIoTDevice: miot_service.platform = platform # entity_category if entity_category := SPEC_SERVICE_TRANS_MAP[service_name].get( -<<<<<<< HEAD 'entity_category', None): -======= - "entity_category", None): ->>>>>>> 83899f8 (fomatted code) miot_service.entity_category = entity_category return entity_data def parse_miot_property_entity(self, miot_prop: MIoTSpecProperty) -> bool: -<<<<<<< HEAD if ( miot_prop.platform or miot_prop.name not in SPEC_PROP_TRANS_MAP['properties'] ): -======= - if (miot_prop.platform or - miot_prop.name not in SPEC_PROP_TRANS_MAP["properties"]): ->>>>>>> 83899f8 (fomatted code) return False prop_name = miot_prop.name if isinstance(SPEC_PROP_TRANS_MAP['properties'][prop_name], str): @@ -777,7 +592,6 @@ class MIoTDevice: if prop_access != (SPEC_PROP_TRANS_MAP[ 'entities'][platform]['access']): return False -<<<<<<< HEAD if miot_prop.format_.__name__ not in SPEC_PROP_TRANS_MAP[ 'entities'][platform]['format']: return False @@ -795,22 +609,6 @@ class MIoTDevice: # Priority: spec_modify.unit > unit_convert > specv2entity.unit miot_prop.external_unit = SPEC_PROP_TRANS_MAP['properties'][ prop_name]['unit_of_measurement'] -======= - if (miot_prop.format_.__name__ - not in SPEC_PROP_TRANS_MAP["entities"][platform]["format"]): - return False - miot_prop.device_class = SPEC_PROP_TRANS_MAP["properties"][prop_name][ - "device_class"] - # Optional params - if "state_class" in SPEC_PROP_TRANS_MAP["properties"][prop_name]: - miot_prop.state_class = SPEC_PROP_TRANS_MAP["properties"][ - prop_name]["state_class"] - if (not miot_prop.external_unit and "unit_of_measurement" - in SPEC_PROP_TRANS_MAP["properties"][prop_name]): - # Priority: spec_modify.unit > unit_convert > specv2entity.unit - miot_prop.external_unit = SPEC_PROP_TRANS_MAP["properties"][ - prop_name]["unit_of_measurement"] ->>>>>>> 83899f8 (fomatted code) # Priority: default.icon when device_class is set > spec_modify.icon # > icon_convert miot_prop.platform = platform @@ -1011,18 +809,7 @@ class MIoTDevice: if spec_unit in {'percentage'}: return 'mdi:percent' if spec_unit in { -<<<<<<< HEAD 'weeks', 'days', 'hour', 'hours', 'minutes', 'seconds', 'ms', 'μs' -======= - "weeks", - "days", - "hour", - "hours", - "minutes", - "seconds", - "ms", - "μs", ->>>>>>> 83899f8 (fomatted code) }: return 'mdi:clock' if spec_unit in {'celsius'}: @@ -1100,7 +887,6 @@ class MIoTServiceEntity(Entity): _state_sub_id: int _value_sub_ids: dict[str, int] -<<<<<<< HEAD _event_occurred_handler: Optional[ Callable[[MIoTSpecEvent, dict], None]] _prop_changed_subs: dict[ @@ -1117,18 +903,6 @@ class MIoTServiceEntity(Entity): or entity_data.spec is None ): raise MIoTDeviceError('init error, invalid params') -======= - _event_occurred_handler: Optional[Callable[[MIoTSpecEvent, dict], None]] - _prop_changed_subs: dict[MIoTSpecProperty, Callable[[MIoTSpecProperty, Any], - None]] - - _pending_write_ha_state_timer: Optional[asyncio.TimerHandle] - - def __init__(self, miot_device: MIoTDevice, - entity_data: MIoTEntityData) -> None: - if miot_device is None or entity_data is None or entity_data.spec is None: - raise MIoTDeviceError("init error, invalid params") ->>>>>>> 83899f8 (fomatted code) self.miot_device = miot_device self.entity_data = entity_data self._main_loop = miot_device.miot_client.main_loop @@ -1144,13 +918,8 @@ class MIoTServiceEntity(Entity): DOMAIN, siid=self.entity_data.spec.iid, description=self.entity_data.spec.description) self._attr_name = ( -<<<<<<< HEAD f'{"* "if self.entity_data.spec.proprietary else " "}' f'{self.entity_data.spec.description_trans}') -======= - f"{'* ' if self.entity_data.spec.proprietary else ' '}" - f"{self.entity_data.spec.description_trans}") ->>>>>>> 83899f8 (fomatted code) self._attr_entity_category = entity_data.spec.entity_category # Set entity attr self._attr_unique_id = self.entity_id @@ -1168,12 +937,8 @@ class MIoTServiceEntity(Entity): @property def event_occurred_handler( -<<<<<<< HEAD self ) -> Optional[Callable[[MIoTSpecEvent, dict], None]]: -======= - self) -> Optional[Callable[[MIoTSpecEvent, dict], None]]: ->>>>>>> 83899f8 (fomatted code) return self._event_occurred_handler @event_occurred_handler.setter @@ -1181,14 +946,9 @@ class MIoTServiceEntity(Entity): self._event_occurred_handler = func def sub_prop_changed( -<<<<<<< HEAD self, prop: MIoTSpecProperty, handler: Callable[[MIoTSpecProperty, Any], None] ) -> None: -======= - self, prop: MIoTSpecProperty, - handler: Callable[[MIoTSpecProperty, Any], None]) -> None: ->>>>>>> 83899f8 (fomatted code) if not prop or not handler: _LOGGER.error( 'sub_prop_changed error, invalid prop/handler') @@ -1221,12 +981,7 @@ class MIoTServiceEntity(Entity): key = f'e.{event.service.iid}.{event.iid}' self._value_sub_ids[key] = self.miot_device.sub_event( handler=self.__on_event_occurred, -<<<<<<< HEAD siid=event.service.iid, eiid=event.iid) -======= - siid=event.service.iid, - eiid=event.iid) ->>>>>>> 83899f8 (fomatted code) # Refresh value if self._attr_available: @@ -1238,20 +993,13 @@ class MIoTServiceEntity(Entity): self._pending_write_ha_state_timer = None state_id = 's.0' if isinstance(self.entity_data.spec, MIoTSpecService): -<<<<<<< HEAD state_id = f's.{self.entity_data.spec.iid}' self.miot_device.unsub_device_state( key=state_id, sub_id=self._state_sub_id) -======= - state_id = f"s.{self.entity_data.spec.iid}" - self.miot_device.unsub_device_state(key=state_id, - sub_id=self._state_sub_id) ->>>>>>> 83899f8 (fomatted code) # Unsub prop for prop in self.entity_data.props: if not prop.notifiable and not prop.readable: continue -<<<<<<< HEAD sub_id = self._value_sub_ids.pop( f'p.{prop.service.iid}.{prop.iid}', None) if sub_id: @@ -1264,22 +1012,6 @@ class MIoTServiceEntity(Entity): if sub_id: self.miot_device.unsub_event( siid=event.service.iid, eiid=event.iid, sub_id=sub_id) -======= - sub_id = self._value_sub_ids.pop(f"p.{prop.service.iid}.{prop.iid}", - None) - if sub_id: - self.miot_device.unsub_property(siid=prop.service.iid, - piid=prop.iid, - sub_id=sub_id) - # Unsub event - for event in self.entity_data.events: - sub_id = self._value_sub_ids.pop( - f"e.{event.service.iid}.{event.iid}", None) - if sub_id: - self.miot_device.unsub_event(siid=event.service.iid, - eiid=event.iid, - sub_id=sub_id) ->>>>>>> 83899f8 (fomatted code) def get_map_value( self, map_: Optional[dict[int, Any]], key: int @@ -1288,14 +1020,9 @@ class MIoTServiceEntity(Entity): return None return map_.get(key, None) -<<<<<<< HEAD def get_map_key( self, map_: Optional[dict[int, Any]], value: Any ) -> Optional[int]: -======= - def get_map_key(self, map_: Optional[dict[int, Any]], - value: Any) -> Optional[int]: ->>>>>>> 83899f8 (fomatted code) if map_ is None: return None for key, value_ in map_.items(): @@ -1311,14 +1038,9 @@ class MIoTServiceEntity(Entity): return None return self._prop_value_map.get(prop, None) -<<<<<<< HEAD def set_prop_value( self, prop: Optional[MIoTSpecProperty], value: Any ) -> None: -======= - def set_prop_value(self, prop: Optional[MIoTSpecProperty], - value: Any) -> None: ->>>>>>> 83899f8 (fomatted code) if not prop: _LOGGER.error( 'set_prop_value error, property is None, %s, %s', @@ -1337,7 +1059,6 @@ class MIoTServiceEntity(Entity): value = prop.value_format(value) value = prop.value_precision(value) if prop not in self.entity_data.props: -<<<<<<< HEAD raise RuntimeError( f'set property failed, unknown property, ' f'{self.entity_id}, {self.name}, {prop.name}') @@ -1345,24 +1066,13 @@ class MIoTServiceEntity(Entity): raise RuntimeError( f'set property failed, not writable, ' f'{self.entity_id}, {self.name}, {prop.name}') -======= - raise RuntimeError(f"set property failed, unknown property, " - f"{self.entity_id}, {self.name}, {prop.name}") - if not prop.writable: - raise RuntimeError(f"set property failed, not writable, " - f"{self.entity_id}, {self.name}, {prop.name}") ->>>>>>> 83899f8 (fomatted code) try: await self.miot_device.miot_client.set_prop_async( did=self.miot_device.did, siid=prop.service.iid, piid=prop.iid, value=value) except MIoTClientError as e: raise RuntimeError( -<<<<<<< HEAD f'{e}, {self.entity_id}, {self.name}, {prop.name}') from e -======= - f"{e}, {self.entity_id}, {self.name}, {prop.name}") from e ->>>>>>> 83899f8 (fomatted code) if update_value: self._prop_value_map[prop] = value if write_ha_state: @@ -1379,7 +1089,6 @@ class MIoTServiceEntity(Entity): prop = set_property.get("prop") value = set_property.get("value") if not prop: -<<<<<<< HEAD raise RuntimeError( f'set property failed, property is None, ' f'{self.entity_id}, {self.name}') @@ -1395,19 +1104,6 @@ class MIoTServiceEntity(Entity): raise RuntimeError( f'set property failed, not writable, ' f'{self.entity_id}, {self.name}, {prop.name}') -======= - raise RuntimeError(f"set property failed, property is None, " - f"{self.entity_id}, {self.name}") - set_property["value"] = prop.value_format(value) - if prop not in self.entity_data.props: - raise RuntimeError( - f"set property failed, unknown property, " - f"{self.entity_id}, {self.name}, {prop.name}") - if not prop.writable: - raise RuntimeError( - f"set property failed, not writable, " - f"{self.entity_id}, {self.name}, {prop.name}") ->>>>>>> 83899f8 (fomatted code) try: await self.miot_device.miot_client.set_props_async([{ "did": self.miot_device.did, @@ -1442,19 +1138,11 @@ class MIoTServiceEntity(Entity): 'get property failed, not readable, %s, %s, %s', self.entity_id, self.name, prop.name) return None -<<<<<<< HEAD value: Any = prop.value_format( await self.miot_device.miot_client.get_prop_async( did=self.miot_device.did, siid=prop.service.iid, piid=prop.iid)) value = prop.eval_expr(value) result = prop.value_precision(value) -======= - result = prop.value_format(await - self.miot_device.miot_client.get_prop_async( - did=self.miot_device.did, - siid=prop.service.iid, - piid=prop.iid)) ->>>>>>> 83899f8 (fomatted code) if result != self._prop_value_map[prop]: self._prop_value_map[prop] = result self.async_write_ha_state() @@ -1465,22 +1153,14 @@ class MIoTServiceEntity(Entity): in_list: Optional[list] = None) -> bool: if not action: raise RuntimeError( -<<<<<<< HEAD f'action failed, action is None, {self.entity_id}, {self.name}') -======= - f"action failed, action is None, {self.entity_id}, {self.name}") ->>>>>>> 83899f8 (fomatted code) try: await self.miot_device.miot_client.action_async( did=self.miot_device.did, siid=action.service.iid, aiid=action.iid, in_list=in_list or []) except MIoTClientError as e: raise RuntimeError( -<<<<<<< HEAD f'{e}, {self.entity_id}, {self.name}, {action.name}') from e -======= - f"{e}, {self.entity_id}, {self.name}, {action.name}") from e ->>>>>>> 83899f8 (fomatted code) return True def __on_properties_changed(self, params: dict, ctx: Any) -> None: @@ -1506,15 +1186,10 @@ class MIoTServiceEntity(Entity): if self._event_occurred_handler is None: return for event in self.entity_data.events: -<<<<<<< HEAD if ( event.iid != params['eiid'] or event.service.iid != params['siid'] ): -======= - if event.iid != params["eiid"] or event.service.iid != params[ - "siid"]: ->>>>>>> 83899f8 (fomatted code) continue trans_arg = {} for item in params['arguments']: @@ -1525,14 +1200,9 @@ class MIoTServiceEntity(Entity): self._event_occurred_handler(event, trans_arg) break -<<<<<<< HEAD def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: -======= - def __on_device_state_changed(self, key: str, - state: MIoTDeviceState) -> None: ->>>>>>> 83899f8 (fomatted code) state_new = state == MIoTDeviceState.ONLINE if state_new == self._attr_available: return @@ -1591,27 +1261,15 @@ class MIoTPropertyEntity(Entity): self._pending_write_ha_state_timer = None # Gen entity_id self.entity_id = self.miot_device.gen_prop_entity_id( -<<<<<<< HEAD ha_domain=DOMAIN, spec_name=spec.name, siid=spec.service.iid, piid=spec.iid) -======= - ha_domain=DOMAIN, - spec_name=spec.name, - siid=spec.service.iid, - piid=spec.iid) ->>>>>>> 83899f8 (fomatted code) # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False self._attr_has_entity_name = True self._attr_name = ( -<<<<<<< HEAD f'{"* "if self.spec.proprietary else " "}' f'{self.service.description_trans} {spec.description_trans}') -======= - f"{'* ' if self.spec.proprietary else ' '}" - f"{self.service.description_trans} {spec.description_trans}") ->>>>>>> 83899f8 (fomatted code) self._attr_available = miot_device.online _LOGGER.info( @@ -1631,12 +1289,7 @@ class MIoTPropertyEntity(Entity): # Sub value changed self._value_sub_id = self.miot_device.sub_property( handler=self.__on_value_changed, -<<<<<<< HEAD siid=self.service.iid, piid=self.spec.iid) -======= - siid=self.service.iid, - piid=self.spec.iid) ->>>>>>> 83899f8 (fomatted code) # Refresh value if self._attr_available: self.__request_refresh_prop() @@ -1646,19 +1299,11 @@ class MIoTPropertyEntity(Entity): self._pending_write_ha_state_timer.cancel() self._pending_write_ha_state_timer = None self.miot_device.unsub_device_state( -<<<<<<< HEAD key=f'{ self.service.iid}.{self.spec.iid}', sub_id=self._state_sub_id) self.miot_device.unsub_property( siid=self.service.iid, piid=self.spec.iid, sub_id=self._value_sub_id) -======= - key=f"{self.service.iid}.{self.spec.iid}", - sub_id=self._state_sub_id) - self.miot_device.unsub_property(siid=self.service.iid, - piid=self.spec.iid, - sub_id=self._value_sub_id) ->>>>>>> 83899f8 (fomatted code) def get_vlist_description(self, value: Any) -> Optional[str]: if not self._value_list: @@ -1690,28 +1335,17 @@ class MIoTPropertyEntity(Entity): async def get_property_async(self) -> Any: if not self.spec.readable: -<<<<<<< HEAD _LOGGER.error( 'get property failed, not readable, %s, %s', self.entity_id, self.name) -======= - _LOGGER.error("get property failed, not readable, %s, %s", - self.entity_id, self.name) ->>>>>>> 83899f8 (fomatted code) return None value: Any = self.spec.value_format( await self.miot_device.miot_client.get_prop_async( -<<<<<<< HEAD did=self.miot_device.did, siid=self.spec.service.iid, piid=self.spec.iid)) value = self.spec.eval_expr(value) result = self.spec.value_precision(value) return result -======= - did=self.miot_device.did, - siid=self.spec.service.iid, - piid=self.spec.iid)) ->>>>>>> 83899f8 (fomatted code) def __on_value_changed(self, params: dict, ctx: Any) -> None: _LOGGER.debug('property changed, %s', params) @@ -1721,14 +1355,9 @@ class MIoTPropertyEntity(Entity): if not self._pending_write_ha_state_timer: self.async_write_ha_state() -<<<<<<< HEAD def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: -======= - def __on_device_state_changed(self, key: str, - state: MIoTDeviceState) -> None: ->>>>>>> 83899f8 (fomatted code) self._attr_available = state == MIoTDeviceState.ONLINE if not self._attr_available: self.async_write_ha_state() @@ -1739,12 +1368,7 @@ class MIoTPropertyEntity(Entity): def __request_refresh_prop(self) -> None: if self.spec.readable: self.miot_device.miot_client.request_refresh_prop( -<<<<<<< HEAD did=self.miot_device.did, siid=self.service.iid, -======= - did=self.miot_device.did, - siid=self.service.iid, ->>>>>>> 83899f8 (fomatted code) piid=self.spec.iid) if self._pending_write_ha_state_timer: self._pending_write_ha_state_timer.cancel() @@ -1779,27 +1403,15 @@ class MIoTEventEntity(Entity): self._main_loop = miot_device.miot_client.main_loop # Gen entity_id self.entity_id = self.miot_device.gen_event_entity_id( -<<<<<<< HEAD ha_domain=DOMAIN, spec_name=spec.name, siid=spec.service.iid, eiid=spec.iid) -======= - ha_domain=DOMAIN, - spec_name=spec.name, - siid=spec.service.iid, - eiid=spec.iid) ->>>>>>> 83899f8 (fomatted code) # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False self._attr_has_entity_name = True self._attr_name = ( -<<<<<<< HEAD f'{"* "if self.spec.proprietary else " "}' f'{self.service.description_trans} {spec.description_trans}') -======= - f"{'* ' if self.spec.proprietary else ' '}" - f"{self.service.description_trans} {spec.description_trans}") ->>>>>>> 83899f8 (fomatted code) self._attr_available = miot_device.online self._attr_event_types = [spec.description_trans] @@ -1826,7 +1438,6 @@ class MIoTEventEntity(Entity): # Sub value changed self._value_sub_id = self.miot_device.sub_event( handler=self.__on_event_occurred, -<<<<<<< HEAD siid=self.service.iid, eiid=self.spec.iid) async def async_will_remove_from_hass(self) -> None: @@ -1836,18 +1447,6 @@ class MIoTEventEntity(Entity): self.miot_device.unsub_event( siid=self.service.iid, eiid=self.spec.iid, sub_id=self._value_sub_id) -======= - siid=self.service.iid, - eiid=self.spec.iid) - - async def async_will_remove_from_hass(self) -> None: - self.miot_device.unsub_device_state( - key=f"event.{self.service.iid}.{self.spec.iid}", - sub_id=self._state_sub_id) - self.miot_device.unsub_event(siid=self.service.iid, - eiid=self.spec.iid, - sub_id=self._value_sub_id) ->>>>>>> 83899f8 (fomatted code) @abstractmethod def on_event_occurred(self, @@ -1862,7 +1461,6 @@ class MIoTEventEntity(Entity): try: if 'value' not in item: continue -<<<<<<< HEAD if 'piid' in item: trans_arg[self._arguments_map[item['piid']]] = item[ 'value'] @@ -1870,12 +1468,6 @@ class MIoTEventEntity(Entity): isinstance(item['value'], list) and len(item['value']) == len(self.spec.argument) ): -======= - if "piid" in item: - trans_arg[self._arguments_map[item["piid"]]] = item["value"] - elif isinstance(item["value"], list) and len( - item["value"]) == len(self.spec.argument): ->>>>>>> 83899f8 (fomatted code) # Dirty fix for cloud multi-arguments trans_arg = { prop.description_trans: item['value'][index] @@ -1884,7 +1476,6 @@ class MIoTEventEntity(Entity): break except KeyError as error: _LOGGER.debug( -<<<<<<< HEAD 'on event msg, invalid args, %s, %s, %s', self.entity_id, params, error) self.on_event_occurred( @@ -1894,19 +1485,6 @@ class MIoTEventEntity(Entity): def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: -======= - "on event msg, invalid args, %s, %s, %s", - self.entity_id, - params, - error, - ) - self.on_event_occurred(name=self.spec.description_trans, - arguments=trans_arg) - self.async_write_ha_state() - - def __on_device_state_changed(self, key: str, - state: MIoTDeviceState) -> None: ->>>>>>> 83899f8 (fomatted code) state_new = state == MIoTDeviceState.ONLINE if state_new == self._attr_available: return @@ -1937,27 +1515,15 @@ class MIoTActionEntity(Entity): self._state_sub_id = 0 # Gen entity_id self.entity_id = self.miot_device.gen_action_entity_id( -<<<<<<< HEAD ha_domain=DOMAIN, spec_name=spec.name, siid=spec.service.iid, aiid=spec.iid) -======= - ha_domain=DOMAIN, - spec_name=spec.name, - siid=spec.service.iid, - aiid=spec.iid) ->>>>>>> 83899f8 (fomatted code) # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False self._attr_has_entity_name = True self._attr_name = ( -<<<<<<< HEAD f'{"* "if self.spec.proprietary else " "}' f'{self.service.description_trans} {spec.description_trans}') -======= - f"{'* ' if self.spec.proprietary else ' '}" - f"{self.service.description_trans} {spec.description_trans}") ->>>>>>> 83899f8 (fomatted code) self._attr_available = miot_device.online _LOGGER.debug( @@ -1976,20 +1542,12 @@ class MIoTActionEntity(Entity): async def async_will_remove_from_hass(self) -> None: self.miot_device.unsub_device_state( -<<<<<<< HEAD key=f'a.{ self.service.iid}.{self.spec.iid}', sub_id=self._state_sub_id) async def action_async( self, in_list: Optional[list] = None ) -> Optional[list]: -======= - key=f"a.{self.service.iid}.{self.spec.iid}", - sub_id=self._state_sub_id) - - async def action_async(self, - in_list: Optional[list] = None) -> Optional[list]: ->>>>>>> 83899f8 (fomatted code) try: return await self.miot_device.miot_client.action_async( did=self.miot_device.did, @@ -1999,14 +1557,9 @@ class MIoTActionEntity(Entity): except MIoTClientError as e: raise RuntimeError(f'{e}, {self.entity_id}, {self.name}') from e -<<<<<<< HEAD def __on_device_state_changed( self, key: str, state: MIoTDeviceState ) -> None: -======= - def __on_device_state_changed(self, key: str, - state: MIoTDeviceState) -> None: ->>>>>>> 83899f8 (fomatted code) state_new = state == MIoTDeviceState.ONLINE if state_new == self._attr_available: return diff --git a/custom_components/xiaomi_home/miot/miot_lan.py b/custom_components/xiaomi_home/miot/miot_lan.py index 48a5e2d..dd0046f 100644 --- a/custom_components/xiaomi_home/miot/miot_lan.py +++ b/custom_components/xiaomi_home/miot/miot_lan.py @@ -163,7 +163,6 @@ class _MIoTLanDevice: # All functions SHOULD be called from the internal loop -<<<<<<< HEAD def __init__( self, manager: 'MIoTLan', @@ -171,25 +170,13 @@ class _MIoTLanDevice: token: str, ip: Optional[str] = None ) -> None: -======= - def __init__(self, - manager: "MIoTLan", - did: str, - token: str, - ip: Optional[str] = None) -> None: ->>>>>>> 83899f8 (fomatted code) self._manager: MIoTLan = manager self.did = did self.token = bytes.fromhex(token) aes_key: bytes = self.__md5(self.token) aex_iv: bytes = self.__md5(aes_key + self.token) -<<<<<<< HEAD self.cipher = Cipher( algorithms.AES128(aes_key), modes.CBC(aex_iv), default_backend()) -======= - self.cipher = Cipher(algorithms.AES128(aes_key), modes.CBC(aex_iv), - default_backend()) ->>>>>>> 83899f8 (fomatted code) self.ip = ip self.offset = 0 self.subscribed = False @@ -214,13 +201,8 @@ class _MIoTLanDevice: self.ip = ip if self._if_name != if_name: self._if_name = if_name -<<<<<<< HEAD _LOGGER.info( 'device if_name change, %s, %s', self._if_name, self.did) -======= - _LOGGER.info("device if_name change, %s, %s", self._if_name, - self.did) ->>>>>>> 83899f8 (fomatted code) self.__update_keep_alive(state=_MIoTLanDeviceState.FRESH) @property @@ -233,48 +215,27 @@ class _MIoTLanDevice: return self._online = online self._manager.broadcast_device_state( -<<<<<<< HEAD did=self.did, state={ 'online': self._online, 'push_available': self.subscribed}) -======= - did=self.did, - state={ - "online": self._online, - "push_available": self.subscribed - }, - ) ->>>>>>> 83899f8 (fomatted code) @property def if_name(self) -> Optional[str]: return self._if_name -<<<<<<< HEAD def gen_packet( self, out_buffer: bytearray, clear_data: dict, did: str, offset: int ) -> int: clear_bytes = json.dumps(clear_data, ensure_ascii=False).encode('utf-8') -======= - def gen_packet(self, out_buffer: bytearray, clear_data: dict, did: str, - offset: int) -> int: - clear_bytes = json.dumps(clear_data, ensure_ascii=False).encode("utf-8") ->>>>>>> 83899f8 (fomatted code) padder = padding.PKCS7(algorithms.AES128.block_size).padder() padded_data = padder.update(clear_bytes) + padder.finalize() if len(padded_data) + self.OT_HEADER_LEN > len(out_buffer): raise ValueError('rpc too long') encryptor = self.cipher.encryptor() encrypted_data = encryptor.update(padded_data) + encryptor.finalize() -<<<<<<< HEAD data_len: int = len(encrypted_data)+self.OT_HEADER_LEN out_buffer[:32] = struct.pack( '>HHQI16s', self.OT_HEADER, data_len, int(did), offset, self.token) -======= - data_len: int = len(encrypted_data) + self.OT_HEADER_LEN - out_buffer[:32] = struct.pack(">HHQI16s", self.OT_HEADER, data_len, - int(did), offset, self.token) ->>>>>>> 83899f8 (fomatted code) out_buffer[32:data_len] = encrypted_data msg_md5: bytes = self.__md5(out_buffer[0:data_len]) out_buffer[16:32] = msg_md5 @@ -288,13 +249,8 @@ class _MIoTLanDevice: if md5_orig != md5_calc: raise ValueError(f'invalid md5, {md5_orig}, {md5_calc}') decryptor = self.cipher.decryptor() -<<<<<<< HEAD decrypted_padded_data = decryptor.update( encrypted_data[32:data_len]) + decryptor.finalize() -======= - decrypted_padded_data = (decryptor.update(encrypted_data[32:data_len]) + - decryptor.finalize()) ->>>>>>> 83899f8 (fomatted code) unpadder = padding.PKCS7(algorithms.AES128.block_size).unpadder() decrypted_data = unpadder.update( decrypted_padded_data) + unpadder.finalize() @@ -345,17 +301,8 @@ class _MIoTLanDevice: timeout_ms=5000) self.subscribed = False self._manager.broadcast_device_state( -<<<<<<< HEAD did=self.did, state={ 'online': self._online, 'push_available': self.subscribed}) -======= - did=self.did, - state={ - "online": self._online, - "push_available": self.subscribed - }, - ) ->>>>>>> 83899f8 (fomatted code) def on_delete(self) -> None: if self._ka_timer: @@ -367,21 +314,15 @@ class _MIoTLanDevice: _LOGGER.debug('miot lan device delete, %s', self.did) def update_info(self, info: dict) -> None: -<<<<<<< HEAD if ( 'token' in info and len(info['token']) == 32 and info['token'].upper() != self.token.hex().upper() ): -======= - if ("token" in info and len(info["token"]) == 32 and - info["token"].upper() != self.token.hex().upper()): ->>>>>>> 83899f8 (fomatted code) # Update token self.token = bytes.fromhex(info['token']) aes_key: bytes = self.__md5(self.token) aex_iv: bytes = self.__md5(aes_key + self.token) -<<<<<<< HEAD self.cipher = Cipher( algorithms.AES128(aes_key), modes.CBC(aex_iv), default_backend()) @@ -394,21 +335,10 @@ class _MIoTLanDevice: or msg['result']['code'] != 0 ): _LOGGER.error('subscribe device error, %s, %s', self.did, msg) -======= - self.cipher = Cipher(algorithms.AES128(aes_key), modes.CBC(aex_iv), - default_backend()) - _LOGGER.debug("update token, %s", self.did) - - def __subscribe_handler(self, msg: dict, sub_ts: int) -> None: - if ("result" not in msg or "code" not in msg["result"] or - msg["result"]["code"] != 0): - _LOGGER.error("subscribe device error, %s, %s", self.did, msg) ->>>>>>> 83899f8 (fomatted code) return self.subscribed = True self.sub_ts = sub_ts self._manager.broadcast_device_state( -<<<<<<< HEAD did=self.did, state={ 'online': self._online, 'push_available': self.subscribed}) _LOGGER.info('subscribe success, %s, %s', self._if_name, self.did) @@ -420,20 +350,6 @@ class _MIoTLanDevice: or msg['result']['code'] != 0 ): _LOGGER.error('unsubscribe device error, %s, %s', self.did, msg) -======= - did=self.did, - state={ - "online": self._online, - "push_available": self.subscribed - }, - ) - _LOGGER.info("subscribe success, %s, %s", self._if_name, self.did) - - def __unsubscribe_handler(self, msg: dict, ctx: Any) -> None: - if ("result" not in msg or "code" not in msg["result"] or - msg["result"]["code"] != 0): - _LOGGER.error("unsubscribe device error, %s, %s", self.did, msg) ->>>>>>> 83899f8 (fomatted code) return _LOGGER.info('unsubscribe success, %s, %s', self._if_name, self.did) @@ -451,7 +367,6 @@ class _MIoTLanDevice: self._ka_internal = self.KA_INTERVAL_MIN self.__change_online(True) self._ka_timer = self._manager.internal_loop.call_later( -<<<<<<< HEAD self.__get_next_ka_timeout(), self.__update_keep_alive, _MIoTLanDeviceState.PING1) case ( @@ -459,14 +374,6 @@ class _MIoTLanDevice: | _MIoTLanDeviceState.PING2 | _MIoTLanDeviceState.PING3 ): -======= - self.__get_next_ka_timeout(), - self.__update_keep_alive, - _MIoTLanDeviceState.PING1, - ) - case (_MIoTLanDeviceState.PING1 | _MIoTLanDeviceState.PING2 | - _MIoTLanDeviceState.PING3): ->>>>>>> 83899f8 (fomatted code) # Set the timer first to avoid Any early returns self._ka_timer = self._manager.internal_loop.call_later( self.FAST_PING_INTERVAL, self.__update_keep_alive, @@ -503,7 +410,6 @@ class _MIoTLanDevice: if not online: self.online = False else: -<<<<<<< HEAD if ( len(self._online_offline_history) < self.NETWORK_UNSTABLE_CNT_TH or ( @@ -517,18 +423,6 @@ class _MIoTLanDevice: self._manager.internal_loop.call_later( self.NETWORK_UNSTABLE_RESUME_TH, self.__online_resume_handler)) -======= - if len(self._online_offline_history - ) < self.NETWORK_UNSTABLE_CNT_TH or ( - ts_now - self._online_offline_history[0]["ts"] - > self.NETWORK_UNSTABLE_TIME_TH): - self.online = True - else: - _LOGGER.info("unstable device detected, %s", self.did) - self._online_offline_timer = self._manager.internal_loop.call_later( - self.NETWORK_UNSTABLE_RESUME_TH, - self.__online_resume_handler) ->>>>>>> 83899f8 (fomatted code) def __online_resume_handler(self) -> None: _LOGGER.info('unstable resume threshold past, %s', self.did) @@ -607,7 +501,6 @@ class MIoTLan: self._net_ifs = set(net_ifs) self._network = network self._network.sub_network_info( -<<<<<<< HEAD key='miot_lan', handler=self.__on_network_info_change_external_async) self._mips_service = mips_service @@ -624,23 +517,6 @@ class MIoTLan: b'!1\x00\x20\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFMDID') probe_bytes[20:28] = struct.pack('>Q', int(self._virtual_did)) probe_bytes[28:32] = b'\x00\x00\x00\x00' -======= - key="miot_lan", - handler=self.__on_network_info_change_external_async) - self._mips_service = mips_service - self._mips_service.sub_service_change( - key="miot_lan", group_id="*", handler=self.__on_mips_service_change) - self._enable_subscribe = enable_subscribe - self._virtual_did = (str(virtual_did) if - (virtual_did is not None) else str( - secrets.randbits(64))) - # Init socket probe message - probe_bytes = bytearray(self.OT_PROBE_LEN) - probe_bytes[:20] = ( - b"!1\x00\x20\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffMDID") - probe_bytes[20:28] = struct.pack(">Q", int(self._virtual_did)) - probe_bytes[28:32] = b"\x00\x00\x00\x00" ->>>>>>> 83899f8 (fomatted code) self._probe_msg = bytes(probe_bytes) self._read_buffer = bytearray(self.OT_MSG_LEN) self._write_buffer = bytearray(self.OT_MSG_LEN) @@ -663,7 +539,6 @@ class MIoTLan: self._init_lock = asyncio.Lock() self._init_done = False -<<<<<<< HEAD if ( len(self._mips_service.get_services()) == 0 and len(self._net_ifs) > 0 @@ -678,18 +553,6 @@ class MIoTLan: raise MIoTLanError( 'MIoT lan is not ready', MIoTErrorCode.CODE_LAN_UNAVAILABLE) -======= - if len(self._mips_service.get_services()) == 0 and len( - self._net_ifs) > 0: - _LOGGER.info("no central hub gateway service, init miot lan") - self._main_loop.call_later( - 0, lambda: self._main_loop.create_task(self.init_async())) - - def __assert_service_ready(self) -> None: - if not self._init_done: - raise MIoTLanError("MIoT lan is not ready", - MIoTErrorCode.CODE_LAN_UNAVAILABLE) ->>>>>>> 83899f8 (fomatted code) @property def virtual_did(self) -> str: @@ -742,23 +605,14 @@ class MIoTLan: self._init_done = True for handler in list(self._lan_state_sub_map.values()): self._main_loop.create_task(handler(True)) -<<<<<<< HEAD _LOGGER.info( 'miot lan init, %s ,%s', self._net_ifs, self._available_net_ifs) -======= - _LOGGER.info("miot lan init, %s ,%s", self._net_ifs, - self._available_net_ifs) ->>>>>>> 83899f8 (fomatted code) def __internal_loop_thread(self) -> None: _LOGGER.info('miot lan thread start') self.__init_socket() self._scan_timer = self._internal_loop.call_later( -<<<<<<< HEAD int(3*random.random()), self.__scan_devices) -======= - int(3 * random.random()), self.__scan_devices) ->>>>>>> 83899f8 (fomatted code) self._internal_loop.run_forever() _LOGGER.info('miot lan thread exit') @@ -828,11 +682,7 @@ class MIoTLan: return self._internal_loop.call_soon_threadsafe( self.__update_subscribe_option, -<<<<<<< HEAD {'enable_subscribe': enable_subscribe}) -======= - {"enable_subscribe": enable_subscribe}) ->>>>>>> 83899f8 (fomatted code) def update_devices(self, devices: dict[str, dict]) -> bool: _LOGGER.info('update devices, %s', devices) @@ -850,14 +700,9 @@ class MIoTLan: self.__delete_devices, devices) return True -<<<<<<< HEAD def sub_lan_state( self, key: str, handler: Callable[[bool], Coroutine] ) -> None: -======= - def sub_lan_state(self, key: str, handler: Callable[[bool], - Coroutine]) -> None: ->>>>>>> 83899f8 (fomatted code) self._lan_state_sub_map[key] = handler def unsub_lan_state(self, key: str) -> None: @@ -872,15 +717,8 @@ class MIoTLan: return False self._internal_loop.call_soon_threadsafe( self.__sub_device_state, -<<<<<<< HEAD _MIoTLanSubDeviceData( key=key, handler=handler, handler_ctx=handler_ctx)) -======= - _MIoTLanSubDeviceData(key=key, - handler=handler, - handler_ctx=handler_ctx), - ) ->>>>>>> 83899f8 (fomatted code) return True @final @@ -909,7 +747,6 @@ class MIoTLan: f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') self._internal_loop.call_soon_threadsafe( self.__sub_broadcast, -<<<<<<< HEAD _MIoTLanRegisterBroadcastData( key=key, handler=handler, handler_ctx=handler_ctx)) return True @@ -921,19 +758,6 @@ class MIoTLan: siid: Optional[int] = None, piid: Optional[int] = None ) -> bool: -======= - _MIoTLanRegisterBroadcastData(key=key, - handler=handler, - handler_ctx=handler_ctx), - ) - return True - - @final - def unsub_prop(self, - did: str, - siid: Optional[int] = None, - piid: Optional[int] = None) -> bool: ->>>>>>> 83899f8 (fomatted code) if not self._init_done: return False if not self._enable_subscribe: @@ -942,12 +766,8 @@ class MIoTLan: f'{did}/p/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') self._internal_loop.call_soon_threadsafe( -<<<<<<< HEAD self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) -======= - self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) ->>>>>>> 83899f8 (fomatted code) return True @final @@ -968,7 +788,6 @@ class MIoTLan: f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') self._internal_loop.call_soon_threadsafe( self.__sub_broadcast, -<<<<<<< HEAD _MIoTLanRegisterBroadcastData( key=key, handler=handler, handler_ctx=handler_ctx)) return True @@ -980,19 +799,6 @@ class MIoTLan: siid: Optional[int] = None, eiid: Optional[int] = None ) -> bool: -======= - _MIoTLanRegisterBroadcastData(key=key, - handler=handler, - handler_ctx=handler_ctx), - ) - return True - - @final - def unsub_event(self, - did: str, - siid: Optional[int] = None, - eiid: Optional[int] = None) -> bool: ->>>>>>> 83899f8 (fomatted code) if not self._init_done: return False if not self._enable_subscribe: @@ -1001,12 +807,8 @@ class MIoTLan: f'{did}/e/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') self._internal_loop.call_soon_threadsafe( -<<<<<<< HEAD self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) -======= - self.__unsub_broadcast, _MIoTLanUnregisterBroadcastData(key=key)) ->>>>>>> 83899f8 (fomatted code) return True @final @@ -1017,7 +819,6 @@ class MIoTLan: timeout_ms: int = 10000) -> Any: self.__assert_service_ready() result_obj = await self.__call_api_async( -<<<<<<< HEAD did=did, msg={ 'method': 'get_properties', 'params': [{'did': did, 'siid': siid, 'piid': piid}] @@ -1054,71 +855,14 @@ class MIoTLan: ): return result_obj['result'][0] if 'code' in result_obj: -======= - did=did, - msg={ - "method": "get_properties", - "params": [{ - "did": did, - "siid": siid, - "piid": piid - }], - }, - timeout_ms=timeout_ms, - ) - - if (result_obj and "result" in result_obj and - len(result_obj["result"]) == 1 and - "did" in result_obj["result"][0] and - result_obj["result"][0]["did"] == did): - return result_obj["result"][0].get("value", None) - return None - - @final - async def set_prop_async(self, - did: str, - siid: int, - piid: int, - value: Any, - timeout_ms: int = 10000) -> dict: - self.__assert_service_ready() - result_obj = await self.__call_api_async( - did=did, - msg={ - "method": - "set_properties", - "params": [{ - "did": did, - "siid": siid, - "piid": piid, - "value": value - }], - }, - timeout_ms=timeout_ms, - ) - if result_obj: - if ("result" in result_obj and len(result_obj["result"]) == 1 and - "did" in result_obj["result"][0] and - result_obj["result"][0]["did"] == did and - "code" in result_obj["result"][0]): - return result_obj["result"][0] - if "code" in result_obj: ->>>>>>> 83899f8 (fomatted code) return result_obj raise MIoTError('Invalid result', MIoTErrorCode.CODE_INTERNAL_ERROR) @final -<<<<<<< HEAD async def set_props_async( self,did: str,props_list: List[Dict[str, Any]], timeout_ms: int = 10000) -> dict: # props_list = [{'did': did, 'siid': siid, 'piid': piid, 'value': value}......] -======= - async def set_props_async(self, - did: str, - props_list: List[Dict[str, Any]], - timeout_ms: int = 10000) -> dict: ->>>>>>> 83899f8 (fomatted code) self.__assert_service_ready() result_obj = await self.__call_api_async( did=did, msg={ @@ -1126,7 +870,6 @@ class MIoTLan: 'params': props_list, }, timeout_ms=timeout_ms) if result_obj: -<<<<<<< HEAD if ( 'result' in result_obj and len(result_obj['result']) == len(props_list) @@ -1150,41 +893,6 @@ class MIoTLan: 'params': { 'did': did, 'siid': siid, 'aiid': aiid, 'in': in_list} }, timeout_ms=timeout_ms) -======= - if ("result" in result_obj and - len(result_obj["result"]) == len(props_list) and - result_obj["result"][0].get("did") == did and - all("code" in item for item in result_obj["result"])): - return result_obj["result"] - if "error" in result_obj: - return result_obj["error"] - return { - "code": MIoTErrorCode.CODE_INTERNAL_ERROR.value, - "message": "Invalid result", - } - - @final - async def action_async(self, - did: str, - siid: int, - aiid: int, - in_list: list, - timeout_ms: int = 10000) -> dict: - self.__assert_service_ready() - result_obj = await self.__call_api_async( - did=did, - msg={ - "method": "action", - "params": { - "did": did, - "siid": siid, - "aiid": aiid, - "in": in_list - }, - }, - timeout_ms=timeout_ms, - ) ->>>>>>> 83899f8 (fomatted code) if result_obj: if 'result' in result_obj and 'code' in result_obj['result']: return result_obj['result'] @@ -1193,14 +901,9 @@ class MIoTLan: raise MIoTError('Invalid result', MIoTErrorCode.CODE_INTERNAL_ERROR) @final -<<<<<<< HEAD async def get_dev_list_async( self, timeout_ms: int = 10000 ) -> dict[str, dict]: -======= - async def get_dev_list_async(self, - timeout_ms: int = 10000) -> dict[str, dict]: ->>>>>>> 83899f8 (fomatted code) if not self._init_done: return {} @@ -1211,17 +914,10 @@ class MIoTLan: fut: asyncio.Future = self._main_loop.create_future() self._internal_loop.call_soon_threadsafe( self.__get_dev_list, -<<<<<<< HEAD _MIoTLanGetDevListData( handler=get_device_list_handler, handler_ctx=fut, timeout_ms=timeout_ms)) -======= - _MIoTLanGetDevListData(handler=get_device_list_handler, - handler_ctx=fut, - timeout_ms=timeout_ms), - ) ->>>>>>> 83899f8 (fomatted code) return await fut async def __call_api_async(self, @@ -1234,7 +930,6 @@ class MIoTLan: fut.set_result, msg) fut: asyncio.Future = self._main_loop.create_future() -<<<<<<< HEAD self._internal_loop.call_soon_threadsafe( self.__call_api, did, msg, call_api_handler, fut, timeout_ms) return await fut @@ -1246,17 +941,6 @@ class MIoTLan: ) -> None: _LOGGER.info( 'on network info change, status: %s, info: %s', status, info) -======= - self._internal_loop.call_soon_threadsafe(self.__call_api, did, msg, - call_api_handler, fut, - timeout_ms) - return await fut - - async def __on_network_info_change_external_async( - self, status: InterfaceStatus, info: NetworkInfo) -> None: - _LOGGER.info("on network info change, status: %s, info: %s", status, - info) ->>>>>>> 83899f8 (fomatted code) available_net_ifs = set() for if_name in list(self._network.network_info.keys()): available_net_ifs.add(if_name) @@ -1277,19 +961,11 @@ class MIoTLan: self.__on_network_info_change, _MIoTLanNetworkUpdateData(status=status, if_name=info.name)) -<<<<<<< HEAD async def __on_mips_service_change( self, group_id: str, state: MipsServiceState, data: dict ) -> None: _LOGGER.info( 'on mips service change, %s, %s, %s', group_id, state, data) -======= - async def __on_mips_service_change(self, group_id: str, - state: MipsServiceState, - data: dict) -> None: - _LOGGER.info("on mips service change, %s, %s, %s", group_id, state, - data) ->>>>>>> 83899f8 (fomatted code) if len(self._mips_service.get_services()) > 0: _LOGGER.info('find central service, deinit miot lan') await self.deinit_async() @@ -1302,16 +978,9 @@ class MIoTLan: def ping(self, if_name: Optional[str], target_ip: str) -> None: if not target_ip: return -<<<<<<< HEAD self.__sendto( if_name=if_name, data=self._probe_msg, address=target_ip, port=self.OT_PORT) -======= - self.__sendto(if_name=if_name, - data=self._probe_msg, - address=target_ip, - port=self.OT_PORT) ->>>>>>> 83899f8 (fomatted code) def send2device( self, did: str, @@ -1361,7 +1030,6 @@ class MIoTLan: def request_timeout_handler(req_data: _MIoTLanRequestData): self._pending_requests.pop(req_data.msg_id, None) if req_data and req_data.handler: -<<<<<<< HEAD req_data.handler({ 'code': MIoTErrorCode.CODE_TIMEOUT.value, 'error': 'timeout'}, @@ -1376,25 +1044,6 @@ class MIoTLan: if timeout_ms: timer = self._internal_loop.call_later( timeout_ms/1000, request_timeout_handler, request_data) -======= - req_data.handler( - { - "code": MIoTErrorCode.CODE_TIMEOUT.value, - "error": "timeout" - }, - req_data.handler_ctx, - ) - - timer: Optional[asyncio.TimerHandle] = None - request_data = _MIoTLanRequestData(msg_id=msg_id, - handler=handler, - handler_ctx=handler_ctx, - timeout=timer) - if timeout_ms: - timer = self._internal_loop.call_later(timeout_ms / 1000, - request_timeout_handler, - request_data) ->>>>>>> 83899f8 (fomatted code) request_data.timeout = timer self._pending_requests[msg_id] = request_data self.__sendto(if_name=if_name, data=msg, address=ip, port=self.OT_PORT) @@ -1424,34 +1073,16 @@ class MIoTLan: try: self.send2device( did=did, -<<<<<<< HEAD msg={'from': 'ha.xiaomi_home', **msg}, -======= - msg={ - "from": "ha.xiaomi_home", - **msg - }, ->>>>>>> 83899f8 (fomatted code) handler=handler, handler_ctx=handler_ctx, timeout_ms=timeout_ms) except Exception as err: # pylint: disable=broad-exception-caught -<<<<<<< HEAD _LOGGER.error('send2device error, %s', err) handler({ 'code': MIoTErrorCode.CODE_INTERNAL_ERROR.value, 'error': str(err)}, handler_ctx) -======= - _LOGGER.error("send2device error, %s", err) - handler( - { - "code": MIoTErrorCode.CODE_INTERNAL_ERROR.value, - "error": str(err) - }, - handler_ctx, - ) ->>>>>>> 83899f8 (fomatted code) def __sub_device_state(self, data: _MIoTLanSubDeviceData) -> None: self._device_state_sub_map[data.key] = data @@ -1471,7 +1102,6 @@ class MIoTLan: def __get_dev_list(self, data: _MIoTLanGetDevListData) -> None: dev_list = { device.did: { -<<<<<<< HEAD 'online': device.online, 'push_available': device.subscribed } @@ -1479,13 +1109,6 @@ class MIoTLan: if device.online} data.handler( dev_list, data.handler_ctx) -======= - "online": device.online, - "push_available": device.subscribed - } for device in self._lan_devices.values() if device.online - } - data.handler(dev_list, data.handler_ctx) ->>>>>>> 83899f8 (fomatted code) def __update_devices(self, devices: dict[str, dict]) -> None: for did, info in devices.items(): @@ -1498,14 +1121,9 @@ class MIoTLan: or info['model'] in self._profile_models): # Do not support the local control of # Profile device for the time being -<<<<<<< HEAD _LOGGER.info( 'model not support local ctrl, %s, %s', did, info.get('model')) -======= - _LOGGER.info("model not support local ctrl, %s, %s", did, - info.get("model")) ->>>>>>> 83899f8 (fomatted code) continue if did not in self._lan_devices: if 'token' not in info: @@ -1516,16 +1134,9 @@ class MIoTLan: _LOGGER.error( 'invalid device token, %s, %s', did, info) continue -<<<<<<< HEAD self._lan_devices[did] = _MIoTLanDevice( manager=self, did=did, token=info['token'], ip=info.get('ip', None)) -======= - self._lan_devices[did] = _MIoTLanDevice(manager=self, - did=did, - token=info["token"], - ip=info.get("ip", None)) ->>>>>>> 83899f8 (fomatted code) else: self._lan_devices[did].update_info(info) @@ -1596,7 +1207,6 @@ class MIoTLan: return # Create socket try: -<<<<<<< HEAD sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) @@ -1607,19 +1217,6 @@ class MIoTLan: sock.bind(('', self._local_port or 0)) self._internal_loop.add_reader( sock.fileno(), self.__socket_read_handler, (if_name, sock)) -======= - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.IPPROTO_UDP) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - # Set SO_BINDTODEVICE - sock.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, - if_name.encode()) - sock.bind(("", self._local_port or 0)) - self._internal_loop.add_reader(sock.fileno(), - self.__socket_read_handler, - (if_name, sock)) ->>>>>>> 83899f8 (fomatted code) self._broadcast_socks[if_name] = sock self._local_port = self._local_port or sock.getsockname()[1] _LOGGER.info( @@ -1642,14 +1239,8 @@ class MIoTLan: def __socket_read_handler(self, ctx: tuple[str, socket.socket]) -> None: try: -<<<<<<< HEAD data_len, addr = ctx[1].recvfrom_into( self._read_buffer, self.OT_MSG_LEN, socket.MSG_DONTWAIT) -======= - data_len, addr = ctx[1].recvfrom_into(self._read_buffer, - self.OT_MSG_LEN, - socket.MSG_DONTWAIT) ->>>>>>> 83899f8 (fomatted code) if data_len < 0: # Socket error _LOGGER.error('socket read error, %s, %s', ctx[0], data_len) @@ -1657,13 +1248,8 @@ class MIoTLan: if addr[1] != self.OT_PORT: # Not ot msg return -<<<<<<< HEAD self.__raw_message_handler( self._read_buffer[:data_len], data_len, addr[0], ctx[0]) -======= - self.__raw_message_handler(self._read_buffer[:data_len], data_len, - addr[0], ctx[0]) ->>>>>>> 83899f8 (fomatted code) except Exception as err: # pylint: disable=broad-exception-caught _LOGGER.error('socket read handler error, %s', err) @@ -1682,7 +1268,6 @@ class MIoTLan: if data_len == self.OT_PROBE_LEN or device.subscribed: device.keep_alive(ip=ip, if_name=if_name) # Manage device subscribe status -<<<<<<< HEAD if ( self._enable_subscribe and data_len == self.OT_PROBE_LEN @@ -1692,13 +1277,6 @@ class MIoTLan: device.supported_wildcard_sub = ( int(data[28]) == self.OT_SUPPORT_WILDCARD_SUB) sub_ts = struct.unpack('>I', data[20:24])[0] -======= - if (self._enable_subscribe and data_len == self.OT_PROBE_LEN and - data[16:20] == b"MSUB" and data[24:27] == b"PUB"): - device.supported_wildcard_sub = (int( - data[28]) == self.OT_SUPPORT_WILDCARD_SUB) - sub_ts = struct.unpack(">I", data[20:24])[0] ->>>>>>> 83899f8 (fomatted code) sub_type = int(data[27]) if (device.supported_wildcard_sub and sub_type in [0, 1, 4] and sub_ts != device.sub_ts): @@ -1718,19 +1296,13 @@ class MIoTLan: _LOGGER.warning('invalid message, no id, %s, %s', did, msg) return # Reply -<<<<<<< HEAD req: Optional[_MIoTLanRequestData] = ( self._pending_requests.pop(msg['id'], None)) -======= - req: Optional[_MIoTLanRequestData] = self._pending_requests.pop( - msg["id"], None) ->>>>>>> 83899f8 (fomatted code) if req: if req.timeout: req.timeout.cancel() req.timeout = None if req.handler is not None: -<<<<<<< HEAD self._main_loop.call_soon_threadsafe( req.handler, msg, req.handler_ctx) return @@ -1750,32 +1322,6 @@ class MIoTLan: if 'siid' not in param and 'piid' not in param: _LOGGER.debug( 'invalid message, no siid or piid, %s, %s', did, msg) -======= - self._main_loop.call_soon_threadsafe(req.handler, msg, - req.handler_ctx) - return - # Handle up link message - if "method" not in msg or "params" not in msg: - _LOGGER.debug("invalid message, no method or params, %s, %s", did, - msg) - return - # Filter dup message - if self.__filter_dup_message(did, msg["id"]): - self.send2device(did=did, - msg={ - "id": msg["id"], - "result": { - "code": 0 - } - }) - return - _LOGGER.debug("lan message, %s, %s", did, msg) - if msg["method"] == "properties_changed": - for param in msg["params"]: - if "siid" not in param and "piid" not in param: - _LOGGER.debug("invalid message, no siid or piid, %s, %s", - did, msg) ->>>>>>> 83899f8 (fomatted code) continue key = f'{did}/p/{param["siid"]}/{param["piid"]}' subs: list[_MIoTLanRegisterBroadcastData] = list( @@ -1783,7 +1329,6 @@ class MIoTLan: for sub in subs: self._main_loop.call_soon_threadsafe( sub.handler, param, sub.handler_ctx) -<<<<<<< HEAD elif ( msg['method'] == 'event_occured' and 'siid' in msg['params'] @@ -1795,16 +1340,6 @@ class MIoTLan: for sub in subs: self._main_loop.call_soon_threadsafe( sub.handler, msg['params'], sub.handler_ctx) -======= - elif (msg["method"] == "event_occured" and "siid" in msg["params"] and - "eiid" in msg["params"]): - key = f"{did}/e/{msg['params']['siid']}/{msg['params']['eiid']}" - subs: list[_MIoTLanRegisterBroadcastData] = list( - self._device_msg_matcher.iter_match(key)) - for sub in subs: - self._main_loop.call_soon_threadsafe(sub.handler, msg["params"], - sub.handler_ctx) ->>>>>>> 83899f8 (fomatted code) else: _LOGGER.debug( 'invalid message, unknown method, %s, %s', did, msg) @@ -1817,12 +1352,8 @@ class MIoTLan: if filter_id in self._reply_msg_buffer: return True self._reply_msg_buffer[filter_id] = self._internal_loop.call_later( -<<<<<<< HEAD 5, lambda filter_id: self._reply_msg_buffer.pop(filter_id, None), -======= - 5, lambda filter_id: self._reply_msg_buffer.pop(filter_id, None), ->>>>>>> 83899f8 (fomatted code) filter_id) return False @@ -1855,20 +1386,11 @@ class MIoTLan: scan_time = self.__get_next_scan_time() self._scan_timer = self._internal_loop.call_later( scan_time, self.__scan_devices) -<<<<<<< HEAD _LOGGER.debug('next scan time: %ss', scan_time) -======= - _LOGGER.debug("next scan time: %ss", scan_time) ->>>>>>> 83899f8 (fomatted code) def __get_next_scan_time(self) -> float: if not self._last_scan_interval: self._last_scan_interval = self.OT_PROBE_INTERVAL_MIN -<<<<<<< HEAD self._last_scan_interval = min( self._last_scan_interval*2, self.OT_PROBE_INTERVAL_MAX) -======= - self._last_scan_interval = min(self._last_scan_interval * 2, - self.OT_PROBE_INTERVAL_MAX) ->>>>>>> 83899f8 (fomatted code) return self._last_scan_interval diff --git a/custom_components/xiaomi_home/miot/miot_mips.py b/custom_components/xiaomi_home/miot/miot_mips.py index 5c39089..fa9da7a 100644 --- a/custom_components/xiaomi_home/miot/miot_mips.py +++ b/custom_components/xiaomi_home/miot/miot_mips.py @@ -101,7 +101,6 @@ class _MipsMessage: data_start = 0 data_end = 0 while data_start < data_len: -<<<<<<< HEAD data_end = data_start+5 unpack_len, unpack_type = struct.unpack( '>>>>>> 83899f8 (fomatted code) case _MipsMsgTypeOptions.PAYLOAD.value: mips_msg.payload = str(unpack_data.strip(b'\x00'), 'utf-8') case _MipsMsgTypeOptions.FROM.value: @@ -401,13 +386,8 @@ class _MipsClient(ABC): def update_mqtt_password(self, password: str) -> None: self._password = password if self._mqtt: -<<<<<<< HEAD self._mqtt.username_pw_set( username=self._username, password=self._password) -======= - self._mqtt.username_pw_set(username=self._username, - password=self._password) ->>>>>>> 83899f8 (fomatted code) def log_debug(self, msg, *args, **kwargs) -> None: if self._logger: @@ -424,14 +404,9 @@ class _MipsClient(ABC): def enable_logger(self, logger: Optional[logging.Logger] = None) -> None: self._logger = logger -<<<<<<< HEAD def enable_mqtt_logger( self, logger: Optional[logging.Logger] = None ) -> None: -======= - def enable_mqtt_logger(self, - logger: Optional[logging.Logger] = None) -> None: ->>>>>>> 83899f8 (fomatted code) self._mqtt_logger = logger if self._mqtt: if logger: @@ -472,7 +447,6 @@ class _MipsClient(ABC): handler: Callable[[dict, Any], None], siid: Optional[int] = None, piid: Optional[int] = None, -<<<<<<< HEAD handler_ctx: Any = None ) -> bool: ... @@ -483,18 +457,6 @@ class _MipsClient(ABC): siid: Optional[int] = None, piid: Optional[int] = None ) -> bool: ... -======= - handler_ctx: Any = None, - ) -> bool: - ... - - @abstractmethod - def unsub_prop(self, - did: str, - siid: Optional[int] = None, - piid: Optional[int] = None) -> bool: - ... ->>>>>>> 83899f8 (fomatted code) @abstractmethod def sub_event( @@ -503,7 +465,6 @@ class _MipsClient(ABC): handler: Callable[[dict, Any], None], siid: Optional[int] = None, eiid: Optional[int] = None, -<<<<<<< HEAD handler_ctx: Any = None ) -> bool: ... @@ -521,24 +482,6 @@ class _MipsClient(ABC): payload: Optional[str] = None, timeout_ms: int = 10000 ) -> dict[str, dict]: ... -======= - handler_ctx: Any = None, - ) -> bool: - ... - - @abstractmethod - def unsub_event(self, - did: str, - siid: Optional[int] = None, - eiid: Optional[int] = None) -> bool: - ... - - @abstractmethod - async def get_dev_list_async(self, - payload: Optional[str] = None, - timeout_ms: int = 10000) -> dict[str, dict]: - ... ->>>>>>> 83899f8 (fomatted code) @abstractmethod async def get_prop_async(self, @@ -549,7 +492,6 @@ class _MipsClient(ABC): ... @abstractmethod -<<<<<<< HEAD async def set_prop_async( self, did: str, siid: int, piid: int, value: Any, timeout_ms: int = 10000 @@ -560,24 +502,6 @@ class _MipsClient(ABC): self, did: str, siid: int, aiid: int, in_list: list, timeout_ms: int = 10000 ) -> dict: ... -======= - async def set_prop_async(self, - did: str, - siid: int, - piid: int, - value: Any, - timeout_ms: int = 10000) -> dict: - ... - - @abstractmethod - async def action_async(self, - did: str, - siid: int, - aiid: int, - in_list: list, - timeout_ms: int = 10000) -> dict: - ... ->>>>>>> 83899f8 (fomatted code) @abstractmethod def _on_mips_message(self, topic: str, payload: bytes) -> None: @@ -600,24 +524,12 @@ class _MipsClient(ABC): if not self._mqtt or not self._mqtt.is_connected(): self.log_error(f'mips sub when not connected, {topic}') return -<<<<<<< HEAD if topic not in self._mips_sub_pending_map: self._mips_sub_pending_map[topic] = 0 if not self._mips_sub_pending_timer: self._mips_sub_pending_timer = self._internal_loop.call_later( 0.01, self.__mips_sub_internal_pending_handler, topic) -======= - try: - if topic not in self._mips_sub_pending_map: - self._mips_sub_pending_map[topic] = 0 - if not self._mips_sub_pending_timer: - self._mips_sub_pending_timer = self._internal_loop.call_later( - 0.01, self.__mips_sub_internal_pending_handler, topic) - except Exception as err: # pylint: disable=broad-exception-caught - # Catch all exception - self.log_error(f"mips sub internal error, {topic}. {err}") ->>>>>>> 83899f8 (fomatted code) @final def _mips_unsub_internal(self, topic: str) -> None: @@ -630,21 +542,12 @@ class _MipsClient(ABC): return try: result, mid = self._mqtt.unsubscribe(topic=topic) -<<<<<<< HEAD if (result == MQTT_ERR_SUCCESS) or (result == MQTT_ERR_NO_CONN): self.log_debug( f'mips unsub internal success, {result}, {mid}, {topic}') return self.log_error( f'mips unsub internal error, {result}, {mid}, {topic}') -======= - if result == MQTT_ERR_SUCCESS: - self.log_debug( - f"mips unsub internal success, {result}, {mid}, {topic}") - return - self.log_error( - f"mips unsub internal error, {result}, {mid}, {topic}") ->>>>>>> 83899f8 (fomatted code) except Exception as err: # pylint: disable=broad-exception-caught # Catch all exception self.log_error(f'mips unsub internal error, {topic}, {err}') @@ -662,14 +565,8 @@ class _MipsClient(ABC): if not self._mqtt or not self._mqtt.is_connected(): return False try: -<<<<<<< HEAD handle = self._mqtt.publish( topic=topic, payload=payload, qos=self.MIPS_QOS) -======= - handle = self._mqtt.publish(topic=topic, - payload=payload, - qos=self.MIPS_QOS) ->>>>>>> 83899f8 (fomatted code) # self.log_debug(f'_mips_publish_internal, {topic}, {payload}') if wait_for_publish is True: handle.wait_for_publish(timeout_ms/1000.0) @@ -712,13 +609,8 @@ class _MipsClient(ABC): if self._mqtt: self._mqtt.loop_misc() if self._mqtt and self._mqtt.want_write(): -<<<<<<< HEAD self._internal_loop.add_writer( self._mqtt_fd, self.__mqtt_write_handler) -======= - self._internal_loop.add_writer(self._mqtt_fd, - self.__mqtt_write_handler) ->>>>>>> 83899f8 (fomatted code) except Exception as err: # pylint: disable=broad-exception-caught # Catch all exception self.log_error(f'__mqtt_loop_handler, {err}') @@ -732,7 +624,6 @@ class _MipsClient(ABC): self._mqtt.enable_logger(logger=self._mqtt_logger) # Set mqtt config if self._username: -<<<<<<< HEAD self._mqtt.username_pw_set( username=self._username, password=self._password) if ( @@ -740,11 +631,6 @@ class _MipsClient(ABC): and self._cert_file and self._key_file ): -======= - self._mqtt.username_pw_set(username=self._username, - password=self._password) - if self._ca_file and self._cert_file and self._key_file: ->>>>>>> 83899f8 (fomatted code) self._mqtt.tls_set( tls_version=ssl.PROTOCOL_TLS_CLIENT, ca_certs=self._ca_file, @@ -780,12 +666,8 @@ class _MipsClient(ABC): if item.handler is None: continue self.main_loop.call_soon_threadsafe( -<<<<<<< HEAD self.main_loop.create_task, item.handler(item.key, True)) -======= - self.main_loop.create_task, item.handler(item.key, True)) ->>>>>>> 83899f8 (fomatted code) # Resolve future self.main_loop.call_soon_threadsafe( self._event_connect.set) @@ -799,13 +681,8 @@ class _MipsClient(ABC): def __on_disconnect(self, client, user_data, rc, props) -> None: if self._mqtt_state: -<<<<<<< HEAD (self.log_info if rc == 0 else self.log_error)( f'mips disconnect, {rc}, {props}') -======= - (self.log_info - if rc == 0 else self.log_error)(f"mips disconnect, {rc}, {props}") ->>>>>>> 83899f8 (fomatted code) self._mqtt_state = False if self._mqtt_timer: self._mqtt_timer.cancel() @@ -838,27 +715,18 @@ class _MipsClient(ABC): self.main_loop.call_soon_threadsafe( self._event_connect.clear) -<<<<<<< HEAD def __on_message( self, client: Client, user_data: Any, msg: MQTTMessage ) -> None: -======= - def __on_message(self, client: Client, user_data: Any, - msg: MQTTMessage) -> None: ->>>>>>> 83899f8 (fomatted code) self._on_mips_message(topic=msg.topic, payload=msg.payload) def __mips_sub_internal_pending_handler(self, ctx: Any) -> None: if not self._mqtt or not self._mqtt.is_connected(): _LOGGER.error( -<<<<<<< HEAD 'mips sub internal pending, but mqtt is None or disconnected') -======= - "mips sub internal pending, but mqtt is None or disconnected") ->>>>>>> 83899f8 (fomatted code) return subbed_count = 1 for topic in list(self._mips_sub_pending_map.keys()): @@ -882,11 +750,7 @@ class _MipsClient(ABC): self.log_error(f'mips sub internal error, {topic}. {err}') self._mips_sub_pending_map[topic] = count+1 self.log_error( -<<<<<<< HEAD f'retry mips sub internal, {count}, {topic}, {result}, {mid}') -======= - f"retry mips sub internal, {count}, {topic}, {result}, {mid}") ->>>>>>> 83899f8 (fomatted code) if len(self._mips_sub_pending_map): self._mips_sub_pending_timer = self._internal_loop.call_later( @@ -923,7 +787,6 @@ class _MipsClient(ABC): socket = self._mqtt.socket() if socket is None: self.log_error( -<<<<<<< HEAD '__mips_connect, connect success, but socket is None') self.__mips_try_reconnect() return @@ -934,18 +797,6 @@ class _MipsClient(ABC): if self._mqtt.want_write(): self._internal_loop.add_writer( self._mqtt_fd, self.__mqtt_write_handler) -======= - "__mips_connect, connect success, but socket is None") - self.__mips_try_reconnect() - return - self._mqtt_fd = socket.fileno() - self.log_debug(f"__mips_connect, _mqtt_fd, {self._mqtt_fd}") - self._internal_loop.add_reader(self._mqtt_fd, - self.__mqtt_read_handler) - if self._mqtt.want_write(): - self._internal_loop.add_writer(self._mqtt_fd, - self.__mqtt_write_handler) ->>>>>>> 83899f8 (fomatted code) self._mqtt_timer = self._internal_loop.call_later( self.MQTT_INTERVAL_S, self.__mqtt_timer_handler) else: @@ -997,11 +848,7 @@ class _MipsClient(ABC): self._mips_reconnect_interval = self.MIPS_RECONNECT_INTERVAL_MIN else: self._mips_reconnect_interval = min( -<<<<<<< HEAD self._mips_reconnect_interval*2, -======= - self._mips_reconnect_interval * 2, ->>>>>>> 83899f8 (fomatted code) self.MIPS_RECONNECT_INTERVAL_MAX) return self._mips_reconnect_interval @@ -1050,13 +897,8 @@ class MipsCloudClient(_MipsClient): raise MIoTMipsError('invalid params') topic: str = ( -<<<<<<< HEAD f'device/{did}/up/properties_changed/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') -======= - f"device/{did}/up/properties_changed/" - f"{'#' if siid is None or piid is None else f'{siid}/{piid}'}") ->>>>>>> 83899f8 (fomatted code) def on_prop_msg(topic: str, payload: str, ctx: Any) -> None: try: @@ -1065,7 +907,6 @@ class MipsCloudClient(_MipsClient): self.log_error( f'on_prop_msg, invalid msg, {topic}, {payload}') return -<<<<<<< HEAD if ( not isinstance(msg.get('params', None), dict) or 'siid' not in msg['params'] @@ -1088,37 +929,11 @@ class MipsCloudClient(_MipsClient): siid: Optional[int] = None, piid: Optional[int] = None ) -> bool: -======= - if (not isinstance(msg.get("params", None), dict) or - "siid" not in msg["params"] or - "piid" not in msg["params"] or - "value" not in msg["params"]): - self.log_error(f"on_prop_msg, invalid msg, {topic}, {payload}") - return - if handler: - self.log_debug("on properties_changed, %s", payload) - handler(msg["params"], ctx) - - return self.__reg_broadcast_external(topic=topic, - handler=on_prop_msg, - handler_ctx=handler_ctx) - - @final - def unsub_prop(self, - did: str, - siid: Optional[int] = None, - piid: Optional[int] = None) -> bool: ->>>>>>> 83899f8 (fomatted code) if not isinstance(did, str): raise MIoTMipsError('invalid params') topic: str = ( -<<<<<<< HEAD f'device/{did}/up/properties_changed/' f'{"#" if siid is None or piid is None else f"{siid}/{piid}"}') -======= - f"device/{did}/up/properties_changed/" - f"{'#' if siid is None or piid is None else f'{siid}/{piid}'}") ->>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -1134,13 +949,8 @@ class MipsCloudClient(_MipsClient): raise MIoTMipsError('invalid params') # Spelling error: event_occured topic: str = ( -<<<<<<< HEAD f'device/{did}/up/event_occured/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') -======= - f"device/{did}/up/event_occured/" - f"{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}") ->>>>>>> 83899f8 (fomatted code) def on_event_msg(topic: str, payload: str, ctx: Any) -> None: try: @@ -1149,7 +959,6 @@ class MipsCloudClient(_MipsClient): self.log_error( f'on_event_msg, invalid msg, {topic}, {payload}') return -<<<<<<< HEAD if ( not isinstance(msg.get('params', None), dict) or 'siid' not in msg['params'] @@ -1173,39 +982,12 @@ class MipsCloudClient(_MipsClient): siid: Optional[int] = None, eiid: Optional[int] = None ) -> bool: -======= - if (not isinstance(msg.get("params", None), dict) or - "siid" not in msg["params"] or - "eiid" not in msg["params"] or - "arguments" not in msg["params"]): - self.log_error(f"on_event_msg, invalid msg, {topic}, {payload}") - return - if handler: - self.log_debug("on on_event_msg, %s", payload) - msg["params"]["from"] = "cloud" - handler(msg["params"], ctx) - - return self.__reg_broadcast_external(topic=topic, - handler=on_event_msg, - handler_ctx=handler_ctx) - - @final - def unsub_event(self, - did: str, - siid: Optional[int] = None, - eiid: Optional[int] = None) -> bool: ->>>>>>> 83899f8 (fomatted code) if not isinstance(did, str): raise MIoTMipsError('invalid params') # Spelling error: event_occured topic: str = ( -<<<<<<< HEAD f'device/{did}/up/event_occured/' f'{"#" if siid is None or eiid is None else f"{siid}/{eiid}"}') -======= - f"device/{did}/up/event_occured/" - f"{'#' if siid is None or eiid is None else f'{siid}/{eiid}'}") ->>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -1225,20 +1007,13 @@ class MipsCloudClient(_MipsClient): if msg is None or 'device_id' not in msg or 'event' not in msg: self.log_error(f'on_state_msg, recv unknown msg, {payload}') return -<<<<<<< HEAD if msg['device_id'] != did: self.log_error( f'on_state_msg, err msg, {did}!={msg["device_id"]}') -======= - if msg["device_id"] != did: - self.log_error( - f"on_state_msg, err msg, {did}!={msg['device_id']}") ->>>>>>> 83899f8 (fomatted code) return if handler: self.log_debug('cloud, device state changed, %s', payload) handler( -<<<<<<< HEAD did, MIoTDeviceState.ONLINE if msg['event'] == 'online' else MIoTDeviceState.OFFLINE, ctx) @@ -1250,17 +1025,6 @@ class MipsCloudClient(_MipsClient): return True return self.__reg_broadcast_external( topic=topic, handler=on_state_msg, handler_ctx=handler_ctx) -======= - did, - MIoTDeviceState.ONLINE - if msg["event"] == "online" else MIoTDeviceState.OFFLINE, - ctx, - ) - - return self.__reg_broadcast_external(topic=topic, - handler=on_state_msg, - handler_ctx=handler_ctx) ->>>>>>> 83899f8 (fomatted code) @final def unsub_device_state(self, did: str) -> bool: @@ -1269,7 +1033,6 @@ class MipsCloudClient(_MipsClient): topic: str = f'device/{did}/state/#' return self.__unreg_broadcast_external(topic=topic) -<<<<<<< HEAD async def get_dev_list_async( self, payload: Optional[str] = None, timeout_ms: int = 10000 ) -> dict[str, dict]: @@ -1291,47 +1054,13 @@ class MipsCloudClient(_MipsClient): timeout_ms: int = 10000 ) -> dict: raise NotImplementedError('please call in http client') -======= - async def get_dev_list_async(self, - payload: Optional[str] = None, - timeout_ms: int = 10000) -> dict[str, dict]: - raise NotImplementedError("please call in http client") - - async def get_prop_async(self, - did: str, - siid: int, - piid: int, - timeout_ms: int = 10000) -> Any: - raise NotImplementedError("please call in http client") - - async def set_prop_async(self, - did: str, - siid: int, - piid: int, - value: Any, - timeout_ms: int = 10000) -> dict: - raise NotImplementedError("please call in http client") - - async def action_async(self, - did: str, - siid: int, - aiid: int, - in_list: list, - timeout_ms: int = 10000) -> dict: - raise NotImplementedError("please call in http client") ->>>>>>> 83899f8 (fomatted code) def __reg_broadcast_external( self, topic: str, handler: Callable[[str, str, Any], None], handler_ctx: Any = None ) -> bool: -<<<<<<< HEAD self._internal_loop.call_soon_threadsafe( self.__reg_broadcast, topic, handler, handler_ctx) -======= - self._internal_loop.call_soon_threadsafe(self.__reg_broadcast, topic, - handler, handler_ctx) ->>>>>>> 83899f8 (fomatted code) return True def __unreg_broadcast_external(self, topic: str) -> bool: @@ -1344,15 +1073,9 @@ class MipsCloudClient(_MipsClient): handler_ctx: Any = None ) -> None: if not self._msg_matcher.get(topic=topic): -<<<<<<< HEAD sub_bc: _MipsBroadcast = _MipsBroadcast( topic=topic, handler=handler, handler_ctx=handler_ctx) -======= - sub_bc: _MipsBroadcast = _MipsBroadcast(topic=topic, - handler=handler, - handler_ctx=handler_ctx) ->>>>>>> 83899f8 (fomatted code) self._msg_matcher[topic] = sub_bc self._mips_sub_internal(topic=topic) else: @@ -1389,13 +1112,8 @@ class MipsCloudClient(_MipsClient): if item.handler is None: continue # NOTICE: call threadsafe -<<<<<<< HEAD self.main_loop.call_soon_threadsafe( item.handler, topic, payload_str, item.handler_ctx) -======= - self.main_loop.call_soon_threadsafe(item.handler, topic, - payload_str, item.handler_ctx) ->>>>>>> 83899f8 (fomatted code) class MipsLocalClient(_MipsClient): @@ -1477,7 +1195,6 @@ class MipsLocalClient(_MipsClient): handler_ctx: Any = None ) -> bool: topic: str = ( -<<<<<<< HEAD f'appMsg/notify/iot/{did}/property/' f'{"#" if siid is None or piid is None else f"{siid}.{piid}"}') @@ -1491,21 +1208,10 @@ class MipsLocalClient(_MipsClient): or 'value' not in msg ): self.log_info('unknown prop msg, %s', payload) -======= - f"appMsg/notify/iot/{did}/property/" - f"{'#' if siid is None or piid is None else f'{siid}.{piid}'}") - - def on_prop_msg(topic: str, payload: str, ctx: Any): - msg: dict = json.loads(payload) - if (msg is None or "did" not in msg or "siid" not in msg or - "piid" not in msg or "value" not in msg): - # self.log_error(f'on_prop_msg, recv unknown msg, {payload}') ->>>>>>> 83899f8 (fomatted code) return if handler: self.log_debug('local, on properties_changed, %s', payload) handler(msg, ctx) -<<<<<<< HEAD return self.__reg_broadcast_external( topic=topic, handler=on_prop_msg, handler_ctx=handler_ctx) @@ -1519,21 +1225,6 @@ class MipsLocalClient(_MipsClient): topic: str = ( f'appMsg/notify/iot/{did}/property/' f'{"#" if siid is None or piid is None else f"{siid}.{piid}"}') -======= - - return self.__reg_broadcast_external(topic=topic, - handler=on_prop_msg, - handler_ctx=handler_ctx) - - @final - def unsub_prop(self, - did: str, - siid: Optional[int] = None, - piid: Optional[int] = None) -> bool: - topic: str = ( - f"appMsg/notify/iot/{did}/property/" - f"{'#' if siid is None or piid is None else f'{siid}.{piid}'}") ->>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -1546,7 +1237,6 @@ class MipsLocalClient(_MipsClient): handler_ctx: Any = None ) -> bool: topic: str = ( -<<<<<<< HEAD f'appMsg/notify/iot/{did}/event/' f'{"#" if siid is None or eiid is None else f"{siid}.{eiid}"}') @@ -1560,18 +1250,6 @@ class MipsLocalClient(_MipsClient): # or 'arguments' not in msg ): self.log_info('unknown event msg, %s', payload) -======= - f"appMsg/notify/iot/{did}/event/" - f"{'#' if siid is None or eiid is None else f'{siid}.{eiid}'}") - - def on_event_msg(topic: str, payload: str, ctx: Any): - msg: dict = json.loads(payload) - if (msg is None or "did" not in msg or "siid" not in msg or - "eiid" not in msg - # or 'arguments' not in msg - ): - self.log_info("unknown event msg, %s", payload) ->>>>>>> 83899f8 (fomatted code) return if 'arguments' not in msg: self.log_info('wrong event msg, %s', payload) @@ -1579,7 +1257,6 @@ class MipsLocalClient(_MipsClient): if handler: self.log_debug('local, on event_occurred, %s', payload) handler(msg, ctx) -<<<<<<< HEAD return self.__reg_broadcast_external( topic=topic, handler=on_event_msg, handler_ctx=handler_ctx) @@ -1593,21 +1270,6 @@ class MipsLocalClient(_MipsClient): topic: str = ( f'appMsg/notify/iot/{did}/event/' f'{"#" if siid is None or eiid is None else f"{siid}.{eiid}"}') -======= - - return self.__reg_broadcast_external(topic=topic, - handler=on_event_msg, - handler_ctx=handler_ctx) - - @final - def unsub_event(self, - did: str, - siid: Optional[int] = None, - eiid: Optional[int] = None) -> bool: - topic: str = ( - f"appMsg/notify/iot/{did}/event/" - f"{'#' if siid is None or eiid is None else f'{siid}.{eiid}'}") ->>>>>>> 83899f8 (fomatted code) return self.__unreg_broadcast_external(topic=topic) @final @@ -1619,7 +1281,6 @@ class MipsLocalClient(_MipsClient): self._get_prop_queue.setdefault(did, []) fut: asyncio.Future = self.main_loop.create_future() self._get_prop_queue[did].append({ -<<<<<<< HEAD 'param': json.dumps({ 'did': did, 'siid': siid, @@ -1633,19 +1294,6 @@ class MipsLocalClient(_MipsClient): 0.1, self.main_loop.create_task, self.__get_prop_timer_handle()) -======= - "param": json.dumps({ - "did": did, - "siid": siid, - "piid": piid - }), - "fut": fut, - "timeout_ms": timeout_ms, - }) - if self._get_prop_timer is None: - self._get_prop_timer = self.main_loop.call_later( - 0.1, self.main_loop.create_task, self.__get_prop_timer_handle()) ->>>>>>> 83899f8 (fomatted code) return await fut @final @@ -1655,7 +1303,6 @@ class MipsLocalClient(_MipsClient): piid: int, timeout_ms: int = 10000) -> Any: result_obj = await self.__request_async( -<<<<<<< HEAD topic='proxy/get', payload=json.dumps({ 'did': did, @@ -1664,22 +1311,10 @@ class MipsLocalClient(_MipsClient): }), timeout_ms=timeout_ms) if not isinstance(result_obj, dict) or 'value' not in result_obj: -======= - topic="proxy/get", - payload=json.dumps({ - "did": did, - "siid": siid, - "piid": piid - }), - timeout_ms=timeout_ms, - ) - if not isinstance(result_obj, dict) or "value" not in result_obj: ->>>>>>> 83899f8 (fomatted code) return None return result_obj['value'] @final -<<<<<<< HEAD async def set_prop_async( self, did: str, siid: int, piid: int, value: Any, timeout_ms: int = 10000 @@ -1712,46 +1347,11 @@ class MipsLocalClient(_MipsClient): return result_obj['result'][0] if 'error' in result_obj: return result_obj['error'] -======= - async def set_prop_async(self, - did: str, - siid: int, - piid: int, - value: Any, - timeout_ms: int = 10000) -> dict: - payload_obj: dict = { - "did": did, - "rpc": { - "id": - self.__gen_mips_id, - "method": - "set_properties", - "params": [{ - "did": did, - "siid": siid, - "piid": piid, - "value": value - }], - }, - } - result_obj = await self.__request_async(topic="proxy/rpcReq", - payload=json.dumps(payload_obj), - timeout_ms=timeout_ms) - if result_obj: - if ("result" in result_obj and len(result_obj["result"]) == 1 and - "did" in result_obj["result"][0] and - result_obj["result"][0]["did"] == did and - "code" in result_obj["result"][0]): - return result_obj["result"][0] - if "error" in result_obj: - return result_obj["error"] ->>>>>>> 83899f8 (fomatted code) return { 'code': MIoTErrorCode.CODE_INTERNAL_ERROR.value, 'message': 'Invalid result'} @final -<<<<<<< HEAD async def set_props_async( self, did: str, props_list: List[Dict[str, Any]], timeout_ms: int = 10000 @@ -1762,12 +1362,6 @@ class MipsLocalClient(_MipsClient): # 'piid': piid, # 'value': value # }] -======= - async def set_props_async(self, - did: str, - props_list: List[Dict[str, Any]], - timeout_ms: int = 10000) -> dict: ->>>>>>> 83899f8 (fomatted code) payload_obj: dict = { "did": did, "rpc": { @@ -1776,16 +1370,10 @@ class MipsLocalClient(_MipsClient): "params": props_list, } } -<<<<<<< HEAD result_obj = await self.__request_async( topic="proxy/rpcReq", payload=json.dumps(payload_obj), timeout_ms=timeout_ms) -======= - result_obj = await self.__request_async(topic="proxy/rpcReq", - payload=json.dumps(payload_obj), - timeout_ms=timeout_ms) ->>>>>>> 83899f8 (fomatted code) if result_obj: if ("result" in result_obj and len(result_obj["result"]) == len(props_list) and @@ -1799,7 +1387,6 @@ class MipsLocalClient(_MipsClient): 'message': 'Invalid result'} @final -<<<<<<< HEAD async def action_async( self, did: str, siid: int, aiid: int, in_list: list, timeout_ms: int = 10000 @@ -1820,30 +1407,6 @@ class MipsLocalClient(_MipsClient): result_obj = await self.__request_async( topic='proxy/rpcReq', payload=json.dumps(payload_obj), timeout_ms=timeout_ms) -======= - async def action_async(self, - did: str, - siid: int, - aiid: int, - in_list: list, - timeout_ms: int = 10000) -> dict: - payload_obj: dict = { - "did": did, - "rpc": { - "id": self.__gen_mips_id, - "method": "action", - "params": { - "did": did, - "siid": siid, - "aiid": aiid, - "in": in_list - }, - }, - } - result_obj = await self.__request_async(topic="proxy/rpcReq", - payload=json.dumps(payload_obj), - timeout_ms=timeout_ms) ->>>>>>> 83899f8 (fomatted code) if result_obj: if 'result' in result_obj and 'code' in result_obj['result']: return result_obj['result'] @@ -1854,7 +1417,6 @@ class MipsLocalClient(_MipsClient): 'message': 'Invalid result'} @final -<<<<<<< HEAD async def get_dev_list_async( self, payload: Optional[str] = None, timeout_ms: int = 10000 ) -> dict[str, dict]: @@ -1863,16 +1425,6 @@ class MipsLocalClient(_MipsClient): timeout_ms=timeout_ms) if not result_obj or 'devList' not in result_obj: raise MIoTMipsError('invalid result') -======= - async def get_dev_list_async(self, - payload: Optional[str] = None, - timeout_ms: int = 10000) -> dict[str, dict]: - result_obj = await self.__request_async(topic="proxy/getDevList", - payload=payload or "{}", - timeout_ms=timeout_ms) - if not result_obj or "devList" not in result_obj: - raise MIoTMipsError("invalid result") ->>>>>>> 83899f8 (fomatted code) device_list = {} for did, info in result_obj['devList'].items(): name: str = info.get('name', None) @@ -1893,7 +1445,6 @@ class MipsLocalClient(_MipsClient): return device_list @final -<<<<<<< HEAD async def get_action_group_list_async( self, timeout_ms: int = 10000 ) -> list[str]: @@ -1904,17 +1455,6 @@ class MipsLocalClient(_MipsClient): if not result_obj or 'result' not in result_obj: raise MIoTMipsError('invalid result') return result_obj['result'] -======= - async def get_action_group_list_async(self, - timeout_ms: int = 10000) -> list[str]: - result_obj = await self.__request_async( - topic="proxy/getMijiaActionGroupList", - payload="{}", - timeout_ms=timeout_ms) - if not result_obj or "result" not in result_obj: - raise MIoTMipsError("invalid result") - return result_obj["result"] ->>>>>>> 83899f8 (fomatted code) @final async def exec_action_group_list_async(self, @@ -1936,12 +1476,8 @@ class MipsLocalClient(_MipsClient): @final @property def on_dev_list_changed( -<<<<<<< HEAD self ) -> Optional[Callable[[Any, list[str]], Coroutine]]: -======= - self) -> Optional[Callable[[Any, list[str]], Coroutine]]: ->>>>>>> 83899f8 (fomatted code) return self._on_dev_list_changed @final @@ -1961,7 +1497,6 @@ class MipsLocalClient(_MipsClient): mid=self.__gen_mips_id, on_reply=on_reply, on_reply_ctx=on_reply_ctx, -<<<<<<< HEAD timer=None) pub_topic: str = f'master/{topic}' result = self.__mips_publish( @@ -1992,37 +1527,6 @@ class MipsLocalClient(_MipsClient): sub_bc: _MipsBroadcast = _MipsBroadcast( topic=sub_topic, handler=handler, handler_ctx=handler_ctx) -======= - timer=None, - ) - pub_topic: str = f"master/{topic}" - result = self.__mips_publish(topic=pub_topic, - payload=payload, - mid=req.mid, - ret_topic=self._reply_topic) - self.log_debug( - f"mips local call api, {result}, {req.mid}, {pub_topic}, {payload}") - - def on_request_timeout(req: _MipsRequest): - self.log_error( - f"on mips request timeout, {req.mid}, {pub_topic}, {payload}") - self._request_map.pop(str(req.mid), None) - req.on_reply('{"error":{"code":-10006, "message":"timeout"}}', - req.on_reply_ctx) - - req.timer = self._internal_loop.call_later(timeout_ms / 1000, - on_request_timeout, req) - self._request_map[str(req.mid)] = req - - def __reg_broadcast(self, topic: str, handler: Callable[[str, str, Any], - None], - handler_ctx: Any) -> None: - sub_topic: str = f"{self._did}/{topic}" - if not self._msg_matcher.get(sub_topic): - sub_bc: _MipsBroadcast = _MipsBroadcast(topic=sub_topic, - handler=handler, - handler_ctx=handler_ctx) ->>>>>>> 83899f8 (fomatted code) self._msg_matcher[sub_topic] = sub_bc self._mips_sub_internal(topic=f'master/{topic}') else: @@ -2034,11 +1538,7 @@ class MipsLocalClient(_MipsClient): if self._msg_matcher.get(unsub_topic): del self._msg_matcher[unsub_topic] self._mips_unsub_internal( -<<<<<<< HEAD topic=re.sub(f'^{self._did}', 'master', unsub_topic)) -======= - topic=re.sub(f"^{self._did}", "master", unsub_topic)) ->>>>>>> 83899f8 (fomatted code) @final def _on_mips_connect(self, rc: int, props: dict) -> None: @@ -2052,11 +1552,7 @@ class MipsLocalClient(_MipsClient): # Sub broadcast topic for topic, _ in list(self._msg_matcher.iter_all_nodes()): self._mips_sub_internal( -<<<<<<< HEAD topic=re.sub(f'^{self._did}', 'master', topic)) -======= - topic=re.sub(f"^{self._did}", "master", topic)) ->>>>>>> 83899f8 (fomatted code) @final def _on_mips_disconnect(self, rc: int, props: dict) -> None: @@ -2069,11 +1565,7 @@ class MipsLocalClient(_MipsClient): # f"mips local client, on_message, {topic} -> {mips_msg}") # Reply if topic == self._reply_topic: -<<<<<<< HEAD self.log_debug(f'on request reply, {mips_msg}') -======= - self.log_debug(f"on request reply, {mips_msg}") ->>>>>>> 83899f8 (fomatted code) req: Optional[_MipsRequest] = self._request_map.pop( str(mips_msg.mid), None) if req: @@ -2082,37 +1574,20 @@ class MipsLocalClient(_MipsClient): req.timer.cancel() if req.on_reply: self.main_loop.call_soon_threadsafe( -<<<<<<< HEAD req.on_reply, mips_msg.payload or '{}', req.on_reply_ctx) return # Broadcast bc_list: list[_MipsBroadcast] = list(self._msg_matcher.iter_match( topic=topic)) -======= - req.on_reply, mips_msg.payload or "{}", - req.on_reply_ctx) - return - # Broadcast - bc_list: list[_MipsBroadcast] = list( - self._msg_matcher.iter_match(topic=topic)) ->>>>>>> 83899f8 (fomatted code) if bc_list: self.log_debug(f'on broadcast, {topic}, {mips_msg}') for item in bc_list or []: if item.handler is None: continue self.main_loop.call_soon_threadsafe( -<<<<<<< HEAD item.handler, topic[topic.find('/')+1:], mips_msg.payload or '{}', item.handler_ctx) -======= - item.handler, - topic[topic.find("/") + 1:], - mips_msg.payload or "{}", - item.handler_ctx, - ) ->>>>>>> 83899f8 (fomatted code) return # Device list change if topic == self._dev_list_change_topic: @@ -2132,11 +1607,7 @@ class MipsLocalClient(_MipsClient): return self.log_debug( -<<<<<<< HEAD f'mips local client, recv unknown msg, {topic} -> {mips_msg}') -======= - f"mips local client, recv unknown msg, {topic} -> {mips_msg}") ->>>>>>> 83899f8 (fomatted code) @property def __gen_mips_id(self) -> int: @@ -2166,7 +1637,6 @@ class MipsLocalClient(_MipsClient): on_reply_ctx: Any = None, timeout_ms: int = 10000 ) -> bool: if topic is None or payload is None or on_reply is None: -<<<<<<< HEAD raise MIoTMipsError('invalid params') self._internal_loop.call_soon_threadsafe( self.__request, topic, payload, on_reply, on_reply_ctx, timeout_ms) @@ -2179,19 +1649,6 @@ class MipsLocalClient(_MipsClient): self._internal_loop.call_soon_threadsafe( self.__reg_broadcast, topic, handler, handler_ctx) -======= - raise MIoTMipsError("invalid params") - self._internal_loop.call_soon_threadsafe(self.__request, topic, payload, - on_reply, on_reply_ctx, - timeout_ms) - return True - - def __reg_broadcast_external(self, topic: str, - handler: Callable[[str, str, Any], None], - handler_ctx: Any) -> bool: - self._internal_loop.call_soon_threadsafe(self.__reg_broadcast, topic, - handler, handler_ctx) ->>>>>>> 83899f8 (fomatted code) return True def __unreg_broadcast_external(self, topic) -> bool: @@ -2215,12 +1672,7 @@ class MipsLocalClient(_MipsClient): payload=payload, on_reply=on_msg_reply, on_reply_ctx=fut_handler, -<<<<<<< HEAD timeout_ms=timeout_ms): -======= - timeout_ms=timeout_ms, - ): ->>>>>>> 83899f8 (fomatted code) # Request error fut_handler.set_result('internal request error') @@ -2237,19 +1689,11 @@ class MipsLocalClient(_MipsClient): item = self._get_prop_queue[did].pop() _LOGGER.debug('get prop, %s, %s', did, item) result_obj = await self.__request_async( -<<<<<<< HEAD topic='proxy/get', payload=item['param'], timeout_ms=item['timeout_ms']) if result_obj is None or 'value' not in result_obj: item['fut'].set_result(None) -======= - topic="proxy/get", - payload=item["param"], - timeout_ms=item["timeout_ms"]) - if result_obj is None or "value" not in result_obj: - item["fut"].set_result(None) ->>>>>>> 83899f8 (fomatted code) else: item['fut'].set_result(result_obj['value']) @@ -2258,13 +1702,7 @@ class MipsLocalClient(_MipsClient): if self._get_prop_queue: self._get_prop_timer = self.main_loop.call_later( -<<<<<<< HEAD 0.1, lambda: self.main_loop.create_task( self.__get_prop_timer_handle())) -======= - 0.1, - lambda: self.main_loop.create_task(self.__get_prop_timer_handle( - ))) ->>>>>>> 83899f8 (fomatted code) else: self._get_prop_timer = None diff --git a/custom_components/xiaomi_home/select.py b/custom_components/xiaomi_home/select.py index a49fc06..3804d63 100644 --- a/custom_components/xiaomi_home/select.py +++ b/custom_components/xiaomi_home/select.py @@ -66,11 +66,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up a config entry.""" -<<<<<<< HEAD device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][ -======= - device_list: list[MIoTDevice] = hass.data[DOMAIN]["devices"][ ->>>>>>> 83899f8 (fomatted code) config_entry.entry_id] new_entities = [] @@ -84,25 +80,12 @@ async def async_setup_entry( # create select for light new_light_select_entities = [] for miot_device in device_list: -<<<<<<< HEAD # Add it to all devices with light entities, because some bathroom heaters and clothes drying racks also have lights. # if "device:light" in miot_device.spec_instance.urn: if miot_device.entity_list.get("light", []): device_id = list(miot_device.device_info.get("identifiers"))[0][1] new_light_select_entities.append( LightCommandSendMode(hass=hass, device_id=device_id)) -======= - if "device:light" in miot_device.spec_instance.urn: - if miot_device.entity_list.get("light", []): - device_id = list( - miot_device.device_info.get("identifiers"))[0][1] - light_entity_id = miot_device.gen_device_entity_id(DOMAIN) - new_light_select_entities.append( - LightCommandSendMode(hass=hass, - light_entity_id=light_entity_id, - device_id=device_id)) - ->>>>>>> 83899f8 (fomatted code) if new_light_select_entities: async_add_entities(new_light_select_entities) @@ -117,13 +100,8 @@ class Select(MIoTPropertyEntity, SelectEntity): async def async_select_option(self, option: str) -> None: """Change the selected option.""" -<<<<<<< HEAD await self.set_property_async( value=self.get_vlist_value(description=option)) -======= - await self.set_property_async(value=self.get_vlist_value( - description=option)) ->>>>>>> 83899f8 (fomatted code) @property def current_option(self) -> Optional[str]: @@ -136,34 +114,19 @@ class LightCommandSendMode(SelectEntity, RestoreEntity): then send other color temperatures and brightness or send them all at the same time. The default is to send one by one.""" -<<<<<<< HEAD def __init__(self, hass: HomeAssistant, device_id: str): -======= - def __init__(self, hass: HomeAssistant, light_entity_id: str, - device_id: str): ->>>>>>> 83899f8 (fomatted code) super().__init__() self.hass = hass self._device_id = device_id self._attr_name = "Command Send Mode" -<<<<<<< HEAD self.entity_id = f"select.light_{device_id}_command_send_mode" self._attr_unique_id = self.entity_id -======= - self._attr_unique_id = f"{light_entity_id}_command_send_mode" ->>>>>>> 83899f8 (fomatted code) self._attr_options = [ "Send One by One", "Send Turn On First", "Send Together" ] self._attr_device_info = {"identifiers": {(DOMAIN, device_id)}} -<<<<<<< HEAD self._attr_current_option = self._attr_options[0] self._attr_entity_category = EntityCategory.CONFIG -======= - self._attr_current_option = self._attr_options[0] # 默认选项 - self._attr_entity_category = (EntityCategory.CONFIG - ) # **重点:告诉 HA 这是配置类实体** ->>>>>>> 83899f8 (fomatted code) async def async_select_option(self, option: str): if option in self._attr_options: From 4c7b6d570d47ad389549d10a886eb52cc7c6b36b Mon Sep 17 00:00:00 2001 From: GavinIves Date: Sun, 28 Dec 2025 15:10:02 +0000 Subject: [PATCH 4/5] sync main --- .../xiaomi_home/miot/miot_client.py | 20 ++++--- .../xiaomi_home/miot/miot_cloud.py | 19 +++---- .../xiaomi_home/miot/miot_device.py | 26 +++++---- .../xiaomi_home/miot/miot_lan.py | 34 +++++------ .../xiaomi_home/miot/miot_mips.py | 56 ++++++++----------- 5 files changed, 75 insertions(+), 80 deletions(-) diff --git a/custom_components/xiaomi_home/miot/miot_client.py b/custom_components/xiaomi_home/miot/miot_client.py index c17fa62..194b7e3 100644 --- a/custom_components/xiaomi_home/miot/miot_client.py +++ b/custom_components/xiaomi_home/miot/miot_client.py @@ -1415,8 +1415,9 @@ class MIoTClient: _LOGGER.error('on event msg error, %s, %s', params, err) @final - def __check_device_state(self, cloud_state: Optional[bool], gw_state: bool, - lan_state: bool) -> Optional[bool]: + def __check_device_state( + self, cloud_state: Optional[bool], gw_state: bool, lan_state: bool + ) -> Optional[bool]: if cloud_state is None and not gw_state and not lan_state: # Device remove return None @@ -1698,10 +1699,9 @@ class MIoTClient: self.__request_show_devices_changed_notify() @final - def __request_refresh_gw_devices_by_group_id(self, - group_id: str, - immediately: bool = False - ) -> None: + def __request_refresh_gw_devices_by_group_id( + self, group_id: str, immediately: bool = False + ) -> None: """Request refresh gateway devices by group_id""" refresh_timer = self._mips_local_state_changed_timers.get( group_id, None) @@ -1865,9 +1865,11 @@ class MIoTClient: if not self._refresh_props_list: return # Cloud, Central hub gateway, Lan control - if (await self.__refresh_props_from_cloud() or - await self.__refresh_props_from_gw() or - await self.__refresh_props_from_lan()): + if ( + await self.__refresh_props_from_cloud() + or await self.__refresh_props_from_gw() + or await self.__refresh_props_from_lan() + ): self._refresh_props_retry_count = 0 if self._refresh_props_list: self._refresh_props_timer = self._main_loop.call_later( diff --git a/custom_components/xiaomi_home/miot/miot_cloud.py b/custom_components/xiaomi_home/miot/miot_cloud.py index 2c72a6f..d9acd5c 100644 --- a/custom_components/xiaomi_home/miot/miot_cloud.py +++ b/custom_components/xiaomi_home/miot/miot_cloud.py @@ -624,9 +624,9 @@ class MIoTHttpClient: devices.update(result) return devices - async def get_devices_async(self, - home_ids: Optional[list[str]] = None - ) -> dict[str, dict]: + async def get_devices_async( + self, home_ids: Optional[list[str]] = None + ) -> dict[str, dict]: homeinfos = await self.get_homeinfos_async() homes: dict[str, dict[str, Any]] = {} devices: dict[str, dict] = {} @@ -787,11 +787,9 @@ class MIoTHttpClient: self._get_prop_timer = None return True - async def get_prop_async(self, - did: str, - siid: int, - piid: int, - immediately: bool = False) -> Any: + async def get_prop_async( + self, did: str, siid: int, piid: int, immediately: bool = False + ) -> Any: if immediately: return await self.__get_prop_async(did, siid, piid) key: str = f'{did}.{siid}.{piid}' @@ -843,8 +841,9 @@ class MIoTHttpClient: return res_obj['result'] - async def action_async(self, did: str, siid: int, aiid: int, - in_list: list[dict]) -> dict: + async def action_async( + self, did: str, siid: int, aiid: int, in_list: list[dict] + ) -> dict: """ params = {"did": "xxxx", "siid": 2, "aiid": 1, "in": []} """ diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index 3158caa..a7883ce 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -78,6 +78,7 @@ from homeassistant.const import ( from homeassistant.helpers.entity import DeviceInfo from homeassistant.components.switch import SwitchDeviceClass + # pylint: disable=relative-beyond-top-level from .specs.specv2entity import ( SPEC_ACTION_TRANS_MAP, @@ -242,8 +243,8 @@ class MIoTDevice: did=self._did, siid=siid, aiid=aiid, in_list=in_list) def sub_device_state( - self, key: str, handler: Callable[[str, MIoTDeviceState], - None]) -> int: + self, key: str, handler: Callable[[str, MIoTDeviceState], None] + ) -> int: sub_id = self.__gen_sub_id() if key in self._device_state_sub_list: self._device_state_sub_list[key][str(sub_id)] = handler @@ -409,7 +410,8 @@ class MIoTDevice: self._action_list[action.platform].append(action) def parse_miot_device_entity( - self, spec_instance: MIoTSpecInstance) -> Optional[MIoTEntityData]: + self, spec_instance: MIoTSpecInstance + ) -> Optional[MIoTEntityData]: if spec_instance.name not in SPEC_DEVICE_TRANS_MAP: return None spec_name: str = spec_instance.name @@ -866,8 +868,9 @@ class MIoTDevice: self._sub_id += 1 return self._sub_id - def __on_device_state_changed(self, did: str, state: MIoTDeviceState, - ctx: Any) -> None: + def __on_device_state_changed( + self, did: str, state: MIoTDeviceState, ctx: Any + ) -> None: self._online = state == MIoTDeviceState.ONLINE for key, sub_list in self._device_state_sub_list.items(): for handler in sub_list.values(): @@ -1148,9 +1151,9 @@ class MIoTServiceEntity(Entity): self.async_write_ha_state() return result - async def action_async(self, - action: MIoTSpecAction, - in_list: Optional[list] = None) -> bool: + async def action_async( + self, action: MIoTSpecAction, in_list: Optional[list] = None + ) -> bool: if not action: raise RuntimeError( f'action failed, action is None, {self.entity_id}, {self.name}') @@ -1449,10 +1452,9 @@ class MIoTEventEntity(Entity): sub_id=self._value_sub_id) @abstractmethod - def on_event_occurred(self, - name: str, - arguments: dict[str, Any] | None = None) -> None: - ... + def on_event_occurred( + self, name: str, arguments: dict[str, Any] | None = None + ) -> None: ... def __on_event_occurred(self, params: dict, ctx: Any) -> None: _LOGGER.debug('event occurred, %s', params) diff --git a/custom_components/xiaomi_home/miot/miot_lan.py b/custom_components/xiaomi_home/miot/miot_lan.py index dd0046f..002b26f 100644 --- a/custom_components/xiaomi_home/miot/miot_lan.py +++ b/custom_components/xiaomi_home/miot/miot_lan.py @@ -71,6 +71,7 @@ from .miot_mdns import MipsService, MipsServiceState from .common import ( randomize_float, load_yaml_file, gen_absolute_path, MIoTMatcher) + _LOGGER = logging.getLogger(__name__) @@ -812,11 +813,9 @@ class MIoTLan: return True @final - async def get_prop_async(self, - did: str, - siid: int, - piid: int, - timeout_ms: int = 10000) -> Any: + async def get_prop_async( + self, did: str, siid: int, piid: int, timeout_ms: int = 10000 + ) -> Any: self.__assert_service_ready() result_obj = await self.__call_api_async( did=did, msg={ @@ -920,10 +919,9 @@ class MIoTLan: timeout_ms=timeout_ms)) return await fut - async def __call_api_async(self, - did: str, - msg: dict, - timeout_ms: int = 10000) -> dict: + async def __call_api_async( + self, did: str, msg: dict, timeout_ms: int = 10000 + ) -> dict: def call_api_handler(msg: dict, fut: asyncio.Future): self._main_loop.call_soon_threadsafe( @@ -1026,7 +1024,6 @@ class MIoTLan: handler_ctx: Any = None, timeout_ms: Optional[int] = None ) -> None: - def request_timeout_handler(req_data: _MIoTLanRequestData): self._pending_requests.pop(req_data.msg_id, None) if req_data and req_data.handler: @@ -1253,8 +1250,9 @@ class MIoTLan: except Exception as err: # pylint: disable=broad-exception-caught _LOGGER.error('socket read handler error, %s', err) - def __raw_message_handler(self, data: bytearray, data_len: int, ip: str, - if_name: str) -> None: + def __raw_message_handler( + self, data: bytearray, data_len: int, ip: str, if_name: str + ) -> None: if data[:2] != self.OT_HEADER: return # Keep alive message @@ -1278,8 +1276,11 @@ class MIoTLan: int(data[28]) == self.OT_SUPPORT_WILDCARD_SUB) sub_ts = struct.unpack('>I', data[20:24])[0] sub_type = int(data[27]) - if (device.supported_wildcard_sub and sub_type in [0, 1, 4] and - sub_ts != device.sub_ts): + if ( + device.supported_wildcard_sub + and sub_type in [0, 1, 4] + and sub_ts != device.sub_ts + ): device.subscribed = False device.subscribe() if data_len > self.OT_PROBE_LEN: @@ -1357,8 +1358,9 @@ class MIoTLan: filter_id) return False - def __sendto(self, if_name: Optional[str], data: bytes, address: str, - port: int) -> None: + def __sendto( + self, if_name: Optional[str], data: bytes, address: str, port: int + ) -> None: if if_name is None: # Broadcast for if_n, sock in self._broadcast_socks.items(): diff --git a/custom_components/xiaomi_home/miot/miot_mips.py b/custom_components/xiaomi_home/miot/miot_mips.py index fa9da7a..a3c59ae 100644 --- a/custom_components/xiaomi_home/miot/miot_mips.py +++ b/custom_components/xiaomi_home/miot/miot_mips.py @@ -415,8 +415,9 @@ class _MipsClient(ABC): self._mqtt.disable_logger() @final - def sub_mips_state(self, key: str, handler: Callable[[str, bool], - Coroutine]) -> bool: + def sub_mips_state( + self, key: str, handler: Callable[[str, bool], Coroutine] + ) -> bool: """Subscribe mips state. NOTICE: callback to main loop thread This will be called before the client is connected. @@ -484,12 +485,9 @@ class _MipsClient(ABC): ) -> dict[str, dict]: ... @abstractmethod - async def get_prop_async(self, - did: str, - siid: int, - piid: int, - timeout_ms: int = 10000) -> Any: - ... + async def get_prop_async( + self, did: str, siid: int, piid: int, timeout_ms: int = 10000 + ) -> Any: ... @abstractmethod async def set_prop_async( @@ -504,16 +502,13 @@ class _MipsClient(ABC): ) -> dict: ... @abstractmethod - def _on_mips_message(self, topic: str, payload: bytes) -> None: - ... + def _on_mips_message(self, topic: str, payload: bytes) -> None: ... @abstractmethod - def _on_mips_connect(self, rc: int, props: dict) -> None: - ... + def _on_mips_connect(self, rc: int, props: dict) -> None: ... @abstractmethod - def _on_mips_disconnect(self, rc: int, props: dict) -> None: - ... + def _on_mips_disconnect(self, rc: int, props: dict) -> None: ... @final def _mips_sub_internal(self, topic: str) -> None: @@ -1273,11 +1268,9 @@ class MipsLocalClient(_MipsClient): return self.__unreg_broadcast_external(topic=topic) @final - async def get_prop_safe_async(self, - did: str, - siid: int, - piid: int, - timeout_ms: int = 10000) -> Any: + async def get_prop_safe_async( + self, did: str, siid: int, piid: int, timeout_ms: int = 10000 + ) -> Any: self._get_prop_queue.setdefault(did, []) fut: asyncio.Future = self.main_loop.create_future() self._get_prop_queue[did].append({ @@ -1297,11 +1290,9 @@ class MipsLocalClient(_MipsClient): return await fut @final - async def get_prop_async(self, - did: str, - siid: int, - piid: int, - timeout_ms: int = 10000) -> Any: + async def get_prop_async( + self, did: str, siid: int, piid: int, timeout_ms: int = 10000 + ) -> Any: result_obj = await self.__request_async( topic='proxy/get', payload=json.dumps({ @@ -1457,9 +1448,9 @@ class MipsLocalClient(_MipsClient): return result_obj['result'] @final - async def exec_action_group_list_async(self, - ag_id: str, - timeout_ms: int = 10000) -> dict: + async def exec_action_group_list_async( + self, ag_id: str, timeout_ms: int = 10000 + ) -> dict: result_obj = await self.__request_async( topic='proxy/execMijiaActionGroup', payload=f'{{"id":"{ag_id}"}}', @@ -1483,8 +1474,8 @@ class MipsLocalClient(_MipsClient): @final @on_dev_list_changed.setter def on_dev_list_changed( - self, func: Optional[Callable[[Any, list[str]], - Coroutine]]) -> None: + self, func: Optional[Callable[[Any, list[str]], Coroutine]] + ) -> None: """run in main loop.""" self._on_dev_list_changed = func @@ -1657,10 +1648,9 @@ class MipsLocalClient(_MipsClient): return True @final - async def __request_async(self, - topic: str, - payload: str, - timeout_ms: int = 10000) -> dict: + async def __request_async( + self, topic: str, payload: str, timeout_ms: int = 10000 + ) -> dict: fut_handler: asyncio.Future = self.main_loop.create_future() def on_msg_reply(payload: str, ctx: Any): From f5bc880c62ef5242777d17b76add4c9bdef16566 Mon Sep 17 00:00:00 2001 From: GavinIves Date: Sun, 28 Dec 2025 15:24:34 +0000 Subject: [PATCH 5/5] fixbug --- custom_components/xiaomi_home/miot/miot_client.py | 2 +- custom_components/xiaomi_home/miot/miot_lan.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/custom_components/xiaomi_home/miot/miot_client.py b/custom_components/xiaomi_home/miot/miot_client.py index 194b7e3..965b60c 100644 --- a/custom_components/xiaomi_home/miot/miot_client.py +++ b/custom_components/xiaomi_home/miot/miot_client.py @@ -716,7 +716,7 @@ class MIoTClient: # props_list = [{'did': str, 'siid': int, 'piid': int, 'value': Any}......] # 判断是不是只有一个did did_set = {prop["did"] for prop in props_list} - if len(did_set) == 1: + if len(did_set) != 1: raise MIoTClientError(f"more than one or no did once, {did_set}") did = did_set.pop() diff --git a/custom_components/xiaomi_home/miot/miot_lan.py b/custom_components/xiaomi_home/miot/miot_lan.py index 002b26f..8e95b32 100644 --- a/custom_components/xiaomi_home/miot/miot_lan.py +++ b/custom_components/xiaomi_home/miot/miot_lan.py @@ -922,7 +922,6 @@ class MIoTLan: async def __call_api_async( self, did: str, msg: dict, timeout_ms: int = 10000 ) -> dict: - def call_api_handler(msg: dict, fut: asyncio.Future): self._main_loop.call_soon_threadsafe( fut.set_result, msg)