Compare commits

...

5 Commits

Author SHA1 Message Date
skyboooox
4ef6ee4718
Merge 112c63dc23 into 001af5384a 2026-01-07 12:45:36 +08:00
Li Shuzhen
001af5384a
docs: update changelog and version to v0.4.7 (#1599)
Some checks failed
Tests / check-rule-format (push) Has been cancelled
Validate / validate-hassfest (push) Has been cancelled
Validate / validate-hacs (push) Has been cancelled
Validate / validate-lint (push) Has been cancelled
Validate / validate-setup (push) Has been cancelled
2026-01-07 10:45:07 +08:00
Li Shuzhen
c8d48625e9
Fix specs (#1567)
* fix: the playing-state property's access field of xiaomi.wifispeaker.lx04 and xiaomi.wifispeaker.lx06 (#1566)

* fix: the playing-state property's access field of xiaomi.wifispeaker.x08c

* feat: remove xiaomi.router.rd03 from UNSUPPORTED_MODELS and add era.airp.cwb03 into it

* fix: xiaomi.airc.h09h00 humidity-range unit (#1589)

* fix: add k0918.toothbrush.t700 into UNSUPPORTED_MODELS (#1585)

* fix: the playing-state property's access field of xiaomi.wifispeaker.l04m (#1596)
2026-01-07 10:04:42 +08:00
skyboooox
112c63dc23
Merge branch 'XiaoMi:main' into main 2026-01-05 10:05:01 +08:00
skyboooox
5d46e5e438 Fix sensor state class and frequency units 2026-01-05 10:04:25 +08:00
6 changed files with 125 additions and 50 deletions

View File

@ -1,4 +1,16 @@
# CHANGELOG
## v0.4.7
### Added
- Add turkish language in multi_lang.json. [#1593](https://github.com/XiaoMi/ha_xiaomi_home/pull/1593)
### Changed
- Remove unused info getting from central hub gateway. [#1574](https://github.com/XiaoMi/ha_xiaomi_home/pull/1574)
- Remove xiaomi.router.rd03 from `UNSUPPORTED_MODELS` and add era.airp.cwb03, k0918.toothbrush.t700 into it. [#1567](https://github.com/XiaoMi/ha_xiaomi_home/pull/1567)
### Fixed
- Update the BLE mesh device online state from the central hub gateway. Partially fix the BLE mesh device online state. [#1579](https://github.com/XiaoMi/ha_xiaomi_home/pull/1579)
- Add unit for xiaomi.toothbrush.p001 brush-head-left-level property. [#1588](https://github.com/XiaoMi/ha_xiaomi_home/pull/1588)
- Fix the playing-state property's access field of xiaomi.wifispeaker.lx04, xiaomi.wifispeaker.lx06, xiaomi.wifispeaker.x08c and xiaomi.wifispeaker.l04m. [#1567](https://github.com/XiaoMi/ha_xiaomi_home/pull/1567)
- Fix the MIoT-Spec-V2 of xiaomi.airc.h09h00 humidity-range unit. [#1567](https://github.com/XiaoMi/ha_xiaomi_home/pull/1567)
## v0.4.6
### Added
- Add tv-box device as the media player entity. [#1562](https://github.com/XiaoMi/ha_xiaomi_home/pull/1562)
@ -12,7 +24,7 @@
- Catch paho-mqtt subscribe error properly. [#1551](https://github.com/XiaoMi/ha_xiaomi_home/pull/1551)
- After the network resumes, keep retrying to fetch the device list until it succeeds. [#1555](https://github.com/XiaoMi/ha_xiaomi_home/pull/1555)
- Catch the http post error properly. [#1555](https://github.com/XiaoMi/ha_xiaomi_home/pull/1555)
- Fixed the format and the access field of daikin.aircondition.k2 and fix: daikin.airfresh.k33 string value properties. [#1561](https://github.com/XiaoMi/ha_xiaomi_home/pull/1561)
- Fix the format and the access field of daikin.aircondition.k2 and daikin.airfresh.k33 string value properties. [#1561](https://github.com/XiaoMi/ha_xiaomi_home/pull/1561)
## v0.4.5
### Changed

View File

@ -25,7 +25,7 @@
"cryptography",
"psutil"
],
"version": "v0.4.6",
"version": "v0.4.7",
"zeroconf": [
"_miot-central._tcp.local."
]

View File

@ -90,8 +90,9 @@ SUPPORTED_PLATFORMS: list = [
UNSUPPORTED_MODELS: list = [
'chuangmi.ir.v2',
'era.airp.cwb03',
'hmpace.motion.v6nfc',
'xiaomi.router.rd03'
'k0918.toothbrush.t700'
]
DEFAULT_CLOUD_SERVER: str = 'cn'

View File

@ -682,58 +682,66 @@ class MIoTDevice:
def unit_convert(self, spec_unit: str) -> Optional[str]:
"""Convert MIoT unit to Home Assistant unit.
25/01/20: All online prop unit statistical tables: unit, quantity.
2026/01/06: property unit statistics of the latest released
MIoT-Spec-V2 for all device models: unit, quantity.
{
"no_unit": 148499,
"percentage": 10042,
"kelvin": 1895,
"rgb": 772, // color
"celsius": 5762,
"none": 16106,
"hours": 1540,
"minutes": 5061,
"ms": 27,
"watt": 216,
"arcdegrees": 159,
"ppm": 177,
"μg/m3": 106,
"days": 571,
"seconds": 2749,
"percentage": 12074,
"none": 11857,
"minutes": 5707,
"celsius": 5767,
"seconds": 3062,
"kelvin": 2511,
"hours": 1380,
"days": 615,
"rgb": 752, // color
"L": 379,
"mg/m3": 335,
"ppm": 182,
"watt": 246,
"arcdegrees": 130,
"μg/m3": 117,
"kWh": 149,
"ms": 108,
"pascal": 108,
"lux": 100,
"V": 59,
"m": 45,
"A": 36,
"mL": 30,
"arcdegress": 25,
"mA": 26,
"bpm": 21, // realtime-heartrate
"B/s": 21,
"pascal": 110,
"mg/m3": 339,
"lux": 125,
"kWh": 124,
"mv": 2,
"V": 38,
"A": 29,
"mV": 4,
"L": 352,
"m": 37,
"毫摩尔每升": 2, // blood-sugar, cholesterol
"mmol/L": 1, // urea
"weeks": 26,
"meter": 3,
"dB": 26,
"hour": 14,
"calorie": 19, // 1 cal = 4.184 J
"ppb": 3,
"arcdegress": 30,
"bpm": 4, // realtime-heartrate
"gram": 7,
"km/h": 9,
"W": 1,
"m3/h": 2,
"kilopascal": 1,
"mL": 4,
"weeks": 18,
"dB": 17,
"calorie": 18, // 1 cal = 4.184 J
"metre": 15,
"hour": 11,
"cm": 12,
"gram": 8,
"km/h": 8,
"mV": 9,
"times": 4, // exercise-count
"kCal": 4,
"mmHg": 4,
"pcs": 3,
"meter": 3,
"kW": 2,
"KByte/s": 2,
"毫摩尔每升": 2, // blood-sugar, cholesterol
"m3/h": 2,
"ppb": 2,
"mv": 2,
"w": 1,
"bar": 1,
"megapascal": 1,
"kB": 1,
"mmol/L": 1, // urea
"min/km": 1,
"kilopascal": 1,
"liter": 1,
"cm": 3,
"mA": 2,
"kilogram": 2,
"kcal/d": 2, // basal-metabolism
"times": 1 // exercise-count
"W": 1
}
"""
unit_map = {
@ -804,6 +812,25 @@ class MIoTDevice:
except Exception: # pylint: disable=broad-except
unit_map['μS/cm'] = 'μS/cm'
unit_map['mWh'] = 'mWh'
# Handle UnitOfFrequency and UnitOfRotationalSpeed separately since
# they might not be available in all HA versions
try:
# pylint: disable=import-outside-toplevel
from homeassistant.const import ( # type: ignore
UnitOfFrequency,
UnitOfRotationalSpeed,
)
unit_map['Hz'] = UnitOfFrequency.HERTZ
unit_map['hz'] = UnitOfFrequency.HERTZ
unit_map['RPM'] = UnitOfRotationalSpeed.REVOLUTIONS_PER_MINUTE
unit_map['rpm'] = UnitOfRotationalSpeed.REVOLUTIONS_PER_MINUTE
unit_map['r/min'] = UnitOfRotationalSpeed.REVOLUTIONS_PER_MINUTE
except Exception: # pylint: disable=broad-except
unit_map['Hz'] = 'Hz'
unit_map['hz'] = 'Hz'
unit_map['RPM'] = 'RPM'
unit_map['rpm'] = 'rpm'
unit_map['r/min'] = 'r/min'
return unit_map.get(spec_unit, None)

View File

@ -54,6 +54,9 @@ urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c35:1:
prop.10.6:
unit: none
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c35:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c35:1
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-h09h00:4:
prop.10.6:
unit: none
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-h40h00:1:
prop.10.6:
unit: none
@ -499,6 +502,26 @@ urn:miot-spec-v2:device:safe-box:0000A042:loock-v1:1:
prop.5.1:
name: contact-state
expr: (src_value!=1)
urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l04m:2:
prop.3.1:
access:
- read
- notify
urn:miot-spec-v2:device:speaker:0000A015:xiaomi-lx04:2:
prop.3.1:
access:
- read
- notify
urn:miot-spec-v2:device:speaker:0000A015:xiaomi-lx06:2:
prop.3.1:
access:
- read
- notify
urn:miot-spec-v2:device:speaker:0000A015:xiaomi-x08c:2:
prop.2.1:
access:
- read
- notify
urn:miot-spec-v2:device:speaker:0000A015:xiaomi-x08e:1:
prop.3.1:
name: playing-state-a

View File

@ -52,7 +52,11 @@ from typing import Any
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.sensor import SensorEntity, SensorDeviceClass
from homeassistant.components.sensor import (
SensorEntity,
SensorDeviceClass,
SensorStateClass,
)
from homeassistant.components.sensor import DEVICE_CLASS_UNITS
from .miot.miot_device import MIoTDevice, MIoTPropertyEntity
@ -102,6 +106,8 @@ class Sensor(MIoTPropertyEntity, SensorEntity):
self._attr_device_class = spec.device_class
if spec.external_unit:
self._attr_native_unit_of_measurement = spec.external_unit
elif spec.unit and spec.unit not in {'none', 'no_unit'}:
self._attr_native_unit_of_measurement = spec.unit
else:
# device_class is not empty but unit is empty.
# Set the default unit according to device_class.
@ -115,6 +121,12 @@ class Sensor(MIoTPropertyEntity, SensorEntity):
# Set state_class
if spec.state_class:
self._attr_state_class = spec.state_class
elif (
spec.value_range
or spec.format_ in (int, float)
or self._attr_native_unit_of_measurement
):
self._attr_state_class = SensorStateClass.MEASUREMENT
# Set icon
if spec.icon and not self.device_class:
self._attr_icon = spec.icon