boneio 1.4.0.dev3__tar.gz → 1.4.0.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boneio-1.4.0.dev3/boneio.egg-info → boneio-1.4.0.dev4}/PKG-INFO +1 -1
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/cover/cover.py +6 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/cover/venetian.py +11 -4
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/output/remote.py +224 -3
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/manager.py +129 -3
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/remote.py +58 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/actions.yaml +11 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/remote_outputs.yaml +93 -0
- boneio-1.4.0.dev4/boneio/version.py +2 -0
- boneio-1.4.0.dev3/boneio/webui/frontend-dist/assets/ConfigEditor-B7qJAsAx.js → boneio-1.4.0.dev4/boneio/webui/frontend-dist/assets/ConfigEditor-BBQ49dou.js +1 -1
- boneio-1.4.0.dev3/boneio/webui/frontend-dist/assets/aiConfig-Dq5oh99L.js → boneio-1.4.0.dev4/boneio/webui/frontend-dist/assets/aiConfig-BwEuqxu2.js +1 -1
- boneio-1.4.0.dev3/boneio/webui/frontend-dist/assets/aiWizardPrompt-r-xmvrUB.js → boneio-1.4.0.dev4/boneio/webui/frontend-dist/assets/aiWizardPrompt-CEIyLZ8l.js +1 -1
- boneio-1.4.0.dev3/boneio/webui/frontend-dist/assets/index-BVRhWldF.js → boneio-1.4.0.dev4/boneio/webui/frontend-dist/assets/index-CfQ35RrC.js +4 -4
- boneio-1.4.0.dev3/boneio/webui/frontend-dist/assets/useTranslation-VOFZRLzq.js → boneio-1.4.0.dev4/boneio/webui/frontend-dist/assets/useTranslation-ChbxfQ44.js +2 -2
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/index.html +3 -3
- {boneio-1.4.0.dev3/boneio/webui → boneio-1.4.0.dev4/boneio/webui/frontend-dist}/schema/binary_sensor.schema.json +44 -0
- {boneio-1.4.0.dev3/boneio/webui → boneio-1.4.0.dev4/boneio/webui/frontend-dist}/schema/config.schema.json +312 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/event.schema.json +154 -0
- boneio-1.4.0.dev4/boneio/webui/frontend-dist/schema/remote_outputs.schema.json +228 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/sw.js +1 -1
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/config.py +26 -7
- {boneio-1.4.0.dev3/boneio/webui/frontend-dist → boneio-1.4.0.dev4/boneio/webui}/schema/binary_sensor.schema.json +44 -0
- {boneio-1.4.0.dev3/boneio/webui/frontend-dist → boneio-1.4.0.dev4/boneio/webui}/schema/config.schema.json +312 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/event.schema.json +154 -0
- boneio-1.4.0.dev4/boneio/webui/schema/remote_outputs.schema.json +228 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4/boneio.egg-info}/PKG-INFO +1 -1
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio.egg-info/SOURCES.txt +5 -5
- boneio-1.4.0.dev3/boneio/version.py +0 -2
- boneio-1.4.0.dev3/boneio/webui/frontend-dist/schema/remote_outputs.schema.json +0 -114
- boneio-1.4.0.dev3/boneio/webui/schema/remote_outputs.schema.json +0 -114
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/LICENSE +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/MANIFEST.in +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/README.md +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.2/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.2/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.2/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.2/output_32_5.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.2/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.3/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.3/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.3/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.3/output_32_5.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.3/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.4/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.4/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.4/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.4/output_32_5.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.4/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.5/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.5/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.5/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.5/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.6/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.6/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.6/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.6/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.7/output_48_4.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.8/output_48_4.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/bonecli.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/cover/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/cover/time_based.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/group/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/group/output_group.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/binary_sensor.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/detectors.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/event.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/remote/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/remote/base.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/input/remote/esphome.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/irrigation/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/irrigation/controller.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/irrigation/water_source.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/output/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/output/basic.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/output/mcp.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/output/pca.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/output/pcf.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/sensor/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/sensor/virtual_energy.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/template/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/template/alarm_panel.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/template/gate_cover.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/components/template/thermostat.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/const.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/data/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/data/docker-compose-cloud.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/data/docker-compose.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/data/init-certs-cloud.sh +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/registration.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/cloud/secrets.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/config_helper.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/migrations/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/migrations/v1_proxy_port.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/migrations/v2_transition.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/package-lock.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/package.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/schema_converter.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/config/yaml_util.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/discovery.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/events/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/events/bus.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/action_conditions.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/canopen.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/covers.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/display.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/inputs.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/irrigation.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/modbus.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/outputs.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/remote_input_registrar.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/sensors.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/templates/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/templates/alarm.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/templates/gate_cover.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/templates/thermostat.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/templates.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/manager/update.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/basic.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/basic_mqtt.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/composite.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/local.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/lox.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/loxone.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/mqtt.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/messaging/queue.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/remote/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/remote/base.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/remote/can.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/remote/esphome.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/remote/mqtt.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/remote/wled.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/sensor/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/sensor/base.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/sensor/system.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/state/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/state/manager.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/system/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/system/host_data.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/system/monitor.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/async_updater.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/conditions.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/filter.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/font_util.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/logger.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/timeperiod.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/core/utils/util.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/48x4/adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/48x4/binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/48x4/config.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/48x4/event.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/48x4/mqtt.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/48x4/output48x4A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/can_master.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/can_slave.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/exceptions.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/analog/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/analog/adc.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/bridge.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/client.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/interface.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/node.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/node_id.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/can/test_od.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/display/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/display/early_oled.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/display/fonts/danube__.ttf +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/display/oled.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/expanders/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/expanders/mcp23017.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/input/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/input/base.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/gpio/input/manager.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/i2c/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/i2c/bus.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/i2c/ina219.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/i2c/ina219_driver.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/i2c/mcp9808.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/i2c/pct2075.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/onewire/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/onewire/bus.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/onewire/dallas.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/onewire/ds2482.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/sensor/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/sensor/temperature/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/sensor/temperature/base.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/integration/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/integration/homeassistant.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/integration/interlock.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/integration/lox_template.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/actions.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/MANIFEST.sha256 +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/docker/daemon.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/docker/nodered/docker-compose.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/docker/nodered/nginx/default.conf +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/docker/nodered/node-red/settings.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/journald/journald.conf +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/mosquitto/boneio.conf +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/sudoers/boneio +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/systemd/boneio-oled-boot.service +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/systemd/boneio.service +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/systemd/set-hostname-once.service +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/usr-local-bin/set-hostname-once.sh +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/usr-sbin/oled_boot_splash.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/usr-sbin/oled_boot_splash.sh +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/usr-sbin/oled_msg.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/assets/usr-sbin/oled_msg.sh +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/bootstrap/boneio-migrate +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/bootstrap/install-helper.sh +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/bootstrap/sudoers-migrate +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/runner.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/versions/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/versions/v1_3_0_baseline.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/versions/v1_3_1_fix_oled_boot.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/versions/v1_3_2_cleanup_can_sudoers.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/migrations/versions/v1_4_0_fix_mqtt_sudoers.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/cli.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/client.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/coordinator.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/le-03mw.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/le-03mwct.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/socomec_e03.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/energy_meters/socomec_e23.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/hvac/ventclear.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/inverters/sofar.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/inverters/thessla.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/other/esp32_relay_x4_modbus.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/other/n4dsc08.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/other/r4dcb08.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/other/wanas415.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/boneio-edge-temp.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/cwt.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/dts1964_3f.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/dyp-a12-ultrasonic.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/gdfs.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/gdfx.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/pt100.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/sht20.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/devices/sensors/sht30.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/base.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/derived/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/derived/numeric.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/derived/select.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/derived/switch.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/derived/text.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/sensor/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/sensor/binary.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/sensor/numeric.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/sensor/text.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/writeable/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/writeable/binary.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/entities/writeable/numeric.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/modbus/utils.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/actions.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/events.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/files.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/logs.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/mqtt.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/models/state.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/runner.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/condition.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/filters.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/id.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/remote_devices.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/remote_inputs.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/schema.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/schema/update_interval.yaml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/action_validation.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/app.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/editor.worker-BVjSvWeP.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/index-D-R9QzIP.css +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/json.worker-CqOJL4FD.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/monaco-B9WiNxkw.css +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/monaco-CAZoGZNF.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/rolldown-runtime-Dw2cE7zH.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/vendor-BD5Ml_Uz.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/workbox-window.prod.es5-BJd1pjeW.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/assets/yaml.worker-nZQZSRZ7.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/boneio-192.png +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/boneio-512.png +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/adc.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/areas.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/boneio.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/can.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/cover.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/dallas.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/ds2482.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/ina219.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/irrigation.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/lm75.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/logger.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/lox_udp.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/mcp23017.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/mcp9808.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/modbus.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/modbus_devices.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/mqtt.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/oled.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/output.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/output_group.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/pca9685.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/pcf8575.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/remote_devices.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/remote_inputs.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/sensor.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/template.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/schema/web.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/frontend-dist/workbox-4eca85ba.js +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/middleware/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/middleware/auth.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/auth.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/caddy.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/can.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/covers.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/irrigation.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/migrations.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/modbus.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/outputs.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/remote_devices.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/sensors.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/system.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/templates.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/timezone_sudoers.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/tools.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/routes/update.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/areas.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/boneio.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/can.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/irrigation.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/lox_udp.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/modbus_devices.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/mqtt.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/output.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/remote_devices.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/remote_inputs.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/template.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/schema/web.schema.json +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/services/__init__.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/services/logs.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/web_server.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio/webui/websocket_manager.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio.egg-info/dependency_links.txt +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio.egg-info/entry_points.txt +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio.egg-info/requires.txt +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/boneio.egg-info/top_level.txt +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/pyproject.toml +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/setup.cfg +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/setup.py +0 -0
- {boneio-1.4.0.dev3 → boneio-1.4.0.dev4}/tests/test_py313_compatibility.py +0 -0
|
@@ -192,6 +192,12 @@ class BaseCover(BaseCoverABC, BasicMqtt):
|
|
|
192
192
|
self._movement_thread = None
|
|
193
193
|
self._stop_event = threading.Event()
|
|
194
194
|
|
|
195
|
+
# Flag set by action executor to signal this call originates from a button action.
|
|
196
|
+
# Used by VenetianCover to conditionally skip tilt restore.
|
|
197
|
+
self._from_action: bool = False
|
|
198
|
+
# When True, tilt restore is explicitly requested by the action definition.
|
|
199
|
+
self._action_tilt_restore: bool = False
|
|
200
|
+
|
|
195
201
|
self._event_bus.add_sigterm_listener(self.on_exit)
|
|
196
202
|
|
|
197
203
|
with suppress(RuntimeError):
|
|
@@ -35,7 +35,7 @@ class VenetianCover(BaseCover, BaseVenetianCoverABC):
|
|
|
35
35
|
actuator_activation_duration: Actuator activation time (unused).
|
|
36
36
|
restored_state: Persisted position/tilt from disk.
|
|
37
37
|
tilt_restore_after_close: If True, restore previous tilt
|
|
38
|
-
position after closing the cover.
|
|
38
|
+
position after closing the cover (UI/HA calls).
|
|
39
39
|
"""
|
|
40
40
|
self._tilt_duration = tilt_duration.total_milliseconds # Czas trwania ruchu lameli
|
|
41
41
|
self._initial_tilt_position = float(restored_state.get("tilt", DEFAULT_RESTORED_STATE["tilt"]))
|
|
@@ -300,10 +300,17 @@ class VenetianCover(BaseCover, BaseVenetianCoverABC):
|
|
|
300
300
|
def _save_tilt_for_restore(self) -> None:
|
|
301
301
|
"""Save current tilt position for later restoration.
|
|
302
302
|
|
|
303
|
-
Called before any closing movement
|
|
304
|
-
|
|
303
|
+
Called before any closing movement. Determines whether to save
|
|
304
|
+
based on the call source:
|
|
305
|
+
- UI/HA calls: uses tilt_restore_after_close setting
|
|
306
|
+
- Action calls: uses _action_tilt_restore flag (set by executor)
|
|
305
307
|
"""
|
|
306
|
-
if self.
|
|
308
|
+
if self._from_action:
|
|
309
|
+
should_restore = self._action_tilt_restore
|
|
310
|
+
else:
|
|
311
|
+
should_restore = self._tilt_restore_after_close
|
|
312
|
+
|
|
313
|
+
if should_restore and self._tilt_position > 0:
|
|
307
314
|
self._tilt_before_close = self._tilt_position
|
|
308
315
|
_LOGGER.debug(
|
|
309
316
|
"VenetianCover %s: saving tilt=%d%% before close",
|
|
@@ -10,15 +10,21 @@ The actual hardware control is delegated to the parent ``ESPHomeDeviceManager``
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import asyncio
|
|
13
14
|
import logging
|
|
14
15
|
import time
|
|
15
|
-
from typing import Any
|
|
16
|
+
from typing import TYPE_CHECKING, Any
|
|
16
17
|
|
|
17
18
|
from boneio.const import OFF, ON, SWITCH
|
|
18
|
-
from boneio.core.events import EventBus
|
|
19
|
+
from boneio.core.events import EventBus, async_track_point_in_time, utcnow
|
|
20
|
+
from boneio.core.utils import callback
|
|
21
|
+
from boneio.core.utils.timeperiod import TimePeriod, parse_time_to_seconds
|
|
19
22
|
from boneio.models import OutputState
|
|
20
23
|
from boneio.models.events import OutputEvent
|
|
21
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from boneio.integration.interlock import SoftwareInterlockManager
|
|
27
|
+
|
|
22
28
|
_LOGGER = logging.getLogger(__name__)
|
|
23
29
|
|
|
24
30
|
|
|
@@ -60,6 +66,16 @@ class RemoteOutputBase:
|
|
|
60
66
|
show_in_ha: bool = False,
|
|
61
67
|
area: str | None = None,
|
|
62
68
|
on_disconnect: str = "ignore",
|
|
69
|
+
interlock_manager: SoftwareInterlockManager | None = None,
|
|
70
|
+
interlock_groups: list[str] | None = None,
|
|
71
|
+
enforce_interlock: bool = False,
|
|
72
|
+
momentary_turn_on: TimePeriod | None = None,
|
|
73
|
+
momentary_turn_off: TimePeriod | None = None,
|
|
74
|
+
adjustable_duration: bool = False,
|
|
75
|
+
duration_default: float = 60.0,
|
|
76
|
+
duration_min: float = 1.0,
|
|
77
|
+
duration_max: float = 3600.0,
|
|
78
|
+
duration_unit: str = "s",
|
|
63
79
|
) -> None:
|
|
64
80
|
self._id = id
|
|
65
81
|
self._name = name
|
|
@@ -72,10 +88,32 @@ class RemoteOutputBase:
|
|
|
72
88
|
self.area: str | None = area
|
|
73
89
|
self._on_disconnect = on_disconnect
|
|
74
90
|
|
|
91
|
+
# Interlock support (shared with local BasicOutput instances)
|
|
92
|
+
self._interlock_manager: SoftwareInterlockManager | None = interlock_manager
|
|
93
|
+
self._interlock_groups: list[str] = interlock_groups or []
|
|
94
|
+
self._enforce_interlock: bool = enforce_interlock
|
|
95
|
+
|
|
96
|
+
# Momentary actions (auto-off / auto-on after duration)
|
|
97
|
+
self._momentary_turn_on: TimePeriod | None = momentary_turn_on
|
|
98
|
+
self._momentary_turn_off: TimePeriod | None = momentary_turn_off
|
|
99
|
+
self._momentary_action: Any = None
|
|
100
|
+
|
|
101
|
+
# Adjustable duration (HA number entity slider)
|
|
102
|
+
self._adjustable_duration_enabled: bool = adjustable_duration
|
|
103
|
+
self._duration_min: float = max(1.0, duration_min)
|
|
104
|
+
self._duration_max: float = max(self._duration_min, duration_max)
|
|
105
|
+
self._duration_default: float = duration_default
|
|
106
|
+
self._duration_unit: str = duration_unit
|
|
107
|
+
self._adjustable_duration: float = max(self._duration_min, min(self._duration_max, self._duration_default))
|
|
108
|
+
# If adjustable_duration is on, momentary_turn_on is managed by the slider
|
|
109
|
+
if self._adjustable_duration_enabled:
|
|
110
|
+
self._momentary_turn_on = None
|
|
111
|
+
|
|
75
112
|
self._state: str = OFF
|
|
76
113
|
self._last_timestamp: float = 0.0
|
|
77
114
|
self._available: bool = False
|
|
78
115
|
self._brightness: int | None = None # 0-255, None if not a dimmable light
|
|
116
|
+
self._loop: asyncio.AbstractEventLoop | None = None
|
|
79
117
|
|
|
80
118
|
# Reference to remote device manager — set by register_remote_outputs().
|
|
81
119
|
# May be None at startup if ESPHome devices load in background.
|
|
@@ -186,6 +224,34 @@ class RemoteOutputBase:
|
|
|
186
224
|
self._id,
|
|
187
225
|
)
|
|
188
226
|
|
|
227
|
+
# ------------------------------------------------------------------
|
|
228
|
+
# Interlock
|
|
229
|
+
# ------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
def set_interlock(
|
|
232
|
+
self,
|
|
233
|
+
interlock_manager: SoftwareInterlockManager,
|
|
234
|
+
interlock_groups: list[str],
|
|
235
|
+
) -> None:
|
|
236
|
+
"""Set interlock manager and groups.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
interlock_manager: Shared interlock manager instance.
|
|
240
|
+
interlock_groups: List of group names this output belongs to.
|
|
241
|
+
"""
|
|
242
|
+
self._interlock_manager = interlock_manager
|
|
243
|
+
self._interlock_groups = interlock_groups
|
|
244
|
+
|
|
245
|
+
def check_interlock(self) -> bool:
|
|
246
|
+
"""Check if this output can be turned on without violating interlocks.
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
True if no interlock violation, False if blocked.
|
|
250
|
+
"""
|
|
251
|
+
if self._interlock_manager is not None and self._interlock_groups:
|
|
252
|
+
return self._interlock_manager.can_turn_on(self, self._interlock_groups)
|
|
253
|
+
return True
|
|
254
|
+
|
|
189
255
|
# ------------------------------------------------------------------
|
|
190
256
|
# Core control methods (duck-type compatible with BasicOutput)
|
|
191
257
|
# ------------------------------------------------------------------
|
|
@@ -193,12 +259,21 @@ class RemoteOutputBase:
|
|
|
193
259
|
async def async_turn_on(self, timestamp: float | None = None) -> bool:
|
|
194
260
|
"""Turn on the remote output.
|
|
195
261
|
|
|
262
|
+
Checks interlock before sending the ON command. If another output
|
|
263
|
+
in the same interlock group is already ON, the request is rejected.
|
|
264
|
+
After successful ON, schedules momentary auto-OFF if configured.
|
|
265
|
+
|
|
196
266
|
Args:
|
|
197
267
|
timestamp: Optional timestamp for state tracking.
|
|
198
268
|
|
|
199
269
|
Returns:
|
|
200
|
-
True if the output was turned on, False
|
|
270
|
+
True if the output was turned on, False if blocked or failed.
|
|
201
271
|
"""
|
|
272
|
+
can_turn_on = self.check_interlock()
|
|
273
|
+
if not can_turn_on:
|
|
274
|
+
_LOGGER.warning("Interlock active: cannot turn on remote output '%s'", self._id)
|
|
275
|
+
return False
|
|
276
|
+
|
|
202
277
|
if not self._resolve_device_manager():
|
|
203
278
|
_LOGGER.error("Remote output '%s' has no device manager, cannot turn on", self._id)
|
|
204
279
|
return False
|
|
@@ -211,6 +286,7 @@ class RemoteOutputBase:
|
|
|
211
286
|
self._state = ON
|
|
212
287
|
self._last_timestamp = timestamp or time.time()
|
|
213
288
|
self._emit_state_event()
|
|
289
|
+
self._execute_momentary_turn(ON)
|
|
214
290
|
_LOGGER.debug("Remote output '%s' turned ON", self._id)
|
|
215
291
|
else:
|
|
216
292
|
_LOGGER.warning("Failed to turn ON remote output '%s'", self._id)
|
|
@@ -219,6 +295,8 @@ class RemoteOutputBase:
|
|
|
219
295
|
async def async_turn_off(self, timestamp: float | None = None) -> None:
|
|
220
296
|
"""Turn off the remote output.
|
|
221
297
|
|
|
298
|
+
After successful OFF, schedules momentary auto-ON if configured.
|
|
299
|
+
|
|
222
300
|
Args:
|
|
223
301
|
timestamp: Optional timestamp for state tracking.
|
|
224
302
|
"""
|
|
@@ -234,6 +312,7 @@ class RemoteOutputBase:
|
|
|
234
312
|
self._state = OFF
|
|
235
313
|
self._last_timestamp = timestamp or time.time()
|
|
236
314
|
self._emit_state_event()
|
|
315
|
+
self._execute_momentary_turn(OFF)
|
|
237
316
|
_LOGGER.debug("Remote output '%s' turned OFF", self._id)
|
|
238
317
|
else:
|
|
239
318
|
_LOGGER.warning("Failed to turn OFF remote output '%s'", self._id)
|
|
@@ -259,6 +338,10 @@ class RemoteOutputBase:
|
|
|
259
338
|
Called by ESPHomeDeviceManager when it receives a state update
|
|
260
339
|
for this output's entity.
|
|
261
340
|
|
|
341
|
+
If ``enforce_interlock`` is enabled and the output was turned ON
|
|
342
|
+
externally while violating an interlock, boneIO will immediately
|
|
343
|
+
send a turn-off command.
|
|
344
|
+
|
|
262
345
|
Args:
|
|
263
346
|
new_state: ``True`` if the output is now ON.
|
|
264
347
|
brightness: Optional brightness value (0-255) for dimmable lights.
|
|
@@ -281,6 +364,15 @@ class RemoteOutputBase:
|
|
|
281
364
|
self._brightness,
|
|
282
365
|
)
|
|
283
366
|
|
|
367
|
+
# Enforce interlock: if turned ON externally and violating interlock,
|
|
368
|
+
# immediately send OFF command to the remote device.
|
|
369
|
+
if new_state and self._enforce_interlock and not self.check_interlock():
|
|
370
|
+
_LOGGER.warning(
|
|
371
|
+
"Remote output '%s' turned ON externally, violating interlock — forcing OFF",
|
|
372
|
+
self._id,
|
|
373
|
+
)
|
|
374
|
+
asyncio.ensure_future(self._enforce_interlock_off())
|
|
375
|
+
|
|
284
376
|
async def async_set_brightness(self, brightness: int, timestamp: float | None = None) -> None:
|
|
285
377
|
"""Set brightness on the remote light output.
|
|
286
378
|
|
|
@@ -386,9 +478,138 @@ class RemoteOutputBase:
|
|
|
386
478
|
area=self.area,
|
|
387
479
|
remote=True,
|
|
388
480
|
brightness=self._brightness,
|
|
481
|
+
interlock_groups=self._interlock_groups,
|
|
389
482
|
)
|
|
390
483
|
self._event_bus.trigger_event(OutputEvent(entity_id=self._id, state=output_state))
|
|
391
484
|
|
|
485
|
+
# ------------------------------------------------------------------
|
|
486
|
+
# Momentary actions (auto-off / auto-on after delay)
|
|
487
|
+
# ------------------------------------------------------------------
|
|
488
|
+
|
|
489
|
+
def _execute_momentary_turn(self, momentary_type: str) -> None:
|
|
490
|
+
"""Schedule momentary action (auto-off after ON, or auto-on after OFF).
|
|
491
|
+
|
|
492
|
+
If adjustable_duration is enabled and this is a turn-ON action,
|
|
493
|
+
the slider value is used instead of the static momentary_turn_on.
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
momentary_type: ON or OFF.
|
|
497
|
+
"""
|
|
498
|
+
if self._loop is None:
|
|
499
|
+
try:
|
|
500
|
+
self._loop = asyncio.get_running_loop()
|
|
501
|
+
except RuntimeError:
|
|
502
|
+
return
|
|
503
|
+
|
|
504
|
+
if self._momentary_action:
|
|
505
|
+
_LOGGER.debug("Cancelling momentary action for %s", self._name)
|
|
506
|
+
self._momentary_action()
|
|
507
|
+
|
|
508
|
+
if momentary_type == ON:
|
|
509
|
+
action = self.async_turn_off
|
|
510
|
+
if self._adjustable_duration_enabled:
|
|
511
|
+
delayed_action = TimePeriod(seconds=self._adjustable_duration)
|
|
512
|
+
else:
|
|
513
|
+
delayed_action = self._momentary_turn_on
|
|
514
|
+
else:
|
|
515
|
+
action = self.async_turn_on
|
|
516
|
+
delayed_action = self._momentary_turn_off
|
|
517
|
+
|
|
518
|
+
if delayed_action:
|
|
519
|
+
_LOGGER.debug(
|
|
520
|
+
"Scheduling momentary action for %s in %s",
|
|
521
|
+
self._name,
|
|
522
|
+
delayed_action.as_timedelta,
|
|
523
|
+
)
|
|
524
|
+
self._momentary_action = async_track_point_in_time(
|
|
525
|
+
loop=self._loop,
|
|
526
|
+
job=self._momentary_callback,
|
|
527
|
+
point_in_time=utcnow() + delayed_action.as_timedelta,
|
|
528
|
+
action=action,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
@callback
|
|
532
|
+
async def _momentary_callback(self, timestamp: float, action: Any) -> None:
|
|
533
|
+
"""Execute the scheduled momentary turn-on or turn-off."""
|
|
534
|
+
_LOGGER.info("Momentary callback at %s for remote output %s", timestamp, self._name)
|
|
535
|
+
await action(timestamp=timestamp)
|
|
536
|
+
self._momentary_action = None
|
|
537
|
+
|
|
538
|
+
# -- Adjustable duration -------------------------------------------------
|
|
539
|
+
|
|
540
|
+
@property
|
|
541
|
+
def adjustable_duration_enabled(self) -> bool:
|
|
542
|
+
"""Whether this output has an adjustable duration (HA number entity)."""
|
|
543
|
+
return self._adjustable_duration_enabled
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def adjustable_duration(self) -> float:
|
|
547
|
+
"""Current adjustable duration value in seconds."""
|
|
548
|
+
return self._adjustable_duration
|
|
549
|
+
|
|
550
|
+
@property
|
|
551
|
+
def duration_min(self) -> float:
|
|
552
|
+
"""Minimum duration in seconds for HA slider."""
|
|
553
|
+
return self._duration_min
|
|
554
|
+
|
|
555
|
+
@property
|
|
556
|
+
def duration_max(self) -> float:
|
|
557
|
+
"""Maximum duration in seconds for HA slider."""
|
|
558
|
+
return self._duration_max
|
|
559
|
+
|
|
560
|
+
@property
|
|
561
|
+
def duration_unit(self) -> str:
|
|
562
|
+
"""Unit of measurement for HA number entity ('s' or 'min')."""
|
|
563
|
+
return self._duration_unit
|
|
564
|
+
|
|
565
|
+
def set_adjustable_duration(self, seconds: float) -> None:
|
|
566
|
+
"""Set the adjustable duration value.
|
|
567
|
+
|
|
568
|
+
Clamps to [duration_min, duration_max].
|
|
569
|
+
|
|
570
|
+
Args:
|
|
571
|
+
seconds: New duration in seconds.
|
|
572
|
+
"""
|
|
573
|
+
self._adjustable_duration = max(self._duration_min, min(self._duration_max, seconds))
|
|
574
|
+
_LOGGER.debug(
|
|
575
|
+
"Remote output '%s' adjustable duration set to %.1fs",
|
|
576
|
+
self.id,
|
|
577
|
+
self._adjustable_duration,
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
def restore_adjustable_duration(self, seconds: float) -> None:
|
|
581
|
+
"""Restore persisted duration value.
|
|
582
|
+
|
|
583
|
+
Args:
|
|
584
|
+
seconds: Persisted duration value.
|
|
585
|
+
"""
|
|
586
|
+
self._adjustable_duration = max(self._duration_min, min(self._duration_max, seconds))
|
|
587
|
+
|
|
588
|
+
async def _enforce_interlock_off(self) -> None:
|
|
589
|
+
"""Send OFF command to remote device after interlock violation.
|
|
590
|
+
|
|
591
|
+
Called when the remote device reports ON state that violates an
|
|
592
|
+
active interlock group. Small delay allows the state to settle.
|
|
593
|
+
"""
|
|
594
|
+
await asyncio.sleep(0.1) # Allow state to settle
|
|
595
|
+
if not self._resolve_device_manager():
|
|
596
|
+
_LOGGER.error(
|
|
597
|
+
"Cannot enforce interlock OFF on '%s': no device manager",
|
|
598
|
+
self._id,
|
|
599
|
+
)
|
|
600
|
+
return
|
|
601
|
+
success = await self._device_manager.control_output(
|
|
602
|
+
output_id=self._output_id,
|
|
603
|
+
action="OFF",
|
|
604
|
+
)
|
|
605
|
+
if success:
|
|
606
|
+
_LOGGER.info("Interlock enforced: remote output '%s' turned OFF", self._id)
|
|
607
|
+
else:
|
|
608
|
+
_LOGGER.error(
|
|
609
|
+
"Failed to enforce interlock OFF on remote output '%s'",
|
|
610
|
+
self._id,
|
|
611
|
+
)
|
|
612
|
+
|
|
392
613
|
# ------------------------------------------------------------------
|
|
393
614
|
# Properties (duck-type compatible with BasicOutput)
|
|
394
615
|
# ------------------------------------------------------------------
|
|
@@ -169,6 +169,10 @@ class Manager:
|
|
|
169
169
|
# Used by the delay/delay_cancel_on action system (e.g. motion sensors)
|
|
170
170
|
self._pending_delayed_actions: dict[str, list[asyncio.Task]] = {}
|
|
171
171
|
|
|
172
|
+
# Pending remote tilt restores: key = "device_id:cover_id" -> asyncio.Task
|
|
173
|
+
# Background tasks that wait for ESPHome cover IDLE then restore tilt
|
|
174
|
+
self._pending_tilt_restores: dict[str, asyncio.Task] = {}
|
|
175
|
+
|
|
172
176
|
# Startup status tracking
|
|
173
177
|
self._startup_status: str = "initializing"
|
|
174
178
|
self._startup_complete: bool = False
|
|
@@ -1043,8 +1047,16 @@ class Manager:
|
|
|
1043
1047
|
cover.name if hasattr(cover, "name") else entity_id,
|
|
1044
1048
|
time.time() - start_time,
|
|
1045
1049
|
)
|
|
1046
|
-
|
|
1047
|
-
|
|
1050
|
+
# Signal to cover that this call originates from an action.
|
|
1051
|
+
# If restore_tilt is set in the action definition, enable tilt restore.
|
|
1052
|
+
cover._from_action = True
|
|
1053
|
+
cover._action_tilt_restore = bool(action_definition.get("restore_tilt", False))
|
|
1054
|
+
try:
|
|
1055
|
+
_f = getattr(cover, action_to_execute)
|
|
1056
|
+
await _f(**filtered_data)
|
|
1057
|
+
finally:
|
|
1058
|
+
cover._from_action = False
|
|
1059
|
+
cover._action_tilt_restore = False
|
|
1048
1060
|
|
|
1049
1061
|
elif action == OUTPUT_OVER_MQTT:
|
|
1050
1062
|
boneio_id = action_definition.get("boneio_id")
|
|
@@ -1127,6 +1139,21 @@ class Manager:
|
|
|
1127
1139
|
assert entity_id and remote_device_id # guaranteed by guard above
|
|
1128
1140
|
action_cover = action_definition.get("action_cover", "TOGGLE")
|
|
1129
1141
|
extra_data = action_definition.get("extra_data", {})
|
|
1142
|
+
restore_tilt = action_definition.get("restore_tilt", False)
|
|
1143
|
+
|
|
1144
|
+
# Save tilt before executing action (ESPHome only)
|
|
1145
|
+
saved_tilt_pct: int | None = None
|
|
1146
|
+
if restore_tilt:
|
|
1147
|
+
cover_state = self.remote_devices.get_cover_state(
|
|
1148
|
+
remote_device_id, entity_id
|
|
1149
|
+
)
|
|
1150
|
+
if cover_state and cover_state.get("tilt") is not None:
|
|
1151
|
+
saved_tilt_pct = int(round(cover_state["tilt"] * 100))
|
|
1152
|
+
_LOGGER.debug(
|
|
1153
|
+
"Remote cover %s/%s: saving tilt=%d%% for restore",
|
|
1154
|
+
remote_device_id, entity_id, saved_tilt_pct,
|
|
1155
|
+
)
|
|
1156
|
+
|
|
1130
1157
|
await self.remote_devices.control_cover(
|
|
1131
1158
|
device_id=remote_device_id,
|
|
1132
1159
|
cover_id=entity_id,
|
|
@@ -1134,6 +1161,19 @@ class Manager:
|
|
|
1134
1161
|
**extra_data,
|
|
1135
1162
|
)
|
|
1136
1163
|
|
|
1164
|
+
# Schedule background tilt restore after movement completes
|
|
1165
|
+
if saved_tilt_pct is not None and saved_tilt_pct > 0:
|
|
1166
|
+
task_key = f"{remote_device_id}:{entity_id}"
|
|
1167
|
+
# Cancel any previous pending restore for the same cover
|
|
1168
|
+
old_task = self._pending_tilt_restores.get(task_key)
|
|
1169
|
+
if old_task and not old_task.done():
|
|
1170
|
+
old_task.cancel()
|
|
1171
|
+
self._pending_tilt_restores[task_key] = asyncio.create_task(
|
|
1172
|
+
self._restore_remote_tilt(
|
|
1173
|
+
remote_device_id, entity_id, saved_tilt_pct
|
|
1174
|
+
)
|
|
1175
|
+
)
|
|
1176
|
+
|
|
1137
1177
|
async def _run_delayed_action(
|
|
1138
1178
|
self, input_id: str, action_definition: dict, delay_seconds: float
|
|
1139
1179
|
) -> None:
|
|
@@ -1203,6 +1243,58 @@ class Manager:
|
|
|
1203
1243
|
)
|
|
1204
1244
|
return cancelled
|
|
1205
1245
|
|
|
1246
|
+
async def _restore_remote_tilt(
|
|
1247
|
+
self, device_id: str, cover_id: str, tilt_pct: int
|
|
1248
|
+
) -> None:
|
|
1249
|
+
"""Restore tilt position on a remote ESPHome cover after movement.
|
|
1250
|
+
|
|
1251
|
+
Waits for the cover to reach IDLE state, then sends a set_tilt
|
|
1252
|
+
command to restore the previously saved tilt position.
|
|
1253
|
+
|
|
1254
|
+
Args:
|
|
1255
|
+
device_id: Remote device ID
|
|
1256
|
+
cover_id: Cover entity ID on the remote device
|
|
1257
|
+
tilt_pct: Tilt position to restore (0-100)
|
|
1258
|
+
"""
|
|
1259
|
+
task_key = f"{device_id}:{cover_id}"
|
|
1260
|
+
try:
|
|
1261
|
+
_LOGGER.debug(
|
|
1262
|
+
"Waiting for remote cover %s/%s to reach IDLE before restoring tilt=%d%%",
|
|
1263
|
+
device_id, cover_id, tilt_pct,
|
|
1264
|
+
)
|
|
1265
|
+
# Wait for cover to stop moving (up to 120s)
|
|
1266
|
+
if not await self.remote_devices.wait_for_cover_idle(device_id, cover_id):
|
|
1267
|
+
_LOGGER.warning(
|
|
1268
|
+
"Remote cover %s/%s did not reach IDLE, skipping tilt restore",
|
|
1269
|
+
device_id, cover_id,
|
|
1270
|
+
)
|
|
1271
|
+
return
|
|
1272
|
+
|
|
1273
|
+
# Small settle delay to avoid command overlap
|
|
1274
|
+
await asyncio.sleep(0.5)
|
|
1275
|
+
|
|
1276
|
+
_LOGGER.info(
|
|
1277
|
+
"Restoring tilt=%d%% on remote cover %s/%s",
|
|
1278
|
+
tilt_pct, device_id, cover_id,
|
|
1279
|
+
)
|
|
1280
|
+
await self.remote_devices.control_cover(
|
|
1281
|
+
device_id=device_id,
|
|
1282
|
+
cover_id=cover_id,
|
|
1283
|
+
action="TILT",
|
|
1284
|
+
tilt_position=tilt_pct,
|
|
1285
|
+
)
|
|
1286
|
+
except asyncio.CancelledError:
|
|
1287
|
+
_LOGGER.debug(
|
|
1288
|
+
"Remote tilt restore cancelled for %s/%s (new action triggered?)",
|
|
1289
|
+
device_id, cover_id,
|
|
1290
|
+
)
|
|
1291
|
+
except Exception:
|
|
1292
|
+
_LOGGER.exception(
|
|
1293
|
+
"Failed to restore tilt on remote cover %s/%s", device_id, cover_id
|
|
1294
|
+
)
|
|
1295
|
+
finally:
|
|
1296
|
+
self._pending_tilt_restores.pop(task_key, None)
|
|
1297
|
+
|
|
1206
1298
|
def _reload_logger(self) -> None:
|
|
1207
1299
|
"""Reload logger configuration from config file.
|
|
1208
1300
|
|
|
@@ -1300,6 +1392,25 @@ class Manager:
|
|
|
1300
1392
|
area = out_cfg.get("area")
|
|
1301
1393
|
on_disconnect = str(out_cfg.get("on_disconnect", "ignore"))
|
|
1302
1394
|
|
|
1395
|
+
# Interlock configuration
|
|
1396
|
+
interlock_groups = out_cfg.get("interlock_group", [])
|
|
1397
|
+
if isinstance(interlock_groups, str):
|
|
1398
|
+
interlock_groups = [interlock_groups]
|
|
1399
|
+
enforce_interlock = bool(out_cfg.get("enforce_interlock", False))
|
|
1400
|
+
|
|
1401
|
+
# Momentary actions
|
|
1402
|
+
momentary_turn_on = out_cfg.get("momentary_turn_on")
|
|
1403
|
+
momentary_turn_off = out_cfg.get("momentary_turn_off")
|
|
1404
|
+
|
|
1405
|
+
# Adjustable duration
|
|
1406
|
+
adjustable_duration_enabled = bool(out_cfg.get("adjustable_duration", False))
|
|
1407
|
+
from boneio.core.utils.timeperiod import parse_time_to_seconds
|
|
1408
|
+
|
|
1409
|
+
dur_default = parse_time_to_seconds(out_cfg.get("duration_default"), 60.0)
|
|
1410
|
+
dur_min = max(1.0, parse_time_to_seconds(out_cfg.get("duration_min"), 1.0))
|
|
1411
|
+
dur_max = max(dur_min, parse_time_to_seconds(out_cfg.get("duration_max"), 3600.0))
|
|
1412
|
+
dur_unit = str(out_cfg.get("duration_unit", "s"))
|
|
1413
|
+
|
|
1303
1414
|
# Check for duplicates
|
|
1304
1415
|
if self.outputs.get_output(entity_id) is not None:
|
|
1305
1416
|
_LOGGER.warning(
|
|
@@ -1319,8 +1430,22 @@ class Manager:
|
|
|
1319
1430
|
show_in_ha=show_in_ha,
|
|
1320
1431
|
area=area,
|
|
1321
1432
|
on_disconnect=on_disconnect,
|
|
1433
|
+
interlock_manager=self.outputs._interlock_manager,
|
|
1434
|
+
interlock_groups=interlock_groups,
|
|
1435
|
+
enforce_interlock=enforce_interlock,
|
|
1436
|
+
momentary_turn_on=momentary_turn_on,
|
|
1437
|
+
momentary_turn_off=momentary_turn_off,
|
|
1438
|
+
adjustable_duration=adjustable_duration_enabled,
|
|
1439
|
+
duration_default=dur_default,
|
|
1440
|
+
duration_min=dur_min,
|
|
1441
|
+
duration_max=dur_max,
|
|
1442
|
+
duration_unit=dur_unit,
|
|
1322
1443
|
)
|
|
1323
1444
|
|
|
1445
|
+
# Register in shared interlock manager
|
|
1446
|
+
if interlock_groups:
|
|
1447
|
+
self.outputs._interlock_manager.register(remote_output, interlock_groups)
|
|
1448
|
+
|
|
1324
1449
|
# Set the device manager reference if the device is already loaded.
|
|
1325
1450
|
# ESPHome devices may not be in _devices yet (loaded in background),
|
|
1326
1451
|
# so _device_manager may remain None — resolved lazily in
|
|
@@ -1342,11 +1467,12 @@ class Manager:
|
|
|
1342
1467
|
# Register in OutputManager so it's available everywhere
|
|
1343
1468
|
self.outputs._outputs[entity_id] = remote_output # type: ignore[assignment]
|
|
1344
1469
|
_LOGGER.info(
|
|
1345
|
-
"Registered remote output: id='%s' device='%s' output='%s' type='%s'",
|
|
1470
|
+
"Registered remote output: id='%s' device='%s' output='%s' type='%s' interlock=%s",
|
|
1346
1471
|
entity_id,
|
|
1347
1472
|
device_id,
|
|
1348
1473
|
output_id,
|
|
1349
1474
|
output_type,
|
|
1475
|
+
interlock_groups or "none",
|
|
1350
1476
|
)
|
|
1351
1477
|
|
|
1352
1478
|
_LOGGER.info(
|
|
@@ -609,6 +609,64 @@ class RemoteDeviceManager:
|
|
|
609
609
|
**kwargs,
|
|
610
610
|
)
|
|
611
611
|
|
|
612
|
+
def get_cover_state(self, device_id: str, cover_id: str) -> dict[str, Any] | None:
|
|
613
|
+
"""Get current cover state from an ESPHome remote device.
|
|
614
|
+
|
|
615
|
+
Returns the cached state dict containing position, tilt,
|
|
616
|
+
current_operation, and last_known_operation.
|
|
617
|
+
|
|
618
|
+
Args:
|
|
619
|
+
device_id: ID of the remote device
|
|
620
|
+
cover_id: ID of the cover
|
|
621
|
+
|
|
622
|
+
Returns:
|
|
623
|
+
State dictionary or None if device/cover not found or not ESPHome
|
|
624
|
+
"""
|
|
625
|
+
device = self.get_device(device_id)
|
|
626
|
+
if not device or device.protocol != RemoteDeviceProtocol.ESPHOME_API:
|
|
627
|
+
return None
|
|
628
|
+
return cast(Any, device)._cover_states.get(cover_id)
|
|
629
|
+
|
|
630
|
+
async def wait_for_cover_idle(
|
|
631
|
+
self,
|
|
632
|
+
device_id: str,
|
|
633
|
+
cover_id: str,
|
|
634
|
+
timeout: float = 120.0,
|
|
635
|
+
poll_interval: float = 0.5,
|
|
636
|
+
) -> bool:
|
|
637
|
+
"""Wait for an ESPHome cover to reach IDLE state.
|
|
638
|
+
|
|
639
|
+
Polls the cached cover state until current_operation becomes 0 (IDLE)
|
|
640
|
+
or the timeout expires.
|
|
641
|
+
|
|
642
|
+
Args:
|
|
643
|
+
device_id: ID of the remote device
|
|
644
|
+
cover_id: ID of the cover to monitor
|
|
645
|
+
timeout: Maximum time to wait in seconds (default: 120s)
|
|
646
|
+
poll_interval: Time between polls in seconds (default: 0.5s)
|
|
647
|
+
|
|
648
|
+
Returns:
|
|
649
|
+
True if cover reached IDLE, False on timeout
|
|
650
|
+
"""
|
|
651
|
+
device = self.get_device(device_id)
|
|
652
|
+
if not device or device.protocol != RemoteDeviceProtocol.ESPHOME_API:
|
|
653
|
+
return False
|
|
654
|
+
|
|
655
|
+
esphome = cast(Any, device)
|
|
656
|
+
start = asyncio.get_event_loop().time()
|
|
657
|
+
|
|
658
|
+
while asyncio.get_event_loop().time() - start < timeout:
|
|
659
|
+
state = esphome._cover_states.get(cover_id, {})
|
|
660
|
+
if state.get("current_operation", 0) == 0:
|
|
661
|
+
return True
|
|
662
|
+
await asyncio.sleep(poll_interval)
|
|
663
|
+
|
|
664
|
+
_LOGGER.warning(
|
|
665
|
+
"Timeout (%.0fs) waiting for cover '%s' on device '%s' to reach IDLE",
|
|
666
|
+
timeout, cover_id, device_id,
|
|
667
|
+
)
|
|
668
|
+
return False
|
|
669
|
+
|
|
612
670
|
async def reload(self, remote_devices_config: list[dict[str, Any]] | None = None) -> None:
|
|
613
671
|
"""Reload remote devices from config.
|
|
614
672
|
|
|
@@ -69,6 +69,17 @@ schema:
|
|
|
69
69
|
Position threshold for SMART_TOGGLE action.
|
|
70
70
|
If cover position is at or below this value, it will always open.
|
|
71
71
|
Above this value, normal toggle behavior applies.
|
|
72
|
+
restore_tilt:
|
|
73
|
+
type: boolean
|
|
74
|
+
required: False
|
|
75
|
+
default: false
|
|
76
|
+
meta:
|
|
77
|
+
label: Restore Tilt After Movement
|
|
78
|
+
description: |
|
|
79
|
+
When true, the previous tilt angle is saved before executing this cover action
|
|
80
|
+
and restored after the movement finishes. Only applies to venetian covers.
|
|
81
|
+
Example: pressing a button to close the blinds to 50% and then restoring
|
|
82
|
+
the slat angle to the previous value.
|
|
72
83
|
action_output:
|
|
73
84
|
type: string
|
|
74
85
|
required_if:
|