diff --git a/custom_components/xiaomi_home/miot/common.py b/custom_components/xiaomi_home/miot/common.py index 5a5137d..0b03f96 100644 --- a/custom_components/xiaomi_home/miot/common.py +++ b/custom_components/xiaomi_home/miot/common.py @@ -46,10 +46,19 @@ Common utilities. """ import json +from os import path import random from typing import Optional import hashlib from paho.mqtt.client import MQTTMatcher +import yaml + +MIOT_ROOT_PATH: str = path.dirname(path.abspath(__file__)) + + +def gen_absolute_path(relative_path: str) -> str: + """Generate an absolute path.""" + return path.join(MIOT_ROOT_PATH, relative_path) def calc_group_id(uid: str, home_id: str) -> str: @@ -64,6 +73,12 @@ def load_json_file(json_file: str) -> dict: return json.load(f) +def load_yaml_file(yaml_file: str) -> dict: + """Load a YAML file.""" + with open(yaml_file, 'r', encoding='utf-8') as f: + return yaml.load(f, Loader=yaml.FullLoader) + + def randomize_int(value: int, ratio: float) -> int: """Randomize an integer value.""" return int(value * (1 - ratio + random.random()*2*ratio)) @@ -74,12 +89,12 @@ class MIoTMatcher(MQTTMatcher): def iter_all_nodes(self) -> any: """Return an iterator on all nodes with their paths and contents.""" - def rec(node, path): + def rec(node, path_): # pylint: disable=protected-access if node._content: - yield ('/'.join(path), node._content) + yield ('/'.join(path_), node._content) for part, child in node._children.items(): - yield from rec(child, path + [part]) + yield from rec(child, path_ + [part]) return rec(self._root, []) def get(self, topic: str) -> Optional[any]: diff --git a/custom_components/xiaomi_home/miot/lan/profile_models.yaml b/custom_components/xiaomi_home/miot/lan/profile_models.yaml new file mode 100644 index 0000000..5e14086 --- /dev/null +++ b/custom_components/xiaomi_home/miot/lan/profile_models.yaml @@ -0,0 +1,1320 @@ +090615.curtain.mt800w: + ts: 1604589513 +090615.curtain.p01: + ts: 1603355069 +090615.curtain.sidt82: + ts: 1604589553 +090615.switch.switch01: + ts: 1605166385 +090615.switch.switch02: + ts: 1604589655 +090615.switch.switch03: + ts: 1605161171 +090615.switch.xswitch01: + ts: 1603965395 +090615.switch.xswitch02: + ts: 1603967482 +090615.switch.xswitch03: + ts: 1603967572 +1245.airpurifier.dl01: + ts: 1607502661 +17216.massage.ec1266a: + ts: 1615881124 +397.light.hallight: + ts: 1605161883 +666.curtain.em75: + ts: 1605857796 +aden.aircondition.a1: + ts: 1618982254 +aden.aircondition.a2: + ts: 1605167390 +aden.aircondition.a4: + ts: 1605167477 +aice.motor.kzmu3: + ts: 1646394583 +air.fan.ca23ad9: + ts: 1635406920 +airdog.airpurifier.x5: + ts: 1623915265 +airdog.airpurifier.x7: + ts: 1614656371 +airdog.airpurifier.x7sm: + ts: 1614656402 +asp.treadmill.pbj: + ts: 1611217046 +aux.aircondition.v1: + ts: 1626427548 +bdx.i_stove.a1xs: + ts: 1610614201 +bdx.i_stove.a1z: + ts: 1614667065 +bdx.i_stove.c1x: + ts: 1610614303 +bdx.i_stove.c2x: + ts: 1611823486 +bj352.airmonitor.m30: + ts: 1686644541 +bj352.waterpuri.s100cm: + ts: 1615795630 +cgllc.airmonitor.b1: + ts: 1676339912 +cgllc.airmonitor.s1: + ts: 1608189468 +cgllc.clock.cgc1: + ts: 1686644422 +cgllc.clock.dove: + ts: 1619607474 +cgllc.magnet.hodor: + ts: 1724329476 +cgllc.motion.cgpr1: + ts: 1639479505 +cgllc.sensor_ht.cgm1: + ts: 1602667557 +cgllc.sensor_ht.dk2: + ts: 1620724988 +cgllc.sensor_ht.g1: + ts: 1607505446 +cgllc.sensor_ht.qpg1: + ts: 1602667461 +chuangmi.camera.ipc004b: + ts: 1531108800 +chuangmi.camera.ipc007b: + ts: 1531108800 +chuangmi.camera.ipc009: + ts: 1531108800 +chuangmi.camera.ipc010: + ts: 1531108800 +chuangmi.camera.ipc013: + ts: 1531108800 +chuangmi.camera.ipc013d: + ts: 1531108800 +chuangmi.camera.ipc016: + ts: 1531108800 +chuangmi.camera.ipc017: + ts: 1531108800 +chuangmi.camera.ipc019: + ts: 1531108800 +chuangmi.camera.ipc019b: + ts: 1531108800 +chuangmi.camera.ipc019e: + ts: 1531108800 +chuangmi.camera.ipc020: + ts: 1531108800 +chuangmi.camera.ipc021: + ts: 1531108800 +chuangmi.camera.v2: + ts: 1531108800 +chuangmi.camera.v3: + ts: 1531108800 +chuangmi.camera.v4: + ts: 1531108800 +chuangmi.camera.v5: + ts: 1531108800 +chuangmi.camera.v6: + ts: 1531108800 +chuangmi.camera.xiaobai: + ts: 1531108800 +chuangmi.cateye.i023a01: + ts: 1624535092 +chuangmi.cateye.ipc018: + ts: 1632735241 +chuangmi.cateye.ipc508: + ts: 1633677521 +chuangmi.door.hmi515: + ts: 1640334316 +chuangmi.lock.hmi501: + ts: 1614742147 +chuangmi.lock.hmi501b01: + ts: 1614742108 +chuangmi.lock.hmi503a01: + ts: 1614742180 +chuangmi.lock.hmi505a01: + ts: 1614742900 +chuangmi.plug.hmi206: + ts: 1645409193 +chuangmi.plug.hmi208: + ts: 1677652804 +chuangmi.plug.m1: + ts: 1620814339 +chuangmi.plug.m3: + ts: 1637228027 +chuangmi.plug.v1: + ts: 1621925183 +chuangmi.plug.v3: + ts: 1644480255 +chuangmi.radio.v1: + ts: 1531108800 +chuangmi.radio.v2: + ts: 1531108800 +chunmi.cooker.eh1: + ts: 1607339278 +chunmi.cooker.eh402: + ts: 1638506382 +chunmi.cooker.k1pro1: + ts: 1607393855 +chunmi.cooker.normal2: + ts: 1607393898 +chunmi.cooker.normal3: + ts: 1620369915 +chunmi.cooker.normal4: + ts: 1607394370 +chunmi.cooker.normal5: + ts: 1607394381 +chunmi.cooker.normalcd1: + ts: 1607395198 +chunmi.cooker.normalcd2: + ts: 1607395220 +chunmi.cooker.press1: + ts: 1607395268 +chunmi.cooker.press2: + ts: 1607395280 +chunmi.ihcooker.chefnic: + ts: 1604591216 +chunmi.ihcooker.double: + ts: 1609924806 +chunmi.ihcooker.hk1: + ts: 1605167058 +chunmi.ihcooker.tkpro1: + ts: 1614756253 +chunmi.ihcooker.tkv1: + ts: 1615801005 +chunmi.ihcooker.v1: + ts: 1605167116 +chunmi.juicer.a1: + ts: 1624530635 +chunmi.microwave.n20l01: + ts: 1638505282 +chunmi.microwave.n23l01: + ts: 1638505524 +chunmi.oven.steam30lv1: + ts: 1605855556 +chunmi.pre_cooker.eh1: + ts: 1614570773 +cleargrass.sensor_ht.dk1: + ts: 1619344277 +deerma.humidifier.jsq1: + ts: 1683863719 +deerma.humidifier.mjjsq: + ts: 1684727440 +dicook.cooker.wfz4003: + ts: 1614678405 +dmaker.airfresh.a1: + ts: 1715677691 +dmaker.airfresh.t2017: + ts: 1686731233 +dmaker.fan.p5: + ts: 1655793784 +dsm.lock.h3: + ts: 1615283790 +dsm.lock.q3: + ts: 1614741870 +dsm.lock.r5: + ts: 1614741913 +dun.cateye.nknk500: + ts: 1615358692 +duoqin.safe.pbfv01: + ts: 1614740167 +fawad.airrtc.fwd20011: + ts: 1610607149 +fbs.airmonitor.pth02: + ts: 1686644918 +hannto.printer.anise: + ts: 1618989537 +hannto.printer.honey: + ts: 1607504864 +hannto.printer.honey1s: + ts: 1614332725 +hfjh.fishbowl.v1: + ts: 1615278556 +hhcc.plantmonitor.v1: + ts: 1664163526 +hith.foot_bath.q2: + ts: 1531108800 +huohe.lock.m1: + ts: 1635410938 +hutlon.lock.v0001: + ts: 1634799698 +idelan.aircondition.v1: + ts: 1614666973 +idelan.aircondition.v2: + ts: 1626427579 +ihealth.bp.bpm1: + ts: 1608189506 +ihealth.bpm.kd5907: + ts: 1614673307 +ikea.light.led1536g5: + ts: 1605162819 +ikea.light.led1537r6: + ts: 1605162872 +ikea.light.led1545g12: + ts: 1605162937 +ikea.light.led1623g12: + ts: 1605163009 +ikea.light.led1649c5: + ts: 1605163064 +imibar.cooker.mbihr3: + ts: 1624620659 +imou99.camera.tp2: + ts: 1531108800 +isa.camera.df3: + ts: 1531108800 +isa.camera.hl5: + ts: 1531108800 +isa.camera.hlc6: + ts: 1531108800 +isa.camera.isc5: + ts: 1531108800 +isa.camera.isc5c1: + ts: 1621238175 +isa.magnet.dw2hl: + ts: 1638274655 +jiqid.mistory.pro: + ts: 1531108800 +jiqid.mistory.v1: + ts: 1531108800 +jiqid.mistudy.v2: + ts: 1610612349 +jiwu.lock.jwp01: + ts: 1614752632 +jyaiot.cm.ccj01: + ts: 1611824545 +ksmb.treadmill.v1: + ts: 1611211447 +ksmb.treadmill.v2: + ts: 1610606684 +ksmb.walkingpad.v1: + ts: 1621238199 +ksmb.walkingpad.v3: + ts: 1621238214 +kxf321.mop.mo001: + ts: 1638343629 +lcrmcr.safe.20mini: + ts: 1617765416 +lcrmcr.safe.30mk: + ts: 1628215806 +lcrmcr.safe.an35sidz: + ts: 1614741042 +lcrmcr.safe.an35sizw: + ts: 1614741076 +lcrmcr.safe.d60ht: + ts: 1624351108 +lcrmcr.safe.ms30b: + ts: 1606986586 +lcrmcr.safe.ms30mp: + ts: 1604587256 +lcrmcr.safe.ms55kn: + ts: 1606980410 +lcrmcr.safe.ms80b: + ts: 1614740261 +lcrmcr.safe.sd003: + ts: 1637033698 +lcrmcr.safe.x142: + ts: 1634813125 +leshow.fan.ss310: + ts: 1686896880 +leshow.fan.ss320: + ts: 1686896668 +leshow.fan.ss4: + ts: 1606376586 +leshow.heater.bs1: + ts: 1608187309 +leshow.humidifier.is2: + ts: 1604589602 +linp.doorbell.g03: + ts: 1609311251 +linp.remote.k9b: + ts: 1621825941 +linp.remote.k9b1: + ts: 1621825926 +linp.remote.k9b11: + ts: 1621825903 +loock.cateye.v01: + ts: 1627291525 +loock.cateye.v02: + ts: 1661739898 +loock.lock.cc2s: + ts: 1614752275 +loock.lock.cc2xpro: + ts: 1614752365 +loock.lock.fcl112: + ts: 1658997537 +loock.lock.fcp50m: + ts: 1647246522 +loock.lock.fvl109: + ts: 1640252939 +loock.lock.fvl111: + ts: 1646134370 +loock.lock.ojjz1: + ts: 1614741370 +loock.lock.p50: + ts: 1644572168 +loock.lock.pfvl10: + ts: 1630040903 +loock.lock.s30: + ts: 1614740862 +loock.lock.s30v2: + ts: 1614829588 +loock.lock.s50c: + ts: 1649309703 +loock.lock.s50f: + ts: 1639967451 +loock.lock.t1: + ts: 1634542543 +loock.lock.t1pro: + ts: 1634543113 +loock.lock.t2v1: + ts: 1655983879 +loock.lock.v1: + ts: 1618889646 +loock.lock.v14: + ts: 1614741632 +loock.lock.v15: + ts: 1619508939 +loock.lock.v16: + ts: 1621235279 +loock.lock.v3: + ts: 1619341106 +loock.lock.v4: + ts: 1619340970 +loock.lock.v5: + ts: 1614752242 +loock.lock.v6: + ts: 1634796911 +loock.lock.v7: + ts: 1614741195 +loock.lock.v8: + ts: 1619413983 +loock.lock.v9: + ts: 1614741328 +loock.lock.xfvl10: + ts: 1632814256 +loock.safe.v1: + ts: 1619607755 +lumi.acpartner.v1: + ts: 1531108800 +lumi.acpartner.v2: + ts: 1531108800 +lumi.acpartner.v3: + ts: 1531108800 +lumi.airer.acn01: + ts: 1611818317 +lumi.airrtc.tcpco2ecn01: + ts: 1531108800 +lumi.airrtc.tcpecn01: + ts: 1531108800 +lumi.airrtc.tcpecn02: + ts: 1531108800 +lumi.camera.aq1: + ts: 1531108800 +lumi.camera.gwagl01: + ts: 1531108800 +lumi.ctrl_86plug.aq1: + ts: 1627292331 +lumi.ctrl_86plug.v1: + ts: 1627291597 +lumi.ctrl_ln1.aq1: + ts: 1648791623 +lumi.ctrl_ln1.v1: + ts: 1653297884 +lumi.ctrl_ln2.aq1: + ts: 1653292857 +lumi.ctrl_ln2.v1: + ts: 1653299006 +lumi.ctrl_neutral1.v1: + ts: 1653294867 +lumi.ctrl_neutral2.v1: + ts: 1653294492 +lumi.curtain.aq2: + ts: 1605857829 +lumi.curtain.hagl04: + ts: 1615351634 +lumi.curtain.v1: + ts: 1608188918 +lumi.flood.bmcn01: + ts: 1614666824 +lumi.gateway.aqhm01: + ts: 1687160720 +lumi.gateway.aqhm02: + ts: 1687162682 +lumi.gateway.lmuk01: + ts: 1687164111 +lumi.gateway.mieu01: + ts: 1687163976 +lumi.gateway.mihk01: + ts: 1687163477 +lumi.gateway.mitw01: + ts: 1687160954 +lumi.gateway.v1: + ts: 1687162995 +lumi.gateway.v2: + ts: 1687163777 +lumi.gateway.v3: + ts: 1686895771 +lumi.light.aqcn02: + ts: 1620727535 +lumi.light.cwopcn01: + ts: 1605855768 +lumi.light.cwopcn02: + ts: 1605855809 +lumi.light.cwopcn03: + ts: 1605855836 +lumi.lock.acn02: + ts: 1623928631 +lumi.lock.acn03: + ts: 1614752574 +lumi.lock.bacn01: + ts: 1614741699 +lumi.lock.bmcn02: + ts: 1637292825 +lumi.lock.bmcn03: + ts: 1634546176 +lumi.lock.bmcn04: + ts: 1636451160 +lumi.lock.bmcn05: + ts: 1636454200 +lumi.lock.bzacn1: + ts: 1614741727 +lumi.lock.bzacn2: + ts: 1614741815 +lumi.lock.eicn02: + ts: 1639976382 +lumi.lock.mcn007: + ts: 1650446757 +lumi.lock.mcn01: + ts: 1679881881 +lumi.lock.wbmcn1: + ts: 1619422072 +lumi.motion.bmgl01: + ts: 1639983139 +lumi.plug.v1: + ts: 1653299040 +lumi.relay.c2acn01: + ts: 1609310261 +lumi.remote.b186acn01: + ts: 1614154507 +lumi.remote.b186acn02: + ts: 1607395626 +lumi.remote.b1acn01: + ts: 1608794798 +lumi.remote.b286acn01: + ts: 1607397501 +lumi.remote.b286acn02: + ts: 1608794723 +lumi.remote.b286opcn01: + ts: 1614154602 +lumi.remote.b486opcn01: + ts: 1614154660 +lumi.remote.b686opcn01: + ts: 1614154713 +lumi.sensor_86sw1.v1: + ts: 1609311038 +lumi.sensor_86sw2.v1: + ts: 1608795035 +lumi.sensor_ht.v1: + ts: 1621239877 +lumi.sensor_magnet.aq2: + ts: 1641112867 +lumi.sensor_magnet.v2: + ts: 1641113779 +lumi.sensor_motion.aq2: + ts: 1676433994 +lumi.sensor_motion.v2: + ts: 1672818550 +lumi.sensor_natgas.v1: + ts: 1635762582 +lumi.sensor_smoke.mcn02: + ts: 1634635296 +lumi.sensor_smoke.v1: + ts: 1634809938 +lumi.sensor_switch.aq2: + ts: 1615256430 +lumi.sensor_switch.aq3: + ts: 1607399487 +lumi.sensor_switch.v2: + ts: 1609310683 +lumi.sensor_wleak.aq1: + ts: 1614669352 +lumi.switch.b1lacn02: + ts: 1653297814 +lumi.switch.b1nacn02: + ts: 1653297756 +lumi.switch.b2lacn02: + ts: 1653296711 +lumi.switch.b2nacn02: + ts: 1655201416 +lumi.switch.l3acn3: + ts: 1653296585 +lumi.switch.n3acn3: + ts: 1653294817 +lumi.vibration.aq1: + ts: 1614156721 +lumi.weather.v1: + ts: 1621239934 +madv.alarm.winlock1: + ts: 1611215780 +madv.cateye.dlowl: + ts: 1632714747 +madv.cateye.dlowlplus: + ts: 1615876742 +madv.cateye.dlowlse: + ts: 1607409634 +madv.cateye.dlowlse2: + ts: 1615876830 +madv.cateye.miowl: + ts: 1632714912 +madv.cateye.miowlv2: + ts: 1614152626 +madv.cateye.miowlv2l: + ts: 1615450328 +miaomiaoce.clock.ht02: + ts: 1620728504 +miaomiaoce.sensor_ht.h1: + ts: 1623929417 +miaomiaoce.sensor_ht.t1: + ts: 1616057242 +miaomiaoce.sensor_ht.t2: + ts: 1636603553 +miir.aircondition.ir01: + ts: 1531108800 +miir.aircondition.ir02: + ts: 1531108800 +miir.fan.ir01: + ts: 1531108800 +miir.light.ir01: + ts: 1531108800 +miir.projector.ir01: + ts: 1531108800 +miir.stb.ir01: + ts: 1531108800 +miir.tv.hir01: + ts: 1531108800 +miir.tv.ir01: + ts: 1531108800 +miir.tvbox.ir01: + ts: 1531108800 +mijia.camera.v1: + ts: 1531108800 +mijia.camera.v3: + ts: 1531108800 +minij.washer.v1: + ts: 1611818798 +minij.washer.v10: + ts: 1608792100 +minij.washer.v11: + ts: 1608792159 +minij.washer.v12: + ts: 1614656828 +minij.washer.v14: + ts: 1608792176 +minij.washer.v15: + ts: 1607410326 +minij.washer.v5: + ts: 1622792196 +minij.washer.v8: + ts: 1615777868 +miot.light.plato2: + ts: 1685518142 +miot.light.plato3: + ts: 1675941846 +miot.light.plato4: + ts: 1675941712 +mmgg.feeder.petfeeder: + ts: 1646394400 +mmgg.feeder.snack: + ts: 1607503182 +moyu.washer.s1hm: + ts: 1624620888 +mrbond.airer.m1pro: + ts: 1646393746 +mrbond.airer.m1s: + ts: 1646393874 +msj.f_washer.m1: + ts: 1614914340 +mxiang.cateye.mdb10: + ts: 1616140362 +mxiang.cateye.xmcatt1: + ts: 1616140207 +nwt.derh.wdh318efw1: + ts: 1611822375 +opple.light.bydceiling: + ts: 1608187619 +opple.light.fanlight: + ts: 1608793315 +opple.remote.5pb111: + ts: 1627453753 +opple.remote.5pb112: + ts: 1627453840 +opple.remote.5pb113: + ts: 1636599905 +ows.towel_w.mj1x0: + ts: 1610604939 +philips.light.bceiling1: + ts: 1642048160 +philips.light.bceiling2: + ts: 1642048073 +philips.light.bulb: + ts: 1620814142 +philips.light.candle: + ts: 1620814078 +philips.light.candle2: + ts: 1620814121 +philips.light.cbulb: + ts: 1639039185 +philips.light.ceiling: + ts: 1646394746 +philips.light.downlight: + ts: 1620814088 +philips.light.lnblight1: + ts: 1605857128 +philips.light.lnblight2: + ts: 1623902902 +philips.light.lnlrlight: + ts: 1621845517 +philips.light.lrceiling: + ts: 1642047751 +philips.light.mono1: + ts: 1608790977 +philips.light.moonlight: + ts: 1642582053 +philips.light.nlight: + ts: 1614147878 +philips.light.rwread: + ts: 1603352187 +philips.light.sread1: + ts: 1620814093 +philips.light.sread2: + ts: 1615259714 +philips.light.zyceiling: + ts: 1637228869 +philips.light.zysread: + ts: 1615970237 +philips.light.zystrip: + ts: 1605166337 +phnix.waterheater.sf: + ts: 1616050758 +pwzn.relay.apple: + ts: 1611217196 +pwzn.relay.banana: + ts: 1646647255 +qike.bhf_light.qk201801: + ts: 1608174909 +qmi.powerstrip.v1: + ts: 1621240280 +roborock.sweeper.s5v2: + ts: 1531108800 +roborock.vacuum.a01: + ts: 1685425888 +roborock.vacuum.a08: + ts: 1626231977 +roborock.vacuum.a09: + ts: 1611048152 +roborock.vacuum.a11: + ts: 1615360022 +roborock.vacuum.c1: + ts: 1531108800 +roborock.vacuum.e2: + ts: 1531108800 +roborock.vacuum.m1s: + ts: 1531108800 +roborock.vacuum.p5: + ts: 1611048094 +roborock.vacuum.s5: + ts: 1531108800 +roborock.vacuum.t4: + ts: 1615449261 +roborock.vacuum.t6: + ts: 1619423841 +rockrobo.vacuum.v1: + ts: 1531108800 +roome.bhf_light.yf6002: + ts: 1531108800 +rotai.massage.rt5728: + ts: 1610607000 +rotai.massage.rt5850: + ts: 1611816888 +rotai.massage.rt5850s: + ts: 1616727205 +rotai.massage.rt5863: + ts: 1611827937 +rotai.massage.rt5870: + ts: 1632376570 +scishare.coffee.s1102: + ts: 1611824402 +shuii.humidifier.jsq002: + ts: 1606376290 +skyrc.pet_waterer.fre1: + ts: 1608186812 +smith.waterheater.cxea1: + ts: 1611826349 +smith.waterheater.cxeb1: + ts: 1611826388 +smith.waterpuri.jnt600: + ts: 1531108800 +soocare.toothbrush.m1s: + ts: 1610611310 +soocare.toothbrush.t501: + ts: 1672192586 +sxds.pillow.pillow02: + ts: 1611222235 +syniot.curtain.syc1: + ts: 1608794071 +tinymu.toilet.ailid: + ts: 1615292165 +tinymu.toiletlid.v1: + ts: 1608791137 +tokit.cooker.press1: + ts: 1614842943 +tokit.cooker.tk20l01: + ts: 1646646903 +tokit.cooker.tk4001: + ts: 1639651673 +tokit.ihcooker.tkpro1: + ts: 1624533824 +tokit.ihcooker.tkv1: + ts: 1614667669 +tokit.oven.tk12l01: + ts: 1616729526 +tokit.oven.tk32pro1: + ts: 1617002408 +tokit.pre_cooker.tkih1: + ts: 1607410832 +viomi.aircondition.v10: + ts: 1606375041 +viomi.aircondition.v21: + ts: 1610608182 +viomi.aircondition.v22: + ts: 1610608198 +viomi.aircondition.v23: + ts: 1610608214 +viomi.aircondition.v24: + ts: 1610608242 +viomi.aircondition.v25: + ts: 1610608276 +viomi.aircondition.v26: + ts: 1609924120 +viomi.aircondition.v6: + ts: 1608188576 +viomi.aircondition.v7: + ts: 1608794437 +viomi.aircondition.v8: + ts: 1606376969 +viomi.aircondition.v9: + ts: 1608794507 +viomi.bhf_light.v1: + ts: 1614308454 +viomi.cooker.v1: + ts: 1607410870 +viomi.cooker.v2: + ts: 1607410911 +viomi.curtain.v1: + ts: 1658732587 +viomi.dishwasher.m01: + ts: 1610605899 +viomi.dishwasher.m02: + ts: 1610605964 +viomi.dishwasher.v01: + ts: 1614307805 +viomi.dishwasher.v03: + ts: 1614308206 +viomi.dishwasher.v05: + ts: 1610606831 +viomi.fridge.m1: + ts: 1614667789 +viomi.fridge.p1: + ts: 1614655704 +viomi.fridge.u1: + ts: 1614667927 +viomi.fridge.u12: + ts: 1614666058 +viomi.fridge.u13: + ts: 1614667152 +viomi.fridge.u15: + ts: 1607505693 +viomi.fridge.u18: + ts: 1614655755 +viomi.fridge.u2: + ts: 1531108800 +viomi.fridge.u24: + ts: 1614667214 +viomi.fridge.u4: + ts: 1614667295 +viomi.fridge.u6: + ts: 1614667319 +viomi.fridge.u7: + ts: 1614667341 +viomi.fridge.u8: + ts: 1624589504 +viomi.fridge.v3: + ts: 1614667699 +viomi.fridge.w1: + ts: 1607505903 +viomi.fridge.w2: + ts: 1614655838 +viomi.fridge.x11: + ts: 1614655870 +viomi.fridge.x12: + ts: 1614656914 +viomi.fridge.x4: + ts: 1614223422 +viomi.fridge.x7: + ts: 1637305932 +viomi.health_pot.v1: + ts: 1607502489 +viomi.hood.a10: + ts: 1611823231 +viomi.hood.a9: + ts: 1611823172 +viomi.hood.c1: + ts: 1611220032 +viomi.hood.c2: + ts: 1611823145 +viomi.hood.h1: + ts: 1610612690 +viomi.hood.h3: + ts: 1611823101 +viomi.hood.h4: + ts: 1611823078 +viomi.hood.v1: + ts: 1684390912 +viomi.i_stove.v1: + ts: 1611825720 +viomi.i_stove.v3: + ts: 1606372593 +viomi.juicer.v1: + ts: 1619688553 +viomi.juicer.v2: + ts: 1607504511 +viomi.lock.lbt14a: + ts: 1617940506 +viomi.lock.lbt41e: + ts: 1633750723 +viomi.lock.lbt48a: + ts: 1648788518 +viomi.lock.lbt51a: + ts: 1648536993 +viomi.lock.link1: + ts: 1634546007 +viomi.lock.link2: + ts: 1614740735 +viomi.lock.link2p: + ts: 1626166712 +viomi.lock.link2v: + ts: 1626166615 +viomi.lock.link3: + ts: 1639967286 +viomi.lock.link4s: + ts: 1681980137 +viomi.oven.so1: + ts: 1621243328 +viomi.oven.so2: + ts: 1611816582 +viomi.steriliser.v1: + ts: 1607503139 +viomi.vacuum.v10: + ts: 1619171223 +viomi.vacuum.v3: + ts: 1619171356 +viomi.vacuum.v31: + ts: 1624348346 +viomi.vacuum.v6: + ts: 1620720046 +viomi.vacuum.v7: + ts: 1618969602 +viomi.vacuum.v9: + ts: 1626232015 +viomi.washer.s1: + ts: 1616644328 +viomi.washer.u1: + ts: 1648122511 +viomi.washer.u2: + ts: 1632886871 +viomi.washer.u3: + ts: 1616644429 +viomi.washer.u4: + ts: 1616644467 +viomi.washer.u5: + ts: 1616647921 +viomi.washer.v10: + ts: 1616647971 +viomi.washer.v11: + ts: 1616644507 +viomi.washer.v4: + ts: 1616644547 +viomi.washer.v5: + ts: 1616407442 +viomi.washer.v6: + ts: 1616644619 +viomi.washer.v7: + ts: 1616644253 +viomi.washer.v8: + ts: 1616644309 +viomi.waterheater.e1: + ts: 1615343927 +viomi.waterheater.e3: + ts: 1615344258 +viomi.waterheater.e4: + ts: 1615345547 +viomi.waterheater.e7: + ts: 1604589755 +viomi.waterheater.e8: + ts: 1606982993 +viomi.waterheater.u1: + ts: 1616648390 +viomi.waterheater.u10: + ts: 1606984271 +viomi.waterheater.u11: + ts: 1606984299 +viomi.waterheater.u12: + ts: 1606376892 +viomi.waterheater.u15: + ts: 1646394494 +viomi.waterheater.u16: + ts: 1637304955 +viomi.waterheater.u3: + ts: 1620811497 +viomi.waterheater.u4: + ts: 1615864332 +viomi.waterheater.u6: + ts: 1615442495 +viomi.waterheater.u7: + ts: 1605857988 +viomi.waterheater.u8: + ts: 1615864849 +xiaomi.aircondition.ma1: + ts: 1721628903 +xiaomi.aircondition.ma2: + ts: 1721181139 +xiaomi.aircondition.ma4: + ts: 1726230966 +xiaomi.aircondition.ma5: + ts: 1721629118 +xiaomi.aircondition.ma6: + ts: 1721629272 +xiaomi.aircondition.ma9: + ts: 1721629362 +xiaomi.wifispeaker.l04m: + ts: 1658817956 +xiaomi.wifispeaker.l06a: + ts: 1672731009 +xiaomi.wifispeaker.l09a: + ts: 1626336048 +xiaomi.wifispeaker.l7a: + ts: 1637306490 +xiaomi.wifispeaker.lx01: + ts: 1637306716 +xiaomi.wifispeaker.lx04: + ts: 1669695484 +xiaomi.wifispeaker.lx05: + ts: 1672299502 +xiaomi.wifispeaker.lx06: + ts: 1672299546 +xiaomi.wifispeaker.lx5a: + ts: 1672299577 +xiaomi.wifispeaker.s12: + ts: 1672299594 +xiaomi.wifispeaker.x08a: + ts: 1672818945 +xiaomi.wifispeaker.x08c: + ts: 1658819390 +xiaovv.camera.lamp: + ts: 1531108800 +xiaovv.camera.ptz: + ts: 1531108800 +xiaovv.camera.xva3: + ts: 1531108800 +xiaovv.camera.xvb4: + ts: 1531108800 +xiaovv.camera.xvd5: + ts: 1531108800 +xiaovv.camera.xvsnowman: + ts: 1531108800 +xjx.toilet.pro: + ts: 1615965466 +xjx.toilet.pure: + ts: 1615969114 +xjx.toilet.relax: + ts: 1615968257 +xjx.toilet.zero: + ts: 1618302169 +ydhome.cateye.pr1: + ts: 1615360329 +ydhome.lock.c1p: + ts: 1614740027 +ydhome.lock.m2p: + ts: 1620728837 +ydhome.lock.m2silver: + ts: 1614743037 +ydzl.waterpuri.t1: + ts: 1609926143 +yeelink.bhf_light.v1: + ts: 1608790026 +yeelink.bhf_light.v2: + ts: 1608790085 +yeelink.bhf_light.v3: + ts: 1608790102 +yeelink.bhf_light.v5: + ts: 1601292562 +yeelink.light.bslamp1: + ts: 1703120679 +yeelink.light.bslamp2: + ts: 1703120782 +yeelink.light.bslamp3: + ts: 1646394180 +yeelink.light.ceil27: + ts: 1646394323 +yeelink.light.ceiling1: + ts: 1626343431 +yeelink.light.ceiling10: + ts: 1646393927 +yeelink.light.ceiling11: + ts: 1626341443 +yeelink.light.ceiling12: + ts: 1646122053 +yeelink.light.ceiling13: + ts: 1626341533 +yeelink.light.ceiling14: + ts: 1626341941 +yeelink.light.ceiling15: + ts: 1626342080 +yeelink.light.ceiling16: + ts: 1626342123 +yeelink.light.ceiling17: + ts: 1626342230 +yeelink.light.ceiling18: + ts: 1626342296 +yeelink.light.ceiling19: + ts: 1626342431 +yeelink.light.ceiling2: + ts: 1637308139 +yeelink.light.ceiling20: + ts: 1626339402 +yeelink.light.ceiling21: + ts: 1703121290 +yeelink.light.ceiling22: + ts: 1703121209 +yeelink.light.ceiling23: + ts: 1703120912 +yeelink.light.ceiling24: + ts: 1626343504 +yeelink.light.ceiling3: + ts: 1626343459 +yeelink.light.ceiling4: + ts: 1646393658 +yeelink.light.ceiling5: + ts: 1626342461 +yeelink.light.ceiling6: + ts: 1626343314 +yeelink.light.ceiling7: + ts: 1626343090 +yeelink.light.ceiling8: + ts: 1626343130 +yeelink.light.ceiling9: + ts: 1626343286 +yeelink.light.color1: + ts: 1626343469 +yeelink.light.color2: + ts: 1626343174 +yeelink.light.color3: + ts: 1626166445 +yeelink.light.color4: + ts: 1626343343 +yeelink.light.color5: + ts: 1626227410 +yeelink.light.color6: + ts: 1637309445 +yeelink.light.color7: + ts: 1626227373 +yeelink.light.color8: + ts: 1626343365 +yeelink.light.ct2: + ts: 1626343390 +yeelink.light.lamp1: + ts: 1626342474 +yeelink.light.lamp10: + ts: 1646122763 +yeelink.light.lamp2: + ts: 1638589912 +yeelink.light.lamp3: + ts: 1626343245 +yeelink.light.lamp4: + ts: 1629022996 +yeelink.light.lamp5: + ts: 1626343399 +yeelink.light.lamp7: + ts: 1626418317 +yeelink.light.lamp9: + ts: 1626343409 +yeelink.light.mono1: + ts: 1626343418 +yeelink.light.mono4: + ts: 1626343373 +yeelink.light.mono5: + ts: 1626343352 +yeelink.light.nl1: + ts: 1639479487 +yeelink.light.panel1: + ts: 1626343379 +yeelink.light.panel3: + ts: 1626343334 +yeelink.light.strip1: + ts: 1626343486 +yeelink.light.strip2: + ts: 1732605062 +yeelink.light.strip4: + ts: 1626342354 +yeelink.light.strip6: + ts: 1726730787 +yeelink.mirror.bm1: + ts: 1607504924 +yeelink.remote.remote: + ts: 1608186464 +yeelink.ven_fan.vf1: + ts: 1621237766 +yeelink.wifispeaker.v1: + ts: 1611818727 +yilai.light.ceiling1: + ts: 1603354689 +yilai.light.ceiling2: + ts: 1623911828 +yilai.light.ceiling3: + ts: 1606986226 +yuemee.airmonitor.mhfd1: + ts: 1619608729 +yunlu.door.sd2101: + ts: 1656661489 +yunlu.door.sd2103: + ts: 1657762233 +yunlu.door.sd2104: + ts: 1658317727 +yunmi.kettle.r1: + ts: 1614648943 +yunmi.kettle.r2: + ts: 1606372087 +yunmi.kettle.r3: + ts: 1637309534 +yunmi.plmachine.mg2: + ts: 1611833658 +yunmi.waterpuri.c5: + ts: 1604588322 +yunmi.waterpuri.lx11: + ts: 1604588450 +yunmi.waterpuri.lx12: + ts: 1722239438 +yunmi.waterpuri.lx2: + ts: 1614155130 +yunmi.waterpuri.lx3: + ts: 1606371237 +yunmi.waterpuri.lx4: + ts: 1606978913 +yunmi.waterpuri.lx5: + ts: 1603963118 +yunmi.waterpuri.lx6: + ts: 1606371311 +yunmi.waterpuri.lx7: + ts: 1603963241 +yunmi.waterpuri.lx8: + ts: 1603963353 +yunmi.waterpuri.lx9: + ts: 1607505784 +yunmi.waterpuri.s3: + ts: 1614303228 +yunmi.waterpuri.s4: + ts: 1611221280 +yunmi.waterpuri.s5: + ts: 1607501816 +yunmi.waterpuri.x2: + ts: 1603963460 +yunmi.waterpuri.x7: + ts: 1603963565 +yunmi.waterpurifier.v2: + ts: 1632377061 +yunmi.waterpurifier.v3: + ts: 1611221428 +yyunyi.wopener.yypy24: + ts: 1616741966 +zdeer.ajh.a8: + ts: 1531108800 +zdeer.ajh.a9: + ts: 1531108800 +zdeer.ajh.zda10: + ts: 1531108800 +zdeer.ajh.zda9: + ts: 1531108800 +zdeer.ajh.zjy: + ts: 1531108800 +zhimi.aircondition.ma1: + ts: 1615185265 +zhimi.aircondition.ma3: + ts: 1615185279 +zhimi.aircondition.ma4: + ts: 1626334057 +zhimi.aircondition.v1: + ts: 1610610931 +zhimi.aircondition.va1: + ts: 1609924720 +zhimi.aircondition.za1: + ts: 1626334343 +zhimi.aircondition.za2: + ts: 1626334315 +zhimi.airfresh.va2: + ts: 1690860366 +zhimi.airfresh.va4: + ts: 1690860327 +zhimi.airmonitor.v1: + ts: 1621243516 +zhimi.airpurifier.m1: + ts: 1636711231 +zhimi.airpurifier.m2: + ts: 1636711316 +zhimi.airpurifier.ma2: + ts: 1636962519 +zhimi.airpurifier.mb1: + ts: 1604588729 +zhimi.airpurifier.mc1: + ts: 1644487928 +zhimi.airpurifier.sa2: + ts: 1635820002 +zhimi.airpurifier.v1: + ts: 1635855633 +zhimi.airpurifier.v3: + ts: 1676339933 +zhimi.airpurifier.v6: + ts: 1636978652 +zhimi.airpurifier.v7: + ts: 1605856617 +zhimi.airpurifier.v8: + ts: 1626168185 +zhimi.fan.sa1: + ts: 1700644763 +zhimi.fan.v2: + ts: 1615975066 +zhimi.fan.v3: + ts: 1689041686 +zhimi.fan.za1: + ts: 1604590500 +zhimi.fan.za3: + ts: 1689040855 +zhimi.fan.za4: + ts: 1689040869 +zhimi.heater.ma1: + ts: 1645683725 +zhimi.heater.za1: + ts: 1645683820 +zhimi.humidifier.ca1: + ts: 1636099783 +zhimi.humidifier.v1: + ts: 1639639102 +zhimi.lock.da1: + ts: 1614741765 +zhimi.lock.da2: + ts: 1614741779 +zhimi.toilet.sa1: + ts: 1608186583 +zhimi.toilet.va1: + ts: 1607503081 +zimi.clock.myk01: + ts: 1531108800 +zimi.mosq.v1: + ts: 1620728957 +zimi.powerstrip.v2: + ts: 1620812714 diff --git a/custom_components/xiaomi_home/miot/miot_lan.py b/custom_components/xiaomi_home/miot/miot_lan.py index 525be2f..07aadbc 100644 --- a/custom_components/xiaomi_home/miot/miot_lan.py +++ b/custom_components/xiaomi_home/miot/miot_lan.py @@ -71,7 +71,8 @@ from .miot_ev import MIoTEventLoop, TimeoutHandle from .miot_network import InterfaceStatus, MIoTNetwork, NetworkInfo from .miot_mdns import MipsService, MipsServiceState -from .common import randomize_int, MIoTMatcher +from .common import ( + randomize_int, load_yaml_file, gen_absolute_path, MIoTMatcher) _LOGGER = logging.getLogger(__name__) @@ -175,7 +176,7 @@ class MIoTLanDevice: OT_HEADER_LEN: int = 32 NETWORK_UNSTABLE_CNT_TH: int = 10 NETWORK_UNSTABLE_TIME_TH: int = 120000 - NETWORK_UNSTABLE_RESUME_TH: int = 300 + NETWORK_UNSTABLE_RESUME_TH: int = 300000 FAST_PING_INTERVAL: int = 5000 CONSTRUCT_STATE_PENDING: int = 15000 KA_INTERVAL_MIN = 10000 @@ -472,6 +473,8 @@ class MIoTLan: OT_PROBE_INTERVAL_MIN: int = 5000 OT_PROBE_INTERVAL_MAX: int = 45000 + PROFILE_MODELS_FILE: str = 'lan/profile_models.yaml' + _main_loop: asyncio.AbstractEventLoop _net_ifs: set[str] _network: MIoTNetwork @@ -502,6 +505,8 @@ class MIoTLan: _lan_state_sub_map: dict[str, Callable[[bool], asyncio.Future]] _lan_ctrl_vote_map: dict[str, bool] + _profile_models: dict[str, dict] + _init_done: bool def __init__( @@ -597,6 +602,12 @@ async def init_async(self) -> None: if self._net_ifs.isdisjoint(self._available_net_ifs): _LOGGER.info('no valid net_ifs') return + try: + self._profile_models = load_yaml_file( + yaml_file=gen_absolute_path(self.PROFILE_MODELS_FILE)) + except Exception as err: # pylint: disable=broad-exception-caught + _LOGGER.error('load profile models error, %s', err) + self._profile_models = {} self._mev = MIoTEventLoop() self._queue = queue.Queue() self._cmd_event_fd = os.eventfd(0, os.O_NONBLOCK) @@ -620,6 +631,7 @@ async def deinit_async(self) -> None: self.__lan_send_cmd(MIoTLanCmdType.DEINIT, None) self._thread.join() + self._profile_models = {} self._lan_devices = {} self._broadcast_socks = {} self._local_port = None @@ -1032,6 +1044,19 @@ def __cmd_read_handler(self, ctx: any) -> None: elif mips_cmd.type_ == MIoTLanCmdType.DEVICE_UPDATE: devices: dict[str, dict] = mips_cmd.data for did, info in devices.items(): + # did MUST be digit(UINT64) + if not did.isdigit(): + _LOGGER.info('invalid did, %s', did) + continue + if ( + 'model' not in info + or info['model'] in self._profile_models): + # Do not support the local control of + # Profile device for the time being + _LOGGER.info( + 'model not support local ctrl, %s, %s', + did, info.get('model')) + continue if did not in self._lan_devices: if 'token' not in info: _LOGGER.error( diff --git a/test/conftest.py b/test/conftest.py index e6583d9..9263402 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -43,6 +43,13 @@ def load_py_file(): dst=path.join(TEST_FILES_PATH, 'specs'), dirs_exist_ok=True) print('loaded spec test folder, specs') + # Copy lan files to test folder + shutil.copytree( + src=path.join( + TEST_ROOT_PATH, '../custom_components/xiaomi_home/miot/lan'), + dst=path.join(TEST_FILES_PATH, 'lan'), + dirs_exist_ok=True) + print('loaded lan test folder, lan') # Copy i18n files to test folder shutil.copytree( src=path.join( diff --git a/test/test_lan.py b/test/test_lan.py index e86a8be..4f96725 100755 --- a/test/test_lan.py +++ b/test/test_lan.py @@ -8,8 +8,37 @@ # pylint: disable=import-outside-toplevel, unused-argument +@pytest.mark.parametrize('test_devices', [{ + # specv2 model + '123456': { + 'token': '11223344556677d9a03d43936fc384205', + 'model': 'xiaomi.gateway.hub1' + }, + # profile model + '123457': { + 'token': '11223344556677d9a03d43936fc384205', + 'model': 'yeelink.light.lamp9' + }, + '123458': { + 'token': '11223344556677d9a03d43936fc384205', + 'model': 'zhimi.heater.ma1' + }, + # Non -digital did + 'group.123456': { + 'token': '11223344556677d9a03d43936fc384205', + 'model': 'mijia.light.group3' + }, + 'proxy.123456.1': { + 'token': '11223344556677d9a03d43936fc384205', + 'model': 'xiaomi.light.p1' + }, + 'miwifi_123456': { + 'token': '11223344556677d9a03d43936fc384205', + 'model': 'xiaomi.light.p1' + } +}]) @pytest.mark.asyncio -async def test_lan_async(): +async def test_lan_async(test_devices: dict): """ Use the central hub gateway as a test equipment, and through the local area network control central hub gateway indicator light switch. Please replace @@ -21,10 +50,13 @@ async def test_lan_async(): from miot.miot_lan import MIoTLan from miot.miot_mdns import MipsService - test_did = '' - test_token = '' + # Your central hub gateway did + test_did = '111111' + # Your central hub gateway did + test_token = '11223344556677d9a03d43936fc384205' test_model = 'xiaomi.gateway.hub1' - test_if_names = [''] + # Your computer interface list, such as enp3s0, wlp5s0 + test_if_names = ['enp3s0', 'wlp5s0'] # Check test params assert int(test_did) > 0 @@ -76,7 +108,8 @@ async def lan_state_change(state: bool): test_did: { 'token': test_token, 'model': test_model - } + }, + **test_devices }) # Test sub device state diff --git a/tools/common.py b/tools/common.py new file mode 100644 index 0000000..8dbb03a --- /dev/null +++ b/tools/common.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +"""Common functions.""" +import json +import yaml +from urllib.parse import urlencode +from urllib.request import Request, urlopen + + +def load_yaml_file(yaml_file: str) -> dict: + with open(yaml_file, 'r', encoding='utf-8') as file: + return yaml.safe_load(file) + + +def save_yaml_file(yaml_file: str, data: dict) -> None: + with open(yaml_file, 'w', encoding='utf-8') as file: + yaml.safe_dump( + data=data, stream=file, allow_unicode=True) + + +def load_json_file(json_file: str) -> dict: + with open(json_file, 'r', encoding='utf-8') as file: + return json.load(file) + + +def save_json_file(json_file: str, data: dict) -> None: + with open(json_file, 'w', encoding='utf-8') as file: + json.dump(data, file, ensure_ascii=False, indent=4) + + +def http_get( + url: str, params: dict = None, headers: dict = None +) -> dict: + if params: + encoded_params = urlencode(params) + full_url = f'{url}?{encoded_params}' + else: + full_url = url + request = Request(full_url, method='GET', headers=headers or {}) + content: bytes = None + with urlopen(request) as response: + content = response.read() + return ( + json.loads(str(content, 'utf-8')) + if content is not None else None) diff --git a/tools/update_lan_rule.py b/tools/update_lan_rule.py new file mode 100644 index 0000000..9f4d4fa --- /dev/null +++ b/tools/update_lan_rule.py @@ -0,0 +1,80 @@ +""" Update LAN rule.""" +# -*- coding: utf-8 -*- +# pylint: disable=relative-beyond-top-level +from os import path +from common import ( + http_get, + load_yaml_file, + save_yaml_file) + + +ROOT_PATH: str = path.dirname(path.abspath(__file__)) +LAN_PROFILE_MODELS_FILE: str = path.join( + ROOT_PATH, + '../custom_components/xiaomi_home/miot/lan/profile_models.yaml') + + +SPECIAL_MODELS: list[str] = [ + # model2class-v2 + 'chuangmi.camera.ipc007b', 'chuangmi.camera.ipc019b', + 'chuangmi.camera.ipc019e', 'chuangmi.camera.ipc020', + 'chuangmi.camera.v2', 'chuangmi.camera.v5', + 'chuangmi.camera.v6', 'chuangmi.camera.xiaobai', + 'chuangmi.radio.v1', 'chuangmi.radio.v2', + 'hith.foot_bath.q2', 'imou99.camera.tp2', + 'isa.camera.hl5', 'isa.camera.isc5', + 'jiqid.mistory.pro', 'jiqid.mistory.v1', + 'lumi.airrtc.tcpco2ecn01', 'lumi.airrtc.tcpecn02', + 'lumi.camera.gwagl01', 'miir.light.ir01', + 'miir.projector.ir01', 'miir.tv.hir01', + 'miir.tvbox.ir01', 'roome.bhf_light.yf6002', + 'smith.waterpuri.jnt600', 'viomi.fridge.u2', + 'xiaovv.camera.lamp', 'xiaovv.camera.ptz', + 'xiaovv.camera.xva3', 'xiaovv.camera.xvb4', + 'xiaovv.camera.xvsnowman', 'zdeer.ajh.a8', + 'zdeer.ajh.a9', 'zdeer.ajh.zda10', + 'zdeer.ajh.zda9', 'zdeer.ajh.zjy', 'zimi.clock.myk01', + # specialModels + 'chuangmi.camera.ipc004b', 'chuangmi.camera.ipc009', + 'chuangmi.camera.ipc010', 'chuangmi.camera.ipc013', + 'chuangmi.camera.ipc013d', 'chuangmi.camera.ipc016', + 'chuangmi.camera.ipc017', 'chuangmi.camera.ipc019', + 'chuangmi.camera.ipc021', 'chuangmi.camera.v3', + 'chuangmi.camera.v4', 'isa.camera.df3', + 'isa.camera.hlc6', 'lumi.acpartner.v1', + 'lumi.acpartner.v2', 'lumi.acpartner.v3', + 'lumi.airrtc.tcpecn01', 'lumi.camera.aq1', + 'miir.aircondition.ir01', 'miir.aircondition.ir02', + 'miir.fan.ir01', 'miir.stb.ir01', + 'miir.tv.ir01', 'mijia.camera.v1', + 'mijia.camera.v3', 'roborock.sweeper.s5v2', + 'roborock.vacuum.c1', 'roborock.vacuum.e2', + 'roborock.vacuum.m1s', 'roborock.vacuum.s5', + 'rockrobo.vacuum.v1', 'xiaovv.camera.xvd5'] + + +def update_profile_model(file_path: str): + profile_rules: dict = http_get( + url='https://miot-spec.org/instance/translate/models') + if not profile_rules and 'models' not in profile_rules and not isinstance( + profile_rules['models'], dict): + raise ValueError('Failed to get profile rule') + local_rules: dict = load_yaml_file( + yaml_file=file_path) or {} + for rule, ts in profile_rules['models'].items(): + if rule not in local_rules: + local_rules[rule] = {'ts': ts} + else: + local_rules[rule]['ts'] = ts + for mode in SPECIAL_MODELS: + if mode not in local_rules: + local_rules[mode] = {'ts': 1531108800} + else: + local_rules[mode]['ts'] = 1531108800 + local_rules = dict(sorted(local_rules.items())) + save_yaml_file( + yaml_file=file_path, data=local_rules) + + +update_profile_model(file_path=LAN_PROFILE_MODELS_FILE) +print('profile model list updated.')