tuya2ildevice 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tuya2ildevice-0.1.0/.gitignore +9 -0
- tuya2ildevice-0.1.0/LICENSE +21 -0
- tuya2ildevice-0.1.0/PKG-INFO +146 -0
- tuya2ildevice-0.1.0/README.md +127 -0
- tuya2ildevice-0.1.0/docs/analysis/PHASE1_SYNTHESIS.md +85 -0
- tuya2ildevice-0.1.0/docs/analysis/PHASE2_GAP_ANALYSIS.md +277 -0
- tuya2ildevice-0.1.0/docs/analysis/PHASE3_SPEC_REVIEW.md +296 -0
- tuya2ildevice-0.1.0/docs/analysis/PHASE4_GOLDEN.md +16 -0
- tuya2ildevice-0.1.0/docs/analysis/SDK_CONVERT_INVESTIGATION.md +121 -0
- tuya2ildevice-0.1.0/docs/analysis/SOURCES.txt +6 -0
- tuya2ildevice-0.1.0/docs/analysis/catalog/A_value_transform.md +208 -0
- tuya2ildevice-0.1.0/docs/analysis/catalog/B_quirks.md +157 -0
- tuya2ildevice-0.1.0/docs/analysis/catalog/C_light_climate_fan_humidifier.md +440 -0
- tuya2ildevice-0.1.0/docs/analysis/catalog/D_cover_vacuum_valve_siren_alarm.md +357 -0
- tuya2ildevice-0.1.0/docs/analysis/catalog/E_simple_platforms.md +473 -0
- tuya2ildevice-0.1.0/docs/analysis/catalog/F_core_crosscutting.md +256 -0
- tuya2ildevice-0.1.0/docs/engine-spec.md +441 -0
- tuya2ildevice-0.1.0/pyproject.toml +34 -0
- tuya2ildevice-0.1.0/scripts/gen_core_tables.py +131 -0
- tuya2ildevice-0.1.0/scripts/gen_host_units.py +16 -0
- tuya2ildevice-0.1.0/scripts/gen_quirks.py +58 -0
- tuya2ildevice-0.1.0/scripts/golden/README.md +38 -0
- tuya2ildevice-0.1.0/scripts/golden/ambr.py +79 -0
- tuya2ildevice-0.1.0/scripts/golden/build_golden.py +48 -0
- tuya2ildevice-0.1.0/scripts/golden/extract_actions.py +55 -0
- tuya2ildevice-0.1.0/scripts/golden/quirk_oracle.py +33 -0
- tuya2ildevice-0.1.0/scripts/golden/quirk_oracle_synthetic.py +18 -0
- tuya2ildevice-0.1.0/scripts/golden/snapshots.json +7907 -0
- tuya2ildevice-0.1.0/scripts/golden/synthetic_snapshots.json +272 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/__init__.py +18 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/assemble.py +397 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/checks.py +69 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/converters.py +139 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/driver.py +266 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/fallback.py +96 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/__init__.py +20 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/bridge.py +37 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/devices.py +87 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/memory.py +65 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/mqtt.py +103 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/runner.py +137 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/host/transport.py +27 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/io.py +96 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/mqtt.py +322 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/overrides.py +209 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/__init__.py +8 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/adapter.py +208 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/codecs.py +104 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/data/host_units.json +766 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/model.py +144 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/ops.py +71 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/platforms.py +1034 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/quirks/quirks.json +916 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/quirks.py +104 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/runtime.py +127 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/_enums.json +560 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/_units.json +208 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/alarm_control_panel.json +29 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/binary_sensor.json +591 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/button.json +69 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/camera.json +15 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/climate.json +57 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/cover.json +131 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/event.json +104 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/fan.json +35 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/humidifier.json +29 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/light.json +470 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/number.json +627 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/select.json +510 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/sensor.json +3796 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/siren.json +49 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/switch.json +1377 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/vacuum.json +19 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/tables/valve.json +87 -0
- tuya2ildevice-0.1.0/src/tuya2ildevice/tuya/units.py +42 -0
- tuya2ildevice-0.1.0/tests/chain/baseline.json +58 -0
- tuya2ildevice-0.1.0/tests/chain/conftest.py +11 -0
- tuya2ildevice-0.1.0/tests/chain/measure.py +45 -0
- tuya2ildevice-0.1.0/tests/chain/props.py +81 -0
- tuya2ildevice-0.1.0/tests/chain/test_counts.py +41 -0
- tuya2ildevice-0.1.0/tests/chain/test_props.py +45 -0
- tuya2ildevice-0.1.0/tests/conftest.py +6 -0
- tuya2ildevice-0.1.0/tests/golden/actions_golden.json +887 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/bh_dft4ebatvon3ha5s.json +80 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/bzyd_45idzfufidgee7ir.json +137 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/bzyd_ssimhf6r8kgwepfb.json +76 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/bzyd_tkqgkrutewrmbn9c.json +147 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cjkg_hmabvy81.json +283 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cjkg_uenof8jd.json +171 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ckmkzq_1yyqfw4djv9eii3q.json +59 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_3r8gc33pnqsxfe1g.json +122 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_669wsr2w4cvinbh4.json +138 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_cpbo62rn.json +100 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_ebt12ypvexnixvtf.json +57 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_g1cp07dsqnbdbbki.json +102 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_lfkr93x0ukp5gaia.json +138 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_n3xgr5pdmpinictg.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_qqdxfdht.json +65 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_qtemqjy7axczkkls.json +109 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_rD7uqAAgQOpSA2Rx.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cl_zah67ekd.json +60 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/clkg_nhyj64w2.json +93 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/clkg_wltqkykhni0papzj.json +114 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/clkg_xqvhthwkbmp3aghs.json +114 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/clkg_y7j64p60glp8qpx7.json +108 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/co2bj_yakol79dibtswovc.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/co2bj_yrr3eiyiacm31ski.json +285 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cobj_hcdy5zrq3ikzthws.json +59 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_b9oyi2yofflroq1g.json +134 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_biflejkeshx1sqig.json +130 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_eguoms25tkxtf5u8.json +88 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_ipmyy4nigpqcnd8q.json +40 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_ka2wfrdoogpvgzfi.json +127 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_qhxmvae667uap4zh.json +30 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_u0wirz487erb0eka.json +169 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_vmxuxszzjwp5smli.json +30 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cs_zibqa9dutqyaxym2.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cwjwq_agwu93lr.json +64 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cwwsq_lxfvx41gqdotrkgi.json +111 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cwwsq_wfkzyy0evslzsmoi.json +99 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cwysj_akln8rb04cav403q.json +73 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cwysj_z3rpyvznfcch99aa.json +130 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_0fHWRe8ULjtmnBNd.json +149 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_0g1fmqh6d5io7lcn.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_2iepauebcvo74ujc.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_2jxesipczks0kdct.json +86 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_37mnhia3pojleqfh.json +87 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_39sy2g68gsjwo2xv.json +155 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_4mbgrfotyNzMxDAv.json +87 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_6fa7odsufen374x2.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_79a7z01v3n35kytb.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_9ivirni8wemum6cw.json +87 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_AiHXxAyyn7eAkLQY.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_CHLZe9HQ6QIXujVN.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_EYfNTuTPZln9e4cn.json +87 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_ExGgQmjt0SHMdlDZ.json +57 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_HBRBzv1UVBVfF6SL.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_IGzCi97RpN2Lf9cu.json +149 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_PGEkBctAbtzKOZng.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_anwgf2xugjxpkfxb.json +116 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_cuhokdii7ojyw8k2.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_dhto3y4uachr1wll.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_dntgh2ngvshfxpsz.json +33 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_fbvia0apnlnattcy.json +101 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_fencxse0bnut96ig.json +100 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_gbtxrqfy9xcsakyp.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_gjnozsaz.json +133 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_guitoc9iylae4axs.json +217 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_hA2GsgMfTQFTz9JL.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_hj0a5c7ckzzexu8l.json +98 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_ik9sbig3mthx9hjz.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_ipabufmlmodje1ws.json +165 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_iqhidxhhmgxk5eja.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_jnbbxsb84gvvyfg5.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_jti3ce2hzvsposgj.json +215 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_mQUhiTg9kwydBFBd.json +87 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_n8iVBAPLFKAAAszH.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_nkb0fmtlfyqosnvk.json +98 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_nx8rv6jpe1tsnffk.json +116 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_piuensvr.json +33 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_qm0iq4nqnrlzh4qc.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_qxJSyTLEtX5WrzA9.json +87 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_raceucn29wk2yawe.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_sb6bwb1n8ma2c5q4.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_t0a4hwsf8anfsadp.json +116 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_tf6qp8t3hl9h7m94.json +86 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_tkn2s79mzedk6pwr.json +160 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_vrbpx6h7fsi5mujb.json +223 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_vxqn72kwtosoy4d3.json +98 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_w0qqde0g.json +133 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_wifvoilfrqeo6hvu.json +98 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_wrz6vzch8htux2zp.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_y4jnobxh.json +33 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_yncyws7tu1q4cpsz.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/cz_z6pht25s3p0gs26q.json +207 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dc_l3bpgg8ibsagon4x.json +147 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dd_gaobbrxqiblcng2p.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dgnbj_layxxij0sdbrfmrf.json +508 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_0gyaslysqfp4gfis.json +557 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_8szt7whdvwpmxglk.json +493 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_8ugheslg.json +57 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_8y0aquaa8v6tho8w.json +336 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_AqHUMdcbYzIq1Of4.json +508 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_amx1bgdrfab6jngb.json +333 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_bSXSSFArVKtc4DyC.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_baf9tt9lb8t5uc7z.json +75 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_c3nsqogqovapdpfj.json +348 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_d4g0fbsoaal841o6.json +375 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_dbou1ap4.json +390 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_djnozmdyqyriow8z.json +482 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_ekwolitfjhxn55js.json +557 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_fuupmcr2mb1odkja.json +336 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_h4aX2JkHZNByQ4AV.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_hp6orhaqm6as3jnv.json +508 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_hpc8ddyfv85haxa7.json +154 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_iayz2jmtlipjnxj7.json +527 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_idnfq7xbx8qewyoa.json +521 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_ilddqqih3tucdk68.json +75 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_j1bgp31cffutizub.json +432 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_k3okx0w3bsgmindp.json +921 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_kgaob37tz2muf3mi.json +548 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_lmnt3uyltk1xffrt.json +75 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_mki13ie507rlry4r.json +456 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_nbumqpv8vz61enji.json +557 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_nlxvjzy1hoeiqsg6.json +75 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_oe0cpnjg.json +224 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_oj4fqh3fo3obgu6a.json +830 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_p06rbu0a9jp37ixo.json +899 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_qoqolwtqzfuhgghq.json +477 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_riwp3k79.json +400 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_tgewj70aowigv8fz.json +140 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_tmsloaroqavbucgn.json +375 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_ufq2xwuzd4nb0qdr.json +333 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_vqwcnabamzrc2kab.json +530 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_xdvitmhhmgefaeuq.json +510 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_xokdfs6kh5ednakk.json +375 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_yfqmcabsid3gkd1y.json +379 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_zakhnlpdiu0ycdxn.json +75 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_zav1pa32pyxray78.json +320 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dj_zputiamzanuk6yky.json +411 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_0tnvg2xaisqdadcf.json +247 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_cnpkf4xdmd9v49iq.json +158 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_dikb3dp6.json +146 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_fygozcnralhwbauo.json +268 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_jdj6ccklup7btq3a.json +216 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_kxdr6su0c55p7bbo.json +135 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_r9kg2g1uhhyicycb.json +143 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dlq_z3jngbyubvwgfrcv.json +222 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/dr_pjvxl1wsyqxivsaf.json +185 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/fs_g0ewlb1vmwqljzji.json +132 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/fs_ibytpo6fpnugft1c.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/fsd_9ecs16c53uqskxw6.json +151 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ggq_7ytb3h8u.json +52 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/gyd_lgekqfxdabipm3tn.json +263 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/hcdd_expmpw4xxd0kkifb.json +91 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/hjjcy_9f8pjxsmaqnk2tzr.json +334 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/hps_2aaelwxk.json +184 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/hps_wqashyqo.json +41 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/hwsb_ircs2n82vgrozoew.json +34 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/infrared_ac_47peys.json +96 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/infrared_ac_qzktzhehinzsz2je.json +96 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/infrared_tv_47pew0.json +129 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/infrared_tv_lplun31mo1xaonwz.json +129 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/jsq_r492ifwk6f2ssptb.json +86 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/jtmspro_xqeob8h6.json +398 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kg_4nqs33emdwJxpQ8O.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kg_5ftkaulg.json +80 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kg_gbm9ata1zrzaez4a.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kj_CAjWAxBUZt7QZHfz.json +84 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kj_fsxtzzhujkrak2oy.json +104 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kj_s4uzibibgzdxzowo.json +115 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kj_yrzylxax1qspdgpp.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ks_j9fa8ahzac8uvlfl.json +105 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kt_5wnlzekkstwcdsvm.json +78 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kt_ibmmirhhq62mmf1g.json +110 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kt_vdadlnmsorlhw4td.json +78 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/kt_wxqdp6ecfkd78zzz.json +152 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ktkzq_urzivdhumrwfakie.json +74 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ldcg_9kbbfeho.json +45 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mal_gyitctrjj1kefxp2.json +224 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mc_oSQljE9YDqwCwTUA.json +35 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mcs_6ywsnauy.json +44 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mcs_7jIGJAymiH8OsFFb.json +41 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mcs_8yhypbo7.json +39 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mcs_hx5ztlztij4yxxvg.json +35 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mcs_oxslv1c9.json +39 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mcs_qxu3flpqjsc1kqu3.json +39 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/msp_3ddulzljdjjwkhoy.json +149 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/msp_5t7esmqqh92ssbe5.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/msp_mzuro9jgjs7uiryn.json +155 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mzj_jlapoy5liocmtdvd.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/mzj_qavcakohisj5adyh.json +117 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ntq_9mqdhwklpvnnvb7t.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pc_t2afic7i3v1bwhfp.json +42 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pc_trjopo1vdlt9q1tg.json +84 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pc_tsbguim4trl6fa7g.json +188 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pc_yku9wsimasckdt15.json +189 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pir_3amxzozho9xp4mkh.json +42 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pir_fcdjzz3s.json +46 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pir_j5jgnjvdaczeb6dc.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pir_o1l76njefmksbgkk.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/pir_wqz93nrdomectyoz.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qccdz_7bvgooyjhiua1yyq.json +103 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qccdz_dsmsam7xpb3ht7rl.json +157 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qn_5ls2jw49hpczwqng.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qt_TtXKwTMwiPpURWLJ.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qxj_fsea1lat3vuktbt6.json +410 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qxj_is2indt9nlth6esa.json +63 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/qxj_xbwbniyt6bgws9ia.json +265 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/rqbj_4iqe2hsfyd86kwwc.json +88 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/rs_d7woucobqi8ncacf.json +57 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sd_i6hyjg3af7doaswm.json +64 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sd_lr33znaodtyarrrz.json +474 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_1fcnd8xk.json +130 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_d4vpmigg.json +130 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_ed7frwissyqrejic.json +282 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_kcdiut0eqeni7b8n.json +132 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_nxquc5lb.json +130 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_o6dagifntoafakst.json +54 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sfkzq_rzklytdei8i8vo37.json +100 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sgbj_DYgId0sz6zWlmmYu.json +74 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sgbj_im2eqqhj72suwwko.json +92 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sgbj_ulv4nnue7gqp0rjk.json +67 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sj_rzeSU2h9uoklxEwq.json +41 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sj_tgvtvdoc.json +41 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sjz_ftbc8rp8ipksdfpv.json +143 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_6bmk1remyscwyx6i.json +229 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_csr2fqitalj5o0tq.json +127 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_drezasavompxpcgm.json +180 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_ehzbfjrau5lbph4o.json +160 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_knkaf1d0dytgyhix.json +289 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_nzauwyj3mcnjnf35.json +220 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_rjKXWRohlvOTyLBu.json +211 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_rudejjigkywujjvs.json +240 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/sp_sdd5f5f2dl5wydjf.json +381 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/swtz_3rzngbyy.json +116 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/szjcy_u5xgcpcngk3pfxb4.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_1aegphq4yfd50e6b.json +137 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_1ctrc5jx88mtdh9w.json +303 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_9htyiowaf5rtdhrv.json +137 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_cq1p0nt0a4rixnex.json +246 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_emb5khohohihmbxc.json +303 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_gdknjvdpiwoq6smx.json +253 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_nockvv2k39vbrxxk.json +225 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_p6sqiuesvhmhvv4f.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_pu8uhxhwcp3tgoz7.json +167 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_uoa3mayicscacseb.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tdq_x3o8epevyeo3z3oa.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tyndj_pyakuuoc.json +143 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/tzc1_5vlawhjm.json +210 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wfcon_b25mh8sxawsgndck.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wfcon_lieerjyy6l4ykjor.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wfcon_plp0gnfcacdeqk5o.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_2gowdgni.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_haclbl0qkqlf2qds.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_nwxr8qcu4seltoro.json +88 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_pkhw2vbphv4csrir.json +135 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_setmxeqgs63xwopm.json +68 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_tmwhss6ntjfc7prs.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wg2_v7owd9tzcaninc36.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_6kijc7nd.json +187 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_B0eP8qYAdpUo4yR9.json +53 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_IAYz2WK1th0cMLmL.json +93 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_aqoouq7x.json +100 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_ccpwojhalfxryigz.json +121 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_cpmgn2cf.json +85 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_fi6dne5tu4t1nm6j.json +186 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_gc1bxoq2hafxpa35.json +110 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_gogb05wrtredz3bs.json +195 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_t94pit6zjbask9qo.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_tfbhw0mg.json +109 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wk_y5obtqhuztqsf2mj.json +74 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wkcz_gc4b1mdw7kebtuyz.json +227 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wkf_9xfjixap.json +85 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wkf_p3dbf6qs.json +85 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wnykq_kzwdw5bpxlbs9h9g.json +40 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wnykq_npbbca46yiug8ysk.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wnykq_om518smspsaltzdi.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wnykq_rqhxdyusjrwxyff6.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wnykq_x0lyfgjuguuh1vof.json +22 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_g2y6z3p3ja2qhyav.json +155 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_iq4ygaai.json +45 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_iv7hudlj.json +168 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_krlcihrpzpc8olw9.json +66 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_lf36y5nwb8jkxwgg.json +66 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_qrztc3ev.json +210 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_s5l7qidyapl1rbrs.json +59 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_vlzqwckk.json +348 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_vtA4pDd6PLUZzXgZ.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_xflodz7oja0pndk3.json +428 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_xpxdr5q6vc8aztq0.json +59 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_xr3htd96.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdcg_yqiqbaldtr0i7mru.json +259 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wsdykq_ay30hrndaogxclh0.json +22 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wxkg_ja5osu5g.json +64 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wxkg_l8yaz4um5b3pwyvf.json +50 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/wxnbq_5l1ht8jygsyr1wn1.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/xdd_shx9mmadyyeaq88t.json +139 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/xfj_pjabraecffsfrmxz.json +75 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/xktyd_3djw12ln4xtvv8eq.json +175 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/xnyjcn_pb0tc75khaik8qbg.json +794 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ydkt_jevroj5aguwdbs2e.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ygsb_l6ax0u6jwbz82atk.json +63 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ykq_bngwdjsr.json +70 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywbj_arywmw6h6vesoz5t.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywbj_cjlutkuuvxnie17o.json +37 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywbj_gf9dejhmzffgdyfj.json +63 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywbj_kscbebaf3s1eogvt.json +51 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywbj_rccxox8p.json +68 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywcgq_h8lvyoahr6s6aybf.json +146 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/ywcgq_wtzwyhkev3b4ubns.json +139 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zjq_nkkl7uzv.json +21 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_4ggkyflayu1h1ho9.json +227 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_gqmmtjclqb7reg5p.json +22 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_iow5ux77dxy3yrpj.json +129 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_uqzhc4bx5zqwpg2m.json +74 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_v5jlnn5hwyffkhp3.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_z95s7p3z54xbsjnl.json +136 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zndb_ze8faryrxr0glqnn.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/znjdq_au6dqazvkxqnpaak.json +269 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/znnbq_0kllybtbzftaee7y.json +70 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/znnbq_6b3pbbuqbfabhfiq.json +56 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/znrb_8ln34bg8u4y6rdda.json +419 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/znrb_db81ge24jctwx8lo.json +172 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/znrb_gpzittzfnzhduquz.json +265 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zwjcy_gvygg3m8.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/core_fixtures/zwjcy_myd45weu.json +77 -0
- tuya2ildevice-0.1.0/tests/golden/fixtures.py +18 -0
- tuya2ildevice-0.1.0/tests/golden/golden.json +32909 -0
- tuya2ildevice-0.1.0/tests/golden/quirk_golden.json +960 -0
- tuya2ildevice-0.1.0/tests/golden/quirk_synthetic_golden.json +1132 -0
- tuya2ildevice-0.1.0/tests/helpers.py +33 -0
- tuya2ildevice-0.1.0/tests/test_adapter.py +88 -0
- tuya2ildevice-0.1.0/tests/test_delta.py +25 -0
- tuya2ildevice-0.1.0/tests/test_driver.py +312 -0
- tuya2ildevice-0.1.0/tests/test_golden.py +178 -0
- tuya2ildevice-0.1.0/tests/test_host.py +216 -0
- tuya2ildevice-0.1.0/tests/test_mqtt.py +139 -0
- tuya2ildevice-0.1.0/tests/test_platforms.py +30 -0
- tuya2ildevice-0.1.0/tests/test_quirks.py +87 -0
- tuya2ildevice-0.1.0/tests/test_vectors.py +74 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 3735943886
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: tuya2ildevice
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Sans-IO converter: Tuya (rustuya / rustuya-bridge) device + DPS packets <-> ildevice descriptor, values and commands
|
|
5
|
+
Project-URL: Repository, https://github.com/3735943886/tuya2ildevice
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Topic :: Home Automation
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Provides-Extra: host
|
|
12
|
+
Requires-Dist: paho-mqtt>=2.0; extra == 'host'
|
|
13
|
+
Provides-Extra: test
|
|
14
|
+
Requires-Dist: jsonschema; extra == 'test'
|
|
15
|
+
Requires-Dist: paho-mqtt>=2.0; extra == 'test'
|
|
16
|
+
Requires-Dist: pytest; extra == 'test'
|
|
17
|
+
Requires-Dist: pytest-asyncio; extra == 'test'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# tuya2ildevice
|
|
21
|
+
|
|
22
|
+
The one place that interprets Tuya. Sans-IO Python: takes a Tuya device as [rustuya](https://github.com/3735943886/rustuya) /
|
|
23
|
+
[rustuya-bridge](https://github.com/3735943886/rustuya-bridge) know it and produces an
|
|
24
|
+
[ildevice](https://github.com/3735943886/ildevice): descriptor, live values and events from dps packets, and dps for
|
|
25
|
+
ildevice commands. It opens no sockets and reads no clock. Other projects
|
|
26
|
+
([rustuya-homeassistant](https://github.com/3735943886/rustuya-homeassistant), ildevice hosts,
|
|
27
|
+
[rustuya-manager](https://github.com/3735943886/rustuya-manager)) import this instead of carrying their own Tuya knowledge.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
pip install tuya2ildevice # no dependencies; tuya2ildevice[host] adds paho-mqtt for `tuya2ildevice.host`, [test] for the tests
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from tuya2ildevice import TuyaDriver, Connected, Message, Command, descriptor_of
|
|
35
|
+
|
|
36
|
+
descriptor_of(device) # just the ildevice descriptor of a tuyadevices.json entry
|
|
37
|
+
d = TuyaDriver(device) # the state machine (il.md section 8)
|
|
38
|
+
d.handle(now, Connected()) # -> [Descriptor]
|
|
39
|
+
d.handle(now, Message("active", {"data": {"dps": {"1": True}}})) # -> [Value(...), Event(...)]
|
|
40
|
+
d.handle(now, Command("switch_1", "off")) # -> [SendMessage("set", {"dps": {"1": False}})] or [Reject(...)]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Packets and commands
|
|
44
|
+
|
|
45
|
+
- `Message(channel, json)`: `active` (device push: fires events, accumulates `add_ele`-style deltas) or `passive` /
|
|
46
|
+
`state` (readback, snapshot: values only). Payload: `{"dps":{}}`, `{"data":{"dps":{}}}` or bare `{"1":true}`.
|
|
47
|
+
- `Command(prop, value)` is checked as il.md section 5 says before anything is sent; failures come back as `Reject`.
|
|
48
|
+
Values convert as in Home Assistant core (brightness goes through 0..255; cover position is reversed unless
|
|
49
|
+
`control_back_mode` is `back`), so a written value can differ slightly from what is read back.
|
|
50
|
+
- Covers of class garage/gate are read only unless `TuyaDriver(..., allow_hazardous=True)` (il.md S-1).
|
|
51
|
+
- A dp no platform table claims gets no property, as in Home Assistant core; `TuyaDriver(..., expose_unused=True)` gives
|
|
52
|
+
each one a property chosen by its Tuya type (rustuya-homeassistant v1 did that). Integer, Enum and Boolean are writable only if the dp is
|
|
53
|
+
in `function`; String, Raw, Json and Bitmap are read-only. `config` if writable, else `diagnostic`.
|
|
54
|
+
- Assembled: switch, button, select, number, sensor, binary_sensor, event, light, cover, fan, siren, valve,
|
|
55
|
+
humidifier, climate, alarm (kind `alarm`), vacuum. Not assembled: camera (a stream is outside the IL; `driver.unsupported` lists it).
|
|
56
|
+
A doorbell `alarm_message` event loses its message text (an ildevice event has only a kind).
|
|
57
|
+
|
|
58
|
+
## User overrides
|
|
59
|
+
|
|
60
|
+
`TuyaDriver(device, overrides=mapping)` / `Hub(devices, overrides=mapping)`; `mapping` is `{product_id or device id: block}`,
|
|
61
|
+
already loaded (the host reads files; `merge_all([...])` merges several, later wins). Details and the block format are in
|
|
62
|
+
[overrides.py](src/tuya2ildevice/overrides.py):
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{ "5rta89nj": {
|
|
66
|
+
"dp": {"104": {"code": "percent_control", "type": "Integer", "values": {"min": 0, "max": 100, "scale": 0, "step": 1}}},
|
|
67
|
+
"remove": ["cycle_time"],
|
|
68
|
+
"props": {"countdown_1": {"label": "Timer", "category": "config", "rw": false}},
|
|
69
|
+
"device": {"model": "Sliding Window Opener"} } }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`dp`, `remove`, `category` patch the schema before classification (a defined dp is classified like any other);
|
|
73
|
+
`props` (by property name) and `device` patch the descriptor. Unknown keys raise `OverrideError`.
|
|
74
|
+
`Hub.reload(mapping)` applies new overrides live: republishes changed descriptors and clears removed properties.
|
|
75
|
+
`from_v1(custom_converters)` converts rustuya-homeassistant `dp_meta`; `discovery_overrides` (HA payload fields) are
|
|
76
|
+
dropped with a warning.
|
|
77
|
+
|
|
78
|
+
## Code converters
|
|
79
|
+
|
|
80
|
+
The equivalent of v1's `custom_converters/*.py`: a per-device `Converter` object sees the driver's dp state on every
|
|
81
|
+
packet and returns derived property values (and timer requests, since it cannot read a clock). See
|
|
82
|
+
[converters.py](src/tuya2ildevice/converters.py).
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
class MyConverter(Converter):
|
|
86
|
+
def props(self): return {"motion": {"type": "select", "role": "motion", "options": ["opening", "closing", "stopped"]}}
|
|
87
|
+
def update(self, now, codes, changed, active): return {"motion": "stopped"} # or Result(values=..., timers=...)
|
|
88
|
+
|
|
89
|
+
TuyaDriver(device, converters={"<product_id or device id>": [lambda device: MyConverter()]})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Built-in ones are named in an override block: `{"<product_id>": {"converters": {"cover_motion": {"settle": 5}}}}`.
|
|
93
|
+
`cover_motion` (ported from v1's `00_curtain.py`) derives the cover's `motion` role (opening / closing / stopped) from the
|
|
94
|
+
control, set-position and position dps; a snapshot never starts motion. Timers come out as `SetTimer` (driver) or
|
|
95
|
+
`Schedule` (`Hub`); the host calls back with `Timer` / `hub.on_timer(now, id, name)`. Loading a user's `.py` file is the
|
|
96
|
+
host's job; the code runs in-process.
|
|
97
|
+
|
|
98
|
+
## rustuya-bridge <-> tuya2ildevice <-> an IL host over MQTT
|
|
99
|
+
|
|
100
|
+
`Hub` ([mqtt.py](src/tuya2ildevice/mqtt.py)) owns one driver per device and maps both sides. Its methods take what was
|
|
101
|
+
received and return `Publish(side, topic, payload, retain, qos)`; the host only executes them.
|
|
102
|
+
`tuya2ildevice.host` is the host: `Runner` drives a `Hub` on two transports (`MqttTransport` over paho, or the in-process
|
|
103
|
+
`InProcessTransport`), keeps the Last Will presence (M-12), reconnects, adds/removes devices while running
|
|
104
|
+
(`set_device`, `remove_device`, `sync_devices`) and follows rustuya-manager's `tuyadevices.json` (`DeviceWatcher`).
|
|
105
|
+
`read_bridge_config` + `BridgeTopics.from_config` take the topic layout the bridge announces on `{root}/bridge/config`.
|
|
106
|
+
|
|
107
|
+
| direction | topic |
|
|
108
|
+
|---|---|
|
|
109
|
+
| bridge -> hub | `rustuya/event/{active,passive,state}/<id>` (dps JSON, or single-DP), `rustuya/error/<id>` (`errorCode` 0 = connected) |
|
|
110
|
+
| hub -> bridge | `rustuya/command` `{"action":"set"/"get",...}` (a `get` after each connect) |
|
|
111
|
+
| hub -> IL host | il-mqtt.md: retained `il/<id>` and `il/<id>/<prop>`; events and `il/<id>/reject` not retained; `il/_producer/tuya` presence |
|
|
112
|
+
| IL host -> hub | `il/<id>/<prop>/set` (retained writes ignored) |
|
|
113
|
+
|
|
114
|
+
Run the bridge with `mqtt_retain: true` and register the devices in it yourself (`add`); the hub never touches keys.
|
|
115
|
+
|
|
116
|
+
## Layout
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
src/tuya2ildevice/
|
|
120
|
+
driver.py TuyaDriver: packets/commands <-> outputs io.py inputs and outputs as data
|
|
121
|
+
assemble.py engine entity plans -> ildevice props/roles checks.py il.md section 5 command checks
|
|
122
|
+
mqtt.py Hub, BridgeTopics, IlTopics tuya/ the DP engine (see below)
|
|
123
|
+
tuya/ classify + platforms, adapter (raw dps <-> values), quirks, ops, codecs, units
|
|
124
|
+
tuya/tables/ per-platform description tables, generated from HA core tuya/quirks/ from tuya-device-handlers
|
|
125
|
+
tuya/data/ HA's allowed units per device class
|
|
126
|
+
scripts/ generators for those data files, and golden/ (builds the golden data; needs HA core + oracle venvs)
|
|
127
|
+
docs/ engine-spec.md (the engine's behaviour), analysis/ (how it was derived from HA core)
|
|
128
|
+
tests/ golden/ = 324 HA core fixtures + core's own snapshots; chain/ = the same through an IL host's planner
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The engine reproduces Home Assistant core's `tuya` integration exactly, including its quirks, and the golden tests
|
|
132
|
+
pin it: `tests/golden/golden.json` is core's own entity snapshots for every fixture. To follow a new HA core /
|
|
133
|
+
tuya-device-handlers release, run the generators in `scripts/` against it, then the tests; a difference is either
|
|
134
|
+
a real change to adopt or a regression.
|
|
135
|
+
|
|
136
|
+
## Tests
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
pip install -e .[test] && python -m pytest
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`tests/test_adapter.py` compares the raw-dps adapter with the Tuya SDK and is skipped unless `tuya-device-sharing-sdk==0.2.15`
|
|
143
|
+
is installed. The spec repository (`../ildevice`, or `$ILDEVICE`) supplies the schema and the language-neutral vectors
|
|
144
|
+
(commands, wire values, topics) read directly from its checkout; those tests are skipped if it is not there. `tests/chain/`
|
|
145
|
+
compares every Home Assistant core tuya fixture with core's entity snapshots through an IL host's HA-free planner
|
|
146
|
+
(needs that host's `ildevice.core` on `sys.path`; not collected without it).
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# tuya2ildevice
|
|
2
|
+
|
|
3
|
+
The one place that interprets Tuya. Sans-IO Python: takes a Tuya device as [rustuya](https://github.com/3735943886/rustuya) /
|
|
4
|
+
[rustuya-bridge](https://github.com/3735943886/rustuya-bridge) know it and produces an
|
|
5
|
+
[ildevice](https://github.com/3735943886/ildevice): descriptor, live values and events from dps packets, and dps for
|
|
6
|
+
ildevice commands. It opens no sockets and reads no clock. Other projects
|
|
7
|
+
([rustuya-homeassistant](https://github.com/3735943886/rustuya-homeassistant), ildevice hosts,
|
|
8
|
+
[rustuya-manager](https://github.com/3735943886/rustuya-manager)) import this instead of carrying their own Tuya knowledge.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
pip install tuya2ildevice # no dependencies; tuya2ildevice[host] adds paho-mqtt for `tuya2ildevice.host`, [test] for the tests
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from tuya2ildevice import TuyaDriver, Connected, Message, Command, descriptor_of
|
|
16
|
+
|
|
17
|
+
descriptor_of(device) # just the ildevice descriptor of a tuyadevices.json entry
|
|
18
|
+
d = TuyaDriver(device) # the state machine (il.md section 8)
|
|
19
|
+
d.handle(now, Connected()) # -> [Descriptor]
|
|
20
|
+
d.handle(now, Message("active", {"data": {"dps": {"1": True}}})) # -> [Value(...), Event(...)]
|
|
21
|
+
d.handle(now, Command("switch_1", "off")) # -> [SendMessage("set", {"dps": {"1": False}})] or [Reject(...)]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Packets and commands
|
|
25
|
+
|
|
26
|
+
- `Message(channel, json)`: `active` (device push: fires events, accumulates `add_ele`-style deltas) or `passive` /
|
|
27
|
+
`state` (readback, snapshot: values only). Payload: `{"dps":{}}`, `{"data":{"dps":{}}}` or bare `{"1":true}`.
|
|
28
|
+
- `Command(prop, value)` is checked as il.md section 5 says before anything is sent; failures come back as `Reject`.
|
|
29
|
+
Values convert as in Home Assistant core (brightness goes through 0..255; cover position is reversed unless
|
|
30
|
+
`control_back_mode` is `back`), so a written value can differ slightly from what is read back.
|
|
31
|
+
- Covers of class garage/gate are read only unless `TuyaDriver(..., allow_hazardous=True)` (il.md S-1).
|
|
32
|
+
- A dp no platform table claims gets no property, as in Home Assistant core; `TuyaDriver(..., expose_unused=True)` gives
|
|
33
|
+
each one a property chosen by its Tuya type (rustuya-homeassistant v1 did that). Integer, Enum and Boolean are writable only if the dp is
|
|
34
|
+
in `function`; String, Raw, Json and Bitmap are read-only. `config` if writable, else `diagnostic`.
|
|
35
|
+
- Assembled: switch, button, select, number, sensor, binary_sensor, event, light, cover, fan, siren, valve,
|
|
36
|
+
humidifier, climate, alarm (kind `alarm`), vacuum. Not assembled: camera (a stream is outside the IL; `driver.unsupported` lists it).
|
|
37
|
+
A doorbell `alarm_message` event loses its message text (an ildevice event has only a kind).
|
|
38
|
+
|
|
39
|
+
## User overrides
|
|
40
|
+
|
|
41
|
+
`TuyaDriver(device, overrides=mapping)` / `Hub(devices, overrides=mapping)`; `mapping` is `{product_id or device id: block}`,
|
|
42
|
+
already loaded (the host reads files; `merge_all([...])` merges several, later wins). Details and the block format are in
|
|
43
|
+
[overrides.py](src/tuya2ildevice/overrides.py):
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{ "5rta89nj": {
|
|
47
|
+
"dp": {"104": {"code": "percent_control", "type": "Integer", "values": {"min": 0, "max": 100, "scale": 0, "step": 1}}},
|
|
48
|
+
"remove": ["cycle_time"],
|
|
49
|
+
"props": {"countdown_1": {"label": "Timer", "category": "config", "rw": false}},
|
|
50
|
+
"device": {"model": "Sliding Window Opener"} } }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`dp`, `remove`, `category` patch the schema before classification (a defined dp is classified like any other);
|
|
54
|
+
`props` (by property name) and `device` patch the descriptor. Unknown keys raise `OverrideError`.
|
|
55
|
+
`Hub.reload(mapping)` applies new overrides live: republishes changed descriptors and clears removed properties.
|
|
56
|
+
`from_v1(custom_converters)` converts rustuya-homeassistant `dp_meta`; `discovery_overrides` (HA payload fields) are
|
|
57
|
+
dropped with a warning.
|
|
58
|
+
|
|
59
|
+
## Code converters
|
|
60
|
+
|
|
61
|
+
The equivalent of v1's `custom_converters/*.py`: a per-device `Converter` object sees the driver's dp state on every
|
|
62
|
+
packet and returns derived property values (and timer requests, since it cannot read a clock). See
|
|
63
|
+
[converters.py](src/tuya2ildevice/converters.py).
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
class MyConverter(Converter):
|
|
67
|
+
def props(self): return {"motion": {"type": "select", "role": "motion", "options": ["opening", "closing", "stopped"]}}
|
|
68
|
+
def update(self, now, codes, changed, active): return {"motion": "stopped"} # or Result(values=..., timers=...)
|
|
69
|
+
|
|
70
|
+
TuyaDriver(device, converters={"<product_id or device id>": [lambda device: MyConverter()]})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Built-in ones are named in an override block: `{"<product_id>": {"converters": {"cover_motion": {"settle": 5}}}}`.
|
|
74
|
+
`cover_motion` (ported from v1's `00_curtain.py`) derives the cover's `motion` role (opening / closing / stopped) from the
|
|
75
|
+
control, set-position and position dps; a snapshot never starts motion. Timers come out as `SetTimer` (driver) or
|
|
76
|
+
`Schedule` (`Hub`); the host calls back with `Timer` / `hub.on_timer(now, id, name)`. Loading a user's `.py` file is the
|
|
77
|
+
host's job; the code runs in-process.
|
|
78
|
+
|
|
79
|
+
## rustuya-bridge <-> tuya2ildevice <-> an IL host over MQTT
|
|
80
|
+
|
|
81
|
+
`Hub` ([mqtt.py](src/tuya2ildevice/mqtt.py)) owns one driver per device and maps both sides. Its methods take what was
|
|
82
|
+
received and return `Publish(side, topic, payload, retain, qos)`; the host only executes them.
|
|
83
|
+
`tuya2ildevice.host` is the host: `Runner` drives a `Hub` on two transports (`MqttTransport` over paho, or the in-process
|
|
84
|
+
`InProcessTransport`), keeps the Last Will presence (M-12), reconnects, adds/removes devices while running
|
|
85
|
+
(`set_device`, `remove_device`, `sync_devices`) and follows rustuya-manager's `tuyadevices.json` (`DeviceWatcher`).
|
|
86
|
+
`read_bridge_config` + `BridgeTopics.from_config` take the topic layout the bridge announces on `{root}/bridge/config`.
|
|
87
|
+
|
|
88
|
+
| direction | topic |
|
|
89
|
+
|---|---|
|
|
90
|
+
| bridge -> hub | `rustuya/event/{active,passive,state}/<id>` (dps JSON, or single-DP), `rustuya/error/<id>` (`errorCode` 0 = connected) |
|
|
91
|
+
| hub -> bridge | `rustuya/command` `{"action":"set"/"get",...}` (a `get` after each connect) |
|
|
92
|
+
| hub -> IL host | il-mqtt.md: retained `il/<id>` and `il/<id>/<prop>`; events and `il/<id>/reject` not retained; `il/_producer/tuya` presence |
|
|
93
|
+
| IL host -> hub | `il/<id>/<prop>/set` (retained writes ignored) |
|
|
94
|
+
|
|
95
|
+
Run the bridge with `mqtt_retain: true` and register the devices in it yourself (`add`); the hub never touches keys.
|
|
96
|
+
|
|
97
|
+
## Layout
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
src/tuya2ildevice/
|
|
101
|
+
driver.py TuyaDriver: packets/commands <-> outputs io.py inputs and outputs as data
|
|
102
|
+
assemble.py engine entity plans -> ildevice props/roles checks.py il.md section 5 command checks
|
|
103
|
+
mqtt.py Hub, BridgeTopics, IlTopics tuya/ the DP engine (see below)
|
|
104
|
+
tuya/ classify + platforms, adapter (raw dps <-> values), quirks, ops, codecs, units
|
|
105
|
+
tuya/tables/ per-platform description tables, generated from HA core tuya/quirks/ from tuya-device-handlers
|
|
106
|
+
tuya/data/ HA's allowed units per device class
|
|
107
|
+
scripts/ generators for those data files, and golden/ (builds the golden data; needs HA core + oracle venvs)
|
|
108
|
+
docs/ engine-spec.md (the engine's behaviour), analysis/ (how it was derived from HA core)
|
|
109
|
+
tests/ golden/ = 324 HA core fixtures + core's own snapshots; chain/ = the same through an IL host's planner
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The engine reproduces Home Assistant core's `tuya` integration exactly, including its quirks, and the golden tests
|
|
113
|
+
pin it: `tests/golden/golden.json` is core's own entity snapshots for every fixture. To follow a new HA core /
|
|
114
|
+
tuya-device-handlers release, run the generators in `scripts/` against it, then the tests; a difference is either
|
|
115
|
+
a real change to adopt or a regression.
|
|
116
|
+
|
|
117
|
+
## Tests
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
pip install -e .[test] && python -m pytest
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`tests/test_adapter.py` compares the raw-dps adapter with the Tuya SDK and is skipped unless `tuya-device-sharing-sdk==0.2.15`
|
|
124
|
+
is installed. The spec repository (`../ildevice`, or `$ILDEVICE`) supplies the schema and the language-neutral vectors
|
|
125
|
+
(commands, wire values, topics) read directly from its checkout; those tests are skipped if it is not there. `tests/chain/`
|
|
126
|
+
compares every Home Assistant core tuya fixture with core's entity snapshots through an IL host's HA-free planner
|
|
127
|
+
(needs that host's `ildevice.core` on `sys.path`; not collected without it).
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Phase 1 synthesis: what HA core's tuya integration actually does
|
|
2
|
+
|
|
3
|
+
Sources: HA core dev @ 949a484 (2026-09-19), tuya-device-handlers 0.0.29,
|
|
4
|
+
tuya-device-sharing-sdk 0.2.15. Per-area catalogs (with file:line evidence) are
|
|
5
|
+
catalog/A..F. Headline claims were spot-checked against source by the
|
|
6
|
+
coordinator (PLATFORMS list, siren features, local_strategy usage, quirk count).
|
|
7
|
+
|
|
8
|
+
## 1. Shape of the system
|
|
9
|
+
|
|
10
|
+
CustomerDevice (cloud schema: function / status_range / status)
|
|
11
|
+
-> quirk stage (by product_id; mutates schema/status/category) [handlers]
|
|
12
|
+
-> category -> per-platform description tables [core]
|
|
13
|
+
-> definition (resolves dp codes + types into wrappers) [handlers]
|
|
14
|
+
-> wrapper: read(status)->value ; write(value)->[{code,value}] [handlers]
|
|
15
|
+
-> HA entity (thin) [core]
|
|
16
|
+
|
|
17
|
+
Handlers (7.1k lines) has NO homeassistant imports. Core (9.7k lines) holds the
|
|
18
|
+
tables + thin entities. 18 platforms; lock / media_player / water_heater are NOT
|
|
19
|
+
among them (lock-category devices register but create zero entities).
|
|
20
|
+
|
|
21
|
+
## 2. Numbers
|
|
22
|
+
|
|
23
|
+
- DeviceCategory 139 members (98 referenced; categories are open strings in fixtures)
|
|
24
|
+
- DPCode 415 members
|
|
25
|
+
- 617 literal entity descriptions (834 expanded); sensor alone 250/450
|
|
26
|
+
- 32 quirk files (14 override kinds; 30 pure data, 3 code hooks)
|
|
27
|
+
- 324 test fixtures, 285 produce entities (1205 total, quirks disabled), 39 produce none
|
|
28
|
+
- only 16/324 fixtures carry local_strategy (numeric dp ids)
|
|
29
|
+
|
|
30
|
+
## 3. Facts that constrain the IL
|
|
31
|
+
|
|
32
|
+
1. Everything is keyed by dp CODE, never dp id. Schema = function + status_range
|
|
33
|
+
(type, range, scale, step, enum values). local_strategy is touched only by quirks.
|
|
34
|
+
2. Entity existence = category table AND required dp codes present with required
|
|
35
|
+
type (tuple-of-candidates fallback, prefer_function toggle). No product_id
|
|
36
|
+
selection outside quirks. Some platforms have degenerate rules (climate: every
|
|
37
|
+
dbl/kt/qn/rs/wk/wkf device gets one even with no dps; vacuum: always for `sd`).
|
|
38
|
+
3. Reads are pure; invalid raw values become None (unknown), not errors. One
|
|
39
|
+
stateful reader (delta accumulator, needs dp_timestamps).
|
|
40
|
+
4. Writes are pure: value -> list of {code,value}; validated against schema.
|
|
41
|
+
Multi-dp writes exist only in light (ordered color+mode) and a few climate paths.
|
|
42
|
+
5. Cross-dp rules exist: cover inversion depends on control_back_mode; alarm
|
|
43
|
+
TRIGGERED depends on master_state + decoded alarm_msg; light color mode depends
|
|
44
|
+
on work_mode; climate hvac_mode from switch+mode. Some read dps NOT in schema.
|
|
45
|
+
6. Named fixed transforms needed: linear remap (with inversion), mired/Kelvin,
|
|
46
|
+
HSV json/hex codecs, unit conversion, electricity raw/json parsers, wind lookup,
|
|
47
|
+
bitmap bit/in-set, base64 utf8/raw, enum<->HA maps, many-to-one status maps.
|
|
48
|
+
7. No optimistic state, no debounce; dp_timestamps only for the delta accumulator.
|
|
49
|
+
Availability = device online flag only.
|
|
50
|
+
8. Quirks: keyed product_id; run before classification; add/replace/remove dp,
|
|
51
|
+
retype/rescale, category override, initial status map, TypeInformation class swap
|
|
52
|
+
per dpcode, apply_when predicate (code), feeder wrapper (code). Custom user
|
|
53
|
+
quirks are arbitrary Python files (out of scope for a data IL).
|
|
54
|
+
9. Hard-coded literals live in code ("Sensor Low Battery", FZ/ZZ/STOP, chargego,
|
|
55
|
+
back) -- IL must carry them as data.
|
|
56
|
+
10. Documented quirks of core itself: climate hvac_mode reads an unfiltered map (can
|
|
57
|
+
report a mode not in hvac_modes); cover open/close with a position dp sends only
|
|
58
|
+
position; unverified paths: cover tilt, mach_operate (no fixtures).
|
|
59
|
+
|
|
60
|
+
## 4. Fit with our situation
|
|
61
|
+
|
|
62
|
+
- Our registration cache already stores local_strategy + function + status_range
|
|
63
|
+
(const.py CONF_LOCAL_STRATEGY/FUNCTION/STATUS_RANGE), so core's actual required
|
|
64
|
+
input (function/status_range) IS available to us; tuya2ha today classifies from
|
|
65
|
+
local_strategy alone and ignores function/status_range types.
|
|
66
|
+
- We need dp code <-> dp id translation on top (bridge speaks numeric dp ids);
|
|
67
|
+
the SDK also has 24 value-convert strategies (local raw -> cloud value) that
|
|
68
|
+
core assumes already applied. Whether the bridge's values need those is UNKNOWN
|
|
69
|
+
(SDK strategy implementations were not read).
|
|
70
|
+
- Lock is outside "reuse of core knowledge": core has none. Needs another source.
|
|
71
|
+
- Removable from IL scope: cloud auth/MQ, scenes, camera streaming, feeder
|
|
72
|
+
services, user-quirk plugins, optimistic state, debounce.
|
|
73
|
+
|
|
74
|
+
## 5. Decisions the IL design needs from the user
|
|
75
|
+
|
|
76
|
+
D1. Fidelity target: reproduce core exactly (including its quirks like the climate
|
|
77
|
+
unfiltered map) vs. reproduce intended behavior.
|
|
78
|
+
D2. Schema source contract: require function/status_range (like core) with
|
|
79
|
+
local_strategy for dp-id mapping, vs. keep tuya2ha's local_strategy-only mode too.
|
|
80
|
+
D3. Do SDK value-convert strategies need porting (blocked on live verification).
|
|
81
|
+
D4. Quirk scope: data-only quirks in IL (30/32) + small declarative predicate
|
|
82
|
+
language, or also code hooks.
|
|
83
|
+
D5. Lock/media_player/etc: out of scope, or source knowledge elsewhere (tuya-local
|
|
84
|
+
yaml corpus / own design).
|
|
85
|
+
D6. Golden tests: use core's snapshots as-is (quirks off) and add quirk-on cases.
|