diff --git a/CHANGELOG.md b/CHANGELOG.md index 75c7caf..1093ab5 100644 --- a/CHANGELOG.md +++ b/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) diff --git a/custom_components/xiaomi_home/binary_sensor.py b/custom_components/xiaomi_home/binary_sensor.py index 8019104..b2d00b6 100644 --- a/custom_components/xiaomi_home/binary_sensor.py +++ b/custom_components/xiaomi_home/binary_sensor.py @@ -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 diff --git a/custom_components/xiaomi_home/manifest.json b/custom_components/xiaomi_home/manifest.json index e444e30..0a9ada4 100644 --- a/custom_components/xiaomi_home/manifest.json +++ b/custom_components/xiaomi_home/manifest.json @@ -25,7 +25,7 @@ "cryptography", "psutil" ], - "version": "v0.4.1", + "version": "v0.4.3", "zeroconf": [ "_miot-central._tcp.local." ] diff --git a/custom_components/xiaomi_home/miot/const.py b/custom_components/xiaomi_home/miot/const.py index 8a0e44b..2b8be01 100644 --- a/custom_components/xiaomi_home/miot/const.py +++ b/custom_components/xiaomi_home/miot/const.py @@ -89,6 +89,7 @@ SUPPORTED_PLATFORMS: list = [ UNSUPPORTED_MODELS: list = [ 'chuangmi.ir.v2', + 'hmpace.motion.v6nfc', 'xiaomi.router.rd03' ] diff --git a/custom_components/xiaomi_home/miot/miot_client.py b/custom_components/xiaomi_home/miot/miot_client.py index 03b7b84..4a3a396 100644 --- a/custom_components/xiaomi_home/miot/miot_client.py +++ b/custom_components/xiaomi_home/miot/miot_client.py @@ -1481,10 +1481,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: diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index 2ed9c35..4c590bb 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -1154,7 +1154,9 @@ class MIoTServiceEntity(Entity): for prop in self.entity_data.props: if prop.iid != params["piid"] or prop.service.iid != params["siid"]: continue - value: Any = prop.value_format(params["value"]) + 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) @@ -1335,9 +1337,10 @@ class MIoTPropertyEntity(Entity): piid=self.spec.iid)) 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) + _LOGGER.debug('property changed, %s', params) + 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() diff --git a/custom_components/xiaomi_home/miot/miot_mips.py b/custom_components/xiaomi_home/miot/miot_mips.py index ef814fb..6d52cdc 100644 --- a/custom_components/xiaomi_home/miot/miot_mips.py +++ b/custom_components/xiaomi_home/miot/miot_mips.py @@ -539,6 +539,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: @@ -557,6 +558,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) @@ -666,6 +668,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() @@ -1017,9 +1020,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, diff --git a/custom_components/xiaomi_home/miot/miot_spec.py b/custom_components/xiaomi_home/miot/miot_spec.py index 9cabdcb..7f6a5b2 100644 --- a/custom_components/xiaomi_home/miot/miot_spec.py +++ b/custom_components/xiaomi_home/miot/miot_spec.py @@ -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: diff --git a/custom_components/xiaomi_home/miot/specs/multi_lang.json b/custom_components/xiaomi_home/miot/specs/multi_lang.json index 68d2fb9..becd9e1 100644 --- a/custom_components/xiaomi_home/miot/specs/multi_lang.json +++ b/custom_components/xiaomi_home/miot/specs/multi_lang.json @@ -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": "中档", diff --git a/custom_components/xiaomi_home/miot/specs/spec_add.json b/custom_components/xiaomi_home/miot/specs/spec_add.json index 2a5bba3..c161f9d 100644 --- a/custom_components/xiaomi_home/miot/specs/spec_add.json +++ b/custom_components/xiaomi_home/miot/specs/spec_add.json @@ -82,6 +82,22 @@ ] } ], + "urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l05b:1": [ + { + "iid": 3, + "type": "urn:miot-spec-v2:service:play:0000781D:xiaomi-l05b:1", + "description": "Play Control", + "actions": [ + { + "iid": 2, + "type": "urn:miot-spec-v2:action:play:0000280B:xiaomi-l05b:1", + "description": "Play", + "in": [], + "out": [] + } + ] + } + ], "urn:miot-spec-v2:device:thermostat:0000A031:tofan-wk01:1:0000C822": [ { "iid": 2, @@ -241,6 +257,1443 @@ ] } ], + "urn:miot-spec-v2:device:vacuum:0000A006:narwa-001:1": [ + { + "iid": 2, + "type": "urn:miot-spec-v2:service:vacuum:00007810:narwa-001:1", + "description": "Robot Cleaner", + "properties": [ + { + "iid": 2, + "type": "urn:miot-spec-v2:property:status:00000007:narwa-001:1", + "description": "Status", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 1, + "description": "Idle" + }, + { + "value": 2, + "description": "Charging" + }, + { + "value": 3, + "description": "BreakCharging" + }, + { + "value": 4, + "description": "Sweeping" + }, + { + "value": 5, + "description": "Paused" + }, + { + "value": 6, + "description": "Go Charging" + }, + { + "value": 7, + "description": "GoWash" + }, + { + "value": 8, + "description": "Remote" + }, + { + "value": 9, + "description": "Charging" + }, + { + "value": 10, + "description": "BuildingMap" + }, + { + "value": 11, + "description": "Updating" + }, + { + "value": 12, + "description": "Sleeping" + }, + { + "value": 13, + "description": "Relocation" + }, + { + "value": 14, + "description": "StationWorking" + }, + { + "value": 15, + "description": "Error" + }, + { + "value": 16, + "description": "Sweeping and Mopping" + }, + { + "value": 17, + "description": "Mopping" + }, + { + "value": 18, + "description": "Paused" + }, + { + "value": 19, + "description": "GoChargeBreak" + }, + { + "value": 20, + "description": "WashBreak" + }, + { + "value": 21, + "description": "IdleInOutside" + } + ] + }, + { + "iid": 3, + "type": "urn:miot-spec-v2:property:fault:00000009:narwa-001:1", + "description": "Device Fault", + "format": "uint32", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 0, + "description": "No Faults" + }, + { + "value": 16777248, + "description": "16777248" + }, + { + "value": 34603008, + "description": "34603008" + }, + { + "value": 34668608, + "description": "34668608" + }, + { + "value": 16842848, + "description": "16842848" + }, + { + "value": 16842849, + "description": "16842849" + }, + { + "value": 16842850, + "description": "16842850" + }, + { + "value": 16842851, + "description": "16842851" + }, + { + "value": 33751106, + "description": "33751106" + }, + { + "value": 16842852, + "description": "16842852" + }, + { + "value": 33751105, + "description": "33751105" + }, + { + "value": 16842853, + "description": "16842853" + }, + { + "value": 33751104, + "description": "33751104" + }, + { + "value": 34603121, + "description": "34603121" + }, + { + "value": 34603120, + "description": "34603120" + }, + { + "value": 34603123, + "description": "34603123" + }, + { + "value": 34603122, + "description": "34603122" + }, + { + "value": 33685523, + "description": "33685523" + }, + { + "value": 34603125, + "description": "34603125" + }, + { + "value": 33685524, + "description": "33685524" + }, + { + "value": 34603124, + "description": "34603124" + }, + { + "value": 34668592, + "description": "34668592" + }, + { + "value": 36765959, + "description": "36765959" + }, + { + "value": 34603126, + "description": "34603126" + }, + { + "value": 36765952, + "description": "36765952" + }, + { + "value": 36765954, + "description": "36765954" + }, + { + "value": 36765953, + "description": "36765953" + }, + { + "value": 36765956, + "description": "36765956" + }, + { + "value": 36765955, + "description": "36765955" + }, + { + "value": 36765958, + "description": "36765958" + }, + { + "value": 36765957, + "description": "36765957" + }, + { + "value": 33685525, + "description": "33685525" + }, + { + "value": 16843026, + "description": "16843026" + }, + { + "value": 33751122, + "description": "33751122" + }, + { + "value": 33751121, + "description": "33751121" + }, + { + "value": 16843024, + "description": "16843024" + }, + { + "value": 33751120, + "description": "33751120" + }, + { + "value": 16843025, + "description": "16843025" + }, + { + "value": 33685602, + "description": "33685602" + }, + { + "value": 34603104, + "description": "34603104" + }, + { + "value": 34603105, + "description": "34603105" + }, + { + "value": 33751078, + "description": "33751078" + }, + { + "value": 34668576, + "description": "34668576" + }, + { + "value": 34603107, + "description": "34603107" + }, + { + "value": 33685600, + "description": "33685600" + }, + { + "value": 33685601, + "description": "33685601" + }, + { + "value": 33751076, + "description": "33751076" + }, + { + "value": 33751075, + "description": "33751075" + }, + { + "value": 33751073, + "description": "33751073" + }, + { + "value": 36765745, + "description": "36765745" + }, + { + "value": 34603089, + "description": "34603089" + }, + { + "value": 34603088, + "description": "34603088" + }, + { + "value": 34603090, + "description": "34603090" + }, + { + "value": 16842832, + "description": "16842832" + }, + { + "value": 16842833, + "description": "16842833" + }, + { + "value": 16842834, + "description": "16842834" + }, + { + "value": 16842841, + "description": "16842841" + }, + { + "value": 16842835, + "description": "16842835" + }, + { + "value": 16842836, + "description": "16842836" + }, + { + "value": 33685568, + "description": "33685568" + }, + { + "value": 36765995, + "description": "36765995" + }, + { + "value": 33685569, + "description": "33685569" + }, + { + "value": 36765994, + "description": "36765994" + }, + { + "value": 33685570, + "description": "33685570" + }, + { + "value": 34668545, + "description": "34668545" + }, + { + "value": 34668544, + "description": "34668544" + }, + { + "value": 33685585, + "description": "33685585" + }, + { + "value": 34799648, + "description": "34799648" + }, + { + "value": 33685586, + "description": "33685586" + }, + { + "value": 33685584, + "description": "33685584" + }, + { + "value": 36765733, + "description": "36765733" + }, + { + "value": 36765735, + "description": "36765735" + }, + { + "value": 36765734, + "description": "36765734" + }, + { + "value": 36765736, + "description": "36765736" + }, + { + "value": 16842805, + "description": "16842805" + }, + { + "value": 16842806, + "description": "16842806" + }, + { + "value": 16842801, + "description": "16842801" + }, + { + "value": 36766016, + "description": "36766016" + }, + { + "value": 16842802, + "description": "16842802" + }, + { + "value": 16842804, + "description": "16842804" + }, + { + "value": 34603040, + "description": "34603040" + }, + { + "value": 34603042, + "description": "34603042" + }, + { + "value": 34603041, + "description": "34603041" + }, + { + "value": 34603044, + "description": "34603044" + }, + { + "value": 34668641, + "description": "34668641" + }, + { + "value": 34603043, + "description": "34603043" + }, + { + "value": 34668640, + "description": "34668640" + }, + { + "value": 34603045, + "description": "34603045" + }, + { + "value": 36765969, + "description": "36765969" + }, + { + "value": 36765968, + "description": "36765968" + }, + { + "value": 33685544, + "description": "33685544" + }, + { + "value": 33685545, + "description": "33685545" + }, + { + "value": 33685552, + "description": "33685552" + }, + { + "value": 33685553, + "description": "33685553" + }, + { + "value": 33685554, + "description": "33685554" + }, + { + "value": 36765996, + "description": "36765996" + }, + { + "value": 33685555, + "description": "33685555" + }, + { + "value": 33685556, + "description": "33685556" + }, + { + "value": 36765993, + "description": "36765993" + }, + { + "value": 34603029, + "description": "34603029" + }, + { + "value": 34603031, + "description": "34603031" + }, + { + "value": 34603030, + "description": "34603030" + }, + { + "value": 34603033, + "description": "34603033" + }, + { + "value": 16842899, + "description": "16842899" + }, + { + "value": 34603032, + "description": "34603032" + }, + { + "value": 36765696, + "description": "36765696" + }, + { + "value": 16842897, + "description": "16842897" + }, + { + "value": 36765992, + "description": "36765992" + }, + { + "value": 16842771, + "description": "16842771" + }, + { + "value": 16842769, + "description": "16842769" + }, + { + "value": 16842770, + "description": "16842770" + } + ] + }, + { + "iid": 17, + "type": "urn:miot-spec-v2:property:last-clean-time:00000280:narwa-001:1", + "description": "Last Clean Time", + "format": "uint32", + "access": [ + "notify", + "read" + ], + "value-range": [ + 0, + 4294967295, + 1 + ] + }, + { + "iid": 18, + "type": "urn:miot-spec-v2:property:base-station-working-status:00000281:narwa-001:1", + "description": "Base Station Working Status", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 0, + "description": "NULL" + }, + { + "value": 1, + "description": "Mop Clean" + }, + { + "value": 2, + "description": "Mop Air Dry" + } + ] + }, + { + "iid": 71, + "type": "urn:miot-spec-v2:property:on:00000006:narwa-001:1", + "description": "Switch Status", + "format": "bool", + "access": [ + "read", + "write", + "notify" + ] + } + ], + "actions": [ + { + "iid": 1, + "type": "urn:miot-spec-v2:action:start-sweep:00002804:narwa-001:1", + "description": "Start Sweep", + "in": [], + "out": [] + }, + { + "iid": 2, + "type": "urn:miot-spec-v2:action:stop-sweeping:00002805:narwa-001:1", + "description": "Stop Sweeping", + "in": [], + "out": [] + }, + { + "iid": 3, + "type": "urn:miot-spec-v2:action:stop-and-gocharge:000028B4:narwa-001:1", + "description": "Stop And Gocharge", + "in": [], + "out": [] + }, + { + "iid": 7, + "type": "urn:miot-spec-v2:action:pause-sweeping:00002863:narwa-001:1", + "description": "Pause Sweeping", + "in": [], + "out": [] + }, + { + "iid": 8, + "type": "urn:miot-spec-v2:action:continue-sweep:000028AA:narwa-001:1", + "description": "Continue Sweep", + "in": [], + "out": [] + } + ] + }, + { + "iid": 11, + "type": "urn:miot-spec-v2:service:battery:00007805:narwa-001:1", + "description": "Battery", + "properties": [ + { + "iid": 1, + "type": "urn:miot-spec-v2:property:battery-level:00000014:narwa-001:1", + "description": "Battery Level", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "unit": "percentage", + "value-range": [ + 0, + 100, + 1 + ] + }, + { + "iid": 2, + "type": "urn:miot-spec-v2:property:charging-state:00000015:narwa-001:1", + "description": "Charging State", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 1, + "description": "Charging" + }, + { + "value": 2, + "description": "Not Charging" + }, + { + "value": 3, + "description": "Not Chargeable" + } + ] + } + ] + } + ], + "urn:miot-spec-v2:device:vacuum:0000A006:narwa-ax11:1": [ + { + "iid": 2, + "type": "urn:miot-spec-v2:service:vacuum:00007810:narwa-ax11:1", + "description": "Robot Cleaner", + "properties": [ + { + "iid": 2, + "type": "urn:miot-spec-v2:property:status:00000007:narwa-ax11:1", + "description": "Status", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 1, + "description": "Idle" + }, + { + "value": 2, + "description": "Charging" + }, + { + "value": 3, + "description": "BreakCharging" + }, + { + "value": 4, + "description": "Sweeping" + }, + { + "value": 5, + "description": "Paused" + }, + { + "value": 6, + "description": "Go Charging" + }, + { + "value": 7, + "description": "GoWash" + }, + { + "value": 8, + "description": "Remote" + }, + { + "value": 9, + "description": "Charging" + }, + { + "value": 10, + "description": "BuildingMap" + }, + { + "value": 11, + "description": "Updating" + }, + { + "value": 12, + "description": "Sleeping" + }, + { + "value": 13, + "description": "Relocation" + }, + { + "value": 14, + "description": "StationWorking" + }, + { + "value": 15, + "description": "Error" + }, + { + "value": 16, + "description": "Sweeping and Mopping" + }, + { + "value": 17, + "description": "Mopping" + }, + { + "value": 18, + "description": "Paused" + }, + { + "value": 19, + "description": "GoChargeBreak" + }, + { + "value": 20, + "description": "WashBreak" + }, + { + "value": 21, + "description": "IdleInOutside" + } + ] + }, + { + "iid": 3, + "type": "urn:miot-spec-v2:property:fault:00000009:narwa-ax11:1", + "description": "Device Fault", + "format": "uint32", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 0, + "description": "No Faults" + }, + { + "value": 16777248, + "description": "16777248" + }, + { + "value": 34603008, + "description": "34603008" + }, + { + "value": 34668608, + "description": "34668608" + }, + { + "value": 16842848, + "description": "16842848" + }, + { + "value": 16842849, + "description": "16842849" + }, + { + "value": 16842850, + "description": "16842850" + }, + { + "value": 16842851, + "description": "16842851" + }, + { + "value": 33751106, + "description": "33751106" + }, + { + "value": 16842852, + "description": "16842852" + }, + { + "value": 33751105, + "description": "33751105" + }, + { + "value": 16842853, + "description": "16842853" + }, + { + "value": 33751104, + "description": "33751104" + }, + { + "value": 34603121, + "description": "34603121" + }, + { + "value": 34603120, + "description": "34603120" + }, + { + "value": 34603123, + "description": "34603123" + }, + { + "value": 34603122, + "description": "34603122" + }, + { + "value": 33685523, + "description": "33685523" + }, + { + "value": 34603125, + "description": "34603125" + }, + { + "value": 33685524, + "description": "33685524" + }, + { + "value": 34603124, + "description": "34603124" + }, + { + "value": 34668592, + "description": "34668592" + }, + { + "value": 36765959, + "description": "36765959" + }, + { + "value": 34603126, + "description": "34603126" + }, + { + "value": 36765952, + "description": "36765952" + }, + { + "value": 36765954, + "description": "36765954" + }, + { + "value": 36765953, + "description": "36765953" + }, + { + "value": 36765956, + "description": "36765956" + }, + { + "value": 36765955, + "description": "36765955" + }, + { + "value": 36765958, + "description": "36765958" + }, + { + "value": 36765957, + "description": "36765957" + }, + { + "value": 33685525, + "description": "33685525" + }, + { + "value": 16843026, + "description": "16843026" + }, + { + "value": 33751122, + "description": "33751122" + }, + { + "value": 33751121, + "description": "33751121" + }, + { + "value": 16843024, + "description": "16843024" + }, + { + "value": 33751120, + "description": "33751120" + }, + { + "value": 16843025, + "description": "16843025" + }, + { + "value": 33685602, + "description": "33685602" + }, + { + "value": 34603104, + "description": "34603104" + }, + { + "value": 34603105, + "description": "34603105" + }, + { + "value": 33751078, + "description": "33751078" + }, + { + "value": 34668576, + "description": "34668576" + }, + { + "value": 34603107, + "description": "34603107" + }, + { + "value": 33685600, + "description": "33685600" + }, + { + "value": 33685601, + "description": "33685601" + }, + { + "value": 33751076, + "description": "33751076" + }, + { + "value": 33751075, + "description": "33751075" + }, + { + "value": 33751073, + "description": "33751073" + }, + { + "value": 36765745, + "description": "36765745" + }, + { + "value": 34603089, + "description": "34603089" + }, + { + "value": 34603088, + "description": "34603088" + }, + { + "value": 34603090, + "description": "34603090" + }, + { + "value": 16842832, + "description": "16842832" + }, + { + "value": 16842833, + "description": "16842833" + }, + { + "value": 16842834, + "description": "16842834" + }, + { + "value": 16842841, + "description": "16842841" + }, + { + "value": 16842835, + "description": "16842835" + }, + { + "value": 16842836, + "description": "16842836" + }, + { + "value": 33685568, + "description": "33685568" + }, + { + "value": 36765995, + "description": "36765995" + }, + { + "value": 33685569, + "description": "33685569" + }, + { + "value": 36765994, + "description": "36765994" + }, + { + "value": 33685570, + "description": "33685570" + }, + { + "value": 34668545, + "description": "34668545" + }, + { + "value": 34668544, + "description": "34668544" + }, + { + "value": 33685585, + "description": "33685585" + }, + { + "value": 34799648, + "description": "34799648" + }, + { + "value": 33685586, + "description": "33685586" + }, + { + "value": 33685584, + "description": "33685584" + }, + { + "value": 36765733, + "description": "36765733" + }, + { + "value": 36765735, + "description": "36765735" + }, + { + "value": 36765734, + "description": "36765734" + }, + { + "value": 36765736, + "description": "36765736" + }, + { + "value": 16842805, + "description": "16842805" + }, + { + "value": 16842806, + "description": "16842806" + }, + { + "value": 16842801, + "description": "16842801" + }, + { + "value": 36766016, + "description": "36766016" + }, + { + "value": 16842802, + "description": "16842802" + }, + { + "value": 16842804, + "description": "16842804" + }, + { + "value": 34603040, + "description": "34603040" + }, + { + "value": 34603042, + "description": "34603042" + }, + { + "value": 34603041, + "description": "34603041" + }, + { + "value": 34603044, + "description": "34603044" + }, + { + "value": 34668641, + "description": "34668641" + }, + { + "value": 34603043, + "description": "34603043" + }, + { + "value": 34668640, + "description": "34668640" + }, + { + "value": 34603045, + "description": "34603045" + }, + { + "value": 36765969, + "description": "36765969" + }, + { + "value": 36765968, + "description": "36765968" + }, + { + "value": 33685544, + "description": "33685544" + }, + { + "value": 33685545, + "description": "33685545" + }, + { + "value": 33685552, + "description": "33685552" + }, + { + "value": 33685553, + "description": "33685553" + }, + { + "value": 33685554, + "description": "33685554" + }, + { + "value": 36765996, + "description": "36765996" + }, + { + "value": 33685555, + "description": "33685555" + }, + { + "value": 33685556, + "description": "33685556" + }, + { + "value": 36765993, + "description": "36765993" + }, + { + "value": 34603029, + "description": "34603029" + }, + { + "value": 34603031, + "description": "34603031" + }, + { + "value": 34603030, + "description": "34603030" + }, + { + "value": 34603033, + "description": "34603033" + }, + { + "value": 16842899, + "description": "16842899" + }, + { + "value": 34603032, + "description": "34603032" + }, + { + "value": 36765696, + "description": "36765696" + }, + { + "value": 16842897, + "description": "16842897" + }, + { + "value": 36765992, + "description": "36765992" + }, + { + "value": 16842771, + "description": "16842771" + }, + { + "value": 16842769, + "description": "16842769" + }, + { + "value": 16842770, + "description": "16842770" + } + ] + }, + { + "iid": 4, + "type": "urn:miot-spec-v2:property:sweep-mop-type:00000135:narwa-ax11:1", + "description": "Sweep Mop Type", + "format": "uint8", + "access": [ + "read", + "write", + "notify" + ], + "value-list": [ + { + "value": 1, + "description": "Sweep" + }, + { + "value": 2, + "description": "Mop" + }, + { + "value": 3, + "description": "Sweep Mop" + }, + { + "value": 4, + "description": "Sweep Before Mopping" + } + ] + }, + { + "iid": 17, + "type": "urn:miot-spec-v2:property:last-clean-time:00000280:narwa-ax11:1", + "description": "Last Clean Time", + "format": "uint32", + "access": [ + "notify", + "read" + ], + "value-range": [ + 0, + 4294967295, + 1 + ] + }, + { + "iid": 18, + "type": "urn:miot-spec-v2:property:base-station-working-status:00000281:narwa-ax11:1", + "description": "Base Station Working Status", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 0, + "description": "NULL" + }, + { + "value": 1, + "description": "Mop Clean" + }, + { + "value": 2, + "description": "Mop Air Dry" + } + ] + }, + { + "iid": 71, + "type": "urn:miot-spec-v2:property:on:00000006:narwa-ax11:1", + "description": "Switch Status", + "format": "bool", + "access": [ + "read", + "write", + "notify" + ] + } + ], + "actions": [ + { + "iid": 1, + "type": "urn:miot-spec-v2:action:start-sweep:00002804:narwa-ax11:1", + "description": "Start Sweep", + "in": [], + "out": [] + }, + { + "iid": 2, + "type": "urn:miot-spec-v2:action:stop-sweeping:00002805:narwa-ax11:1", + "description": "Stop Sweeping", + "in": [], + "out": [] + }, + { + "iid": 3, + "type": "urn:miot-spec-v2:action:stop-and-gocharge:000028B4:narwa-ax11:1", + "description": "Stop And Gocharge", + "in": [], + "out": [] + }, + { + "iid": 7, + "type": "urn:miot-spec-v2:action:pause-sweeping:00002863:narwa-ax11:1", + "description": "Pause Sweeping", + "in": [], + "out": [] + }, + { + "iid": 8, + "type": "urn:miot-spec-v2:action:continue-sweep:000028AA:narwa-ax11:1", + "description": "Continue Sweep", + "in": [], + "out": [] + } + ] + }, + { + "iid": 11, + "type": "urn:miot-spec-v2:service:battery:00007805:narwa-ax11:1", + "description": "Battery", + "properties": [ + { + "iid": 1, + "type": "urn:miot-spec-v2:property:battery-level:00000014:narwa-ax11:1", + "description": "Battery Level", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "unit": "percentage", + "value-range": [ + 0, + 100, + 1 + ] + }, + { + "iid": 2, + "type": "urn:miot-spec-v2:property:charging-state:00000015:narwa-ax11:1", + "description": "Charging State", + "format": "uint8", + "access": [ + "read", + "notify" + ], + "value-list": [ + { + "value": 1, + "description": "Charging" + }, + { + "value": 2, + "description": "Not Charging" + }, + { + "value": 3, + "description": "Not Chargeable" + } + ] + } + ] + } + ], + "urn:miot-spec-v2:device:vacuum:0000A006:roidmi-v60:3": [ + { + "iid": 2, + "type": "urn:miot-spec-v2:service:vacuum:00007810:roidmi-v60:1", + "description": "Robot Cleaner", + "actions": [ + { + "iid": 3, + "type": "urn:miot-spec-v2:action:start-room-sweep:00002826:roidmi-v60:1", + "description": "Start Room Sweep", + "in": [ + 9 + ], + "out": [] + } + ] + } + ], "urn:miot-spec-v2:device:water-heater:0000A02A:viomi-m1:2": [ { "iid": 2, diff --git a/custom_components/xiaomi_home/miot/specs/spec_filter.yaml b/custom_components/xiaomi_home/miot/specs/spec_filter.yaml index a7116fb..7c172ab 100644 --- a/custom_components/xiaomi_home/miot/specs/spec_filter.yaml +++ b/custom_components/xiaomi_home/miot/specs/spec_filter.yaml @@ -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' diff --git a/custom_components/xiaomi_home/miot/specs/spec_modify.yaml b/custom_components/xiaomi_home/miot/specs/spec_modify.yaml index 183879a..48f1327 100644 --- a/custom_components/xiaomi_home/miot/specs/spec_modify.yaml +++ b/custom_components/xiaomi_home/miot/specs/spec_modify.yaml @@ -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 diff --git a/custom_components/xiaomi_home/miot/specs/specv2entity.py b/custom_components/xiaomi_home/miot/specs/specv2entity.py index 48d56c2..ff7849d 100644 --- a/custom_components/xiaomi_home/miot/specs/specv2entity.py +++ b/custom_components/xiaomi_home/miot/specs/specv2entity.py @@ -167,8 +167,8 @@ SPEC_DEVICE_TRANS_MAP: dict = { }, 'battery': { 'required': { - 'properties': { - 'battery-level': {'read'} + 'actions': { + 'start-charge' } } } diff --git a/custom_components/xiaomi_home/miot/web_pages.py b/custom_components/xiaomi_home/miot/web_pages.py index d6ffd9f..c86bdb4 100644 --- a/custom_components/xiaomi_home/miot/web_pages.py +++ b/custom_components/xiaomi_home/miot/web_pages.py @@ -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( diff --git a/custom_components/xiaomi_home/vacuum.py b/custom_components/xiaomi_home/vacuum.py index 3957f86..242d96b 100644 --- a/custom_components/xiaomi_home/vacuum.py +++ b/custom_components/xiaomi_home/vacuum.py @@ -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."""