mirror of
https://github.com/XiaoMi/ha_xiaomi_home.git
synced 2026-01-19 00:20:44 +08:00
Compare commits
17 Commits
59c35be221
...
4f4ff94ce9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f4ff94ce9 | ||
|
|
8be0fa5d61 | ||
|
|
07cb4ed193 | ||
|
|
4e1185f4e5 | ||
|
|
6ad8da42be | ||
|
|
4aa6bb579f | ||
|
|
e83aa9367e | ||
|
|
04c44f36b1 | ||
|
|
a40363d3e6 | ||
|
|
13e6863678 | ||
|
|
b0d0d6b107 | ||
|
|
085caff660 | ||
|
|
fe3756db9b | ||
|
|
bf33f0c60d | ||
|
|
72f3a5df3e | ||
|
|
f452611b87 | ||
|
|
36d5a3e4de |
@ -46,6 +46,7 @@ off Xiaomi or its affiliates' products.
|
|||||||
Event entities for Xiaomi Home.
|
Event entities for Xiaomi Home.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -57,6 +58,8 @@ from .miot.miot_spec import MIoTSpecEvent
|
|||||||
from .miot.miot_device import MIoTDevice, MIoTEventEntity
|
from .miot.miot_device import MIoTDevice, MIoTEventEntity
|
||||||
from .miot.const import DOMAIN
|
from .miot.const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -89,4 +92,5 @@ class Event(MIoTEventEntity, EventEntity):
|
|||||||
self, name: str, arguments: dict[str, Any] | None = None
|
self, name: str, arguments: dict[str, Any] | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""An event is occurred."""
|
"""An event is occurred."""
|
||||||
|
_LOGGER.debug('%s, attributes: %s', name, str(arguments))
|
||||||
self._trigger_event(event_type=name, event_attributes=arguments)
|
self._trigger_event(event_type=name, event_attributes=arguments)
|
||||||
|
|||||||
@ -591,13 +591,8 @@ class MIoTDevice:
|
|||||||
# Priority: spec_modify.unit > unit_convert > specv2entity.unit
|
# Priority: spec_modify.unit > unit_convert > specv2entity.unit
|
||||||
miot_prop.external_unit = SPEC_PROP_TRANS_MAP['properties'][
|
miot_prop.external_unit = SPEC_PROP_TRANS_MAP['properties'][
|
||||||
prop_name]['unit_of_measurement']
|
prop_name]['unit_of_measurement']
|
||||||
if (
|
# Priority: default.icon when device_class is set > spec_modify.icon
|
||||||
not miot_prop.icon
|
# > icon_convert
|
||||||
and 'icon' in SPEC_PROP_TRANS_MAP['properties'][prop_name]
|
|
||||||
):
|
|
||||||
# Priority: spec_modify.icon > icon_convert > specv2entity.icon
|
|
||||||
miot_prop.icon = SPEC_PROP_TRANS_MAP['properties'][prop_name][
|
|
||||||
'icon']
|
|
||||||
miot_prop.platform = platform
|
miot_prop.platform = platform
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@ -1215,9 +1215,10 @@ class MipsLocalClient(_MipsClient):
|
|||||||
or 'eiid' not in msg
|
or 'eiid' not in msg
|
||||||
# or 'arguments' not in msg
|
# or 'arguments' not in msg
|
||||||
):
|
):
|
||||||
# self.log_error(f'on_event_msg, recv unknown msg, {payload}')
|
self.log_error('unknown event msg, %s', payload)
|
||||||
return
|
return
|
||||||
if 'arguments' not in msg:
|
if 'arguments' not in msg:
|
||||||
|
self.log_info('wrong event msg, %s', payload)
|
||||||
msg['arguments'] = []
|
msg['arguments'] = []
|
||||||
if handler:
|
if handler:
|
||||||
self.log_debug('local, on event_occurred, %s', payload)
|
self.log_debug('local, on event_occurred, %s', payload)
|
||||||
|
|||||||
@ -213,6 +213,12 @@ class MIoTSpecValueList:
|
|||||||
return item.description
|
return item.description
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_name_by_value(self, value: Any) -> Optional[str]:
|
||||||
|
for item in self.items:
|
||||||
|
if item.value == value:
|
||||||
|
return item.name
|
||||||
|
return None
|
||||||
|
|
||||||
def dump(self) -> list:
|
def dump(self) -> list:
|
||||||
return [item.dump() for item in self.items]
|
return [item.dump() for item in self.items]
|
||||||
|
|
||||||
@ -1205,6 +1211,9 @@ class _SpecModify:
|
|||||||
if isinstance(self._selected, str):
|
if isinstance(self._selected, str):
|
||||||
return await self.set_spec_async(urn=self._selected)
|
return await self.set_spec_async(urn=self._selected)
|
||||||
|
|
||||||
|
def get_prop_name(self, siid: int, piid: int) -> Optional[str]:
|
||||||
|
return self.__get_prop_item(siid=siid, piid=piid, key='name')
|
||||||
|
|
||||||
def get_prop_unit(self, siid: int, piid: int) -> Optional[str]:
|
def get_prop_unit(self, siid: int, piid: int) -> Optional[str]:
|
||||||
return self.__get_prop_item(siid=siid, piid=piid, key='unit')
|
return self.__get_prop_item(siid=siid, piid=piid, key='unit')
|
||||||
|
|
||||||
@ -1518,6 +1527,10 @@ class MIoTSpecParser:
|
|||||||
siid=service['iid'], piid=property_['iid'])
|
siid=service['iid'], piid=property_['iid'])
|
||||||
if custom_range:
|
if custom_range:
|
||||||
spec_prop.value_range = custom_range
|
spec_prop.value_range = custom_range
|
||||||
|
custom_name = self._spec_modify.get_prop_name(
|
||||||
|
siid=service['iid'], piid=property_['iid'])
|
||||||
|
if custom_name:
|
||||||
|
spec_prop.name = custom_name
|
||||||
# Parse service event
|
# Parse service event
|
||||||
for event in service.get('events', []):
|
for event in service.get('events', []):
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -58,3 +58,13 @@ urn:miot-spec-v2:device:bath-heater:0000A028:opple-acmoto:1:
|
|||||||
description: medium
|
description: medium
|
||||||
- value: 255
|
- value: 255
|
||||||
description: high
|
description: high
|
||||||
|
urn:miot-spec-v2:device:bath-heater:0000A028:mike-2:1:
|
||||||
|
prop.3.1:
|
||||||
|
name: mode-a
|
||||||
|
prop.3.11:
|
||||||
|
name: mode-b
|
||||||
|
prop.3.12:
|
||||||
|
name: mode-c
|
||||||
|
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p51:1:
|
||||||
|
prop.2.2:
|
||||||
|
name: fan-level-a
|
||||||
|
|||||||
@ -88,7 +88,7 @@ class Number(MIoTPropertyEntity, NumberEntity):
|
|||||||
if self.spec.external_unit:
|
if self.spec.external_unit:
|
||||||
self._attr_native_unit_of_measurement = self.spec.external_unit
|
self._attr_native_unit_of_measurement = self.spec.external_unit
|
||||||
# Set icon
|
# Set icon
|
||||||
if self.spec.icon:
|
if self.spec.icon and not self.device_class:
|
||||||
self._attr_icon = self.spec.icon
|
self._attr_icon = self.spec.icon
|
||||||
# Set value range
|
# Set value range
|
||||||
if self._value_range:
|
if self._value_range:
|
||||||
|
|||||||
@ -116,7 +116,7 @@ class Sensor(MIoTPropertyEntity, SensorEntity):
|
|||||||
if spec.state_class:
|
if spec.state_class:
|
||||||
self._attr_state_class = spec.state_class
|
self._attr_state_class = spec.state_class
|
||||||
# Set icon
|
# Set icon
|
||||||
if spec.icon:
|
if spec.icon and not self.device_class:
|
||||||
self._attr_icon = spec.icon
|
self._attr_icon = spec.icon
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@ -54,7 +54,8 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.components.vacuum import (
|
from homeassistant.components.vacuum import (
|
||||||
StateVacuumEntity,
|
StateVacuumEntity,
|
||||||
VacuumEntityFeature
|
VacuumEntityFeature,
|
||||||
|
VacuumActivity
|
||||||
)
|
)
|
||||||
|
|
||||||
from .miot.const import DOMAIN
|
from .miot.const import DOMAIN
|
||||||
@ -191,10 +192,47 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self) -> Optional[str]:
|
def state(self) -> Optional[str]:
|
||||||
"""Return the current state of the vacuum cleaner."""
|
"""Return the current state of the vacuum cleaner.
|
||||||
|
|
||||||
|
To fix the HA warning below:
|
||||||
|
Detected that custom integration 'xiaomi_home' is setting state
|
||||||
|
directly.Entity XXX(<class 'custom_components.xiaomi_home.vacuum
|
||||||
|
.Vacuum'>)should implement the 'activity' property and return
|
||||||
|
its state using the VacuumActivity enum.This will stop working in
|
||||||
|
Home Assistant 2026.1.
|
||||||
|
|
||||||
|
Refer to
|
||||||
|
https://developers.home-assistant.io/blog/2024/12/08/new-vacuum-state-property
|
||||||
|
|
||||||
|
There are only 6 states in VacuumActivity enum. To be compatible with
|
||||||
|
more constants, try get matching VacuumActivity enum first, return state
|
||||||
|
string as before if there is no match. In Home Assistant 2026.1, every
|
||||||
|
state should map to a VacuumActivity enum.
|
||||||
|
"""
|
||||||
|
if (activity := self.activity) is not None:
|
||||||
|
return activity
|
||||||
return self.get_map_value(
|
return self.get_map_value(
|
||||||
map_=self._status_map,
|
map_=self._status_map,
|
||||||
key=self.get_prop_value(prop=self._prop_status))
|
key=self.get_prop_value(prop=self._prop_status)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def activity(self) -> VacuumActivity | None:
|
||||||
|
"""Return the current vacuum activity."""
|
||||||
|
state_trans_map = {
|
||||||
|
'Sleep': VacuumActivity.IDLE,
|
||||||
|
'Idle': VacuumActivity.IDLE,
|
||||||
|
'Paused': VacuumActivity.PAUSED,
|
||||||
|
'Go Charging': VacuumActivity.RETURNING,
|
||||||
|
'Charging': VacuumActivity.DOCKED,
|
||||||
|
'Sweeping': VacuumActivity.CLEANING,
|
||||||
|
'Sweeping and Mopping': VacuumActivity.CLEANING,
|
||||||
|
'Mopping': VacuumActivity.CLEANING,
|
||||||
|
'Error': VacuumActivity.ERROR,
|
||||||
|
}
|
||||||
|
prop_value = self.get_prop_value(prop=self._prop_status)
|
||||||
|
state_name = self._prop_status.value_list.get_name_by_value(prop_value)
|
||||||
|
return state_trans_map.get(state_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def battery_level(self) -> Optional[int]:
|
def battery_level(self) -> Optional[int]:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user