boneio 1.6.0.dev4__tar.gz → 1.6.0.dev5__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.6.0.dev4/boneio.egg-info → boneio-1.6.0.dev5}/PKG-INFO +1 -1
- boneio-1.6.0.dev5/boneio/core/cloud/__init__.py +5 -0
- {boneio-1.6.0.dev4/boneio/migrations/assets/docker/nodered → boneio-1.6.0.dev5/boneio/core/cloud/data}/docker-compose-cloud.yaml +4 -0
- {boneio-1.6.0.dev4/boneio/migrations/assets/docker/nodered → boneio-1.6.0.dev5/boneio/core/cloud/data}/docker-compose.yaml +4 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/cloud/data/init-certs-cloud.sh +6 -28
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/cloud/registration.py +78 -3
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/yaml_patch.py +121 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/containers.py +6 -1
- boneio-1.6.0.dev5/boneio/core/security/certificate.py +297 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/security/posture.py +89 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/MANIFEST.sha256 +3 -3
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/docker/nodered/caddy/init-certs.sh +31 -32
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/helpers/boneio-containers +4 -1
- boneio-1.6.0.dev5/boneio/migrations/assets/issue.d/10-boneio.issue +1 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.3.0.json +1 -1
- boneio-1.6.0.dev5/boneio/migrations/plans/1.3.0.sig +1 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.4.4.json +1 -1
- boneio-1.6.0.dev5/boneio/migrations/plans/1.4.4.sig +1 -0
- boneio-1.6.0.dev4/boneio/migrations/plans/1.4.0.json → boneio-1.6.0.dev5/boneio/migrations/plans/1.6.10.json +1 -1
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.10.sig +2 -0
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.12.json +1 -0
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.12.sig +1 -0
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.13.json +1 -0
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.13.sig +1 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.4.json +1 -1
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.4.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.5.json +1 -1
- boneio-1.6.0.dev5/boneio/migrations/plans/1.6.5.sig +2 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/manifest.json +1 -1
- boneio-1.6.0.dev5/boneio/migrations/plans/manifest.sig +1 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_3_0_baseline.py +3 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_4_0_fix_mqtt_sudoers.py +3 -0
- boneio-1.6.0.dev5/boneio/migrations/versions/v1_6_13_custom_certificate.py +52 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_4_ssh_login_hardening.py +3 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/runner.py +7 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/schema.yaml +11 -0
- boneio-1.6.0.dev5/boneio/version.py +2 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/app.py +7 -1
- boneio-1.6.0.dev5/boneio/webui/bind.py +193 -0
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/AccountsView-iveRbldx.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/AccountsView-Bmey_Yr2.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/ActionFields-DdCxR8lP.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/ActionFields-Dd53m3KH.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/BackupSection-C1qj4qOG.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/BackupSection-BIhcVjYm.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/BindingMatrix-Bj6KE0yY.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/BindingMatrix-D9Pr22Wp.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/DeviceControlSection-CPmqccka.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/DeviceControlSection-DKC8tOXc.js +1 -1
- boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/DiagnosticsView-C_oo-SRw.js +5 -0
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/EditItemDialog-BH1onHq0.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/EditItemDialog-Dm4kPdmF.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/EntityCard-yD9_Hl71.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/EntityCard-CkJgrIUC.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/FactoryResetSection-E3xtkFLr.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/FactoryResetSection-sz3F--K9.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/FormInputToggle-Spiz-w7l.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/FormInputToggle-C7Nq2Hp8.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/HaDashboardWizard-f8fMg8FC.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/HaDashboardWizard-DEf4Sy_8.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/HostnameSection-DrpKbp6I.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/HostnameSection-D0zvj1uy.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/InputsView-W99g8hSl.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/InputsView-DkpdOPNR.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/LocationSection-ZILUsfeR.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/LocationSection-D5EoVv-i.js +2 -2
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/LoggerForm-Chw9zm0N.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/LoggerForm-DHJUPaaV.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/MigrationsSection-DSbw5UVz.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/MigrationsSection-BPvuefg6.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/ModbusView-CdP0fXYx.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/ModbusView-Cch7ykif.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/MqttPasswordsSection-BYwPAyFi.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/MqttPasswordsSection-dncPiufr.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/NodeRedManagement-DRMiFlH2.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/NodeRedManagement-Cowu2_4i.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/OutputsView-C9sDLF1P.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/OutputsView-C_PNR9px.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/ScheduleSection-C2qLKNWR.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/ScheduleSection-ByEXYj3H.js +1 -1
- boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/SecurityView-BGcKCB34.js +1 -0
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/SensorView-DNtKJE4b.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/SensorView-DxwEx546.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/SystemState-DbY5T6BB.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/SystemState-CvlqTKsV.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/TemplatesView-6kNzVE3p.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/TemplatesView-D0PTisZV.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/TilePicker-jd3hKaoZ.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/TilePicker-I46eKfzF.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/TimezoneSection-BEuXBmWp.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/TimezoneSection-DRA9cBch.js +1 -1
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/UISettings-DIcCTtXU.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/UISettings-qOAoRlwa.js +3 -3
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/index-1pLHiRke.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/index-BDR1Gl2A.js +24 -4
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/monaco-C9XC2D1j.js → boneio-1.6.0.dev5/boneio/webui/frontend-dist/assets/monaco-CQ8fwGzT.js +1 -1
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/index.html +1 -1
- {boneio-1.6.0.dev4/boneio/webui → boneio-1.6.0.dev5/boneio/webui/frontend-dist}/schema/config.schema.json +13 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/web.schema.json +13 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/sw.js +1 -1
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/config_core.py +131 -1
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/onboarding.py +9 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/security.py +297 -2
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/system.py +8 -0
- {boneio-1.6.0.dev4/boneio/webui/frontend-dist → boneio-1.6.0.dev5/boneio/webui}/schema/config.schema.json +13 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/web.schema.json +13 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/web_server.py +5 -1
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/websocket_manager.py +42 -2
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5/boneio.egg-info}/PKG-INFO +1 -1
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio.egg-info/SOURCES.txt +35 -30
- boneio-1.6.0.dev4/boneio/core/cloud/__init__.py +0 -5
- boneio-1.6.0.dev4/boneio/migrations/assets/issue.d/10-boneio.issue +0 -1
- boneio-1.6.0.dev4/boneio/migrations/plans/1.3.0.sig +0 -0
- boneio-1.6.0.dev4/boneio/migrations/plans/1.4.0.sig +0 -1
- boneio-1.6.0.dev4/boneio/migrations/plans/1.4.4.sig +0 -1
- boneio-1.6.0.dev4/boneio/migrations/plans/1.6.12.json +0 -1
- boneio-1.6.0.dev4/boneio/migrations/plans/1.6.12.sig +0 -2
- boneio-1.6.0.dev4/boneio/migrations/plans/1.6.4.sig +0 -1
- boneio-1.6.0.dev4/boneio/migrations/plans/1.6.5.sig +0 -2
- boneio-1.6.0.dev4/boneio/migrations/plans/manifest.sig +0 -0
- boneio-1.6.0.dev4/boneio/version.py +0 -2
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/DiagnosticsView-Bi1hrIcs.js +0 -5
- boneio-1.6.0.dev4/boneio/webui/frontend-dist/assets/SecurityView-DBkwBU2t.js +0 -1
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/LICENSE +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/MANIFEST.in +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/README.md +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.2/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.2/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.2/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.2/output_32_5.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.2/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.3/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.3/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.3/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.3/output_32_5.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.3/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.4/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.4/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.4/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.4/output_32_5.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.4/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.5/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.5/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.5/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.5/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.6/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.6/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.6/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.6/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.7/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.7/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.7/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.7/output_48_4.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.7/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.8/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.8/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.8/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.8/output_48_4.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.8/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/1.0/input.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/1.0/output_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/1.0/output_32_10.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/1.0/output_48_4.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/1.0/output_cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/boards/1.0/output_cover_mix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/bonecli.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/cover/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/cover/cover.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/cover/remote.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/cover/time_based.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/cover/venetian.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/group/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/group/output_group.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/binary_sensor.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/detectors.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/event.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/remote/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/remote/base.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/input/remote/esphome.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/irrigation/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/irrigation/controller.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/irrigation/water_source.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/basic.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/buzzer.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/mcp.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/pca.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/pcf.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/output/remote.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/sensor/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/sensor/virtual_energy.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/template/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/template/alarm_panel.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/template/gate_cover.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/components/template/thermostat.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/const.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/auth/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/auth/cli.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/auth/hashing.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/auth/migration.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/auth/models.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/auth/store.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/cloud/data/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/cloud/secrets.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/config_helper.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/input_bindings.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/migrations/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/migrations/v1_proxy_port.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/migrations/v2_transition.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/migrations/v4_wled_cache.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/migrations/v5_ina_screen.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/package-lock.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/package.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/provenance.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/schema_converter.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/secret_masking.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/yaml_compat.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/config/yaml_util.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/diagnostics/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/diagnostics/collect.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/discovery.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/events/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/events/bus.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/action_conditions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/canopen.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/covers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/display.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/inputs.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/irrigation.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/manager.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/modbus.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/outputs.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/remote.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/remote_input_registrar.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/scheduler.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/security_alert.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/sensors.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/sun.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/templates/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/templates/alarm.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/templates/gate_cover.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/templates/thermostat.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/templates.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/manager/update.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/basic.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/basic_mqtt.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/composite.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/local.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/lox.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/mqtt.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/messaging/queue.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/net/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/net/discovery_guard.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/base.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/can.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/esphome.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/mqtt.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/wled.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/remote/wled_cache.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/security/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/security/framing.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/sensor/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/sensor/base.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/sensor/sun.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/sensor/system.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/state/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/state/manager.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/system/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/system/host_data.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/system/monitor.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/system_ops.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/async_updater.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/conditions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/filter.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/font_util.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/logger.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/overlay.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/sun.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/timeperiod.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/core/utils/util.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/24x16/adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/24x16/config.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/24x16/event.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/24x16/mqtt.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/24x16/output24x16A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/32x10/adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/32x10/config.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/32x10/event.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/32x10/mqtt.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/32x10/output32x10A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/48x4/adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/48x4/binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/48x4/config.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/48x4/event.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/48x4/mqtt.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/48x4/output48x4A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/can_master.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/can_slave.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/config.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/event.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/mqtt.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover/outputCover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/config.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/cover.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/event.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/event_all.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/exceptions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/analog/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/analog/adc.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/bridge.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/client.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/interface.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/node.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/node_id.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/can/test_od.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/display/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/display/early_oled.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/display/fonts/danube__.ttf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/display/oled.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/expanders/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/expanders/mcp23017.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/input/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/input/base.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/gpio/input/manager.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/bus.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/ina219.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/ina219_driver.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/ina226.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/ina226_driver.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/mcp9808.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/i2c/pct2075.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/onewire/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/onewire/dallas.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/sensor/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/sensor/temperature/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/sensor/temperature/base.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/integration/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/integration/homeassistant.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/integration/interlock.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/integration/lox_template.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/actions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/docker/daemon.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/docker/nodered/caddy/502.html +0 -0
- {boneio-1.6.0.dev4/boneio/core/cloud/data → boneio-1.6.0.dev5/boneio/migrations/assets/docker/nodered}/docker-compose-cloud.yaml +0 -0
- {boneio-1.6.0.dev4/boneio/core/cloud/data → boneio-1.6.0.dev5/boneio/migrations/assets/docker/nodered}/docker-compose.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/docker/nodered/node-red/settings.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/helpers/boneio-helpers-heal +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/helpers/boneio-migrate-v2 +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/helpers/boneio-system +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/journald/journald.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/kernel/postinst-boneio-overlay +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/migrations-recovery.pem +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/migrations.pem +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/modules-load.d/onewire.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/mosquitto/boneio.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/sshd/10-boneio-hardening.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/sudoers/boneio +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/sudoers/boneio-helpers +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/sudoers/boneio-timedatectl +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/boneio-helpers-heal.service +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/boneio-oled-boot.service +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/boneio-oled-shutdown.service +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/boneio.service +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/dropins/avahi-daemon-defer.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/dropins/bb-usb-gadgets-defer.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/dropins/mosquitto-priority.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/dropins/timer-no-persistent.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/dropins/user-manager-defer.conf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/linger-marker +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/systemd/set-hostname-once.service +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/usr-local-bin/set-hostname-once.sh +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/usr-sbin/oled_boot_splash.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/usr-sbin/oled_boot_splash.sh +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/usr-sbin/oled_msg.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/usr-sbin/oled_msg.sh +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/assets/wheels/pyyaml-6.0.3-cp313-cp313-linux_armv7l.whl +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/bootstrap/boneio-migrate +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/bootstrap/install-helper.sh +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/bootstrap/sudoers-migrate +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.3.1.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.3.1.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.3.2.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.3.2.sig +0 -0
- /boneio-1.6.0.dev4/boneio/migrations/plans/1.6.10.json → /boneio-1.6.0.dev5/boneio/migrations/plans/1.4.0.json +0 -0
- /boneio-1.6.0.dev4/boneio/migrations/plans/1.6.10.sig → /boneio-1.6.0.dev5/boneio/migrations/plans/1.4.0.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.4.3.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.4.3.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.0.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.0.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.1.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.1.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.10.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.10.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.11.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.11.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.12.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.12.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.13.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.13.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.14.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.14.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.15.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.15.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.16.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.16.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.17.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.17.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.18.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.18.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.2.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.2.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.3.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.3.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.4.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.4.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.5.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.5.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.6.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.6.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.7.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.7.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.8.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.8.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.9.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.5.9.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.0.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.0.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.1.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.1.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.11.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.11.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.2.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.2.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.3.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.3.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.6.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.6.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.7.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.7.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.8.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.8.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.9.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/plans/1.6.9.sig +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/runner.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_3_1_fix_oled_boot.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_3_2_cleanup_can_sudoers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_4_3_oled_shutdown.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_4_4_caddy.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_0_fix_oled_fifo_permissions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_10_disable_console_setup.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_11_timer_catchup.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_12_oled_splash_off_critical_path.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_13_mosquitto_priority.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_14_journal_apparent_size.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_15_prune_orphan_journals.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_16_login_linger.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_17_defer_user_manager.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_18_fix_hostname_once.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_1_ufw_lox_udp.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_2_libyaml.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_3_libyaml_retry.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_4_onewire_modules.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_5_overlay_kernel_hook.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_6_boot_service_order.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_7_journald_limits.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_8_apparmor_prune.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_5_9_defer_nonessential.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_0_nodered_admin_auth.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_10_narrow_sudo_rules.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_11_drop_docker_group.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_12_console_shows_ip.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_1_mosquitto_passwd_perms.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_2_drop_build_sudo_rule.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_3_firewall_rule_gaps.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_5_trust_transition.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_6_retire_legacy_helper.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_7_timedatectl_sudoers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_8_system_helper.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/migrations/versions/v1_6_9_ntp_servers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/cli.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/client.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/coordinator.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/dts1964_3f.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/le-03mw.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/le-03mwct.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/socomec_e03.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/energy_meters/socomec_e23.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/hvac/defro-drx.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/hvac/eht-topventil-plus.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/hvac/thessla.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/hvac/ventclear.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/hvac/wanas415.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/inverters/sofar.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/other/esp32_relay_x4_modbus.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/other/n4dsc08.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/other/r4dcb08.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/boneio-edge-temp.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/cwt.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/dyp-a12-ultrasonic.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/gdfs.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/gdfx.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/pt100.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/qdw90a.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/sht20.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/devices/sensors/sht30.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/base.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/derived/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/derived/numeric.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/derived/select.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/derived/switch.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/derived/text.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/sensor/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/sensor/binary.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/sensor/numeric.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/sensor/text.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/writeable/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/writeable/binary.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/entities/writeable/numeric.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/mock_coordinator.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/modbus/utils.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/actions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/events.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/files.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/logs.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/mqtt.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/models/state.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/actions.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/actions_sensor.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/actions_switch.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/condition.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/filters.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/filters_adc.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/id.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/remote_devices.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/remote_inputs.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/remote_outputs.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/temp_unit.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/schema/update_interval.yaml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/action_validation.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/dashboard_cards.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/AppInitContext-CsffdB9c.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/EntityGrid-BDdmT0qN.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/LongPressWrapper-BKkWvoC1.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/NodeRedView-Ct08K8xu.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/Sparkline-D-2-v-7o.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/ViewToggle-B8OpHNHc.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/aiConfig-_hPXvgdY.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/aiWizardPrompt-Dc7dZBzw.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/axios-uEi8e3Ln.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/basePath-CxHj-SSK.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/chunk-QTnfLwEv.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/clipboard-CCtx29e-.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/codicon-ngg6Pgfi.ttf +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/configCache-CLN4xEny.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/coverUtils-Cf4Uxn2U.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/createLucideIcon-BEjh8B3y.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/editor.worker-Cn2oRESe.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/fa-BEzM11bH.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/formatters-zOiGPJLh.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/gi-tOlGxC0X.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/index-lVrZSgFS.css +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/longPress-Dx7OCSyP.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/monaco-Br_kD0ds.css +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/monaco-DUFfd7ef.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/monaco-Dpn-hvLa.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/select-D3PIwbEj.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/tabs-box-Byn-MOyS.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/utils-B6KiDbIe.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/assets/yaml.worker-8qQfrID5.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/boneio-192.png +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/boneio-512.png +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/boneio.svg +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/adc.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/areas.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/binary_sensor.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/boneio.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/can.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/cover.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/dallas.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/ds2482.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/event.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/ina219.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/ina226.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/irrigation.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/lm75.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/location.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/logger.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/lox_udp.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/mcp23017.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/mcp9808.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/modbus.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/modbus_devices.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/mqtt.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/oled.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/output.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/output_group.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/pca9685.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/pcf8575.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/remote_devices.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/remote_inputs.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/remote_outputs.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/schedule.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/sensor.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/template.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/frontend-dist/workbox-7e79c025.js +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/hvac_svg_templates.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/middleware/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/middleware/auth.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/middleware/csrf.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/middleware/policy.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/modbus_card_templates.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/rate_limit.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/accounts.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/auth.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/can.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/config.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/config_actions.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/config_backups.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/config_discovery.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/config_files.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/covers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/dashboard.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/dev_fake_device.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/diagnostics.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/irrigation.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/migrations.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/modbus.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/mqtt_reference.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/nodered.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/outputs.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/remote_devices.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/schedule.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/sensors.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/sun.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/templates.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/timezone_sudoers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/tools.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/routes/update.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/adc.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/areas.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/binary_sensor.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/boneio.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/can.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/cover.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/dallas.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/ds2482.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/event.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/ina219.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/ina226.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/irrigation.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/lm75.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/location.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/logger.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/lox_udp.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/mcp23017.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/mcp9808.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/modbus.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/modbus_devices.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/mqtt.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/oled.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/output.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/output_group.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/pca9685.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/pcf8575.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/remote_devices.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/remote_inputs.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/remote_outputs.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/schedule.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/sensor.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/template.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/security_headers.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/services/__init__.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/services/logs.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio/webui/sudo_rate_limiter.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio.egg-info/dependency_links.txt +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio.egg-info/entry_points.txt +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio.egg-info/requires.txt +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/boneio.egg-info/top_level.txt +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/pyproject.toml +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/setup.cfg +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/setup.py +0 -0
- {boneio-1.6.0.dev4 → boneio-1.6.0.dev5}/tests/test_py313_compatibility.py +0 -0
|
@@ -20,6 +20,10 @@ services:
|
|
|
20
20
|
- "${HTTPS_PORT:-8443}:443"
|
|
21
21
|
environment:
|
|
22
22
|
- HOST_HOSTNAME=${HOSTNAME}
|
|
23
|
+
# The port the host publishes 443 on. Caddy only sees 443 from
|
|
24
|
+
# inside the container, so a redirect built from what it sees
|
|
25
|
+
# would send browsers to a port nothing listens on.
|
|
26
|
+
- PUBLIC_HTTPS_PORT=${HTTPS_PORT:-8443}
|
|
23
27
|
volumes:
|
|
24
28
|
- ./caddy/502.html:/srv/502.html:ro
|
|
25
29
|
- ./caddy/init-certs-cloud.sh:/init-certs-cloud.sh:ro
|
|
@@ -25,6 +25,10 @@ services:
|
|
|
25
25
|
- "${HTTPS_PORT:-8443}:443"
|
|
26
26
|
environment:
|
|
27
27
|
- HOST_HOSTNAME=${HOSTNAME:-boneio}
|
|
28
|
+
# The port the host publishes 443 on. Caddy only sees 443 from
|
|
29
|
+
# inside the container, so a redirect built from what it sees
|
|
30
|
+
# would send browsers to a port nothing listens on.
|
|
31
|
+
- PUBLIC_HTTPS_PORT=${HTTPS_PORT:-8443}
|
|
28
32
|
volumes:
|
|
29
33
|
- ./caddy/502.html:/srv/502.html:ro
|
|
30
34
|
- ./caddy/init-certs.sh:/init-certs.sh:ro
|
|
@@ -79,34 +79,12 @@ cat > /tmp/Caddyfile << EOF
|
|
|
79
79
|
|
|
80
80
|
# HTTP - serve directly
|
|
81
81
|
:80 {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
handle /nodered-status {
|
|
92
|
-
header Content-Type application/json
|
|
93
|
-
header X-NodeRed-Available "true"
|
|
94
|
-
header Access-Control-Expose-Headers "X-NodeRed-Available"
|
|
95
|
-
respond \`{"available": true}\` 200
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
handle /nodered/* {
|
|
99
|
-
reverse_proxy node-red:1880 {
|
|
100
|
-
header_up X-Forwarded-Proto {scheme}
|
|
101
|
-
header_down X-NodeRed-Available "true"
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
handle {
|
|
106
|
-
reverse_proxy host.docker.internal:8090 {
|
|
107
|
-
header_up X-Forwarded-Proto {scheme}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
82
|
+
# Redirect to HTTPS. This port used to serve the panel in the clear —
|
|
83
|
+
# the login form, the token it hands back, and a configuration carrying
|
|
84
|
+
# passwords. The port is substituted by this shell as the file is
|
|
85
|
+
# written: Caddy only sees 443 from inside the container, while the
|
|
86
|
+
# host publishes it as 8443.
|
|
87
|
+
redir https://{host}:${PUBLIC_HTTPS_PORT:-8443}{uri}
|
|
110
88
|
}
|
|
111
89
|
|
|
112
90
|
${CLOUD_BLOCK}
|
|
@@ -41,9 +41,11 @@ KEY_FILE = CERT_DIR / "privkey.pem"
|
|
|
41
41
|
|
|
42
42
|
# Caddy configuration paths
|
|
43
43
|
CADDY_CONFIG_DIR = _DOCKER_DIR / "caddy"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
# No Caddyfile constants here on purpose. Caddy's configuration is not a file
|
|
45
|
+
# in this directory — init-certs.sh (or init-certs-cloud.sh) writes it to
|
|
46
|
+
# /tmp/Caddyfile inside the container on every start. Switching between local
|
|
47
|
+
# and cloud mode swaps the compose file, and with it which of those two scripts
|
|
48
|
+
# runs; there is no Caddyfile to copy over another.
|
|
47
49
|
|
|
48
50
|
# Registration interval (1 hour)
|
|
49
51
|
REGISTRATION_INTERVAL = 3600
|
|
@@ -637,3 +639,76 @@ class CloudRegistration:
|
|
|
637
639
|
return "init-certs-cloud.sh" in content
|
|
638
640
|
except Exception:
|
|
639
641
|
return False
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
async def set_enabled(config_helper, enabled: bool, local_ip: str | None = None) -> str:
|
|
645
|
+
"""Turn cloud registration on or off on a running device.
|
|
646
|
+
|
|
647
|
+
Registration used to begin only in :mod:`boneio.runner`, so switching it on
|
|
648
|
+
from the panel wrote a line to config.yaml and asked for a restart —
|
|
649
|
+
on a controller whose whole point is that it is running. Everything the
|
|
650
|
+
change needs is already here: :meth:`CloudRegistration.start` does no more
|
|
651
|
+
than launch the loop that registers the name, fetches the certificate,
|
|
652
|
+
swaps the compose template and recreates Caddy.
|
|
653
|
+
|
|
654
|
+
Idempotent in both directions, because the panel can be open twice and a
|
|
655
|
+
save can be repeated.
|
|
656
|
+
|
|
657
|
+
Args:
|
|
658
|
+
config_helper: The live :class:`ConfigHelper`.
|
|
659
|
+
enabled: The state asked for.
|
|
660
|
+
local_ip: This device's address on the LAN. Read from the system when
|
|
661
|
+
not given.
|
|
662
|
+
|
|
663
|
+
Returns:
|
|
664
|
+
A short word for what happened: ``started``, ``stopped``, ``unchanged``
|
|
665
|
+
or ``unavailable``.
|
|
666
|
+
"""
|
|
667
|
+
existing = getattr(config_helper, "_cloud_reg", None)
|
|
668
|
+
|
|
669
|
+
if not enabled:
|
|
670
|
+
config_helper._cloud_registration = False
|
|
671
|
+
if existing is None:
|
|
672
|
+
return "unchanged"
|
|
673
|
+
try:
|
|
674
|
+
await existing.stop()
|
|
675
|
+
# Put the plain template back, or Caddy keeps trying to serve a
|
|
676
|
+
# certificate for a name that is no longer being renewed.
|
|
677
|
+
await existing._restore_local_config()
|
|
678
|
+
except Exception as err: # noqa: BLE001
|
|
679
|
+
_LOGGER.warning("Could not stop cloud registration cleanly: %s", err)
|
|
680
|
+
config_helper._cloud_reg = None
|
|
681
|
+
_LOGGER.info("Cloud registration stopped on request")
|
|
682
|
+
return "stopped"
|
|
683
|
+
|
|
684
|
+
if existing is not None:
|
|
685
|
+
config_helper._cloud_registration = True
|
|
686
|
+
return "unchanged"
|
|
687
|
+
|
|
688
|
+
serial = getattr(config_helper, "serial_number", None)
|
|
689
|
+
if not local_ip:
|
|
690
|
+
try:
|
|
691
|
+
from boneio.core.system.monitor import get_network_info
|
|
692
|
+
|
|
693
|
+
local_ip = (get_network_info() or {}).get("ip", "")
|
|
694
|
+
except Exception as err: # noqa: BLE001
|
|
695
|
+
_LOGGER.warning("Could not read this device's address: %s", err)
|
|
696
|
+
local_ip = ""
|
|
697
|
+
|
|
698
|
+
if not serial or not local_ip:
|
|
699
|
+
# The setting is saved either way; the next start picks it up. Saying
|
|
700
|
+
# so is better than reporting success for a service that did not begin.
|
|
701
|
+
_LOGGER.warning(
|
|
702
|
+
"Cloud registration is enabled but %s is not known yet; it will "
|
|
703
|
+
"start on the next boot.",
|
|
704
|
+
"the serial number" if not serial else "this device's address",
|
|
705
|
+
)
|
|
706
|
+
config_helper._cloud_registration = True
|
|
707
|
+
return "unavailable"
|
|
708
|
+
|
|
709
|
+
registration = CloudRegistration(serial_number=serial, local_ip=local_ip)
|
|
710
|
+
await registration.start()
|
|
711
|
+
config_helper._cloud_reg = registration
|
|
712
|
+
config_helper._cloud_registration = True
|
|
713
|
+
_LOGGER.info("Cloud registration started for %s (IP: %s)", serial, local_ip)
|
|
714
|
+
return "started"
|
|
@@ -260,3 +260,124 @@ def ensure_section(config_file: str | Path, path: tuple[str, ...]) -> bool:
|
|
|
260
260
|
file_path.write_text("".join(lines), encoding="utf-8")
|
|
261
261
|
_LOGGER.info("Created section '%s' in %s", ".".join(path), file_path)
|
|
262
262
|
return True
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _find_section_line(lines: list[str], path: tuple[str, ...]) -> int | None:
|
|
266
|
+
"""Index of the line declaring a nested key, or None if it is not there.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
lines: File lines.
|
|
270
|
+
path: Section path, outermost first.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
The index of the key's own line, or None.
|
|
274
|
+
"""
|
|
275
|
+
depth = 0
|
|
276
|
+
for index, line in enumerate(lines):
|
|
277
|
+
parsed = _line_key(line)
|
|
278
|
+
if parsed is None:
|
|
279
|
+
continue
|
|
280
|
+
key, indent, _ = parsed
|
|
281
|
+
if depth and indent <= (depth - 1) * len(INDENT):
|
|
282
|
+
return None
|
|
283
|
+
if key == path[depth] and indent == depth * len(INDENT):
|
|
284
|
+
depth += 1
|
|
285
|
+
if depth == len(path):
|
|
286
|
+
return index
|
|
287
|
+
return None
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def has_section(config_file: str | Path, path: tuple[str, ...]) -> bool:
|
|
291
|
+
"""Whether a nested key is present in the file.
|
|
292
|
+
|
|
293
|
+
Separate from :func:`remove_section` so a caller can find out before doing
|
|
294
|
+
anything irreversible — such as writing a backup copy over the one it made
|
|
295
|
+
the last time it was asked.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
config_file: Path to config.yaml.
|
|
299
|
+
path: Section path, outermost first.
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
True when the key is there.
|
|
303
|
+
|
|
304
|
+
Raises:
|
|
305
|
+
YamlPatchError: If the path is empty.
|
|
306
|
+
"""
|
|
307
|
+
if not path:
|
|
308
|
+
raise YamlPatchError("No section path given.")
|
|
309
|
+
lines = Path(config_file).read_text(encoding="utf-8").splitlines(keepends=True)
|
|
310
|
+
return _find_section_line(lines, path) is not None
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def remove_section(config_file: str | Path, path: tuple[str, ...]) -> bool:
|
|
314
|
+
"""Delete a nested mapping key and everything under it.
|
|
315
|
+
|
|
316
|
+
Written for one job: taking the pre-1.6 ``web.auth`` block out of a
|
|
317
|
+
configuration after its account has been migrated into the hashed store.
|
|
318
|
+
Nothing reads it any more, and it still holds the owner's password in
|
|
319
|
+
plain text — in the file, and in every backup and diagnostic bundle made
|
|
320
|
+
since.
|
|
321
|
+
|
|
322
|
+
Line-based rather than a parse-and-dump, for the usual reason: the file
|
|
323
|
+
belongs to the owner, and round-tripping it through a YAML library would
|
|
324
|
+
return their comments, ordering and ``!include`` directives as something
|
|
325
|
+
they did not write.
|
|
326
|
+
|
|
327
|
+
Comment lines immediately above the key are removed with it. They describe
|
|
328
|
+
the block, and leaving them behind stranded over an unrelated setting is
|
|
329
|
+
worse than taking one comment too many.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
config_file: Path to config.yaml.
|
|
333
|
+
path: Section path, outermost first, e.g. ``("web", "auth")``.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
True if something was removed, False if the key was not there.
|
|
337
|
+
|
|
338
|
+
Raises:
|
|
339
|
+
YamlPatchError: If the path is empty.
|
|
340
|
+
"""
|
|
341
|
+
if not path:
|
|
342
|
+
raise YamlPatchError("No section path given.")
|
|
343
|
+
|
|
344
|
+
file_path = Path(config_file)
|
|
345
|
+
lines = file_path.read_text(encoding="utf-8").splitlines(keepends=True)
|
|
346
|
+
|
|
347
|
+
start = _find_section_line(lines, path)
|
|
348
|
+
if start is None:
|
|
349
|
+
return False
|
|
350
|
+
key_indent = len(lines[start]) - len(lines[start].lstrip())
|
|
351
|
+
|
|
352
|
+
# Everything indented under the key belongs to it, blank lines included
|
|
353
|
+
# while more indented content follows.
|
|
354
|
+
end = start + 1
|
|
355
|
+
while end < len(lines):
|
|
356
|
+
line = lines[end]
|
|
357
|
+
if not line.strip():
|
|
358
|
+
following = next(
|
|
359
|
+
(i for i in range(end + 1, len(lines)) if lines[i].strip()), None
|
|
360
|
+
)
|
|
361
|
+
if following is None:
|
|
362
|
+
break
|
|
363
|
+
next_indent = len(lines[following]) - len(lines[following].lstrip())
|
|
364
|
+
if next_indent <= key_indent:
|
|
365
|
+
break
|
|
366
|
+
end += 1
|
|
367
|
+
continue
|
|
368
|
+
indent = len(line) - len(line.lstrip())
|
|
369
|
+
if indent <= key_indent:
|
|
370
|
+
break
|
|
371
|
+
end += 1
|
|
372
|
+
|
|
373
|
+
# Take the comment block sitting directly on top of it.
|
|
374
|
+
while start > 0:
|
|
375
|
+
above = lines[start - 1].strip()
|
|
376
|
+
if above.startswith("#"):
|
|
377
|
+
start -= 1
|
|
378
|
+
continue
|
|
379
|
+
break
|
|
380
|
+
|
|
381
|
+
del lines[start:end]
|
|
382
|
+
file_path.write_text("".join(lines), encoding="utf-8")
|
|
383
|
+
return True
|
|
@@ -55,7 +55,12 @@ _FALLBACK: dict[str, list[str]] = {
|
|
|
55
55
|
"restart-caddy": ["docker", "compose", "restart", CADDY_SERVICE],
|
|
56
56
|
"reload-caddy": [
|
|
57
57
|
"docker", "compose", "exec", CADDY_SERVICE,
|
|
58
|
-
|
|
58
|
+
# /tmp/Caddyfile, not /etc/caddy/Caddyfile: the container runs the
|
|
59
|
+
# file init-certs.sh writes on every start. /etc/caddy/Caddyfile is the
|
|
60
|
+
# stock config baked into the image, and reloading that swaps the
|
|
61
|
+
# working proxy for Caddy's welcome page — HTTPS goes down and stays
|
|
62
|
+
# down until the container is restarted.
|
|
63
|
+
"caddy", "reload", "--config", "/tmp/Caddyfile",
|
|
59
64
|
],
|
|
60
65
|
}
|
|
61
66
|
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"""Checking a certificate and key before the device starts serving them.
|
|
2
|
+
|
|
3
|
+
An operator who does not want cloud registration still deserves a panel that
|
|
4
|
+
browsers accept, and the way there is their own certificate: from a company CA,
|
|
5
|
+
or from Let's Encrypt obtained on a machine that can actually run the
|
|
6
|
+
challenge. This is the part that decides whether what they uploaded is usable.
|
|
7
|
+
|
|
8
|
+
The checking is the point. A certificate that does not match its key makes the
|
|
9
|
+
proxy fail to start, and a certificate whose names do not cover the address
|
|
10
|
+
people type produces the same browser warning as before — except now the
|
|
11
|
+
operator believes they fixed it, which is worse than knowing they had not.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import datetime
|
|
17
|
+
import logging
|
|
18
|
+
import os
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from cryptography import x509
|
|
23
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
|
24
|
+
|
|
25
|
+
_LOGGER = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
#: Refuse anything larger. A certificate chain is a few kilobytes; a megabyte
|
|
28
|
+
#: of PEM is somebody uploading the wrong file.
|
|
29
|
+
MAX_PEM_BYTES = 256 * 1024
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class CertificateError(Exception):
|
|
33
|
+
"""The uploaded material cannot be served."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class CertificateInfo:
|
|
38
|
+
"""What a usable certificate turned out to be."""
|
|
39
|
+
|
|
40
|
+
subject: str
|
|
41
|
+
issuer: str
|
|
42
|
+
not_before: datetime.datetime
|
|
43
|
+
not_after: datetime.datetime
|
|
44
|
+
names: list[str] = field(default_factory=list)
|
|
45
|
+
fingerprint: str = ""
|
|
46
|
+
#: Names the device is reached by that this certificate does not cover.
|
|
47
|
+
#: Not an error — the operator may know something we do not — but the one
|
|
48
|
+
#: thing worth saying out loud.
|
|
49
|
+
uncovered: list[str] = field(default_factory=list)
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def days_left(self) -> int:
|
|
53
|
+
"""Whole days until it expires."""
|
|
54
|
+
now = datetime.datetime.now(datetime.UTC)
|
|
55
|
+
return max(0, (self.not_after - now).days)
|
|
56
|
+
|
|
57
|
+
def to_dict(self) -> dict:
|
|
58
|
+
"""Serialise for the API."""
|
|
59
|
+
return {
|
|
60
|
+
"subject": self.subject,
|
|
61
|
+
"issuer": self.issuer,
|
|
62
|
+
"not_before": self.not_before.isoformat(),
|
|
63
|
+
"not_after": self.not_after.isoformat(),
|
|
64
|
+
"days_left": self.days_left,
|
|
65
|
+
"names": self.names,
|
|
66
|
+
"fingerprint": self.fingerprint,
|
|
67
|
+
"uncovered": self.uncovered,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _names_of(cert: x509.Certificate) -> list[str]:
|
|
72
|
+
"""Every name the certificate is valid for.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
cert: The parsed certificate.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
DNS names and IP addresses from the SAN extension.
|
|
79
|
+
"""
|
|
80
|
+
try:
|
|
81
|
+
san = cert.extensions.get_extension_for_class(
|
|
82
|
+
x509.SubjectAlternativeName
|
|
83
|
+
).value
|
|
84
|
+
except x509.ExtensionNotFound:
|
|
85
|
+
return []
|
|
86
|
+
names = [str(n) for n in san.get_values_for_type(x509.DNSName)]
|
|
87
|
+
names += [str(n) for n in san.get_values_for_type(x509.IPAddress)]
|
|
88
|
+
return names
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _covers(names: list[str], wanted: str) -> bool:
|
|
92
|
+
"""Whether a certificate's names cover one address.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
names: Names from the certificate.
|
|
96
|
+
wanted: A hostname or IP address the device is reached by.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
True when a browser would accept the certificate for *wanted*.
|
|
100
|
+
"""
|
|
101
|
+
wanted = wanted.strip().lower()
|
|
102
|
+
if not wanted:
|
|
103
|
+
return True
|
|
104
|
+
for name in names:
|
|
105
|
+
name = name.lower()
|
|
106
|
+
if name == wanted:
|
|
107
|
+
return True
|
|
108
|
+
# A wildcard matches one label, and never the bare domain.
|
|
109
|
+
if name.startswith("*.") and "." in wanted:
|
|
110
|
+
if wanted.split(".", 1)[1] == name[2:]:
|
|
111
|
+
return True
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def inspect(cert_pem: bytes, key_pem: bytes, reached_by: list[str] | None = None) -> CertificateInfo:
|
|
116
|
+
"""Check a certificate and key, and describe what they are.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
cert_pem: The certificate, or a full chain, in PEM.
|
|
120
|
+
key_pem: The private key in PEM. Must not be encrypted — the proxy
|
|
121
|
+
starts unattended and has nobody to ask for a passphrase.
|
|
122
|
+
reached_by: Hostnames and addresses this device is reached by, checked
|
|
123
|
+
against the certificate's names.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
What the certificate is.
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
CertificateError: If it cannot be parsed, the key does not match, the
|
|
130
|
+
key is encrypted, or the certificate has expired.
|
|
131
|
+
"""
|
|
132
|
+
if len(cert_pem) > MAX_PEM_BYTES or len(key_pem) > MAX_PEM_BYTES:
|
|
133
|
+
raise CertificateError("That file is far too large to be a certificate.")
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
cert = x509.load_pem_x509_certificate(cert_pem)
|
|
137
|
+
except Exception as err: # noqa: BLE001
|
|
138
|
+
raise CertificateError(f"The certificate is not readable PEM: {err}") from err
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
key = serialization.load_pem_private_key(key_pem, password=None)
|
|
142
|
+
except TypeError as err:
|
|
143
|
+
raise CertificateError(
|
|
144
|
+
"The private key is protected by a passphrase. The proxy starts "
|
|
145
|
+
"unattended and has nobody to ask, so upload an unencrypted key."
|
|
146
|
+
) from err
|
|
147
|
+
except Exception as err: # noqa: BLE001
|
|
148
|
+
raise CertificateError(f"The private key is not readable PEM: {err}") from err
|
|
149
|
+
|
|
150
|
+
cert_public = cert.public_key().public_bytes(
|
|
151
|
+
serialization.Encoding.DER,
|
|
152
|
+
serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
153
|
+
)
|
|
154
|
+
key_public = key.public_key().public_bytes(
|
|
155
|
+
serialization.Encoding.DER,
|
|
156
|
+
serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
157
|
+
)
|
|
158
|
+
if cert_public != key_public:
|
|
159
|
+
raise CertificateError(
|
|
160
|
+
"That key does not belong to that certificate. Serving them "
|
|
161
|
+
"together would stop the proxy from starting at all."
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
not_after = cert.not_valid_after_utc
|
|
165
|
+
not_before = cert.not_valid_before_utc
|
|
166
|
+
now = datetime.datetime.now(datetime.UTC)
|
|
167
|
+
if not_after <= now:
|
|
168
|
+
raise CertificateError(
|
|
169
|
+
f"That certificate expired on {not_after.date()}. Browsers would "
|
|
170
|
+
"reject it more loudly than the self-signed one it replaces."
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
names = _names_of(cert)
|
|
174
|
+
uncovered = [
|
|
175
|
+
address
|
|
176
|
+
for address in (reached_by or [])
|
|
177
|
+
if address and not _covers(names, address)
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
return CertificateInfo(
|
|
181
|
+
subject=cert.subject.rfc4514_string(),
|
|
182
|
+
issuer=cert.issuer.rfc4514_string(),
|
|
183
|
+
not_before=not_before,
|
|
184
|
+
not_after=not_after,
|
|
185
|
+
names=names,
|
|
186
|
+
fingerprint=cert.fingerprint(hashes.SHA256()).hex(),
|
|
187
|
+
uncovered=uncovered,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def device_addresses(hostname: str | None, ip: str | None) -> list[str]:
|
|
192
|
+
"""The names a browser is likely to be pointed at this device by.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
hostname: The device's hostname.
|
|
196
|
+
ip: Its address on the local network.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Addresses to check a certificate against.
|
|
200
|
+
"""
|
|
201
|
+
addresses = []
|
|
202
|
+
for value in (hostname, f"{hostname}.local" if hostname else None, ip):
|
|
203
|
+
if value and value not in addresses:
|
|
204
|
+
addresses.append(value)
|
|
205
|
+
return addresses
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# --------------------------------------------------------------- on the device
|
|
209
|
+
|
|
210
|
+
#: Where the proxy reads an uploaded certificate from.
|
|
211
|
+
#:
|
|
212
|
+
#: Inside Caddy's data directory on purpose. That directory is already mounted
|
|
213
|
+
#: into the container and already belongs to the account the panel runs as, so
|
|
214
|
+
#: nothing here needs a change to docker-compose.yaml — which is root-owned and
|
|
215
|
+
#: would have to go out as a migration — and no new mount point can be created
|
|
216
|
+
#: by Docker as root before the panel ever gets to write in it. The cloud
|
|
217
|
+
#: path's own certificate lives elsewhere and is untouched by any of this.
|
|
218
|
+
CERT_DIR = Path.home() / "docker" / "nodered" / "caddy" / "data" / "custom"
|
|
219
|
+
CUSTOM_CERT = CERT_DIR / "fullchain.pem"
|
|
220
|
+
CUSTOM_KEY = CERT_DIR / "privkey.pem"
|
|
221
|
+
|
|
222
|
+
#: Caddy's own certificate authority, created on first start. Offering it for
|
|
223
|
+
#: download is the cheapest way to a panel that browsers accept: no domain, no
|
|
224
|
+
#: DNS credentials, nothing reachable from outside. What it costs is that a
|
|
225
|
+
#: machine trusting it will believe that authority about any name, so it is
|
|
226
|
+
#: offered with that said rather than as the obvious thing to do.
|
|
227
|
+
ROOT_CA = (
|
|
228
|
+
Path.home()
|
|
229
|
+
/ "docker" / "nodered" / "caddy" / "data" / "caddy" / "pki"
|
|
230
|
+
/ "authorities" / "local" / "root.crt"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
#: The key is a secret, and it is written by the account the panel runs as.
|
|
234
|
+
KEY_MODE = 0o600
|
|
235
|
+
CERT_MODE = 0o644
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def install(cert_pem: bytes, key_pem: bytes) -> None:
|
|
239
|
+
"""Write a checked certificate and key where the proxy will find them.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
cert_pem: The certificate or chain.
|
|
243
|
+
key_pem: Its private key.
|
|
244
|
+
|
|
245
|
+
Raises:
|
|
246
|
+
CertificateError: If the files cannot be written.
|
|
247
|
+
"""
|
|
248
|
+
try:
|
|
249
|
+
CERT_DIR.mkdir(parents=True, exist_ok=True)
|
|
250
|
+
# The key is created with its mode already set, so it is never even
|
|
251
|
+
# briefly readable by anything else on the device.
|
|
252
|
+
def _private(path: str, flags: int) -> int:
|
|
253
|
+
return os.open(path, flags, KEY_MODE)
|
|
254
|
+
|
|
255
|
+
with open(CUSTOM_KEY, "wb", opener=_private) as handle:
|
|
256
|
+
handle.write(key_pem)
|
|
257
|
+
CUSTOM_KEY.chmod(KEY_MODE)
|
|
258
|
+
CUSTOM_CERT.write_bytes(cert_pem)
|
|
259
|
+
CUSTOM_CERT.chmod(CERT_MODE)
|
|
260
|
+
except OSError as err:
|
|
261
|
+
raise CertificateError(f"Could not store the certificate: {err}") from err
|
|
262
|
+
_LOGGER.warning("A custom TLS certificate was installed at %s", CUSTOM_CERT)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def remove() -> bool:
|
|
266
|
+
"""Delete the custom certificate, returning the proxy to its own.
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
True if something was removed.
|
|
270
|
+
"""
|
|
271
|
+
removed = False
|
|
272
|
+
for path in (CUSTOM_CERT, CUSTOM_KEY):
|
|
273
|
+
try:
|
|
274
|
+
path.unlink()
|
|
275
|
+
removed = True
|
|
276
|
+
except FileNotFoundError:
|
|
277
|
+
continue
|
|
278
|
+
except OSError as err:
|
|
279
|
+
raise CertificateError(f"Could not remove {path.name}: {err}") from err
|
|
280
|
+
if removed:
|
|
281
|
+
_LOGGER.warning("The custom TLS certificate was removed")
|
|
282
|
+
return removed
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def installed() -> CertificateInfo | None:
|
|
286
|
+
"""Describe the custom certificate in place, if there is one.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
Its details, or None when the proxy is using its own.
|
|
290
|
+
"""
|
|
291
|
+
if not (CUSTOM_CERT.exists() and CUSTOM_KEY.exists()):
|
|
292
|
+
return None
|
|
293
|
+
try:
|
|
294
|
+
return inspect(CUSTOM_CERT.read_bytes(), CUSTOM_KEY.read_bytes())
|
|
295
|
+
except (OSError, CertificateError) as err:
|
|
296
|
+
_LOGGER.warning("The installed certificate cannot be read: %s", err)
|
|
297
|
+
return None
|