6 Commits

Author SHA1 Message Date
152933a223 docs: update changelog and version to v0.1.5b1 (#616) 2025-01-10 09:46:34 +08:00
6557b22a52 fix: fix multi ha instance login (#560)
* fix: fix multi ha instance login

* fix: fix option flow oauth
2025-01-10 09:19:24 +08:00
5d4b975f85 fix: the number of profile models updated from 660 to 823 (#583) 2025-01-07 20:22:06 +08:00
0566546a99 feat: filter miwifi.* devices (#564)
* feat: filter miwifi.* devices

* feat: update log level

* feat: filter special xiaomi router model, xiaomi.router.rd03
2025-01-07 20:21:43 +08:00
c0d100ce2b feat: fan entity support direction ctrl (#556)
* feat: fan entity support direction

* fix: fix value judgement logic
2025-01-07 20:21:24 +08:00
ce7ce7af4b fix: fan speed (#464)
* fix: fan speed

* fix: fan speed names map

* fix: set percentage

* docs: the instance code format of valuelist

* fix: fan level property

* fix: pylint too long line.

* style: code format

---------

Co-authored-by: topsworld <sworldtop@gmail.com>
2025-01-07 20:21:04 +08:00
21 changed files with 496 additions and 42 deletions

View File

@ -1,5 +1,16 @@
# CHANGELOG
## v0.1.5b1
This version will cause some Xiaomi routers that do not support access (#564) to become unavailable. You can update the device list in the configuration or delete it manually.
### Added
- Fan entity support direction ctrl [#556](https://github.com/XiaoMi/ha_xiaomi_home/pull/556)
### Changed
- Filter miwifi.* devices and xiaomi.router.rd03 [#564](https://github.com/XiaoMi/ha_xiaomi_home/pull/564)
### Fixed
- Fix multi ha instance login [#560](https://github.com/XiaoMi/ha_xiaomi_home/pull/560)
- Fix fan speed [#464](https://github.com/XiaoMi/ha_xiaomi_home/pull/464)
- The number of profile models updated from 660 to 823. [#583](https://github.com/XiaoMi/ha_xiaomi_home/pull/583)
## v0.1.5b0
### Added
- Add missing parameter state_class [#101](https://github.com/XiaoMi/ha_xiaomi_home/pull/101)

View File

@ -351,7 +351,7 @@ The instance code is the code of the MIoT-Spec-V2 instance, which is in the form
```
service:<siid> # service
service:<siid>:property:<piid> # property
service:<siid>:property:<piid>:valuelist:<value> # the value in value-list of a property
service:<siid>:property:<piid>:valuelist:<index> # The index of a value in the value-list of a property
service:<siid>:event:<eiid> # event
service:<siid>:action:<aiid> # action
```

View File

@ -68,6 +68,7 @@ from homeassistant.components.webhook import (
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import AbortFlow
from homeassistant.helpers.instance_id import async_get
import homeassistant.helpers.config_validation as cv
from .miot.const import (
@ -247,6 +248,13 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if user_input:
self._cloud_server = user_input.get(
'cloud_server', self._cloud_server)
# Gen instance uuid
ha_uuid = await async_get(self.hass)
if not ha_uuid:
raise AbortFlow(reason='ha_uuid_get_failed')
self._uuid = hashlib.sha256(
f'{ha_uuid}.{self._virtual_did}.{self._cloud_server}'.encode(
'utf-8')).hexdigest()[:32]
self._integration_language = user_input.get(
'integration_language', DEFAULT_INTEGRATION_LANGUAGE)
self._miot_i18n = MIoTI18n(
@ -415,9 +423,11 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
miot_oauth = MIoTOauthClient(
client_id=OAUTH2_CLIENT_ID,
redirect_url=self._oauth_redirect_url_full,
cloud_server=self._cloud_server
)
state = str(secrets.randbits(64))
cloud_server=self._cloud_server,
uuid=self._uuid,
loop=self._main_loop)
state = hashlib.sha1(
f'd=ha.{self._uuid}'.encode('utf-8')).hexdigest()
self.hass.data[DOMAIN][self._virtual_did]['oauth_state'] = state
self._cc_oauth_auth_url = miot_oauth.gen_auth_url(
redirect_url=self._oauth_redirect_url_full, state=state)
@ -498,11 +508,6 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
client_id=OAUTH2_CLIENT_ID,
access_token=auth_info['access_token'])
self._auth_info = auth_info
# Gen uuid
self._uuid = hashlib.sha256(
f'{self._virtual_did}.{auth_info["access_token"]}'.encode(
'utf-8')
).hexdigest()[:32]
try:
self._nick_name = (
await self._miot_http.get_user_info_async() or {}
@ -1145,7 +1150,9 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
async def async_step_oauth(self, user_input=None):
try:
if self._cc_task_oauth is None:
state = str(secrets.randbits(64))
state = hashlib.sha1(
f'd=ha.{self._entry_data["uuid"]}'.encode('utf-8')
).hexdigest()
self.hass.data[DOMAIN][self._virtual_did]['oauth_state'] = state
self._miot_oauth.set_redirect_url(
redirect_url=self._oauth_redirect_url_full)

View File

@ -55,7 +55,9 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.util.percentage import (
percentage_to_ranged_value,
ranged_value_to_percentage
ranged_value_to_percentage,
ordered_list_item_to_percentage,
percentage_to_ordered_list_item
)
from .miot.miot_spec import MIoTSpecProperty
@ -89,10 +91,15 @@ class Fan(MIoTServiceEntity, FanEntity):
_prop_fan_level: Optional[MIoTSpecProperty]
_prop_mode: Optional[MIoTSpecProperty]
_prop_horizontal_swing: Optional[MIoTSpecProperty]
_prop_wind_reverse: Optional[MIoTSpecProperty]
_prop_wind_reverse_forward: Any
_prop_wind_reverse_reverse: Any
_speed_min: Optional[int]
_speed_max: Optional[int]
_speed_step: Optional[int]
_speed_min: int
_speed_max: int
_speed_step: int
_speed_names: Optional[list]
_speed_name_map: Optional[dict[int, str]]
_mode_list: Optional[dict[Any, Any]]
def __init__(
@ -101,15 +108,22 @@ class Fan(MIoTServiceEntity, FanEntity):
"""Initialize the Fan."""
super().__init__(miot_device=miot_device, entity_data=entity_data)
self._attr_preset_modes = []
self._attr_current_direction = None
self._attr_supported_features = FanEntityFeature(0)
self._prop_on = None
self._prop_fan_level = None
self._prop_mode = None
self._prop_horizontal_swing = None
self._prop_wind_reverse = None
self._prop_wind_reverse_forward = None
self._prop_wind_reverse_reverse = None
self._speed_min = 65535
self._speed_max = 0
self._speed_step = 1
self._speed_names = []
self._speed_name_map = {}
self._mode_list = None
# properties
@ -124,7 +138,8 @@ class Fan(MIoTServiceEntity, FanEntity):
self._speed_min = prop.value_range['min']
self._speed_max = prop.value_range['max']
self._speed_step = prop.value_range['step']
self._attr_speed_count = self._speed_max - self._speed_min+1
self._attr_speed_count = int((
self._speed_max - self._speed_min)/self._speed_step)+1
self._attr_supported_features |= FanEntityFeature.SET_SPEED
self._prop_fan_level = prop
elif (
@ -133,10 +148,13 @@ class Fan(MIoTServiceEntity, FanEntity):
and prop.value_list
):
# Fan level with value-list
for item in prop.value_list:
self._speed_min = min(self._speed_min, item['value'])
self._speed_max = max(self._speed_max, item['value'])
self._attr_speed_count = self._speed_max - self._speed_min+1
# Fan level with value-range is prior to fan level with
# value-list when a fan has both fan level properties.
self._speed_name_map = {
item['value']: item['description']
for item in prop.value_list}
self._speed_names = list(self._speed_name_map.values())
self._attr_speed_count = len(prop.value_list)
self._attr_supported_features |= FanEntityFeature.SET_SPEED
self._prop_fan_level = prop
elif prop.name == 'mode':
@ -156,6 +174,30 @@ class Fan(MIoTServiceEntity, FanEntity):
elif prop.name == 'horizontal-swing':
self._attr_supported_features |= FanEntityFeature.OSCILLATE
self._prop_horizontal_swing = prop
elif prop.name == 'wind-reverse':
if prop.format_ == 'bool':
self._prop_wind_reverse_forward = False
self._prop_wind_reverse_reverse = True
elif (
isinstance(prop.value_list, list)
and prop.value_list
):
for item in prop.value_list:
if item['name'].lower() in {'foreward'}:
self._prop_wind_reverse_forward = item['value']
elif item['name'].lower() in {
'reversal', 'reverse'}:
self._prop_wind_reverse_reverse = item['value']
if (
self._prop_wind_reverse_forward is None
or self._prop_wind_reverse_reverse is None
):
# NOTICE: Value may be 0 or False
_LOGGER.info(
'invalid wind-reverse, %s', self.entity_id)
continue
self._attr_supported_features |= FanEntityFeature.DIRECTION
self._prop_wind_reverse = prop
def __get_mode_description(self, key: int) -> Optional[str]:
if self._mode_list is None:
@ -182,9 +224,19 @@ class Fan(MIoTServiceEntity, FanEntity):
await self.set_property_async(prop=self._prop_on, value=True)
# percentage
if percentage:
await self.set_property_async(
prop=self._prop_fan_level,
value=int(percentage*self._attr_speed_count/100))
if self._speed_names:
speed = percentage_to_ordered_list_item(
self._speed_names, percentage)
speed_value = self.get_map_value(
map_=self._speed_name_map, description=speed)
await self.set_property_async(
prop=self._prop_fan_level, value=speed_value)
else:
await self.set_property_async(
prop=self._prop_fan_level,
value=int(percentage_to_ranged_value(
low_high_range=(self._speed_min, self._speed_max),
percentage=percentage)))
# preset_mode
if preset_mode:
await self.set_property_async(
@ -202,11 +254,19 @@ class Fan(MIoTServiceEntity, FanEntity):
async def async_set_percentage(self, percentage: int) -> None:
"""Set the percentage of the fan speed."""
if percentage > 0:
await self.set_property_async(
prop=self._prop_fan_level,
value=int(percentage_to_ranged_value(
low_high_range=(self._speed_min, self._speed_max),
percentage=percentage)))
if self._speed_names:
speed = percentage_to_ordered_list_item(
self._speed_names, percentage)
speed_value = self.get_map_value(
map_=self._speed_name_map, description=speed)
await self.set_property_async(
prop=self._prop_fan_level, value=speed_value)
else:
await self.set_property_async(
prop=self._prop_fan_level,
value=int(percentage_to_ranged_value(
low_high_range=(self._speed_min, self._speed_max),
percentage=percentage)))
if not self.is_on:
# If the fan is off, turn it on.
await self.set_property_async(prop=self._prop_on, value=True)
@ -221,6 +281,14 @@ class Fan(MIoTServiceEntity, FanEntity):
async def async_set_direction(self, direction: str) -> None:
"""Set the direction of the fan."""
if not self._prop_wind_reverse:
return
await self.set_property_async(
prop=self._prop_wind_reverse,
value=(
self._prop_wind_reverse_reverse
if self.current_direction == 'reverse'
else self._prop_wind_reverse_forward))
async def async_oscillate(self, oscillating: bool) -> None:
"""Oscillate the fan."""
@ -242,13 +310,28 @@ class Fan(MIoTServiceEntity, FanEntity):
key=self.get_prop_value(prop=self._prop_mode))
if self._prop_mode else None)
@property
def current_direction(self) -> Optional[str]:
"""Return the current direction of the fan."""
if not self._prop_wind_reverse:
return None
return 'reverse' if self.get_prop_value(
prop=self._prop_wind_reverse
) == self._prop_wind_reverse_reverse else 'forward'
@property
def percentage(self) -> Optional[int]:
"""Return the current percentage of the fan speed."""
fan_level = self.get_prop_value(prop=self._prop_fan_level)
return ranged_value_to_percentage(
low_high_range=(self._speed_min, self._speed_max),
value=fan_level) if fan_level else None
if fan_level is None:
return None
if self._speed_names:
return ordered_list_item_to_percentage(
self._speed_names, self._speed_name_map[fan_level])
else:
return ranged_value_to_percentage(
low_high_range=(self._speed_min, self._speed_max),
value=fan_level)
@property
def oscillating(self) -> Optional[bool]:
@ -257,8 +340,3 @@ class Fan(MIoTServiceEntity, FanEntity):
self.get_prop_value(
prop=self._prop_horizontal_swing)
if self._prop_horizontal_swing else None)
@property
def percentage_step(self) -> float:
"""Return the step of the fan speed."""
return self._speed_step

View File

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

View File

@ -18,6 +18,10 @@
ts: 1603967572
1245.airpurifier.dl01:
ts: 1607502661
17216.magic_touch.d150:
ts: 1575097876
17216.magic_touch.d152:
ts: 1575097876
17216.massage.ec1266a:
ts: 1615881124
397.light.hallight:
@ -56,6 +60,10 @@ bj352.airmonitor.m30:
ts: 1686644541
bj352.waterpuri.s100cm:
ts: 1615795630
bymiot.gateway.v1:
ts: 1575097876
bymiot.gateway.v2:
ts: 1575097876
cgllc.airmonitor.b1:
ts: 1676339912
cgllc.airmonitor.s1:
@ -64,6 +72,8 @@ cgllc.clock.cgc1:
ts: 1686644422
cgllc.clock.dove:
ts: 1619607474
cgllc.gateway.s1:
ts: 1575097876
cgllc.magnet.hodor:
ts: 1724329476
cgllc.motion.cgpr1:
@ -120,8 +130,14 @@ chuangmi.cateye.ipc018:
ts: 1632735241
chuangmi.cateye.ipc508:
ts: 1633677521
chuangmi.door.hmi508:
ts: 1611733437
chuangmi.door.hmi515:
ts: 1640334316
chuangmi.gateway.ipc011:
ts: 1575097876
chuangmi.ir.v2:
ts: 1575097876
chuangmi.lock.hmi501:
ts: 1614742147
chuangmi.lock.hmi501b01:
@ -142,10 +158,18 @@ chuangmi.plug.v1:
ts: 1621925183
chuangmi.plug.v3:
ts: 1644480255
chuangmi.plug.vtl_v1:
ts: 1575097876
chuangmi.radio.v1:
ts: 1531108800
chuangmi.radio.v2:
ts: 1531108800
chuangmi.remote.h102a03:
ts: 1575097876
chuangmi.remote.h102c01:
ts: 1575097876
chuangmi.remote.v2:
ts: 1575097876
chunmi.cooker.eh1:
ts: 1607339278
chunmi.cooker.eh402:
@ -204,6 +228,8 @@ dmaker.airfresh.t2017:
ts: 1686731233
dmaker.fan.p5:
ts: 1655793784
doco.fcb.docov001:
ts: 1575097876
dsm.lock.h3:
ts: 1615283790
dsm.lock.q3:
@ -218,6 +244,30 @@ fawad.airrtc.fwd20011:
ts: 1610607149
fbs.airmonitor.pth02:
ts: 1686644918
fengmi.projector.fm05:
ts: 1575097876
fengmi.projector.fm15:
ts: 1575097876
fengmi.projector.fm154k:
ts: 1575097876
fengmi.projector.l166:
ts: 1650352923
fengmi.projector.l176:
ts: 1649936204
fengmi.projector.l246:
ts: 1575097876
fengmi.projector.m055:
ts: 1652839826
fengmi.projector.m055d:
ts: 1654067980
fengyu.intercom.beebird:
ts: 1575097876
fengyu.intercom.sharkv1:
ts: 1575097876
fotile.hood.emd1tmi:
ts: 1607483642
guoshi.other.sem01:
ts: 1602662080
hannto.printer.anise:
ts: 1618989537
hannto.printer.honey:
@ -226,14 +276,26 @@ hannto.printer.honey1s:
ts: 1614332725
hfjh.fishbowl.v1:
ts: 1615278556
hhcc.bleflowerpot.v2:
ts: 1575097876
hhcc.plantmonitor.v1:
ts: 1664163526
hith.foot_bath.q2:
ts: 1531108800
hmpace.bracelet.v4:
ts: 1575097876
hmpace.scales.mibfs:
ts: 1575097876
hmpace.scales.miscale2:
ts: 1575097876
huohe.lock.m1:
ts: 1635410938
huoman.litter_box.co1:
ts: 1687165034
hutlon.lock.v0001:
ts: 1634799698
idelan.aircondition.g1:
ts: 1575097876
idelan.aircondition.v1:
ts: 1614666973
idelan.aircondition.v2:
@ -248,14 +310,22 @@ ikea.light.led1537r6:
ts: 1605162872
ikea.light.led1545g12:
ts: 1605162937
ikea.light.led1546g12:
ts: 1575097876
ikea.light.led1623g12:
ts: 1605163009
ikea.light.led1649c5:
ts: 1605163064
ikea.light.led1650r5:
ts: 1575097876
imibar.cooker.mbihr3:
ts: 1624620659
imou99.camera.tp2:
ts: 1531108800
inovel.projector.me2:
ts: 1575097876
iracc.aircondition.d19:
ts: 1609914362
isa.camera.df3:
ts: 1531108800
isa.camera.hl5:
@ -266,18 +336,34 @@ isa.camera.isc5:
ts: 1531108800
isa.camera.isc5c1:
ts: 1621238175
isa.camera.qf3:
ts: 1575097876
isa.cateye.hldb6:
ts: 1575097876
isa.magnet.dw2hl:
ts: 1638274655
jieman.magic_touch.js78:
ts: 1575097876
jiqid.mistory.ipen1:
ts: 1575097876
jiqid.mistory.pro:
ts: 1531108800
jiqid.mistory.v1:
ts: 1531108800
jiqid.mistudy.v2:
ts: 1610612349
jiqid.robot.cube:
ts: 1575097876
jiwu.lock.jwp01:
ts: 1614752632
jyaiot.cm.ccj01:
ts: 1611824545
k0918.toothbrush.kid01:
ts: 1575097876
kejia.airer.th001:
ts: 1575097876
ksmb.treadmill.k12:
ts: 1575097876
ksmb.treadmill.v1:
ts: 1611211447
ksmb.treadmill.v2:
@ -390,6 +476,8 @@ loock.lock.xfvl10:
ts: 1632814256
loock.safe.v1:
ts: 1619607755
lumi.acpartner.mcn02:
ts: 1655791626
lumi.acpartner.v1:
ts: 1531108800
lumi.acpartner.v2:
@ -462,6 +550,8 @@ lumi.lock.acn02:
ts: 1623928631
lumi.lock.acn03:
ts: 1614752574
lumi.lock.aq1:
ts: 1612518044
lumi.lock.bacn01:
ts: 1614741699
lumi.lock.bmcn02:
@ -482,6 +572,8 @@ lumi.lock.mcn007:
ts: 1650446757
lumi.lock.mcn01:
ts: 1679881881
lumi.lock.v1:
ts: 1575097876
lumi.lock.wbmcn1:
ts: 1619422072
lumi.motion.bmgl01:
@ -510,14 +602,20 @@ lumi.sensor_86sw1.v1:
ts: 1609311038
lumi.sensor_86sw2.v1:
ts: 1608795035
lumi.sensor_cube.aqgl01:
ts: 1575097876
lumi.sensor_ht.v1:
ts: 1621239877
lumi.sensor_magnet.aq2:
ts: 1641112867
lumi.sensor_magnet.v1:
ts: 1606120416
lumi.sensor_magnet.v2:
ts: 1641113779
lumi.sensor_motion.aq2:
ts: 1676433994
lumi.sensor_motion.v1:
ts: 1605093075
lumi.sensor_motion.v2:
ts: 1672818550
lumi.sensor_natgas.v1:
@ -530,6 +628,8 @@ lumi.sensor_switch.aq2:
ts: 1615256430
lumi.sensor_switch.aq3:
ts: 1607399487
lumi.sensor_switch.v1:
ts: 1606874434
lumi.sensor_switch.v2:
ts: 1609310683
lumi.sensor_wleak.aq1:
@ -574,6 +674,20 @@ miaomiaoce.sensor_ht.t1:
ts: 1616057242
miaomiaoce.sensor_ht.t2:
ts: 1636603553
miaomiaoce.thermo.t01:
ts: 1575097876
midea.aircondition.v1:
ts: 1575097876
midea.aircondition.xa1:
ts: 1575097876
midea.aircondition.xa2:
ts: 1575097876
midr.rv_mirror.m2:
ts: 1575097876
midr.rv_mirror.m5:
ts: 1575097876
midr.rv_mirror.v1:
ts: 1575097876
miir.aircondition.ir01:
ts: 1531108800
miir.aircondition.ir02:
@ -612,6 +726,8 @@ minij.washer.v5:
ts: 1622792196
minij.washer.v8:
ts: 1615777868
minuo.tracker.lm001:
ts: 1575097876
miot.light.plato2:
ts: 1685518142
miot.light.plato3:
@ -624,18 +740,32 @@ mmgg.feeder.snack:
ts: 1607503182
moyu.washer.s1hm:
ts: 1624620888
mrbond.airer.m0:
ts: 1575097876
mrbond.airer.m1pro:
ts: 1646393746
mrbond.airer.m1s:
ts: 1646393874
mrbond.airer.m1super:
ts: 1575097876
msj.f_washer.m1:
ts: 1614914340
mxiang.cateye.mdb10:
ts: 1616140362
mxiang.cateye.xmcatt1:
ts: 1616140207
nhy.airrtc.v1:
ts: 1575097876
ninebot.scooter.v1:
ts: 1602662395
ninebot.scooter.v6:
ts: 1575097876
nuwa.robot.minikiwi:
ts: 1575097876
nwt.derh.wdh318efw1:
ts: 1611822375
onemore.wifispeaker.sm4:
ts: 1575097876
opple.light.bydceiling:
ts: 1608187619
opple.light.fanlight:
@ -646,6 +776,8 @@ opple.remote.5pb112:
ts: 1627453840
opple.remote.5pb113:
ts: 1636599905
orion.wifispeaker.cm1:
ts: 1575097876
ows.towel_w.mj1x0:
ts: 1610604939
philips.light.bceiling1:
@ -696,6 +828,8 @@ pwzn.relay.apple:
ts: 1611217196
pwzn.relay.banana:
ts: 1646647255
qicyc.bike.tdp02z:
ts: 1575097876
qike.bhf_light.qk201801:
ts: 1608174909
qmi.powerstrip.v1:
@ -726,8 +860,32 @@ roborock.vacuum.t6:
ts: 1619423841
rockrobo.vacuum.v1:
ts: 1531108800
roidmi.carairpuri.pro:
ts: 1575097876
roidmi.carairpuri.v1:
ts: 1575097876
roidmi.cleaner.f8pro:
ts: 1575097876
roidmi.cleaner.v1:
ts: 1575097876
roidmi.cleaner.v2:
ts: 1638514177
roidmi.cleaner.v382:
ts: 1575097876
roidmi.vacuum.v1:
ts: 1575097876
rokid.robot.me:
ts: 1575097876
rokid.robot.mini:
ts: 1575097876
rokid.robot.pebble:
ts: 1575097876
rokid.robot.pebble2:
ts: 1575097876
roome.bhf_light.yf6002:
ts: 1531108800
rotai.magic_touch.sx300:
ts: 1602662578
rotai.massage.rt5728:
ts: 1610607000
rotai.massage.rt5850:
@ -738,22 +896,42 @@ rotai.massage.rt5863:
ts: 1611827937
rotai.massage.rt5870:
ts: 1632376570
runmi.suitcase.v1:
ts: 1575097876
scishare.coffee.s1102:
ts: 1611824402
shjszn.gateway.c1:
ts: 1575097876
shjszn.lock.c1:
ts: 1575097876
shjszn.lock.kx:
ts: 1575097876
shuii.humidifier.jsq001:
ts: 1575097876
shuii.humidifier.jsq002:
ts: 1606376290
skyrc.feeder.dfeed:
ts: 1626082349
skyrc.pet_waterer.fre1:
ts: 1608186812
smith.w_soften.cxs05ta1:
ts: 1575097876
smith.waterheater.cxea1:
ts: 1611826349
smith.waterheater.cxeb1:
ts: 1611826388
smith.waterpuri.jnt600:
ts: 1531108800
soocare.toothbrush.m1:
ts: 1575097876
soocare.toothbrush.m1s:
ts: 1610611310
soocare.toothbrush.mc1:
ts: 1575097876
soocare.toothbrush.t501:
ts: 1672192586
soocare.toothbrush.x3:
ts: 1575097876
sxds.pillow.pillow02:
ts: 1611222235
syniot.curtain.syc1:
@ -778,6 +956,10 @@ tokit.oven.tk32pro1:
ts: 1617002408
tokit.pre_cooker.tkih1:
ts: 1607410832
trios1.bleshoes.v02:
ts: 1602662599
txdd.wifispeaker.x1:
ts: 1575097876
viomi.aircondition.v10:
ts: 1606375041
viomi.aircondition.v21:
@ -830,12 +1012,16 @@ viomi.fridge.u13:
ts: 1614667152
viomi.fridge.u15:
ts: 1607505693
viomi.fridge.u17:
ts: 1575097876
viomi.fridge.u18:
ts: 1614655755
viomi.fridge.u2:
ts: 1531108800
viomi.fridge.u24:
ts: 1614667214
viomi.fridge.u25:
ts: 1575097876
viomi.fridge.u4:
ts: 1614667295
viomi.fridge.u6:
@ -992,6 +1178,82 @@ xiaomi.aircondition.ma6:
ts: 1721629272
xiaomi.aircondition.ma9:
ts: 1721629362
xiaomi.plc.v1:
ts: 1575097876
xiaomi.repeater.v1:
ts: 1575097876
xiaomi.repeater.v2:
ts: 1575097876
xiaomi.repeater.v3:
ts: 1575097876
xiaomi.router.d01:
ts: 1575097876
xiaomi.router.lv1:
ts: 1575097876
xiaomi.router.lv3:
ts: 1575097876
xiaomi.router.mv1:
ts: 1575097876
xiaomi.router.r2100:
ts: 1575097876
xiaomi.router.r3600:
ts: 1575097876
xiaomi.router.r3a:
ts: 1575097876
xiaomi.router.r3d:
ts: 1575097876
xiaomi.router.r3g:
ts: 1575097876
xiaomi.router.r3gv2:
ts: 1575097876
xiaomi.router.r3gv2n:
ts: 1575097876
xiaomi.router.r3p:
ts: 1575097876
xiaomi.router.r4:
ts: 1575097876
xiaomi.router.r4a:
ts: 1575097876
xiaomi.router.r4ac:
ts: 1575097876
xiaomi.router.r4c:
ts: 1575097876
xiaomi.router.r4cm:
ts: 1575097876
xiaomi.router.rm1800:
ts: 1575097876
xiaomi.router.v1:
ts: 1575097876
xiaomi.router.v2:
ts: 1575097876
xiaomi.router.v3:
ts: 1575097876
xiaomi.split_tv.b1:
ts: 1575097876
xiaomi.split_tv.v1:
ts: 1575097876
xiaomi.tv.b1:
ts: 1661248580
xiaomi.tv.h1:
ts: 1575097876
xiaomi.tv.i1:
ts: 1661248572
xiaomi.tv.v1:
ts: 1670811870
xiaomi.tvbox.b1:
ts: 1694503508
xiaomi.tvbox.i1:
ts: 1694503515
xiaomi.tvbox.v1:
ts: 1694503501
xiaomi.watch.band1:
ts: 1575097876
xiaomi.watch.band1A:
ts: 1575097876
xiaomi.watch.band1S:
ts: 1575097876
xiaomi.watch.band2:
ts: 1575097876
xiaomi.wifispeaker.l04m:
ts: 1658817956
xiaomi.wifispeaker.l06a:
@ -1012,6 +1274,10 @@ xiaomi.wifispeaker.lx5a:
ts: 1672299577
xiaomi.wifispeaker.s12:
ts: 1672299594
xiaomi.wifispeaker.v1:
ts: 1575097876
xiaomi.wifispeaker.v3:
ts: 1575097876
xiaomi.wifispeaker.x08a:
ts: 1672818945
xiaomi.wifispeaker.x08c:
@ -1028,6 +1294,44 @@ xiaovv.camera.xvd5:
ts: 1531108800
xiaovv.camera.xvsnowman:
ts: 1531108800
xiaoxun.robot.v1:
ts: 1575097876
xiaoxun.tracker.v1:
ts: 1575097876
xiaoxun.watch.sw306:
ts: 1575097876
xiaoxun.watch.sw560:
ts: 1575097876
xiaoxun.watch.sw705:
ts: 1575097876
xiaoxun.watch.sw710a2:
ts: 1575097876
xiaoxun.watch.sw760:
ts: 1575097876
xiaoxun.watch.sw900:
ts: 1575097876
xiaoxun.watch.sw960:
ts: 1575097876
xiaoxun.watch.v1:
ts: 1575097876
xiaoxun.watch.v10:
ts: 1575097876
xiaoxun.watch.v11:
ts: 1575097876
xiaoxun.watch.v2:
ts: 1575097876
xiaoxun.watch.v3:
ts: 1575097876
xiaoxun.watch.v4:
ts: 1575097876
xiaoxun.watch.v5:
ts: 1575097876
xiaoxun.watch.v7:
ts: 1575097876
xiaoxun.watch.v8:
ts: 1575097876
xiaoxun.watch.v9:
ts: 1575097876
xjx.toilet.pro:
ts: 1615965466
xjx.toilet.pure:
@ -1054,6 +1358,8 @@ yeelink.bhf_light.v3:
ts: 1608790102
yeelink.bhf_light.v5:
ts: 1601292562
yeelink.gateway.v1:
ts: 1575097876
yeelink.light.bslamp1:
ts: 1703120679
yeelink.light.bslamp2:
@ -1192,6 +1498,10 @@ yunmi.kettle.r2:
ts: 1606372087
yunmi.kettle.r3:
ts: 1637309534
yunmi.kettle.v1:
ts: 1575097876
yunmi.kettle.v9:
ts: 1602662686
yunmi.plmachine.mg2:
ts: 1611833658
yunmi.waterpuri.c5:
@ -1230,18 +1540,26 @@ yunmi.waterpurifier.v2:
ts: 1632377061
yunmi.waterpurifier.v3:
ts: 1611221428
yunyi.camera.v1:
ts: 1575097876
yyunyi.wopener.yypy24:
ts: 1616741966
yyzhn.gateway.yn181126:
ts: 1610689325
zdeer.ajh.a8:
ts: 1531108800
zdeer.ajh.a9:
ts: 1531108800
zdeer.ajh.ajb:
ts: 1608276454
zdeer.ajh.zda10:
ts: 1531108800
zdeer.ajh.zda9:
ts: 1531108800
zdeer.ajh.zjy:
ts: 1531108800
zhij.toothbrush.bv1:
ts: 1575097876
zhimi.aircondition.ma1:
ts: 1615185265
zhimi.aircondition.ma3:
@ -1250,6 +1568,8 @@ zhimi.aircondition.ma4:
ts: 1626334057
zhimi.aircondition.v1:
ts: 1610610931
zhimi.aircondition.v2:
ts: 1575097876
zhimi.aircondition.va1:
ts: 1609924720
zhimi.aircondition.za1:
@ -1276,8 +1596,12 @@ zhimi.airpurifier.sa2:
ts: 1635820002
zhimi.airpurifier.v1:
ts: 1635855633
zhimi.airpurifier.v2:
ts: 1575097876
zhimi.airpurifier.v3:
ts: 1676339933
zhimi.airpurifier.v5:
ts: 1575097876
zhimi.airpurifier.v6:
ts: 1636978652
zhimi.airpurifier.v7:
@ -1318,3 +1642,5 @@ zimi.mosq.v1:
ts: 1620728957
zimi.powerstrip.v2:
ts: 1620812714
zimi.projector.v1:
ts: 1575097876

View File

@ -257,6 +257,7 @@ class MIoTClient:
client_id=OAUTH2_CLIENT_ID,
redirect_url=self._entry_data['oauth_redirect_url'],
cloud_server=self._cloud_server,
uuid=self._entry_data["uuid"],
loop=self._main_loop)
# MIoT http client instance
self._http = MIoTHttpClient(

View File

@ -75,10 +75,11 @@ class MIoTOauthClient:
_oauth_host: str
_client_id: int
_redirect_url: str
_device_id: str
def __init__(
self, client_id: str, redirect_url: str, cloud_server: str,
loop: Optional[asyncio.AbstractEventLoop] = None
uuid: str, loop: Optional[asyncio.AbstractEventLoop] = None
) -> None:
self._main_loop = loop or asyncio.get_running_loop()
if client_id is None or client_id.strip() == '':
@ -87,6 +88,8 @@ class MIoTOauthClient:
raise MIoTOauthError('invalid redirect_url')
if not cloud_server:
raise MIoTOauthError('invalid cloud_server')
if not uuid:
raise MIoTOauthError('invalid uuid')
self._client_id = int(client_id)
self._redirect_url = redirect_url
@ -94,6 +97,7 @@ class MIoTOauthClient:
self._oauth_host = DEFAULT_OAUTH2_API_HOST
else:
self._oauth_host = f'{cloud_server}.{DEFAULT_OAUTH2_API_HOST}'
self._device_id = f'ha.{uuid}'
self._session = aiohttp.ClientSession(loop=self._main_loop)
async def deinit_async(self) -> None:
@ -132,6 +136,7 @@ class MIoTOauthClient:
'redirect_uri': redirect_url or self._redirect_url,
'client_id': self._client_id,
'response_type': 'code',
'device_id': self._device_id
}
if state:
params['state'] = state
@ -191,6 +196,7 @@ class MIoTOauthClient:
'client_id': self._client_id,
'redirect_uri': self._redirect_url,
'code': code,
'device_id': self._device_id
})
async def refresh_access_token_async(self, refresh_token: str) -> dict:
@ -531,9 +537,18 @@ class MIoTHttpClient:
name = device.get('name', None)
urn = device.get('spec_type', None)
model = device.get('model', None)
if did is None or name is None or urn is None or model is None:
_LOGGER.error(
'get_device_list, cloud, invalid device, %s', device)
if did is None or name is None:
_LOGGER.info(
'invalid device, cloud, %s', device)
continue
if urn is None or model is None:
_LOGGER.info(
'missing the urn|model field, cloud, %s', device)
continue
if did.startswith('miwifi.'):
# The miwifi.* routers defined SPEC functions, but none of them
# were implemented.
_LOGGER.info('ignore miwifi.* device, cloud, %s', did)
continue
device_infos[did] = {
'did': did,
@ -634,7 +649,7 @@ class MIoTHttpClient:
for did in dids:
if did not in results:
devices.pop(did, None)
_LOGGER.error('get device info failed, %s', did)
_LOGGER.info('get device info failed, %s', did)
continue
devices[did].update(results[did])
# Whether sub devices

View File

@ -59,5 +59,10 @@
"1",
"5"
]
},
"urn:miot-spec-v2:device:router:0000A036:xiaomi-rd03": {
"services": [
"*"
]
}
}

View File

@ -289,7 +289,7 @@ SPEC_SERVICE_TRANS_MAP: dict[str, dict | str] = {
}
},
'optional': {
'properties': {'mode', 'horizontal-swing'}
'properties': {'mode', 'horizontal-swing', 'wind-reverse'}
},
'entity': 'fan'
},

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Xiaomi MQTT Broker-Adresse ist nicht erreichbar, bitte überprüfen Sie die Netzwerkkonfiguration."
},
"abort": {
"ha_uuid_get_failed": "Fehler beim Abrufen der Home Assistant-UUID.",
"network_connect_error": "Konfiguration fehlgeschlagen. Netzwerkverbindung fehlgeschlagen. Überprüfen Sie die Netzwerkkonfiguration des Geräts.",
"already_configured": "Dieser Benutzer hat die Konfiguration bereits abgeschlossen. Gehen Sie zur Integrationsseite und klicken Sie auf die Schaltfläche \"Konfiguration\", um die Konfiguration zu ändern.",
"invalid_auth_info": "Authentifizierungsinformationen sind abgelaufen. Gehen Sie zur Integrationsseite und klicken Sie auf die Schaltfläche \"Konfiguration\", um die Authentifizierung erneut durchzuführen.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Unable to reach Xiaomi MQTT Broker address, please check network configuration."
},
"abort": {
"ha_uuid_get_failed": "Failed to get Home Assistant UUID.",
"network_connect_error": "Configuration failed. The network connection is abnormal. Please check the equipment network configuration.",
"already_configured": "Configuration for this user is already completed. Please go to the integration page and click the CONFIGURE button for modifications.",
"invalid_auth_info": "Authentication information has expired. Please go to the integration page and click the CONFIGURE button to re-authenticate.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "No se puede acceder a la dirección del Broker MQTT de Xiaomi, por favor verifique la configuración de la red."
},
"abort": {
"ha_uuid_get_failed": "Error al obtener el UUID de Home Assistant.",
"network_connect_error": "La configuración ha fallado. Existe un problema con la conexión de red, verifique la configuración de red del dispositivo.",
"already_configured": "Esta cuenta ya ha finalizado la configuración. Ingrese a la página de integración y haga clic en el botón \"Configurar\" para modificar la configuración.",
"invalid_auth_info": "La información de autorización ha caducado. Ingrese a la página de integración y haga clic en el botón \"Configurar\" para volver a autenticarse.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Impossible d'atteindre l'adresse du Broker MQTT de Xiaomi, veuillez vérifier la configuration réseau."
},
"abort": {
"ha_uuid_get_failed": "Échec de l'obtention de l'UUID de Home Assistant.",
"network_connect_error": "La configuration a échoué. Erreur de connexion réseau. Veuillez vérifier la configuration du réseau de l'appareil.",
"already_configured": "Cet utilisateur a déjà terminé la configuration. Veuillez accéder à la page d'intégration et cliquer sur le bouton \"Configurer\" pour modifier la configuration.",
"invalid_auth_info": "Les informations d'authentification ont expiré. Veuillez accéder à la page d'intégration et cliquer sur le bouton \"Configurer\" pour vous authentifier à nouveau.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Xiaomi MQTT ブローカーアドレスにアクセスできません。ネットワーク設定を確認してください。"
},
"abort": {
"ha_uuid_get_failed": "Home Assistant インスタンスIDを取得できませんでした。",
"network_connect_error": "設定に失敗しました。ネットワーク接続に異常があります。デバイスのネットワーク設定を確認してください。",
"already_configured": "このユーザーはすでに設定が完了しています。統合ページにアクセスして、「設定」ボタンをクリックして設定を変更してください。",
"invalid_auth_info": "認証情報が期限切れになりました。統合ページにアクセスして、「設定」ボタンをクリックして再度認証してください。",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Kan Xiaomi MQTT Broker-adres niet bereiken, controleer de netwerkconfiguratie."
},
"abort": {
"ha_uuid_get_failed": "Mislukt bij het ophalen van Home Assistant UUID.",
"network_connect_error": "Configuratie mislukt. De netwerkverbinding is abnormaal. Controleer de netwerkinstellingen van de apparatuur.",
"already_configured": "Configuratie voor deze gebruiker is al voltooid. Ga naar de integratiepagina en klik op de CONFIGUREER-knop om wijzigingen aan te brengen.",
"invalid_auth_info": "Authenticatie-informatie is verlopen. Ga naar de integratiepagina en klik op de CONFIGUREER-knop om opnieuw te authentiseren.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Não é possível acessar o endereço do Broker MQTT da Xiaomi, verifique a configuração da rede."
},
"abort": {
"ha_uuid_get_failed": "Falha ao obter o UUID do Home Assistant.",
"network_connect_error": "Configuração falhou. A conexão de rede está anormal. Verifique a configuração de rede do equipamento.",
"already_configured": "A configuração para este usuário já foi concluída. Vá para a página de integrações e clique no botão CONFIGURAR para modificações.",
"invalid_auth_info": "As informações de autenticação expiraram. Vá para a página de integrações e clique em CONFIGURAR para reautenticar.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Não é possível acessar o endereço do Broker MQTT da Xiaomi, verifique a configuração da rede."
},
"abort": {
"ha_uuid_get_failed": "Não foi possível obter o UUID do Home Assistant.",
"network_connect_error": "A configuração falhou. A ligação de rede é anormal. Verifique a configuração de rede do equipamento.",
"already_configured": "A configuração para este utilizador já foi concluída. Vá à página de integrações e clique em CONFIGURAR para efetuar alterações.",
"invalid_auth_info": "A informação de autenticação expirou. Vá à página de integrações e clique em CONFIGURAR para reautenticar.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "Не удается подключиться к адресу MQTT брокера Xiaomi, проверьте настройки сети."
},
"abort": {
"ha_uuid_get_failed": "Не удалось получить UUID Home Assistant.",
"network_connect_error": "Ошибка настройки. Сетевое подключение недоступно. Проверьте настройки сети устройства.",
"already_configured": "Этот пользователь уже настроен. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы изменить настройки.",
"invalid_auth_info": "Информация об авторизации истекла. Перейдите на страницу интеграции и нажмите кнопку «Настроить», чтобы переавторизоваться.",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "无法访问小米 MQTT Broker 地址,请检查网络配置。"
},
"abort": {
"ha_uuid_get_failed": "获取 Home Assistant UUID 失败。",
"network_connect_error": "配置失败。网络连接异常,请检查设备网络配置。",
"already_configured": "该用户已配置完成。请进入集成页面,点击“配置”按钮修改配置。",
"invalid_auth_info": "认证信息已过期。请进入集成页面,点击“配置”按钮重新认证。",

View File

@ -90,6 +90,7 @@
"unreachable_mqtt_broker": "無法訪問小米 MQTT Broker 地址,請檢查網絡配置。"
},
"abort": {
"ha_uuid_get_failed": "獲取 Home Assistant UUID 失敗。",
"network_connect_error": "配置失敗。網絡連接異常,請檢查設備網絡配置。",
"already_configured": "該用戶已配置完成。請進入集成頁面,點擊“配置”按鈕修改配置。",
"invalid_auth_info": "認證信息已過期。請進入集成頁面,點擊“配置”按鈕重新認證。",