boneIO 0.11.0.dev6__tar.gz → 0.11.0.dev8__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-0.11.0.dev6 → boneio-0.11.0.dev8}/PKG-INFO +1 -1
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/ha_discovery.py +1 -1
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/loader.py +29 -5
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/yaml_util.py +38 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/manager.py +8 -6
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/mqtt.py +3 -3
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/client.py +68 -65
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sensor.py +3 -3
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/oled.py +8 -8
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/basic.py +164 -95
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/runner.py +6 -8
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/actions.yaml +1 -1
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/schema.yaml +8 -0
- boneio-0.11.0.dev8/boneio/version.py +2 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/binary_sensor.schema.json +2 -2
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/config.schema.json +14 -5
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/event.schema.json +3 -3
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/output.schema.json +9 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/pyproject.toml +2 -2
- boneio-0.11.0.dev6/boneio/version.py +0 -2
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/LICENSE +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/README.md +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/bonecli.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/const.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/cover.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/previous.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/time_based.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/venetian.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/fonts/danube__.ttf +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/group/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/group/output.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/async_updater.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/click_timer.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/config.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/events.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/exceptions.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/filter.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/gpio.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/gpiod.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/interlock.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/logger.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/mqtt.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/oled.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/W1ThermSensor.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/ds2482.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/onewire.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/pcf8575.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/queue.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/schema_converter.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/sensor/ina_219_smbus.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/state_manager.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/stats.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/timeperiod.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/util.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/input/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/input/gpio.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/input/gpio_new.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/basic.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/local.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/cwt.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/dts1964_3f.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/liquid-sensor.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/modbuscli.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/orno-or-we-517.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/pt100.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/r4dcb08.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sdm120.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sdm630.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sht20.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sht30.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/single_sensor.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/socomec_e03.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/socomec_e23.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sofar.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/utils.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/models/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/models/files.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/models/logs.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/gpio.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/mcp.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/pca.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/pcf.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/filters.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/id.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/update_interval.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/adc.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/gpio.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/gpio_new.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/ina219.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/serial_number.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/__init__.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/dallas.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/lm75.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/mcp9808.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/app.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/abap-BrgZPUOV.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/apex-DyP6w7ZV.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/azcli-BaLxmfj-.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/bat-CFOPXBzS.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/bicep-BfEKNvv3.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cameligo-BFG1Mk7z.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/clojure-DTECt2xU.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/coffee-CDGzqUPQ.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cpp-CLLBncYj.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/csharp-dUCx_-0o.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/csp-5Rap-vPy.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/css-D3h14YRZ.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cssMode-C5afUc0K.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cypher-DrQuvNYM.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/dart-CFKIUWau.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/dockerfile-Zznr-cwX.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ecl-Ce3n6wWz.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/editor.worker-oRlJJsnX.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/elixir-deUWdS0T.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/flow9-i9-g7ZhI.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/freemarker2-emRcpycN.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/fsharp-CzKuDChf.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/go-Cphgjts3.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/graphql-Cg7bfA9N.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/handlebars-mMSD-c9g.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/hcl-0cvrggvQ.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/html-Clq5L_-r.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/htmlMode-CYqwdxDX.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/index-BcJKL9Rz.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/index-DzcnWIxb.css +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ini-Drc7WvVn.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/java-B_fMsGYe.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/javascript-BR7Nbw1G.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/json.worker-BnUULff4.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/jsonMode-aJvzz7xf.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/julia-Bqgm2twL.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/kotlin-BSkB5QuD.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/less-BsTHnhdd.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/lexon-YWi4-JPR.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/liquid-BNyvmcbu.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/lua-nf6ki56Z.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/m3-Cpb6xl2v.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/markdown-DSZPf7rp.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mdx-pWhQfMuK.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mips-B_c3zf-v.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/msdax-rUNN04Wq.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mysql-DDwshQtU.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/objective-c-B5zXfXm9.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pascal-CXOwvkN_.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pascaligo-Bc-ZgV77.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/perl-CwNk8-XU.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pgsql-tGk8EFnU.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/php-CpIb_Oan.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pla-B03wrqEc.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/postiats-BKlk5iyT.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/powerquery-Bhzvs7bI.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/powershell-Dd3NCNK9.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/protobuf-COyEY5Pt.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pug-BaJupSGV.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/python-CVtAQrrC.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/qsharp-DXyYeYxl.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/r-CdQndTaG.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/razor-BBiV-C6e.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/redis-CVwtpugi.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/redshift-25W9uPmb.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/restructuredtext-DfzH4Xui.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ruby-Cp1zYvxS.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/rust-D5C2fndG.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sb-CDntyWJ8.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scala-BoFRg7Ot.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scheme-Bio4gycK.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scss-4Ik7cdeQ.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/shell-CX-rkNHf.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/solidity-Tw7wswEv.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sophia-C5WLch3f.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sparql-DHaeiCBh.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sql-CCSDG5nI.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/st-pnP8ivHi.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/swift-DwJ7jVG9.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/systemverilog-B9Xyijhd.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/tcl-DnHyzjbg.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/tsMode-COZIvtMx.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/twig-CPajHgWi.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/typescript-DKdGc2VX.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/typespec-D-MeaMDU.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/vb-DgyLZaXg.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/wgsl-BIv9DU6q.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/xml-CTK9ybeu.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/yaml-ggTgJ1wa.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/yaml.worker-DSHdx_mx.js +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/index.html +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/boneio.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/modbus_sensors.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/mqtt.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/web.schema.json +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/web_server.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/websocket_manager.py +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/tests/32_5_config.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/tests/bandit.yaml +0 -0
- {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/tests/relay_32_5.py +0 -0
|
@@ -228,7 +228,7 @@ def modbus_sensor_availabilty_message(
|
|
|
228
228
|
):
|
|
229
229
|
"""Create Modbus Sensor availability topic for HA."""
|
|
230
230
|
return {
|
|
231
|
-
"availability": [{"topic": f"{topic}/{id}{STATE}"}],
|
|
231
|
+
"availability": [{"topic": f"{topic}/{id}/{STATE}"}],
|
|
232
232
|
"device": {
|
|
233
233
|
"identifiers": [id],
|
|
234
234
|
"manufacturer": "boneIO",
|
|
@@ -235,7 +235,6 @@ def create_modbus_sensors(manager: Manager, message_bus: MessageBus, sensors, **
|
|
|
235
235
|
for sensor in sensors:
|
|
236
236
|
name = sensor.get(ID)
|
|
237
237
|
id = name.replace(" ", "")
|
|
238
|
-
print("name to check", name)
|
|
239
238
|
additional_data = sensor.get("data", {})
|
|
240
239
|
try:
|
|
241
240
|
modbus_sensors[id.lower()] = ModbusSensor(
|
|
@@ -364,8 +363,8 @@ def configure_relay(
|
|
|
364
363
|
"output_type": output_type,
|
|
365
364
|
}
|
|
366
365
|
elif output_kind == GPIO:
|
|
367
|
-
if GPIO not in manager.
|
|
368
|
-
manager.
|
|
366
|
+
if GPIO not in manager.grouped_outputs_by_expander:
|
|
367
|
+
manager.grouped_outputs_by_expander[GPIO] = {}
|
|
369
368
|
extra_args = {
|
|
370
369
|
"pin": config.pop(PIN),
|
|
371
370
|
}
|
|
@@ -392,8 +391,8 @@ def configure_relay(
|
|
|
392
391
|
**extra_args,
|
|
393
392
|
)
|
|
394
393
|
manager._interlock_manager.register(relay, interlock_groups)
|
|
395
|
-
manager.
|
|
396
|
-
if relay.
|
|
394
|
+
manager.grouped_outputs_by_expander[expander_id][relay_id] = relay
|
|
395
|
+
if relay.is_virtual_power:
|
|
397
396
|
manager.send_ha_autodiscovery(
|
|
398
397
|
id=f"{relay_id}_virtual_power",
|
|
399
398
|
relay_id=relay_id,
|
|
@@ -418,6 +417,31 @@ def configure_relay(
|
|
|
418
417
|
state_class="total_increasing",
|
|
419
418
|
value_template="{{ value_json.energy }}"
|
|
420
419
|
)
|
|
420
|
+
if relay.is_virtual_volume_flow_rate:
|
|
421
|
+
manager.send_ha_autodiscovery(
|
|
422
|
+
id=f"{relay_id}_virtual_volume_flow_rate",
|
|
423
|
+
relay_id=relay_id,
|
|
424
|
+
name=f"{name} Virtual Volume Flow Rate",
|
|
425
|
+
ha_type="sensor",
|
|
426
|
+
device_type="energy",
|
|
427
|
+
availability_msg_func=ha_virtual_energy_sensor_discovery_message,
|
|
428
|
+
unit_of_measurement="L/h",
|
|
429
|
+
device_class="volume_flow_rate",
|
|
430
|
+
state_class="measurement",
|
|
431
|
+
value_template="{{ value_json.volume_flow_rate }}"
|
|
432
|
+
)
|
|
433
|
+
manager.send_ha_autodiscovery(
|
|
434
|
+
id=f"{relay_id}_virtual_consumption",
|
|
435
|
+
relay_id=relay_id,
|
|
436
|
+
name=f"{name} Virtual consumption",
|
|
437
|
+
ha_type="sensor",
|
|
438
|
+
device_type="energy",
|
|
439
|
+
availability_msg_func=ha_virtual_energy_sensor_discovery_message,
|
|
440
|
+
unit_of_measurement="L",
|
|
441
|
+
device_class="water",
|
|
442
|
+
state_class="total_increasing",
|
|
443
|
+
value_template="{{ value_json.water }}"
|
|
444
|
+
)
|
|
421
445
|
return relay
|
|
422
446
|
|
|
423
447
|
|
|
@@ -618,6 +618,44 @@ class CustomValidator(Validator):
|
|
|
618
618
|
_LOGGER.debug(f"Parsed power value '{value}' as {result} W")
|
|
619
619
|
return result
|
|
620
620
|
|
|
621
|
+
def _normalize_coerce_volume_flow_rate_to_lph(self, value):
|
|
622
|
+
"""
|
|
623
|
+
Parse a volume flow rate value and return it in liters per minute (L/min).
|
|
624
|
+
Accepts:
|
|
625
|
+
- Numeric values (int, float)
|
|
626
|
+
- Strings with units: 'L/min', 'L/h', etc.
|
|
627
|
+
Example:
|
|
628
|
+
9 -> 9.0
|
|
629
|
+
'9L/min' -> 9.0
|
|
630
|
+
'1L/h' -> 1000.0
|
|
631
|
+
Returns float (L/h) or raises ValueError if invalid.
|
|
632
|
+
"""
|
|
633
|
+
if value is None:
|
|
634
|
+
return None
|
|
635
|
+
if isinstance(value, (int, float)):
|
|
636
|
+
return float(value)
|
|
637
|
+
if not isinstance(value, str):
|
|
638
|
+
raise ValueError(f"Unsupported type for volume flow rate value: {type(value)}")
|
|
639
|
+
value = value.strip().replace(' ', '').lower()
|
|
640
|
+
pattern = r"^([-+]?[0-9]*\.?[0-9]+)\s*([a-zA-Z/]*)$"
|
|
641
|
+
match = re.match(pattern, value)
|
|
642
|
+
if not match:
|
|
643
|
+
_LOGGER.warning(f"Could not parse volume flow rate value: {value}")
|
|
644
|
+
raise ValueError(f"Could not parse volume flow rate value: {value}")
|
|
645
|
+
num, unit = match.groups()
|
|
646
|
+
num = float(num)
|
|
647
|
+
multiplier = 1.0
|
|
648
|
+
if unit in ('lph', 'l/h', ''):
|
|
649
|
+
multiplier = 1.0
|
|
650
|
+
elif unit in ('lpm', 'l/min'):
|
|
651
|
+
multiplier = 60.0
|
|
652
|
+
else:
|
|
653
|
+
_LOGGER.warning(f"Unknown unit for volume flow rate value: {unit}")
|
|
654
|
+
raise ValueError(f"Unknown unit for volume flow rate value: {unit}")
|
|
655
|
+
result = num * multiplier
|
|
656
|
+
_LOGGER.debug(f"Parsed volume flow rate value '{value}' as {result} L/h")
|
|
657
|
+
return result
|
|
658
|
+
|
|
621
659
|
|
|
622
660
|
|
|
623
661
|
def load_config_from_string(config_str: str) -> dict:
|
|
@@ -176,13 +176,13 @@ class Manager:
|
|
|
176
176
|
dallas=dallas, ds2482=ds2482, sensors=sensors.get(ONEWIRE)
|
|
177
177
|
)
|
|
178
178
|
|
|
179
|
-
self.
|
|
179
|
+
self.grouped_outputs_by_expander = create_expander(
|
|
180
180
|
expander_dict=self._mcp,
|
|
181
181
|
expander_config=mcp23017,
|
|
182
182
|
exp_type=MCP,
|
|
183
183
|
i2cbusio=self._i2cbusio,
|
|
184
184
|
)
|
|
185
|
-
self.
|
|
185
|
+
self.grouped_outputs_by_expander.update(
|
|
186
186
|
create_expander(
|
|
187
187
|
expander_dict=self._pcf,
|
|
188
188
|
expander_config=pcf8575,
|
|
@@ -190,7 +190,7 @@ class Manager:
|
|
|
190
190
|
i2cbusio=self._i2cbusio,
|
|
191
191
|
)
|
|
192
192
|
)
|
|
193
|
-
self.
|
|
193
|
+
self.grouped_outputs_by_expander.update(
|
|
194
194
|
create_expander(
|
|
195
195
|
expander_dict=self._pca,
|
|
196
196
|
expander_config=pca9685,
|
|
@@ -205,6 +205,7 @@ class Manager:
|
|
|
205
205
|
_name = _config.pop(ID)
|
|
206
206
|
restore_state = _config.pop(RESTORE_STATE, False)
|
|
207
207
|
_id = strip_accents(_name)
|
|
208
|
+
_LOGGER.debug("Configuring relay: %s", _id)
|
|
208
209
|
out = configure_relay( # grouped_output updated here.
|
|
209
210
|
manager=self,
|
|
210
211
|
message_bus=message_bus,
|
|
@@ -236,7 +237,8 @@ class Manager:
|
|
|
236
237
|
)
|
|
237
238
|
self._loop.create_task(self._delayed_send_state(out))
|
|
238
239
|
|
|
239
|
-
self.
|
|
240
|
+
if self._outputs:
|
|
241
|
+
self._configure_covers()
|
|
240
242
|
|
|
241
243
|
self._outputs_group = output_group
|
|
242
244
|
self._configure_output_group()
|
|
@@ -261,7 +263,7 @@ class Manager:
|
|
|
261
263
|
manager=self,
|
|
262
264
|
event_bus=self._event_bus,
|
|
263
265
|
enabled_screens=self._screens,
|
|
264
|
-
output=self.
|
|
266
|
+
output=self.grouped_outputs_by_expander,
|
|
265
267
|
inputs=self._inputs,
|
|
266
268
|
temp_sensor=(self._temp_sensors[0] if self._temp_sensors else None),
|
|
267
269
|
ina219=(self._ina219_sensors[0] if self._ina219_sensors else None),
|
|
@@ -271,7 +273,7 @@ class Manager:
|
|
|
271
273
|
self._oled = Oled(
|
|
272
274
|
host_data=self._host_data,
|
|
273
275
|
screen_order=self._screens,
|
|
274
|
-
|
|
276
|
+
grouped_outputs_by_expander=list(self.grouped_outputs_by_expander),
|
|
275
277
|
sleep_timeout=oled.get("screensaver_timeout", 60),
|
|
276
278
|
event_bus=self._event_bus,
|
|
277
279
|
)
|
|
@@ -128,6 +128,7 @@ class MQTTClient(MessageBus):
|
|
|
128
128
|
params["properties"] = properties
|
|
129
129
|
|
|
130
130
|
# e.g. subscribe([("my/topic", SubscribeOptions(qos=0), ("another/topic", SubscribeOptions(qos=2)])
|
|
131
|
+
_LOGGER.debug("Subscribing to %s", args)
|
|
131
132
|
await self.asyncio_client.subscribe(
|
|
132
133
|
topic=args, **params, timeout=timeout
|
|
133
134
|
)
|
|
@@ -250,9 +251,8 @@ class MQTTClient(MessageBus):
|
|
|
250
251
|
cancel_task = asyncio.create_task(wait_for_cancel())
|
|
251
252
|
tasks.add(cancel_task)
|
|
252
253
|
|
|
253
|
-
|
|
254
|
-
await self.subscribe(topics=
|
|
255
|
-
await self.subscribe(topics=self._discovery_topics)
|
|
254
|
+
topics = self._topics + list(self._mqtt_energy_listeners.keys()) + self._discovery_topics
|
|
255
|
+
await self.subscribe(topics=topics)
|
|
256
256
|
|
|
257
257
|
# Wait for everything to complete (or fail due to, e.g., network errors).
|
|
258
258
|
await asyncio.gather(*tasks)
|
|
@@ -138,28 +138,27 @@ class Modbus:
|
|
|
138
138
|
|
|
139
139
|
async def async_close(self) -> None:
|
|
140
140
|
"""Disconnect client."""
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
_LOGGER.warning("modbus communication closed")
|
|
141
|
+
if self._client:
|
|
142
|
+
try:
|
|
143
|
+
# Run close in the executor
|
|
144
|
+
await self._loop.run_in_executor(self._executor, self._client.close)
|
|
145
|
+
except asyncio.CancelledError:
|
|
146
|
+
_LOGGER.warning("modbus communication closed")
|
|
147
|
+
pass
|
|
148
|
+
except ModbusException as exception_error:
|
|
149
|
+
_LOGGER.error(exception_error)
|
|
150
|
+
finally:
|
|
151
|
+
del self._client
|
|
152
|
+
self._client = None
|
|
153
|
+
self._executor.shutdown(wait=False)
|
|
154
|
+
_LOGGER.warning("modbus communication closed")
|
|
156
155
|
|
|
157
156
|
def _pymodbus_connect(self) -> bool:
|
|
158
157
|
"""Connect client."""
|
|
159
158
|
try:
|
|
160
159
|
return self._client.connect() # type: ignore[union-attr]
|
|
161
160
|
except ModbusException as exception_error:
|
|
162
|
-
_LOGGER.error(exception_error)
|
|
161
|
+
_LOGGER.error(f"No connection to Modbus: {exception_error}")
|
|
163
162
|
return False
|
|
164
163
|
|
|
165
164
|
async def read_and_decode(
|
|
@@ -181,6 +180,58 @@ class Modbus:
|
|
|
181
180
|
)
|
|
182
181
|
return decoded_value
|
|
183
182
|
|
|
183
|
+
def read_registers_blocking(self, unit: int | str, address: int, count: int = 2, method: str = "input") -> ModbusResponse:
|
|
184
|
+
start_time = time.perf_counter()
|
|
185
|
+
result = None
|
|
186
|
+
kwargs = {"unit": unit, "count": count} if unit else {}
|
|
187
|
+
read_method = self._read_methods[method]
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
# Run connection in the executor
|
|
191
|
+
connected = self._pymodbus_connect()
|
|
192
|
+
if not connected:
|
|
193
|
+
_LOGGER.error("Can't connect to Modbus.")
|
|
194
|
+
return None
|
|
195
|
+
|
|
196
|
+
_LOGGER.debug(
|
|
197
|
+
"Reading %s registers from %s with method %s from device %s.",
|
|
198
|
+
count,
|
|
199
|
+
address,
|
|
200
|
+
method,
|
|
201
|
+
unit,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Run the read operation in the executor
|
|
205
|
+
result: ReadInputRegistersResponse = read_method(address, **kwargs)
|
|
206
|
+
|
|
207
|
+
if not hasattr(result, REGISTERS):
|
|
208
|
+
_LOGGER.error("No result from read: %s", str(result))
|
|
209
|
+
result = None
|
|
210
|
+
|
|
211
|
+
except ValueError as exception_error:
|
|
212
|
+
_LOGGER.error("Error reading registers: %s", exception_error)
|
|
213
|
+
pass
|
|
214
|
+
except (ModbusException, struct.error) as exception_error:
|
|
215
|
+
_LOGGER.error("Error reading registers: %s", exception_error)
|
|
216
|
+
pass
|
|
217
|
+
except asyncio.TimeoutError:
|
|
218
|
+
_LOGGER.error("Timeout reading registers from device %s", unit)
|
|
219
|
+
pass
|
|
220
|
+
except asyncio.CancelledError as err:
|
|
221
|
+
_LOGGER.error("Operation cancelled reading registers from device %s with error %s", unit, err)
|
|
222
|
+
pass
|
|
223
|
+
except Exception as e:
|
|
224
|
+
_LOGGER.error(f"Unexpected error reading registers: {type(e).__name__} - {e}")
|
|
225
|
+
pass
|
|
226
|
+
finally:
|
|
227
|
+
end_time = time.perf_counter()
|
|
228
|
+
_LOGGER.debug(
|
|
229
|
+
"Read completed in %.3f seconds: %s",
|
|
230
|
+
end_time - start_time,
|
|
231
|
+
result.registers if hasattr(result, REGISTERS) else None,
|
|
232
|
+
)
|
|
233
|
+
return result
|
|
234
|
+
|
|
184
235
|
async def read_registers(
|
|
185
236
|
self,
|
|
186
237
|
unit: int | str, # device address
|
|
@@ -190,56 +241,8 @@ class Modbus:
|
|
|
190
241
|
) -> ModbusResponse:
|
|
191
242
|
"""Call async pymodbus."""
|
|
192
243
|
async with self._lock:
|
|
193
|
-
|
|
194
|
-
result = None
|
|
244
|
+
return await self._loop.run_in_executor(self._executor, self.read_registers_blocking, unit, address, count, method)
|
|
195
245
|
|
|
196
|
-
try:
|
|
197
|
-
# Run connection in the executor
|
|
198
|
-
connected = self._pymodbus_connect()
|
|
199
|
-
if not connected:
|
|
200
|
-
_LOGGER.error("Can't connect to Modbus.")
|
|
201
|
-
return None
|
|
202
|
-
|
|
203
|
-
kwargs = {"unit": unit, "count": count} if unit else {}
|
|
204
|
-
read_method = self._read_methods[method]
|
|
205
|
-
_LOGGER.debug(
|
|
206
|
-
"Reading %s registers from %s with method %s from device %s.",
|
|
207
|
-
count,
|
|
208
|
-
address,
|
|
209
|
-
method,
|
|
210
|
-
unit,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
# Run the read operation in the executor
|
|
214
|
-
result: ReadInputRegistersResponse = await self._loop.run_in_executor(
|
|
215
|
-
self._executor,
|
|
216
|
-
lambda: read_method(address, **kwargs)
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
if not hasattr(result, REGISTERS):
|
|
220
|
-
_LOGGER.error("No result from read: %s", str(result))
|
|
221
|
-
result = None
|
|
222
|
-
|
|
223
|
-
except (ModbusException, struct.error) as exception_error:
|
|
224
|
-
_LOGGER.error("Error reading registers: %s", exception_error)
|
|
225
|
-
pass
|
|
226
|
-
except asyncio.TimeoutError:
|
|
227
|
-
_LOGGER.error("Timeout reading registers from device %s", unit)
|
|
228
|
-
pass
|
|
229
|
-
except asyncio.CancelledError as err:
|
|
230
|
-
_LOGGER.error("Operation cancelled reading registers from device %s with error %s", unit, err)
|
|
231
|
-
pass
|
|
232
|
-
except Exception as e:
|
|
233
|
-
_LOGGER.error(f"Unexpected error reading registers: {type(e).__name__} - {e}")
|
|
234
|
-
pass
|
|
235
|
-
finally:
|
|
236
|
-
end_time = time.perf_counter()
|
|
237
|
-
_LOGGER.debug(
|
|
238
|
-
"Read completed in %.3f seconds: %s",
|
|
239
|
-
end_time - start_time,
|
|
240
|
-
result.registers if hasattr(result, REGISTERS) else None,
|
|
241
|
-
)
|
|
242
|
-
return result
|
|
243
246
|
|
|
244
247
|
def decode_value(self, payload, value_type):
|
|
245
248
|
_payload_type = VALUE_TYPES[value_type]
|
|
@@ -73,7 +73,6 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
73
73
|
self._additional_sensors: List[Dict[str, SingleAdditionalSensor]] = []
|
|
74
74
|
self._additional_sensors_by_source_name: Dict[str, List[SingleAdditionalSensor]] = {}
|
|
75
75
|
self._additional_data = additional_data
|
|
76
|
-
print("aaa", additional_data)
|
|
77
76
|
# Standard sensors
|
|
78
77
|
for index, data in enumerate(self._db[REGISTERS_BASE]):
|
|
79
78
|
base = data[BASE]
|
|
@@ -253,7 +252,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
253
252
|
)
|
|
254
253
|
self._payload_online = ONLINE
|
|
255
254
|
self._message_bus.send_message(
|
|
256
|
-
topic=f"{self._config_helper.topic_prefix}/{self._id}{STATE}",
|
|
255
|
+
topic=f"{self._config_helper.topic_prefix}/{self._id}/{STATE}",
|
|
257
256
|
payload=self._payload_online,
|
|
258
257
|
)
|
|
259
258
|
if not values:
|
|
@@ -264,7 +263,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
264
263
|
# Let's assume device is offline.
|
|
265
264
|
self.set_payload_offline()
|
|
266
265
|
self._message_bus.send_message(
|
|
267
|
-
topic=f"{self._config_helper.topic_prefix}/{self._id}{STATE}",
|
|
266
|
+
topic=f"{self._config_helper.topic_prefix}/{self._id}/{STATE}",
|
|
268
267
|
payload=self._payload_online,
|
|
269
268
|
)
|
|
270
269
|
self._discovery_sent = False
|
|
@@ -329,6 +328,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
329
328
|
timestamp=sensor.last_timestamp,
|
|
330
329
|
),
|
|
331
330
|
)
|
|
331
|
+
|
|
332
332
|
self._timestamp = timestamp
|
|
333
333
|
self._message_bus.send_message(
|
|
334
334
|
topic=f"{self._send_topic}/{data[BASE]}",
|
|
@@ -54,7 +54,7 @@ class Oled:
|
|
|
54
54
|
def __init__(
|
|
55
55
|
self,
|
|
56
56
|
host_data: HostData,
|
|
57
|
-
|
|
57
|
+
grouped_outputs_by_expander: List[str],
|
|
58
58
|
sleep_timeout: TimePeriod,
|
|
59
59
|
screen_order: List[str],
|
|
60
60
|
event_bus: EventBus
|
|
@@ -62,19 +62,19 @@ class Oled:
|
|
|
62
62
|
"""Initialize OLED screen."""
|
|
63
63
|
self._loop = asyncio.get_running_loop()
|
|
64
64
|
self._event_bus = event_bus
|
|
65
|
-
self.
|
|
65
|
+
self.grouped_outputs_by_expander = None
|
|
66
66
|
self._input_groups = []
|
|
67
67
|
self._host_data = host_data
|
|
68
68
|
|
|
69
69
|
def configure_outputs() -> None:
|
|
70
70
|
try:
|
|
71
71
|
_ind_screen = screen_order.index("outputs")
|
|
72
|
-
if not
|
|
72
|
+
if not grouped_outputs_by_expander:
|
|
73
73
|
_LOGGER.debug("No outputs configured. Omitting in screen.")
|
|
74
74
|
return
|
|
75
75
|
screen_order.pop(_ind_screen)
|
|
76
|
-
screen_order[_ind_screen:_ind_screen] =
|
|
77
|
-
self.
|
|
76
|
+
screen_order[_ind_screen:_ind_screen] = grouped_outputs_by_expander
|
|
77
|
+
self.grouped_outputs_by_expander = grouped_outputs_by_expander
|
|
78
78
|
except ValueError:
|
|
79
79
|
pass
|
|
80
80
|
|
|
@@ -216,8 +216,8 @@ class Oled:
|
|
|
216
216
|
else:
|
|
217
217
|
with canvas(self._device) as draw:
|
|
218
218
|
if (
|
|
219
|
-
self.
|
|
220
|
-
and self._current_screen in self.
|
|
219
|
+
self.grouped_outputs_by_expander
|
|
220
|
+
and self._current_screen in self.grouped_outputs_by_expander
|
|
221
221
|
):
|
|
222
222
|
self._draw_output(data, draw)
|
|
223
223
|
for id in data.keys():
|
|
@@ -245,7 +245,7 @@ class Oled:
|
|
|
245
245
|
)
|
|
246
246
|
|
|
247
247
|
async def _output_callback(self, event: OutputState):
|
|
248
|
-
if self.
|
|
248
|
+
if self.grouped_outputs_by_expander and self._current_screen in self.grouped_outputs_by_expander:
|
|
249
249
|
self.handle_data_update(type=self._current_screen)
|
|
250
250
|
|
|
251
251
|
async def _standard_callback(self, event: SensorState):
|