boneIO 1.0.0.dev22__tar.gz → 1.0.0.dev24__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.
- {boneio-1.0.0.dev22/boneio.egg-info → boneio-1.0.0.dev24}/PKG-INFO +1 -1
- {boneio-1.0.0.dev22/boneio/boards/0.4 → boneio-1.0.0.dev24/boneio/boards/0.2}/output_24_16.yaml +2 -2
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.3/output_24_16.yaml +2 -2
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/input/detectors.py +190 -3
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/input/event.py +74 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/config/config_helper.py +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/covers.py +3 -3
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/inputs.py +40 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/manager.py +12 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/system/host_data.py +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/24x16/config.yaml +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/32x10/config.yaml +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/config.yaml +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/config.yaml +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/input/base.py +34 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/integration/homeassistant.py +32 -6
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/schema.yaml +45 -1
- boneio-1.0.0.dev24/boneio/version.py +2 -0
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/cssMode-CTEJXHUr.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/cssMode-Cu-5LYe_.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/freemarker2-DSCsQPcZ.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/freemarker2-nq6oJG_Y.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/handlebars-BxUcZhlf.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/handlebars-B5W2-m2x.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/html-CeIuVMbE.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/html-vUTSIY6B.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/htmlMode-CPIPzTN0.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/htmlMode-CDTfRhqt.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/index-BehXyBY8.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/index-BQrDKk-6.js +250 -250
- boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/index-CU6eO3xb.css +1 -0
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/javascript-CpYki0-I.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/javascript-BT4M2_pD.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/jsonMode-D9XhtrDP.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/jsonMode-D-E2Vrak.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/liquid-B00joeAd.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/liquid-D1aceO1w.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/mdx-DvdDUhMH.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/mdx-DohT_XYH.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/python-CSHyK2oP.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/python-C8fD_30g.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/razor-CGXQVQhg.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/razor-090nAgDD.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/tsMode-CaUDBDMJ.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/tsMode-BAlzCa-y.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/typescript-DMGXfEu0.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/typescript-C3QTnewR.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/xml-D2UC847g.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/xml-D3NSlFbJ.js +1 -1
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/yaml-DfvHGUeZ.js → boneio-1.0.0.dev24/boneio/webui/frontend-dist/assets/yaml-1y1ho8Rn.js +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/index.html +2 -2
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/adc.schema.json +2 -2
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/binary_sensor.schema.json +18 -18
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/boneio.schema.json +7 -3
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/config.schema.json +280 -165
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/cover.schema.json +8 -8
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/event.schema.json +175 -64
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/ina219.schema.json +4 -4
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/lm75.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/mcp23017.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/mcp9808.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/modbus.schema.json +6 -6
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/modbus_devices.schema.json +6 -6
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/mqtt.schema.json +2 -2
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/oled.schema.json +2 -2
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/output.schema.json +8 -8
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/pca9685.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/pcf8575.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/remote_devices.schema.json +12 -12
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/sensor.schema.json +2 -2
- {boneio-1.0.0.dev22/boneio/webui/schema → boneio-1.0.0.dev24/boneio/webui/frontend-dist/schem}/web.schema.json +8 -8
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/update.py +20 -11
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/adc.schema.json +2 -2
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/binary_sensor.schema.json +18 -18
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/boneio.schema.json +7 -3
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/config.schema.json +280 -165
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/cover.schema.json +8 -8
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/event.schema.json +175 -64
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/ina219.schema.json +4 -4
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/lm75.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/mcp23017.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/mcp9808.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/modbus.schema.json +6 -6
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/modbus_devices.schema.json +6 -6
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/mqtt.schema.json +2 -2
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/oled.schema.json +2 -2
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/output.schema.json +8 -8
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/pca9685.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/pcf8575.schema.json +4 -4
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/remote_devices.schema.json +12 -12
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/sensor.schema.json +2 -2
- {boneio-1.0.0.dev22/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev24/boneio/webui/schema}/web.schema.json +8 -8
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24/boneio.egg-info}/PKG-INFO +1 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio.egg-info/SOURCES.txt +17 -17
- boneio-1.0.0.dev22/boneio/version.py +0 -2
- boneio-1.0.0.dev22/boneio/webui/frontend-dist/assets/index-BODT6D6E.css +0 -1
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/LICENSE +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/MANIFEST.in +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/README.md +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.2/input.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.2/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.2/output_32_5.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.2/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.3/input.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.3/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.3/output_32_5.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.3/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.4/input.yaml +0 -0
- {boneio-1.0.0.dev22/boneio/boards/0.2 → boneio-1.0.0.dev24/boneio/boards/0.4}/output_24_16.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.4/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.4/output_32_5.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.4/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.5/input.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.5/output_24_16.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.5/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.5/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.6/input.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.6/output_24_16.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.6/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.6/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/bonecli.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/cover/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/cover/cover.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/cover/previous.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/cover/time_based.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/cover/venetian.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/group/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/group/output_group.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/input/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/input/binary_sensor.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/output/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/output/basic.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/output/mcp.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/output/pca.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/output/pcf.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/sensor/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/components/sensor/virtual_energy.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/const.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/config/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/config/package-lock.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/config/package.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/config/schema_converter.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/config/yaml_util.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/discovery.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/events/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/events/bus.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/display.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/modbus.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/outputs.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/remote.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/manager/sensors.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/messaging/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/messaging/basic.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/messaging/basic_mqtt.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/messaging/local.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/messaging/mqtt.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/messaging/queue.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/remote/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/remote/base.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/remote/esphome.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/remote/mqtt.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/sensor/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/sensor/base.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/sensor/system.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/state/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/state/manager.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/system/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/system/monitor.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/async_updater.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/filter.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/font_util.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/logger.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/timeperiod.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/core/utils/util.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/exceptions.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/analog/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/analog/adc.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/display/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/display/fonts/danube__.ttf +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/display/oled.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/expanders/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/expanders/mcp23017.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/input/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/gpio/input/manager.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/i2c/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/i2c/bus.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/i2c/ina219.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/i2c/ina219_driver.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/i2c/mcp9808.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/i2c/pct2075.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/onewire/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/onewire/bus.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/onewire/dallas.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/onewire/ds2482.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/sensor/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/sensor/temperature/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/sensor/temperature/base.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/integration/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/integration/interlock.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/cli.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/client.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/coordinator.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/energy_meters/socomec_e03.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/energy_meters/socomec_e23.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/hvac/ventclear.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/inverters/sofar.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/inverters/thessla.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/other/r4dcb08.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/other/wanas415.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/sensors/cwt.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/sensors/dts1964_3f.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/sensors/pt100.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/sensors/sht20.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/devices/sensors/sht30.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/base.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/derived/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/derived/numeric.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/derived/select.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/derived/switch.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/derived/text.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/sensor/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/sensor/binary.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/sensor/numeric.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/sensor/text.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/writeable/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/writeable/binary.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/entities/writeable/numeric.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/modbus/utils.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/actions.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/events.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/files.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/logs.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/mqtt.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/models/state.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/runner.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/actions.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/filters.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/id.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/remote_devices.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/schema/update_interval.yaml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/app.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/abap-CRCWOmpq.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/apex-DnsZk_dE.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/azcli-1IWB1ccx.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/bat-DPkNLes8.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/bicep-Corcdgou.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/cameligo-CGrWLZr3.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/clojure-D9WOWImG.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/coffee-B7EJu28W.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/cpp-SEyurbux.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/csharp-BoL64M5l.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/csp-C46ZqvIl.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/css-DQU6DXDx.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/cypher-D84EuPTj.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/dart-D8lhlL1r.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/dockerfile-DLk6rpji.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/ecl-BO6FnfXk.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/editor.worker-DsAeyiJ5.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/elixir-BRjLKONM.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/flow9-Cac8vKd7.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/fsharp-fd1GTHhf.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/go-O9LJTZXk.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/graphql-LQdxqEYJ.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/hcl-DxDQ3s82.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/ini-BvajGCUy.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/java-SYsfObOQ.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/json.worker-DaRII17c.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/julia-DQXNmw_w.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/kotlin-qQ0MG-9I.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/less-GGFNNJHn.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/lexon-Canl7DCW.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/lua-D28Ae8-K.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/m3-DPitgjJI.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/markdown-B811l8j2.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/mips-CdjsipkG.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/msdax-CYqgjx_P.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/mysql-BHd6q0vd.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/objective-c-B1aVtJYH.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/pascal-BhNW15KB.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/pascaligo-5jv8CcQD.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/perl-DlYyT36c.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/pgsql-Dy0bjov7.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/php-120yhfDK.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/pla-CjnFlu4u.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/postiats-CQpG440k.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/powerquery-DdJtto1Z.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/powershell-Bu_VLpJB.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/protobuf-IBS6jZEB.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/pug-kFxLfcjb.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/qsharp-q7JyzKFN.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/r-BIFz-_sK.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/redis-CHOsPHWR.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/redshift-CBifECDb.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/restructuredtext-CghPJEOS.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/ruby-CYWGW-b1.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/rust-DMDD0SHb.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/sb-BYAiYHFx.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/scala-Bqvq8jcR.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/scheme-Dhb-2j9p.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/scss-CTwUZ5N7.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/shell-CsDZo4DB.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/solidity-CME5AdoB.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/sophia-RYC1BQQz.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/sparql-KEyrF7De.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/sql-BdTr02Mf.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/st-C7iG7M4S.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/swift-D7IUmUK8.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/systemverilog-DgMryOEJ.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/tcl-PloMZuKG.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/twig-BfRIq3la.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/typespec-CzxlYoT_.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/vb-BwAE3J76.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/wgsl-B_1kOXbF.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/assets/yaml.worker-BTE-_K6g.js +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/areas.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/dallas.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/ds2482.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/logger.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/output_group.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/frontend-dist/schem/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/middleware/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/middleware/auth.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/auth.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/caddy.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/config.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/covers.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/modbus.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/outputs.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/remote_devices.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/sensors.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/routes/system.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/areas.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/services/__init__.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/services/logs.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/web_server.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio/webui/websocket_manager.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio.egg-info/dependency_links.txt +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio.egg-info/entry_points.txt +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio.egg-info/requires.txt +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/boneio.egg-info/top_level.txt +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/pyproject.toml +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/setup.cfg +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/setup.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/tests/test_i2c_smbus2.py +0 -0
- {boneio-1.0.0.dev22 → boneio-1.0.0.dev24}/tests/test_py313_compatibility.py +0 -0
|
@@ -39,6 +39,10 @@ class ClickState:
|
|
|
39
39
|
# Sequence tracking
|
|
40
40
|
last_click_type: str | None = None
|
|
41
41
|
last_click_time: float | None = None
|
|
42
|
+
# Exclusive mode: pending click waiting for sequence window
|
|
43
|
+
pending_click_type: str | None = None
|
|
44
|
+
pending_click_duration: float | None = None
|
|
45
|
+
pending_click_timer: asyncio.TimerHandle | None = None
|
|
42
46
|
|
|
43
47
|
|
|
44
48
|
@dataclass
|
|
@@ -64,6 +68,9 @@ class MultiClickDetector:
|
|
|
64
68
|
multiclick_window_ms: float = 220.0,
|
|
65
69
|
hold_threshold_ms: float = 400.0,
|
|
66
70
|
sequence_window_ms: float = DEFAULT_SEQUENCE_WINDOW_MS,
|
|
71
|
+
sequence_mode: str = "immediate",
|
|
72
|
+
enabled_sequences: set[str] | None = None,
|
|
73
|
+
enable_triple_click: bool = False,
|
|
67
74
|
name: str = "unknown",
|
|
68
75
|
pin: str = "unknown",
|
|
69
76
|
):
|
|
@@ -76,6 +83,9 @@ class MultiClickDetector:
|
|
|
76
83
|
multiclick_window_ms: Window for double-click detection
|
|
77
84
|
hold_threshold_ms: Time threshold for long press
|
|
78
85
|
sequence_window_ms: Window for sequence detection (e.g., double_then_long)
|
|
86
|
+
sequence_mode: 'immediate' (default) or 'exclusive'
|
|
87
|
+
enabled_sequences: Set of enabled sequence types (e.g., {'double_then_long'})
|
|
88
|
+
enable_triple_click: Enable triple click detection (default: False)
|
|
79
89
|
name: Name of the input
|
|
80
90
|
pin: Pin name for logging
|
|
81
91
|
"""
|
|
@@ -85,9 +95,23 @@ class MultiClickDetector:
|
|
|
85
95
|
self._multiclick_window = multiclick_window_ms / 1000.0
|
|
86
96
|
self._hold_threshold = hold_threshold_ms / 1000.0
|
|
87
97
|
self._sequence_window = sequence_window_ms / 1000.0
|
|
98
|
+
self._sequence_mode = sequence_mode
|
|
99
|
+
self._enabled_sequences = enabled_sequences or set()
|
|
100
|
+
self._enable_triple_click = enable_triple_click
|
|
88
101
|
self._name = name
|
|
89
102
|
self._pin = pin
|
|
90
103
|
self._state = ClickState()
|
|
104
|
+
|
|
105
|
+
# Pre-compute which click types should be delayed in exclusive mode
|
|
106
|
+
# based on enabled sequences
|
|
107
|
+
self._delay_click_types: set[str] = set()
|
|
108
|
+
if sequence_mode == "exclusive" and self._enabled_sequences:
|
|
109
|
+
for seq in self._enabled_sequences:
|
|
110
|
+
# Find which click type starts this sequence
|
|
111
|
+
for (first, _second), seq_name in CLICK_SEQUENCES.items():
|
|
112
|
+
if seq_name == seq:
|
|
113
|
+
self._delay_click_types.add(first)
|
|
114
|
+
break
|
|
91
115
|
|
|
92
116
|
def _finalize_clicks(self) -> None:
|
|
93
117
|
"""Finalize a multi-click sequence."""
|
|
@@ -100,8 +124,18 @@ class MultiClickDetector:
|
|
|
100
124
|
click_type = DOUBLE
|
|
101
125
|
_LOGGER.info("Detected DOUBLE click on %s (%s)", self._name, self._pin)
|
|
102
126
|
elif count == 3:
|
|
103
|
-
|
|
104
|
-
|
|
127
|
+
if self._enable_triple_click:
|
|
128
|
+
click_type = TRIPLE
|
|
129
|
+
_LOGGER.info("Detected TRIPLE click on %s (%s)", self._name, self._pin)
|
|
130
|
+
else:
|
|
131
|
+
# Triple click disabled - emit double + single instead
|
|
132
|
+
_LOGGER.info("Triple click disabled on %s (%s), emitting DOUBLE + SINGLE", self._name, self._pin)
|
|
133
|
+
self._state.click_count = 0
|
|
134
|
+
self._state.finalizer = None
|
|
135
|
+
self._state.finalizer_scheduled_loop_ts = None
|
|
136
|
+
self._emit_click(DOUBLE, None)
|
|
137
|
+
self._emit_click(SINGLE, None)
|
|
138
|
+
return
|
|
105
139
|
else:
|
|
106
140
|
click_type = SINGLE # Fallback for 4+ clicks
|
|
107
141
|
_LOGGER.info("Detected %d clicks on %s (%s), treating as SINGLE", count, self._name, self._pin)
|
|
@@ -116,12 +150,22 @@ class MultiClickDetector:
|
|
|
116
150
|
def _emit_click(self, click_type: ClickTypes, duration: float | None) -> None:
|
|
117
151
|
"""Emit a click event, checking for sequences first.
|
|
118
152
|
|
|
153
|
+
In 'immediate' mode: emit events immediately, sequences are additional.
|
|
154
|
+
In 'exclusive' mode: delay single/double, if sequence detected only emit sequence.
|
|
155
|
+
|
|
119
156
|
Args:
|
|
120
157
|
click_type: The detected click type (single, double, triple, long)
|
|
121
158
|
duration: Duration of the click (for long press)
|
|
122
159
|
"""
|
|
123
160
|
current_time = self._loop.time()
|
|
124
161
|
|
|
162
|
+
if self._sequence_mode == "exclusive":
|
|
163
|
+
self._emit_click_exclusive(click_type, duration, current_time)
|
|
164
|
+
else:
|
|
165
|
+
self._emit_click_immediate(click_type, duration, current_time)
|
|
166
|
+
|
|
167
|
+
def _emit_click_immediate(self, click_type: ClickTypes, duration: float | None, current_time: float) -> None:
|
|
168
|
+
"""Immediate mode: emit events immediately, sequences are additional."""
|
|
125
169
|
# Check if this click forms a sequence with the previous one
|
|
126
170
|
sequence_type = self._check_sequence(click_type, current_time)
|
|
127
171
|
if sequence_type:
|
|
@@ -144,6 +188,138 @@ class MultiClickDetector:
|
|
|
144
188
|
self._state.last_click_type = click_type
|
|
145
189
|
self._state.last_click_time = current_time
|
|
146
190
|
|
|
191
|
+
def _emit_click_exclusive(self, click_type: ClickTypes, duration: float | None, current_time: float) -> None:
|
|
192
|
+
"""Exclusive mode: delay single/double, if sequence detected only emit sequence.
|
|
193
|
+
|
|
194
|
+
Logic:
|
|
195
|
+
- For single/double: store as pending, start timer for sequence_window
|
|
196
|
+
- For long/single: check if pending exists, if so check for sequence
|
|
197
|
+
- Timer expiry: emit the pending click
|
|
198
|
+
|
|
199
|
+
Supported sequences:
|
|
200
|
+
- double_then_long: double (pending) + long
|
|
201
|
+
- single_then_long: single (pending) + long
|
|
202
|
+
- double_then_single: double (pending) + single
|
|
203
|
+
"""
|
|
204
|
+
# Check if there's a pending click and this could form a sequence
|
|
205
|
+
if self._state.pending_click_type:
|
|
206
|
+
# Check if we can form a sequence with current click
|
|
207
|
+
sequence_key = (self._state.pending_click_type, click_type)
|
|
208
|
+
sequence_type = CLICK_SEQUENCES.get(sequence_key)
|
|
209
|
+
|
|
210
|
+
# Only detect sequences that are actually enabled
|
|
211
|
+
if sequence_type and sequence_type in self._enabled_sequences:
|
|
212
|
+
# Cancel pending timer
|
|
213
|
+
if self._state.pending_click_timer:
|
|
214
|
+
self._state.pending_click_timer.cancel()
|
|
215
|
+
self._state.pending_click_timer = None
|
|
216
|
+
|
|
217
|
+
_LOGGER.info(
|
|
218
|
+
"Detected sequence %s on %s (%s) [exclusive mode]",
|
|
219
|
+
sequence_type.upper(), self._name, self._pin
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Clear pending state
|
|
223
|
+
self._state.pending_click_type = None
|
|
224
|
+
self._state.pending_click_duration = None
|
|
225
|
+
|
|
226
|
+
# Emit only the sequence, not the base events
|
|
227
|
+
try:
|
|
228
|
+
self._callback(cast(ClickTypes, sequence_type), duration)
|
|
229
|
+
except Exception as exc:
|
|
230
|
+
_LOGGER.error("Error in sequence callback for %s: %s", self._name, exc, exc_info=True)
|
|
231
|
+
|
|
232
|
+
# Clear sequence tracking
|
|
233
|
+
self._state.last_click_type = None
|
|
234
|
+
self._state.last_click_time = None
|
|
235
|
+
return
|
|
236
|
+
else:
|
|
237
|
+
# Sequence not enabled - emit the pending click now and continue
|
|
238
|
+
# Cancel pending timer
|
|
239
|
+
if self._state.pending_click_timer:
|
|
240
|
+
self._state.pending_click_timer.cancel()
|
|
241
|
+
self._state.pending_click_timer = None
|
|
242
|
+
|
|
243
|
+
pending_type = self._state.pending_click_type
|
|
244
|
+
pending_duration = self._state.pending_click_duration
|
|
245
|
+
|
|
246
|
+
_LOGGER.debug(
|
|
247
|
+
"Sequence %s not enabled, emitting pending click %s on %s",
|
|
248
|
+
sequence_type, pending_type, self._name
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# Clear pending state
|
|
252
|
+
self._state.pending_click_type = None
|
|
253
|
+
self._state.pending_click_duration = None
|
|
254
|
+
|
|
255
|
+
# Emit the pending click
|
|
256
|
+
try:
|
|
257
|
+
self._callback(cast(ClickTypes, pending_type), pending_duration)
|
|
258
|
+
except Exception as exc:
|
|
259
|
+
_LOGGER.error("Error in click callback for %s: %s", self._name, exc, exc_info=True)
|
|
260
|
+
|
|
261
|
+
# Continue to process current click below (don't return)
|
|
262
|
+
|
|
263
|
+
# Only delay click types that can start a configured sequence
|
|
264
|
+
# e.g., if only double_then_long is enabled, only delay 'double', not 'single'
|
|
265
|
+
if click_type in self._delay_click_types:
|
|
266
|
+
# Cancel any existing pending timer
|
|
267
|
+
if self._state.pending_click_timer:
|
|
268
|
+
self._state.pending_click_timer.cancel()
|
|
269
|
+
|
|
270
|
+
# Store pending click
|
|
271
|
+
self._state.pending_click_type = click_type
|
|
272
|
+
self._state.pending_click_duration = duration
|
|
273
|
+
|
|
274
|
+
# Start timer to emit after sequence window
|
|
275
|
+
self._state.pending_click_timer = self._loop.call_later(
|
|
276
|
+
self._sequence_window,
|
|
277
|
+
self._emit_pending_click
|
|
278
|
+
)
|
|
279
|
+
_LOGGER.debug(
|
|
280
|
+
"Pending click %s on %s, waiting %.0fms for sequence",
|
|
281
|
+
click_type, self._name, self._sequence_window * 1000
|
|
282
|
+
)
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
# For long (without pending) or other types: emit immediately
|
|
286
|
+
try:
|
|
287
|
+
self._callback(click_type, duration)
|
|
288
|
+
except Exception as exc:
|
|
289
|
+
_LOGGER.error("Error in click callback for %s: %s", self._name, exc, exc_info=True)
|
|
290
|
+
|
|
291
|
+
# Remember for sequence detection
|
|
292
|
+
self._state.last_click_type = click_type
|
|
293
|
+
self._state.last_click_time = current_time
|
|
294
|
+
|
|
295
|
+
def _emit_pending_click(self) -> None:
|
|
296
|
+
"""Emit the pending click after sequence window expired (exclusive mode)."""
|
|
297
|
+
if not self._state.pending_click_type:
|
|
298
|
+
return
|
|
299
|
+
|
|
300
|
+
click_type = cast(ClickTypes, self._state.pending_click_type)
|
|
301
|
+
duration = self._state.pending_click_duration
|
|
302
|
+
|
|
303
|
+
_LOGGER.debug(
|
|
304
|
+
"Sequence window expired, emitting pending click %s on %s",
|
|
305
|
+
click_type, self._name
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Clear pending state
|
|
309
|
+
self._state.pending_click_type = None
|
|
310
|
+
self._state.pending_click_duration = None
|
|
311
|
+
self._state.pending_click_timer = None
|
|
312
|
+
|
|
313
|
+
# Emit the click
|
|
314
|
+
try:
|
|
315
|
+
self._callback(click_type, duration)
|
|
316
|
+
except Exception as exc:
|
|
317
|
+
_LOGGER.error("Error in pending click callback for %s: %s", self._name, exc, exc_info=True)
|
|
318
|
+
|
|
319
|
+
# Remember for sequence detection (in case of chained sequences)
|
|
320
|
+
self._state.last_click_type = click_type
|
|
321
|
+
self._state.last_click_time = self._loop.time()
|
|
322
|
+
|
|
147
323
|
def _check_sequence(self, current_click: ClickTypes, current_time: float) -> ClickTypes | None:
|
|
148
324
|
"""Check if current click forms a sequence with previous click.
|
|
149
325
|
|
|
@@ -166,7 +342,8 @@ class MultiClickDetector:
|
|
|
166
342
|
sequence_key = (self._state.last_click_type, current_click)
|
|
167
343
|
sequence_type = CLICK_SEQUENCES.get(sequence_key)
|
|
168
344
|
|
|
169
|
-
|
|
345
|
+
# Only detect sequences that are actually enabled
|
|
346
|
+
if sequence_type and sequence_type in self._enabled_sequences:
|
|
170
347
|
# Clear sequence state to prevent chaining
|
|
171
348
|
self._state.last_click_type = None
|
|
172
349
|
self._state.last_click_time = None
|
|
@@ -227,6 +404,16 @@ class MultiClickDetector:
|
|
|
227
404
|
self._state.finalizer = None
|
|
228
405
|
self._state.finalizer_scheduled_loop_ts = None
|
|
229
406
|
|
|
407
|
+
# In exclusive mode: if there's a pending click waiting for sequence,
|
|
408
|
+
# cancel its timer - user is continuing the sequence with this press
|
|
409
|
+
if self._sequence_mode == "exclusive" and self._state.pending_click_timer:
|
|
410
|
+
_LOGGER.debug(
|
|
411
|
+
"Cancelling pending click timer for %s - user continuing sequence",
|
|
412
|
+
self._name
|
|
413
|
+
)
|
|
414
|
+
self._state.pending_click_timer.cancel()
|
|
415
|
+
self._state.pending_click_timer = None
|
|
416
|
+
|
|
230
417
|
# Schedule a check for a long press
|
|
231
418
|
scheduled_at = self._loop.time()
|
|
232
419
|
self._state.long_press_scheduled_loop_ts = scheduled_at
|
|
@@ -65,6 +65,30 @@ class GpioEventButton(GpioBaseClass):
|
|
|
65
65
|
DEFAULT_SEQUENCE_WINDOW_MS
|
|
66
66
|
)
|
|
67
67
|
|
|
68
|
+
# Determine which sequences are enabled based on configured actions OR mqtt_sequences
|
|
69
|
+
# A sequence is enabled if it has actions defined OR is set to publish to MQTT
|
|
70
|
+
enabled_sequences: set[str] = set()
|
|
71
|
+
sequence_types = {'double_then_long', 'single_then_long', 'double_then_single'}
|
|
72
|
+
|
|
73
|
+
# Check actions
|
|
74
|
+
actions = kwargs.get('actions', {})
|
|
75
|
+
if isinstance(actions, dict):
|
|
76
|
+
for seq_type in sequence_types:
|
|
77
|
+
if seq_type in actions and actions[seq_type]:
|
|
78
|
+
enabled_sequences.add(seq_type)
|
|
79
|
+
|
|
80
|
+
# Check mqtt_sequences
|
|
81
|
+
mqtt_sequences = kwargs.get('mqtt_sequences', {})
|
|
82
|
+
if isinstance(mqtt_sequences, dict):
|
|
83
|
+
for seq_type in sequence_types:
|
|
84
|
+
if mqtt_sequences.get(seq_type):
|
|
85
|
+
enabled_sequences.add(seq_type)
|
|
86
|
+
|
|
87
|
+
_LOGGER.debug("Enabled sequences for %s: %s", self._name, enabled_sequences)
|
|
88
|
+
|
|
89
|
+
# Get enable_triple_click setting (default: False)
|
|
90
|
+
enable_triple_click = kwargs.get('enable_triple_click', False)
|
|
91
|
+
|
|
68
92
|
# Create multiclick detector
|
|
69
93
|
self._detector = MultiClickDetector(
|
|
70
94
|
loop=self._loop,
|
|
@@ -73,6 +97,9 @@ class GpioEventButton(GpioBaseClass):
|
|
|
73
97
|
multiclick_window_ms=double_click_duration,
|
|
74
98
|
hold_threshold_ms=long_press_duration,
|
|
75
99
|
sequence_window_ms=sequence_window_duration,
|
|
100
|
+
sequence_mode=self._sequence_mode,
|
|
101
|
+
enabled_sequences=enabled_sequences,
|
|
102
|
+
enable_triple_click=enable_triple_click,
|
|
76
103
|
name=self._name,
|
|
77
104
|
pin=self._pin,
|
|
78
105
|
)
|
|
@@ -116,6 +143,10 @@ class GpioEventButton(GpioBaseClass):
|
|
|
116
143
|
double_click_duration: int | float | None = None,
|
|
117
144
|
long_press_duration: int | float | None = None,
|
|
118
145
|
sequence_window_duration: int | float | None = None,
|
|
146
|
+
sequence_mode: str | None = None,
|
|
147
|
+
actions: dict | None = None,
|
|
148
|
+
mqtt_sequences: dict | None = None,
|
|
149
|
+
enable_triple_click: bool | None = None,
|
|
119
150
|
) -> None:
|
|
120
151
|
"""Update timing parameters for click detection.
|
|
121
152
|
|
|
@@ -126,7 +157,13 @@ class GpioEventButton(GpioBaseClass):
|
|
|
126
157
|
double_click_duration: Time window in ms to detect double click
|
|
127
158
|
long_press_duration: Time in ms to detect long press
|
|
128
159
|
sequence_window_duration: Time window in ms to detect sequences
|
|
160
|
+
sequence_mode: 'immediate' or 'exclusive'
|
|
161
|
+
actions: Actions dict to determine enabled sequences
|
|
162
|
+
mqtt_sequences: MQTT sequences dict to determine enabled sequences
|
|
163
|
+
enable_triple_click: Enable triple click detection
|
|
129
164
|
"""
|
|
165
|
+
from boneio.const import CLICK_SEQUENCES
|
|
166
|
+
|
|
130
167
|
if double_click_duration is not None:
|
|
131
168
|
value_ms = _to_milliseconds(double_click_duration, DEFAULT_DOUBLE_CLICK_DURATION_MS)
|
|
132
169
|
self._detector._multiclick_window = value_ms / 1000.0
|
|
@@ -140,4 +177,40 @@ class GpioEventButton(GpioBaseClass):
|
|
|
140
177
|
if sequence_window_duration is not None:
|
|
141
178
|
value_ms = _to_milliseconds(sequence_window_duration, DEFAULT_SEQUENCE_WINDOW_MS)
|
|
142
179
|
self._detector._sequence_window = value_ms / 1000.0
|
|
143
|
-
_LOGGER.debug("Updated sequence_window_duration to %dms for %s", value_ms, self._name)
|
|
180
|
+
_LOGGER.debug("Updated sequence_window_duration to %dms for %s", value_ms, self._name)
|
|
181
|
+
|
|
182
|
+
if sequence_mode is not None:
|
|
183
|
+
self._sequence_mode = sequence_mode
|
|
184
|
+
self._detector._sequence_mode = sequence_mode
|
|
185
|
+
_LOGGER.debug("Updated sequence_mode to %s for %s", sequence_mode, self._name)
|
|
186
|
+
|
|
187
|
+
if enable_triple_click is not None:
|
|
188
|
+
self._detector._enable_triple_click = enable_triple_click
|
|
189
|
+
_LOGGER.debug("Updated enable_triple_click to %s for %s", enable_triple_click, self._name)
|
|
190
|
+
|
|
191
|
+
# Update enabled sequences based on actions and mqtt_sequences
|
|
192
|
+
sequence_types = {'double_then_long', 'single_then_long', 'double_then_single'}
|
|
193
|
+
enabled_sequences: set[str] = set()
|
|
194
|
+
|
|
195
|
+
if actions is not None and isinstance(actions, dict):
|
|
196
|
+
for seq_type in sequence_types:
|
|
197
|
+
if seq_type in actions and actions[seq_type]:
|
|
198
|
+
enabled_sequences.add(seq_type)
|
|
199
|
+
|
|
200
|
+
if mqtt_sequences is not None and isinstance(mqtt_sequences, dict):
|
|
201
|
+
for seq_type in sequence_types:
|
|
202
|
+
if mqtt_sequences.get(seq_type):
|
|
203
|
+
enabled_sequences.add(seq_type)
|
|
204
|
+
|
|
205
|
+
if actions is not None or mqtt_sequences is not None:
|
|
206
|
+
self._detector._enabled_sequences = enabled_sequences
|
|
207
|
+
|
|
208
|
+
# Recompute delay_click_types
|
|
209
|
+
self._detector._delay_click_types = set()
|
|
210
|
+
if self._detector._sequence_mode == "exclusive" and enabled_sequences:
|
|
211
|
+
for seq in enabled_sequences:
|
|
212
|
+
for (first, _second), seq_name in CLICK_SEQUENCES.items():
|
|
213
|
+
if seq_name == seq:
|
|
214
|
+
self._detector._delay_click_types.add(first)
|
|
215
|
+
break
|
|
216
|
+
_LOGGER.debug("Updated enabled_sequences to %s for %s", enabled_sequences, self._name)
|
|
@@ -146,7 +146,7 @@ class ConfigHelper:
|
|
|
146
146
|
return "https" if self._proxy_port else "http"
|
|
147
147
|
|
|
148
148
|
@property
|
|
149
|
-
def
|
|
149
|
+
def web_configuration_port(self) -> int:
|
|
150
150
|
"""Get port for HA discovery URL. Uses proxy_port if set, otherwise web_port."""
|
|
151
151
|
return self._proxy_port if self._proxy_port else self._web_port
|
|
152
152
|
|
|
@@ -216,7 +216,7 @@ class CoverManager:
|
|
|
216
216
|
restored_state=restored_state,
|
|
217
217
|
tilt_duration=tilt_duration,
|
|
218
218
|
actuator_activation_duration=config.get("actuator_activation_duration", TimePeriod(milliseconds=0)),
|
|
219
|
-
**{k: v for k, v in config.items() if k not in ("platform", "actuator_activation_duration", "tilt_duration", RESTORE_STATE, SHOW_HA, DEVICE_CLASS, NAME)},
|
|
219
|
+
**{k: v for k, v in config.items() if k not in ("id", "platform", "actuator_activation_duration", "tilt_duration", RESTORE_STATE, SHOW_HA, DEVICE_CLASS, NAME)},
|
|
220
220
|
)
|
|
221
221
|
availability_msg_func = ha_cover_with_tilt_availabilty_message
|
|
222
222
|
elif platform == "time_based":
|
|
@@ -236,7 +236,7 @@ class CoverManager:
|
|
|
236
236
|
event_bus=self._manager._event_bus,
|
|
237
237
|
topic_prefix=self._manager._topic_prefix,
|
|
238
238
|
restored_state=restored_state,
|
|
239
|
-
**{k: v for k, v in config.items() if k not in ("platform", RESTORE_STATE, SHOW_HA, DEVICE_CLASS, NAME)},
|
|
239
|
+
**{k: v for k, v in config.items() if k not in ("id", "platform", RESTORE_STATE, SHOW_HA, DEVICE_CLASS, NAME)},
|
|
240
240
|
)
|
|
241
241
|
availability_msg_func = ha_cover_availabilty_message
|
|
242
242
|
elif platform == "previous":
|
|
@@ -256,7 +256,7 @@ class CoverManager:
|
|
|
256
256
|
event_bus=self._manager._event_bus,
|
|
257
257
|
topic_prefix=self._manager._topic_prefix,
|
|
258
258
|
restored_state=restored_state,
|
|
259
|
-
**{k: v for k, v in config.items() if k not in ("platform", RESTORE_STATE, SHOW_HA, DEVICE_CLASS, NAME)},
|
|
259
|
+
**{k: v for k, v in config.items() if k not in ("id", "platform", RESTORE_STATE, SHOW_HA, DEVICE_CLASS, NAME)},
|
|
260
260
|
)
|
|
261
261
|
availability_msg_func = ha_cover_availabilty_message
|
|
262
262
|
|
|
@@ -216,10 +216,12 @@ class InputManager:
|
|
|
216
216
|
# Reload: update existing input's actions and name
|
|
217
217
|
if existing_input:
|
|
218
218
|
|
|
219
|
-
# Check if HA-relevant fields changed (name, area)
|
|
219
|
+
# Check if HA-relevant fields changed (name, area, mqtt_sequences)
|
|
220
220
|
old_name = existing_input._name if hasattr(existing_input, '_name') else None
|
|
221
221
|
old_area = getattr(existing_input, 'area', None)
|
|
222
|
-
|
|
222
|
+
old_mqtt_sequences = existing_input.mqtt_sequences if hasattr(existing_input, 'mqtt_sequences') else {}
|
|
223
|
+
new_mqtt_sequences = gpio.get("mqtt_sequences", {})
|
|
224
|
+
ha_fields_changed = (old_name != name) or (old_area != area) or (old_mqtt_sequences != new_mqtt_sequences)
|
|
223
225
|
|
|
224
226
|
# Update actions (always - this is internal to the controller)
|
|
225
227
|
existing_input.set_actions(actions=actions)
|
|
@@ -231,14 +233,22 @@ class InputManager:
|
|
|
231
233
|
# Store area on input
|
|
232
234
|
existing_input.area = area
|
|
233
235
|
|
|
236
|
+
# Update mqtt_sequences configuration
|
|
237
|
+
if hasattr(existing_input, '_mqtt_sequences'):
|
|
238
|
+
existing_input._mqtt_sequences = new_mqtt_sequences
|
|
239
|
+
|
|
234
240
|
# Update timing parameters if this is an event button
|
|
235
241
|
existing_input.update_timings(
|
|
236
242
|
double_click_duration=gpio.get('double_click_duration'),
|
|
237
243
|
long_press_duration=gpio.get('long_press_duration'),
|
|
238
244
|
sequence_window_duration=gpio.get('sequence_window_duration'),
|
|
245
|
+
sequence_mode=gpio.get('sequence_mode'),
|
|
246
|
+
actions=actions,
|
|
247
|
+
mqtt_sequences=new_mqtt_sequences,
|
|
248
|
+
enable_triple_click=gpio.get('enable_triple_click'),
|
|
239
249
|
)
|
|
240
250
|
|
|
241
|
-
# Re-send HA discovery only if HA-relevant fields changed (name, area)
|
|
251
|
+
# Re-send HA discovery only if HA-relevant fields changed (name, area, mqtt_sequences)
|
|
242
252
|
# Actions are internal to the controller and don't need HA update
|
|
243
253
|
if ha_fields_changed and gpio.get(SHOW_HA, True):
|
|
244
254
|
_LOGGER.debug(f"HA-relevant fields changed for {input_id}, re-sending discovery")
|
|
@@ -249,6 +259,8 @@ class InputManager:
|
|
|
249
259
|
device_class=gpio.get(DEVICE_CLASS, None),
|
|
250
260
|
availability_msg_func=ha_event_availabilty_message,
|
|
251
261
|
area=area,
|
|
262
|
+
mqtt_sequences=gpio.get("mqtt_sequences"),
|
|
263
|
+
enable_triple_click=gpio.get("enable_triple_click", False),
|
|
252
264
|
)
|
|
253
265
|
return existing_input
|
|
254
266
|
|
|
@@ -275,6 +287,8 @@ class InputManager:
|
|
|
275
287
|
device_class=gpio.get(DEVICE_CLASS, None),
|
|
276
288
|
availability_msg_func=ha_event_availabilty_message,
|
|
277
289
|
area=area,
|
|
290
|
+
mqtt_sequences=gpio.get("mqtt_sequences"),
|
|
291
|
+
enable_triple_click=gpio.get("enable_triple_click", False),
|
|
278
292
|
)
|
|
279
293
|
|
|
280
294
|
return input_device
|
|
@@ -566,6 +580,9 @@ class InputManager:
|
|
|
566
580
|
# Remove from internal cache
|
|
567
581
|
self._manager._config_helper.remove_autodiscovery_msg(ha_type, topic)
|
|
568
582
|
|
|
583
|
+
# Sequence click types that require mqtt_sequences configuration
|
|
584
|
+
SEQUENCE_CLICK_TYPES = {"double_then_long", "single_then_long", "double_then_single"}
|
|
585
|
+
|
|
569
586
|
def _publish_input_event_to_mqtt(
|
|
570
587
|
self, input_instance: GpioBaseClass, event: InputEvent
|
|
571
588
|
) -> None:
|
|
@@ -574,6 +591,9 @@ class InputManager:
|
|
|
574
591
|
For event buttons (input_type=INPUT): sends JSON with event_type
|
|
575
592
|
For binary sensors (input_type=INPUT_SENSOR): sends pressed/released state
|
|
576
593
|
|
|
594
|
+
Sequence events (double_then_long, single_then_long, double_then_single) are only
|
|
595
|
+
published if explicitly enabled in mqtt_sequences configuration.
|
|
596
|
+
|
|
577
597
|
Args:
|
|
578
598
|
input_instance: The input device instance
|
|
579
599
|
event: The input event data
|
|
@@ -584,7 +604,21 @@ class InputManager:
|
|
|
584
604
|
click_type = event.click_type
|
|
585
605
|
topic = f"{topic_prefix}/input/{input_id}"
|
|
586
606
|
|
|
587
|
-
if input_type == INPUT:
|
|
607
|
+
if input_type == INPUT:
|
|
608
|
+
# Check if this is a sequence event that requires mqtt_sequences config
|
|
609
|
+
if click_type in self.SEQUENCE_CLICK_TYPES:
|
|
610
|
+
_LOGGER.debug(
|
|
611
|
+
"Sequence event %s on %s, mqtt_sequences=%s, should_publish=%s",
|
|
612
|
+
click_type, input_id, input_instance.mqtt_sequences,
|
|
613
|
+
input_instance.should_publish_sequence_to_mqtt(click_type)
|
|
614
|
+
)
|
|
615
|
+
if not input_instance.should_publish_sequence_to_mqtt(click_type):
|
|
616
|
+
_LOGGER.debug(
|
|
617
|
+
"Skipping MQTT publish for sequence %s on %s (not enabled in mqtt_sequences)",
|
|
618
|
+
click_type, input_id
|
|
619
|
+
)
|
|
620
|
+
return
|
|
621
|
+
|
|
588
622
|
event_payload: dict[str, str | float | None] = {"event_type": click_type}
|
|
589
623
|
if event.duration is not None:
|
|
590
624
|
event_payload["duration"] = round(event.duration, 3)
|
|
@@ -671,6 +705,8 @@ class InputManager:
|
|
|
671
705
|
device_class=getattr(input_device, '_device_class', None),
|
|
672
706
|
availability_msg_func=ha_event_availabilty_message,
|
|
673
707
|
area=input_area,
|
|
708
|
+
mqtt_sequences=input_device.mqtt_sequences,
|
|
709
|
+
enable_triple_click=getattr(input_device._detector, '_enable_triple_click', False),
|
|
674
710
|
)
|
|
675
711
|
elif isinstance(input_device, GpioInputBinarySensor):
|
|
676
712
|
self._manager.send_ha_autodiscovery(
|
|
@@ -766,6 +766,7 @@ class Manager:
|
|
|
766
766
|
"virtual_energy_sensor": self.sensors.reload_virtual_energy_sensors, # Virtual energy sensors
|
|
767
767
|
"logger": self._reload_logger, # Logger configuration
|
|
768
768
|
"remote_devices": self._reload_remote_devices, # Remote devices configuration
|
|
769
|
+
"areas": lambda: None, # Areas are already reloaded in reload_config above
|
|
769
770
|
}
|
|
770
771
|
|
|
771
772
|
# If specific sections requested, filter
|
|
@@ -920,6 +921,17 @@ class Manager:
|
|
|
920
921
|
await cover.set_cover_position(position)
|
|
921
922
|
except ValueError:
|
|
922
923
|
_LOGGER.warning("Invalid cover position value: %s", message)
|
|
924
|
+
elif command == "tilt":
|
|
925
|
+
# Set cover tilt position (only for VenetianCover)
|
|
926
|
+
from boneio.components.cover.venetian import VenetianCover
|
|
927
|
+
if isinstance(cover, VenetianCover):
|
|
928
|
+
try:
|
|
929
|
+
tilt = int(message)
|
|
930
|
+
await cover.set_tilt(tilt)
|
|
931
|
+
except ValueError:
|
|
932
|
+
_LOGGER.warning("Invalid cover tilt value: %s", message)
|
|
933
|
+
else:
|
|
934
|
+
_LOGGER.debug("Cover %s does not support tilt control", device_id)
|
|
923
935
|
else:
|
|
924
936
|
# Handle open/close/stop/toggle actions
|
|
925
937
|
action = cover_actions.get(message.upper())
|
|
@@ -317,7 +317,7 @@ class HostData:
|
|
|
317
317
|
return None
|
|
318
318
|
network_state = self._data[NETWORK].state
|
|
319
319
|
if IP in network_state:
|
|
320
|
-
return f"{self._manager.config_helper.http_proto}://{network_state[IP]}:{self._manager.config_helper.
|
|
320
|
+
return f"{self._manager.config_helper.http_proto}://{network_state[IP]}:{self._manager.config_helper.web_configuration_port}"
|
|
321
321
|
return None
|
|
322
322
|
|
|
323
323
|
def get(self, type: str) -> dict | str | None:
|
|
@@ -76,6 +76,11 @@ class GpioBaseClass:
|
|
|
76
76
|
self._event_bus = event_bus
|
|
77
77
|
self._event_lock = asyncio.Lock()
|
|
78
78
|
self.area: str | None = None # HA area/room assignment
|
|
79
|
+
# MQTT sequences configuration - which sequences to publish to MQTT
|
|
80
|
+
mqtt_seq = kwargs.get("mqtt_sequences")
|
|
81
|
+
self._mqtt_sequences: dict[str, bool] = mqtt_seq if isinstance(mqtt_seq, dict) else {}
|
|
82
|
+
# Sequence mode: 'immediate' (default) or 'exclusive'
|
|
83
|
+
self._sequence_mode: str = kwargs.get("sequence_mode", "immediate")
|
|
79
84
|
|
|
80
85
|
@property
|
|
81
86
|
def boneio_input(self) -> str:
|
|
@@ -222,3 +227,32 @@ class GpioBaseClass:
|
|
|
222
227
|
Unix timestamp
|
|
223
228
|
"""
|
|
224
229
|
return self._last_timestamp
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def mqtt_sequences(self) -> dict[str, bool]:
|
|
233
|
+
"""Get MQTT sequences configuration.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Dictionary mapping sequence types to boolean (publish to MQTT or not)
|
|
237
|
+
"""
|
|
238
|
+
return self._mqtt_sequences
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def sequence_mode(self) -> str:
|
|
242
|
+
"""Get sequence mode.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
'immediate' or 'exclusive'
|
|
246
|
+
"""
|
|
247
|
+
return self._sequence_mode
|
|
248
|
+
|
|
249
|
+
def should_publish_sequence_to_mqtt(self, sequence_type: str) -> bool:
|
|
250
|
+
"""Check if a sequence type should be published to MQTT.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
sequence_type: Type of sequence (e.g., 'double_then_long')
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
True if the sequence should be published to MQTT
|
|
257
|
+
"""
|
|
258
|
+
return self._mqtt_sequences.get(sequence_type, False)
|