mirror of
https://github.com/XiaoMi/ha_xiaomi_home.git
synced 2025-10-27 23:03:12 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c04fa542a3 | ||
|
|
fbddaf80a7 | ||
|
|
a11c3e2fda | ||
|
|
739998211e | ||
|
|
ec833b6539 | ||
|
|
f2200ba003 | ||
|
|
073cdf2dcb | ||
|
|
0f65635342 | ||
|
|
947169f18d | ||
|
|
65a7a6d22a | ||
|
|
c29f7eecbd | ||
|
|
58c671483e |
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,4 +1,27 @@
|
||||
# CHANGELOG
|
||||
## v0.4.3
|
||||
### Changed
|
||||
- Remove `VacuumEntityFeature.BATTERY` from the vacuum entity. [#1433](https://github.com/XiaoMi/ha_xiaomi_home/pull/1433)
|
||||
- Subscribe the proxy gateway child device up messages even though the device is offline. [#1393](https://github.com/XiaoMi/ha_xiaomi_home/pull/1393)
|
||||
### Fixed
|
||||
- Fix the integer value step. [#1388](https://github.com/XiaoMi/ha_xiaomi_home/pull/1388)
|
||||
- Fix the contact-state property value format. [#1387](https://github.com/XiaoMi/ha_xiaomi_home/pull/1387)
|
||||
- Fix the MIoT-Spec-V2 of xiaomi.airc.rr0r00 swing mode and hyd.airer.lyjpro current-position. [#1394](https://github.com/XiaoMi/ha_xiaomi_home/pull/1394)
|
||||
- Fix roidmi.vacuum.v60 siid=2 aiid=3 out field format.
|
||||
- Ignore unsupported properties of xiaomi.wifispeaker.l15a and 759413.aircondition.iez.
|
||||
- Add an alongside button entity for xiaomi.wifispeaker.l05b play action.
|
||||
- Add zhimi.fan.za1 fan mode description in zh_Hans.
|
||||
- Fix the error reported by pylint-4.0.0. [#1455](https://github.com/XiaoMi/ha_xiaomi_home/pull/1455)
|
||||
|
||||
## v0.4.2
|
||||
### Changed
|
||||
- Set the battery service's start-charge action as the fallback action to support RETURN_HOME feature of the vacuum entity. [#1344](https://github.com/XiaoMi/ha_xiaomi_home/pull/1344)
|
||||
### Fixed
|
||||
- Correct the property value format after expression calculation. [#1366](https://github.com/XiaoMi/ha_xiaomi_home/pull/1366)
|
||||
- Fix the MIoT-Spec-V2 of xiaomi.fan.p70 and xiaomi.fan.p76 fan level, xiaomi.airc.rr0r00 and xiaomi.airc.h43h00 humidity-range, and zhimi.humidifier.ca4 water level. [#1367](https://github.com/XiaoMi/ha_xiaomi_home/pull/1367)
|
||||
- Ignore the unsupported model hmpace.motion.v6nfc.
|
||||
- Delete all unsupported MIoT-Spec-V2 instances of narwa.vacuum.001 and narwa.vacuum.ax11. [#1355](https://github.com/XiaoMi/ha_xiaomi_home/pull/1355)
|
||||
|
||||
## v0.4.1
|
||||
### Changed
|
||||
- The setting option "Cover closed position" in CONFIGURE is changed to "Cover dead zone width". [#1301](https://github.com/XiaoMi/ha_xiaomi_home/pull/1301)
|
||||
|
||||
@@ -70,8 +70,8 @@ async def async_setup_entry(
|
||||
for miot_device in device_list:
|
||||
if miot_device.miot_client.display_binary_bool:
|
||||
for prop in miot_device.prop_list.get('binary_sensor', []):
|
||||
new_entities.append(BinarySensor(
|
||||
miot_device=miot_device, spec=prop))
|
||||
new_entities.append(
|
||||
BinarySensor(miot_device=miot_device, spec=prop))
|
||||
|
||||
if new_entities:
|
||||
async_add_entities(new_entities)
|
||||
@@ -90,7 +90,7 @@ class BinarySensor(MIoTPropertyEntity, BinarySensorEntity):
|
||||
def is_on(self) -> bool:
|
||||
"""On/Off state. True if the binary sensor is on, False otherwise."""
|
||||
if self.spec.name == 'contact-state':
|
||||
return self._value is False
|
||||
return bool(self._value) is False
|
||||
elif self.spec.name == 'occupancy-status':
|
||||
return bool(self._value)
|
||||
return self._value is True
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"cryptography",
|
||||
"psutil"
|
||||
],
|
||||
"version": "v0.4.1",
|
||||
"version": "v0.4.3",
|
||||
"zeroconf": [
|
||||
"_miot-central._tcp.local."
|
||||
]
|
||||
|
||||
@@ -89,6 +89,7 @@ SUPPORTED_PLATFORMS: list = [
|
||||
|
||||
UNSUPPORTED_MODELS: list = [
|
||||
'chuangmi.ir.v2',
|
||||
'hmpace.motion.v6nfc',
|
||||
'xiaomi.router.rd03'
|
||||
]
|
||||
|
||||
|
||||
@@ -1374,10 +1374,13 @@ class MIoTClient:
|
||||
"""Update cloud devices.
|
||||
NOTICE: This function will operate the cloud_list
|
||||
"""
|
||||
# MIoT cloud service may not publish the online state updating message
|
||||
# MIoT cloud may not publish the online state updating message
|
||||
# for the BLE device. Assume that all BLE devices are online.
|
||||
# MIoT cloud does not publish the online state updating message for the
|
||||
# child device under the proxy gateway (eg, VRF air conditioner
|
||||
# controller). Assume that all proxy gateway child devices are online.
|
||||
for did, info in cloud_list.items():
|
||||
if did.startswith('blt.'):
|
||||
if did.startswith('blt.') or did.startswith('proxy.'):
|
||||
info['online'] = True
|
||||
for did, info in self._device_list_cache.items():
|
||||
if filter_dids and did not in filter_dids:
|
||||
|
||||
@@ -1108,6 +1108,8 @@ class MIoTServiceEntity(Entity):
|
||||
):
|
||||
continue
|
||||
value: Any = prop.value_format(params['value'])
|
||||
value = prop.eval_expr(value)
|
||||
value = prop.value_format(value)
|
||||
self._prop_value_map[prop] = value
|
||||
if prop in self._prop_changed_subs:
|
||||
self._prop_changed_subs[prop](prop, value)
|
||||
@@ -1279,8 +1281,9 @@ class MIoTPropertyEntity(Entity):
|
||||
|
||||
def __on_value_changed(self, params: dict, ctx: Any) -> None:
|
||||
_LOGGER.debug('property changed, %s', params)
|
||||
self._value = self.spec.value_format(params['value'])
|
||||
self._value = self.spec.eval_expr(self._value)
|
||||
value: Any = self.spec.value_format(params['value'])
|
||||
value = self.spec.eval_expr(value)
|
||||
self._value = self.spec.value_format(value)
|
||||
if not self._pending_write_ha_state_timer:
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
@@ -513,6 +513,7 @@ class _MipsClient(ABC):
|
||||
"""
|
||||
self.__thread_check()
|
||||
if not self._mqtt or not self._mqtt.is_connected():
|
||||
self.log_error(f'mips sub when not connected, {topic}')
|
||||
return
|
||||
try:
|
||||
if topic not in self._mips_sub_pending_map:
|
||||
@@ -531,6 +532,7 @@ class _MipsClient(ABC):
|
||||
"""
|
||||
self.__thread_check()
|
||||
if not self._mqtt or not self._mqtt.is_connected():
|
||||
self.log_debug(f'mips unsub when not connected, {topic}')
|
||||
return
|
||||
try:
|
||||
result, mid = self._mqtt.unsubscribe(topic=topic)
|
||||
@@ -639,6 +641,7 @@ class _MipsClient(ABC):
|
||||
_LOGGER.error('__on_connect, but mqtt is None')
|
||||
return
|
||||
if not self._mqtt.is_connected():
|
||||
_LOGGER.error('__on_connect, but mqtt is disconnected')
|
||||
return
|
||||
self.log_info(f'mips connect, {flags}, {rc}, {props}')
|
||||
self.__reset_reconnect_time()
|
||||
@@ -995,9 +998,11 @@ class MipsCloudClient(_MipsClient):
|
||||
did, MIoTDeviceState.ONLINE if msg['event'] == 'online'
|
||||
else MIoTDeviceState.OFFLINE, ctx)
|
||||
|
||||
if did.startswith('blt.'):
|
||||
# MIoT cloud may not publish BLE device online/offline state message.
|
||||
# Do not subscribe BLE device online/offline state.
|
||||
if did.startswith('blt.') or did.startswith('proxy.'):
|
||||
# MIoT cloud may not publish BLE device or proxy gateway child device
|
||||
# online/offline state message.
|
||||
# Do not subscribe BLE device or proxy gateway child device
|
||||
# online/offline state.
|
||||
return True
|
||||
return self.__reg_broadcast_external(
|
||||
topic=topic, handler=on_state_msg, handler_ctx=handler_ctx)
|
||||
|
||||
@@ -601,7 +601,10 @@ class MIoTSpecProperty(_MIoTSpecBase):
|
||||
if value is None:
|
||||
return None
|
||||
if self.format_ == int:
|
||||
return int(round(value))
|
||||
if self.value_range is None:
|
||||
return int(round(value))
|
||||
return int(
|
||||
round(value / self.value_range.step) * self.value_range.step)
|
||||
if self.format_ == float:
|
||||
return round(value, self.precision)
|
||||
if self.format_ == bool:
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
"service:003:property:001:valuelist:001": "Dry"
|
||||
}
|
||||
},
|
||||
"urn:miot-spec-v2:device:fan:0000A005:zhimi-za1": {
|
||||
"zh-Hans": {
|
||||
"service:002:property:005:valuelist:000": "自然风",
|
||||
"service:002:property:005:valuelist:001": "直吹风"
|
||||
}
|
||||
},
|
||||
"urn:miot-spec-v2:device:gateway:0000A019:xiaomi-hub1": {
|
||||
"de": {
|
||||
"service:001": "Geräteinformationen",
|
||||
@@ -274,13 +280,13 @@
|
||||
"service:002:property:002": "Air Conditioner Mode",
|
||||
"service:004": "Air Conditioner"
|
||||
},
|
||||
"zh_cn": {
|
||||
"zh-Hans": {
|
||||
"service:002": "地暖",
|
||||
"service:004": "空调"
|
||||
}
|
||||
},
|
||||
"urn:miot-spec-v2:device:vacuum:0000A006:ijai-v1": {
|
||||
"zh_cn": {
|
||||
"zh-Hans": {
|
||||
"service:007:property:005:valuelist:000": "安静",
|
||||
"service:007:property:005:valuelist:001": "标准",
|
||||
"service:007:property:005:valuelist:002": "中档",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,9 @@
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:090615-ktf:
|
||||
services:
|
||||
- '4'
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:759413-iez:
|
||||
properties:
|
||||
- '2.3'
|
||||
urn:miot-spec-v2:device:air-purifier:0000A007:zhimi-ma4:
|
||||
properties:
|
||||
- 9.*
|
||||
@@ -44,7 +47,23 @@ urn:miot-spec-v2:device:motion-sensor:0000A014:xiaomi-pir1:
|
||||
services:
|
||||
- '1'
|
||||
- '5'
|
||||
urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l15a:
|
||||
properties:
|
||||
- '3.3'
|
||||
- '6.1'
|
||||
- '6.2'
|
||||
- '6.3'
|
||||
- '6.4'
|
||||
urn:miot-spec-v2:device:thermostat:0000A031:tofan-wk01:
|
||||
services:
|
||||
- '2'
|
||||
- '4'
|
||||
urn:miot-spec-v2:device:vacuum:0000A006:narwa-001:
|
||||
services:
|
||||
- '*'
|
||||
urn:miot-spec-v2:device:vacuum:0000A006:narwa-ax11:
|
||||
services:
|
||||
- '*'
|
||||
urn:miot-spec-v2:device:vacuum:0000A006:roidmi-v60:
|
||||
actions:
|
||||
- '2.3'
|
||||
|
||||
@@ -22,6 +22,10 @@ urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c35:2: urn:miot-spec-v2:
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-h40h00:1:
|
||||
prop.10.6:
|
||||
unit: none
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-h43h00:1:
|
||||
prop.10.6:
|
||||
unit: none
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-h43h00:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-h43h00:1
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:1:
|
||||
prop.10.6:
|
||||
unit: none
|
||||
@@ -41,6 +45,24 @@ urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-mt0:1:
|
||||
prop.10.6:
|
||||
unit: none
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-mt0:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-mt0:1
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:1:
|
||||
prop.10.6:
|
||||
unit: none
|
||||
prop.3.12:
|
||||
name: vertical-swing-left-up
|
||||
prop.3.13:
|
||||
name: vertical-swing-left-down
|
||||
prop.3.14:
|
||||
name: vertical-swing-right-up
|
||||
prop.3.15:
|
||||
name: vertical-swing-right-down
|
||||
prop.3.20:
|
||||
name: horizontal-swing-left
|
||||
prop.3.22:
|
||||
name: horizontal-swing-right
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:1
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:3: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:1
|
||||
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:4: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-rr0r00:1
|
||||
urn:miot-spec-v2:device:air-monitor:0000A008:cgllc-cgd1st:1:
|
||||
prop.3.7:
|
||||
value-range:
|
||||
@@ -62,6 +84,8 @@ urn:miot-spec-v2:device:airer:0000A00D:hyd-lyjpro:1:
|
||||
name: target-position-a
|
||||
prop.2.9:
|
||||
name: target-position-b
|
||||
prop.2.11:
|
||||
expr: (100-src_value)
|
||||
urn:miot-spec-v2:device:airer:0000A00D:hyd-znlyj5:1:
|
||||
prop.2.3:
|
||||
value-range:
|
||||
@@ -130,6 +154,12 @@ urn:miot-spec-v2:device:fan:0000A005:xiaomi-p51:1:
|
||||
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p69:1:0000D062:
|
||||
prop.2.4:
|
||||
name: fan-level-a
|
||||
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p70:1:0000D062:
|
||||
prop.2.4:
|
||||
name: fan-level-a
|
||||
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p76:1:0000D062:
|
||||
prop.2.4:
|
||||
name: fan-level-a
|
||||
urn:miot-spec-v2:device:fan:0000A005:zhimi-sa1:3:
|
||||
prop.2.2:
|
||||
name: fan-level-a
|
||||
@@ -175,6 +205,10 @@ urn:miot-spec-v2:device:hood:0000A01B:cykj-jyj22:2: urn:miot-spec-v2:device:hood
|
||||
urn:miot-spec-v2:device:hood:0000A01B:cykj-jyj22:3:
|
||||
prop.3.1:
|
||||
name: on-ventilation
|
||||
urn:miot-spec-v2:device:humidifier:0000A00E:zhimi-ca4:2:
|
||||
prop.2.7:
|
||||
unit: percentage
|
||||
expr: round(src_value*0.83)
|
||||
urn:miot-spec-v2:device:kettle:0000A009:yunmi-r3:1:
|
||||
prop.3.1:
|
||||
unit: ppm
|
||||
|
||||
@@ -167,8 +167,8 @@ SPEC_DEVICE_TRANS_MAP: dict = {
|
||||
},
|
||||
'battery': {
|
||||
'required': {
|
||||
'properties': {
|
||||
'battery-level': {'read'}
|
||||
'actions': {
|
||||
'start-charge'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ MIoT redirect web pages.
|
||||
import os
|
||||
import asyncio
|
||||
|
||||
_template = ''
|
||||
web_template = ''
|
||||
|
||||
|
||||
def _load_page_template():
|
||||
@@ -57,18 +57,18 @@ def _load_page_template():
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
'resource/oauth_redirect_page.html')
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
global _template
|
||||
_template = f.read()
|
||||
global web_template
|
||||
web_template = f.read()
|
||||
|
||||
|
||||
async def oauth_redirect_page(
|
||||
title: str, content: str, button: str, success: bool
|
||||
) -> str:
|
||||
"""Return oauth redirect page."""
|
||||
if _template == '':
|
||||
if web_template == '':
|
||||
await asyncio.get_running_loop().run_in_executor(
|
||||
None, _load_page_template)
|
||||
web_page = _template.replace('TITLE_PLACEHOLDER', title)
|
||||
web_page = web_template.replace('TITLE_PLACEHOLDER', title)
|
||||
web_page = web_page.replace('CONTENT_PLACEHOLDER', content)
|
||||
web_page = web_page.replace('BUTTON_PLACEHOLDER', button)
|
||||
web_page = web_page.replace(
|
||||
|
||||
@@ -90,7 +90,6 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
|
||||
# pylint: disable=unused-argument
|
||||
_prop_status: Optional[MIoTSpecProperty]
|
||||
_prop_fan_level: Optional[MIoTSpecProperty]
|
||||
_prop_battery_level: Optional[MIoTSpecProperty]
|
||||
_prop_status_cleaning: Optional[list[int]]
|
||||
_prop_status_docked: Optional[list[int]]
|
||||
_prop_status_paused: Optional[list[int]]
|
||||
@@ -117,7 +116,6 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
|
||||
|
||||
self._prop_status = None
|
||||
self._prop_fan_level = None
|
||||
self._prop_battery_level = None
|
||||
self._prop_status_cleaning = []
|
||||
self._prop_status_docked = []
|
||||
self._prop_status_paused = []
|
||||
@@ -180,9 +178,6 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
|
||||
self._attr_fan_speed_list = list(self._fan_level_map.values())
|
||||
self._attr_supported_features |= VacuumEntityFeature.FAN_SPEED
|
||||
self._prop_fan_level = prop
|
||||
elif prop.name == 'battery-level':
|
||||
self._attr_supported_features |= VacuumEntityFeature.BATTERY
|
||||
self._prop_battery_level = prop
|
||||
# action
|
||||
for action in entity_data.actions:
|
||||
if action.name == 'start-sweep':
|
||||
@@ -203,6 +198,16 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
|
||||
self._attr_supported_features |= VacuumEntityFeature.LOCATE
|
||||
self._action_identify = action
|
||||
|
||||
# Use start-charge from battery service as fallback
|
||||
# if stop-and-gocharge is not available
|
||||
if self._action_stop_and_gocharge is None:
|
||||
for action in entity_data.actions:
|
||||
if action.name == 'start-charge':
|
||||
self._attr_supported_features |= (
|
||||
VacuumEntityFeature.RETURN_HOME)
|
||||
self._action_stop_and_gocharge = action
|
||||
break
|
||||
|
||||
async def async_start(self) -> None:
|
||||
"""Start or resume the cleaning task."""
|
||||
if self._prop_status is not None:
|
||||
@@ -241,11 +246,6 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
|
||||
"""Name of the vacuum entity."""
|
||||
return self._device_name
|
||||
|
||||
@property
|
||||
def battery_level(self) -> Optional[int]:
|
||||
"""The current battery level of the vacuum cleaner."""
|
||||
return self.get_prop_value(prop=self._prop_battery_level)
|
||||
|
||||
@property
|
||||
def fan_speed(self) -> Optional[str]:
|
||||
"""The current fan speed of the vacuum cleaner."""
|
||||
|
||||
Reference in New Issue
Block a user