boneio 1.5.0.dev41__tar.gz → 1.5.2.dev1__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.5.0.dev41/boneio.egg-info → boneio-1.5.2.dev1}/PKG-INFO +1 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/bonecli.py +0 -3
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/time_based.py +14 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/venetian.py +14 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/irrigation/controller.py +29 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/yaml_util.py +49 -6
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/covers.py +18 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/outputs.py +45 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/update.py +21 -4
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/system/monitor.py +18 -2
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/async_updater.py +30 -2
- boneio-1.5.2.dev1/boneio/core/utils/overlay.py +159 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/oled.py +6 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/mcp23017.py +163 -21
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/homeassistant.py +4 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/actions.py +68 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/MANIFEST.sha256 +11 -4
- boneio-1.5.2.dev1/boneio/migrations/assets/journald/journald.conf +43 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/kernel/postinst-boneio-overlay +79 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/boneio-oled-boot.service +30 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/boneio.service +49 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/avahi-daemon-defer.conf +11 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/bb-usb-gadgets-defer.conf +22 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/mosquitto-priority.conf +16 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/timer-no-persistent.conf +21 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/user-manager-defer.conf +27 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/systemd/linger-marker +0 -0
- boneio-1.5.2.dev1/boneio/migrations/assets/usr-local-bin/set-hostname-once.sh +15 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/bootstrap/boneio-migrate +130 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/runner.py +155 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_10_disable_console_setup.py +33 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_11_timer_catchup.py +64 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_12_oled_splash_off_critical_path.py +69 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_13_mosquitto_priority.py +43 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_14_journal_apparent_size.py +50 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_15_prune_orphan_journals.py +37 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_16_login_linger.py +53 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_17_defer_user_manager.py +60 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_18_fix_hostname_once.py +57 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_5_overlay_kernel_hook.py +32 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_6_boot_service_order.py +59 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_7_journald_limits.py +47 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_8_apparmor_prune.py +72 -0
- boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_9_defer_nonessential.py +50 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/wanas415.json +1 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/runner.py +4 -1
- boneio-1.5.2.dev1/boneio/version.py +2 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/action_validation.py +7 -4
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/BindingMatrix-nIxlEHTd.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/BindingMatrix-D1OvlTso.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/ConfigEditor-set_Qoo1.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/ConfigEditor-Bdpm9_Qo.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/EditItemDialog-_53aIb2_.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/EditItemDialog-BIjzsrqq.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/EntityCard-D74vPKzA.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/EntityCard-CJ0ccsW1.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/EntityGrid-BN3hkCWK.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/EntityGrid-xCqfJxkw.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/FormInputToggle-C3N_UWzy.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/FormInputToggle-Cn_hJrna.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/InputsView-B7on4rOh.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/InputsView-CySRVJ90.js +1 -1
- boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/LogViewer-Bs7Xx9vL.js +2 -0
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/ModbusView-Dwd3_KJS.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/ModbusView-8rNY0iJT.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/NodeRedView--ogT6Dbm.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/NodeRedView-DD2w3NAX.js +1 -1
- boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/OutputsView-B6cZ8NHI.js +1 -0
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/SensorView-C3kPKCFf.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/SensorView-DsdnJqni.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/SudoPasswordDialog-DS-3pCx-.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/SudoPasswordDialog-W42OQ76m.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/SystemState-CUmudnMp.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/SystemState-De_QpQ-z.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/TemplatesView-CFa1qlRa.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/TemplatesView-CuLPA7iV.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/Tools-CUS0azhR.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/Tools-DOmBe8W2.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/UISettings-BWNODvh7.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/UISettings-CtJheTh8.js +3 -3
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/gi-7Mj_ioeM.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/gi-czqU2m4e.js +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/index-FA3V0TxG.css → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/index-CJSdgTd5.css +1 -1
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/index-N_Atf1i3.js → boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/index-DCzOrheh.js +2 -2
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/index.html +2 -2
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/sw.js +1 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_core.py +20 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/nodered.py +28 -2
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/system.py +35 -10
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/update.py +34 -2
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1/boneio.egg-info}/PKG-INFO +1 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/SOURCES.txt +42 -20
- boneio-1.5.0.dev41/boneio/migrations/assets/journald/journald.conf +0 -6
- boneio-1.5.0.dev41/boneio/migrations/assets/systemd/boneio-oled-boot.service +0 -17
- boneio-1.5.0.dev41/boneio/migrations/assets/systemd/boneio.service +0 -15
- boneio-1.5.0.dev41/boneio/migrations/assets/usr-local-bin/set-hostname-once.sh +0 -10
- boneio-1.5.0.dev41/boneio/version.py +0 -2
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/LogViewer-RefUkoWR.js +0 -2
- boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/OutputsView-BxFJRwd4.js +0 -1
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/LICENSE +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/MANIFEST.in +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/README.md +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_32_5.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_32_5.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_32_5.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_48_4.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_48_4.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/input.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_32_10.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_48_4.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_cover_mix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/cover.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/group/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/group/output_group.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/binary_sensor.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/detectors.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/event.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/remote/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/remote/base.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/remote/esphome.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/irrigation/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/irrigation/water_source.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/basic.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/buzzer.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/mcp.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/pca.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/pcf.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/remote.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/sensor/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/sensor/virtual_energy.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/alarm_panel.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/gate_cover.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/thermostat.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/const.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/docker-compose-cloud.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/docker-compose.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/init-certs-cloud.sh +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/registration.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/secrets.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/config_helper.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v1_proxy_port.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v2_transition.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v4_wled_cache.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v5_ina_screen.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/package-lock.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/package.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/schema_converter.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/yaml_compat.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/discovery.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/events/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/events/bus.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/action_conditions.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/canopen.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/display.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/inputs.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/irrigation.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/manager.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/modbus.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/remote.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/remote_input_registrar.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/sensors.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/alarm.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/gate_cover.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/thermostat.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/basic.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/basic_mqtt.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/composite.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/local.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/lox.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/mqtt.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/queue.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/base.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/can.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/esphome.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/mqtt.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/wled.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/wled_cache.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/sensor/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/sensor/base.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/sensor/system.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/state/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/state/manager.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/system/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/system/host_data.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/conditions.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/filter.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/font_util.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/logger.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/timeperiod.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/util.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/config.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/event.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/mqtt.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/output48x4A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/can_master.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/can_slave.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/exceptions.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/analog/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/analog/adc.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/bridge.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/client.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/interface.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/node.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/node_id.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/test_od.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/early_oled.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/fonts/danube__.ttf +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/input/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/input/base.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/input/manager.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/bus.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina219.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina219_driver.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina226.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina226_driver.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/mcp9808.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/pct2075.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/onewire/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/onewire/dallas.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/base.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/interlock.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/lox_template.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/daemon.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/caddy/502.html +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/caddy/init-certs.sh +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/docker-compose.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/nginx/default.conf +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/node-red/settings.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/modules-load.d/onewire.conf +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/mosquitto/boneio.conf +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/sudoers/boneio +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/systemd/boneio-oled-shutdown.service +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/systemd/set-hostname-once.service +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_boot_splash.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_boot_splash.sh +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_msg.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_msg.sh +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/wheels/pyyaml-6.0.3-cp313-cp313-linux_armv7l.whl +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/bootstrap/install-helper.sh +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/bootstrap/sudoers-migrate +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_3_0_baseline.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_3_1_fix_oled_boot.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_3_2_cleanup_can_sudoers.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_4_0_fix_mqtt_sudoers.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_4_3_oled_shutdown.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_4_4_caddy.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_0_fix_oled_fifo_permissions.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_1_ufw_lox_udp.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_2_libyaml.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_3_libyaml_retry.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_4_onewire_modules.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/cli.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/client.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/coordinator.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/dts1964_3f.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/le-03mw.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/le-03mwct.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/socomec_e03.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/socomec_e23.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/eht-topventil-plus.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/thessla.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/ventclear.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/inverters/sofar.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/other/esp32_relay_x4_modbus.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/other/n4dsc08.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/other/r4dcb08.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/boneio-edge-temp.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/cwt.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/dyp-a12-ultrasonic.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/gdfs.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/gdfx.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/pt100.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/qdw90a.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/sht20.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/sht30.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/base.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/numeric.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/select.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/switch.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/text.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/binary.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/numeric.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/text.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/writeable/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/writeable/binary.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/writeable/numeric.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/mock_coordinator.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/utils.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/actions.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/events.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/files.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/logs.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/mqtt.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/state.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/actions.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/condition.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/filters.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/id.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/remote_devices.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/remote_inputs.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/remote_outputs.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/schema.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/update_interval.yaml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/app.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/dashboard_cards.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/HelpLabel-BSTjOtDA.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/LongPressWrapper-BHOQV7Wq.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/Sparkline-BGWlVLtt.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/aiConfig-IRYCBmLm.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/aiWizardPrompt-D9OJ-cE7.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/axios-DHUeYRnu.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/basePath-CxHj-SSK.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/clipboard-CCtx29e-.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/codicon-ngg6Pgfi.ttf +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/configCache-BAkc0Ye7.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/css.worker-CvXBzhp8.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/editor.worker-Cn2oRESe.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/formatters-zOiGPJLh.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/html.worker-BO6WuOEO.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/json.worker-BkJRGcCJ.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/longPress-Dx7OCSyP.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/modbusDeviceCatalog-L6as-BKo.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/monaco-61yH0vfd.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/monaco-Br_kD0ds.css +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/rolldown-runtime-QTnfLwEv.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/select-B2YDgQ4X.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/tabs-box-Dj36r4_e.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/ts.worker-B0J26iPs.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/utils-C8nShLO6.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/vendor-IzweXARb.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/yaml.worker-BKRoXlmz.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio-192.png +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio-512.png +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/adc.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/areas.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/binary_sensor.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/boneio.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/can.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/config.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/cover.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/dallas.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/ds2482.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/event.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/ina219.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/ina226.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/irrigation.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/lm75.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/logger.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/lox_udp.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/mcp23017.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/mcp9808.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/modbus.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/modbus_devices.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/mqtt.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/oled.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/output.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/output_group.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/pca9685.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/pcf8575.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/remote_devices.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/remote_inputs.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/remote_outputs.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/sensor.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/template.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/web.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/workbox-4918f2f6.js +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/hvac_svg_templates.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/middleware/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/middleware/auth.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/modbus_card_templates.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/auth.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/caddy.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/can.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_actions.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_backups.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_discovery.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_files.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/covers.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/dashboard.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/dev_fake_device.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/irrigation.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/migrations.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/modbus.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/mqtt_reference.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/outputs.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/remote_devices.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/sensors.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/templates.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/timezone_sudoers.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/tools.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/areas.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/binary_sensor.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/boneio.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/can.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/config.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/event.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/ina226.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/irrigation.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/lox_udp.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/modbus_devices.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/mqtt.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/output.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/remote_devices.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/remote_inputs.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/remote_outputs.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/template.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/web.schema.json +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/services/__init__.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/services/logs.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/sudo_rate_limiter.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/web_server.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/websocket_manager.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/dependency_links.txt +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/entry_points.txt +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/requires.txt +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/top_level.txt +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/pyproject.toml +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/setup.cfg +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/setup.py +0 -0
- {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/tests/test_py313_compatibility.py +0 -0
|
@@ -258,9 +258,6 @@ def run(
|
|
|
258
258
|
from boneio.const import ACTION
|
|
259
259
|
_LOGGER.debug("[RUNNER IMPORT] boneio.const: %.2fs", _time.monotonic() - _t_a)
|
|
260
260
|
_t_a = _time.monotonic()
|
|
261
|
-
from boneio.core.cloud import CloudRegistration
|
|
262
|
-
_LOGGER.debug("[RUNNER IMPORT] boneio.core.cloud: %.2fs", _time.monotonic() - _t_a)
|
|
263
|
-
_t_a = _time.monotonic()
|
|
264
261
|
from boneio.core.manager import Manager
|
|
265
262
|
_LOGGER.debug("[RUNNER IMPORT] boneio.core.manager: %.2fs", _time.monotonic() - _t_a)
|
|
266
263
|
_t_a = _time.monotonic()
|
|
@@ -61,6 +61,20 @@ class TimeBasedCover(BaseCover):
|
|
|
61
61
|
else:
|
|
62
62
|
return
|
|
63
63
|
|
|
64
|
+
if duration == 0:
|
|
65
|
+
# A zero open_time/close_time makes movement impossible: the guard
|
|
66
|
+
# below returns before relay.turn_on(), so the relay is never
|
|
67
|
+
# energised and the motor never gets voltage — while the cover still
|
|
68
|
+
# reports IDLE and publishes state, so the UI looks like it worked.
|
|
69
|
+
# This is always a misconfiguration, never a normal outcome.
|
|
70
|
+
_LOGGER.error(
|
|
71
|
+
"Cover %s cannot move %s: %s_time is 0. The relay will NOT be "
|
|
72
|
+
"switched. Set a non-zero time in the cover configuration.",
|
|
73
|
+
self._id,
|
|
74
|
+
direction,
|
|
75
|
+
"open" if direction == OPEN else "close",
|
|
76
|
+
)
|
|
77
|
+
|
|
64
78
|
if total_steps == 0 or duration == 0:
|
|
65
79
|
self._current_operation = IDLE
|
|
66
80
|
with suppress(RuntimeError):
|
|
@@ -93,6 +93,20 @@ class VenetianCover(BaseCover, BaseVenetianCoverABC):
|
|
|
93
93
|
else:
|
|
94
94
|
total_steps = 1
|
|
95
95
|
|
|
96
|
+
if duration == 0:
|
|
97
|
+
# A zero open_time/close_time makes movement impossible: the guard
|
|
98
|
+
# below returns before relay.turn_on(), so the relay is never
|
|
99
|
+
# energised and the motor never gets voltage — while the cover still
|
|
100
|
+
# reports IDLE and publishes state, so the UI looks like it worked.
|
|
101
|
+
# This is always a misconfiguration, never a normal outcome.
|
|
102
|
+
_LOGGER.error(
|
|
103
|
+
"Cover %s cannot move %s: %s_time is 0. The relay will NOT be "
|
|
104
|
+
"switched. Set a non-zero time in the cover configuration.",
|
|
105
|
+
self._id,
|
|
106
|
+
direction,
|
|
107
|
+
"open" if direction == OPEN else "close",
|
|
108
|
+
)
|
|
109
|
+
|
|
96
110
|
if total_steps == 0 or duration == 0:
|
|
97
111
|
self._current_operation = IDLE
|
|
98
112
|
self._loop.call_soon_threadsafe(self.send_state, self.state, self.json_position)
|
|
@@ -1010,6 +1010,13 @@ class IrrigationController:
|
|
|
1010
1010
|
await self.next_valve()
|
|
1011
1011
|
|
|
1012
1012
|
async def handle_zone_command(self, zone_id: str, payload: str) -> None:
|
|
1013
|
+
"""Handle ON/OFF command for a specific zone.
|
|
1014
|
+
|
|
1015
|
+
ON starts the zone in single-zone mode (shutting down any running cycle first).
|
|
1016
|
+
OFF only shuts down the controller if ``zone_id`` matches the currently
|
|
1017
|
+
active zone — this prevents HA state-sync messages (OFF for inactive
|
|
1018
|
+
zones) from killing a running cycle.
|
|
1019
|
+
"""
|
|
1013
1020
|
upper = payload.strip().upper()
|
|
1014
1021
|
_LOGGER.debug(
|
|
1015
1022
|
"Irrigation %s handle_zone_command: zone='%s' payload='%s' → upper='%s'", self.id, zone_id, payload, upper
|
|
@@ -1017,7 +1024,28 @@ class IrrigationController:
|
|
|
1017
1024
|
if upper == ON:
|
|
1018
1025
|
await self.start_single_zone(zone_id)
|
|
1019
1026
|
elif upper == OFF:
|
|
1020
|
-
|
|
1027
|
+
# Only shutdown if this zone is the one currently running.
|
|
1028
|
+
# HA sends OFF to all zone switches when one is activated,
|
|
1029
|
+
# so we must NOT shutdown the controller for inactive zones.
|
|
1030
|
+
if self._state == ControllerState.IDLE:
|
|
1031
|
+
return
|
|
1032
|
+
active_zone = (
|
|
1033
|
+
self._zones[self._active_zone_idx]
|
|
1034
|
+
if self._active_zone_idx is not None and self._active_zone_idx < len(self._zones)
|
|
1035
|
+
else None
|
|
1036
|
+
)
|
|
1037
|
+
if active_zone is not None and active_zone.id == zone_id:
|
|
1038
|
+
_LOGGER.info(
|
|
1039
|
+
"Irrigation %s: OFF received for active zone '%s' — shutting down",
|
|
1040
|
+
self.id, zone_id,
|
|
1041
|
+
)
|
|
1042
|
+
await self.shutdown()
|
|
1043
|
+
else:
|
|
1044
|
+
_LOGGER.debug(
|
|
1045
|
+
"Irrigation %s: ignoring OFF for zone '%s' (active zone is '%s')",
|
|
1046
|
+
self.id, zone_id,
|
|
1047
|
+
active_zone.id if active_zone else "none",
|
|
1048
|
+
)
|
|
1021
1049
|
|
|
1022
1050
|
async def handle_zone_duration_command(self, zone_id: str, payload: str) -> None:
|
|
1023
1051
|
"""Handle duration change from HA (value in minutes)."""
|
|
@@ -720,13 +720,17 @@ class CustomValidator(Validator):
|
|
|
720
720
|
return result
|
|
721
721
|
|
|
722
722
|
def _normalize_coerce_positive_time_period(self, value) -> TimePeriod:
|
|
723
|
-
"""Validate and transform time period with time unit and integer value.
|
|
724
|
-
|
|
723
|
+
"""Validate and transform time period with time unit and integer value.
|
|
724
|
+
|
|
725
|
+
Bare integers (e.g. ``30``) are treated as **milliseconds** for
|
|
726
|
+
backward compatibility — the frontend and earlier configs sometimes
|
|
727
|
+
omit the unit for bounce_time / duration fields.
|
|
728
|
+
"""
|
|
729
|
+
if isinstance(value, (int, float)):
|
|
725
730
|
if value == 0:
|
|
726
731
|
return TimePeriod(seconds=0)
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
)
|
|
732
|
+
# Treat bare numbers as milliseconds for backward compatibility
|
|
733
|
+
return TimePeriod(milliseconds=float(value))
|
|
730
734
|
if isinstance(value, TimePeriod):
|
|
731
735
|
value = str(value)
|
|
732
736
|
if not isinstance(value, str):
|
|
@@ -759,7 +763,14 @@ class CustomValidator(Validator):
|
|
|
759
763
|
match = re.match(r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*)$", value)
|
|
760
764
|
if match is None:
|
|
761
765
|
raise ConfigurationException(f"Expected time period with unit, got {value}")
|
|
762
|
-
|
|
766
|
+
|
|
767
|
+
unit_str = match.group(2)
|
|
768
|
+
# Bare number without unit (e.g. '30' from coerce: str on int 30)
|
|
769
|
+
# → treat as milliseconds for backward compatibility
|
|
770
|
+
if not unit_str:
|
|
771
|
+
return TimePeriod(milliseconds=float(match.group(1)))
|
|
772
|
+
|
|
773
|
+
kwarg = unit_to_kwarg[one_of(*unit_to_kwarg)(unit_str)]
|
|
763
774
|
return TimePeriod(**{kwarg: float(match.group(1))})
|
|
764
775
|
|
|
765
776
|
def _lookup_field(self, path: str) -> tuple:
|
|
@@ -928,6 +939,30 @@ def _run_config_migrations(doc: dict, config_file: str | None = None) -> tuple[d
|
|
|
928
939
|
return doc, new_version > current_version
|
|
929
940
|
|
|
930
941
|
|
|
942
|
+
def _strip_empty_strings_deep(obj: Any) -> Any:
|
|
943
|
+
"""Recursively remove dictionary keys whose value is an empty string.
|
|
944
|
+
|
|
945
|
+
The frontend may occasionally persist ``''`` for optional fields
|
|
946
|
+
(e.g. ``bounce_time: ''``). Cerberus ``positive_time_period``
|
|
947
|
+
coercion fails on bare empty strings, so we strip them before
|
|
948
|
+
normalization. Only *empty* strings are removed – non-empty strings
|
|
949
|
+
and other falsy values (``0``, ``False``, ``None``) are preserved.
|
|
950
|
+
"""
|
|
951
|
+
if isinstance(obj, dict):
|
|
952
|
+
return {
|
|
953
|
+
k: _strip_empty_strings_deep(v)
|
|
954
|
+
for k, v in obj.items()
|
|
955
|
+
if v != ""
|
|
956
|
+
}
|
|
957
|
+
if isinstance(obj, list):
|
|
958
|
+
return [
|
|
959
|
+
_strip_empty_strings_deep(item)
|
|
960
|
+
for item in obj
|
|
961
|
+
if item != ""
|
|
962
|
+
]
|
|
963
|
+
return obj
|
|
964
|
+
|
|
965
|
+
|
|
931
966
|
def load_config_from_string(config_str: str) -> dict:
|
|
932
967
|
"""Load config from string."""
|
|
933
968
|
schema = _get_schema() # Use cached schema instead of loading every time
|
|
@@ -940,6 +975,11 @@ def load_config_from_string(config_str: str) -> dict:
|
|
|
940
975
|
# (coerce: positive_time_period would fail on bare int like transition: 2)
|
|
941
976
|
migrated_doc, _ = _run_config_migrations(raw_doc, config_file=None)
|
|
942
977
|
|
|
978
|
+
# Strip empty string values that may have been saved by the frontend
|
|
979
|
+
# (e.g. bounce_time: '' instead of being omitted). Cerberus coercion
|
|
980
|
+
# for positive_time_period chokes on bare empty strings.
|
|
981
|
+
migrated_doc = _strip_empty_strings_deep(migrated_doc)
|
|
982
|
+
|
|
943
983
|
# Normalize the document (applies coercion rules)
|
|
944
984
|
doc = v.normalized(migrated_doc, always_return_document=True) # type: ignore[attr-defined]
|
|
945
985
|
|
|
@@ -1153,6 +1193,9 @@ def _full_config_validation(
|
|
|
1153
1193
|
config_yaml, migrations_applied = _run_config_migrations(config_yaml, config_file=config_file)
|
|
1154
1194
|
_LOGGER.debug("[STARTUP TIMING] migrations: %.2fs", _time.monotonic() - _t3)
|
|
1155
1195
|
|
|
1196
|
+
# Strip empty string values that may have been saved by the frontend
|
|
1197
|
+
config_yaml = _strip_empty_strings_deep(config_yaml)
|
|
1198
|
+
|
|
1156
1199
|
# Normalize the document (applies coercion rules)
|
|
1157
1200
|
_progress("Normalizing config...")
|
|
1158
1201
|
_t4 = _time.monotonic()
|
|
@@ -235,6 +235,24 @@ class CoverManager:
|
|
|
235
235
|
for time_key in ("open_time", "close_time", "actuator_activation_duration"):
|
|
236
236
|
if time_key in config and config[time_key] is not None:
|
|
237
237
|
config[time_key] = ensure_time_period(config[time_key])
|
|
238
|
+
|
|
239
|
+
# A zero open_time/close_time leaves the cover permanently immobile: the
|
|
240
|
+
# movement thread bails out before energising the relay, and from
|
|
241
|
+
# position 0% even close() short-circuits, so no command can ever move
|
|
242
|
+
# it again. The WebUI form rejects sub-second values, but a hand-edited
|
|
243
|
+
# or imported config reaches here unchecked — say so at startup instead
|
|
244
|
+
# of letting the user discover it when the blinds fail to open.
|
|
245
|
+
for time_key in ("open_time", "close_time"):
|
|
246
|
+
value = config.get(time_key)
|
|
247
|
+
if value is not None and value.total_milliseconds == 0:
|
|
248
|
+
_LOGGER.error(
|
|
249
|
+
"Cover %s has %s = 0. This cover will NOT move in that "
|
|
250
|
+
"direction — its relay is never switched. Set a non-zero "
|
|
251
|
+
"%s in the cover configuration.",
|
|
252
|
+
cover_id,
|
|
253
|
+
time_key,
|
|
254
|
+
time_key,
|
|
255
|
+
)
|
|
238
256
|
if tilt_duration is not None and not isinstance(tilt_duration, TimePeriod):
|
|
239
257
|
tilt_duration = ensure_time_period(tilt_duration)
|
|
240
258
|
|
|
@@ -64,6 +64,14 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
64
64
|
# Expander class mapping
|
|
65
65
|
_EXPANDER_CLASS = {MCP: MCP23017, PCA: PCA9685, PCF: PCF8575}
|
|
66
66
|
|
|
67
|
+
# How often to re-check that MCP23017 expanders still hold their output
|
|
68
|
+
# configuration. A brown-out or electrical noise can reset an expander back to
|
|
69
|
+
# all-inputs, which silently stops the relays from following commanded state
|
|
70
|
+
# without producing a single I2C error (see MCP23017.health_check).
|
|
71
|
+
EXPANDER_HEALTH_CHECK_INTERVAL = TimePeriod(seconds=30)
|
|
72
|
+
# Keep the first check off the startup critical path.
|
|
73
|
+
EXPANDER_HEALTH_CHECK_INITIAL_DELAY = TimePeriod(seconds=30)
|
|
74
|
+
|
|
67
75
|
|
|
68
76
|
# Map output_type -> HA availability message builder
|
|
69
77
|
_OUTPUT_HA_FUNC = {
|
|
@@ -164,6 +172,43 @@ class OutputManager:
|
|
|
164
172
|
)
|
|
165
173
|
)
|
|
166
174
|
|
|
175
|
+
if self._mcp:
|
|
176
|
+
self._manager.append_task(
|
|
177
|
+
self._expander_health_watchdog,
|
|
178
|
+
name="mcp23017_health_watchdog",
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
async def _expander_health_watchdog(self) -> None:
|
|
182
|
+
"""Periodically re-assert MCP23017 output configuration.
|
|
183
|
+
|
|
184
|
+
An expander that has been reset back to all-inputs keeps accepting
|
|
185
|
+
writes, so nothing in the write path reports a problem — the relays
|
|
186
|
+
simply stop switching until something reconfigures the chip. Without
|
|
187
|
+
this loop the only recovery is restarting boneIO.
|
|
188
|
+
|
|
189
|
+
The check is a handful of I2C reads per expander, run in the default
|
|
190
|
+
executor so the blocking bus access stays off the event loop.
|
|
191
|
+
"""
|
|
192
|
+
loop = asyncio.get_running_loop()
|
|
193
|
+
await asyncio.sleep(EXPANDER_HEALTH_CHECK_INITIAL_DELAY.total_seconds)
|
|
194
|
+
while True:
|
|
195
|
+
for expander_id, mcp in list(self._mcp.items()):
|
|
196
|
+
try:
|
|
197
|
+
repaired = await loop.run_in_executor(None, mcp.health_check)
|
|
198
|
+
except Exception as err: # noqa: BLE001 - watchdog must never die
|
|
199
|
+
_LOGGER.error(
|
|
200
|
+
"Health check for MCP %s raised: %s", expander_id, err
|
|
201
|
+
)
|
|
202
|
+
continue
|
|
203
|
+
if repaired:
|
|
204
|
+
_LOGGER.warning(
|
|
205
|
+
"MCP %s (0x%02X) was reconfigured by the health watchdog; "
|
|
206
|
+
"its outputs are driving again.",
|
|
207
|
+
expander_id,
|
|
208
|
+
mcp.address,
|
|
209
|
+
)
|
|
210
|
+
await asyncio.sleep(EXPANDER_HEALTH_CHECK_INTERVAL.total_seconds)
|
|
211
|
+
|
|
167
212
|
def _create_expander(
|
|
168
213
|
self,
|
|
169
214
|
expander_dict: dict,
|
|
@@ -43,12 +43,19 @@ class UpdateManager(AsyncUpdater):
|
|
|
43
43
|
self,
|
|
44
44
|
manager: Manager,
|
|
45
45
|
update_interval: TimePeriod | None = None,
|
|
46
|
+
initial_delay: TimePeriod | None = None,
|
|
46
47
|
):
|
|
47
48
|
"""Initialize UpdateManager.
|
|
48
49
|
|
|
49
50
|
Args:
|
|
50
51
|
manager: Parent Manager instance
|
|
51
52
|
update_interval: Time between update checks (default: 4 hours)
|
|
53
|
+
initial_delay: Delay before the first check (default: 5 minutes).
|
|
54
|
+
An update check is a GitHub round trip and is worthless to a
|
|
55
|
+
controller that is still starting up; running it immediately put
|
|
56
|
+
it squarely on the startup critical path. HA discovery for the
|
|
57
|
+
update entity is unaffected — Manager.send_ha_autodiscovery()
|
|
58
|
+
sends it as part of the normal discovery flow.
|
|
52
59
|
"""
|
|
53
60
|
self.id = "update_manager"
|
|
54
61
|
self._manager = manager
|
|
@@ -56,6 +63,8 @@ class UpdateManager(AsyncUpdater):
|
|
|
56
63
|
# Update check interval (default: 4 hours)
|
|
57
64
|
if update_interval is None:
|
|
58
65
|
update_interval = TimePeriod(hours=4)
|
|
66
|
+
if initial_delay is None:
|
|
67
|
+
initial_delay = TimePeriod(minutes=5)
|
|
59
68
|
|
|
60
69
|
# Cache for update info to avoid excessive GitHub API calls
|
|
61
70
|
self._last_check_result: dict | None = None
|
|
@@ -64,9 +73,17 @@ class UpdateManager(AsyncUpdater):
|
|
|
64
73
|
self._update_running: bool = False
|
|
65
74
|
|
|
66
75
|
# Initialize AsyncUpdater (starts periodic task)
|
|
67
|
-
super().__init__(
|
|
76
|
+
super().__init__(
|
|
77
|
+
manager=manager,
|
|
78
|
+
update_interval=update_interval,
|
|
79
|
+
initial_delay=initial_delay,
|
|
80
|
+
)
|
|
68
81
|
|
|
69
|
-
_LOGGER.info(
|
|
82
|
+
_LOGGER.info(
|
|
83
|
+
"UpdateManager initialized (check interval: %s, first check in %s)",
|
|
84
|
+
update_interval,
|
|
85
|
+
initial_delay,
|
|
86
|
+
)
|
|
70
87
|
|
|
71
88
|
async def async_update(self, timestamp: float) -> float | None:
|
|
72
89
|
"""Perform periodic update check.
|
|
@@ -124,9 +141,9 @@ class UpdateManager(AsyncUpdater):
|
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
try:
|
|
127
|
-
from boneio.webui.routes.update import
|
|
144
|
+
from boneio.webui.routes.update import _fetch_github_releases_async
|
|
128
145
|
|
|
129
|
-
releases, error =
|
|
146
|
+
releases, error = await _fetch_github_releases_async()
|
|
130
147
|
|
|
131
148
|
if error:
|
|
132
149
|
return {"status": "error", "message": error, "current_version": current_version}
|
|
@@ -60,7 +60,7 @@ def display_time(seconds: int | float) -> str:
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def get_network_info() -> dict[str, str]:
|
|
63
|
-
"""Fetch network information for eth0
|
|
63
|
+
"""Fetch network information for Ethernet interface (eth0 or end0).
|
|
64
64
|
|
|
65
65
|
Returns:
|
|
66
66
|
Dictionary with keys: 'ip', 'mask', 'mac'
|
|
@@ -71,7 +71,8 @@ def get_network_info() -> dict[str, str]:
|
|
|
71
71
|
{'ip': '192.168.1.100', 'mask': '255.255.255.0', 'mac': 'aa:bb:cc:dd:ee:ff'}
|
|
72
72
|
"""
|
|
73
73
|
try:
|
|
74
|
-
|
|
74
|
+
net_addrs = psutil.net_if_addrs()
|
|
75
|
+
addrs = net_addrs.get("eth0") or net_addrs.get("end0") or []
|
|
75
76
|
out = {IP: NONE, MASK: NONE, MAC: NONE}
|
|
76
77
|
|
|
77
78
|
for addr in addrs:
|
|
@@ -80,6 +81,21 @@ def get_network_info() -> dict[str, str]:
|
|
|
80
81
|
out["mask"] = addr.netmask if addr.netmask is not None else ""
|
|
81
82
|
elif addr.family == psutil.AF_LINK:
|
|
82
83
|
out["mac"] = addr.address
|
|
84
|
+
|
|
85
|
+
# Fallback for MAC address via /sys if AF_LINK didn't populate it
|
|
86
|
+
if out["mac"] == NONE:
|
|
87
|
+
import os
|
|
88
|
+
for iface in ("eth0", "end0"):
|
|
89
|
+
mac_file = f"/sys/class/net/{iface}/address"
|
|
90
|
+
if os.path.exists(mac_file):
|
|
91
|
+
try:
|
|
92
|
+
with open(mac_file, "r") as f:
|
|
93
|
+
mac_val = f.read().strip()
|
|
94
|
+
if mac_val:
|
|
95
|
+
out["mac"] = mac_val
|
|
96
|
+
break
|
|
97
|
+
except Exception:
|
|
98
|
+
pass
|
|
83
99
|
|
|
84
100
|
return out
|
|
85
101
|
except (KeyError, AttributeError):
|
|
@@ -28,12 +28,23 @@ class AsyncUpdater:
|
|
|
28
28
|
Implementation is validated at initialization time.
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
|
-
def __init__(
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
manager: Manager,
|
|
34
|
+
update_interval: TimePeriod,
|
|
35
|
+
initial_delay: TimePeriod | None = None,
|
|
36
|
+
**kwargs,
|
|
37
|
+
):
|
|
32
38
|
"""Initialize async updater.
|
|
33
39
|
|
|
34
40
|
Args:
|
|
35
41
|
manager: Manager instance to register the update task
|
|
36
42
|
update_interval: Time period between updates
|
|
43
|
+
initial_delay: Optional delay before the *first* update. Without it
|
|
44
|
+
the refresh loop fires immediately, which puts the component on
|
|
45
|
+
the application's startup critical path. Use this for anything
|
|
46
|
+
that is not needed for the controller to serve I/O — network
|
|
47
|
+
calls in particular.
|
|
37
48
|
**kwargs: Additional arguments (passed to parent classes)
|
|
38
49
|
|
|
39
50
|
Raises:
|
|
@@ -64,6 +75,7 @@ class AsyncUpdater:
|
|
|
64
75
|
|
|
65
76
|
self.manager = manager
|
|
66
77
|
self._update_interval = update_interval or TimePeriod(seconds=60)
|
|
78
|
+
self._initial_delay = initial_delay
|
|
67
79
|
self._wakeup_event = asyncio.Event() # Event to wake up from sleep early
|
|
68
80
|
self._requested_update_interval: float | None = None # Custom interval for next update
|
|
69
81
|
self.manager.append_task(coro=self._refresh, name=self.id) # type: ignore[attr-defined]
|
|
@@ -111,7 +123,23 @@ class AsyncUpdater:
|
|
|
111
123
|
# Determine which update method to use (check once, not every loop)
|
|
112
124
|
use_async = self.__class__.async_update is not AsyncUpdater.async_update
|
|
113
125
|
|
|
114
|
-
#
|
|
126
|
+
# Optional delay before the first update. Components that only
|
|
127
|
+
# report status (rather than drive hardware) use this so they do not
|
|
128
|
+
# compete with startup. Interruptible via request_update(), so an
|
|
129
|
+
# explicit refresh from the WebUI is still immediate.
|
|
130
|
+
if self._initial_delay is not None:
|
|
131
|
+
delay = self._initial_delay.total_in_seconds
|
|
132
|
+
if delay > 0:
|
|
133
|
+
_LOGGER.debug(
|
|
134
|
+
"%s: deferring first update by %ss",
|
|
135
|
+
getattr(self, "id", "unknown"),
|
|
136
|
+
delay,
|
|
137
|
+
)
|
|
138
|
+
try:
|
|
139
|
+
await asyncio.wait_for(self._wakeup_event.wait(), timeout=delay)
|
|
140
|
+
self._wakeup_event.clear()
|
|
141
|
+
except TimeoutError:
|
|
142
|
+
pass
|
|
115
143
|
|
|
116
144
|
while True:
|
|
117
145
|
timestamp = time.time()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Device tree overlay locations and applied-state detection.
|
|
2
|
+
|
|
3
|
+
Single source of truth for *where* boneIO overlay ``.dtbo`` files must live and
|
|
4
|
+
*whether* an overlay actually took effect. This knowledge used to be duplicated
|
|
5
|
+
in ``boneio.migrations.runner`` and ``boneio.webui.routes.system``, and both
|
|
6
|
+
copies carried the same defect: they only ever looked at
|
|
7
|
+
``/boot/dtbs/$uname_r/overlays/``.
|
|
8
|
+
|
|
9
|
+
Two directories matter, for different consumers:
|
|
10
|
+
|
|
11
|
+
``/boot/dtbs/$uname_r/``
|
|
12
|
+
U-Boot resolves bare filenames from ``uEnv.txt`` here, e.g.
|
|
13
|
+
``uboot_overlay_addr0=BONEIO-BLACK-PINS-v1.0.dtbo``. **This is the only
|
|
14
|
+
path that decides whether the overlay is actually applied at boot.**
|
|
15
|
+
|
|
16
|
+
``/boot/dtbs/$uname_r/overlays/``
|
|
17
|
+
Used by kernel/userspace overlay tooling.
|
|
18
|
+
|
|
19
|
+
Stock BeagleBoard overlays (``BB-ADC-00A0.dtbo`` and friends) ship in both.
|
|
20
|
+
Installing only into ``overlays/`` makes U-Boot log
|
|
21
|
+
|
|
22
|
+
uboot_overlays: unable to find [mmc 0:3 BONEIO-BLACK-PINS-v1.0.dtbo]
|
|
23
|
+
|
|
24
|
+
and continue with the stock BeagleBone pinmux. Nothing in userspace reports an
|
|
25
|
+
error, so file-presence checks against ``overlays/`` report success while the
|
|
26
|
+
board silently runs unconfigured pins.
|
|
27
|
+
|
|
28
|
+
The authoritative answer to "is an overlay applied" is therefore not the
|
|
29
|
+
filesystem at all but ``/proc/device-tree/chosen/overlays/``, which the kernel
|
|
30
|
+
populates from what U-Boot actually merged into the device tree.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import logging
|
|
36
|
+
import os
|
|
37
|
+
import platform
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
|
|
40
|
+
_LOGGER = logging.getLogger(__name__)
|
|
41
|
+
|
|
42
|
+
OVERLAY_GLOB = "BONEIO-BLACK-PINS*.dtbo"
|
|
43
|
+
"""Glob matching every boneIO pin overlay binary."""
|
|
44
|
+
|
|
45
|
+
DT_CHOSEN_OVERLAYS = Path("/proc/device-tree/chosen/overlays")
|
|
46
|
+
"""Kernel-reported list of overlays merged into the live device tree."""
|
|
47
|
+
|
|
48
|
+
DTBS_ROOT = Path("/boot/dtbs")
|
|
49
|
+
"""Root of the per-kernel device tree blob directories."""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def kernel_release() -> str:
|
|
53
|
+
"""Return the running kernel release, or an empty string if unavailable."""
|
|
54
|
+
try:
|
|
55
|
+
return platform.uname().release
|
|
56
|
+
except Exception: # pragma: no cover - platform call is effectively safe
|
|
57
|
+
return ""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def overlay_dirs_for_kernel(kernel_version: str) -> tuple[Path, Path]:
|
|
61
|
+
"""Return both overlay destinations for a kernel version.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
kernel_version: Kernel release string, e.g. ``6.18.45-bone48``.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Tuple of ``(uboot_dir, tooling_dir)``. ``uboot_dir`` is the directory
|
|
68
|
+
U-Boot reads; ``tooling_dir`` is its ``overlays/`` subdirectory.
|
|
69
|
+
"""
|
|
70
|
+
base = DTBS_ROOT / kernel_version
|
|
71
|
+
return base, base / "overlays"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def find_overlay_source(exclude: tuple[Path, ...] = ()) -> Path | None:
|
|
75
|
+
"""Find a directory containing boneIO overlays, to copy from.
|
|
76
|
+
|
|
77
|
+
Searches every ``/boot/dtbs/*/`` directory and its ``overlays/``
|
|
78
|
+
subdirectory, newest kernel first, so a repair prefers the most recent
|
|
79
|
+
known-good set.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
exclude: Directories to skip (typically the repair destinations).
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Directory containing at least one boneIO overlay, or ``None``.
|
|
86
|
+
"""
|
|
87
|
+
if not DTBS_ROOT.is_dir():
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
excluded = {p.resolve() for p in exclude if p.exists()}
|
|
91
|
+
|
|
92
|
+
for kdir in sorted(DTBS_ROOT.iterdir(), reverse=True):
|
|
93
|
+
if not kdir.is_dir():
|
|
94
|
+
continue
|
|
95
|
+
for candidate in (kdir, kdir / "overlays"):
|
|
96
|
+
if not candidate.is_dir():
|
|
97
|
+
continue
|
|
98
|
+
try:
|
|
99
|
+
if candidate.resolve() in excluded:
|
|
100
|
+
continue
|
|
101
|
+
except OSError:
|
|
102
|
+
continue
|
|
103
|
+
if any(candidate.glob(OVERLAY_GLOB)):
|
|
104
|
+
return candidate
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def missing_overlay_dirs(kernel_version: str) -> list[Path]:
|
|
109
|
+
"""Return the overlay destinations that lack boneIO overlays.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
kernel_version: Kernel release string.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
List of directories (possibly empty) that need to be populated. An
|
|
116
|
+
empty list means both destinations already hold overlays.
|
|
117
|
+
"""
|
|
118
|
+
uboot_dir, tooling_dir = overlay_dirs_for_kernel(kernel_version)
|
|
119
|
+
# No DTB directory for this kernel means the kernel package is not
|
|
120
|
+
# installed here; there is nothing for us to repair.
|
|
121
|
+
if not uboot_dir.is_dir():
|
|
122
|
+
return []
|
|
123
|
+
|
|
124
|
+
missing: list[Path] = []
|
|
125
|
+
for directory in (uboot_dir, tooling_dir):
|
|
126
|
+
# glob() on a non-existent directory yields nothing rather than raising,
|
|
127
|
+
# which is the behaviour we want for a not-yet-created overlays/ dir.
|
|
128
|
+
if not any(directory.glob(OVERLAY_GLOB)):
|
|
129
|
+
missing.append(directory)
|
|
130
|
+
return missing
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def applied_overlay_names() -> list[str]:
|
|
134
|
+
"""Return the overlay names the kernel reports as merged into the DT.
|
|
135
|
+
|
|
136
|
+
Reads ``/proc/device-tree/chosen/overlays/``. Entries are named after the
|
|
137
|
+
overlay that produced them, e.g. ``BB-ADC-00A0.kernel``.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
List of entry names, or an empty list if the node is absent (which
|
|
141
|
+
happens when U-Boot merged no overlays at all).
|
|
142
|
+
"""
|
|
143
|
+
if not DT_CHOSEN_OVERLAYS.is_dir():
|
|
144
|
+
return []
|
|
145
|
+
try:
|
|
146
|
+
# 'name' is a property of the node itself, not an applied overlay.
|
|
147
|
+
return sorted(e for e in os.listdir(DT_CHOSEN_OVERLAYS) if e != "name")
|
|
148
|
+
except OSError as exc:
|
|
149
|
+
_LOGGER.debug("Cannot read %s: %s", DT_CHOSEN_OVERLAYS, exc)
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def is_boneio_overlay_applied() -> bool:
|
|
154
|
+
"""Return whether a boneIO pin overlay is live in the device tree.
|
|
155
|
+
|
|
156
|
+
This is the authoritative check. File presence under ``/boot/dtbs`` proves
|
|
157
|
+
nothing about what U-Boot actually loaded.
|
|
158
|
+
"""
|
|
159
|
+
return any(name.startswith("BONEIO-BLACK-PINS") for name in applied_overlay_names())
|
|
@@ -7,7 +7,6 @@ import subprocess
|
|
|
7
7
|
from itertools import cycle
|
|
8
8
|
from typing import TYPE_CHECKING
|
|
9
9
|
|
|
10
|
-
import qrcode
|
|
11
10
|
from luma.core.error import DeviceNotFoundError
|
|
12
11
|
from luma.core.interface.serial import i2c
|
|
13
12
|
from luma.core.render import canvas
|
|
@@ -212,6 +211,12 @@ class Oled:
|
|
|
212
211
|
if not url:
|
|
213
212
|
return
|
|
214
213
|
|
|
214
|
+
# Imported here rather than at module level: qrcode costs 0.38 s to
|
|
215
|
+
# import on an AM335x and is only needed for this one screen, which the
|
|
216
|
+
# user has to navigate to. At module level it was paid on every startup,
|
|
217
|
+
# pulled in via early_oled -> display -> oled.
|
|
218
|
+
import qrcode
|
|
219
|
+
|
|
215
220
|
# Create QR code with box_size 2 and scale down later
|
|
216
221
|
qr = qrcode.QRCode(version=1, box_size=2, border=1)
|
|
217
222
|
qr.add_data(url)
|