6 Commits

Author SHA1 Message Date
d65fe32a98 docs: update changelog and version to v0.1.5b0 (#563)
* style: code format

* docs: update changelog and version to v0.1.5b0

* docs: update changelog
2025-01-03 21:08:39 +08:00
50be2c5df9 doc: make git update guide more accurate (#561)
* Improve installation guide

* Improve installation guide (zh)
2025-01-03 20:45:00 +08:00
b75cafb184 fix: limit *light.mode count (value-range) (#535)
* feat: spec filter add lemesh.switch.sw3f13 indicator-light.mode

* feat: limit mode count (value-range)

* revert: spec-filter.json

* fix: fix judgment logic

* style: remove unuse code

* style: change light log level
2025-01-03 20:43:15 +08:00
5438698a6e feat:add missing parameter state_class (#101)
* feat: add state_class for sensor

* feat: add optional state_class and unit_of_measurement for properties

* feat:add support for state_class and unit process

* style: fix pylint format

* style: fix pylint format

* sytle: change logic to suit conversation

---------

Co-authored-by: LiShuzhen <SusanPhevos@gmail.com>
2025-01-03 20:42:34 +08:00
da90e099d1 fix: update miot cloud raise error msg (#551) 2025-01-03 19:00:11 +08:00
ted
2703d68920 docs: fix table header misplacement (#554)
fix table header misplacement
2025-01-03 18:59:24 +08:00
10 changed files with 106 additions and 14 deletions

View File

@ -1,5 +1,15 @@
# CHANGELOG
## v0.1.5b0
### Added
- Add missing parameter state_class [#101](https://github.com/XiaoMi/ha_xiaomi_home/pull/101)
### Changed
- Make git update guide more accurate [#561](https://github.com/XiaoMi/ha_xiaomi_home/pull/561)
### Fixed
- Limit *light.mode count (value-range) [#535](https://github.com/XiaoMi/ha_xiaomi_home/pull/535)
- Update miot cloud raise error msg [#551](https://github.com/XiaoMi/ha_xiaomi_home/pull/551)
- Fix table header misplacement [#554](https://github.com/XiaoMi/ha_xiaomi_home/pull/554)
## v0.1.4
### Added
- Refactor miot network, add network detection logic, improve devices filter logic. [458](https://github.com/XiaoMi/ha_xiaomi_home/pull/458) [#191](https://github.com/XiaoMi/ha_xiaomi_home/pull/191)

View File

@ -26,6 +26,7 @@ For example, update to version v1.0.0
```bash
cd config/ha_xiaomi_home
git fetch
git checkout v1.0.0
./install.sh /config
```
@ -140,7 +141,7 @@ In MIoT-Spec-V2 protocol, a product is defined as a device. A device contains se
- Property
| format | access | value-list | value-range | Entity in Home Assistant |
| access | format | value-list | value-range | Entity in Home Assistant |
| ------------ | --------------------- | ------------ | ----------- | ------------------------ |
| writable | string | - | - | Text |
| writable | bool | - | - | Switch |

View File

@ -95,6 +95,7 @@ async def async_setup_entry(
class Light(MIoTServiceEntity, LightEntity):
"""Light entities for Xiaomi Home."""
# pylint: disable=unused-argument
_VALUE_RANGE_MODE_COUNT_MAX = 30
_prop_on: Optional[MIoTSpecProperty]
_prop_brightness: Optional[MIoTSpecProperty]
_prop_color_temp: Optional[MIoTSpecProperty]
@ -147,13 +148,13 @@ class Light(MIoTServiceEntity, LightEntity):
self._attr_supported_features |= LightEntityFeature.EFFECT
self._prop_mode = prop
else:
_LOGGER.error(
_LOGGER.info(
'invalid brightness format, %s', self.entity_id)
continue
# color-temperature
if prop.name == 'color-temperature':
if not isinstance(prop.value_range, dict):
_LOGGER.error(
_LOGGER.info(
'invalid color-temperature value_range format, %s',
self.entity_id)
continue
@ -179,16 +180,29 @@ class Light(MIoTServiceEntity, LightEntity):
for item in prop.value_list}
elif isinstance(prop.value_range, dict):
mode_list = {}
for value in range(
prop.value_range['min'], prop.value_range['max']):
mode_list[value] = f'{value}'
if (
int((
prop.value_range['max']
- prop.value_range['min']
) / prop.value_range['step'])
> self._VALUE_RANGE_MODE_COUNT_MAX
):
_LOGGER.info(
'too many mode values, %s, %s, %s',
self.entity_id, prop.name, prop.value_range)
else:
for value in range(
prop.value_range['min'],
prop.value_range['max'],
prop.value_range['step']):
mode_list[value] = f'mode {value}'
if mode_list:
self._mode_list = mode_list
self._attr_effect_list = list(self._mode_list.values())
self._attr_supported_features |= LightEntityFeature.EFFECT
self._prop_mode = prop
else:
_LOGGER.error('invalid mode format, %s', self.entity_id)
_LOGGER.info('invalid mode format, %s', self.entity_id)
continue
if not self._attr_supported_color_modes:

View File

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

View File

@ -166,7 +166,7 @@ class MIoTOauthClient:
key in res_obj['result']
for key in ['access_token', 'refresh_token', 'expires_in'])
):
raise MIoTOauthError(f'invalid http response, {http_res.text}')
raise MIoTOauthError(f'invalid http response, {res_str}')
return {
**res_obj['result'],

View File

@ -515,9 +515,15 @@ class MIoTDevice:
prop.icon = self.icon_convert(prop.unit)
device_class = SPEC_PROP_TRANS_MAP['properties'][prop_name][
'device_class']
prop.platform = device_class
return {'platform': platform, 'device_class': device_class}
result = {'platform': platform, 'device_class': device_class}
# optional:
if 'optional' in SPEC_PROP_TRANS_MAP['properties'][prop_name]:
optional = SPEC_PROP_TRANS_MAP['properties'][prop_name]['optional']
if 'state_class' in optional:
result['state_class'] = optional['state_class']
if not prop.unit and 'unit_of_measurement' in optional:
result['unit_of_measurement'] = optional['unit_of_measurement']
return result
def spec_transform(self) -> None:
"""Parse service, property, event, action from device spec."""
@ -544,6 +550,13 @@ class MIoTDevice:
if prop_entity:
prop.platform = prop_entity['platform']
prop.device_class = prop_entity['device_class']
if 'state_class' in prop_entity:
prop.state_class = prop_entity['state_class']
if 'unit_of_measurement' in prop_entity:
prop.external_unit = self.unit_convert(
prop_entity['unit_of_measurement'])
prop.icon = self.icon_convert(
prop_entity['unit_of_measurement'])
# general conversion
if not prop.platform:
if prop.writable:

View File

@ -79,6 +79,7 @@ class MIoTSpecBase:
# External params
platform: str
device_class: Any
state_class: Any
icon: str
external_unit: Any
@ -96,6 +97,7 @@ class MIoTSpecBase:
self.platform = None
self.device_class = None
self.state_class = None
self.icon = None
self.external_unit = None

View File

@ -46,8 +46,16 @@ off Xiaomi or its affiliates' products.
Conversion rules of MIoT-Spec-V2 instance to Home Assistant entity.
"""
from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.sensor import SensorStateClass
from homeassistant.components.event import EventDeviceClass
from homeassistant.const import (
UnitOfEnergy,
UnitOfPower,
UnitOfElectricCurrent,
UnitOfElectricPotential,
)
# pylint: disable=pointless-string-statement
"""SPEC_DEVICE_TRANS_MAP
{
@ -325,7 +333,11 @@ SPEC_SERVICE_TRANS_MAP: dict[str, dict | str] = {
'properties': {
'<property instance name>':{
'device_class': str,
'entity': str
'entity': str,
'optional':{
'state_class': str,
'unit_of_measurement': str
}
}
}
}
@ -381,7 +393,11 @@ SPEC_PROP_TRANS_MAP: dict[str, dict | str] = {
},
'voltage': {
'device_class': SensorDeviceClass.VOLTAGE,
'entity': 'sensor'
'entity': 'sensor',
'optional': {
'state_class': SensorStateClass.MEASUREMENT,
'unit_of_measurement': UnitOfElectricPotential.VOLT
}
},
'illumination': {
'device_class': SensorDeviceClass.ILLUMINANCE,
@ -391,6 +407,38 @@ SPEC_PROP_TRANS_MAP: dict[str, dict | str] = {
'device_class': SensorDeviceClass.DURATION,
'entity': 'sensor'
},
'electric-power': {
'device_class': SensorDeviceClass.POWER,
'entity': 'sensor',
'optional': {
'state_class': SensorStateClass.MEASUREMENT,
'unit_of_measurement': UnitOfPower.WATT
}
},
'electric-current': {
'device_class': SensorDeviceClass.CURRENT,
'entity': 'sensor',
'optional': {
'state_class': SensorStateClass.MEASUREMENT,
'unit_of_measurement': UnitOfElectricCurrent.AMPERE
}
},
'power-consumption': {
'device_class': SensorDeviceClass.ENERGY,
'entity': 'sensor',
'optional': {
'state_class': SensorStateClass.TOTAL_INCREASING,
'unit_of_measurement': UnitOfEnergy.KILO_WATT_HOUR
}
},
'total-battery': {
'device_class': SensorDeviceClass.ENERGY,
'entity': 'sensor',
'optional': {
'state_class': SensorStateClass.TOTAL_INCREASING,
'unit_of_measurement': UnitOfEnergy.KILO_WATT_HOUR
}
},
'has-someone-duration': 'no-one-determine-time',
'no-one-duration': 'no-one-determine-time'
}

View File

@ -106,6 +106,9 @@ class Sensor(MIoTPropertyEntity, SensorEntity):
# Set icon
if spec.icon:
self._attr_icon = spec.icon
# Set state_class
if spec.state_class:
self._attr_state_class = spec.state_class
@property
def native_value(self) -> Any:

View File

@ -26,6 +26,7 @@ cd ha_xiaomi_home
```bash
cd config/ha_xiaomi_home
git fetch
git checkout v1.0.0
./install.sh /config
```