boneIO 0.11.0.dev5__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.dev5 → boneio-0.11.0.dev8}/PKG-INFO +1 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/const.py +2 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/config.py +18 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/filter.py +3 -2
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/ha_discovery.py +2 -2
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/loader.py +31 -4
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/util.py +26 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/yaml_util.py +72 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/manager.py +80 -53
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/message_bus/mqtt.py +3 -3
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/client.py +68 -65
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/liquid-sensor.json +11 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/sensor.py +82 -3
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/single_sensor.py +50 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/oled.py +8 -8
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/relay/basic.py +164 -95
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/runner.py +17 -15
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/actions.yaml +13 -11
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/schema.yaml +35 -2
- boneio-0.11.0.dev8/boneio/version.py +2 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/binary_sensor.schema.json +12 -8
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/config.schema.json +69 -21
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/event.schema.json +18 -12
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/modbus_sensors.schema.json +30 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/mqtt.schema.json +0 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/output.schema.json +9 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/pyproject.toml +2 -2
- boneio-0.11.0.dev5/boneio/version.py +0 -2
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/LICENSE +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/README.md +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/bonecli.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/cover/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/cover/cover.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/cover/previous.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/cover/time_based.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/cover/venetian.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/fonts/danube__.ttf +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/group/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/group/output.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/async_updater.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/click_timer.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/events.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/exceptions.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/gpiod.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/interlock.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/logger.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/mqtt.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/oled.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/onewire/W1ThermSensor.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/onewire/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/onewire/ds2482.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/onewire/onewire.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/pcf8575.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/queue.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/schema_converter.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/sensor/ina_219_smbus.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/state_manager.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/stats.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/helper/timeperiod.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/input/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/input/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/input/gpio_new.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/message_bus/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/message_bus/basic.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/message_bus/local.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/cwt.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/dts1964_3f.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/modbuscli.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/orno-or-we-517.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/pt100.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/r4dcb08.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/sdm120.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/sdm630.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/sht20.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/sht30.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/socomec_e03.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/socomec_e23.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/sofar.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/modbus/utils.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/models/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/models/files.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/models/logs.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/relay/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/relay/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/relay/mcp.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/relay/pca.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/relay/pcf.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/filters.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/id.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/schema/update_interval.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/adc.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/gpio_new.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/ina219.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/serial_number.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/temp/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/temp/dallas.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/temp/lm75.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/sensor/temp/mcp9808.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/app.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/abap-BrgZPUOV.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/apex-DyP6w7ZV.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/azcli-BaLxmfj-.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/bat-CFOPXBzS.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/bicep-BfEKNvv3.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cameligo-BFG1Mk7z.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/clojure-DTECt2xU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/coffee-CDGzqUPQ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cpp-CLLBncYj.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/csharp-dUCx_-0o.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/csp-5Rap-vPy.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/css-D3h14YRZ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cssMode-C5afUc0K.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cypher-DrQuvNYM.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/dart-CFKIUWau.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/dockerfile-Zznr-cwX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ecl-Ce3n6wWz.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/editor.worker-oRlJJsnX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/elixir-deUWdS0T.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/flow9-i9-g7ZhI.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/freemarker2-emRcpycN.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/fsharp-CzKuDChf.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/go-Cphgjts3.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/graphql-Cg7bfA9N.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/handlebars-mMSD-c9g.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/hcl-0cvrggvQ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/html-Clq5L_-r.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/htmlMode-CYqwdxDX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/index-BcJKL9Rz.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/index-DzcnWIxb.css +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ini-Drc7WvVn.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/java-B_fMsGYe.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/javascript-BR7Nbw1G.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/json.worker-BnUULff4.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/jsonMode-aJvzz7xf.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/julia-Bqgm2twL.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/kotlin-BSkB5QuD.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/less-BsTHnhdd.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/lexon-YWi4-JPR.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/liquid-BNyvmcbu.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/lua-nf6ki56Z.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/m3-Cpb6xl2v.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/markdown-DSZPf7rp.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mdx-pWhQfMuK.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mips-B_c3zf-v.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/msdax-rUNN04Wq.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mysql-DDwshQtU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/objective-c-B5zXfXm9.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pascal-CXOwvkN_.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pascaligo-Bc-ZgV77.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/perl-CwNk8-XU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pgsql-tGk8EFnU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/php-CpIb_Oan.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pla-B03wrqEc.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/postiats-BKlk5iyT.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/powerquery-Bhzvs7bI.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/powershell-Dd3NCNK9.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/protobuf-COyEY5Pt.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pug-BaJupSGV.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/python-CVtAQrrC.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/qsharp-DXyYeYxl.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/r-CdQndTaG.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/razor-BBiV-C6e.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/redis-CVwtpugi.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/redshift-25W9uPmb.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/restructuredtext-DfzH4Xui.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ruby-Cp1zYvxS.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/rust-D5C2fndG.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sb-CDntyWJ8.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scala-BoFRg7Ot.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scheme-Bio4gycK.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scss-4Ik7cdeQ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/shell-CX-rkNHf.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/solidity-Tw7wswEv.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sophia-C5WLch3f.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sparql-DHaeiCBh.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sql-CCSDG5nI.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/st-pnP8ivHi.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/swift-DwJ7jVG9.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/systemverilog-B9Xyijhd.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/tcl-DnHyzjbg.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/tsMode-COZIvtMx.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/twig-CPajHgWi.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/typescript-DKdGc2VX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/typespec-D-MeaMDU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/vb-DgyLZaXg.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/wgsl-BIv9DU6q.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/xml-CTK9ybeu.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/yaml-ggTgJ1wa.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/yaml.worker-DSHdx_mx.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/index.html +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/boneio.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/schema/web.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/web_server.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/boneio/webui/websocket_manager.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/tests/32_5_config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/tests/bandit.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev8}/tests/relay_32_5.py +0 -0
|
@@ -3,6 +3,7 @@ Module to provide basic config options.
|
|
|
3
3
|
"""
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
+
import logging
|
|
6
7
|
from _collections_abc import dict_values
|
|
7
8
|
from typing import Union
|
|
8
9
|
|
|
@@ -18,6 +19,9 @@ from boneio.const import (
|
|
|
18
19
|
SWITCH,
|
|
19
20
|
VALVE,
|
|
20
21
|
)
|
|
22
|
+
from boneio.helper.util import sanitize_mqtt_topic
|
|
23
|
+
|
|
24
|
+
_LOGGER = logging.getLogger(__name__)
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
class ConfigHelper:
|
|
@@ -28,9 +32,12 @@ class ConfigHelper:
|
|
|
28
32
|
device_type: str = "boneIO Black",
|
|
29
33
|
ha_discovery: bool = True,
|
|
30
34
|
ha_discovery_prefix: str = HOMEASSISTANT,
|
|
35
|
+
network_info: dict = None,
|
|
36
|
+
is_web_active: bool = False,
|
|
31
37
|
):
|
|
32
38
|
self._name = name
|
|
33
|
-
|
|
39
|
+
sanitized_topic_prefix = sanitize_mqtt_topic(topic_prefix) if topic_prefix else sanitize_mqtt_topic(name)
|
|
40
|
+
self._topic_prefix = sanitized_topic_prefix
|
|
34
41
|
self._ha_discovery = ha_discovery
|
|
35
42
|
self._ha_discovery_prefix = ha_discovery_prefix
|
|
36
43
|
self._device_type = device_type
|
|
@@ -46,6 +53,16 @@ class ConfigHelper:
|
|
|
46
53
|
VALVE: {},
|
|
47
54
|
}
|
|
48
55
|
self.manager_ready: bool = False
|
|
56
|
+
self._network_info = network_info
|
|
57
|
+
self._is_web_active = is_web_active
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def network_info(self) -> dict:
|
|
61
|
+
return self._network_info
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def is_web_active(self) -> bool:
|
|
65
|
+
return self._is_web_active
|
|
49
66
|
|
|
50
67
|
@property
|
|
51
68
|
def topic_prefix(self) -> str:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Filter class to adjust sensor values."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import logging
|
|
6
|
+
from typing import Optional
|
|
6
7
|
|
|
7
8
|
_LOGGER = logging.getLogger(__name__)
|
|
8
9
|
|
|
@@ -13,7 +14,7 @@ FILTERS = {
|
|
|
13
14
|
"multiply": lambda x, y: x * y if x else x,
|
|
14
15
|
"filter_out": lambda x, y: None if x == y else x,
|
|
15
16
|
"filter_out_greater": lambda x, y: None if x > y else x,
|
|
16
|
-
"filter_out_lower": lambda x, y: None if x < y else x
|
|
17
|
+
"filter_out_lower": lambda x, y: None if x < y else x
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
|
|
@@ -228,12 +228,12 @@ 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
235
|
"model": model,
|
|
236
|
-
"name":
|
|
236
|
+
"name": name,
|
|
237
237
|
"sw_version": __version__,
|
|
238
238
|
},
|
|
239
239
|
"name": sensor_id,
|
|
@@ -235,6 +235,7 @@ 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
|
+
additional_data = sensor.get("data", {})
|
|
238
239
|
try:
|
|
239
240
|
modbus_sensors[id.lower()] = ModbusSensor(
|
|
240
241
|
address=sensor[ADDRESS],
|
|
@@ -247,6 +248,7 @@ def create_modbus_sensors(manager: Manager, message_bus: MessageBus, sensors, **
|
|
|
247
248
|
UPDATE_INTERVAL, TimePeriod(seconds=60)
|
|
248
249
|
),
|
|
249
250
|
sensors_filters=sensor.get("sensors_filters", {}),
|
|
251
|
+
additional_data=additional_data,
|
|
250
252
|
**kwargs,
|
|
251
253
|
)
|
|
252
254
|
except FileNotFoundError as err:
|
|
@@ -361,8 +363,8 @@ def configure_relay(
|
|
|
361
363
|
"output_type": output_type,
|
|
362
364
|
}
|
|
363
365
|
elif output_kind == GPIO:
|
|
364
|
-
if GPIO not in manager.
|
|
365
|
-
manager.
|
|
366
|
+
if GPIO not in manager.grouped_outputs_by_expander:
|
|
367
|
+
manager.grouped_outputs_by_expander[GPIO] = {}
|
|
366
368
|
extra_args = {
|
|
367
369
|
"pin": config.pop(PIN),
|
|
368
370
|
}
|
|
@@ -389,8 +391,8 @@ def configure_relay(
|
|
|
389
391
|
**extra_args,
|
|
390
392
|
)
|
|
391
393
|
manager._interlock_manager.register(relay, interlock_groups)
|
|
392
|
-
manager.
|
|
393
|
-
if relay.
|
|
394
|
+
manager.grouped_outputs_by_expander[expander_id][relay_id] = relay
|
|
395
|
+
if relay.is_virtual_power:
|
|
394
396
|
manager.send_ha_autodiscovery(
|
|
395
397
|
id=f"{relay_id}_virtual_power",
|
|
396
398
|
relay_id=relay_id,
|
|
@@ -415,6 +417,31 @@ def configure_relay(
|
|
|
415
417
|
state_class="total_increasing",
|
|
416
418
|
value_template="{{ value_json.energy }}"
|
|
417
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
|
+
)
|
|
418
445
|
return relay
|
|
419
446
|
|
|
420
447
|
|
|
@@ -19,7 +19,7 @@ def is_callback(func: Callable[..., Any]) -> bool:
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def strip_accents(s):
|
|
22
|
-
|
|
22
|
+
"""Remove accents and spaces from a string."""
|
|
23
23
|
return "".join(
|
|
24
24
|
c
|
|
25
25
|
for c in unicodedata.normalize("NFD", s)
|
|
@@ -27,6 +27,31 @@ def strip_accents(s):
|
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
def sanitize_mqtt_topic(name: str) -> str:
|
|
31
|
+
"""
|
|
32
|
+
Sanitize a string to be used as an MQTT topic:
|
|
33
|
+
- Replace spaces with underscores
|
|
34
|
+
- Remove Polish diacritics
|
|
35
|
+
- Remove/replace forbidden characters (leave only a-z, A-Z, 0-9, '_', '-')
|
|
36
|
+
Args:
|
|
37
|
+
name (str): Input string
|
|
38
|
+
Returns:
|
|
39
|
+
str: Sanitized string
|
|
40
|
+
"""
|
|
41
|
+
import re
|
|
42
|
+
from .logger import _LOGGER
|
|
43
|
+
|
|
44
|
+
original = name
|
|
45
|
+
# Zamień spacje na podkreślenia
|
|
46
|
+
name = name.replace(' ', '_')
|
|
47
|
+
# Usuń polskie znaki
|
|
48
|
+
name = strip_accents(name)
|
|
49
|
+
# Zostaw tylko dozwolone znaki
|
|
50
|
+
name = re.sub(r'[^a-zA-Z0-9_-]', '', name)
|
|
51
|
+
_LOGGER.debug(f"Sanitized MQTT topic: '{original}' -> '{name}'")
|
|
52
|
+
return name
|
|
53
|
+
|
|
54
|
+
|
|
30
55
|
def open_json(path: str, model: str) -> dict:
|
|
31
56
|
"""Open json file."""
|
|
32
57
|
file = f"{os.path.join(path)}/{model}.json"
|
|
@@ -430,6 +430,40 @@ class CustomValidator(Validator):
|
|
|
430
430
|
def _normalize_coerce_actions_output(self, value):
|
|
431
431
|
return str(value).upper()
|
|
432
432
|
|
|
433
|
+
def _normalize_coerce_length_to_meters(self, value) -> float:
|
|
434
|
+
"""
|
|
435
|
+
Convert a length value to meters.
|
|
436
|
+
Accepts:
|
|
437
|
+
- Numeric values (int, float) - assumed to be in meters
|
|
438
|
+
- Strings with units: 'm', 'cm', 'mm'
|
|
439
|
+
Examples:
|
|
440
|
+
5 -> 5.0
|
|
441
|
+
'5m' -> 5.0
|
|
442
|
+
'500cm' -> 5.0
|
|
443
|
+
'2000mm' -> 2.0
|
|
444
|
+
"""
|
|
445
|
+
if value is None:
|
|
446
|
+
return None
|
|
447
|
+
if isinstance(value, (int, float)):
|
|
448
|
+
return float(value)
|
|
449
|
+
value = str(value).strip().lower()
|
|
450
|
+
match = re.match(r"^([-+]?[0-9]*\.?[0-9]*)\s*(m|cm|mm)?$", value)
|
|
451
|
+
if not match:
|
|
452
|
+
raise ValueError(f"Invalid length value: {value}")
|
|
453
|
+
num = float(match.group(1))
|
|
454
|
+
unit = match.group(2) or "m"
|
|
455
|
+
if unit == "m":
|
|
456
|
+
multiplier = 1.0
|
|
457
|
+
elif unit == "cm":
|
|
458
|
+
multiplier = 0.01
|
|
459
|
+
elif unit == "mm":
|
|
460
|
+
multiplier = 0.001
|
|
461
|
+
else:
|
|
462
|
+
raise ValueError(f"Unknown unit for length value: {unit}")
|
|
463
|
+
result = num * multiplier
|
|
464
|
+
_LOGGER.debug(f"Parsed length value '{value}' as {result} m")
|
|
465
|
+
return result
|
|
466
|
+
|
|
433
467
|
def _normalize_coerce_positive_time_period(self, value) -> TimePeriod:
|
|
434
468
|
"""Validate and transform time period with time unit and integer value."""
|
|
435
469
|
if isinstance(value, int):
|
|
@@ -529,7 +563,6 @@ class CustomValidator(Validator):
|
|
|
529
563
|
'2.5MW' -> 2500000.0
|
|
530
564
|
Returns float (watts) or raises ValueError if invalid.
|
|
531
565
|
"""
|
|
532
|
-
import re
|
|
533
566
|
if value is None:
|
|
534
567
|
return None
|
|
535
568
|
if isinstance(value, (int, float)):
|
|
@@ -585,6 +618,44 @@ class CustomValidator(Validator):
|
|
|
585
618
|
_LOGGER.debug(f"Parsed power value '{value}' as {result} W")
|
|
586
619
|
return result
|
|
587
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
|
+
|
|
588
659
|
|
|
589
660
|
|
|
590
661
|
def load_config_from_string(config_str: str) -> dict:
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
5
|
from collections import deque
|
|
6
|
-
from typing import Callable, Coroutine, List, Optional, Set
|
|
6
|
+
from typing import Callable, Coroutine, List, Optional, Set, Tuple
|
|
7
7
|
|
|
8
8
|
from board import SCL, SDA
|
|
9
9
|
from busio import I2C
|
|
@@ -15,6 +15,7 @@ from boneio.const import (
|
|
|
15
15
|
BUTTON,
|
|
16
16
|
CLOSE,
|
|
17
17
|
COVER,
|
|
18
|
+
COVER_OVER_MQTT,
|
|
18
19
|
DALLAS,
|
|
19
20
|
DS2482,
|
|
20
21
|
EVENT_ENTITY,
|
|
@@ -30,12 +31,12 @@ from boneio.const import (
|
|
|
30
31
|
MODBUS,
|
|
31
32
|
MQTT,
|
|
32
33
|
NONE,
|
|
33
|
-
OFF,
|
|
34
34
|
ON,
|
|
35
35
|
ONEWIRE,
|
|
36
36
|
ONLINE,
|
|
37
37
|
OPEN,
|
|
38
38
|
OUTPUT,
|
|
39
|
+
OUTPUT_OVER_MQTT,
|
|
39
40
|
PCA,
|
|
40
41
|
PCF,
|
|
41
42
|
PIN,
|
|
@@ -45,7 +46,6 @@ from boneio.const import (
|
|
|
45
46
|
STATE,
|
|
46
47
|
STOP,
|
|
47
48
|
SWITCH,
|
|
48
|
-
TOGGLE,
|
|
49
49
|
TOPIC,
|
|
50
50
|
UART,
|
|
51
51
|
UARTS,
|
|
@@ -88,6 +88,7 @@ from boneio.helper.yaml_util import load_config_from_file
|
|
|
88
88
|
from boneio.message_bus import MessageBus
|
|
89
89
|
from boneio.modbus.client import Modbus
|
|
90
90
|
from boneio.models import OutputState
|
|
91
|
+
from boneio.relay.basic import BasicRelay
|
|
91
92
|
from boneio.sensor.temp import TempSensor
|
|
92
93
|
|
|
93
94
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -126,7 +127,6 @@ class Manager:
|
|
|
126
127
|
cover: list = [],
|
|
127
128
|
web_active: bool = False,
|
|
128
129
|
web_port: int = 8090,
|
|
129
|
-
network_state: Optional[dict] = None,
|
|
130
130
|
) -> None:
|
|
131
131
|
"""Initialize the manager."""
|
|
132
132
|
_LOGGER.info("Initializing manager module.")
|
|
@@ -140,7 +140,6 @@ class Manager:
|
|
|
140
140
|
self._event_bus = event_bus
|
|
141
141
|
self._is_web_on = web_active
|
|
142
142
|
self._web_bind_port = web_port
|
|
143
|
-
self._network_info = network_state
|
|
144
143
|
|
|
145
144
|
self._message_bus: MessageBus = message_bus
|
|
146
145
|
|
|
@@ -153,7 +152,7 @@ class Manager:
|
|
|
153
152
|
self._mcp = {}
|
|
154
153
|
self._pcf = {}
|
|
155
154
|
self._pca = {}
|
|
156
|
-
self._outputs = {}
|
|
155
|
+
self._outputs: dict[str, BasicRelay] = {}
|
|
157
156
|
self._configured_output_groups = {}
|
|
158
157
|
self._interlock_manager = SoftwareInterlockManager()
|
|
159
158
|
|
|
@@ -177,13 +176,13 @@ class Manager:
|
|
|
177
176
|
dallas=dallas, ds2482=ds2482, sensors=sensors.get(ONEWIRE)
|
|
178
177
|
)
|
|
179
178
|
|
|
180
|
-
self.
|
|
179
|
+
self.grouped_outputs_by_expander = create_expander(
|
|
181
180
|
expander_dict=self._mcp,
|
|
182
181
|
expander_config=mcp23017,
|
|
183
182
|
exp_type=MCP,
|
|
184
183
|
i2cbusio=self._i2cbusio,
|
|
185
184
|
)
|
|
186
|
-
self.
|
|
185
|
+
self.grouped_outputs_by_expander.update(
|
|
187
186
|
create_expander(
|
|
188
187
|
expander_dict=self._pcf,
|
|
189
188
|
expander_config=pcf8575,
|
|
@@ -191,7 +190,7 @@ class Manager:
|
|
|
191
190
|
i2cbusio=self._i2cbusio,
|
|
192
191
|
)
|
|
193
192
|
)
|
|
194
|
-
self.
|
|
193
|
+
self.grouped_outputs_by_expander.update(
|
|
195
194
|
create_expander(
|
|
196
195
|
expander_dict=self._pca,
|
|
197
196
|
expander_config=pca9685,
|
|
@@ -206,6 +205,7 @@ class Manager:
|
|
|
206
205
|
_name = _config.pop(ID)
|
|
207
206
|
restore_state = _config.pop(RESTORE_STATE, False)
|
|
208
207
|
_id = strip_accents(_name)
|
|
208
|
+
_LOGGER.debug("Configuring relay: %s", _id)
|
|
209
209
|
out = configure_relay( # grouped_output updated here.
|
|
210
210
|
manager=self,
|
|
211
211
|
message_bus=message_bus,
|
|
@@ -237,7 +237,8 @@ class Manager:
|
|
|
237
237
|
)
|
|
238
238
|
self._loop.create_task(self._delayed_send_state(out))
|
|
239
239
|
|
|
240
|
-
self.
|
|
240
|
+
if self._outputs:
|
|
241
|
+
self._configure_covers()
|
|
241
242
|
|
|
242
243
|
self._outputs_group = output_group
|
|
243
244
|
self._configure_output_group()
|
|
@@ -262,7 +263,7 @@ class Manager:
|
|
|
262
263
|
manager=self,
|
|
263
264
|
event_bus=self._event_bus,
|
|
264
265
|
enabled_screens=self._screens,
|
|
265
|
-
output=self.
|
|
266
|
+
output=self.grouped_outputs_by_expander,
|
|
266
267
|
inputs=self._inputs,
|
|
267
268
|
temp_sensor=(self._temp_sensors[0] if self._temp_sensors else None),
|
|
268
269
|
ina219=(self._ina219_sensors[0] if self._ina219_sensors else None),
|
|
@@ -272,7 +273,7 @@ class Manager:
|
|
|
272
273
|
self._oled = Oled(
|
|
273
274
|
host_data=self._host_data,
|
|
274
275
|
screen_order=self._screens,
|
|
275
|
-
|
|
276
|
+
grouped_outputs_by_expander=list(self.grouped_outputs_by_expander),
|
|
276
277
|
sleep_timeout=oled.get("screensaver_timeout", 60),
|
|
277
278
|
event_bus=self._event_bus,
|
|
278
279
|
)
|
|
@@ -722,19 +723,21 @@ class Manager:
|
|
|
722
723
|
"""Get PCF by it's id."""
|
|
723
724
|
return self._pcf
|
|
724
725
|
|
|
725
|
-
def get_output_and_action(
|
|
726
|
+
def get_output_and_action(
|
|
727
|
+
self, entity_id: str, action: str, action_output: str, action_cover: str
|
|
728
|
+
) -> Tuple[BasicRelay, str]:
|
|
726
729
|
"""Get output device and its action based on configuration."""
|
|
727
730
|
if action == OUTPUT:
|
|
728
731
|
return (
|
|
729
732
|
self._outputs.get(
|
|
730
|
-
strip_accents(
|
|
731
|
-
self._configured_output_groups.get(
|
|
733
|
+
strip_accents(entity_id),
|
|
734
|
+
self._configured_output_groups.get(entity_id),
|
|
732
735
|
),
|
|
733
736
|
relay_actions.get(action_output),
|
|
734
737
|
)
|
|
735
738
|
else:
|
|
736
739
|
return (
|
|
737
|
-
self._covers.get(strip_accents(
|
|
740
|
+
self._covers.get(strip_accents(entity_id)),
|
|
738
741
|
cover_actions.get(action_cover),
|
|
739
742
|
)
|
|
740
743
|
|
|
@@ -751,6 +754,32 @@ class Manager:
|
|
|
751
754
|
actions = gpio.get_actions_of_click(click_type=x)
|
|
752
755
|
topic = f"{self._config_helper.topic_prefix}/{gpio.input_type}/{gpio.pin}"
|
|
753
756
|
|
|
757
|
+
async def invoke_action_on_output(
|
|
758
|
+
entity_id: str, action_output: str, action: str, action_cover: str
|
|
759
|
+
):
|
|
760
|
+
output, action_to_execute = self.get_output_and_action(
|
|
761
|
+
entity_id=entity_id,
|
|
762
|
+
action=action,
|
|
763
|
+
action_output=action_output,
|
|
764
|
+
action_cover=action_cover,
|
|
765
|
+
)
|
|
766
|
+
if output and action_to_execute:
|
|
767
|
+
_LOGGER.debug(
|
|
768
|
+
"Executing action %s for output %s", action_to_execute, output.name
|
|
769
|
+
)
|
|
770
|
+
_f = getattr(output, action_to_execute)
|
|
771
|
+
if _f:
|
|
772
|
+
await _f(**extra_data)
|
|
773
|
+
else:
|
|
774
|
+
if not action_to_execute:
|
|
775
|
+
_LOGGER.warning(
|
|
776
|
+
"Action doesn't exists %s, %s, %s. Check spelling",
|
|
777
|
+
action_definition,
|
|
778
|
+
actions,
|
|
779
|
+
)
|
|
780
|
+
if not output:
|
|
781
|
+
_LOGGER.warning("Device %s for action not found", entity_id)
|
|
782
|
+
|
|
754
783
|
def generate_payload():
|
|
755
784
|
if gpio.input_type == INPUT:
|
|
756
785
|
if duration:
|
|
@@ -759,48 +788,47 @@ class Manager:
|
|
|
759
788
|
return x
|
|
760
789
|
|
|
761
790
|
for action_definition in actions:
|
|
762
|
-
|
|
791
|
+
entity_id = action_definition.get("pin")
|
|
763
792
|
action = action_definition.get("action")
|
|
764
793
|
action_output = action_definition.get("action_output")
|
|
765
794
|
action_cover = action_definition.get("action_cover")
|
|
795
|
+
extra_data = action_definition.get("data", {})
|
|
766
796
|
if action == MQTT:
|
|
767
797
|
action_topic = action_definition.get(TOPIC)
|
|
768
798
|
action_payload = action_definition.get("action_mqtt_msg")
|
|
769
|
-
action_boneio = action_definition.get("action_mqtt_boneio")
|
|
770
|
-
action_output = action_definition.get("action_output")
|
|
771
|
-
pin = action_definition.get("pin")
|
|
772
|
-
if action_boneio and pin and action_output in (TOGGLE, ON, OFF):
|
|
773
|
-
self.send_message(
|
|
774
|
-
topic=f"{action_boneio}/cmd/relay{pin}",
|
|
775
|
-
payload=action_output,
|
|
776
|
-
retain=False,
|
|
777
|
-
)
|
|
778
799
|
if action_topic and action_payload:
|
|
779
800
|
self.send_message(
|
|
780
801
|
topic=action_topic, payload=action_payload, retain=False
|
|
781
802
|
)
|
|
782
803
|
continue
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
_LOGGER.warning(
|
|
798
|
-
"Action doesn't exists %s, %s, %s. Check spelling",
|
|
799
|
-
action_definition,
|
|
800
|
-
actions,
|
|
804
|
+
elif action == OUTPUT or action == COVER:
|
|
805
|
+
await invoke_action_on_output(
|
|
806
|
+
entity_id=entity_id,
|
|
807
|
+
action_output=action_output,
|
|
808
|
+
action=action,
|
|
809
|
+
action_cover=action_cover,
|
|
810
|
+
)
|
|
811
|
+
elif action == OUTPUT_OVER_MQTT:
|
|
812
|
+
boneio_id = action_definition.get("boneio_id")
|
|
813
|
+
if relay_actions.get(action_output.upper()):
|
|
814
|
+
self.send_message(
|
|
815
|
+
topic=f"{boneio_id}/cmd/relay/{entity_id}/set",
|
|
816
|
+
payload=action_output,
|
|
817
|
+
retain=False,
|
|
801
818
|
)
|
|
802
|
-
|
|
803
|
-
_LOGGER.warning("
|
|
819
|
+
else:
|
|
820
|
+
_LOGGER.warning("Desired action %s does not exists", action_output)
|
|
821
|
+
elif action == COVER_OVER_MQTT:
|
|
822
|
+
boneio_id = action_definition.get("boneio_id")
|
|
823
|
+
if cover_actions.get(action_cover.upper()):
|
|
824
|
+
self.send_message(
|
|
825
|
+
topic=f"{boneio_id}/cmd/cover/{entity_id}/set",
|
|
826
|
+
payload=action_cover,
|
|
827
|
+
retain=False,
|
|
828
|
+
)
|
|
829
|
+
else:
|
|
830
|
+
_LOGGER.warning("Desired action %s does not exists", action_cover)
|
|
831
|
+
|
|
804
832
|
payload = generate_payload()
|
|
805
833
|
_LOGGER.debug("Sending message %s for input %s", payload, topic)
|
|
806
834
|
self.send_message(topic=topic, payload=payload, retain=False)
|
|
@@ -976,13 +1004,12 @@ class Manager:
|
|
|
976
1004
|
if not self._config_helper.ha_discovery:
|
|
977
1005
|
return
|
|
978
1006
|
topic_prefix = topic_prefix or self._config_helper.topic_prefix
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
web_url = None
|
|
1007
|
+
web_url = None
|
|
1008
|
+
if self._config_helper.is_web_active:
|
|
1009
|
+
if self._host_data:
|
|
1010
|
+
web_url = self._host_data.web_url
|
|
1011
|
+
elif self._config_helper.network_info and IP in self._config_helper.network_info:
|
|
1012
|
+
web_url = f"http://{self._config_helper.network_info[IP]}:{self._web_bind_port}"
|
|
986
1013
|
payload = availability_msg_func(
|
|
987
1014
|
topic=topic_prefix,
|
|
988
1015
|
id=id,
|
|
@@ -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)
|