47 Commits

Author SHA1 Message Date
Li Shuzhen
7abc20dcb5 docs: update changelog and version to v0.4.4 (#1497)
Some checks failed
Tests / check-rule-format (push) Failing after 1s
Validate / validate-hassfest (push) Failing after 1s
Validate / validate-hacs (push) Failing after 9s
Validate / validate-lint (push) Failing after 0s
Validate / validate-setup (push) Failing after 2s
2025-11-11 09:12:55 +08:00
Li Shuzhen
3e33804477 Fix specs (#1496)
* fix: roidmi.vacuum.v60 duplicated service name for vacuum entity

* fix: cykj.hood.jyj22 spec urn version 4 (#1477)

* fix: lumi.motion.bmgl01 siid=2 piid=2 value-list (#1444)

* fix: ykcn.valve.cbcs power property value unit (#1488)

* fix: ainice.sensor_occupy.3b siid=2 piid=5,11,14,17 device_class (#1495)

* fix: qdhkl.airc.a42 hvac mode (#1483)
2025-11-11 08:56:33 +08:00
Mümin Köykıran
551b5cc938 feat: add Turkish language support (#1468)
Some checks failed
Tests / check-rule-format (push) Failing after 2s
Validate / validate-hassfest (push) Failing after 2s
Validate / validate-hacs (push) Failing after 7s
Validate / validate-lint (push) Failing after -1s
Validate / validate-setup (push) Failing after 1s
* feat: add Turkish language support

Added comprehensive Turkish (tr) language translations for Xiaomi Home Integration.

Changes:
- Added custom_components/xiaomi_home/translations/tr.json with complete UI translations
- Added custom_components/xiaomi_home/miot/i18n/tr.json with MIoT-specific translations
- All placeholders, markdown formatting, and special characters preserved
- Validated against English source files for structural integrity

Technical details:
- Followed Home Assistant language code standards (ISO 639-1: tr)
- Maintained formal Turkish (siz form) for professional user experience
- Preserved all technical terms (OAuth2, MIoT-Spec-V2, MQTT, etc.)
- JSON structure validated and all keys match English version

* feat: add Turkish translations to bool_trans.yaml

Added Turkish boolean value translations for:
- default: true/false values
- contact_state: contact/no contact states
- motion_state: motion detected states
- open_close: open/close states
- yes_no: yes/no values

* docs: update README to reflect Turkish language support

Updated multiple language support section:
- Changed from 8 to 13 supported languages
- Added Turkish (tr) to the language code list
- Updated language list to include all currently supported languages:
  Italian, Dutch, Portuguese, Brazilian Portuguese, and Turkish

* fix: correct language dictionary sorting and update documentation

- Sort INTEGRATION_LANGUAGES dictionary alphabetically (tr after ru)
- Update CLAUDE.md to reflect 13 supported languages instead of 8
- Fixes test_miot_data_sort() test requirement
- No functional changes, documentation and code style improvements only

* docs: update Chinese README to reflect 13 supported languages

- Changed from 8 to 13 languages in Chinese documentation
- Added Turkish, Italian, Dutch, Portuguese, Brazilian Portuguese
- Updated language code list to include: it, nl, pt, pt-BR, tr
- Changed translation source note from "machine translation"
  to "machine translation or community contributions"
- Maintains consistency with English README.md
2025-11-10 09:50:02 +08:00
Li Shuzhen
f49e76937c fix: climate entity swing mode setting (#1486)
Some checks failed
Tests / check-rule-format (push) Failing after 1s
Validate / validate-hassfest (push) Failing after 0s
Validate / validate-hacs (push) Failing after 6s
Validate / validate-lint (push) Failing after -1s
Validate / validate-setup (push) Failing after 0s
2025-11-07 10:19:31 +08:00
Li Shuzhen
a1a216aea6 fix: float value precision (#1485) 2025-11-07 10:19:01 +08:00
vshijiav
1ec325c9c7 fix: stop MQTT internal loop immediately when main loop is closed (#1484) 2025-11-07 10:18:25 +08:00
Li Shuzhen
c04fa542a3 docs: update changelog and version to v0.4.3 (#1453)
Some checks failed
Tests / check-rule-format (push) Failing after 1s
Validate / validate-hassfest (push) Failing after 2s
Validate / validate-hacs (push) Failing after 8s
Validate / validate-lint (push) Failing after -1s
Validate / validate-setup (push) Failing after 2s
2025-10-14 08:33:36 +08:00
Li Shuzhen
fbddaf80a7 fix: pylint 4.0.0 (#1455)
Some checks failed
Tests / check-rule-format (push) Failing after 0s
Validate / validate-hassfest (push) Failing after 0s
Validate / validate-hacs (push) Failing after 10s
Validate / validate-lint (push) Failing after 2s
Validate / validate-setup (push) Failing after 4s
2025-10-13 17:11:30 +08:00
Li Shuzhen
a11c3e2fda Fix specs (#1394)
Some checks failed
Tests / check-rule-format (push) Failing after 2s
Validate / validate-hassfest (push) Failing after 1s
Validate / validate-hacs (push) Failing after 8s
Validate / validate-lint (push) Failing after 0s
Validate / validate-setup (push) Failing after 2s
* fix: xiaomi.airc.rr0r00 swing mode (#1386)

* fix: hyd.airer.lyjpro current-position (#1376)

* feat: add an alongside button entity for xiaomi.wifispeaker.l05b play action (#1372)

* fix: ignore the unsupported property 2.3 of 759413.aircondition.iez (#1391)

* fix: ignore unsupported properties of xiaomi.wifispeaker.l15a

* feat: zhimi.fan.za1 fan mode description in zh_Hans (#1424)

* fix: roidmi.vacuum.v60 siid=2 aiid=3 out field format (#1437)
2025-10-11 11:33:07 +08:00
Li Shuzhen
739998211e feat: remove VacuumEntityFeature.BATTERY from the vacuum entity (#1433)
Some checks failed
Tests / check-rule-format (push) Failing after 6s
Validate / validate-hassfest (push) Failing after 2s
Validate / validate-hacs (push) Failing after 15s
Validate / validate-lint (push) Failing after 1s
Validate / validate-setup (push) Failing after 4s
2025-10-10 16:31:02 +08:00
Li Shuzhen
ec833b6539 feat: subscribe the proxy gateway child device up messages even though the device is offline (#1393)
Some checks failed
Tests / check-rule-format (push) Failing after 2s
Validate / validate-hassfest (push) Failing after 3s
Validate / validate-hacs (push) Failing after 10s
Validate / validate-lint (push) Failing after 2s
Validate / validate-setup (push) Failing after 5s
* feat: subscribe the proxy gateway child device up messages even though the device is offline (#1313)

* feat: do not subscribe proxy gateway child device online/offline state message
2025-09-02 17:22:40 +08:00
Li Shuzhen
f2200ba003 fix: contact-state value format (#1387)
Some checks failed
Tests / check-rule-format (push) Failing after 4s
Validate / validate-hassfest (push) Failing after 3s
Validate / validate-hacs (push) Failing after 9s
Validate / validate-lint (push) Failing after 2s
Validate / validate-setup (push) Failing after 3s
2025-08-29 17:36:25 +08:00
Li Shuzhen
073cdf2dcb fix: integer value step (#1388) 2025-08-29 17:35:46 +08:00
Li Shuzhen
0f65635342 docs: update changelog and version to v0.4.2 (#1368)
Some checks failed
Tests / check-rule-format (push) Failing after 4s
Validate / validate-hassfest (push) Failing after 3s
Validate / validate-hacs (push) Failing after 10s
Validate / validate-lint (push) Failing after 2s
Validate / validate-setup (push) Failing after 4s
2025-08-20 09:15:31 +08:00
Li Shuzhen
947169f18d Fix specs (#1367)
Some checks failed
Tests / check-rule-format (push) Failing after 5s
Validate / validate-hassfest (push) Failing after 3s
Validate / validate-hacs (push) Failing after 9s
Validate / validate-lint (push) Failing after 3s
Validate / validate-setup (push) Failing after 5s
* fix: xiaomi.fan.p70 fan level

* fix: xiaomi.fan.p76 fan level

* fix: ignore hmpace.motion.v6nfc

* fix: xiaomi.airc.rr0r00 humidity-range

* fix: xiaomi.airc.h43h00 humidity-range

* fix: zhimi.humidifier.ca4 water level
2025-08-19 17:49:27 +08:00
Li Shuzhen
65a7a6d22a fix: correct the property value format after expression calculation (#1366) 2025-08-19 14:36:30 +08:00
Li Shuzhen
c29f7eecbd fix: delete all unsupported MIoT-Spec-V2 instances of Narwa vacuum (#1355) 2025-08-19 14:12:35 +08:00
Brandon Chen
58c671483e fix: add RETURN_HOME functionality for new vacuum cleaner model (#1344)
Some checks failed
Tests / check-rule-format (push) Failing after 4s
Validate / validate-hassfest (push) Failing after 3s
Validate / validate-hacs (push) Failing after 9s
Validate / validate-lint (push) Failing after 2s
Validate / validate-setup (push) Failing after 4s
2025-08-19 10:15:01 +08:00
Li Shuzhen
7c97b85f02 docs: update changelog and version to v0.4.1 (#1336)
Some checks failed
Tests / check-rule-format (push) Failing after 4s
Validate / validate-hassfest (push) Failing after 3s
Validate / validate-hacs (push) Failing after 10s
Validate / validate-lint (push) Failing after 3s
Validate / validate-setup (push) Failing after 4s
2025-08-04 09:44:12 +08:00
Li Shuzhen
3f2c2a648b Fix specs (#1329)
Some checks failed
Tests / check-rule-format (push) Failing after 4s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 11s
Validate / validate-lint (push) Failing after 4s
Validate / validate-setup (push) Failing after 5s
* fix: cuco.plug.cp2d electric current (#1279)

* fix: xiaomi.fan.p45 fan level (#1291)

* docs: add necessary notices

* fix: xiaomi.aircondition.c17 humidity-range unit (#1308)

* fix: xiaomi.airc.h40h00 humidity-range unit

* fix: sanmei.valve.s1 power consumption, current and voltage (#1327)

* fix: xiaomi.aircondition.m16 humidity-range unit
2025-08-01 14:56:42 +08:00
Li Shuzhen
f11b2f2f68 fix: hide sensitive info in printing logs (#1328) 2025-08-01 14:54:33 +08:00
Li Shuzhen
f3abbef94c fix: set the device on when the switch status is False or None (#1303)
Some checks failed
Tests / check-rule-format (push) Failing after 5s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 11s
Validate / validate-lint (push) Failing after 3s
Validate / validate-setup (push) Failing after 5s
* fix: set the air conditioner on if its switch status property is False or None (#1277)

* feat: add a standalone switch for 090615.aircondition.ktf

* fix: add an alongside switch for juhl.aircondition.hvac (#1287)
2025-07-30 15:15:28 +08:00
Li Shuzhen
dae63657d7 fix: vacuum status (#1299)
* fix: vacuum status (#1283)

* fix: vacuum continue to sweep

* refactor: core warnings about vacuum activity (#1288)
2025-07-30 15:14:20 +08:00
Li Shuzhen
3cc66450bd feat: cover dead zone width (#1301) 2025-07-30 15:13:04 +08:00
Li Shuzhen
8cbb451153 docs: update changelog and version to v0.4.0 (#1281)
Some checks failed
Tests / check-rule-format (push) Failing after 3s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 11s
Validate / validate-lint (push) Failing after 3s
Validate / validate-setup (push) Failing after 5s
2025-07-22 09:06:01 +08:00
Li Shuzhen
0fee02ae5c feat: add notifications for the local connection to the central hub gateway (#1280)
Some checks failed
Tests / check-rule-format (push) Failing after 6s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 11s
Validate / validate-lint (push) Failing after 3s
Validate / validate-setup (push) Failing after 7s
* feat: add notifications for the central hub gateway connection status (#1103)

* fix: i18n langurage support

* fix: add notification of disconnection when ServiceStateChange.REMOVED
2025-07-21 16:49:42 +08:00
Li Shuzhen
580ff87e7f fix: specs (#1256)
* fix: xiaomi.aircondition.c24 total power consumption unit (#1243)

* fix: adp.motor.adswb4 motor switch (#1257)

* docs: modify README

* fix: cgllc.airm.cgd1st environment temperature (#1270)

* fix: shhf.light.sflt11 fan switch status (#1276)
2025-07-21 16:44:47 +08:00
Li Shuzhen
94583a23d1 fix: subscribe when connected to the central hub gateway (#1266)
Some checks failed
Tests / check-rule-format (push) Failing after 16s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 10s
Validate / validate-lint (push) Failing after 4s
Validate / validate-setup (push) Failing after 6s
2025-07-16 14:43:50 +08:00
Li Shuzhen
925cf3b90f feat: do not subscribe BLE device online/offline state message (#1264) 2025-07-16 13:57:43 +08:00
Li Shuzhen
836bd01ead fix: cover status (#1262) 2025-07-16 13:57:18 +08:00
Li Shuzhen
4ad040d2ea feat: get devices from the third party cloud (#1258)
Some checks failed
Tests / check-rule-format (push) Failing after 5s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 11s
Validate / validate-lint (push) Failing after 4s
Validate / validate-setup (push) Failing after 5s
2025-07-15 16:26:35 +08:00
Li Shuzhen
981429670a feat: add an alongside switch entity for viomi.waterheater.m1 (#1255) 2025-07-15 16:26:13 +08:00
Li Shuzhen
a82fd86c60 fix: mdns discovered ip address (#1250)
Some checks failed
Tests / check-rule-format (push) Failing after 8s
Validate / validate-hassfest (push) Failing after 6s
Validate / validate-hacs (push) Failing after 12s
Validate / validate-lint (push) Failing after 4s
Validate / validate-setup (push) Failing after 9s
2025-07-14 09:04:38 +08:00
Li Shuzhen
df3faea257 feat: set the cover closed position (#1242)
* feat: add the cover closed position configure option

* feat: estimate the cover entity's is_closed property by the cover closed position (#944)

* fix: translations

* feat: set max cover closed position as 5

* docs: modify README

* fix: remove useless spaces
2025-07-14 09:03:54 +08:00
Li Shuzhen
e09676661c feat: add the watch as the device tracker entity (#1189)
Some checks failed
Tests / check-rule-format (push) Failing after 6s
Validate / validate-hassfest (push) Failing after 6s
Validate / validate-hacs (push) Failing after 14s
Validate / validate-lint (push) Failing after 6s
Validate / validate-setup (push) Failing after 8s
2025-07-09 14:14:27 +08:00
Li Shuzhen
aebeaf0245 feat: add wifi speaker and television as the media player entity (#706) 2025-07-09 14:02:22 +08:00
Li Shuzhen
4c2e10038c docs: update changelog and version to v0.3.4 (#1238) 2025-07-09 09:39:43 +08:00
Li Shuzhen
9afc62f39a docs: modify README (#1237)
* docs: modify spec_filter.yaml in README

* docs: modify event descriptions in README
2025-07-09 09:17:57 +08:00
Li Shuzhen
b46805b92c fix: airer status for cover entity (#1235)
* fix: xiaomi.airer.pro3 airer status rising (#1222)

* fix: airer status

* fix: filter out non alphabetic characters from status descriptions
2025-07-09 09:16:55 +08:00
Li Shuzhen
a43447ef61 Fix specs (#1236)
* fix: ignore bjkcz.curtain.kczble curtain status (#1184)

* fix: yutai.plug.fsov8m power consumption (#1229)
2025-07-09 09:14:10 +08:00
ted
e5165f34da fix: Fix the HA warning in the logs related to vacuum state setting (#694)
Some checks failed
Tests / check-rule-format (push) Failing after 12s
Validate / validate-hassfest (push) Failing after 8s
Validate / validate-hacs (push) Failing after 3m6s
Validate / validate-lint (push) Failing after 11s
Validate / validate-setup (push) Failing after 9s
2025-07-08 13:48:17 +08:00
Li Shuzhen
9fbbb26d33 fix: translation it.json (#1215) 2025-07-08 13:46:36 +08:00
Li Shuzhen
5b1d003bb2 feat: subscribe the BLE device up messages even though the device is offline (#1207)
Some checks failed
Tests / check-rule-format (push) Failing after 10s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 11s
Validate / validate-lint (push) Failing after 4s
Validate / validate-setup (push) Failing after 5s
* feat: subscribe the BLE device up messages even though the device is offline (#1170)

* fix: set all BLE devices online
2025-06-30 11:27:12 +08:00
Li Shuzhen
6069eaaba8 feat: exclude unsupported model (#1205)
* feat: ignore unsupported models (#933)

* fix: remove unnecessary logs
2025-06-30 11:12:58 +08:00
Li Shuzhen
fd57e7c565 fix: reconnect delay time (#1200)
* fix: reset the reconnect interval when connected (#1175)

* feat: set the default reconnect delay time as 10 seconds

* fix: get the minimum reconnect interval
2025-06-30 11:12:18 +08:00
Li Shuzhen
096b33f3c9 fix: the operation mode when the device does not have a mode property (#1199) 2025-06-30 11:11:36 +08:00
天成
664787ca58 fix: ptx air-conditioner environment temperature (#1210)
Some checks failed
Tests / check-rule-format (push) Failing after 6s
Validate / validate-hassfest (push) Failing after 5s
Validate / validate-hacs (push) Failing after 13s
Validate / validate-lint (push) Failing after 4s
Validate / validate-setup (push) Failing after 7s
* fix: ptx air-conditioner temperature #1163

* fix: environment temperature siid and piid
2025-06-27 17:52:39 +08:00
55 changed files with 3609 additions and 233 deletions

View File

@@ -5,8 +5,8 @@ body:
attributes:
label: Describe the Bug / 描述问题
description: |
> A clear and concise description of what the bug is.
> 清晰且简明地描述问题。
> A clear and concise description of what the bug is. Please include the device model information (Like xiaomi.gateway.hub1 which can be found in Device info page).
> 清晰且简明地描述问题。请注明设备 model 信息(例如 xiaomi.gateway.hub1可在设备详情页查询
validations:
required: true

View File

@@ -1,9 +1,81 @@
# CHANGELOG
## v0.4.4
### Added
- Add Turkish language support. [#1468](https://github.com/XiaoMi/ha_xiaomi_home/pull/1468)
### Fixed
- Stop MQTT internal loop immediately when main loop is closed. [#1465](https://github.com/XiaoMi/ha_xiaomi_home/pull/1465)
- Fix the float value precision. [#1485](https://github.com/XiaoMi/ha_xiaomi_home/pull/1485)
- Fix the climate entity swing mode setting. [#1486](https://github.com/XiaoMi/ha_xiaomi_home/pull/1486)
- Fix the MIoT-Spec-V2 of cykj.hood.jyj22 urn version 4, lumi.motion.bmgl01 siid=2 piid=2 value-list, ykcn.valve.cbcs power property value unit, ainice.sensor_occupy.3b people-number property and qdhkl.airc.a42 hvac mode. [#1496](https://github.com/XiaoMi/ha_xiaomi_home/pull/1496)
## 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)
- Add an alongside switch entity for 090615.aircondition.ktf and juhl.aircondition.hvac. [#1303](https://github.com/XiaoMi/ha_xiaomi_home/pull/1303)
### Fixed
- Fix the vacuum status so that the vacuum activity will not always be idle. [#1299](https://github.com/XiaoMi/ha_xiaomi_home/pull/1299)
- Set the device on when the switch status is False or None. [#1303](https://github.com/XiaoMi/ha_xiaomi_home/pull/1303)
- Hide sensitive info in printing logs. [#1328](https://github.com/XiaoMi/ha_xiaomi_home/pull/1328)
- Fix the MIoT-Spec-V2 of cuco.plug.cp2d electric current, xiaomi.fan.p45 fan level, sanmei.valve.s1 power consumption, current and voltage, xiaomi.aircondition.c17, xiaomi.aircondition.m16 and xiaomi.airc.h40h00 humidity-range unit. [#1329](https://github.com/XiaoMi/ha_xiaomi_home/pull/1329)
## v0.4.0
### Added
- Add the watch as the device tracker entity. [#1189](https://github.com/XiaoMi/ha_xiaomi_home/pull/1189)
- Add the wifi speaker and the television as the media player entity. [#706](https://github.com/XiaoMi/ha_xiaomi_home/pull/706)
- Add an option in CONFIGURE to set the cover closed position. [#1242](https://github.com/XiaoMi/ha_xiaomi_home/pull/1242)
- Add notifications to show the status of the local connection to the central hub gateway. [#1280](https://github.com/XiaoMi/ha_xiaomi_home/pull/1280)
- Import the device from the third party cloud. [#1258](https://github.com/XiaoMi/ha_xiaomi_home/pull/1258)
### Changed
- Add an alongside switch entity for viomi.waterheater.m1. [#1255](https://github.com/XiaoMi/ha_xiaomi_home/pull/1255)
- Do not subscribe BLE device online/offline state message. [#1264](https://github.com/XiaoMi/ha_xiaomi_home/pull/1264)
### Fixed
- Keep the first element of the discovered ip address list as the recently added address when getting mdns result. [#1250](https://github.com/XiaoMi/ha_xiaomi_home/pull/1250)
- Subscribe local topics every time when connected to the central hub gateway. [#1266](https://github.com/XiaoMi/ha_xiaomi_home/pull/1266)
- Record the "closing" and "closed" status that occur frequently in the motor-controller, the window-opener and the curtain service. [#1262](https://github.com/XiaoMi/ha_xiaomi_home/pull/1262)
- Fix xiaomi.aircondition.c24 total power consumption unit, adp.motor.adswb4 motor switch, cgllc.airm.cgd1st environment temperature, and shhf.light.sflt11 fan switch status. [#1256](https://github.com/XiaoMi/ha_xiaomi_home/pull/1256)
## v0.3.4
### Added
- Exclude the unsupported device models. [#1205](https://github.com/XiaoMi/ha_xiaomi_home/pull/1205)
### Changed
- Subscribe the BLE device upstream messages even though the device is offline. [#1207](https://github.com/XiaoMi/ha_xiaomi_home/pull/1207)
- Record "opening", "closing" and "closed" status of the airer service that occur frequently and do not record "stop" status for the cover entity. [#1235](https://github.com/XiaoMi/ha_xiaomi_home/pull/1235)
- Modify README about spec_filter.yaml and the event attributes. [#1237](https://github.com/XiaoMi/ha_xiaomi_home/pull/1237)
### Fixed
- Fix the reconnect delay time to be reset when the client is connected to the broker. [#1200](https://github.com/XiaoMi/ha_xiaomi_home/pull/1200)
- Fix the HA warning in the logs related to vacuum state setting. [#694](https://github.com/XiaoMi/ha_xiaomi_home/pull/694)
- Fix the operation mode when the device does not have a mode property. [#1199](https://github.com/XiaoMi/ha_xiaomi_home/pull/1199)
- Fix 090615.aircondition.ktf environment temperature. [#1210](https://github.com/XiaoMi/ha_xiaomi_home/pull/1210)
- Fix a missing variable in translation it.json. [#1215](https://github.com/XiaoMi/ha_xiaomi_home/pull/1215)
- Fix yutai.plug.fsov8m power consumption and ignore bjkcz.curtain.kczble curtain status. [#1236](https://github.com/XiaoMi/ha_xiaomi_home/pull/1236)
## v0.3.3
### Changed
- Change the log level of error "mips unsub internal error, 4, None". [#1135](https://github.com/XiaoMi/ha_xiaomi_home/pull/1135)
- Add necessary logs for distinguishing the set_properties command source. [#1160](https://github.com/XiaoMi/ha_xiaomi_home/pull/1160)
### Fixed
- Fix tofan.airrtc.wk01 thermostat and air conditioner service. [#1160](https://github.com/XiaoMi/ha_xiaomi_home/pull/1160)
- Fix mrbond.airer.m1t closing status. [#1134](https://github.com/XiaoMi/ha_xiaomi_home/pull/1134)

192
CLAUDE.md Normal file
View File

@@ -0,0 +1,192 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Xiaomi Home Integration is an official Home Assistant integration for controlling Xiaomi IoT smart devices. It connects to devices via Xiaomi Cloud (MQTT) or locally through Xiaomi Central Hub Gateway. The integration converts MIoT-Spec-V2 device specifications into Home Assistant entities.
## Development Commands
### Installation & Setup
```bash
# Install to Home Assistant config directory
./install.sh /path/to/config
# Install test dependencies
pip install pytest pytest-asyncio pytest-dependency zeroconf paho.mqtt psutil cryptography slugify
```
### Testing
```bash
# Run all tests
pytest -v -s -m github ./test/
# Run specific test files
pytest -v -s ./test/test_spec.py
pytest -v -s ./test/test_cloud.py
pytest -v -s ./test/test_lan.py
# Check rule format
pytest -v -s -m github ./test/check_rule_format.py
```
### Code Quality
```bash
# Run pylint (follows Google Python Style Guide)
pylint $(git ls-files '*.py')
# Lint specific files
pylint custom_components/xiaomi_home/*.py
```
### Validation
```bash
# HACS validation (run by GitHub Actions)
# Uses: hacs/action@main
# Hassfest validation (run by GitHub Actions)
# Uses: home-assistant/actions/hassfest@master
```
## Architecture Overview
### Core Components (miot/)
The integration is built around the `miot/` core package:
**miot_client.py**: Top-level client instance representing a logged-in Xiaomi user. Each user login creates one MIoTClient. Manages authentication, device list, and message routing.
**miot_cloud.py**: OAuth 2.0 authentication and HTTP API calls to Xiaomi Cloud. Handles token refresh, user info, device control commands, and spec downloads.
**miot_mips.py**: Message bus (MQTT) for subscribing to device property changes and events. Implements both cloud (MipsCloudClient) and local (MipsLocalClient) message handling.
**miot_device.py**: Device entity class. Each MIoT device creates multiple MIoTDevice instances (one per Home Assistant entity). Handles property updates, action execution, and event processing.
**miot_spec.py**: MIoT-Spec-V2 parser. Parses device specifications (URN-based type system) from cloud or local cache. Each spec defines services, properties, events, and actions.
**miot_lan.py**: Local LAN control for IP devices in same network. Discovery and control without cloud (optional).
**miot_mdns.py**: mDNS discovery for Xiaomi Central Hub Gateway services.
**miot_storage.py**: File storage for certificates, device specs, translations, and cached data.
**miot_network.py**: Network status monitoring and IP address detection.
**miot_i18n.py**: Multi-language support (13 languages). Manages translations for entity names.
### Entity Conversion (specs/specv2entity.py)
MIoT-Spec-V2 instances are converted to Home Assistant entities using three mapping dictionaries:
- **SPEC_DEVICE_TRANS_MAP**: Whole-device patterns (e.g., vacuum, humidifier, climate)
- **SPEC_SERVICE_TRANS_MAP**: Service-level patterns (e.g., battery, air-purifier)
- **SPEC_PROP_TRANS_MAP**: Property-level patterns (e.g., temperature, humidity)
Conversion priority: Device > Service > Property > General rules
### Spec Customization Files (miot/specs/)
**spec_filter.yaml**: Filters out MIoT-Spec-V2 instances that should NOT be converted to entities. Uses device URN keys and supports wildcard matching for service/property/event/action IIDs.
**spec_modify.yaml**: Modifies spec instances before conversion (e.g., changing value ranges, access modes).
**multi_lang.json**: Local translation overrides with higher priority than cloud translations. Keyed by device URN (without version).
**spec_add.json**: Additional spec definitions for devices not in cloud database.
**bool_trans.yaml**: Boolean value translation mappings.
After editing spec files, you MUST update conversion rules via Integration CONFIGURE page in Home Assistant.
### Platform Files (custom_components/xiaomi_home/)
Standard Home Assistant platform files (sensor.py, switch.py, climate.py, etc.) implement entity registration and state management. Each platform imports from miot_device.py and creates entity subclasses.
**config_flow.py**: Configuration flow for OAuth login and device selection.
**__init__.py**: Integration setup, entry management, and data structure initialization.
## MIoT-Spec-V2 Concepts
**URN Format**: `urn:<namespace>:<type>:<name>:<value>[:<vendor-product>:<version>]`
- namespace: miot-spec-v2 (Xiaomi), bluetooth-spec (SIG), or vendor-specific
- type: device, service, property, event, action
- name: human-readable identifier (used for mapping)
**IIDs (Instance IDs)**: Decimal identifiers
- siid: Service Instance ID
- piid: Property Instance ID
- eiid: Event Instance ID
- aiid: Action Instance ID
**Instance Code Format**:
```
service:<siid> # service
service:<siid>:property:<piid> # property
service:<siid>:property:<piid>:valuelist:<index> # value list item
service:<siid>:event:<eiid> # event
service:<siid>:action:<aiid> # action
```
## Naming Conventions
From CONTRIBUTING.md:
- **Xiaomi**: Always "Xiaomi" in text. Variables: "xiaomi" or "mi"
- **Xiaomi Home**: Always "Xiaomi Home" in text. Variables: "mihome" or "MiHome"
- **Xiaomi IoT**: Always "MIoT" in text. Variables: "miot" or "MIoT"
- **Home Assistant**: Always "Home Assistant" in text. Variables: "hass" or "hass_xxx"
Mixed Chinese/English: Add space between Chinese and English or use Chinese quotation marks.
## Commit Message Format
```
<type>: <subject>
<body>
<footer>
```
Types: feat, fix, docs, style, refactor, perf, test, chore, revert
Subject: Imperative, present tense. Not capitalized. No period.
Body: Detailed description (mandatory except for docs type).
## Code Style
Follow [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html). Use the provided `.pylintrc` for linting.
## Debugging
Enable debug logging in Home Assistant configuration.yaml:
```yaml
logger:
default: critical
logs:
custom_components.xiaomi_home: debug
```
## Control Modes
- **Cloud Control**: MQTT message subscription + HTTP command API
- **Local Control**: Via Xiaomi Central Hub Gateway (firmware 3.3.0_0023+) or LAN control (IP devices only, may be unstable)
Central gateway local control takes priority over LAN control when both are available.
## Multi-Region Support
Regions: China (cn), Europe (eu), India (in), Russia (ru), Singapore (sg), USA (us)
User data is isolated per region. Integration supports multiple regions in same Home Assistant instance.
## Important Files Location
- Integration source: `custom_components/xiaomi_home/`
- Spec mappings: `custom_components/xiaomi_home/miot/specs/specv2entity.py`
- Spec filters: `custom_components/xiaomi_home/miot/specs/spec_filter.yaml`
- Translations: `custom_components/xiaomi_home/translations/` and `custom_components/xiaomi_home/miot/i18n/`
- Tests: `test/`

View File

@@ -83,9 +83,9 @@ Xiaomi Home Integration and the affiliated cloud interface is provided by Xiaomi
## FAQ
- Does Xiaomi Home Integration support all Xiaomi Home devices?
- Does Xiaomi Home Integration support all Xiaomi smart devices?
Xiaomi Home Integration currently supports most categories of Home device. Only a few categories are not supported. They are Bluetooth device, infrared device and virtual device.
Xiaomi Home Integration currently supports most categories of the smart device. Only a few categories are not supported. They are Bluetooth device, infrared device and virtual device.
- Does Xiaomi Home Integration support multiple Xiaomi accounts?
@@ -93,7 +93,7 @@ Xiaomi Home Integration and the affiliated cloud interface is provided by Xiaomi
- Does Xiaomi Home Integration support local control?
Local control is implemented by [Xiaomi Central Hub Gateway](https://www.mi.com/shop/buy/detail?product_id=15755&cfrom=search) (firmware version 3.4.0_0000 above) or Xiaomi home devices with built-in central hub gateway (software version 0.8.0 above) inside. If you do not have a Xiaomi central hub gateway or other devices having central hub gateway function, all control commands are sent through Xiaomi Cloud. The firmware for Xiaomi central hub gateway including the built-in central hub gateway supporting Home Assistant local control feature has not been released yet. Please refer to MIoT team's notification for upgrade plans.
Local control is implemented by [Xiaomi Central Hub Gateway](https://www.mi.com/shop/buy/detail?product_id=15755&cfrom=search) (firmware version 3.3.0_0023 and above) or Xiaomi smart devices with built-in central hub gateway (software version 0.8.9 and above) inside. If you do not have a Xiaomi central hub gateway or other devices having central hub gateway function, all control commands are sent through Xiaomi Cloud. The firmware for Xiaomi central hub gateway including the built-in central hub gateway supporting Home Assistant local control feature has not been released yet. Please refer to MIoT team's notification for upgrade plans.
Xiaomi central hub gateway is only available in mainland China. In other regions, it is not available.
@@ -155,6 +155,8 @@ In MIoT-Spec-V2 protocol, a product is defined as a device. A device contains se
MIoT-Spec-V2 event is transformed to Event entity in Home Assistant. The event's parameters are also passed to entity's `_trigger_event`.
MIoT-Spec-V2 event's arguments field is the list of parameters of the event. The list elements represent the piid of the property in the same service. For example, the [MIoT-Spec-V2](http://poc.miot-spec.srv/miot-spec-v2/instance?type=urn:miot-spec-v2:device:remote-control:0000A021:xiaomi-mcn002:1:0000D057) of the Xiaomi Wireless Double-key Switch contains the siid=2 Switch Sensor service. The eiid=1014 Long Press event of the service is triggered when a button is long pressed. The debug level log will print `Press and hold, attributes: {'Button Type': 1}`. This is an example log that the button type is 1, which means the right button is long pressed.
- Action
| in | Entity in Home Assistant |
@@ -289,46 +291,44 @@ The value of the event instance name indicates `_attr_device_class` of the Home
### MIoT-Spec-V2 Filter
`spec_filter.json` is used to filter out the MIoT-Spec-V2 instance that will not be converted to Home Assistant entity.
`spec_filter.yaml` is used to filter out the MIoT-Spec-V2 instance that will not be converted to Home Assistant entity.
The format of `spec_filter.json` is as follows.
The format of `spec_filter.yaml` is as follows.
```
{
"<MIoT-Spec-V2 device instance>":{
"services": list<service_iid: str>,
"properties": list<service_iid.property_iid: str>,
"events": list<service_iid.event_iid: str>,
"actions": list<service_iid.action_iid: str>,
}
}
```yaml
<MIoT-Spec-V2 device instance urn without the version field>:
services: list<service_iid: str>
properties: list<service_iid.property_iid: str>
events: list<service_iid.event_iid: str>
actions: list<service_iid.action_iid: str>
```
The key of `spec_filter.json` dictionary is the urn excluding the "version" field of the MIoT-Spec-V2 device instance. The firmware of different versions of the same product may be associated with the MIoT-Spec-V2 device instances of different versions. It is required that the MIoT-Spec-V2 instance of a higher version must contain all MIoT-Spec-V2 instances of the lower versions when a vendor defines the MIoT-Spec-V2 of its product on MIoT platform. Thus, the key of `spec_filter.json` does not need to specify the version number of MIoT-Spec-V2 device instance.
The key of `spec_filter.yaml` dictionary is the urn excluding the "version" field of the MIoT-Spec-V2 device instance. The firmware of different versions of the same product may be associated with the MIoT-Spec-V2 device instances of different versions. It is required that the MIoT-Spec-V2 instance of a higher version must contain all MIoT-Spec-V2 instances of the lower versions when a vendor defines the MIoT-Spec-V2 of its product on MIoT platform. Thus, the key of `spec_filter.yaml` does not need to specify the version number of MIoT-Spec-V2 device instance.
The value of "services", "properties", "events" or "actions" fields under "device instance" is the instance id (iid) of the service, property, event or action that will be ignored in the conversion process. Wildcard matching is supported.
Example:
```
{
"urn:miot-spec-v2:device:television:0000A010:xiaomi-rmi1":{
"services": ["*"] # Filter out all services. It is equivalent to completely ignoring the device with such MIoT-Spec-V2 device instance.
},
"urn:miot-spec-v2:device:gateway:0000A019:xiaomi-hub1": {
"services": ["3"], # Filter out the service whose iid=3.
"properties": ["4.*"] # Filter out all properties in the service whose iid=4.
"events": ["4.1"], # Filter out the iid=1 event in the iid=4 service.
"actions": ["4.1"] # Filter out the iid=1 action in the iid=4 service.
}
}
```yaml
urn:miot-spec-v2:device:television:0000A010:xiaomi-rmi1:
services:
- '*' # Filter out all services. It is equivalent to completely ignoring the device with such MIoT-Spec-V2.
urn:miot-spec-v2:device:gateway:0000A019:xiaomi-hub1:
services:
- '3' # Filter out the siid=3 service.
properties:
- '4.*' # Filter out all properties in the siid=4 service.
events:
- '4.1' # Filter out the eiid=1 event in the siid=4 service.
actions:
- '4.1' # Filter out the aiid=1 action in the siid=4 service.
```
Device information service (urn:miot-spec-v2:service:device-information:00007801) of all devices will never be converted to Home Assistant entity.
## Multiple Language Support
There are 8 languages available for selection in the config flow language option of Xiaomi Home, including Simplified Chinese, Traditional Chinese, English, Spanish, Russian, French, German, and Japanese. The config flow page in Simplified Chinese and English has been manually reviewed by the developer. Other languages are translated by machine translation. If you want to modify the words and sentences in the config flow page, you need to modify the json file of the certain language in `custom_components/xiaomi_home/translations/` and `custom_components/xiaomi_home/miot/i18n/` directory.
There are 13 languages available for selection in the config flow language option of Xiaomi Home, including Simplified Chinese, Traditional Chinese, English, Spanish, Russian, French, German, Japanese, Italian, Dutch, Portuguese, Brazilian Portuguese, and Turkish. The config flow page in Simplified Chinese and English has been manually reviewed by the developer. Other languages are translated by machine translation or community contributions. If you want to modify the words and sentences in the config flow page, you need to modify the json file of the certain language in `custom_components/xiaomi_home/translations/` and `custom_components/xiaomi_home/miot/i18n/` directory.
When displaying Home Assistant entity name, Xiaomi Home downloads the multiple language file configured by the device vendor from MIoT Cloud, which contains translations for MIoT-Spec-V2 instances of the device. `multi_lang.json` is a locally maintained multiple language dictionary, which has a higher priority than the multiple language file obtained from the cloud and can be used to supplement or modify the multiple language translation of devices.
@@ -346,7 +346,7 @@ The format of `multi_lang.json` is as follows.
The key of `multi_lang.json` dictionary is the urn excluding the "version" field of the MIoT-Spec-V2 device instance.
The language code is zh-Hans, zh-Hant, en, es, ru, fr, de, or ja, corresponding to the 8 selectable languages mentioned above.
The language code is zh-Hans, zh-Hant, en, es, ru, fr, de, ja, it, nl, pt, pt-BR, or tr, corresponding to the 13 selectable languages mentioned above.
The instance code is the code of the MIoT-Spec-V2 instance, which is in the format of:
@@ -376,7 +376,7 @@ Example:
}
```
> If you edit any files in the `custom_components/xiaomi_home/miot/specs` directory (`spec_filter.py`, `spec_modify.json`, `multi_lang.json`, etc.) in your Home Assistant, you need to update the entity conversion rule in the integration's CONFIGURE page to take effect. Method: [Settings > Devices & services > Configured > Xiaomi Home](https://my.home-assistant.io/redirect/integration/?domain=xiaomi_home) > CONFIGURE > Update entity conversion rules
> If you edit any files in the `custom_components/xiaomi_home/miot/specs` directory (`spec_filter.yaml`, `spec_modify.yaml`, `multi_lang.json`, etc.) in your Home Assistant, you need to update the entity conversion rule in the integration's CONFIGURE page to take effect. Method: [Settings > Devices & services > Configured > Xiaomi Home](https://my.home-assistant.io/redirect/integration/?domain=xiaomi_home) > CONFIGURE > Update entity conversion rules
## Documents

View File

@@ -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

View File

@@ -320,9 +320,15 @@ class FeatureSwingMode(MIoTServiceEntity, ClimateEntity):
await self.set_property_async(prop=self._prop_vertical_swing,
value=True)
elif swing_mode == SWING_HORIZONTAL:
if self._prop_vertical_swing:
await self.set_property_async(prop=self._prop_vertical_swing,
value=False)
await self.set_property_async(prop=self._prop_horizontal_swing,
value=True)
elif swing_mode == SWING_VERTICAL:
if self._prop_horizontal_swing:
await self.set_property_async(prop=self._prop_horizontal_swing,
value=False)
await self.set_property_async(prop=self._prop_vertical_swing,
value=True)
elif swing_mode == SWING_OFF:
@@ -523,6 +529,8 @@ class AirConditioner(FeatureOnOff, FeatureTargetTemperature,
self._hvac_mode_map[item.value] = HVACMode.DRY
elif item.name in {'fan'}:
self._hvac_mode_map[item.value] = HVACMode.FAN_ONLY
elif item.name in {'heat_cool'}:
self._hvac_mode_map[item.value] = HVACMode.HEAT_COOL
self._attr_hvac_modes = list(self._hvac_mode_map.values())
self._prop_mode = prop
elif prop.name == 'ac-state':
@@ -546,7 +554,7 @@ class AirConditioner(FeatureOnOff, FeatureTargetTemperature,
f'{self.entity_id}')
return
# set the device on
if self.get_prop_value(prop=self._prop_on) is False:
if self.get_prop_value(prop=self._prop_on) is not True:
await self.set_property_async(prop=self._prop_on,
value=True,
write_ha_state=False)

View File

@@ -75,6 +75,9 @@ from .miot.const import (
DEFAULT_CLOUD_SERVER,
DEFAULT_CTRL_MODE,
DEFAULT_INTEGRATION_LANGUAGE,
DEFAULT_COVER_DEAD_ZONE_WIDTH,
MIN_COVER_DEAD_ZONE_WIDTH,
MAX_COVER_DEAD_ZONE_WIDTH,
DEFAULT_NICK_NAME,
DEFAULT_OAUTH2_API_HOST,
DOMAIN,
@@ -129,6 +132,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
_cloud_server: str
_integration_language: str
_cover_dz_width: int
_auth_info: dict
_nick_name: str
_home_selected: dict
@@ -151,6 +155,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._main_loop = asyncio.get_running_loop()
self._cloud_server = DEFAULT_CLOUD_SERVER
self._integration_language = DEFAULT_INTEGRATION_LANGUAGE
self._cover_dz_width = DEFAULT_COVER_DEAD_ZONE_WIDTH
self._storage_path = ''
self._virtual_did = ''
self._uid = ''
@@ -951,6 +956,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
'action_debug': self._action_debug,
'hide_non_standard_entities':
self._hide_non_standard_entities,
'cover_dead_zone_width': self._cover_dz_width,
'display_binary_mode': self._display_binary_mode,
'display_devices_changed_notify':
self._display_devices_changed_notify
@@ -995,6 +1001,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
_hide_non_standard_entities: bool
_display_binary_mode: list[str]
_display_devs_notify: list[str]
_cover_dz_width: int
_oauth_redirect_url_full: str
_auth_info: dict
@@ -1015,6 +1022,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
_opt_lan_ctrl_cfg: bool
_opt_network_detect_cfg: bool
_opt_check_network_deps: bool
_cover_width_new: int
_trans_rules_count: int
_trans_rules_count_success: int
@@ -1043,6 +1051,8 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
self._ctrl_mode = self._entry_data.get('ctrl_mode', DEFAULT_CTRL_MODE)
self._integration_language = self._entry_data.get(
'integration_language', DEFAULT_INTEGRATION_LANGUAGE)
self._cover_dz_width = self._entry_data.get(
'cover_dead_zone_width', DEFAULT_COVER_DEAD_ZONE_WIDTH)
self._nick_name = self._entry_data.get('nick_name', DEFAULT_NICK_NAME)
self._action_debug = self._entry_data.get('action_debug', False)
self._hide_non_standard_entities = self._entry_data.get(
@@ -1068,6 +1078,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
self._action_debug_new = False
self._hide_non_standard_entities_new = False
self._display_binary_mode_new = []
self._cover_width_new = self._cover_dz_width
self._update_user_info = False
self._update_devices = False
self._update_trans_rules = False
@@ -1340,6 +1351,12 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
): cv.multi_select(
self._miot_i18n.translate(
'config.binary_mode')), # type: ignore
vol.Optional(
'cover_dead_zone_width',
default=self._cover_dz_width # type: ignore
): vol.All(vol.Coerce(int), vol.Range(
min=MIN_COVER_DEAD_ZONE_WIDTH,
max=MAX_COVER_DEAD_ZONE_WIDTH)),
vol.Required(
'update_trans_rules',
default=self._update_trans_rules # type: ignore
@@ -1378,6 +1395,8 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
'update_lan_ctrl_config', self._opt_lan_ctrl_cfg)
self._opt_network_detect_cfg = user_input.get(
'network_detect_config', self._opt_network_detect_cfg)
self._cover_width_new = user_input.get(
'cover_dead_zone_width', self._cover_dz_width)
return await self.async_step_update_user_info()
@@ -1926,6 +1945,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
'nick_name': self._nick_name,
'lang_new': INTEGRATION_LANGUAGES[self._lang_new],
'nick_name_new': self._nick_name_new,
'cover_width_new': self._cover_width_new,
'devices_add': len(self._devices_add),
'devices_remove': len(self._devices_remove),
'trans_rules_count': self._trans_rules_count,
@@ -1952,6 +1972,9 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
if self._lang_new != self._integration_language:
self._entry_data['integration_language'] = self._lang_new
self._need_reload = True
if self._cover_width_new != self._cover_dz_width:
self._entry_data['cover_dead_zone_width'] = self._cover_width_new
self._need_reload = True
if self._update_user_info:
self._entry_data['nick_name'] = self._nick_name_new
if self._update_devices:

View File

@@ -46,8 +46,9 @@ off Xiaomi or its affiliates' products.
Cover entities for Xiaomi Home.
"""
from __future__ import annotations
import logging
from typing import Any, Optional
import re
import logging
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
@@ -90,6 +91,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry,
class Cover(MIoTServiceEntity, CoverEntity):
"""Cover entities for Xiaomi Home."""
# pylint: disable=unused-argument
_cover_dead_zone_width: int
_prop_motor_control: Optional[MIoTSpecProperty]
_prop_motor_value_open: Optional[int]
_prop_motor_value_close: Optional[int]
@@ -97,7 +99,6 @@ class Cover(MIoTServiceEntity, CoverEntity):
_prop_status: Optional[MIoTSpecProperty]
_prop_status_opening: Optional[list[int]]
_prop_status_closing: Optional[list[int]]
_prop_status_stop: Optional[list[int]]
_prop_status_closed: Optional[list[int]]
_prop_current_position: Optional[MIoTSpecProperty]
_prop_target_position: Optional[MIoTSpecProperty]
@@ -115,6 +116,9 @@ class Cover(MIoTServiceEntity, CoverEntity):
self._attr_supported_color_modes = set()
self._attr_supported_features = CoverEntityFeature(0)
self._cover_dead_zone_width = (
miot_device.miot_client.cover_dead_zone_width)
self._prop_motor_control = None
self._prop_motor_value_open = None
self._prop_motor_value_close = None
@@ -122,7 +126,6 @@ class Cover(MIoTServiceEntity, CoverEntity):
self._prop_status = None
self._prop_status_opening = []
self._prop_status_closing = []
self._prop_status_stop = []
self._prop_status_closed = []
self._prop_current_position = None
self._prop_target_position = None
@@ -159,13 +162,22 @@ class Cover(MIoTServiceEntity, CoverEntity):
self.entity_id)
continue
for item in prop.value_list.items:
if item.name in {'opening', 'open', 'up'}:
item_str: str = item.name
item_name: str = re.sub(r'[^a-z]', '', item_str)
if item_name in {
'opening', 'open', 'up', 'uping', 'rise', 'rising'
}:
self._prop_status_opening.append(item.value)
elif item.name in {'closing', 'close', 'down', 'dowm'}:
elif item_name in {
'closing', 'close', 'down', 'dowm', 'falling',
'fallin', 'dropping', 'downing', 'lower'
}:
self._prop_status_closing.append(item.value)
elif item.name in {'stop', 'stopped', 'pause'}:
self._prop_status_stop.append(item.value)
elif item.name in {'closed'}:
elif item_name in {
'closed', 'closeover', 'stopatlowest',
'stoplowerlimit', 'lowerlimitstop', 'floor',
'lowerlimit'
}:
self._prop_status_closed.append(item.value)
self._prop_status = prop
elif prop.name == 'current-position':
@@ -263,8 +275,14 @@ class Cover(MIoTServiceEntity, CoverEntity):
self._prop_pos_closing = False
return self.get_prop_value(prop=self._prop_target_position)
pos = self.get_prop_value(prop=self._prop_current_position)
return None if pos is None else round(pos * 100 /
self._prop_position_value_range)
if pos is None:
return None
pos = round(pos*100/self._prop_position_value_range)
if pos <= self._cover_dead_zone_width:
pos = 0
elif pos >= (100 - self._cover_dead_zone_width):
pos = 100
return pos
@property
def is_opening(self) -> Optional[bool]:

View File

@@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2024 Xiaomi Corporation.
The ownership and intellectual property rights of Xiaomi Home Assistant
Integration and related Xiaomi cloud service API interface provided under this
license, including source code and object code (collectively, "Licensed Work"),
are owned by Xiaomi. Subject to the terms and conditions of this License, Xiaomi
hereby grants you a personal, limited, non-exclusive, non-transferable,
non-sublicensable, and royalty-free license to reproduce, use, modify, and
distribute the Licensed Work only for your use of Home Assistant for
non-commercial purposes. For the avoidance of doubt, Xiaomi does not authorize
you to use the Licensed Work for any other purpose, including but not limited
to use Licensed Work to develop applications (APP), Web services, and other
forms of software.
You may reproduce and distribute copies of the Licensed Work, with or without
modifications, whether in source or object form, provided that you must give
any other recipients of the Licensed Work a copy of this License and retain all
copyright and disclaimers.
Xiaomi provides the Licensed Work on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied, including, without
limitation, any warranties, undertakes, or conditions of TITLE, NO ERROR OR
OMISSION, CONTINUITY, RELIABILITY, NON-INFRINGEMENT, MERCHANTABILITY, or
FITNESS FOR A PARTICULAR PURPOSE. In any event, you are solely responsible
for any direct, indirect, special, incidental, or consequential damages or
losses arising from the use or inability to use the Licensed Work.
Xiaomi reserves all rights not expressly granted to you in this License.
Except for the rights expressly granted by Xiaomi under this License, Xiaomi
does not authorize you in any form to use the trademarks, copyrights, or other
forms of intellectual property rights of Xiaomi and its affiliates, including,
without limitation, without obtaining other written permission from Xiaomi, you
shall not use "Xiaomi", "Mijia" and other words related to Xiaomi or words that
may make the public associate with Xiaomi in any form to publicize or promote
the software or hardware devices that use the Licensed Work.
Xiaomi has the right to immediately terminate all your authorization under this
License in the event:
1. You assert patent invalidation, litigation, or other claims against patents
or other intellectual property rights of Xiaomi or its affiliates; or,
2. You make, have made, manufacture, sell, or offer to sell products that knock
off Xiaomi or its affiliates' products.
Device tracker entities for Xiaomi Home.
"""
from __future__ import annotations
from typing import Optional
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.device_tracker import TrackerEntity
from .miot.const import DOMAIN
from .miot.miot_device import MIoTDevice, MIoTServiceEntity, MIoTEntityData
from .miot.miot_spec import MIoTSpecProperty
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][
config_entry.entry_id]
new_entities = []
for miot_device in device_list:
for data in miot_device.entity_list.get('device_tracker', []):
new_entities.append(
DeviceTracker(miot_device=miot_device, entity_data=data))
if new_entities:
async_add_entities(new_entities)
class DeviceTracker(MIoTServiceEntity, TrackerEntity):
"""Tracker entities for Xiaomi Home."""
_prop_battery_level: Optional[MIoTSpecProperty]
_prop_latitude: Optional[MIoTSpecProperty]
_prop_longitude: Optional[MIoTSpecProperty]
_prop_area_id: Optional[MIoTSpecProperty]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
super().__init__(miot_device=miot_device, entity_data=entity_data)
self._prop_battery_level = None
self._prop_latitude = None
self._prop_longitude = None
self._prop_area_id = None
# properties
for prop in entity_data.props:
if prop.name == 'battery-level':
self._prop_battery_level = prop
elif prop.name == 'latitude':
self._prop_latitude = prop
elif prop.name == 'longitude':
self._prop_longitude = prop
elif prop.name == 'area-id':
self._prop_area_id = prop
@property
def battery_level(self) -> Optional[int]:
"""The battery level of the device."""
return None if (self._prop_battery_level
is None) else self.get_prop_value(
prop=self._prop_battery_level)
@property
def latitude(self) -> Optional[float]:
"""The latitude coordinate of the device."""
return None if self._prop_latitude is None else self.get_prop_value(
prop=self._prop_latitude)
@property
def longitude(self) -> Optional[float]:
"""The longitude coordinate of the device."""
return None if self._prop_longitude is None else self.get_prop_value(
prop=self._prop_longitude)
@property
def location_name(self) -> Optional[str]:
"""The location name of the device."""
return None if self._prop_area_id is None else self.get_prop_value(
prop=self._prop_area_id)

View File

@@ -221,7 +221,7 @@ class Fan(MIoTServiceEntity, FanEntity):
# preset_mode
if preset_mode:
await self.set_property_async(
self._prop_mode,
prop=self._prop_mode,
value=self.get_map_key(
map_=self._mode_map, value=preset_mode))
@@ -258,7 +258,7 @@ class Fan(MIoTServiceEntity, FanEntity):
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set the preset mode."""
await self.set_property_async(
self._prop_mode,
prop=self._prop_mode,
value=self.get_map_key(
map_=self._mode_map, value=preset_mode))

View File

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

View File

@@ -0,0 +1,470 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2024 Xiaomi Corporation.
The ownership and intellectual property rights of Xiaomi Home Assistant
Integration and related Xiaomi cloud service API interface provided under this
license, including source code and object code (collectively, "Licensed Work"),
are owned by Xiaomi. Subject to the terms and conditions of this License, Xiaomi
hereby grants you a personal, limited, non-exclusive, non-transferable,
non-sublicensable, and royalty-free license to reproduce, use, modify, and
distribute the Licensed Work only for your use of Home Assistant for
non-commercial purposes. For the avoidance of doubt, Xiaomi does not authorize
you to use the Licensed Work for any other purpose, including but not limited
to use Licensed Work to develop applications (APP), Web services, and other
forms of software.
You may reproduce and distribute copies of the Licensed Work, with or without
modifications, whether in source or object form, provided that you must give
any other recipients of the Licensed Work a copy of this License and retain all
copyright and disclaimers.
Xiaomi provides the Licensed Work on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied, including, without
limitation, any warranties, undertakes, or conditions of TITLE, NO ERROR OR
OMISSION, CONTINUITY, RELIABILITY, NON-INFRINGEMENT, MERCHANTABILITY, or
FITNESS FOR A PARTICULAR PURPOSE. In any event, you are solely responsible
for any direct, indirect, special, incidental, or consequential damages or
losses arising from the use or inability to use the Licensed Work.
Xiaomi reserves all rights not expressly granted to you in this License.
Except for the rights expressly granted by Xiaomi under this License, Xiaomi
does not authorize you in any form to use the trademarks, copyrights, or other
forms of intellectual property rights of Xiaomi and its affiliates, including,
without limitation, without obtaining other written permission from Xiaomi, you
shall not use "Xiaomi", "Mijia" and other words related to Xiaomi or words that
may make the public associate with Xiaomi in any form to publicize or promote
the software or hardware devices that use the Licensed Work.
Xiaomi has the right to immediately terminate all your authorization under this
License in the event:
1. You assert patent invalidation, litigation, or other claims against patents
or other intellectual property rights of Xiaomi or its affiliates; or,
2. You make, have made, manufacture, sell, or offer to sell products that knock
off Xiaomi or its affiliates' products.
Media player entities for Xiaomi Home.
"""
from __future__ import annotations
import logging
from typing import Optional
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.media_player import (MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerDeviceClass,
MediaPlayerState, MediaType)
from .miot.const import DOMAIN
from .miot.miot_device import MIoTDevice, MIoTServiceEntity, MIoTEntityData
from .miot.miot_spec import MIoTSpecProperty, MIoTSpecAction
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback) -> None:
"""Set up a config entry."""
device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][
config_entry.entry_id]
new_entities = []
for miot_device in device_list:
for data in miot_device.entity_list.get('wifi-speaker', []):
new_entities.append(
WifiSpeaker(miot_device=miot_device, entity_data=data))
for data in miot_device.entity_list.get('television', []):
new_entities.append(
Television(miot_device=miot_device, entity_data=data))
if new_entities:
async_add_entities(new_entities)
class FeatureVolumeMute(MIoTServiceEntity, MediaPlayerEntity):
"""VOLUME_MUTE feature of the media player entity."""
_prop_mute: Optional[MIoTSpecProperty]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._prop_mute = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# properties
for prop in entity_data.props:
if prop.name == 'mute':
self._attr_supported_features |= (
MediaPlayerEntityFeature.VOLUME_MUTE)
self._prop_mute = prop
@property
def is_volume_muted(self) -> Optional[bool]:
"""True if volume is currently muted."""
return self.get_prop_value(
prop=self._prop_mute) if self._prop_mute else None
async def async_mute_volume(self, mute: bool) -> None:
"""Mute the volume."""
await self.set_property_async(prop=self._prop_mute, value=mute)
class FeatureVolumeSet(MIoTServiceEntity, MediaPlayerEntity):
"""VOLUME_SET feature of the media player entity."""
_prop_volume: Optional[MIoTSpecProperty]
_volume_value_min: Optional[float]
_volume_value_max: Optional[float]
_volume_value_range: Optional[float]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._prop_volume = None
self._volume_value_min = None
self._volume_value_max = None
self._volume_value_range = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# properties
for prop in entity_data.props:
if prop.name == 'volume':
if not prop.value_range:
_LOGGER.error('invalid volume value_range format, %s',
self.entity_id)
continue
self._volume_value_min = prop.value_range.min_
self._volume_value_max = prop.value_range.max_
self._volume_value_range = (prop.value_range.max_ -
prop.value_range.min_)
self._attr_volume_step = (prop.value_range.step /
self._volume_value_range)
self._attr_supported_features |= (
MediaPlayerEntityFeature.VOLUME_SET |
MediaPlayerEntityFeature.VOLUME_STEP)
self._prop_volume = prop
async def async_set_volume_level(self, volume: float) -> None:
"""Set volume level."""
value = volume * self._volume_value_range + self._volume_value_min
if value > self._volume_value_max:
value = self._volume_value_max
elif value < self._volume_value_min:
value = self._volume_value_min
await self.set_property_async(prop=self._prop_volume, value=value)
@property
def volume_level(self) -> Optional[float]:
"""The current volume level, range [0, 1]."""
value = self.get_prop_value(
prop=self._prop_volume) if self._prop_volume else None
if value is None:
return None
return (value - self._volume_value_min) / self._volume_value_range
class FeaturePlay(MIoTServiceEntity, MediaPlayerEntity):
"""PLAY feature of the media player entity."""
_action_play: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_play = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'play':
self._attr_supported_features |= (MediaPlayerEntityFeature.PLAY)
self._action_play = act
async def async_media_play(self) -> None:
"""Send play command."""
await self.action_async(action=self._action_play)
class FeaturePause(MIoTServiceEntity, MediaPlayerEntity):
"""PAUSE feature of the media player entity."""
_action_pause: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_pause = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'pause':
self._attr_supported_features |= (
MediaPlayerEntityFeature.PAUSE)
self._action_pause = act
async def async_media_pause(self) -> None:
"""Send pause command."""
await self.action_async(action=self._action_pause)
class FeatureStop(MIoTServiceEntity, MediaPlayerEntity):
"""STOP feature of the media player entity."""
_action_stop: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_stop = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'stop':
self._attr_supported_features |= (MediaPlayerEntityFeature.STOP)
self._action_stop = act
async def async_media_stop(self) -> None:
"""Send stop command."""
await self.action_async(action=self._action_stop)
class FeatureNextTrack(MIoTServiceEntity, MediaPlayerEntity):
"""NEXT_TRACK feature of the media player entity."""
_action_next: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_next = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'next':
self._attr_supported_features |= (
MediaPlayerEntityFeature.NEXT_TRACK)
self._action_next = act
async def async_media_next_track(self) -> None:
"""Send next track command."""
await self.action_async(action=self._action_next)
class FeaturePreviousTrack(MIoTServiceEntity, MediaPlayerEntity):
"""PREVIOUS_TRACK feature of the media player entity."""
_action_previous: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_previous = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'previous':
self._attr_supported_features |= (
MediaPlayerEntityFeature.PREVIOUS_TRACK)
self._action_previous = act
async def async_media_previous_track(self) -> None:
"""Send previous track command."""
await self.action_async(action=self._action_previous)
class FeatureSoundMode(MIoTServiceEntity, MediaPlayerEntity):
"""SELECT_SOUND_MODE feature of the media player entity."""
_prop_play_loop_mode: Optional[MIoTSpecProperty]
_sound_mode_map: Optional[dict[int, str]]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._prop_play_loop_mode = None
self._sound_mode_map = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# properties
for prop in entity_data.props:
if prop.name == 'play-loop-mode':
if not prop.value_list:
_LOGGER.error('invalid play-loop-mode value_list, %s',
self.entity_id)
continue
self._sound_mode_map = prop.value_list.to_map()
self._attr_sound_mode_list = list(self._sound_mode_map.values())
self._attr_supported_features |= (
MediaPlayerEntityFeature.SELECT_SOUND_MODE)
self._prop_play_loop_mode = prop
async def async_select_sound_mode(self, sound_mode: str):
"""Switch the sound mode of the entity."""
await self.set_property_async(prop=self._prop_play_loop_mode,
value=self.get_map_key(
map_=self._sound_mode_map,
value=sound_mode))
@property
def sound_mode(self) -> Optional[str]:
"""The current sound mode."""
return (self.get_map_value(map_=self._sound_mode_map,
key=self.get_prop_value(
prop=self._prop_play_loop_mode))
if self._prop_play_loop_mode else None)
class FeatureTurnOn(MIoTServiceEntity, MediaPlayerEntity):
"""TURN_ON feature of the media player entity."""
_action_turn_on: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_turn_on = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'turn-on':
self._attr_supported_features |= (
MediaPlayerEntityFeature.TURN_ON)
self._action_turn_on = act
async def async_turn_on(self) -> None:
"""Turn the media player on."""
await self.action_async(action=self._action_turn_on)
class FeatureTurnOff(MIoTServiceEntity, MediaPlayerEntity):
"""TURN_OFF feature of the media player entity."""
_action_turn_off: Optional[MIoTSpecAction]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._action_turn_off = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# actions
for act in entity_data.actions:
if act.name == 'turn-off':
self._attr_supported_features |= (
MediaPlayerEntityFeature.TURN_OFF)
self._action_turn_off = act
async def async_turn_off(self) -> None:
"""Turn the media player off."""
await self.action_async(action=self._action_turn_off)
class FeatureSource(MIoTServiceEntity, MediaPlayerEntity):
"""SELECT_SOURCE feature of the media player entity."""
_prop_input_control: Optional[MIoTSpecProperty]
_input_source_map: Optional[dict[int, str]]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._prop_input_control = None
self._input_source_map = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# properties
for prop in entity_data.props:
if prop.name == 'input-control':
if not prop.value_list:
_LOGGER.error('invalid input-control value_list, %s',
self.entity_id)
continue
self._input_source_map = prop.value_list.to_map()
self._attr_source_list = list(self._input_source_map.values())
self._attr_supported_features |= (
MediaPlayerEntityFeature.SELECT_SOURCE)
self._prop_input_control = prop
async def async_select_source(self, source: str) -> None:
"""Select input source."""
await self.set_property_async(prop=self._prop_input_control,
value=self.get_map_key(
map_=self._input_source_map,
value=source))
@property
def source(self) -> Optional[str]:
"""The current input source."""
return (self.get_map_value(map_=self._input_source_map,
key=self.get_prop_value(
prop=self._prop_input_control))
if self._prop_input_control else None)
class FeatureState(MIoTServiceEntity, MediaPlayerEntity):
"""States feature of the media player entity."""
_prop_playing_state: Optional[MIoTSpecProperty]
_playing_state_map: Optional[dict[int, str]]
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the feature class."""
self._prop_playing_state = None
self._playing_state_map = None
super().__init__(miot_device=miot_device, entity_data=entity_data)
# properties
for prop in entity_data.props:
if prop.name == 'playing-state':
if not prop.value_list:
_LOGGER.error('invalid mode value_list, %s', self.entity_id)
continue
self._playing_state_map = {}
for item in prop.value_list.items:
if item.name in {'off'}:
self._playing_state_map[
item.value] = MediaPlayerState.OFF
elif item.name in {'idle', 'stop', 'stopped'}:
self._playing_state_map[
item.value] = MediaPlayerState.IDLE
elif item.name in {'playing'}:
self._playing_state_map[
item.value] = MediaPlayerState.PLAYING
elif item.name in {'pause', 'paused'}:
self._playing_state_map[
item.value] = MediaPlayerState.PAUSED
self._prop_playing_state = prop
@property
def state(self) -> Optional[MediaPlayerState]:
"""The current state."""
return (self.get_map_value(map_=self._playing_state_map,
key=self.get_prop_value(
prop=self._prop_playing_state))
if self._prop_playing_state else MediaPlayerState.ON)
class WifiSpeaker(FeatureVolumeSet, FeatureVolumeMute, FeaturePlay,
FeaturePause, FeatureStop, FeatureNextTrack,
FeaturePreviousTrack, FeatureSoundMode, FeatureState):
"""WiFi speaker, aka XiaoAI sound speaker."""
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the device."""
super().__init__(miot_device=miot_device, entity_data=entity_data)
self._attr_device_class = MediaPlayerDeviceClass.SPEAKER
self._attr_media_content_type = MediaType.MUSIC
class Television(FeatureVolumeSet, FeatureVolumeMute, FeaturePlay, FeaturePause,
FeatureStop, FeatureNextTrack, FeaturePreviousTrack,
FeatureSoundMode, FeatureState, FeatureSource, FeatureTurnOn,
FeatureTurnOff):
"""Television"""
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
"""Initialize the device."""
super().__init__(miot_device=miot_device, entity_data=entity_data)
self._attr_device_class = MediaPlayerDeviceClass.TV
self._attr_media_content_type = MediaType.VIDEO

View File

@@ -71,10 +71,12 @@ SUPPORTED_PLATFORMS: list = [
'button',
'climate',
'cover',
'device_tracker',
'event',
'fan',
'humidifier',
'light',
'media_player',
'notify',
'number',
'select',
@@ -85,6 +87,12 @@ SUPPORTED_PLATFORMS: list = [
'water_heater',
]
UNSUPPORTED_MODELS: list = [
'chuangmi.ir.v2',
'hmpace.motion.v6nfc',
'xiaomi.router.rd03'
]
DEFAULT_CLOUD_SERVER: str = 'cn'
CLOUD_SERVERS: dict = {
'cn': '中国大陆',
@@ -109,10 +117,15 @@ INTEGRATION_LANGUAGES = {
'pt': 'Português',
'pt-BR': 'Português (Brasil)',
'ru': 'Русский',
'tr': 'Türkçe',
'zh-Hans': '简体中文',
'zh-Hant': '繁體中文'
}
DEFAULT_COVER_DEAD_ZONE_WIDTH: int = 0
MIN_COVER_DEAD_ZONE_WIDTH: int = 0
MAX_COVER_DEAD_ZONE_WIDTH: int = 5
DEFAULT_CTRL_MODE: str = 'auto'
# Registered in Xiaomi OAuth 2.0 Service

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} Geräte offline:** \n{message}",
"network_status_online": "Online",
"network_status_offline": "Offline",
"central_state_changed_title": "Verbindungsstatus des Zentral-Gateways",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** Lokale Verbindungsstrecke des Zentral-Gateways: {conn_status}",
"central_state_connected": "verbunden",
"central_state_disconnected": "getrennt",
"device_exec_error": "Fehler bei der Ausführung"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} devices offline:** \n{message}",
"network_status_online": "Online",
"network_status_offline": "Offline",
"central_state_changed_title": "Central Hub Gateway Connection Status",
"central_state_changed":"**{nick_name}({uid}, {cloud_server})** local connection to Xiaomi central hub gateway: {conn_status}",
"central_state_connected": "Connected",
"central_state_disconnected": "Disconnected",
"device_exec_error": "Execution error"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} dispositivos sin conexión:** \n{message}",
"network_status_online": "En línea",
"network_status_offline": "Desconectado",
"central_state_changed_title": "Estado de conexión de la puerta de enlace central",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** enlace de conexión local de la puerta de enlace central: {conn_status}",
"central_state_connected": "conectado",
"central_state_disconnected": "desconectado",
"device_exec_error": "Error de ejecución"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} appareils hors ligne :** \n{message}",
"network_status_online": "En ligne",
"network_status_offline": "Hors ligne",
"central_state_changed_title": "État de connexion de la passerelle centrale",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** liaison de connexion locale de la passerelle centrale : {conn_status}",
"central_state_connected": "connecté",
"central_state_disconnected": "déconnecté",
"device_exec_error": "Erreur d'exécution"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} dispositivi offline:** \n{message}",
"network_status_online": "Online",
"network_status_offline": "Offline",
"central_state_changed_title": "Stato di connessione del gateway centrale",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** collegamento locale del gateway centrale: {conn_status}",
"central_state_connected": "connesso",
"central_state_disconnected": "disconnesso",
"device_exec_error": "Errore di esecuzione"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} デバイスがオフライン:** \n{message}",
"network_status_online": "オンライン",
"network_status_offline": "オフライン",
"central_state_changed_title": "中枢ゲートウェイ接続ステータス",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** 中枢ゲートウェイのローカル接続リンク: {conn_status}",
"central_state_connected": "接続済み",
"central_state_disconnected": "切断されました",
"device_exec_error": "実行エラー"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} apparaten offline:** \n{message}",
"network_status_online": "Online",
"network_status_offline": "Offline",
"central_state_changed_title": "Verbindingsstatus van centrale gateway",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** Lokale verbinding van centrale gateway: {conn_status}",
"central_state_connected": "verbonden",
"central_state_disconnected": "verbinding verbroken",
"device_exec_error": "Uitvoeringsfout"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} dispositivos offline**: \n{message}",
"network_status_online": "online",
"network_status_offline": "offline",
"central_state_changed_title": "Status de conexão do gateway central",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** conexão local do gateway central: {conn_status}",
"central_state_connected": "conectado",
"central_state_disconnected": "desconectado",
"device_exec_error": "Erro na execução"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} dispositivos offline**: \n{message}",
"network_status_online": "Online",
"network_status_offline": "Offline",
"central_state_changed_title": "Estado da ligação do gateway central",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** ligação local do gateway central: {conn_status}",
"central_state_connected": "ligado",
"central_state_disconnected": "desligado",
"device_exec_error": "Erro de execução"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} устройств недоступно:** \n{message}",
"network_status_online": "В сети",
"network_status_offline": "Не в сети",
"central_state_changed_title": "Статус подключения центрального шлюза",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** локальное подключение центрального шлюза: {conn_status}",
"central_state_connected": "подключено",
"central_state_disconnected": "разъединено",
"device_exec_error": "Ошибка выполнения"
}
},

View File

@@ -0,0 +1,160 @@
{
"config": {
"other": {
"devices": "Cihazlar",
"found_central_gateway": ", Yerel Merkezi Hub Ağ Geçidi Bulundu",
"without_room": "Oda atanmamış",
"no_display": "Gösterme"
},
"control_mode": {
"auto": "Otomatik",
"cloud": "Bulut"
},
"statistics_logic": {
"or": "VEYA mantığı",
"and": "VE mantığı"
},
"filter_mode": {
"exclude": "Hariç tut",
"include": "Dahil et"
},
"connect_type": {
"0": "WiFi",
"1": "yunyi cihazı",
"2": "Bulut cihazı",
"3": "ZigBee",
"4": "webSocket",
"5": "Sanal cihaz",
"6": "BLE",
"7": "Yerel AP",
"8": "WiFi+BLE",
"9": "Diğer",
"10": "İşlev eklentisi",
"11": "Hücresel ağ",
"12": "Kablo",
"13": "NB-IoT",
"14": "Üçüncü taraf bulut erişimi",
"15": "Kızılötesi uzaktan kumanda cihazı",
"16": "BLE-Mesh",
"17": "Sanal cihaz grubu",
"18": "Ağ geçidi alt cihazı",
"19": "Güvenlik seviyesi ağ geçidi alt cihazı",
"22": "PLC",
"23": "Yalnızca kablo",
"24": "Matter",
"25": "WiFi+Hücresel ağ"
},
"room_name_rule": {
"none": "Senkronize etme",
"home_room": "Ev Adı ve Oda Adı (Xiaomi Home Yatak Odası)",
"room": "Oda Adı (Yatak Odası)",
"home": "Ev Adı (Xiaomi Home)"
},
"option_status": {
"enable": "Etkinleştir",
"disable": "Devre Dışı Bırak"
},
"binary_mode": {
"text": "Metin Sensör Varlığı",
"bool": "İkili Sensör Varlığı"
},
"device_state": {
"add": "Ekle",
"del": "Kullanılamıyor",
"offline": "Çevrimdışı"
},
"lan_ctrl_config": {
"notice_net_dup": "\r\n**[Bildirim]** Aynı ağa bağlı olabilecek birden fazla ağ kartı algılandı. Lütfen seçime dikkat edin.",
"net_unavailable": "Arayüz kullanılamıyor"
}
},
"oauth2": {
"success": {
"title": "Kimlik Doğrulama Başarılı",
"content": "Lütfen bu sayfayı kapatın ve 'İleri'ye tıklamak için hesap kimlik doğrulama sayfasına geri dönün.",
"button": "Kapat"
},
"fail": {
"title": "Kimlik Doğrulama Başarısız",
"content": "{error_msg}, lütfen bu sayfayı kapatın ve kimlik doğrulama bağlantısına tekrar tıklamak için hesap kimlik doğrulama sayfasına geri dönün.",
"button": "Kapat"
},
"error_msg": {
"-10100": "Geçersiz yanıt parametreleri ('code' veya 'state' alanı boş)",
"-10101": "Geçirilen 'state' alanı uyumsuz"
}
},
"miot": {
"client": {
"invalid_oauth_info": "Kimlik doğrulama bilgileri geçersiz, bulut bağlantısı kullanılamayacak, lütfen Xiaomi Home entegrasyon sayfasına girin, yeniden kimlik doğrulaması yapmak için 'Seçenekler'e tıklayın",
"invalid_device_cache": "Önbellek cihaz bilgileri anormal, lütfen Xiaomi Home entegrasyon sayfasına girin, yerel önbelleği güncellemek için 'Seçenekler->Cihaz listesini güncelle'ye tıklayın",
"invalid_cert_info": "Geçersiz kullanıcı sertifikası, yerel merkezi bağlantı kullanılamayacak, lütfen Xiaomi Home entegrasyon sayfasına girin, yeniden kimlik doğrulaması yapmak için 'Seçenekler'e tıklayın",
"device_cloud_error": "Buluttan cihaz bilgileri alınırken bir istisna oluştu, lütfen yerel ağ bağlantısını kontrol edin",
"xiaomi_home_error_title": "Xiaomi Home Entegrasyon Hatası",
"xiaomi_home_error": "**{nick_name}({uid}, {cloud_server})** hatası algılandı, lütfen yeniden yapılandırmak için seçenekler sayfasına girin.\n\n**Hata mesajı**: \n{message}",
"device_list_changed_title": "Xiaomi Home cihaz listesi değişiklikleri",
"device_list_changed": "**{nick_name}({uid}, {cloud_server})** cihaz bilgilerinin değiştiği algılandı, lütfen entegrasyon seçenekleri sayfasına girin, yerel cihaz bilgilerini güncellemek için `Seçenekler->Cihaz listesini güncelle`ye tıklayın.\n\nGeçerli ağ durumu: {network_status}\n{message}\n",
"device_list_add": "\n**{count} yeni cihaz:** \n{message}",
"device_list_del": "\n**{count} cihaz kullanılamıyor:** \n{message}",
"device_list_offline": "\n**{count} cihaz çevrimdışı:** \n{message}",
"network_status_online": "Çevrimiçi",
"network_status_offline": "Çevrimdışı",
"central_state_changed_title": "Merkezi Hub Ağ Geçidi Bağlantı Durumu",
"central_state_changed": "**{nick_name}({uid}, {cloud_server})** Xiaomi merkezi hub ağ geçidine yerel bağlantı: {conn_status}",
"central_state_connected": "Bağlandı",
"central_state_disconnected": "Bağlantı kesildi",
"device_exec_error": "Yürütme hatası"
}
},
"error": {
"common": {
"-10000": "Bilinmeyen hata",
"-10001": "Hizmet kullanılamıyor",
"-10002": "Geçersiz parametre",
"-10003": "Yetersiz kaynaklar",
"-10004": "İç hata",
"-10005": "Yetersiz izinler",
"-10006": "Yürütme zaman aşımı",
"-10007": "Cihaz çevrimdışı veya mevcut değil",
"-10020": "Yetkisiz (OAuth2)",
"-10030": "Geçersiz token (HTTP)",
"-10040": "Geçersiz mesaj formatı",
"-10050": "Geçersiz sertifika",
"-704000000": "Bilinmeyen hata",
"-704010000": "Yetkisiz (cihaz silinmiş olabilir)",
"-704014006": "Cihaz açıklaması bulunamadı",
"-704030013": "Özellik okunabilir değil",
"-704030023": "Özellik yazılabilir değil",
"-704030033": "Özellik abone edilebilir değil",
"-704040002": "Hizmet mevcut değil",
"-704040003": "Özellik mevcut değil",
"-704040004": "Olay mevcut değil",
"-704040005": "Eylem mevcut değil",
"-704040999": "Özellik çevrimiçi değil",
"-704042001": "Cihaz mevcut değil",
"-704042011": "Cihaz çevrimdışı",
"-704053036": "Cihaz işlemi zaman aşımı",
"-704053100": "Cihaz mevcut durumda bu işlemi gerçekleştiremiyor",
"-704083036": "Cihaz işlemi zaman aşımı",
"-704090001": "Cihaz mevcut değil",
"-704220008": "Geçersiz ID",
"-704220025": "Eylem parametre sayısı uyumsuz",
"-704220035": "Eylem parametre hatası",
"-704220043": "Özellik değer hatası",
"-704222034": "Eylem dönüş değer hatası",
"-705004000": "Bilinmeyen hata",
"-705004501": "Bilinmeyen hata",
"-705201013": "Özellik okunabilir değil",
"-705201015": "Eylem yürütme hatası",
"-705201023": "Özellik yazılabilir değil",
"-705201033": "Özellik abone edilebilir değil",
"-706012000": "Bilinmeyen hata",
"-706012013": "Özellik okunabilir değil",
"-706012015": "Eylem yürütme hatası",
"-706012023": "Özellik yazılabilir değil",
"-706012033": "Özellik abone edilebilir değil",
"-706012043": "Özellik değer hatası",
"-706014006": "Cihaz açıklaması bulunamadı"
}
}
}

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} 个设备离线**: \n{message}",
"network_status_online": "在线",
"network_status_offline": "离线",
"central_state_changed_title": "中枢网关连接状态",
"central_state_changed":"**{nick_name}({uid}, {cloud_server})** 中枢网关本地连接链路: {conn_status}",
"central_state_connected": "已连接",
"central_state_disconnected": "断连",
"device_exec_error": "执行错误"
}
},

View File

@@ -99,6 +99,10 @@
"device_list_offline": "\n**{count} 個設備離線:** \n{message}",
"network_status_online": "在線",
"network_status_offline": "離線",
"central_state_changed_title": "中枢網關連接狀態",
"central_state_changed":"**{nick_name}({uid}, {cloud_server})** 中枢網關本地連接鏈路: {conn_status}",
"central_state_connected": "已連接",
"central_state_disconnected": "断連",
"device_exec_error": "執行錯誤"
}
},

View File

@@ -63,7 +63,8 @@ from .common import MIoTMatcher, slugify_did
from .const import (
DEFAULT_CTRL_MODE, DEFAULT_INTEGRATION_LANGUAGE, DEFAULT_NICK_NAME, DOMAIN,
MIHOME_CERT_EXPIRE_MARGIN, NETWORK_REFRESH_INTERVAL,
OAUTH2_CLIENT_ID, SUPPORT_CENTRAL_GATEWAY_CTRL)
OAUTH2_CLIENT_ID, SUPPORT_CENTRAL_GATEWAY_CTRL,
DEFAULT_COVER_DEAD_ZONE_WIDTH)
from .miot_cloud import MIoTHttpClient, MIoTOauthClient
from .miot_error import MIoTClientError, MIoTErrorCode
from .miot_mips import (
@@ -252,7 +253,18 @@ class MIoTClient:
if not self._user_config:
# Integration need to be add again
raise MIoTClientError('load_user_config_async error')
_LOGGER.debug('user config, %s', json.dumps(self._user_config))
# Hide sensitive info in printing
p_user_config: dict = deepcopy(self._user_config)
p_access_token: str = p_user_config['auth_info']['access_token']
p_refresh_token: str = p_user_config['auth_info']['refresh_token']
p_mac_key: str = p_user_config['auth_info']['mac_key']
p_user_config['auth_info'][
'access_token'] = f"{p_access_token[:5]}***{p_access_token[-5:]}"
p_user_config['auth_info'][
'refresh_token'] = f"{p_refresh_token[:5]}***{p_refresh_token[-5:]}"
p_user_config['auth_info'][
'mac_key'] = f"{p_mac_key[:5]}***{p_mac_key[-5:]}"
_LOGGER.debug('user config, %s', json.dumps(p_user_config))
# MIoT i18n client
self._i18n = MIoTI18n(
lang=self._entry_data.get(
@@ -486,6 +498,11 @@ class MIoTClient:
def display_binary_bool(self) -> bool:
return self._display_binary_bool
@property
def cover_dead_zone_width(self) -> int:
return self._entry_data.get('cover_dead_zone_width',
DEFAULT_COVER_DEAD_ZONE_WIDTH)
@display_devices_changed_notify.setter
def display_devices_changed_notify(self, value: list[str]) -> None:
if set(value) == set(self._display_devs_notify):
@@ -990,7 +1007,7 @@ class MIoTClient:
and self._device_list_cloud[did].get('online', False)
):
from_new = 'cloud'
if from_new == from_old:
if (from_new == from_old) and (from_new=='cloud' or from_new=='lan'):
# No need to update
return
# Unsub old
@@ -1109,8 +1126,10 @@ class MIoTClient:
_LOGGER.info('local mips state changed, %s, %s', group_id, state)
mips = self._mips_local.get(group_id, None)
if not mips:
_LOGGER.error(
_LOGGER.info(
'local mips state changed, mips not exist, %s', group_id)
# The connection to the central hub gateway is definitely broken.
self.__show_central_state_changed_notify(False)
return
if state:
# Connected
@@ -1144,6 +1163,7 @@ class MIoTClient:
if sub and sub.handler:
sub.handler(did, MIoTDeviceState.OFFLINE, sub.handler_ctx)
self.__request_show_devices_changed_notify()
self.__show_central_state_changed_notify(state)
@final
async def __on_miot_lan_state_change(self, state: bool) -> None:
@@ -1354,6 +1374,14 @@ class MIoTClient:
"""Update cloud devices.
NOTICE: This function will operate the cloud_list
"""
# 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.') 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:
continue
@@ -1481,8 +1509,6 @@ class MIoTClient:
if did not in filter_dids:
continue
device_old = self._device_list_gateway.get(did, None)
gw_state_old = device_old.get(
'online', False) if device_old else False
gw_state_new: bool = False
device_new = gw_list.pop(did, None)
if device_new:
@@ -1496,7 +1522,7 @@ class MIoTClient:
device_old['online'] = False
# Update cache group_id
info['group_id'] = group_id
if gw_state_old == gw_state_new:
if not gw_state_new:
continue
self.__update_device_msg_sub(did=did)
state_old: Optional[bool] = info.get('online', None)
@@ -1906,6 +1932,23 @@ class MIoTClient:
self._show_devices_changed_notify_timer = self._main_loop.call_later(
delay_sec, self.__show_devices_changed_notify)
@final
def __show_central_state_changed_notify(self, connected: bool) -> None:
conn_status: str = (
self._i18n.translate('miot.client.central_state_connected')
if connected else
self._i18n.translate('miot.client.central_state_disconnected'))
self._persistence_notify(
self.__gen_notify_key('central_state_changed'),
self._i18n.translate('miot.client.central_state_changed_title'),
self._i18n.translate(key='miot.client.central_state_changed',
replace={
'nick_name': self._entry_data.get(
'nick_name', DEFAULT_NICK_NAME),
'uid': self._uid,
'cloud_server': self._cloud_server,
'conn_status': conn_status
}))
@staticmethod
async def get_miot_instance_async(

View File

@@ -59,6 +59,7 @@ import aiohttp
# pylint: disable=relative-beyond-top-level
from .common import calc_group_id
from .const import (
UNSUPPORTED_MODELS,
DEFAULT_OAUTH2_API_HOST,
MIHOME_HTTP_API_TIMEOUT,
OAUTH2_AUTH_URL)
@@ -542,6 +543,7 @@ class MIoTHttpClient:
req_data: dict = {
'limit': 200,
'get_split_device': True,
'get_third_device': True,
'dids': dids
}
if start_did:
@@ -573,6 +575,10 @@ class MIoTHttpClient:
# were implemented.
_LOGGER.info('ignore miwifi.* device, cloud, %s', did)
continue
if model in UNSUPPORTED_MODELS:
_LOGGER.info('ignore unsupported model %s, cloud, %s',
model, did)
continue
device_infos[did] = {
'did': did,
'uid': device.get('uid', None),

View File

@@ -747,6 +747,7 @@ class MIoTDevice:
'watt': UnitOfPower.WATT,
'w': UnitOfPower.WATT,
'W': UnitOfPower.WATT,
'kW': UnitOfPower.KILO_WATT,
'kWh': UnitOfEnergy.KILO_WATT_HOUR,
'A': UnitOfElectricCurrent.AMPERE,
'mA': UnitOfElectricCurrent.MILLIAMPERE,
@@ -1108,6 +1109,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)
@@ -1207,10 +1210,9 @@ class MIoTPropertyEntity(Entity):
self._attr_available = miot_device.online
_LOGGER.info(
'new miot property entity, %s, %s, %s, %s, %s, %s, %s',
'new miot property entity, %s, %s, %s, %s, %s',
self.miot_device.name, self._attr_name, spec.platform,
spec.device_class, self.entity_id, self._value_range,
self._value_list)
spec.device_class, self.entity_id)
@property
def device_info(self) -> Optional[DeviceInfo]:
@@ -1280,8 +1282,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()

View File

@@ -110,7 +110,6 @@ class MipsServiceData:
version=IPVersion.V4Only)
if not self.addresses:
raise MipsServiceError('invalid addresses')
self.addresses.sort()
if not service_info.port:
raise MipsServiceError('invalid port')
self.port = service_info.port
@@ -226,7 +225,7 @@ class MipsService:
state_change: ServiceStateChange
) -> None:
_LOGGER.debug(
'mips service state changed, %s, %s, %s',
'mdns discovery changed, %s, %s, %s',
state_change, name, service_type)
if state_change is ServiceStateChange.Removed:

View File

@@ -68,7 +68,7 @@ from paho.mqtt.client import (
# pylint: disable=relative-beyond-top-level
from .common import MIoTMatcher
from .const import MIHOME_MQTT_KEEPALIVE
from .const import UNSUPPORTED_MODELS, MIHOME_MQTT_KEEPALIVE
from .miot_error import MIoTErrorCode, MIoTMipsError
_LOGGER = logging.getLogger(__name__)
@@ -216,7 +216,7 @@ class _MipsClient(ABC):
MQTT_INTERVAL_S = 1
MIPS_QOS: int = 2
UINT32_MAX: int = 0xFFFFFFFF
MIPS_RECONNECT_INTERVAL_MIN: float = 30
MIPS_RECONNECT_INTERVAL_MIN: float = 10
MIPS_RECONNECT_INTERVAL_MAX: float = 600
MIPS_SUB_PATCH: int = 300
MIPS_SUB_INTERVAL: float = 1
@@ -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)
@@ -587,6 +589,13 @@ class _MipsClient(ABC):
def __mqtt_loop_handler(self) -> None:
try:
# If the main loop is closed, stop the internal loop immediately
if self.main_loop.is_closed():
self.log_debug(
'The main loop is closed, stop the internal loop.')
if not self._internal_loop.is_closed():
self._internal_loop.stop()
return
if self._mqtt:
self._mqtt.loop_read()
if self._mqtt:
@@ -639,8 +648,10 @@ 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()
self._mqtt_state = True
self._internal_loop.call_soon(
self._on_mips_connect, rc, props)
@@ -822,7 +833,7 @@ class _MipsClient(ABC):
self._internal_loop.stop()
def __get_next_reconnect_time(self) -> float:
if self._mips_reconnect_interval == 0:
if self._mips_reconnect_interval < self.MIPS_RECONNECT_INTERVAL_MIN:
self._mips_reconnect_interval = self.MIPS_RECONNECT_INTERVAL_MIN
else:
self._mips_reconnect_interval = min(
@@ -830,6 +841,9 @@ class _MipsClient(ABC):
self.MIPS_RECONNECT_INTERVAL_MAX)
return self._mips_reconnect_interval
def __reset_reconnect_time(self) -> None:
self._mips_reconnect_interval = 0
class MipsCloudClient(_MipsClient):
"""MIoT Pub/Sub Cloud Client."""
@@ -990,6 +1004,13 @@ class MipsCloudClient(_MipsClient):
handler(
did, MIoTDeviceState.ONLINE if msg['event'] == 'online'
else MIoTDeviceState.OFFLINE, ctx)
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)
@@ -1174,7 +1195,7 @@ class MipsLocalClient(_MipsClient):
or 'piid' not in msg
or 'value' not in msg
):
# self.log_error(f'on_prop_msg, recv unknown msg, {payload}')
self.log_info('unknown prop msg, %s', payload)
return
if handler:
self.log_debug('local, on properties_changed, %s', payload)
@@ -1361,6 +1382,9 @@ class MipsLocalClient(_MipsClient):
if name is None or urn is None or model is None:
self.log_error(f'invalid device info, {did}, {info}')
continue
if model in UNSUPPORTED_MODELS:
self.log_info(f'unsupported model, {model}, {did}')
continue
device_list[did] = {
'did': did,
'name': name,

View File

@@ -66,7 +66,7 @@ class MIoTSpecValueRange:
"""MIoT SPEC value range class."""
min_: int
max_: int
step: int
step: int | float
def __init__(self, value_range: Union[dict, list]) -> None:
if isinstance(value_range, dict):
@@ -567,9 +567,8 @@ class MIoTSpecProperty(_MIoTSpecBase):
return
self._value_range = MIoTSpecValueRange(value_range=value)
if isinstance(value, list):
self.precision = len(str(
value[2]).split('.')[1].rstrip('0')) if '.' in str(
value[2]) else 0
step_: str = format(value[2], '.10f').rstrip('0').rstrip('.')
self.precision = len(step_.split('.')[1]) if '.' in step_ else 0
@property
def value_list(self) -> Optional[MIoTSpecValueList]:
@@ -601,7 +600,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:

View File

@@ -90,6 +90,9 @@ translate:
ru:
'false': Ложь
'true': Истина
tr:
'false': Yanlış
'true': Doğru
zh-Hans:
'false':
'true':
@@ -127,6 +130,9 @@ translate:
ru:
'false': Нет контакта
'true': Контакт
tr:
'false': Temas Yok
'true': Temas
zh-Hans:
'false': 分离
'true': 接触
@@ -164,6 +170,9 @@ translate:
ru:
'false': Движение не обнаружено
'true': Обнаружено движение
tr:
'false': Hareket Algılanmadı
'true': Hareket Algılandı
zh-Hans:
'false': 无人
'true': 有人
@@ -201,6 +210,9 @@ translate:
ru:
'false': Закрыть
'true': Открыть
tr:
'false': Kapalı
'true': ık
zh-Hans:
'false': 关闭
'true': 开启
@@ -238,6 +250,9 @@ translate:
ru:
'false': Нет
'true': Да
tr:
'false': Hayır
'true': Evet
zh-Hans:
'false':
'true':

View File

@@ -5,6 +5,18 @@
"service:003:property:001:valuelist:001": "Dry"
}
},
"urn:miot-spec-v2:device:electronic-valve:0000A0A7:ykcn-cbcs": {
"zh-Hans": {
"service:004:property:001": "功率过高-阈值设置",
"service:004:property:009": "欠压告警-阈值设置"
}
},
"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 +286,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

View File

@@ -1,3 +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.*
@@ -41,10 +47,23 @@ urn:miot-spec-v2:device:motion-sensor:0000A014:xiaomi-pir1:
services:
- '1'
- '5'
urn:miot-spec-v2:device:router:0000A036:xiaomi-rd03:
services:
- '*'
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'

View File

@@ -1,11 +1,32 @@
urn:miot-spec-v2:device:air-condition-outlet:0000A045:lumi-mcn04:1:
prop.3.4:
format: uint8
urn:miot-spec-v2:device:air-conditioner:0000A004:qdhkl-a42:1:
prop.2.2:
value-list:
- value: 1
description: Cool
- value: 2
description: Dry
- value: 4
description: Fan
- value: 8
description: Heat
- value: 9
description: Auto
- value: 10
description: Heat_cool
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c17:1:
prop.10.6:
unit: none
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c17:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c17:1
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c20:1:
prop.10.6:
unit: none
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c20:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c20:1
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c24:1:
prop.8.6:
unit: kWh
prop.10.6:
unit: none
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c24:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-c24:1
@@ -13,6 +34,19 @@ 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-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
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:1
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:3: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:1
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:4: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m16:1
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m9:1: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m9:6
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m9:2: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m9:6
urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m9:3: urn:miot-spec-v2:device:air-conditioner:0000A004:xiaomi-m9:6
@@ -26,6 +60,30 @@ 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:
- -30
- 100
- 0.1
urn:miot-spec-v2:device:air-monitor:0000A008:cgllc-s1:1:
prop.2.5:
name: voc-density
@@ -41,6 +99,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:
@@ -75,6 +135,50 @@ urn:miot-spec-v2:device:bath-heater:0000A028:opple-acmoto:1:
urn:miot-spec-v2:device:bath-heater:0000A028:xiaomi-s1:1:
prop.4.4:
name: fan-level-ventilation
urn:miot-spec-v2:device:curtain:0000A00C:bjkcz-kczble:1:0000D031:
prop.2.2:
name: status-a
urn:miot-spec-v2:device:electronic-valve:0000A0A7:sanmei-s1:1:
prop.3.1:
format: float
value-range:
- 0
- 99999999
- 0.01
expr: round(src_value/100, 2)
prop.3.2:
format: float
value-range:
- 0
- 16777216
- 0.01
expr: round(src_value/100, 2)
prop.3.3:
format: float
value-range:
- 0
- 65535
- 0.1
expr: round(src_value/10, 1)
urn:miot-spec-v2:device:electronic-valve:0000A0A7:ykcn-cbcs:1:0000C833:
prop.3.1:
format: float
value-range:
- 0
- 99999999
- 0.01
expr: round(src_value/100, 2)
prop.3.2:
unit: mA
prop.3.3:
format: float
value-range:
- 0
- 65535
- 0.1
expr: round(src_value/10, 1)
prop.4.1:
unit: kW
urn:miot-spec-v2:device:fan:0000A005:dmaker-p33:1:
prop.2.2:
name: fan-level-a
@@ -90,12 +194,21 @@ urn:miot-spec-v2:device:fan:0000A005:dmaker-p5:1:
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p43:1:
prop.2.2:
name: fan-level-a
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p45:1:0000D062:
prop.2.4:
name: fan-level-a
urn:miot-spec-v2:device:fan:0000A005:xiaomi-p51:1:
prop.2.2:
name: fan-level-a
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
@@ -141,6 +254,11 @@ 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:hood:0000A01B:cykj-jyj22:4: urn:miot-spec-v2:device:hood:0000A01B:cykj-jyj22:3
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
@@ -150,6 +268,9 @@ urn:miot-spec-v2:device:light:0000A001:shhf-sfla10:1:
urn:miot-spec-v2:device:light:0000A001:shhf-sfla12:1:
prop.8.11:
name: on-a
urn:miot-spec-v2:device:light:0000A001:shhf-sflt11:1:0000C802:
prop.11.14:
name: on-power
urn:miot-spec-v2:device:magnet-sensor:0000A016:linp-m1:1:
prop.2.1004:
name: contact-state
@@ -158,17 +279,37 @@ urn:miot-spec-v2:device:magnet-sensor:0000A016:linp-m1:1:
description: open
- value: 1
description: closed
expr: src_value!=1
expr: (src_value!=1)
urn:miot-spec-v2:device:motion-sensor:0000A014:lumi-acn001:1:
prop.3.2:
access:
- read
- notify
unit: mV
urn:miot-spec-v2:device:motion-sensor:0000A014:lumi-bmgl01:1:
prop.2.2:
value-list:
- value: 0
description: 0 Seconds
- value: 2
description: 2 Minutes
- value: 5
description: 5 Minutes
urn:miot-spec-v2:device:motor-controller:0000A01D:adp-adswb4:1:0000C837:
prop.2.1:
name: motor-switch
urn:miot-spec-v2:device:occupancy-sensor:0000A0BF:ainice-3b:1: urn:miot-spec-v2:device:occupancy-sensor:0000A0BF:ainice-3b:2
urn:miot-spec-v2:device:occupancy-sensor:0000A0BF:ainice-3b:2:
prop.2.5:
name: people-number
prop.2.8:
name: people-number
prop.2.11:
name: people-number
prop.2.14:
name: people-number
prop.2.17:
name: people-number
urn:miot-spec-v2:device:occupancy-sensor:0000A0BF:izq-24:2:0000C824:
prop.2.6:
unit: cm
@@ -179,26 +320,57 @@ urn:miot-spec-v2:device:outlet:0000A002:chuangmi-212a01:1: urn:miot-spec-v2:devi
urn:miot-spec-v2:device:outlet:0000A002:chuangmi-212a01:2: urn:miot-spec-v2:device:outlet:0000A002:chuangmi-212a01:3
urn:miot-spec-v2:device:outlet:0000A002:chuangmi-212a01:3:
prop.5.1:
expr: round(src_value*6/1000000, 3)
format: float
value-range:
- 0
- 65535
- 0.01
expr: round(src_value*6/1000000, 2)
urn:miot-spec-v2:device:outlet:0000A002:cuco-cp1md:1:
prop.2.2:
name: power-consumption
expr: round(src_value/1000, 3)
format: float
value-range:
- 0
- 65535
- 0.01
expr: round(src_value/1000, 2)
prop.2.3:
format: float
value-range:
- 0
- 3000
- 0.1
expr: round(src_value/10, 1)
prop.2.4:
unit: mA
urn:miot-spec-v2:device:outlet:0000A002:cuco-cp2:1: urn:miot-spec-v2:device:outlet:0000A002:cuco-cp2:2
urn:miot-spec-v2:device:outlet:0000A002:cuco-cp2:2:
prop.2.3:
format: float
value-range:
- 0
- 3000
- 0.1
expr: round(src_value/10, 1)
prop.2.4:
unit: mA
prop.3.2:
format: float
value-range:
- 0
- 65535
- 0.1
expr: round(src_value/10, 1)
urn:miot-spec-v2:device:outlet:0000A002:cuco-cp2d:1:
prop.3.2:
unit: mA
urn:miot-spec-v2:device:outlet:0000A002:cuco-v3:1:
prop.11.1:
name: power-consumption
format: float
value-range:
- 0
- 65535
- 0.01
expr: round(src_value/100, 2)
urn:miot-spec-v2:device:outlet:0000A002:cuco-v3:2: urn:miot-spec-v2:device:outlet:0000A002:cuco-v3:1
urn:miot-spec-v2:device:outlet:0000A002:giot-v8icm:1:0000C816:
@@ -209,10 +381,22 @@ urn:miot-spec-v2:device:outlet:0000A002:qmi-psv3:1:0000C816:
unit: mV
prop.3.4:
unit: mA
urn:miot-spec-v2:device:outlet:0000A002:yutai-fsov8m:1:0000C816:
prop.4.1:
format: float
value-range:
- 0
- 429497
- 0.01
expr: round(src_value/10000, 2)
urn:miot-spec-v2:device:outlet:0000A002:zimi-zncz01:1:0000C816: urn:miot-spec-v2:device:outlet:0000A002:zimi-zncz01:2:0000C816
urn:miot-spec-v2:device:outlet:0000A002:zimi-zncz01:2:0000C816:
prop.3.1:
name: electric-power
format: float
value-range:
- 0
- 350000
- 0.01
expr: round(src_value/100, 2)
urn:miot-spec-v2:device:plant-monitor:0000A030:hhcc-v1:1:
prop.2.1:
@@ -237,7 +421,7 @@ urn:miot-spec-v2:device:router:0000A036:xiaomi-rd08:1:
urn:miot-spec-v2:device:safe-box:0000A042:loock-v1:1:
prop.5.1:
name: contact-state
expr: src_value!=1
expr: (src_value!=1)
urn:miot-spec-v2:device:switch:0000A003:090615-x1tpm:1:0000D042:
prop.27.3:
name: light-on
@@ -245,10 +429,20 @@ urn:miot-spec-v2:device:switch:0000A003:090615-x1tpm:1:0000D042:
name: light-fan-on
urn:miot-spec-v2:device:switch:0000A003:lxzn-cbcsmj:1:0000D00D:
prop.3.1:
format: float
value-range:
- 0
- 99999999
- 0.01
expr: round(src_value/100, 2)
prop.3.2:
expr: round(src_value/1000, 2)
unit: mA
prop.3.3:
format: float
value-range:
- 0
- 65535
- 0.1
expr: round(src_value/10, 1)
urn:miot-spec-v2:device:thermostat:0000A031:suittc-wk168:1:
prop.2.3:

View File

@@ -50,18 +50,11 @@ from homeassistant.components.sensor import SensorStateClass
from homeassistant.components.event import EventDeviceClass
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
EntityCategory,
LIGHT_LUX,
UnitOfEnergy,
UnitOfPower,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfTemperature,
UnitOfPressure,
PERCENTAGE
)
from homeassistant.const import (CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
EntityCategory, LIGHT_LUX, UnitOfEnergy,
UnitOfPower, UnitOfElectricCurrent,
UnitOfElectricPotential, UnitOfTemperature,
UnitOfPressure, PERCENTAGE)
# pylint: disable=pointless-string-statement
"""SPEC_DEVICE_TRANS_MAP
@@ -107,7 +100,7 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'humidifier': {
'required': {
'humidifier': {
'required': {
'required': {
'properties': {
'on': {'read', 'write'}
}
@@ -119,7 +112,7 @@ SPEC_DEVICE_TRANS_MAP: dict = {
},
'optional': {
'environment': {
'required': {
'required': {
'properties': {
'relative-humidity': {'read'}
}
@@ -131,7 +124,7 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'dehumidifier': {
'required': {
'dehumidifier': {
'required': {
'required': {
'properties': {
'on': {'read', 'write'}
}
@@ -143,7 +136,7 @@ SPEC_DEVICE_TRANS_MAP: dict = {
},
'optional': {
'environment': {
'required': {
'required': {
'properties': {
'relative-humidity': {'read'}
}
@@ -155,15 +148,13 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'vacuum': {
'required': {
'vacuum': {
'required': {
'required': {
'actions': {'start-sweep', 'stop-sweeping'},
},
'optional': {
'properties': {'status', 'fan-level'},
'actions': {
'pause-sweeping',
'continue-sweep',
'stop-and-gocharge'
'pause-sweeping', 'continue-sweep', 'stop-and-gocharge'
}
}
}
@@ -171,13 +162,13 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'optional': {
'identify': {
'required': {
'actions': {'identify'}
'actions': {'identify'}
}
},
'battery': {
'required': {
'properties': {
'battery-level': {'read'}
'actions': {
'start-charge'
}
}
}
@@ -204,10 +195,9 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'required': {},
'optional': {
'properties': {
'on',
'fan-level',
'horizontal-swing',
'vertical-swing'}}
'on', 'fan-level', 'horizontal-swing', 'vertical-swing'
}
}
},
'environment': {
'required': {},
@@ -235,8 +225,8 @@ SPEC_DEVICE_TRANS_MAP: dict = {
},
'optional': {
'properties': {
'target-temperature', 'mode', 'fan-level',
'temperature'}
'target-temperature', 'mode', 'fan-level', 'temperature'
}
}
}
},
@@ -278,7 +268,7 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'ptc-bath-heater': {
'required': {
'properties': {
'mode':{'read', 'write'}
'mode': {'read', 'write'}
}
},
'optional': {
@@ -321,6 +311,89 @@ SPEC_DEVICE_TRANS_MAP: dict = {
'optional': {},
'entity': 'electric-blanket'
},
'speaker': {
'required': {
'speaker': {
'required': {
'properties': {
'volume': {'read', 'write'}
}
},
'optional': {
'properties': {'mute'}
}
},
'play-control': {
'required': {
'actions': {'play'}
},
'optional': {
'properties': {'playing-state'},
'actions': {'pause', 'stop', 'next', 'previous'}
}
}
},
'optional': {},
'entity': 'wifi-speaker'
},
'television': {
'required': {
'speaker': {
'required': {
'properties': {
'volume': {'read', 'write'}
}
},
'optional': {
'properties': {'mute'}
}
},
'television': {
'required': {
'actions': {'turn-off'}
},
'optional': {
'properties': {'input-control'},
'actions': {'turn-on'}
}
}
},
'optional': {
'play-control': {
'required': {},
'optional': {
'properties': {'playing-state'},
'actions': {'play', 'pause', 'stop', 'next', 'previous'}
}
}
},
'entity': 'television'
},
'watch': {
'required': {
'watch': {
'required': {
'properties': {
'longitude': {'read'},
'latitude': {'read'}
}
},
'optional': {
'properties': {'area-id'}
}
}
},
'optional': {
'battery': {
'required': {
'properties': {
'battery-level': {'read'}
}
}
}
},
'entity': 'device_tracker'
}
}
"""SPEC_SERVICE_TRANS_MAP
@@ -351,9 +424,7 @@ SPEC_SERVICE_TRANS_MAP: dict = {
}
},
'optional': {
'properties': {
'mode', 'brightness', 'color', 'color-temperature'
}
'properties': {'mode', 'brightness', 'color', 'color-temperature'}
},
'entity': 'light'
},
@@ -368,7 +439,8 @@ SPEC_SERVICE_TRANS_MAP: dict = {
},
'optional': {
'properties': {
'mode', 'brightness',
'mode',
'brightness',
}
},
'entity': 'light',
@@ -401,16 +473,14 @@ SPEC_SERVICE_TRANS_MAP: dict = {
},
'entity': 'water_heater'
},
'curtain': {
'curtain': {
'required': {
'properties': {
'motor-control': {'write'}
}
},
'optional': {
'properties': {
'status', 'current-position', 'target-position'
}
'properties': {'status', 'current-position', 'target-position'}
},
'entity': 'cover'
},
@@ -600,6 +670,4 @@ SPEC_EVENT_TRANS_MAP: dict[str, str] = {
'doorbell-ring': EventDeviceClass.DOORBELL
}
SPEC_ACTION_TRANS_MAP = {
}
SPEC_ACTION_TRANS_MAP = {}

View File

@@ -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(

View File

@@ -4,7 +4,7 @@
"step": {
"eula": {
"title": "Risikohinweis",
"description": "1. Ihre **Xiaomi-Benutzerinformationen und Geräteinformationen** werden in Ihrem Home Assistant-System gespeichert. **Xiaomi kann die Sicherheit des Home Assistant-Speichermechanismus nicht garantieren**. Sie sind dafür verantwortlich, Ihre Informationen vor Diebstahl zu schützen.\r\n2. Diese Integration wird von der Open-Source-Community unterstützt und gewartet. Es können jedoch Stabilitätsprobleme oder andere Probleme auftreten. Wenn Sie auf ein Problem stoßen, das mit dieser Integration zusammenhängt, sollten Sie **die Open-Source-Community um Hilfe bitten, anstatt sich an den Xiaomi Home Kundendienst zu wenden**.\r\n3. Sie benötigen bestimmte technische Fähigkeiten, um Ihre lokale Laufzeitumgebung zu warten. Diese Integration ist für Anfänger nicht geeignet. \r\n4. Bevor Sie diese Integration verwenden, lesen Sie bitte die **README-Datei sorgfältig durch**.\r\n5. Um eine stabile Nutzung der Integration zu gewährleisten und Missbrauch der Schnittstelle zu verhindern, **darf diese Integration nur in Home Assistant verwendet werden. Weitere Informationen finden Sie in der LICENSE**.",
"description": "1. Ihre **Xiaomi-Benutzerinformationen und Geräteinformationen** werden in Ihrem Home Assistant-System gespeichert. **Xiaomi kann die Sicherheit des Home Assistant-Speichermechanismus nicht garantieren**. Sie sind dafür verantwortlich, Ihre Informationen vor Diebstahl zu schützen.\r\n2. Diese Integration wird von der Open-Source-Community unterstützt und gewartet. Es können jedoch Stabilitätsprobleme oder andere Probleme auftreten. Wenn Sie auf ein Problem stoßen, das mit dieser Integration zusammenhängt, sollten Sie **die Open-Source-Community um Hilfe bitten, anstatt sich an den Xiaomi Home Kundendienst zu wenden**.\r\n3. Sie benötigen bestimmte technische Fähigkeiten, um Ihre lokale Laufzeitumgebung zu warten. Diese Integration ist für Anfänger nicht geeignet.\r\n4. Bevor Sie diese Integration verwenden, lesen Sie bitte die **README-Datei sorgfältig durch**.\r\n5. Um eine stabile Nutzung der Integration zu gewährleisten und Missbrauch der Schnittstelle zu verhindern, **darf diese Integration nur in Home Assistant verwendet werden. Weitere Informationen finden Sie in der LICENSE**.",
"data": {
"eula": "Ich habe das oben genannte Risiko zur Kenntnis genommen und übernehme freiwillig die damit verbundenen Risiken durch die Verwendung der Integration."
}
@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Gerätestatusänderungen anzeigen",
"update_trans_rules": "Entitätskonvertierungsregeln aktualisieren",
"update_lan_ctrl_config": "LAN-Steuerungskonfiguration aktualisieren",
"network_detect_config": "Integrierte Netzwerkkonfiguration"
"network_detect_config": "Integrierte Netzwerkkonfiguration",
"cover_dead_zone_width": "Die Breite des toten Winkels des Vorhangs"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Bestätigen Sie die Konfiguration",
"description": "**{nick_name}**, bitte bestätigen Sie die neuesten Konfigurationsinformationen und klicken Sie dann auf \"Senden\". Die Integration wird mit den aktualisierten Konfigurationen erneut geladen.\r\n\r\nIntegrationsprache:\t{lang_new}\r\nBenutzername:\t{nick_name_new}\r\nAction-Debug-Modus:\t{action_debug}\r\nVerstecke Nicht-Standard-Entitäten:\t{hide_non_standard_entities}\r\nGerätestatusänderungen anzeigen:\t{display_devices_changed_notify}\r\nGeräteänderungen:\t{devices_add} neue Geräte hinzufügen, {devices_remove} Geräte entfernen\r\nKonvertierungsregeländerungen:\tInsgesamt {trans_rules_count} Regeln, aktualisiert {trans_rules_count_success} Regeln",
"description": "**{nick_name}**, bitte bestätigen Sie die neuesten Konfigurationsinformationen und klicken Sie dann auf \"Senden\". Die Integration wird mit den aktualisierten Konfigurationen erneut geladen.\r\n\r\nIntegrationsprache:\t{lang_new}\r\nBenutzername:\t{nick_name_new}\r\nAction-Debug-Modus:\t{action_debug}\r\nVerstecke Nicht-Standard-Entitäten:\t{hide_non_standard_entities}\r\nDie Breite des toten Winkels des Vorhangs:\t{cover_width_new}\r\nGerätestatusänderungen anzeigen:\t{display_devices_changed_notify}\r\nGeräteänderungen:\t{devices_add} neue Geräte hinzufügen, {devices_remove} Geräte entfernen\r\nKonvertierungsregeländerungen:\tInsgesamt {trans_rules_count} Regeln, aktualisiert {trans_rules_count_success} Regeln",
"data": {
"confirm": "Änderungen bestätigen"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Display device status change notifications",
"update_trans_rules": "Update entity conversion rules",
"update_lan_ctrl_config": "Update LAN control configuration",
"network_detect_config": "Integrated Network Configuration"
"network_detect_config": "Integrated network configuration",
"cover_dead_zone_width": "Cover dead zone width"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Confirm Configuration",
"description": "Hello **{nick_name}**, please confirm the latest configuration information and then Click SUBMIT.\r\nThe integration will reload using the updated configuration.\r\n\r\nIntegration Language: \t{lang_new}\r\nNickname: \t{nick_name_new}\r\nDebug mode for action: \t{action_debug}\r\nHide non-standard created entities: \t{hide_non_standard_entities}\r\nDisplay device status change notifications:\t{display_devices_changed_notify}\r\nDevice Changes: \tAdd **{devices_add}** devices, Remove **{devices_remove}** devices\r\nTransformation rules change: \tThere are a total of **{trans_rules_count}** rules, and updated **{trans_rules_count_success}** rules",
"description": "Hello **{nick_name}**, please confirm the latest configuration information and then Click SUBMIT.\r\nThe integration will reload using the updated configuration.\r\n\r\nIntegration Language:\t{lang_new}\r\nNickname:\t{nick_name_new}\r\nDebug mode for action:\t{action_debug}\r\nHide non-standard created entities:\t{hide_non_standard_entities}\r\nCover dead zone width:\t{cover_width_new}\r\nDisplay device status change notifications:\t{display_devices_changed_notify}\r\nDevice Changes:\tAdd **{devices_add}** devices, Remove **{devices_remove}** devices\r\nTransformation rules change:\tThere are a total of **{trans_rules_count}** rules, and updated **{trans_rules_count_success}** rules",
"data": {
"confirm": "Confirm the change"
}

View File

@@ -4,7 +4,7 @@
"step": {
"eula": {
"title": "Aviso de riesgo",
"description": "1. Su **información de usuario de Xiaomi e información del dispositivo** se almacenará en su sistema Home Assistant. **Xiaomi no puede garantizar la seguridad del mecanismo de almacenamiento de Home Assistant**. Usted es responsable de evitar que su información sea robada.\r\n2. Esta integración es mantenida por la comunidad de código abierto y puede haber problemas de estabilidad u otros problemas. Cuando tenga problemas relacionados con el uso de esta integración, **busque ayuda en la comunidad de código abierto en lugar de contactar al servicio al cliente de Xiaomi**.\r\n3. Es necesario tener ciertas habilidades técnicas para mantener su entorno de ejecución local, esta integración no es amigable para los usuarios novatos.\r\n4. Antes de utilizar esta integración, por favor **lea detenidamente el archivo README**. \r\n5. Para garantizar el uso estable de la integración y prevenir el abuso de la interfaz, **esta integración solo está permitida en Home Assistant. Para más detalles, consulte la LICENSE**.",
"description": "1. Su **información de usuario de Xiaomi e información del dispositivo** se almacenará en su sistema Home Assistant. **Xiaomi no puede garantizar la seguridad del mecanismo de almacenamiento de Home Assistant**. Usted es responsable de evitar que su información sea robada.\r\n2. Esta integración es mantenida por la comunidad de código abierto y puede haber problemas de estabilidad u otros problemas. Cuando tenga problemas relacionados con el uso de esta integración, **busque ayuda en la comunidad de código abierto en lugar de contactar al servicio al cliente de Xiaomi**.\r\n3. Es necesario tener ciertas habilidades técnicas para mantener su entorno de ejecución local, esta integración no es amigable para los usuarios novatos.\r\n4. Antes de utilizar esta integración, por favor **lea detenidamente el archivo README**.\r\n5. Para garantizar el uso estable de la integración y prevenir el abuso de la interfaz, **esta integración solo está permitida en Home Assistant. Para más detalles, consulte la LICENSE**.",
"data": {
"eula": "He leído y entiendo los riesgos anteriores, y estoy dispuesto a asumir cualquier riesgo relacionado con el uso de esta integración."
}
@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Mostrar notificaciones de cambio de estado del dispositivo",
"update_trans_rules": "Actualizar reglas de conversión de entidad",
"update_lan_ctrl_config": "Actualizar configuración de control LAN",
"network_detect_config": "Configuración de Red Integrada"
"network_detect_config": "Configuración de Red Integrada",
"cover_dead_zone_width": "Anchura del punto ciego de la cortina"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Confirmar configuración",
"description": "¡Hola, **{nick_name}**! Por favor, confirme la última información de configuración y haga clic en \"Enviar\" para finalizar la configuración.\r\nLa integración se volverá a cargar con la nueva configuración.\r\n\r\nIdioma de la integración:\t{lang_new}\r\nApodo de usuario:\t{nick_name_new}\r\nModo de depuración de Action:\t{action_debug}\r\nOcultar entidades generadas no estándar:\t{hide_non_standard_entities}\r\nMostrar notificaciones de cambio de estado del dispositivo:\t{display_devices_changed_notify}\r\nCambios de dispositivos:\t{devices_add} dispositivos agregados, {devices_remove} dispositivos eliminados\r\nCambios en las reglas de conversión:\t{trans_rules_count} reglas en total, {trans_rules_count_success} reglas actualizadas",
"description": "¡Hola, **{nick_name}**! Por favor, confirme la última información de configuración y haga clic en \"Enviar\" para finalizar la configuración.\r\nLa integración se volverá a cargar con la nueva configuración.\r\n\r\nIdioma de la integración:\t{lang_new}\r\nApodo de usuario:\t{nick_name_new}\r\nModo de depuración de Action:\t{action_debug}\r\nOcultar entidades generadas no estándar:\t{hide_non_standard_entities}\r\nAnchura del punto ciego de la cortina:\t{cover_width_new}\r\nMostrar notificaciones de cambio de estado del dispositivo:\t{display_devices_changed_notify}\r\nCambios de dispositivos:\t{devices_add} dispositivos agregados, {devices_remove} dispositivos eliminados\r\nCambios en las reglas de conversión:\t{trans_rules_count} reglas en total, {trans_rules_count_success} reglas actualizadas",
"data": {
"confirm": "Confirmar modificación"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Afficher les notifications de changement d'état de l'appareil",
"update_trans_rules": "Mettre à jour les règles de conversion d'entités",
"update_lan_ctrl_config": "Mettre à jour la configuration de contrôle LAN",
"network_detect_config": "Configuration Réseau Intégrée"
"network_detect_config": "Configuration Réseau Intégrée",
"cover_dead_zone_width": "Largeur de la zone aveugle du rideau"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Confirmer la configuration",
"description": "**{nick_name}** Bonjour ! Veuillez confirmer les dernières informations de configuration et cliquer sur \"Soumettre\".\r\nL'intégration rechargera avec la nouvelle configuration.\r\n\r\nLangue d'intégration : {lang_new}\r\nPseudo utilisateur : {nick_name_new}\r\nMode de débogage d'action : {action_debug}\r\nMasquer les entités générées non standard : {hide_non_standard_entities}\r\nAfficher les notifications de changement d'état de l'appareil:\t{display_devices_changed_notify}\r\nModifications des appareils : Ajouter **{devices_add}** appareils, supprimer **{devices_remove}** appareils\r\nModifications des règles de conversion : **{trans_rules_count}** règles au total, mise à jour de **{trans_rules_count_success}** règles",
"description": "**{nick_name}** Bonjour ! Veuillez confirmer les dernières informations de configuration et cliquer sur \"Soumettre\".\r\nL'intégration rechargera avec la nouvelle configuration.\r\n\r\nLangue d'intégration : {lang_new}\r\nPseudo utilisateur : {nick_name_new}\r\nMode de débogage d'action : {action_debug}\r\nMasquer les entités générées non standard : {hide_non_standard_entities}\r\nLargeur de la zone aveugle du rideau:\t{cover_width_new}\r\nAfficher les notifications de changement d'état de l'appareil:\t{display_devices_changed_notify}\r\nModifications des appareils : Ajouter **{devices_add}** appareils, supprimer **{devices_remove}** appareils\r\nModifications des règles de conversion : **{trans_rules_count}** règles au total, mise à jour de **{trans_rules_count_success}** règles",
"data": {
"confirm": "Confirmer la modification"
}

View File

@@ -113,7 +113,7 @@
},
"config_options": {
"title": "Opzioni di Configurazione",
"description": "### Ciao, {nick_name}\r\n\r\nID Xiaomi: {uid}\r\nRegione di Login Corrente: {cloud_server}\r\n\r\nSeleziona le opzioni che desideri configurare, poi clicca AVANTI.",
"description": "### Ciao, {nick_name}\r\n\r\nID Xiaomi: {uid}\r\nRegione di Login Corrente: {cloud_server}\r\nID istanza di integrazione: {instance_id}\r\n\r\nSeleziona le opzioni che desideri configurare, poi clicca AVANTI.",
"data": {
"integration_language": "Lingua dell'Integrazione",
"update_user_info": "Aggiorna le informazioni dell'utente",
@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Mostra notifiche di cambio stato del dispositivo",
"update_trans_rules": "Aggiorna le regole di conversione delle entità",
"update_lan_ctrl_config": "Aggiorna configurazione del controllo LAN",
"network_detect_config": "Configurazione di Rete Integrata"
"network_detect_config": "Configurazione di Rete Integrata",
"cover_dead_zone_width": "Larghezza dellangolo cieco della tenda"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Conferma Configurazione",
"description": "Ciao **{nick_name}**, si prega di confermare le informazioni di configurazione più recenti e poi fare clic su INVIA.\r\nL'integrazione verrà ricaricata utilizzando la configurazione aggiornata.\r\n\r\nLingua dell'Integrazione: \t{lang_new}\r\nSoprannome: \t{nick_name_new}\r\nModalità di debug per azione: \t{action_debug}\r\nNascondi entità create non standard: \t{hide_non_standard_entities}\r\nMostra notifiche di cambio stato del dispositivo:\t{display_devices_changed_notify}\r\nCambiamenti del Dispositivo: \tAggiungi **{devices_add}** dispositivi, Rimuovi **{devices_remove}** dispositivi\r\nCambiamenti delle regole di trasformazione: \tCi sono un totale di **{trans_rules_count}** regole, e aggiornate **{trans_rules_count_success}** regole",
"description": "Ciao **{nick_name}**, si prega di confermare le informazioni di configurazione più recenti e poi fare clic su INVIA.\r\nL'integrazione verrà ricaricata utilizzando la configurazione aggiornata.\r\n\r\nLingua dell'Integrazione:\t{lang_new}\r\nSoprannome:\t{nick_name_new}\r\nModalità di debug per azione:\t{action_debug}\r\nNascondi entità create non standard:\t{hide_non_standard_entities}\r\nLarghezza dellangolo cieco della tenda:\t{cover_width_new}\r\nMostra notifiche di cambio stato del dispositivo:\t{display_devices_changed_notify}\r\nCambiamenti del Dispositivo:\tAggiungi **{devices_add}** dispositivi, Rimuovi **{devices_remove}** dispositivi\r\nCambiamenti delle regole di trasformazione:\tCi sono un totale di **{trans_rules_count}** regole, e aggiornate **{trans_rules_count_success}** regole",
"data": {
"confirm": "Conferma la modifica"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "デバイスの状態変化通知を表示",
"update_trans_rules": "エンティティ変換ルールを更新する",
"update_lan_ctrl_config": "LAN制御構成を更新する",
"network_detect_config": "統合ネットワーク構成"
"network_detect_config": "統合ネットワーク構成",
"cover_dead_zone_width": "カーテンの死角幅"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "構成を確認する",
"description": "**{nick_name}** さん、こんにちは! 最新の構成情報を確認してください。[送信] をクリックして、更新された構成を使用して再度読み込みます。\r\n\r\n統合言語\t{lang_new}\r\nユーザー名\t{nick_name_new}\r\nAction デバッグモード:\t{action_debug}\r\n非標準生成エンティティを非表示にする\t{hide_non_standard_entities}\r\nデバイスの状態変化通知を表示:\t{display_devices_changed_notify}\r\nデバイス変更\t追加 **{devices_add}** 個のデバイス、削除 **{devices_remove}** 個のデバイス\r\n変換ルール変更\t合計 **{trans_rules_count}** 個の規則、更新 **{trans_rules_count_success}** 個の規則",
"description": "**{nick_name}** さん、こんにちは! 最新の構成情報を確認してください。[送信] をクリックして、更新された構成を使用して再度読み込みます。\r\n\r\n統合言語\t{lang_new}\r\nユーザー名\t{nick_name_new}\r\nAction デバッグモード:\t{action_debug}\r\n非標準生成エンティティを非表示にする\t{hide_non_standard_entities}\r\nカーテンの死角幅:\t{cover_width_new}\r\nデバイスの状態変化通知を表示:\t{display_devices_changed_notify}\r\nデバイス変更\t追加 **{devices_add}** 個のデバイス、削除 **{devices_remove}** 個のデバイス\r\n変換ルール変更\t合計 **{trans_rules_count}** 個の規則、更新 **{trans_rules_count_success}** 個の規則",
"data": {
"confirm": "変更を確認する"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Apparaatstatuswijzigingen weergeven",
"update_trans_rules": "Werk entiteitsconversieregels bij",
"update_lan_ctrl_config": "Werk LAN controleconfiguratie bij",
"network_detect_config": "Geïntegreerde Netwerkconfiguratie"
"network_detect_config": "Geïntegreerde Netwerkconfiguratie",
"cover_dead_zone_width": "Breedte van de dode hoek van het gordijn"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Bevestig Configuratie",
"description": "Hallo **{nick_name}**, bevestig alstublieft de nieuwste configuratie-informatie en klik vervolgens op INDENKEN.\r\nDe integratie zal opnieuw laden met de bijgewerkte configuratie.\r\n\r\nIntegratietaal: \t{lang_new}\r\nBijnaam: \t{nick_name_new}\r\nDebugmodus voor actie: \t{action_debug}\r\nVerberg niet-standaard gemaakte entiteiten: \t{hide_non_standard_entities}\r\nApparaatstatuswijzigingen weergeven:\t{display_devices_changed_notify}\r\nWijzigingen in apparaten: \tVoeg **{devices_add}** apparaten toe, Verwijder **{devices_remove}** apparaten\r\nWijzigingen in transformateregels: \tEr zijn in totaal **{trans_rules_count}** regels, en **{trans_rules_count_success}** regels zijn bijgewerkt",
"description": "Hallo **{nick_name}**, bevestig alstublieft de nieuwste configuratie-informatie en klik vervolgens op INDENKEN.\r\nDe integratie zal opnieuw laden met de bijgewerkte configuratie.\r\n\r\nIntegratietaal:\t{lang_new}\r\nBijnaam:\t{nick_name_new}\r\nDebugmodus voor actie:\t{action_debug}\r\nVerberg niet-standaard gemaakte entiteiten:\t{hide_non_standard_entities}\r\nBreedte van de dode hoek van het gordijn:\t{cover_width_new}\r\nApparaatstatuswijzigingen weergeven:\t{display_devices_changed_notify}\r\nWijzigingen in apparaten:\tVoeg **{devices_add}** apparaten toe, Verwijder **{devices_remove}** apparaten\r\nWijzigingen in transformateregels:\tEr zijn in totaal **{trans_rules_count}** regels, en **{trans_rules_count_success}** regels zijn bijgewerkt",
"data": {
"confirm": "Bevestig de wijziging"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Exibir notificações de mudança de status do dispositivo",
"update_trans_rules": "Atualizar regras de conversão de entidades",
"update_lan_ctrl_config": "Atualizar configuração de controle LAN",
"network_detect_config": "Configuração de Rede Integrada"
"network_detect_config": "Configuração de Rede Integrada",
"cover_dead_zone_width": "Largura da área cega da cortina"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Confirmar Configuração",
"description": "Olá **{nick_name}**, confirme as informações da configuração mais recente e depois clique em ENVIAR.\r\nA integração será recarregada com a configuração atualizada.\r\n\r\nIdioma da Integração:\t{lang_new}\r\nApelido:\t{nick_name_new}\r\nModo de depuração para ação:\t{action_debug}\r\nOcultar entidades não padrão criadas:\t{hide_non_standard_entities}\r\nExibir notificações de mudança de status do dispositivo:\t{display_devices_changed_notify}\r\nAlterações de Dispositivos:\tAdicionar **{devices_add}** dispositivos, Remover **{devices_remove}** dispositivos\r\nAlteração nas Regras de Transformação:\tUm total de **{trans_rules_count}** regras, e **{trans_rules_count_success}** regras atualizadas",
"description": "Olá **{nick_name}**, confirme as informações da configuração mais recente e depois clique em ENVIAR.\r\nA integração será recarregada com a configuração atualizada.\r\n\r\nIdioma da Integração:\t{lang_new}\r\nApelido:\t{nick_name_new}\r\nModo de depuração para ação:\t{action_debug}\r\nOcultar entidades não padrão criadas:\t{hide_non_standard_entities}\r\nLargura da área cega da cortina:\t{cover_width_new}\r\nExibir notificações de mudança de status do dispositivo:\t{display_devices_changed_notify}\r\nAlterações de Dispositivos:\tAdicionar **{devices_add}** dispositivos, Remover **{devices_remove}** dispositivos\r\nAlteração nas Regras de Transformação:\tUm total de **{trans_rules_count}** regras, e **{trans_rules_count_success}** regras atualizadas",
"data": {
"confirm": "Confirmar a mudança"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Exibir notificações de mudança de status do dispositivo",
"update_trans_rules": "Atualizar regras de conversão de entidades",
"update_lan_ctrl_config": "Atualizar configuração de controlo LAN",
"network_detect_config": "Configuração de Rede Integrada"
"network_detect_config": "Configuração de Rede Integrada",
"cover_dead_zone_width": "Largura da zona cega da cortina"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Confirmar Configuração",
"description": "Olá **{nick_name}**, confirme a informação da configuração mais recente e depois clique em SUBMETER.\r\nA integração será recarregada com a configuração atualizada.\r\n\r\nIdioma da Integração:\t{lang_new}\r\nAlcunha:\t{nick_name_new}\r\nModo de depuração de ação:\t{action_debug}\r\nOcultar entidades não padrão:\t{hide_non_standard_entities}\r\nExibir notificações de mudança de status do dispositivo:\t{display_devices_changed_notify}\r\nAlterações aos Dispositivos:\tAdicionar **{devices_add}** dispositivos, Remover **{devices_remove}** dispositivos\r\nAlteração das Regras de Transformação:\tExistem **{trans_rules_count}** regras no total, com **{trans_rules_count_success}** regras atualizadas",
"description": "Olá **{nick_name}**, confirme a informação da configuração mais recente e depois clique em SUBMETER.\r\nA integração será recarregada com a configuração atualizada.\r\n\r\nIdioma da Integração:\t{lang_new}\r\nAlcunha:\t{nick_name_new}\r\nModo de depuração de ação:\t{action_debug}\r\nOcultar entidades não padrão:\t{hide_non_standard_entities}\r\nLargura da zona cega da cortina:\t{cover_width_new}\r\nExibir notificações de mudança de status do dispositivo:\t{display_devices_changed_notify}\r\nAlterações aos Dispositivos:\tAdicionar **{devices_add}** dispositivos, Remover **{devices_remove}** dispositivos\r\nAlteração das Regras de Transformação:\tExistem **{trans_rules_count}** regras no total, com **{trans_rules_count_success}** regras atualizadas",
"data": {
"confirm": "Confirmar a alteração"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "Отображать уведомления о изменении состояния устройства",
"update_trans_rules": "Обновить правила преобразования сущностей",
"update_lan_ctrl_config": "Обновить конфигурацию управления LAN",
"network_detect_config": "Интегрированная Сетевая Конфигурация"
"network_detect_config": "Интегрированная Сетевая Конфигурация",
"cover_dead_zone_width": "Ширина «мертвой зоны» шторы"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "Подтверждение настройки",
"description": "**{nick_name}** Здравствуйте! Подтвердите последнюю информацию о настройке и нажмите «Отправить». Интеграция будет перезагружена с использованием обновленных настроек.\r\n\r\nЯзык интеграции:\t{lang_new}\r\nИмя пользователя:\t{nick_name_new}\r\nРежим отладки Action:\t{action_debug}\r\nСкрыть непроизводственные сущности:\t{hide_non_standard_entities}\r\nОтображать уведомления о изменении состояния устройства:\t{display_devices_changed_notify}\r\nИзменение устройства:\tДобавлено **{devices_add}** устройство, удалено **{devices_remove}** устройства\r\nИзменение правил преобразования:\tВсего **{trans_rules_count}** правил, обновлено **{trans_rules_count_success}** правил",
"description": "**{nick_name}** Здравствуйте! Подтвердите последнюю информацию о настройке и нажмите «Отправить». Интеграция будет перезагружена с использованием обновленных настроек.\r\n\r\nЯзык интеграции:\t{lang_new}\r\nИмя пользователя:\t{nick_name_new}\r\nРежим отладки Action:\t{action_debug}\r\nСкрыть непроизводственные сущности:\t{hide_non_standard_entities}\r\nШирина «мертвой зоны» шторы:\t{cover_width_new}\r\nОтображать уведомления о изменении состояния устройства:\t{display_devices_changed_notify}\r\nИзменение устройства:\tДобавлено **{devices_add}** устройство, удалено **{devices_remove}** устройства\r\nИзменение правил преобразования:\tВсего **{trans_rules_count}** правил, обновлено **{trans_rules_count_success}** правил",
"data": {
"confirm": "Подтвердить изменения"
}

View File

@@ -0,0 +1,225 @@
{
"config": {
"flow_title": "Xiaomi Home Entegrasyonu",
"step": {
"eula": {
"title": "Risk Bildirimi",
"description": "1. Xiaomi kullanıcı bilgileriniz ve cihaz bilgileriniz Home Assistant sisteminde saklanacaktır. **Xiaomi, Home Assistant depolama mekanizmasının güvenliğini garanti edemez**. Bilgilerinizin çalınmasını önlemekten siz sorumlusunuz.\r\n2. Bu entegrasyon açık kaynak topluluğu tarafından sürdürülmektedir. Kararlılık sorunları veya diğer sorunlar olabilir. Bu entegrasyonla ilgili sorunlar veya hatalarla karşılaştığınızda, **Xiaomi müşteri hizmetleriyle iletişime geçmek yerine açık kaynak topluluğundan yardım istemelisiniz**.\r\n3. Yerel işletim ortamınızı sürdürmek için teknik beceriye ihtiyacınız vardır. Entegrasyon yeni başlayanlar için kullanıcı dostu değildir.\r\n4. Lütfen başlamadan önce README dosyasını okuyun.\n\n5. Entegrasyonun kararlı kullanımını sağlamak ve arayüz kötüye kullanımını önlemek için, **bu entegrasyonun yalnızca Home Assistant'ta kullanılmasına izin verilir. Ayrıntılar için lütfen LICENSE'a bakın**.",
"data": {
"eula": "Yukarıdaki risklerin farkındayım ve entegrasyonun kullanımıyla ilişkili tüm riskleri gönüllü olarak üstlenmeye razıyım."
}
},
"auth_config": {
"title": "Temel yapılandırma",
"description": "### Giriş Bölgesi\r\nXiaomi hesabınızın bölgesini seçin. Bunu Xiaomi Home UYGULAMASI > Profil (alttaki menüde bulunur) > Ek ayarlar > Xiaomi Home Hakkında bölümünde bulabilirsiniz.\r\n### Dil\r\nCihaz ve varlık adlarının dilini seçin. Çevirisi olmayan bazı cümleler İngilizce olarak görüntülenecektir.\r\n### OAuth2 Yönlendirme URL'si\r\nOAuth2 kimlik doğrulama yönlendirme adresi **[http://homeassistant.local:8123](http://homeassistant.local:8123)** şeklindedir. Home Assistant'ın mevcut işletim terminali (örn. kişisel bilgisayar) ile aynı yerel ağda olması ve işletim terminalinin bu adres üzerinden Home Assistant ana sayfasına erişebilmesi gerekir. Aksi takdirde giriş kimlik doğrulaması başarısız olabilir.\r\n### Entegre Ağ Yapılandırması\r\nYerel ağın düzgün çalışıp çalışmadığını ve ilgili ağ kaynaklarının erişilebilir olup olmadığını kontrol edin. **İlk kez eklerken bunu seçmeniz önerilir.**\r\n### Not\r\n- Yüzlerce veya daha fazla Mi Home cihazına sahip kullanıcılar için, entegrasyonun ilk eklenmesi biraz zaman alacaktır. Lütfen sabırlı olun.\r\n- Home Assistant bir Docker ortamında çalışıyorsa, lütfen Docker ağ modunun host olarak ayarlandığından emin olun, aksi takdirde yerel kontrol işlevi düzgün çalışmayabilir.\r\n- Entegrasyonun yerel kontrol işlevinin bazı bağımlılıkları vardır. Lütfen README'yi dikkatlice okuyun.",
"data": {
"cloud_server": "Giriş Bölgesi",
"integration_language": "Dil",
"oauth_redirect_url": "OAuth2 Yönlendirme URL'si",
"network_detect_config": "Entegre Ağ Yapılandırması"
}
},
"network_detect_config": {
"title": "Entegre Ağ Yapılandırması",
"description": "## Kullanım Tanıtımı\r\n### Ağ Algılama Adresi\r\nAğın düzgün çalışıp çalışmadığını kontrol etmek için kullanılır. Ayarlanmazsa, sistem varsayılan adresi kullanılacaktır. Varsayılan adres kontrolü başarısız olursa, özel bir adres girmeyi deneyebilirsiniz.\r\n- Virgülle ayrılmış birden fazla algılama adresi girebilirsiniz, örneğin `8.8.8.8,https://www.bing.com`\r\n- Bir IP adresi ise, algılama ping üzerinden yapılacaktır. Bir HTTP(s) adresi ise, algılama HTTP GET isteği üzerinden yapılacaktır.\r\n- Sistem varsayılan algılama adresini geri yüklemek istiyorsanız, lütfen bir virgül `,` girin ve 'İleri'ye tıklayın.\r\n- **Bu yapılandırma geneldir ve değişiklikler diğer entegrasyon örneklerini etkileyecektir. Lütfen dikkatli değiştirin.**\r\n### Ağ Bağımlılıklarını Kontrol Et\r\nAşağıdaki ağ bağımlılıklarının erişilebilir olup olmadığını tek tek kontrol edin. İlgili adresler erişilebilir değilse, entegrasyon sorunlarına neden olacaktır.\r\n- OAuth2 Kimlik Doğrulama Adresi: `https://account.xiaomi.com/oauth2/authorize`.\r\n- Xiaomi HTTP API Adresi: `https://{http_host}/app/v2/ha/oauth/get_token`.\r\n- Xiaomi SPEC API Adresi: `https://miot-spec.org/miot-spec-v2/template/list/device`.\r\n- Xiaomi MQTT Broker Adresi: `mqtts://{cloud_server}-ha.mqtt.io.mi.com:8883`.",
"data": {
"network_detect_addr": "Ağ Algılama Adresi",
"check_network_deps": "Ağ Bağımlılıklarını Kontrol Et"
}
},
"oauth_error": {
"title": "Giriş Hatası",
"description": "Tekrar denemek için İLERİ'ye tıklayın."
},
"homes_select": {
"title": "Ev ve Cihaz Seçimi",
"description": "## Tanıtım\r\n### Cihazın Evini İçe Aktar\r\nEntegrasyon, seçilen evden cihazları ekleyecektir.\r\n### Oda Adı Senkronizasyon Modu\r\nMi Home UYGULAMASINDAN Home Assistant'a cihazlar senkronize edilirken, Home Assistant'taki alanın adlandırılması aşağıdaki kurallara uyacaktır. Senkronizasyon işleminin Mi Home UYGULAMASINDAKI ev ve oda ayarlarını değiştirmeyeceğini unutmayın.\r\n- Senkronize etme: Cihaz herhangi bir alana eklenmeyecektir.\r\n- Diğer seçenekler: Cihazın eklendiği alan, Mi Home UYGULAMASINDAKI ev veya oda adına göre adlandırılacaktır.\r\n### Gelişmiş Ayarlar\r\nEntegrasyonun profesyonel yapılandırma seçeneklerini değiştirmek için gelişmiş ayarları gösterin.\r\n\r\n&emsp;\r\n### {nick_name} Merhaba! Lütfen cihaz eklemek istediğiniz evi seçin.",
"data": {
"home_infos": "Cihazın Evini İçe Aktar",
"area_name_rule": "Oda Adı Senkronizasyon Modu",
"advanced_options": "Gelişmiş Ayarlar"
}
},
"advanced_options": {
"title": "Gelişmiş Ayarlar",
"description": "## Tanıtım\r\n### Aşağıdaki seçeneklerin anlamını çok net bir şekilde bilmiyorsanız, lütfen varsayılan ayarları koruyun.\r\n### Cihazları Filtrele\r\nCihazları oda adı ve cihaz türüne göre filtrelemeyi destekler, ayrıca cihaz boyutu filtrelemesini de destekler.\r\n### Kontrol Modu\r\n- Otomatik: Yerel ağda kullanılabilir bir Xiaomi merkezi hub ağ geçidi olduğunda, Home Assistant cihaz kontrol komutlarını öncelikle merkezi hub ağ geçidi üzerinden göndererek yerel kontrolü sağlar. Yerel ağda merkezi hub ağ geçidi yoksa, Xiaomi OT protokolü üzerinden kontrol komutları göndermeye çalışır. Yalnızca yukarıdaki yerel kontrol koşulları karşılanmadığında, cihaz kontrol komutları bulut üzerinden gönderilir.\r\n- Bulut: Tüm kontrol komutları bulut üzerinden gönderilir.\r\n### Eylem Hata Ayıklama Modu\r\nCihaz MIoT-Spec-V2 tarafından tanımlanan yöntemler için, bildirim varlıkları oluşturmaya ek olarak, bir metin girişi kutusu varlığı da oluşturulacaktır. Hata ayıklama sırasında cihaza kontrol komutları göndermek için bunu kullanabilirsiniz.\r\n### Standart Olmayan Oluşturulan Varlıkları Gizle\r\nAdı \"*\" ile başlayan standart olmayan MIoT-Spec-V2 örnekleri tarafından oluşturulan varlıkları gizle.\r\n### İkili Sensör Görüntüleme Modu\r\nXiaomi Home'daki ikili sensörleri metin sensör varlığı veya ikili sensör varlığı olarak görüntüleyin.\r\n### Cihaz Durum Değişikliği Bildirimlerini Göster\r\nDetaylı cihaz durum değişikliği bildirimlerini görüntüleyin, yalnızca seçilen bildirimleri gösterin.",
"data": {
"devices_filter": "Cihazları Filtrele",
"ctrl_mode": "Kontrol Modu",
"action_debug": "Eylem Hata Ayıklama Modu",
"hide_non_standard_entities": "Standart Olmayan Oluşturulan Varlıkları Gizle",
"display_binary_mode": "İkili Sensör Görüntüleme Modu",
"display_devices_changed_notify": "Cihaz Durum Değişikliği Bildirimlerini Göster"
}
},
"devices_filter": {
"title": "Cihazları Filtrele",
"description": "## Kullanım Talimatları\r\nCihazları ev oda adı, cihaz erişim türü ve cihaz modeline göre filtrelemeyi destekler, ayrıca cihaz boyutu filtrelemesini de destekler. Filtreleme mantığı aşağıdaki gibidir:\r\n- İlk olarak, istatistik mantığına göre, dahil edilen tüm öğelerin birleşimini veya kesişimini alın, ardından hariç tutulan öğelerin kesişimini veya birleşimini alın ve son olarak [hariç tutulan özet sonucu]ndan [dahil edilen özet sonucu]nu çıkararak [filtre sonucu]nu elde edin.\r\n- Dahil edilen öğe seçilmemişse, tümünün dahil edildiği anlamına gelir.\r\n### Filtre Modu\r\n- Hariç tut: İstenmeyen öğeleri kaldırın.\r\n- Dahil et: İstenen öğeleri dahil edin.\r\n### İstatistik Mantığı\r\n- VE mantığı: Aynı moddaki tüm öğelerin kesişimini alın.\r\n- VEYA mantığı: Aynı moddaki tüm öğelerin birleşimini alın.\r\n\r\nAyrıca entegrasyon öğesinin [Yapılandırma > Cihaz Listesini Güncelle] sayfasına gidip, yeniden filtrelemek için [Cihazları Filtrele]'yi işaretleyebilirsiniz.",
"data": {
"room_filter_mode": "Ev Odalarını Filtrele",
"room_list": "Ev Odaları",
"type_filter_mode": "Cihaz Bağlantı Türünü Filtrele",
"type_list": "Cihaz Bağlantı Türü",
"model_filter_mode": "Cihaz Modelini Filtrele",
"model_list": "Cihaz Modeli",
"devices_filter_mode": "Cihazları Filtrele",
"device_list": "Cihaz Listesi",
"statistics_logic": "İstatistik Mantığı"
}
}
},
"progress": {
"oauth": "### {link_left}Giriş yapmak için buraya tıklayın{link_right}\r\n(Başarılı girişten sonra otomatik olarak bir sonraki sayfaya yönlendirileceksiniz)"
},
"error": {
"eula_not_agree": "Lütfen risk bildirimini okuyun.",
"get_token_error": "Giriş yetkilendirme bilgileri (OAuth token) alınamadı.",
"get_homeinfo_error": "Ev bilgileri alınamadı.",
"mdns_discovery_error": "Yerel cihaz keşif hizmeti istisnası.",
"get_cert_error": "Merkezi hub ağ geçidi sertifikası alınamadı.",
"no_family_selected": "Ev seçilmedi.",
"no_devices": "Seçilen evde cihaz yok. Lütfen cihazı olan bir ev seçin ve devam edin.",
"no_filter_devices": "Filtrelenmiş cihazlar boş. Lütfen geçerli filtre kriterleri seçin ve devam edin.",
"no_central_device": "[Merkezi Hub Ağ Geçidi Modu], Home Assistant'ın bulunduğu yerel ağda kullanılabilir bir Xiaomi merkezi hub ağ geçidi gerektirir. Lütfen seçilen evin gereksinimi karşılayıp karşılamadığını kontrol edin.",
"invalid_network_addr": "Geçersiz IP adresi veya HTTP adresi algılandı, lütfen geçerli bir adres girin.",
"invalid_ip_addr": "Ulaşılamayan IP adresi algılandı, lütfen geçerli bir IP adresi girin.",
"invalid_http_addr": "Ulaşılamayan HTTP adresi algılandı, lütfen geçerli bir HTTP adresi girin.",
"invalid_default_addr": "Varsayılan ağ algılama adresi ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin veya özel bir ağ algılama adresi kullanın.",
"unreachable_oauth2_host": "OAuth2 kimlik doğrulama adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin.",
"unreachable_http_host": "Xiaomi HTTP API adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin.",
"unreachable_spec_host": "Xiaomi SPEC API adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin.",
"unreachable_mqtt_broker": "Xiaomi MQTT Broker adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin."
},
"abort": {
"ha_uuid_get_failed": "Home Assistant UUID alınamadı.",
"network_connect_error": "Yapılandırma başarısız oldu. Ağ bağlantısı anormal. Lütfen ekipman ağ yapılandırmasını kontrol edin.",
"already_configured": "Bu kullanıcı için yapılandırma zaten tamamlandı. Lütfen entegrasyon sayfasına gidin ve değişiklikler için YAPILANDIRMA düğmesine tıklayın.",
"invalid_auth_info": "Kimlik doğrulama bilgileri süresi doldu. Lütfen entegrasyon sayfasına gidin ve yeniden kimlik doğrulaması yapmak için YAPILANDIRMA düğmesine tıklayın.",
"config_flow_error": "Entegrasyon yapılandırma hatası: {error}."
}
},
"options": {
"step": {
"auth_config": {
"title": "Kimlik Doğrulama Yapılandırması",
"description": "Yerel kimlik doğrulama bilgileri süresi doldu. Lütfen kimlik doğrulama işlemini yeniden başlatın.\r\n### Geçerli Giriş Bölgesi: {cloud_server}\r\n### OAuth2 Yönlendirme URL'si\r\nOAuth2 kimlik doğrulama yönlendirme adresi **[http://homeassistant.local:8123](http://homeassistant.local:8123)** şeklindedir. Home Assistant'ın mevcut işletim terminali (örn. kişisel bilgisayar) ile aynı yerel ağda olması ve işletim terminalinin bu adres üzerinden Home Assistant ana sayfasına erişebilmesi gerekir. Aksi takdirde giriş kimlik doğrulaması başarısız olabilir.",
"data": {
"oauth_redirect_url": "OAuth2 Yönlendirme URL'si"
}
},
"oauth_error": {
"title": "Giriş sırasında bir hata oluştu.",
"description": "Tekrar denemek için İLERİ'ye tıklayın."
},
"config_options": {
"title": "Yapılandırma Seçenekleri",
"description": "### Merhaba, {nick_name}\r\n\r\nXiaomi ID: {uid}\r\nGeçerli Giriş Bölgesi: {cloud_server}\r\nEntegrasyon Örnek Kimliği: {instance_id}\r\n\r\nLütfen yapılandırmak istediğiniz seçenekleri seçin, ardından İLERİ'ye tıklayın.",
"data": {
"integration_language": "Entegrasyon Dili",
"update_user_info": "Kullanıcı bilgilerini güncelle",
"update_devices": "Cihaz listesini güncelle",
"action_debug": "Eylem için hata ayıklama modu",
"hide_non_standard_entities": "Standart olmayan oluşturulan varlıkları gizle",
"display_binary_mode": "İkili Sensör Görüntüleme Modu",
"display_devices_changed_notify": "Cihaz durum değişikliği bildirimlerini göster",
"update_trans_rules": "Varlık dönüştürme kurallarını güncelle",
"update_lan_ctrl_config": "LAN kontrol yapılandırmasını güncelle",
"network_detect_config": "Entegre ağ yapılandırması",
"cover_dead_zone_width": "Perde ölü bölge genişliği"
}
},
"update_user_info": {
"title": "Kullanıcı Takma Adını Güncelle",
"description": "Merhaba {nick_name}, aşağıda özel takma adınızı değiştirebilirsiniz.",
"data": {
"nick_name": "Takma Ad"
}
},
"homes_select": {
"title": "Evi ve Cihazları Yeniden Seç",
"description": "## Kullanım Talimatları\r\n### Evden cihazları içe aktar\r\nEntegrasyon, seçilen evlerden cihazları ekleyecektir.\r\n### Cihazları Filtrele\r\nCihazları ev oda adı, cihaz erişim türü ve cihaz modeline göre filtrelemeyi destekler, ayrıca cihaz boyutu filtrelemesini de destekler. **{local_count}** cihaz filtrelendi.\r\n### Kontrol modu\r\n- Otomatik: Yerel ağda kullanılabilir bir Xiaomi merkezi hub ağ geçidi olduğunda, Home Assistant cihaz kontrol komutlarını öncelikle merkezi hub ağ geçidi üzerinden göndererek yerel kontrolü sağlar. Yerel ağda merkezi hub ağ geçidi yoksa, Xiaomi LAN kontrol işlevi aracılığıyla kontrol komutları göndermeye çalışır. Yalnızca yukarıdaki yerel kontrol koşulları karşılanmadığında, cihaz kontrol komutları bulut üzerinden gönderilir.\r\n- Bulut: Tüm kontrol komutları bulut üzerinden gönderilir.",
"data": {
"home_infos": "Evden cihazları içe aktar",
"devices_filter": "Cihazları filtrele",
"ctrl_mode": "Kontrol modu"
}
},
"devices_filter": {
"title": "Cihazları Filtrele",
"description": "## Kullanım Talimatları\r\nCihazları ev oda adı, cihaz erişim türü ve cihaz modeline göre filtrelemeyi destekler, ayrıca cihaz boyutu filtrelemesini de destekler. Filtreleme mantığı aşağıdaki gibidir:\r\n- İlk olarak, istatistik mantığına göre, dahil edilen tüm öğelerin birleşimini veya kesişimini alın, ardından hariç tutulan öğelerin kesişimini veya birleşimini alın ve son olarak [hariç tutulan özet sonucu]ndan [dahil edilen özet sonucu]nu çıkararak [filtre sonucu]nu elde edin.\r\n- Dahil edilen öğe seçilmemişse, tümünün dahil edildiği anlamına gelir.\r\n### Filtre Modu\r\n- Hariç tut: İstenmeyen öğeleri kaldırın.\r\n- Dahil et: İstenen öğeleri dahil edin.\r\n### İstatistik Mantığı\r\n- VE mantığı: Aynı moddaki tüm öğelerin kesişimini alın.\r\n- VEYA mantığı: Aynı moddaki tüm öğelerin birleşimini alın.\r\n\r\nAyrıca entegrasyon öğesinin [Yapılandırma > Cihaz Listesini Güncelle] sayfasına gidip, yeniden filtrelemek için [Cihazları Filtrele]'yi işaretleyebilirsiniz.",
"data": {
"room_filter_mode": "Ev Odalarını Filtrele",
"room_list": "Ev Odaları",
"type_filter_mode": "Cihaz Bağlantı Türünü Filtrele",
"type_list": "Cihaz Bağlantı Türü",
"model_filter_mode": "Cihaz Modelini Filtrele",
"model_list": "Cihaz Modeli",
"devices_filter_mode": "Cihazları Filtrele",
"device_list": "Cihaz Listesi",
"statistics_logic": "İstatistik Mantığı"
}
},
"update_trans_rules": {
"title": "Varlık Dönüştürme Kurallarını Güncelle",
"description": "## Kullanım Talimatları\r\n- Mevcut entegrasyon örneğindeki cihazların varlık bilgilerini güncelleyin, MIoT-Spec-V2 çok dilli yapılandırma, boolean çeviri ve model filtreleme dahil.\r\n- **Uyarı**: Bu genel bir yapılandırmadır ve yerel önbelleği güncelleyecektir. Tüm entegrasyon örneklerini etkileyecektir.\r\n- Bu işlem biraz zaman alacaktır, lütfen sabırlı olun. \"Güncellemeyi Onayla\"yı işaretleyin ve **{urn_count}** kuralı güncellemeye başlamak için \"İleri\"ye tıklayın, aksi takdirde güncellemeyi atlayın.",
"data": {
"confirm": "Güncellemeyi onayla"
}
},
"update_lan_ctrl_config": {
"title": "LAN kontrol yapılandırmasını güncelle",
"description": "## Kullanım Talimatları\r\nXiaomi LAN kontrol işlevi için yapılandırmaları güncelleyin. Bulut ve merkezi hub ağ geçidi cihazları kontrol edemediğinde, entegrasyon LAN üzerinden cihazları kontrol etmeye çalışacaktır. Hiçbir ağ kartı seçilmezse, LAN kontrol işlevi etkin olmayacaktır.\r\n- Yalnızca LAN'daki MIoT-Spec-V2 uyumlu IP cihazları desteklenir. 2020'den önce üretilen bazı cihazlar LAN kontrolünü veya LAN aboneliğini desteklemeyebilir.\r\n- Lütfen kontrol edilecek cihazlarla aynı ağdaki ağ kartlarını seçin. Birden fazla ağ kartı seçilebilir. Home Assistant'ın birden fazla ağ kartı seçimi nedeniyle yerel ağa iki veya daha fazla bağlantısı varsa, en iyi ağ bağlantısına sahip olanı seçmeniz önerilir, aksi takdirde cihazlar üzerinde kötü etkisi olabilir.\r\n- LAN'da yerel kontrolü destekleyen terminal cihazlar (ekranlı Xiaomi hoparlör, cep telefonu, vb.) varsa, LAN aboneliğini etkinleştirmek yerel otomasyon ve cihaz anormalliklerine neden olabilir.\r\n- **Uyarı**: Bu genel bir yapılandırmadır. Tüm entegrasyon örneklerini etkileyecektir. Lütfen dikkatli kullanın.\r\n{notice_net_dup}",
"data": {
"net_interfaces": "Lütfen kullanılacak ağ kartını seçin",
"enable_subscribe": "LAN aboneliğini etkinleştir"
}
},
"network_detect_config": {
"title": "Entegre Ağ Yapılandırması",
"description": "## Kullanım Tanıtımı\r\n### Ağ Algılama Adresi\r\nAğın düzgün çalışıp çalışmadığını kontrol etmek için kullanılır. Ayarlanmazsa, sistem varsayılan adresi kullanılacaktır. Varsayılan adres kontrolü başarısız olursa, özel bir adres girmeyi deneyebilirsiniz.\r\n- Virgülle ayrılmış birden fazla algılama adresi girebilirsiniz, örneğin `8.8.8.8,https://www.bing.com`\r\n- Bir IP adresi ise, algılama ping üzerinden yapılacaktır. Bir HTTP(s) adresi ise, algılama HTTP GET isteği üzerinden yapılacaktır.\r\n- Sistem varsayılan algılama adresini geri yüklemek istiyorsanız, lütfen bir virgül `,` girin ve 'İleri'ye tıklayın.\r\n- **Bu yapılandırma geneldir ve değişiklikler diğer entegrasyon örneklerini etkileyecektir. Lütfen dikkatli değiştirin.**\r\n### Ağ Bağımlılıklarını Kontrol Et\r\nAşağıdaki ağ bağımlılıklarının erişilebilir olup olmadığını tek tek kontrol edin. İlgili adresler erişilebilir değilse, entegrasyon sorunlarına neden olacaktır.\r\n- OAuth2 Kimlik Doğrulama Adresi: `https://account.xiaomi.com/oauth2/authorize`.\r\n- Xiaomi HTTP API Adresi: `https://{http_host}/app/v2/ha/oauth/get_token`.\r\n- Xiaomi SPEC API Adresi: `https://miot-spec.org/miot-spec-v2/template/list/device`.\r\n- Xiaomi MQTT Broker Adresi: `mqtts://{cloud_server}-ha.mqtt.io.mi.com:8883`.",
"data": {
"network_detect_addr": "Ağ Algılama Adresi",
"check_network_deps": "Ağ Bağımlılıklarını Kontrol Et"
}
},
"config_confirm": {
"title": "Yapılandırmayı Onayla",
"description": "Merhaba **{nick_name}**, lütfen en son yapılandırma bilgilerini onaylayın ve ardından GÖNDER'e tıklayın.\r\nEntegrasyon güncellenmiş yapılandırmayla yeniden yüklenecektir.\r\n\r\nEntegrasyon Dili:\t{lang_new}\r\nTakma Ad:\t{nick_name_new}\r\nEylem için hata ayıklama modu:\t{action_debug}\r\nStandart olmayan oluşturulan varlıkları gizle:\t{hide_non_standard_entities}\r\nPerde ölü bölge genişliği:\t{cover_width_new}\r\nCihaz durum değişikliği bildirimlerini göster:\t{display_devices_changed_notify}\r\nCihaz Değişiklikleri:\t**{devices_add}** cihaz ekle, **{devices_remove}** cihaz kaldır\r\nDönüştürme kuralları değişikliği:\tToplam **{trans_rules_count}** kural var ve **{trans_rules_count_success}** kural güncellendi",
"data": {
"confirm": "Değişikliği onayla"
}
}
},
"progress": {
"oauth": "### {link_left}Yeniden giriş yapmak için lütfen buraya tıklayın{link_right}"
},
"error": {
"not_auth": "Kimlik doğrulanmadı. Lütfen kullanıcı kimliğini doğrulamak için kimlik doğrulama bağlantısına tıklayın.",
"get_token_error": "Giriş yetkilendirme bilgileri (OAuth token) alınamadı.",
"get_homeinfo_error": "Ev bilgileri alınamadı.",
"get_cert_error": "Merkezi hub ağ geçidi sertifikası alınamadı.",
"no_devices": "Seçilen evde cihaz yok. Lütfen cihazı olan bir ev seçin ve devam edin.",
"no_filter_devices": "Filtrelenmiş cihazlar boş. Lütfen geçerli filtre kriterleri seçin ve devam edin.",
"no_family_selected": "Ev seçilmedi.",
"no_central_device": "[Merkezi Hub Ağ Geçidi Modu], Home Assistant'ın bulunduğu yerel ağda kullanılabilir bir Xiaomi merkezi hub ağ geçidi gerektirir. Lütfen seçilen evin gereksinimi karşılayıp karşılamadığını kontrol edin.",
"mdns_discovery_error": "Yerel cihaz keşif hizmeti istisnası.",
"update_config_error": "Yapılandırma bilgileri güncellenemedi.",
"not_confirm": "Değişiklikler onaylanmadı. Lütfen göndermeden önce değişikliği onaylayın.",
"invalid_network_addr": "Geçersiz IP adresi veya HTTP adresi algılandı, lütfen geçerli bir adres girin.",
"invalid_ip_addr": "Ulaşılamayan IP adresi algılandı, lütfen geçerli bir IP adresi girin.",
"invalid_http_addr": "Ulaşılamayan HTTP adresi algılandı, lütfen geçerli bir HTTP adresi girin.",
"invalid_default_addr": "Varsayılan ağ algılama adresi ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin veya özel bir ağ algılama adresi kullanın.",
"unreachable_oauth2_host": "OAuth2 kimlik doğrulama adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin.",
"unreachable_http_host": "Xiaomi HTTP API adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin.",
"unreachable_spec_host": "Xiaomi SPEC API adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin.",
"unreachable_mqtt_broker": "Xiaomi MQTT Broker adresine ulaşılamıyor, lütfen ağ yapılandırmasını kontrol edin."
},
"abort": {
"network_connect_error": "Yapılandırma başarısız oldu. Ağ bağlantısı anormal. Lütfen ekipman ağ yapılandırmasını kontrol edin.",
"options_flow_error": "Entegrasyon yeniden yapılandırma hatası: {error}",
"re_add": "Lütfen entegrasyonu yeniden ekleyin. Hata mesajı: {error}",
"storage_error": "Entegrasyon depolama modülü istisnası. Lütfen tekrar deneyin veya entegrasyonu yeniden ekleyin: {error}",
"inconsistent_account": "Hesap bilgileri tutarsız. Lütfen doğru hesapla giriş yapın."
}
}
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "显示设备状态变化通知",
"update_trans_rules": "更新实体转换规则",
"update_lan_ctrl_config": "更新局域网控制配置",
"network_detect_config": "集成网络配置"
"network_detect_config": "集成网络配置",
"cover_dead_zone_width": "窗帘盲区宽度"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "确认配置",
"description": "**{nick_name}** 您好!请确认最新的配置信息,然后点击“提交”。\r\n集成将会使用更新后的配置重新载入。\r\n\r\n集成语言\t{lang_new}\r\n用户昵称\t{nick_name_new}\r\nAction 调试模式:\t{action_debug}\r\n隐藏非标准生成实体\t{hide_non_standard_entities}\r\n显示设备状态变化通知\t{display_devices_changed_notify}\r\n设备变化\t新增 **{devices_add}** 个设备,移除 **{devices_remove}** 个设备\r\n转换规则变化\t共条 **{trans_rules_count}** 规则,更新 **{trans_rules_count_success}** 条规则",
"description": "**{nick_name}** 您好!请确认最新的配置信息,然后点击“提交”。\r\n集成将会使用更新后的配置重新载入。\r\n\r\n集成语言\t{lang_new}\r\n用户昵称\t{nick_name_new}\r\nAction 调试模式:\t{action_debug}\r\n隐藏非标准生成实体\t{hide_non_standard_entities}\r\n窗帘盲区宽度:\t{cover_width_new}\r\n显示设备状态变化通知:\t{display_devices_changed_notify}\r\n设备变化\t新增 **{devices_add}** 个设备,移除 **{devices_remove}** 个设备\r\n转换规则变化\t共条 **{trans_rules_count}** 规则,更新 **{trans_rules_count_success}** 条规则",
"data": {
"confirm": "确认修改"
}

View File

@@ -124,7 +124,8 @@
"display_devices_changed_notify": "顯示設備狀態變化通知",
"update_trans_rules": "更新實體轉換規則",
"update_lan_ctrl_config": "更新局域網控制配置",
"network_detect_config": "集成網絡配置"
"network_detect_config": "集成網絡配置",
"cover_dead_zone_width": "窗簾盲區寬度"
}
},
"update_user_info": {
@@ -183,7 +184,7 @@
},
"config_confirm": {
"title": "確認配置",
"description": "**{nick_name}** 您好!請確認最新的配置信息,然後點擊“提交”。\r\n集成將會使用更新後的配置重新載入。\r\n\r\n集成語言\t{lang_new}\r\n用戶暱稱\t{nick_name_new}\r\nAction 調試模式:\t{action_debug}\r\n隱藏非標準生成實體\t{hide_non_standard_entities}\r\n顯示設備狀態變化通知\t{display_devices_changed_notify}\r\n設備變化\t新增 **{devices_add}** 個設備,移除 **{devices_remove}** 個設備\r\n轉換規則變化\t共條 **{trans_rules_count}** 規則,更新 **{trans_rules_count_success}** 條規則",
"description": "**{nick_name}** 您好!請確認最新的配置信息,然後點擊“提交”。\r\n集成將會使用更新後的配置重新載入。\r\n\r\n集成語言\t{lang_new}\r\n用戶暱稱\t{nick_name_new}\r\nAction 調試模式:\t{action_debug}\r\n隱藏非標準生成實體\t{hide_non_standard_entities}\r\n窗簾盲區寬度:\t{cover_width_new}\r\n顯示設備狀態變化通知:\t{display_devices_changed_notify}\r\n設備變化\t新增 **{devices_add}** 個設備,移除 **{devices_remove}** 個設備\r\n轉換規則變化\t共條 **{trans_rules_count}** 規則,更新 **{trans_rules_count_success}** 條規則",
"data": {
"confirm": "確認修改"
}

View File

@@ -47,29 +47,32 @@ Vacuum entities for Xiaomi Home.
"""
from __future__ import annotations
from typing import Any, Optional
import re
import logging
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.vacuum import (
StateVacuumEntity,
VacuumEntityFeature
)
from homeassistant.components.vacuum import (StateVacuumEntity,
VacuumEntityFeature)
from .miot.const import DOMAIN
from .miot.miot_device import MIoTDevice, MIoTServiceEntity, MIoTEntityData
from .miot.miot_spec import (
MIoTSpecAction,
MIoTSpecProperty)
from .miot.miot_spec import (MIoTSpecAction, MIoTSpecProperty)
try: # VacuumActivity is introduced in HA core 2025.1.0
from homeassistant.components.vacuum import VacuumActivity
HA_CORE_HAS_ACTIVITY = True
except ImportError:
HA_CORE_HAS_ACTIVITY = False
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
device_list: list[MIoTDevice] = hass.data[DOMAIN]['devices'][
config_entry.entry_id]
@@ -87,7 +90,11 @@ 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]]
_prop_status_returning: Optional[list[int]]
_prop_status_error: Optional[list[int]]
_action_start_sweep: Optional[MIoTSpecAction]
_action_stop_sweeping: Optional[MIoTSpecAction]
@@ -99,15 +106,21 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
_status_map: Optional[dict[int, str]]
_fan_level_map: Optional[dict[int, str]]
def __init__(
self, miot_device: MIoTDevice, entity_data: MIoTEntityData
) -> None:
_device_name: str
def __init__(self, miot_device: MIoTDevice,
entity_data: MIoTEntityData) -> None:
super().__init__(miot_device=miot_device, entity_data=entity_data)
self._device_name = miot_device.name
self._attr_supported_features = VacuumEntityFeature(0)
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 = []
self._prop_status_returning = []
self._prop_status_error = []
self._action_start_sweep = None
self._action_stop_sweeping = None
self._action_pause_sweeping = None
@@ -121,24 +134,50 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
for prop in entity_data.props:
if prop.name == 'status':
if not prop.value_list:
_LOGGER.error(
'invalid status value_list, %s', self.entity_id)
_LOGGER.error('invalid status value_list, %s',
self.entity_id)
continue
self._status_map = prop.value_list.to_map()
self._attr_supported_features |= VacuumEntityFeature.STATE
self._prop_status = prop
for item in prop.value_list.items:
item_str: str = item.name
item_name: str = re.sub(r'[^a-z]', '', item_str)
if item_name in {
'charging', 'charged', 'chargingcompleted',
'fullcharge', 'fullpower', 'findchargerpause',
'drying', 'washing', 'wash', 'inthewash',
'inthedry', 'stationworking', 'dustcollecting',
'upgrade', 'upgrading', 'updating'
}:
self._prop_status_docked.append(item.value)
elif item_name in {'paused', 'pause'}:
self._prop_status_paused.append(item.value)
elif item_name in {
'gocharging', 'cleancompletegocharging',
'findchargewash', 'backtowashmop', 'gowash',
'gowashing', 'summon'
}:
self._prop_status_returning.append(item.value)
elif item_name in {
'error', 'breakcharging', 'gochargebreak'
}:
self._prop_status_error.append(item.value)
elif (item_name.find('sweeping') != -1) or (
item_name.find('mopping') != -1) or (item_name in {
'cleaning', 'remoteclean', 'continuesweep',
'busy', 'building', 'buildingmap', 'mapping'
}):
self._prop_status_cleaning.append(item.value)
elif prop.name == 'fan-level':
if not prop.value_list:
_LOGGER.error(
'invalid fan-level value_list, %s', self.entity_id)
_LOGGER.error('invalid fan-level value_list, %s',
self.entity_id)
continue
self._fan_level_map = prop.value_list.to_map()
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':
@@ -155,16 +194,28 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
elif action.name == 'stop-and-gocharge':
self._attr_supported_features |= VacuumEntityFeature.RETURN_HOME
self._action_stop_and_gocharge = action
elif action.name == 'identify':
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.state.lower() in ['paused', '暂停中']:
await self.action_async(action=self._action_continue_sweep)
return
if self._prop_status is not None:
status = self.get_prop_value(prop=self._prop_status)
if (status in self._prop_status_paused
) and self._action_continue_sweep:
await self.action_async(action=self._action_continue_sweep)
return
await self.action_async(action=self._action_start_sweep)
async def async_stop(self, **kwargs: Any) -> None:
@@ -179,31 +230,69 @@ class Vacuum(MIoTServiceEntity, StateVacuumEntity):
"""Set the vacuum cleaner to return to the dock."""
await self.action_async(action=self._action_stop_and_gocharge)
async def async_clean_spot(self, **kwargs: Any) -> None:
"""Perform a spot clean-up."""
async def async_locate(self, **kwargs: Any) -> None:
"""Locate the vacuum cleaner."""
await self.action_async(action=self._action_identify)
async def async_set_fan_speed(self, fan_speed: str, **kwargs: Any) -> None:
"""Set fan speed."""
fan_level_value = self.get_map_key(map_=self._fan_level_map,
value=fan_speed)
await self.set_property_async(prop=self._prop_fan_level,
value=fan_level_value)
@property
def state(self) -> Optional[str]:
"""Return the current state of the vacuum cleaner."""
return self.get_map_value(
map_=self._status_map,
key=self.get_prop_value(prop=self._prop_status))
@property
def battery_level(self) -> Optional[int]:
"""Return the current battery level of the vacuum cleaner."""
return self.get_prop_value(prop=self._prop_battery_level)
def name(self) -> Optional[str]:
"""Name of the vacuum entity."""
return self._device_name
@property
def fan_speed(self) -> Optional[str]:
"""Return the current fan speed of the vacuum cleaner."""
"""The current fan speed of the vacuum cleaner."""
return self.get_map_value(
map_=self._fan_level_map,
key=self.get_prop_value(prop=self._prop_fan_level))
if HA_CORE_HAS_ACTIVITY:
@property
def activity(self) -> Optional[str]:
"""The current vacuum activity.
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.
"""
status = self.get_prop_value(prop=self._prop_status)
if status is None:
return None
if status in self._prop_status_cleaning:
return VacuumActivity.CLEANING
if status in self._prop_status_docked:
return VacuumActivity.DOCKED
if status in self._prop_status_paused:
return VacuumActivity.PAUSED
if status in self._prop_status_returning:
return VacuumActivity.RETURNING
if status in self._prop_status_error:
return VacuumActivity.ERROR
return VacuumActivity.IDLE
else:
@property
def state(self) -> Optional[str]:
"""The current state of the vacuum."""
status = self.get_prop_value(prop=self._prop_status)
return None if (status is None) else self.get_map_value(
map_=self._status_map, key=status)

View File

@@ -141,12 +141,11 @@ class WaterHeater(MIoTServiceEntity, WaterHeaterEntity):
continue
self._mode_map = prop.value_list.to_map()
self._attr_operation_list = list(self._mode_map.values())
self._attr_supported_features |= (
WaterHeaterEntityFeature.OPERATION_MODE)
self._prop_mode = prop
if not self._attr_operation_list:
self._attr_operation_list = [STATE_ON]
self._attr_operation_list.append(STATE_OFF)
self._attr_supported_features |= WaterHeaterEntityFeature.OPERATION_MODE
async def async_turn_on(self) -> None:
"""Turn the water heater on."""
@@ -169,7 +168,7 @@ class WaterHeater(MIoTServiceEntity, WaterHeaterEntity):
if operation_mode == STATE_ON:
await self.set_property_async(prop=self._prop_on, value=True)
return
if self.get_prop_value(prop=self._prop_on) is False:
if self.get_prop_value(prop=self._prop_on) is not True:
await self.set_property_async(prop=self._prop_on,
value=True,
write_ha_state=False)
@@ -197,5 +196,5 @@ class WaterHeater(MIoTServiceEntity, WaterHeaterEntity):
return STATE_OFF
if not self._prop_mode and self.get_prop_value(prop=self._prop_on):
return STATE_ON
return self.get_map_value(map_=self._mode_map,
key=self.get_prop_value(prop=self._prop_mode))
return (None if self._prop_mode is None else self.get_map_value(
map_=self._mode_map, key=self.get_prop_value(prop=self._prop_mode)))

View File

@@ -93,7 +93,7 @@ git checkout v1.0.0
- 米家集成是否支持本地化控制?
米家集成支持通过[小米中枢网关](https://www.mi.com/shop/buy/detail?product_id=15755&cfrom=search)(固件版本 3.4.0_000 以上)或内置中枢网关(软件版本 0.8.0 以上)的米家设备实现本地化控制。如果没有小米中枢网关或其他带中枢网关功能的设备,那么所有控制指令都会通过小米云发送。支持 Home Assistant 本地化控制的小米中枢网关(含内置中枢网关)的固件尚未发布,固件升级计划请参阅 MIoT 团队的通知。
米家集成支持通过[小米中枢网关](https://www.mi.com/shop/buy/detail?product_id=15755&cfrom=search)(固件版本 3.3.0_0023 及以上)或内置中枢网关(软件版本 0.8.9 及以上)的米家设备实现本地化控制。如果没有小米中枢网关或其他带中枢网关功能的设备,那么所有控制指令都会通过小米云发送。支持 Home Assistant 本地化控制的小米中枢网关(含内置中枢网关)的固件尚未发布,固件升级计划请参阅 MIoT 团队的通知。
小米中枢网关仅在中国大陆可用,在其他地区不可用。
@@ -157,6 +157,8 @@ git checkout v1.0.0
转换后的实体为 Event事件参数同时传递给实体的 `_trigger_event`
MIoT-Spec-V2 事件的 arguments 字段是事件的参数列表,列表元素代表同服务下属性的 piid 。例如,小米智能无线开关(双开)的 [MIoT-Spec-V2](http://poc.miot-spec.srv/miot-spec-v2/instance?type=urn:miot-spec-v2:device:remote-control:0000A021:xiaomi-mcn002:1:0000D057)的 siid=2 无线开关服务下包含 eiid=1014 长按事件,该事件触发时会携带一个 piid=2 的按键类型属性作为事件参数, debug 等级日志会打印 `长按, attributes: {'按键类型': 1}` (日志示例,按键类型为 1 表示右键触发了长按事件)。
- 方法Action
| in输入参数列表 | 转换后的实体 |
@@ -291,46 +293,44 @@ event instance name 下的值表示转换后实体所用的 `_attr_device_class`
### MIoT-Spec-V2 过滤规则
`spec_filter.json` 用于过滤掉不需要的 MIoT-Spec-V2 实例,过滤掉的实例不会转换成 Home Assistant 实体。
`spec_filter.yaml` 用于过滤掉不需要的 MIoT-Spec-V2 实例,过滤掉的实例不会转换成 Home Assistant 实体。
`spec_filter.json`的格式如下:
`spec_filter.yaml`的格式如下:
```
{
"<MIoT-Spec-V2 device instance>":{
"services": list<service_iid: str>,
"properties": list<service_iid.property_iid: str>,
"events": list<service_iid.event_iid: str>,
"actions": list<service_iid.action_iid: str>,
}
}
```yaml
<MIoT-Spec-V2 device instance urn without the version field>:
services: list<service_iid: str>
properties: list<service_iid.property_iid: str>
events: list<service_iid.event_iid: str>
actions: list<service_iid.action_iid: str>
```
`spec_filter.json` 的键值为 MIoT-Spec-V2 设备实例的 urn 不含版本号“version”字段。一个产品的不同版本的固件可能会关联不同版本的 MIoT-Spec-V2 设备实例。 MIoT 平台要求厂商定义产品的 MIoT-Spec-V2 时,高版本的 MIoT-Spec-V2 实例必须包含全部低版本的 MIoT-Spec-V2 实例。因此, `spec_filter.json` 的键值不需要指定设备实例的版本号。
`spec_filter.yaml` 的键值为 MIoT-Spec-V2 设备实例的 urn 不含版本号“version”字段。一个产品的不同版本的固件可能会关联不同版本的 MIoT-Spec-V2 设备实例。 MIoT 平台要求厂商定义产品的 MIoT-Spec-V2 时,高版本的 MIoT-Spec-V2 实例必须包含全部低版本的 MIoT-Spec-V2 实例。因此, `spec_filter.yaml` 的键值不需要指定设备实例的版本号。
设备实例下的 services 、 properties 、 events 、 actions 域的值表示需要过滤掉的服务、属性、事件、方法的实例号( iid ,即 instance id )。支持通配符匹配。
示例:
```
{
"urn:miot-spec-v2:device:television:0000A010:xiaomi-rmi1":{
"services": ["*"] # Filter out all services. It is equivalent to completely ignoring the device with such MIoT-Spec-V2 device instance.
},
"urn:miot-spec-v2:device:gateway:0000A019:xiaomi-hub1": {
"services": ["3"], # Filter out the service whose iid=3.
"properties": ["4.*"] # Filter out all properties in the service whose iid=4.
"events": ["4.1"], # Filter out the iid=1 event in the iid=4 service.
"actions": ["4.1"] # Filter out the iid=1 action in the iid=4 service.
}
}
```yaml
urn:miot-spec-v2:device:television:0000A010:xiaomi-rmi1:
services:
- '*' # 排除所有服务,相当于排除拥有该 MIoT-Spec-V2 的设备。
urn:miot-spec-v2:device:gateway:0000A019:xiaomi-hub1:
services:
- '3' # 排除 siid=3 的服务。
properties:
- '4.*' # 排除 siid=4 服务的所有属性。
events:
- '4.1' # 排除 siid=4 服务的 eiid=1 的事件。
actions:
- '4.1' # 排除 siid=4 服务的 aiid=1 的方法。
```
所有设备的设备信息服务( urn:miot-spec-v2:service:device-information:00007801 )均不会生成 Home Assistant 实体。
## 多语言支持
米家集成配置选项中可选择的集成使用的语言有简体中文、繁体中文、英文、西班牙语、俄语、法语、德语、日语这八种语言。目前,米家集成配置页面的简体中文和英文已经过人工校审,其他语言由机器翻译。如果您希望修改配置页面的词句,则需要修改 `custom_components/xiaomi_home/translations/` 以及 `custom_components/xiaomi_home/miot/i18n/` 目录下相应语言的 json 文件。
米家集成配置选项中可选择的集成使用的语言有简体中文、繁体中文、英文、西班牙语、俄语、法语、德语、日语、意大利语、荷兰语、葡萄牙语、巴西葡萄牙语、土耳其语这十三种语言。目前,米家集成配置页面的简体中文和英文已经过人工校审,其他语言由机器翻译或社区贡献。如果您希望修改配置页面的词句,则需要修改 `custom_components/xiaomi_home/translations/` 以及 `custom_components/xiaomi_home/miot/i18n/` 目录下相应语言的 json 文件。
在显示 Home Assistant 实体名称时,米家集成会从小米云下载设备厂商为设备配置的多语言文件,该文件包含设备 MIoT-Spec-V2 实例的多语言翻译。 `multi_lang.json` 是本地维护的多语言配置字典,其优先级高于从云端获取的多语言文件,可用于补充或修改设备的多语言翻译。
@@ -348,7 +348,7 @@ event instance name 下的值表示转换后实体所用的 `_attr_device_class`
`multi_lang.json` 的键值为 MIoT-Spec-V2 设备实例的 urn 不含版本号“version”字段
language code 为语言代码,取值为 zh-Hans、zh-Hant、en、es、ru、fr、de、ja (对应上述米家集成可选的种语言)。
language code 为语言代码,取值为 zh-Hans、zh-Hant、en、es、ru、fr、de、ja、it、nl、pt、pt-BR、tr(对应上述米家集成可选的十三种语言)。
instance code 为 MIoT-Spec-V2 实例代码,格式如下:
@@ -378,7 +378,7 @@ siid、piid、eiid、aiid、value 均为十进制三位整数。
}
```
> 在 Home Assistant 中修改了 `custom_components/xiaomi_home/miot/specs` 路径下的任何文件(`spec_filter.py`、`spec_modify.json`、`multi_lang.json`等),需要在集成配置中更新实体转换规则才能生效。方法:[设置 > 设备与服务 > 已配置 > Xiaomi Home](https://my.home-assistant.io/redirect/integration/?domain=xiaomi_home) > 配置 > 更新实体转换规则
> 在 Home Assistant 中修改了 `custom_components/xiaomi_home/miot/specs` 路径下的任何文件(`spec_filter.yaml`、`spec_modify.yaml`、`multi_lang.json`等),需要在集成配置中更新实体转换规则才能生效。方法:[设置 > 设备与服务 > 已配置 > Xiaomi Home](https://my.home-assistant.io/redirect/integration/?domain=xiaomi_home) > 配置 > 更新实体转换规则
## 文档