mirror of
https://github.com/XiaoMi/ha_xiaomi_home.git
synced 2026-01-19 00:20:44 +08:00
feat: same event supports multiple sub
This commit is contained in:
parent
da4cdc47d1
commit
69f1d38a19
@ -245,21 +245,16 @@ class MIoTDevice:
|
|||||||
self._sub_id += 1
|
self._sub_id += 1
|
||||||
if key in self._device_state_sub_list:
|
if key in self._device_state_sub_list:
|
||||||
self._device_state_sub_list[key][str(self._sub_id)] = handler
|
self._device_state_sub_list[key][str(self._sub_id)] = handler
|
||||||
return self._sub_id
|
else:
|
||||||
self._device_state_sub_list[key] = {str(self._sub_id): handler}
|
self._device_state_sub_list[key] = {str(self._sub_id): handler}
|
||||||
return self._sub_id
|
return self._sub_id
|
||||||
|
|
||||||
def unsub_device_state(
|
def unsub_device_state(self, key: str, sub_id: int) -> None:
|
||||||
self, key: str, sub_id: Optional[int] = None
|
sub_list = self._device_state_sub_list.get(key, None)
|
||||||
) -> None:
|
if sub_list:
|
||||||
if sub_id:
|
|
||||||
sub_list = self._device_state_sub_list.get(key, None)
|
|
||||||
if not sub_list:
|
|
||||||
return
|
|
||||||
sub_list.pop(str(sub_id), None)
|
sub_list.pop(str(sub_id), None)
|
||||||
return
|
if not sub_list:
|
||||||
self._device_state_sub_list.pop(key, None)
|
self._device_state_sub_list.pop(key, None)
|
||||||
return
|
|
||||||
|
|
||||||
def sub_property(
|
def sub_property(
|
||||||
self, handler: Callable[[dict, Any], None], siid: int, piid: int
|
self, handler: Callable[[dict, Any], None], siid: int, piid: int
|
||||||
@ -273,36 +268,49 @@ class MIoTDevice:
|
|||||||
self._sub_id += 1
|
self._sub_id += 1
|
||||||
if key in self._value_sub_list:
|
if key in self._value_sub_list:
|
||||||
self._value_sub_list[key][str(self._sub_id)] = handler
|
self._value_sub_list[key][str(self._sub_id)] = handler
|
||||||
return self._sub_id
|
else:
|
||||||
self._value_sub_list[key] = {str(self._sub_id): handler}
|
self._value_sub_list[key] = {str(self._sub_id): handler}
|
||||||
self.miot_client.sub_prop(
|
self.miot_client.sub_prop(
|
||||||
did=self._did, handler=_on_prop_changed, siid=siid, piid=piid)
|
did=self._did, handler=_on_prop_changed, siid=siid, piid=piid)
|
||||||
return self._sub_id
|
return self._sub_id
|
||||||
|
|
||||||
def unsub_property(
|
def unsub_property(self, siid: int, piid: int, sub_id: int) -> None:
|
||||||
self, siid: int, piid: int, sub_id: Optional[int] = None
|
|
||||||
) -> None:
|
|
||||||
key: str = f'p.{siid}.{piid}'
|
key: str = f'p.{siid}.{piid}'
|
||||||
|
|
||||||
sub_list = self._value_sub_list.get(key, None)
|
sub_list = self._value_sub_list.get(key, None)
|
||||||
if sub_list:
|
if sub_list:
|
||||||
sub_list.pop(str(sub_id), None)
|
sub_list.pop(str(sub_id), None)
|
||||||
if not sub_list or not sub_id:
|
if not sub_list:
|
||||||
self.miot_client.unsub_prop(did=self._did, siid=siid, piid=piid)
|
self.miot_client.unsub_prop(did=self._did, siid=siid, piid=piid)
|
||||||
|
self._value_sub_list.pop(key, None)
|
||||||
|
|
||||||
def sub_event(
|
def sub_event(
|
||||||
self, handler: Callable[[dict, Any], None], siid: Optional[int] = None,
|
self, handler: Callable[[dict, Any], None], siid: int, eiid: int
|
||||||
eiid: Optional[int] = None, handler_ctx: Any = None
|
) -> int:
|
||||||
) -> bool:
|
key: str = f'e.{siid}.{eiid}'
|
||||||
return self.miot_client.sub_event(
|
|
||||||
did=self._did, handler=handler, siid=siid, eiid=eiid,
|
|
||||||
handler_ctx=handler_ctx)
|
|
||||||
|
|
||||||
def unsub_event(
|
def _on_event_occurred(params: dict, ctx: Any) -> None:
|
||||||
self, siid: Optional[int] = None, eiid: Optional[int] = None
|
for handler in self._value_sub_list[key].values():
|
||||||
) -> bool:
|
handler(params, ctx)
|
||||||
return self.miot_client.unsub_event(
|
|
||||||
did=self._did, siid=siid, eiid=eiid)
|
self._sub_id += 1
|
||||||
|
if key in self._value_sub_list:
|
||||||
|
self._value_sub_list[key][str(self._sub_id)] = handler
|
||||||
|
else:
|
||||||
|
self._value_sub_list[key] = {str(self._sub_id): handler}
|
||||||
|
self.miot_client.sub_event(
|
||||||
|
did=self._did, handler=_on_event_occurred, siid=siid, eiid=eiid)
|
||||||
|
return self._sub_id
|
||||||
|
|
||||||
|
def unsub_event(self, siid: int, eiid: int, sub_id: int) -> None:
|
||||||
|
key: str = f'e.{siid}.{eiid}'
|
||||||
|
|
||||||
|
sub_list = self._value_sub_list.get(key, None)
|
||||||
|
if sub_list:
|
||||||
|
sub_list.pop(str(sub_id), None)
|
||||||
|
if not sub_list:
|
||||||
|
self.miot_client.unsub_event(did=self._did, siid=siid, eiid=eiid)
|
||||||
|
self._value_sub_list.pop(key, None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
@ -761,7 +769,7 @@ class MIoTServiceEntity(Entity):
|
|||||||
|
|
||||||
_main_loop: asyncio.AbstractEventLoop
|
_main_loop: asyncio.AbstractEventLoop
|
||||||
_prop_value_map: dict[MIoTSpecProperty, Any]
|
_prop_value_map: dict[MIoTSpecProperty, Any]
|
||||||
_state_sub_id: Optional[int]
|
_state_sub_id: int
|
||||||
_value_sub_ids: dict[str, int]
|
_value_sub_ids: dict[str, int]
|
||||||
|
|
||||||
_event_occurred_handler: Optional[
|
_event_occurred_handler: Optional[
|
||||||
@ -784,7 +792,7 @@ class MIoTServiceEntity(Entity):
|
|||||||
self.entity_data = entity_data
|
self.entity_data = entity_data
|
||||||
self._main_loop = miot_device.miot_client.main_loop
|
self._main_loop = miot_device.miot_client.main_loop
|
||||||
self._prop_value_map = {}
|
self._prop_value_map = {}
|
||||||
self._state_sub_id = None
|
self._state_sub_id = 0
|
||||||
self._value_sub_ids = {}
|
self._value_sub_ids = {}
|
||||||
# Gen entity id
|
# Gen entity id
|
||||||
if isinstance(entity_data.spec, MIoTSpecInstance):
|
if isinstance(entity_data.spec, MIoTSpecInstance):
|
||||||
@ -853,7 +861,8 @@ class MIoTServiceEntity(Entity):
|
|||||||
siid=prop.service.iid, piid=prop.iid)
|
siid=prop.service.iid, piid=prop.iid)
|
||||||
# Sub event
|
# Sub event
|
||||||
for event in self.entity_data.events:
|
for event in self.entity_data.events:
|
||||||
self.miot_device.sub_event(
|
key = f'e.{event.service.iid}.{event.iid}'
|
||||||
|
self._value_sub_ids[key] = self.miot_device.sub_event(
|
||||||
handler=self.__on_event_occurred,
|
handler=self.__on_event_occurred,
|
||||||
siid=event.service.iid, eiid=event.iid)
|
siid=event.service.iid, eiid=event.iid)
|
||||||
|
|
||||||
@ -874,14 +883,18 @@ class MIoTServiceEntity(Entity):
|
|||||||
for prop in self.entity_data.props:
|
for prop in self.entity_data.props:
|
||||||
if not prop.notifiable and not prop.readable:
|
if not prop.notifiable and not prop.readable:
|
||||||
continue
|
continue
|
||||||
self.miot_device.unsub_property(
|
sub_id = self._value_sub_ids.pop(
|
||||||
siid=prop.service.iid, piid=prop.iid,
|
f'p.{prop.service.iid}.{prop.iid}', None)
|
||||||
sub_id=self._value_sub_ids.pop(
|
if sub_id:
|
||||||
f'p.{prop.service.iid}.{prop.iid}', None))
|
self.miot_device.unsub_property(
|
||||||
|
siid=prop.service.iid, piid=prop.iid, sub_id=sub_id)
|
||||||
# Unsub event
|
# Unsub event
|
||||||
for event in self.entity_data.events:
|
for event in self.entity_data.events:
|
||||||
self.miot_device.unsub_event(
|
sub_id = self._value_sub_ids.pop(
|
||||||
siid=event.service.iid, eiid=event.iid)
|
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)
|
||||||
|
|
||||||
def get_map_value(
|
def get_map_value(
|
||||||
self, map_: dict[int, Any], key: int
|
self, map_: dict[int, Any], key: int
|
||||||
@ -1059,8 +1072,8 @@ class MIoTPropertyEntity(Entity):
|
|||||||
# {Any: Any}
|
# {Any: Any}
|
||||||
_value_list: Optional[MIoTSpecValueList]
|
_value_list: Optional[MIoTSpecValueList]
|
||||||
_value: Any
|
_value: Any
|
||||||
_state_sub_id: Optional[int]
|
_state_sub_id: int
|
||||||
_value_sub_id: Optional[int]
|
_value_sub_id: int
|
||||||
|
|
||||||
_pending_write_ha_state_timer: Optional[asyncio.TimerHandle]
|
_pending_write_ha_state_timer: Optional[asyncio.TimerHandle]
|
||||||
|
|
||||||
@ -1074,8 +1087,8 @@ class MIoTPropertyEntity(Entity):
|
|||||||
self._value_range = spec.value_range
|
self._value_range = spec.value_range
|
||||||
self._value_list = spec.value_list
|
self._value_list = spec.value_list
|
||||||
self._value = None
|
self._value = None
|
||||||
self._state_sub_id = None
|
self._state_sub_id = 0
|
||||||
self._value_sub_id = None
|
self._value_sub_id = 0
|
||||||
self._pending_write_ha_state_timer = None
|
self._pending_write_ha_state_timer = None
|
||||||
# Gen entity_id
|
# Gen entity_id
|
||||||
self.entity_id = self.miot_device.gen_prop_entity_id(
|
self.entity_id = self.miot_device.gen_prop_entity_id(
|
||||||
@ -1204,7 +1217,8 @@ class MIoTEventEntity(Entity):
|
|||||||
_main_loop: asyncio.AbstractEventLoop
|
_main_loop: asyncio.AbstractEventLoop
|
||||||
_attr_event_types: list[str]
|
_attr_event_types: list[str]
|
||||||
_arguments_map: dict[int, str]
|
_arguments_map: dict[int, str]
|
||||||
_state_sub_id: Optional[int]
|
_state_sub_id: int
|
||||||
|
_value_sub_id: int
|
||||||
|
|
||||||
def __init__(self, miot_device: MIoTDevice, spec: MIoTSpecEvent) -> None:
|
def __init__(self, miot_device: MIoTDevice, spec: MIoTSpecEvent) -> None:
|
||||||
if miot_device is None or spec is None or spec.service is None:
|
if miot_device is None or spec is None or spec.service is None:
|
||||||
@ -1230,6 +1244,8 @@ class MIoTEventEntity(Entity):
|
|||||||
self._arguments_map = {}
|
self._arguments_map = {}
|
||||||
for prop in spec.argument:
|
for prop in spec.argument:
|
||||||
self._arguments_map[prop.iid] = prop.description_trans
|
self._arguments_map[prop.iid] = prop.description_trans
|
||||||
|
self._state_sub_id = 0
|
||||||
|
self._value_sub_id = 0
|
||||||
|
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
'new miot event entity, %s, %s, %s, %s, %s',
|
'new miot event entity, %s, %s, %s, %s, %s',
|
||||||
@ -1246,7 +1262,7 @@ class MIoTEventEntity(Entity):
|
|||||||
key=f'event.{ self.service.iid}.{self.spec.iid}',
|
key=f'event.{ self.service.iid}.{self.spec.iid}',
|
||||||
handler=self.__on_device_state_changed)
|
handler=self.__on_device_state_changed)
|
||||||
# Sub value changed
|
# Sub value changed
|
||||||
self.miot_device.sub_event(
|
self._value_sub_id = self.miot_device.sub_event(
|
||||||
handler=self.__on_event_occurred,
|
handler=self.__on_event_occurred,
|
||||||
siid=self.service.iid, eiid=self.spec.iid)
|
siid=self.service.iid, eiid=self.spec.iid)
|
||||||
|
|
||||||
@ -1255,7 +1271,8 @@ class MIoTEventEntity(Entity):
|
|||||||
key=f'event.{ self.service.iid}.{self.spec.iid}',
|
key=f'event.{ self.service.iid}.{self.spec.iid}',
|
||||||
sub_id=self._state_sub_id)
|
sub_id=self._state_sub_id)
|
||||||
self.miot_device.unsub_event(
|
self.miot_device.unsub_event(
|
||||||
siid=self.service.iid, eiid=self.spec.iid)
|
siid=self.service.iid, eiid=self.spec.iid,
|
||||||
|
sub_id=self._value_sub_id)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def on_event_occurred(
|
def on_event_occurred(
|
||||||
@ -1312,7 +1329,7 @@ class MIoTActionEntity(Entity):
|
|||||||
_main_loop: asyncio.AbstractEventLoop
|
_main_loop: asyncio.AbstractEventLoop
|
||||||
_in_map: dict[int, MIoTSpecProperty]
|
_in_map: dict[int, MIoTSpecProperty]
|
||||||
_out_map: dict[int, MIoTSpecProperty]
|
_out_map: dict[int, MIoTSpecProperty]
|
||||||
_state_sub_id: Optional[int]
|
_state_sub_id: int
|
||||||
|
|
||||||
def __init__(self, miot_device: MIoTDevice, spec: MIoTSpecAction) -> None:
|
def __init__(self, miot_device: MIoTDevice, spec: MIoTSpecAction) -> None:
|
||||||
if miot_device is None or spec is None or spec.service is None:
|
if miot_device is None or spec is None or spec.service is None:
|
||||||
@ -1322,7 +1339,7 @@ class MIoTActionEntity(Entity):
|
|||||||
self.service = spec.service
|
self.service = spec.service
|
||||||
self.action_platform = 'action'
|
self.action_platform = 'action'
|
||||||
self._main_loop = miot_device.miot_client.main_loop
|
self._main_loop = miot_device.miot_client.main_loop
|
||||||
self._state_sub_id = None
|
self._state_sub_id = 0
|
||||||
# Gen entity_id
|
# Gen entity_id
|
||||||
self.entity_id = self.miot_device.gen_action_entity_id(
|
self.entity_id = self.miot_device.gen_action_entity_id(
|
||||||
ha_domain=DOMAIN, spec_name=spec.name,
|
ha_domain=DOMAIN, spec_name=spec.name,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user