refactor: refactor miot device and spec (#592)

* fix: fix miot_device type error

* fix: fix type error

* feat: remove spec cache storage

* feat: update std_lib and multi_lang logic

* feat: update entity value-range

* feat: update value-list logic

* feat: update prop.format_ logic

* fix: fix miot cloud log error

* fix: fix fan entity

* style: ignore type error

* style: rename spec_filter func name

* feat: move bool_trans from storage to spec

* feat: move sepc_filter from storage to spec, use the YAML format file

* feat: same prop supports multiple sub

* feat: same event supports multiple sub

* fix: fix device remove error

* feat: add func slugify_did

* fix: fix multi lang error

* feat: update action debug logic

* feat: ignore normal disconnect log

* feat: support binary mode

* feat: change miot spec name type define

* style: ignore i18n tranlate type error

* fix: fix pylint warning

* fix: miot storage type error

* feat: support binary display mode configure

* feat: set default sensor state_class

* fix: fix sensor entity type error

* fix: fix __init__ type error

* feat: update test case logic

* fix: github actions add dependencies lib

* fix: fix some type error

* feat: update device list changed notify logic
This commit is contained in:
Paul Shawn
2025-01-17 18:14:31 +08:00
committed by GitHub
parent bf116e13a4
commit ef56448dbb
54 changed files with 2050 additions and 1978 deletions

View File

@ -54,6 +54,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.components import persistent_notification
from homeassistant.helpers import device_registry, entity_registry
from .miot.common import slugify_did
from .miot.miot_storage import (
DeviceManufacturer, MIoTStorage, MIoTCert)
from .miot.miot_spec import (
@ -92,7 +93,7 @@ async def async_setup_entry(
"""Send messages in Notifications dialog box."""
if title:
persistent_notification.async_create(
hass=hass, message=message,
hass=hass, message=message or '',
title=title, notification_id=notify_id)
else:
persistent_notification.async_dismiss(
@ -125,9 +126,8 @@ async def async_setup_entry(
miot_devices: list[MIoTDevice] = []
er = entity_registry.async_get(hass=hass)
for did, info in miot_client.device_list.items():
spec_instance: MIoTSpecInstance = await spec_parser.parse(
urn=info['urn'])
if spec_instance is None:
spec_instance = await spec_parser.parse(urn=info['urn'])
if not isinstance(spec_instance, MIoTSpecInstance):
_LOGGER.error('spec content is None, %s, %s', did, info)
continue
device: MIoTDevice = MIoTDevice(
@ -155,7 +155,8 @@ async def async_setup_entry(
for entity in filter_entities:
device.entity_list[platform].remove(entity)
entity_id = device.gen_service_entity_id(
ha_domain=platform, siid=entity.spec.iid)
ha_domain=platform,
siid=entity.spec.iid) # type: ignore
if er.async_get(entity_id_or_uuid=entity_id):
er.async_remove(entity_id=entity_id)
if platform in device.prop_list:
@ -208,12 +209,7 @@ async def async_setup_entry(
if er.async_get(entity_id_or_uuid=entity_id):
er.async_remove(entity_id=entity_id)
# Action debug
if miot_client.action_debug:
if 'notify' in device.action_list:
# Add text entity for debug action
device.action_list['action_text'] = (
device.action_list['notify'])
else:
if not miot_client.action_debug:
# Remove text entity for debug action
for action in device.action_list.get('notify', []):
entity_id = device.gen_action_entity_id(
@ -221,6 +217,21 @@ async def async_setup_entry(
siid=action.service.iid, aiid=action.iid)
if er.async_get(entity_id_or_uuid=entity_id):
er.async_remove(entity_id=entity_id)
# Binary sensor display
if not miot_client.display_binary_bool:
for prop in device.prop_list.get('binary_sensor', []):
entity_id = device.gen_prop_entity_id(
ha_domain='binary_sensor', spec_name=prop.name,
siid=prop.service.iid, piid=prop.iid)
if er.async_get(entity_id_or_uuid=entity_id):
er.async_remove(entity_id=entity_id)
if not miot_client.display_binary_text:
for prop in device.prop_list.get('binary_sensor', []):
entity_id = device.gen_prop_entity_id(
ha_domain='sensor', spec_name=prop.name,
siid=prop.service.iid, piid=prop.iid)
if er.async_get(entity_id_or_uuid=entity_id):
er.async_remove(entity_id=entity_id)
hass.data[DOMAIN]['devices'][config_entry.entry_id] = miot_devices
await hass.config_entries.async_forward_entry_setups(
@ -237,7 +248,7 @@ async def async_setup_entry(
device_entry = dr.async_get_device(
identifiers={(
DOMAIN,
MIoTDevice.gen_did_tag(
slugify_did(
cloud_server=config_entry.data['cloud_server'],
did=did))},
connections=None)
@ -330,21 +341,10 @@ async def async_remove_config_entry_device(
'remove device failed, invalid domain, %s, %s',
device_entry.id, device_entry.identifiers)
return False
device_info = identifiers[1].split('_')
if len(device_info) != 2:
_LOGGER.error(
'remove device failed, invalid device info, %s, %s',
device_entry.id, device_entry.identifiers)
return False
did = device_info[1]
if did not in miot_client.device_list:
_LOGGER.error(
'remove device failed, device not found, %s, %s',
device_entry.id, device_entry.identifiers)
return False
# Remove device
await miot_client.remove_device_async(did)
await miot_client.remove_device2_async(did_tag=identifiers[1])
device_registry.async_get(hass).async_remove_device(device_entry.id)
_LOGGER.info(
'remove device, %s, %s, %s', device_info[0], did, device_entry.id)
'remove device, %s, %s', identifiers[1], device_entry.id)
return True