boneIO 0.11.0.dev5__tar.gz → 0.11.0.dev6__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.dev6}/PKG-INFO +1 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/const.py +2 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/config.py +18 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/filter.py +3 -2
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/ha_discovery.py +1 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/loader.py +3 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/util.py +26 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/yaml_util.py +34 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/manager.py +72 -47
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/liquid-sensor.json +11 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/sensor.py +80 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/single_sensor.py +50 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/runner.py +13 -9
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/actions.yaml +12 -10
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/schema.yaml +27 -2
- boneio-0.11.0.dev6/boneio/version.py +2 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/binary_sensor.schema.json +10 -6
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/config.schema.json +55 -16
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/event.schema.json +15 -9
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/modbus_sensors.schema.json +30 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/mqtt.schema.json +0 -1
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/pyproject.toml +1 -1
- boneio-0.11.0.dev5/boneio/version.py +0 -2
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/LICENSE +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/README.md +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/bonecli.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/cover/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/cover/cover.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/cover/previous.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/cover/time_based.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/cover/venetian.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/fonts/danube__.ttf +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/group/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/group/output.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/async_updater.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/click_timer.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/events.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/exceptions.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/gpiod.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/interlock.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/logger.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/mqtt.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/oled.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/onewire/W1ThermSensor.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/onewire/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/onewire/ds2482.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/onewire/onewire.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/pcf8575.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/queue.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/schema_converter.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/sensor/ina_219_smbus.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/state_manager.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/stats.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/helper/timeperiod.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/input/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/input/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/input/gpio_new.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/message_bus/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/message_bus/basic.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/message_bus/local.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/message_bus/mqtt.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/client.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/cwt.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/dts1964_3f.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/modbuscli.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/orno-or-we-517.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/pt100.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/r4dcb08.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/sdm120.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/sdm630.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/sht20.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/sht30.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/socomec_e03.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/socomec_e23.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/sofar.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/modbus/utils.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/models/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/models/files.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/models/logs.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/oled.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/relay/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/relay/basic.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/relay/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/relay/mcp.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/relay/pca.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/relay/pcf.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/filters.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/id.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/schema/update_interval.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/adc.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/gpio.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/gpio_new.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/ina219.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/serial_number.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/temp/__init__.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/temp/dallas.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/temp/lm75.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/sensor/temp/mcp9808.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/app.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/abap-BrgZPUOV.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/apex-DyP6w7ZV.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/azcli-BaLxmfj-.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/bat-CFOPXBzS.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/bicep-BfEKNvv3.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/cameligo-BFG1Mk7z.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/clojure-DTECt2xU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/coffee-CDGzqUPQ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/cpp-CLLBncYj.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/csharp-dUCx_-0o.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/csp-5Rap-vPy.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/css-D3h14YRZ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/cssMode-C5afUc0K.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/cypher-DrQuvNYM.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/dart-CFKIUWau.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/dockerfile-Zznr-cwX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/ecl-Ce3n6wWz.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/editor.worker-oRlJJsnX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/elixir-deUWdS0T.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/flow9-i9-g7ZhI.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/freemarker2-emRcpycN.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/fsharp-CzKuDChf.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/go-Cphgjts3.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/graphql-Cg7bfA9N.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/handlebars-mMSD-c9g.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/hcl-0cvrggvQ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/html-Clq5L_-r.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/htmlMode-CYqwdxDX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/index-BcJKL9Rz.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/index-DzcnWIxb.css +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/ini-Drc7WvVn.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/java-B_fMsGYe.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/javascript-BR7Nbw1G.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/json.worker-BnUULff4.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/jsonMode-aJvzz7xf.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/julia-Bqgm2twL.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/kotlin-BSkB5QuD.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/less-BsTHnhdd.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/lexon-YWi4-JPR.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/liquid-BNyvmcbu.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/lua-nf6ki56Z.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/m3-Cpb6xl2v.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/markdown-DSZPf7rp.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/mdx-pWhQfMuK.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/mips-B_c3zf-v.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/msdax-rUNN04Wq.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/mysql-DDwshQtU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/objective-c-B5zXfXm9.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/pascal-CXOwvkN_.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/pascaligo-Bc-ZgV77.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/perl-CwNk8-XU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/pgsql-tGk8EFnU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/php-CpIb_Oan.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/pla-B03wrqEc.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/postiats-BKlk5iyT.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/powerquery-Bhzvs7bI.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/powershell-Dd3NCNK9.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/protobuf-COyEY5Pt.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/pug-BaJupSGV.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/python-CVtAQrrC.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/qsharp-DXyYeYxl.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/r-CdQndTaG.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/razor-BBiV-C6e.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/redis-CVwtpugi.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/redshift-25W9uPmb.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/restructuredtext-DfzH4Xui.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/ruby-Cp1zYvxS.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/rust-D5C2fndG.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/sb-CDntyWJ8.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/scala-BoFRg7Ot.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/scheme-Bio4gycK.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/scss-4Ik7cdeQ.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/shell-CX-rkNHf.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/solidity-Tw7wswEv.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/sophia-C5WLch3f.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/sparql-DHaeiCBh.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/sql-CCSDG5nI.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/st-pnP8ivHi.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/swift-DwJ7jVG9.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/systemverilog-B9Xyijhd.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/tcl-DnHyzjbg.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/tsMode-COZIvtMx.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/twig-CPajHgWi.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/typescript-DKdGc2VX.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/typespec-D-MeaMDU.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/vb-DgyLZaXg.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/wgsl-BIv9DU6q.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/xml-CTK9ybeu.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/yaml-ggTgJ1wa.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/assets/yaml.worker-DSHdx_mx.js +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/frontend-dist/index.html +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/boneio.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/output.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/schema/web.schema.json +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/web_server.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/boneio/webui/websocket_manager.py +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/tests/32_5_config.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/tests/bandit.yaml +0 -0
- {boneio-0.11.0.dev5 → boneio-0.11.0.dev6}/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
|
|
|
@@ -235,6 +235,8 @@ 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
|
+
additional_data = sensor.get("data", {})
|
|
238
240
|
try:
|
|
239
241
|
modbus_sensors[id.lower()] = ModbusSensor(
|
|
240
242
|
address=sensor[ADDRESS],
|
|
@@ -247,6 +249,7 @@ def create_modbus_sensors(manager: Manager, message_bus: MessageBus, sensors, **
|
|
|
247
249
|
UPDATE_INTERVAL, TimePeriod(seconds=60)
|
|
248
250
|
),
|
|
249
251
|
sensors_filters=sensor.get("sensors_filters", {}),
|
|
252
|
+
additional_data=additional_data,
|
|
250
253
|
**kwargs,
|
|
251
254
|
)
|
|
252
255
|
except FileNotFoundError as err:
|
|
@@ -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)):
|
|
@@ -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
|
|
|
@@ -722,19 +721,21 @@ class Manager:
|
|
|
722
721
|
"""Get PCF by it's id."""
|
|
723
722
|
return self._pcf
|
|
724
723
|
|
|
725
|
-
def get_output_and_action(
|
|
724
|
+
def get_output_and_action(
|
|
725
|
+
self, entity_id: str, action: str, action_output: str, action_cover: str
|
|
726
|
+
) -> Tuple[BasicRelay, str]:
|
|
726
727
|
"""Get output device and its action based on configuration."""
|
|
727
728
|
if action == OUTPUT:
|
|
728
729
|
return (
|
|
729
730
|
self._outputs.get(
|
|
730
|
-
strip_accents(
|
|
731
|
-
self._configured_output_groups.get(
|
|
731
|
+
strip_accents(entity_id),
|
|
732
|
+
self._configured_output_groups.get(entity_id),
|
|
732
733
|
),
|
|
733
734
|
relay_actions.get(action_output),
|
|
734
735
|
)
|
|
735
736
|
else:
|
|
736
737
|
return (
|
|
737
|
-
self._covers.get(strip_accents(
|
|
738
|
+
self._covers.get(strip_accents(entity_id)),
|
|
738
739
|
cover_actions.get(action_cover),
|
|
739
740
|
)
|
|
740
741
|
|
|
@@ -751,6 +752,32 @@ class Manager:
|
|
|
751
752
|
actions = gpio.get_actions_of_click(click_type=x)
|
|
752
753
|
topic = f"{self._config_helper.topic_prefix}/{gpio.input_type}/{gpio.pin}"
|
|
753
754
|
|
|
755
|
+
async def invoke_action_on_output(
|
|
756
|
+
entity_id: str, action_output: str, action: str, action_cover: str
|
|
757
|
+
):
|
|
758
|
+
output, action_to_execute = self.get_output_and_action(
|
|
759
|
+
entity_id=entity_id,
|
|
760
|
+
action=action,
|
|
761
|
+
action_output=action_output,
|
|
762
|
+
action_cover=action_cover,
|
|
763
|
+
)
|
|
764
|
+
if output and action_to_execute:
|
|
765
|
+
_LOGGER.debug(
|
|
766
|
+
"Executing action %s for output %s", action_to_execute, output.name
|
|
767
|
+
)
|
|
768
|
+
_f = getattr(output, action_to_execute)
|
|
769
|
+
if _f:
|
|
770
|
+
await _f(**extra_data)
|
|
771
|
+
else:
|
|
772
|
+
if not action_to_execute:
|
|
773
|
+
_LOGGER.warning(
|
|
774
|
+
"Action doesn't exists %s, %s, %s. Check spelling",
|
|
775
|
+
action_definition,
|
|
776
|
+
actions,
|
|
777
|
+
)
|
|
778
|
+
if not output:
|
|
779
|
+
_LOGGER.warning("Device %s for action not found", entity_id)
|
|
780
|
+
|
|
754
781
|
def generate_payload():
|
|
755
782
|
if gpio.input_type == INPUT:
|
|
756
783
|
if duration:
|
|
@@ -759,48 +786,47 @@ class Manager:
|
|
|
759
786
|
return x
|
|
760
787
|
|
|
761
788
|
for action_definition in actions:
|
|
762
|
-
|
|
789
|
+
entity_id = action_definition.get("pin")
|
|
763
790
|
action = action_definition.get("action")
|
|
764
791
|
action_output = action_definition.get("action_output")
|
|
765
792
|
action_cover = action_definition.get("action_cover")
|
|
793
|
+
extra_data = action_definition.get("data", {})
|
|
766
794
|
if action == MQTT:
|
|
767
795
|
action_topic = action_definition.get(TOPIC)
|
|
768
796
|
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
797
|
if action_topic and action_payload:
|
|
779
798
|
self.send_message(
|
|
780
799
|
topic=action_topic, payload=action_payload, retain=False
|
|
781
800
|
)
|
|
782
801
|
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,
|
|
802
|
+
elif action == OUTPUT or action == COVER:
|
|
803
|
+
await invoke_action_on_output(
|
|
804
|
+
entity_id=entity_id,
|
|
805
|
+
action_output=action_output,
|
|
806
|
+
action=action,
|
|
807
|
+
action_cover=action_cover,
|
|
808
|
+
)
|
|
809
|
+
elif action == OUTPUT_OVER_MQTT:
|
|
810
|
+
boneio_id = action_definition.get("boneio_id")
|
|
811
|
+
if relay_actions.get(action_output.upper()):
|
|
812
|
+
self.send_message(
|
|
813
|
+
topic=f"{boneio_id}/cmd/relay/{entity_id}/set",
|
|
814
|
+
payload=action_output,
|
|
815
|
+
retain=False,
|
|
801
816
|
)
|
|
802
|
-
|
|
803
|
-
_LOGGER.warning("
|
|
817
|
+
else:
|
|
818
|
+
_LOGGER.warning("Desired action %s does not exists", action_output)
|
|
819
|
+
elif action == COVER_OVER_MQTT:
|
|
820
|
+
boneio_id = action_definition.get("boneio_id")
|
|
821
|
+
if cover_actions.get(action_cover.upper()):
|
|
822
|
+
self.send_message(
|
|
823
|
+
topic=f"{boneio_id}/cmd/cover/{entity_id}/set",
|
|
824
|
+
payload=action_cover,
|
|
825
|
+
retain=False,
|
|
826
|
+
)
|
|
827
|
+
else:
|
|
828
|
+
_LOGGER.warning("Desired action %s does not exists", action_cover)
|
|
829
|
+
|
|
804
830
|
payload = generate_payload()
|
|
805
831
|
_LOGGER.debug("Sending message %s for input %s", payload, topic)
|
|
806
832
|
self.send_message(topic=topic, payload=payload, retain=False)
|
|
@@ -976,13 +1002,12 @@ class Manager:
|
|
|
976
1002
|
if not self._config_helper.ha_discovery:
|
|
977
1003
|
return
|
|
978
1004
|
topic_prefix = topic_prefix or self._config_helper.topic_prefix
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
web_url = None
|
|
1005
|
+
web_url = None
|
|
1006
|
+
if self._config_helper.is_web_active:
|
|
1007
|
+
if self._host_data:
|
|
1008
|
+
web_url = self._host_data.web_url
|
|
1009
|
+
elif self._config_helper.network_info and IP in self._config_helper.network_info:
|
|
1010
|
+
web_url = f"http://{self._config_helper.network_info[IP]}:{self._web_bind_port}"
|
|
986
1011
|
payload = availability_msg_func(
|
|
987
1012
|
topic=topic_prefix,
|
|
988
1013
|
id=id,
|
|
@@ -33,5 +33,16 @@
|
|
|
33
33
|
}
|
|
34
34
|
]
|
|
35
35
|
}
|
|
36
|
+
],
|
|
37
|
+
"additional_sensors": [
|
|
38
|
+
{
|
|
39
|
+
"name": "Measurement Volume",
|
|
40
|
+
"source": "measurement_value",
|
|
41
|
+
"unit_of_measurement": "l",
|
|
42
|
+
"device_class": "volume_storage",
|
|
43
|
+
"state_class": "measurement",
|
|
44
|
+
"formula": "width * length * X * 10",
|
|
45
|
+
"config_keys": ["width", "length"]
|
|
46
|
+
}
|
|
36
47
|
]
|
|
37
48
|
}
|
|
@@ -28,7 +28,7 @@ from boneio.helper.util import open_json
|
|
|
28
28
|
from boneio.models import SensorState
|
|
29
29
|
|
|
30
30
|
from .client import VALUE_TYPES, Modbus
|
|
31
|
-
from .single_sensor import SingleSensor
|
|
31
|
+
from .single_sensor import SingleAdditionalSensor, SingleSensor
|
|
32
32
|
from .utils import CONVERT_METHODS, REGISTERS_BASE
|
|
33
33
|
|
|
34
34
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -49,6 +49,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
49
49
|
config_helper: ConfigHelper,
|
|
50
50
|
event_bus: EventBus,
|
|
51
51
|
id: str = DefaultName,
|
|
52
|
+
additional_data: dict = {},
|
|
52
53
|
**kwargs,
|
|
53
54
|
):
|
|
54
55
|
"""Initialize Modbus sensor class."""
|
|
@@ -69,6 +70,11 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
69
70
|
k.lower(): v for k, v in sensors_filters.items()
|
|
70
71
|
}
|
|
71
72
|
self._modbus_sensors: List[Dict[str, SingleSensor]] = []
|
|
73
|
+
self._additional_sensors: List[Dict[str, SingleAdditionalSensor]] = []
|
|
74
|
+
self._additional_sensors_by_source_name: Dict[str, List[SingleAdditionalSensor]] = {}
|
|
75
|
+
self._additional_data = additional_data
|
|
76
|
+
print("aaa", additional_data)
|
|
77
|
+
# Standard sensors
|
|
72
78
|
for index, data in enumerate(self._db[REGISTERS_BASE]):
|
|
73
79
|
base = data[BASE]
|
|
74
80
|
self._modbus_sensors.append({})
|
|
@@ -98,6 +104,45 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
98
104
|
self._modbus_sensors[index][
|
|
99
105
|
single_sensor.decoded_name
|
|
100
106
|
] = single_sensor
|
|
107
|
+
|
|
108
|
+
# Additional sensors
|
|
109
|
+
if "additional_sensors" in self._db:
|
|
110
|
+
for additional in self._db["additional_sensors"]:
|
|
111
|
+
config_keys = additional.get("config_keys", [])
|
|
112
|
+
if not self._additional_data:
|
|
113
|
+
continue
|
|
114
|
+
if not all(k in self._additional_data for k in config_keys):
|
|
115
|
+
continue
|
|
116
|
+
source_sensor = None
|
|
117
|
+
for sensors in self._modbus_sensors:
|
|
118
|
+
for s in sensors.values():
|
|
119
|
+
if s.decoded_name == additional["source"].replace("_", ""):
|
|
120
|
+
source_sensor = s
|
|
121
|
+
break
|
|
122
|
+
if not source_sensor:
|
|
123
|
+
_LOGGER.warning("Source sensor '%s' for additional sensor '%s' not found.", additional["source"], additional["name"])
|
|
124
|
+
continue
|
|
125
|
+
single_sensor = SingleAdditionalSensor(
|
|
126
|
+
name=additional["name"],
|
|
127
|
+
parent={NAME: self._name, ID: self._id, MODEL: self._model},
|
|
128
|
+
register_address=-1,
|
|
129
|
+
base_address=base,
|
|
130
|
+
unit_of_measurement=additional.get("unit_of_measurement", "m3"),
|
|
131
|
+
state_class=additional.get("state_class", "measurement"),
|
|
132
|
+
device_class=additional.get("device_class", "volume"),
|
|
133
|
+
value_type=None,
|
|
134
|
+
return_type=None,
|
|
135
|
+
filters=[],
|
|
136
|
+
message_bus=self._message_bus,
|
|
137
|
+
config_helper=self._config_helper,
|
|
138
|
+
ha_filter=additional.get("ha_filter", "round(2)"),
|
|
139
|
+
formula=additional.get("formula", ""),
|
|
140
|
+
context_config = { k: v for k,v in self._additional_data.items() if k in config_keys },
|
|
141
|
+
)
|
|
142
|
+
self._additional_sensors.append({single_sensor.decoded_name: single_sensor})
|
|
143
|
+
if source_sensor.decoded_name not in self._additional_sensors_by_source_name:
|
|
144
|
+
self._additional_sensors_by_source_name[source_sensor.decoded_name] = []
|
|
145
|
+
self._additional_sensors_by_source_name[source_sensor.decoded_name].append(single_sensor)
|
|
101
146
|
_LOGGER.info(
|
|
102
147
|
"Available single sensors for %s: %s",
|
|
103
148
|
self._name,
|
|
@@ -109,6 +154,18 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
109
154
|
]
|
|
110
155
|
),
|
|
111
156
|
)
|
|
157
|
+
if self._additional_sensors:
|
|
158
|
+
_LOGGER.info(
|
|
159
|
+
"Available additional sensors for %s: %s",
|
|
160
|
+
self._name,
|
|
161
|
+
", ".join(
|
|
162
|
+
[
|
|
163
|
+
s.name
|
|
164
|
+
for sensors in self._additional_sensors
|
|
165
|
+
for s in sensors.values()
|
|
166
|
+
]
|
|
167
|
+
),
|
|
168
|
+
)
|
|
112
169
|
self._event_bus = event_bus
|
|
113
170
|
self._event_bus.add_haonline_listener(target=self.set_payload_offline)
|
|
114
171
|
try:
|
|
@@ -134,6 +191,9 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
134
191
|
for sensors in self._modbus_sensors:
|
|
135
192
|
for sensor in sensors.values():
|
|
136
193
|
sensor.send_ha_discovery()
|
|
194
|
+
for sensors in self._additional_sensors:
|
|
195
|
+
for sensor in sensors.values():
|
|
196
|
+
sensor.send_ha_discovery()
|
|
137
197
|
return datetime.now()
|
|
138
198
|
|
|
139
199
|
async def check_availability(self) -> None:
|
|
@@ -167,6 +227,15 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
167
227
|
self._id,
|
|
168
228
|
)
|
|
169
229
|
|
|
230
|
+
def _evaluate_formula(self, formula: str, context: dict) -> float:
|
|
231
|
+
"""
|
|
232
|
+
Evaluate the formula for additional sensor using provided context.
|
|
233
|
+
Allowed names: X (value from source sensor), config (dict with config values)
|
|
234
|
+
"""
|
|
235
|
+
code = compile(formula, "<string>", "eval")
|
|
236
|
+
return eval(code, {"__builtins__": {}}, context)
|
|
237
|
+
|
|
238
|
+
|
|
170
239
|
async def async_update(self, timestamp: float) -> Optional[float]:
|
|
171
240
|
"""Fetch state periodically and send to MQTT."""
|
|
172
241
|
update_interval = self._update_interval.total_in_seconds
|
|
@@ -238,6 +307,16 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
|
|
|
238
307
|
)
|
|
239
308
|
decoded_value = None
|
|
240
309
|
sensor.set_value(value=decoded_value, timestamp=timestamp)
|
|
310
|
+
if self._additional_sensors and sensor.get_value() is not None:
|
|
311
|
+
if sensor.decoded_name in self._additional_sensors_by_source_name:
|
|
312
|
+
for additional_sensor in self._additional_sensors_by_source_name[sensor.decoded_name]:
|
|
313
|
+
context = {
|
|
314
|
+
"X": sensor.get_value(),
|
|
315
|
+
**additional_sensor.context
|
|
316
|
+
}
|
|
317
|
+
value = self._evaluate_formula(additional_sensor.formula, context)
|
|
318
|
+
additional_sensor.set_value(value=value, timestamp=timestamp)
|
|
319
|
+
output[additional_sensor.decoded_name] = additional_sensor.state
|
|
241
320
|
output[sensor.decoded_name] = sensor.state
|
|
242
321
|
await self._event_bus.async_trigger_event(
|
|
243
322
|
event_type=MODBUS_SENSOR,
|
|
@@ -158,3 +158,53 @@ class SingleSensor(Filter):
|
|
|
158
158
|
@property
|
|
159
159
|
def last_timestamp(self) -> float:
|
|
160
160
|
return self._timestamp
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class SingleAdditionalSensor(SingleSensor):
|
|
164
|
+
def __init__(
|
|
165
|
+
self,
|
|
166
|
+
name: str,
|
|
167
|
+
parent: dict,
|
|
168
|
+
register_address: int,
|
|
169
|
+
base_address: int,
|
|
170
|
+
unit_of_measurement: str,
|
|
171
|
+
state_class: str,
|
|
172
|
+
device_class: str,
|
|
173
|
+
value_type: str,
|
|
174
|
+
return_type: str,
|
|
175
|
+
filters: list,
|
|
176
|
+
message_bus: MessageBus,
|
|
177
|
+
formula: str,
|
|
178
|
+
context_config: dict,
|
|
179
|
+
config_helper: ConfigHelper,
|
|
180
|
+
user_filters: Optional[list] = [],
|
|
181
|
+
ha_filter: str = "round(2)",
|
|
182
|
+
) -> None:
|
|
183
|
+
super().__init__(
|
|
184
|
+
name=name,
|
|
185
|
+
parent=parent,
|
|
186
|
+
register_address=register_address,
|
|
187
|
+
base_address=base_address,
|
|
188
|
+
unit_of_measurement=unit_of_measurement,
|
|
189
|
+
state_class=state_class,
|
|
190
|
+
device_class=device_class,
|
|
191
|
+
value_type=value_type,
|
|
192
|
+
return_type=return_type,
|
|
193
|
+
filters=filters,
|
|
194
|
+
message_bus=message_bus,
|
|
195
|
+
config_helper=config_helper,
|
|
196
|
+
user_filters=user_filters,
|
|
197
|
+
ha_filter=ha_filter,
|
|
198
|
+
)
|
|
199
|
+
self._formula = formula
|
|
200
|
+
self._context_config = context_config
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def formula(self) -> str:
|
|
204
|
+
return self._formula
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def context(self) -> dict:
|
|
208
|
+
return self._context_config
|
|
209
|
+
|
|
210
|
+
|