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.
Files changed (551) hide show
  1. {boneio-1.5.0.dev41/boneio.egg-info → boneio-1.5.2.dev1}/PKG-INFO +1 -1
  2. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/bonecli.py +0 -3
  3. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/time_based.py +14 -0
  4. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/venetian.py +14 -0
  5. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/irrigation/controller.py +29 -1
  6. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/yaml_util.py +49 -6
  7. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/covers.py +18 -0
  8. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/outputs.py +45 -0
  9. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/update.py +21 -4
  10. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/system/monitor.py +18 -2
  11. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/async_updater.py +30 -2
  12. boneio-1.5.2.dev1/boneio/core/utils/overlay.py +159 -0
  13. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/oled.py +6 -1
  14. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/mcp23017.py +163 -21
  15. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/homeassistant.py +4 -1
  16. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/actions.py +68 -0
  17. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/MANIFEST.sha256 +11 -4
  18. boneio-1.5.2.dev1/boneio/migrations/assets/journald/journald.conf +43 -0
  19. boneio-1.5.2.dev1/boneio/migrations/assets/kernel/postinst-boneio-overlay +79 -0
  20. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/boneio-oled-boot.service +30 -0
  21. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/boneio.service +49 -0
  22. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/avahi-daemon-defer.conf +11 -0
  23. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/bb-usb-gadgets-defer.conf +22 -0
  24. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/mosquitto-priority.conf +16 -0
  25. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/timer-no-persistent.conf +21 -0
  26. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/dropins/user-manager-defer.conf +27 -0
  27. boneio-1.5.2.dev1/boneio/migrations/assets/systemd/linger-marker +0 -0
  28. boneio-1.5.2.dev1/boneio/migrations/assets/usr-local-bin/set-hostname-once.sh +15 -0
  29. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/bootstrap/boneio-migrate +130 -1
  30. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/runner.py +155 -0
  31. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_10_disable_console_setup.py +33 -0
  32. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_11_timer_catchup.py +64 -0
  33. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_12_oled_splash_off_critical_path.py +69 -0
  34. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_13_mosquitto_priority.py +43 -0
  35. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_14_journal_apparent_size.py +50 -0
  36. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_15_prune_orphan_journals.py +37 -0
  37. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_16_login_linger.py +53 -0
  38. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_17_defer_user_manager.py +60 -0
  39. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_18_fix_hostname_once.py +57 -0
  40. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_5_overlay_kernel_hook.py +32 -0
  41. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_6_boot_service_order.py +59 -0
  42. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_7_journald_limits.py +47 -0
  43. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_8_apparmor_prune.py +72 -0
  44. boneio-1.5.2.dev1/boneio/migrations/versions/v1_5_9_defer_nonessential.py +50 -0
  45. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/wanas415.json +1 -1
  46. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/runner.py +4 -1
  47. boneio-1.5.2.dev1/boneio/version.py +2 -0
  48. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/action_validation.py +7 -4
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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
  56. boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/LogViewer-Bs7Xx9vL.js +2 -0
  57. 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
  58. 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
  59. boneio-1.5.2.dev1/boneio/webui/frontend-dist/assets/OutputsView-B6cZ8NHI.js +1 -0
  60. 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
  61. 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
  62. 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
  63. 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
  64. 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
  65. 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
  66. 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
  67. 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
  68. 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
  69. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/index.html +2 -2
  70. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/sw.js +1 -1
  71. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_core.py +20 -0
  72. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/nodered.py +28 -2
  73. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/system.py +35 -10
  74. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/update.py +34 -2
  75. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1/boneio.egg-info}/PKG-INFO +1 -1
  76. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/SOURCES.txt +42 -20
  77. boneio-1.5.0.dev41/boneio/migrations/assets/journald/journald.conf +0 -6
  78. boneio-1.5.0.dev41/boneio/migrations/assets/systemd/boneio-oled-boot.service +0 -17
  79. boneio-1.5.0.dev41/boneio/migrations/assets/systemd/boneio.service +0 -15
  80. boneio-1.5.0.dev41/boneio/migrations/assets/usr-local-bin/set-hostname-once.sh +0 -10
  81. boneio-1.5.0.dev41/boneio/version.py +0 -2
  82. boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/LogViewer-RefUkoWR.js +0 -2
  83. boneio-1.5.0.dev41/boneio/webui/frontend-dist/assets/OutputsView-BxFJRwd4.js +0 -1
  84. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/LICENSE +0 -0
  85. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/MANIFEST.in +0 -0
  86. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/README.md +0 -0
  87. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/__init__.py +0 -0
  88. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/input.yaml +0 -0
  89. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_24_16.yaml +0 -0
  90. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_32_10.yaml +0 -0
  91. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_32_5.yaml +0 -0
  92. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_cover.yaml +0 -0
  93. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
  94. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/input.yaml +0 -0
  95. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_24_16.yaml +0 -0
  96. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_32_10.yaml +0 -0
  97. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_32_5.yaml +0 -0
  98. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_cover.yaml +0 -0
  99. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
  100. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/input.yaml +0 -0
  101. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_24_16.yaml +0 -0
  102. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_32_10.yaml +0 -0
  103. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_32_5.yaml +0 -0
  104. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_cover.yaml +0 -0
  105. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
  106. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/input.yaml +0 -0
  107. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_24_16.yaml +0 -0
  108. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_32_10.yaml +0 -0
  109. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_cover.yaml +0 -0
  110. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
  111. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/input.yaml +0 -0
  112. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_24_16.yaml +0 -0
  113. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_32_10.yaml +0 -0
  114. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_cover.yaml +0 -0
  115. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
  116. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/input.yaml +0 -0
  117. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_24_16.yaml +0 -0
  118. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_32_10.yaml +0 -0
  119. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_48_4.yaml +0 -0
  120. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_cover.yaml +0 -0
  121. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
  122. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/input.yaml +0 -0
  123. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_24_16.yaml +0 -0
  124. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_32_10.yaml +0 -0
  125. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_48_4.yaml +0 -0
  126. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_cover.yaml +0 -0
  127. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
  128. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/input.yaml +0 -0
  129. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_24_16.yaml +0 -0
  130. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_32_10.yaml +0 -0
  131. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_48_4.yaml +0 -0
  132. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_cover.yaml +0 -0
  133. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/boards/1.0/output_cover_mix.yaml +0 -0
  134. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/__init__.py +0 -0
  135. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/__init__.py +0 -0
  136. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/cover/cover.py +0 -0
  137. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/group/__init__.py +0 -0
  138. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/group/output_group.py +0 -0
  139. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/__init__.py +0 -0
  140. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/binary_sensor.py +0 -0
  141. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/detectors.py +0 -0
  142. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/event.py +0 -0
  143. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/remote/__init__.py +0 -0
  144. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/remote/base.py +0 -0
  145. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/input/remote/esphome.py +0 -0
  146. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/irrigation/__init__.py +0 -0
  147. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/irrigation/water_source.py +0 -0
  148. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/__init__.py +0 -0
  149. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/basic.py +0 -0
  150. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/buzzer.py +0 -0
  151. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/mcp.py +0 -0
  152. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/pca.py +0 -0
  153. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/pcf.py +0 -0
  154. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/output/remote.py +0 -0
  155. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/sensor/__init__.py +0 -0
  156. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/sensor/virtual_energy.py +0 -0
  157. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/__init__.py +0 -0
  158. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/alarm_panel.py +0 -0
  159. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/gate_cover.py +0 -0
  160. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/components/template/thermostat.py +0 -0
  161. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/const.py +0 -0
  162. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/__init__.py +0 -0
  163. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/__init__.py +0 -0
  164. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/__init__.py +0 -0
  165. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/docker-compose-cloud.yaml +0 -0
  166. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/docker-compose.yaml +0 -0
  167. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/data/init-certs-cloud.sh +0 -0
  168. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/registration.py +0 -0
  169. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/cloud/secrets.py +0 -0
  170. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/__init__.py +0 -0
  171. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/config_helper.py +0 -0
  172. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/__init__.py +0 -0
  173. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v1_proxy_port.py +0 -0
  174. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v2_transition.py +0 -0
  175. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v4_wled_cache.py +0 -0
  176. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/migrations/v5_ina_screen.py +0 -0
  177. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/package-lock.json +0 -0
  178. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/package.json +0 -0
  179. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/schema_converter.py +0 -0
  180. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/config/yaml_compat.py +0 -0
  181. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/discovery.py +0 -0
  182. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/events/__init__.py +0 -0
  183. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/events/bus.py +0 -0
  184. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/__init__.py +0 -0
  185. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/action_conditions.py +0 -0
  186. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/canopen.py +0 -0
  187. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/display.py +0 -0
  188. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/inputs.py +0 -0
  189. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/irrigation.py +0 -0
  190. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/manager.py +0 -0
  191. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/modbus.py +0 -0
  192. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/remote.py +0 -0
  193. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/remote_input_registrar.py +0 -0
  194. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/sensors.py +0 -0
  195. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/__init__.py +0 -0
  196. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/alarm.py +0 -0
  197. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/gate_cover.py +0 -0
  198. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates/thermostat.py +0 -0
  199. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/manager/templates.py +0 -0
  200. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/__init__.py +0 -0
  201. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/basic.py +0 -0
  202. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/basic_mqtt.py +0 -0
  203. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/composite.py +0 -0
  204. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/local.py +0 -0
  205. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/lox.py +0 -0
  206. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/mqtt.py +0 -0
  207. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/messaging/queue.py +0 -0
  208. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/__init__.py +0 -0
  209. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/base.py +0 -0
  210. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/can.py +0 -0
  211. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/esphome.py +0 -0
  212. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/mqtt.py +0 -0
  213. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/wled.py +0 -0
  214. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/remote/wled_cache.py +0 -0
  215. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/sensor/__init__.py +0 -0
  216. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/sensor/base.py +0 -0
  217. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/sensor/system.py +0 -0
  218. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/state/__init__.py +0 -0
  219. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/state/manager.py +0 -0
  220. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/system/__init__.py +0 -0
  221. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/system/host_data.py +0 -0
  222. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/__init__.py +0 -0
  223. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/conditions.py +0 -0
  224. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/filter.py +0 -0
  225. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/font_util.py +0 -0
  226. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/logger.py +0 -0
  227. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/timeperiod.py +0 -0
  228. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/core/utils/util.py +0 -0
  229. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/adc.yaml +0 -0
  230. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
  231. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/config.yaml +0 -0
  232. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/event.yaml +0 -0
  233. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/mqtt.yaml +0 -0
  234. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/24x16/output24x16A.yaml +0 -0
  235. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/adc.yaml +0 -0
  236. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
  237. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/config.yaml +0 -0
  238. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/event.yaml +0 -0
  239. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/mqtt.yaml +0 -0
  240. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/32x10/output32x10A.yaml +0 -0
  241. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/adc.yaml +0 -0
  242. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/binary_sensor.yaml +0 -0
  243. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/config.yaml +0 -0
  244. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/event.yaml +0 -0
  245. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/mqtt.yaml +0 -0
  246. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/48x4/output48x4A.yaml +0 -0
  247. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/__init__.py +0 -0
  248. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/can_master.yaml +0 -0
  249. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/can_slave.yaml +0 -0
  250. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/adc.yaml +0 -0
  251. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/binary_sensor.yaml +0 -0
  252. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/config.yaml +0 -0
  253. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/cover.yaml +0 -0
  254. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/event.yaml +0 -0
  255. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/mqtt.yaml +0 -0
  256. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover/outputCover.yaml +0 -0
  257. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/adc.yaml +0 -0
  258. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
  259. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/config.yaml +0 -0
  260. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/cover.yaml +0 -0
  261. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/event.yaml +0 -0
  262. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
  263. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
  264. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/adc.yaml +0 -0
  265. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
  266. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
  267. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
  268. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
  269. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/event_all.yaml +0 -0
  270. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
  271. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
  272. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
  273. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
  274. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
  275. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
  276. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/exceptions.py +0 -0
  277. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/__init__.py +0 -0
  278. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/analog/__init__.py +0 -0
  279. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/analog/adc.py +0 -0
  280. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/__init__.py +0 -0
  281. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/bridge.py +0 -0
  282. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/client.py +0 -0
  283. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/interface.py +0 -0
  284. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/node.py +0 -0
  285. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/node_id.py +0 -0
  286. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/can/test_od.py +0 -0
  287. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/__init__.py +0 -0
  288. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/early_oled.py +0 -0
  289. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/display/fonts/danube__.ttf +0 -0
  290. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/__init__.py +0 -0
  291. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/__init__.py +0 -0
  292. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
  293. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
  294. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/input/__init__.py +0 -0
  295. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/input/base.py +0 -0
  296. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/gpio/input/manager.py +0 -0
  297. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/__init__.py +0 -0
  298. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/bus.py +0 -0
  299. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina219.py +0 -0
  300. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina219_driver.py +0 -0
  301. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina226.py +0 -0
  302. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/ina226_driver.py +0 -0
  303. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/mcp9808.py +0 -0
  304. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/i2c/pct2075.py +0 -0
  305. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/onewire/__init__.py +0 -0
  306. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/onewire/dallas.py +0 -0
  307. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/__init__.py +0 -0
  308. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/__init__.py +0 -0
  309. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/base.py +0 -0
  310. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
  311. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
  312. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/__init__.py +0 -0
  313. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/interlock.py +0 -0
  314. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/integration/lox_template.py +0 -0
  315. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/__init__.py +0 -0
  316. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/daemon.json +0 -0
  317. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/caddy/502.html +0 -0
  318. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/caddy/init-certs.sh +0 -0
  319. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/docker-compose.yaml +0 -0
  320. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/nginx/default.conf +0 -0
  321. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/docker/nodered/node-red/settings.js +0 -0
  322. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/modules-load.d/onewire.conf +0 -0
  323. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/mosquitto/boneio.conf +0 -0
  324. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/sudoers/boneio +0 -0
  325. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/systemd/boneio-oled-shutdown.service +0 -0
  326. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/systemd/set-hostname-once.service +0 -0
  327. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_boot_splash.py +0 -0
  328. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_boot_splash.sh +0 -0
  329. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_msg.py +0 -0
  330. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/assets/usr-sbin/oled_msg.sh +0 -0
  331. {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
  332. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/bootstrap/install-helper.sh +0 -0
  333. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/bootstrap/sudoers-migrate +0 -0
  334. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/__init__.py +0 -0
  335. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_3_0_baseline.py +0 -0
  336. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_3_1_fix_oled_boot.py +0 -0
  337. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_3_2_cleanup_can_sudoers.py +0 -0
  338. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_4_0_fix_mqtt_sudoers.py +0 -0
  339. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_4_3_oled_shutdown.py +0 -0
  340. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_4_4_caddy.py +0 -0
  341. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_0_fix_oled_fifo_permissions.py +0 -0
  342. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_1_ufw_lox_udp.py +0 -0
  343. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_2_libyaml.py +0 -0
  344. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_3_libyaml_retry.py +0 -0
  345. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/migrations/versions/v1_5_4_onewire_modules.py +0 -0
  346. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/__init__.py +0 -0
  347. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/cli.py +0 -0
  348. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/client.py +0 -0
  349. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/coordinator.py +0 -0
  350. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/__init__.py +0 -0
  351. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/dts1964_3f.json +0 -0
  352. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/le-03mw.json +0 -0
  353. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/le-03mwct.json +0 -0
  354. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
  355. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
  356. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
  357. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/socomec_e03.json +0 -0
  358. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/energy_meters/socomec_e23.json +0 -0
  359. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/eht-topventil-plus.json +0 -0
  360. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
  361. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/thessla.json +0 -0
  362. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/hvac/ventclear.json +0 -0
  363. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/inverters/sofar.json +0 -0
  364. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/other/esp32_relay_x4_modbus.json +0 -0
  365. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/other/n4dsc08.json +0 -0
  366. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/other/r4dcb08.json +0 -0
  367. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/boneio-edge-temp.json +0 -0
  368. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/cwt.json +0 -0
  369. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/dyp-a12-ultrasonic.json +0 -0
  370. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/gdfs.json +0 -0
  371. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/gdfx.json +0 -0
  372. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
  373. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/pt100.json +0 -0
  374. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/qdw90a.json +0 -0
  375. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/sht20.json +0 -0
  376. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/devices/sensors/sht30.json +0 -0
  377. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/__init__.py +0 -0
  378. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/base.py +0 -0
  379. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/__init__.py +0 -0
  380. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/numeric.py +0 -0
  381. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/select.py +0 -0
  382. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/switch.py +0 -0
  383. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/derived/text.py +0 -0
  384. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/__init__.py +0 -0
  385. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/binary.py +0 -0
  386. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/numeric.py +0 -0
  387. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/sensor/text.py +0 -0
  388. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/writeable/__init__.py +0 -0
  389. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/writeable/binary.py +0 -0
  390. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/entities/writeable/numeric.py +0 -0
  391. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/mock_coordinator.py +0 -0
  392. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/modbus/utils.py +0 -0
  393. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/__init__.py +0 -0
  394. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/actions.py +0 -0
  395. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/events.py +0 -0
  396. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/files.py +0 -0
  397. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/logs.py +0 -0
  398. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/mqtt.py +0 -0
  399. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/models/state.py +0 -0
  400. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/actions.yaml +0 -0
  401. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/actions_sensor.yaml +0 -0
  402. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/actions_switch.yaml +0 -0
  403. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/condition.yaml +0 -0
  404. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/filters.yaml +0 -0
  405. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/filters_adc.yaml +0 -0
  406. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/id.yaml +0 -0
  407. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/remote_devices.yaml +0 -0
  408. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/remote_inputs.yaml +0 -0
  409. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/remote_outputs.yaml +0 -0
  410. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/schema.yaml +0 -0
  411. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/temp_unit.yaml +0 -0
  412. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/schema/update_interval.yaml +0 -0
  413. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/app.py +0 -0
  414. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/dashboard_cards.py +0 -0
  415. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/HelpLabel-BSTjOtDA.js +0 -0
  416. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/LongPressWrapper-BHOQV7Wq.js +0 -0
  417. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/Sparkline-BGWlVLtt.js +0 -0
  418. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/aiConfig-IRYCBmLm.js +0 -0
  419. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/aiWizardPrompt-D9OJ-cE7.js +0 -0
  420. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/axios-DHUeYRnu.js +0 -0
  421. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/basePath-CxHj-SSK.js +0 -0
  422. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/clipboard-CCtx29e-.js +0 -0
  423. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  424. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/configCache-BAkc0Ye7.js +0 -0
  425. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/css.worker-CvXBzhp8.js +0 -0
  426. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/editor.worker-Cn2oRESe.js +0 -0
  427. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/formatters-zOiGPJLh.js +0 -0
  428. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/html.worker-BO6WuOEO.js +0 -0
  429. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/json.worker-BkJRGcCJ.js +0 -0
  430. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/longPress-Dx7OCSyP.js +0 -0
  431. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/modbusDeviceCatalog-L6as-BKo.js +0 -0
  432. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/monaco-61yH0vfd.js +0 -0
  433. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/monaco-Br_kD0ds.css +0 -0
  434. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/rolldown-runtime-QTnfLwEv.js +0 -0
  435. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/select-B2YDgQ4X.js +0 -0
  436. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/tabs-box-Dj36r4_e.js +0 -0
  437. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/ts.worker-B0J26iPs.js +0 -0
  438. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/utils-C8nShLO6.js +0 -0
  439. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/vendor-IzweXARb.js +0 -0
  440. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -0
  441. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/assets/yaml.worker-BKRoXlmz.js +0 -0
  442. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio-192.png +0 -0
  443. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio-512.png +0 -0
  444. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio.svg +0 -0
  445. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
  446. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/adc.schema.json +0 -0
  447. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/areas.schema.json +0 -0
  448. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/binary_sensor.schema.json +0 -0
  449. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/boneio.schema.json +0 -0
  450. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/can.schema.json +0 -0
  451. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/config.schema.json +0 -0
  452. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/cover.schema.json +0 -0
  453. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/dallas.schema.json +0 -0
  454. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/ds2482.schema.json +0 -0
  455. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/event.schema.json +0 -0
  456. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/ina219.schema.json +0 -0
  457. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/ina226.schema.json +0 -0
  458. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/irrigation.schema.json +0 -0
  459. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/lm75.schema.json +0 -0
  460. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/logger.schema.json +0 -0
  461. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/lox_udp.schema.json +0 -0
  462. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/mcp23017.schema.json +0 -0
  463. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/mcp9808.schema.json +0 -0
  464. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/modbus.schema.json +0 -0
  465. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/modbus_devices.schema.json +0 -0
  466. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/mqtt.schema.json +0 -0
  467. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/oled.schema.json +0 -0
  468. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/output.schema.json +0 -0
  469. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/output_group.schema.json +0 -0
  470. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/pca9685.schema.json +0 -0
  471. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/pcf8575.schema.json +0 -0
  472. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/remote_devices.schema.json +0 -0
  473. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/remote_inputs.schema.json +0 -0
  474. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/remote_outputs.schema.json +0 -0
  475. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/sensor.schema.json +0 -0
  476. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/template.schema.json +0 -0
  477. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/virtual_energy_sensor.schema.json +0 -0
  478. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/schema/web.schema.json +0 -0
  479. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/frontend-dist/workbox-4918f2f6.js +0 -0
  480. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/hvac_svg_templates.py +0 -0
  481. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/middleware/__init__.py +0 -0
  482. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/middleware/auth.py +0 -0
  483. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/modbus_card_templates.py +0 -0
  484. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/__init__.py +0 -0
  485. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/auth.py +0 -0
  486. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/caddy.py +0 -0
  487. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/can.py +0 -0
  488. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config.py +0 -0
  489. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_actions.py +0 -0
  490. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_backups.py +0 -0
  491. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_discovery.py +0 -0
  492. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/config_files.py +0 -0
  493. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/covers.py +0 -0
  494. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/dashboard.py +0 -0
  495. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/dev_fake_device.py +0 -0
  496. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/irrigation.py +0 -0
  497. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/migrations.py +0 -0
  498. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/modbus.py +0 -0
  499. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/mqtt_reference.py +0 -0
  500. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/outputs.py +0 -0
  501. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/remote_devices.py +0 -0
  502. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/sensors.py +0 -0
  503. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/templates.py +0 -0
  504. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/timezone_sudoers.py +0 -0
  505. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/routes/tools.py +0 -0
  506. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/adc.schema.json +0 -0
  507. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/areas.schema.json +0 -0
  508. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/binary_sensor.schema.json +0 -0
  509. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/boneio.schema.json +0 -0
  510. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/can.schema.json +0 -0
  511. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/config.schema.json +0 -0
  512. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/cover.schema.json +0 -0
  513. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/dallas.schema.json +0 -0
  514. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/ds2482.schema.json +0 -0
  515. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/event.schema.json +0 -0
  516. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/ina219.schema.json +0 -0
  517. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/ina226.schema.json +0 -0
  518. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/irrigation.schema.json +0 -0
  519. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/lm75.schema.json +0 -0
  520. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/logger.schema.json +0 -0
  521. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/lox_udp.schema.json +0 -0
  522. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/mcp23017.schema.json +0 -0
  523. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/mcp9808.schema.json +0 -0
  524. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/modbus.schema.json +0 -0
  525. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/modbus_devices.schema.json +0 -0
  526. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/mqtt.schema.json +0 -0
  527. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/oled.schema.json +0 -0
  528. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/output.schema.json +0 -0
  529. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/output_group.schema.json +0 -0
  530. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/pca9685.schema.json +0 -0
  531. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/pcf8575.schema.json +0 -0
  532. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/remote_devices.schema.json +0 -0
  533. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/remote_inputs.schema.json +0 -0
  534. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/remote_outputs.schema.json +0 -0
  535. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/sensor.schema.json +0 -0
  536. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/template.schema.json +0 -0
  537. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
  538. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/schema/web.schema.json +0 -0
  539. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/services/__init__.py +0 -0
  540. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/services/logs.py +0 -0
  541. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/sudo_rate_limiter.py +0 -0
  542. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/web_server.py +0 -0
  543. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio/webui/websocket_manager.py +0 -0
  544. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/dependency_links.txt +0 -0
  545. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/entry_points.txt +0 -0
  546. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/requires.txt +0 -0
  547. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/boneio.egg-info/top_level.txt +0 -0
  548. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/pyproject.toml +0 -0
  549. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/setup.cfg +0 -0
  550. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/setup.py +0 -0
  551. {boneio-1.5.0.dev41 → boneio-1.5.2.dev1}/tests/test_py313_compatibility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boneio
3
- Version: 1.5.0.dev41
3
+ Version: 1.5.2.dev1
4
4
  Summary: Python App for BoneIO
5
5
  Author-email: Paweł Szafer <pszafer@gmail.com>
6
6
  License: GNU General Public License v3.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
- await self.shutdown()
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
- if isinstance(value, int):
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
- raise ConfigurationException(
728
- f"Don't know what '{value}' means as it has no time *unit*! Did you mean '{value}s'?"
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
- kwarg = unit_to_kwarg[one_of(*unit_to_kwarg)(match.group(2))]
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__(manager=manager, update_interval=update_interval)
76
+ super().__init__(
77
+ manager=manager,
78
+ update_interval=update_interval,
79
+ initial_delay=initial_delay,
80
+ )
68
81
 
69
- _LOGGER.info("UpdateManager initialized (check interval: %s)", update_interval)
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 _fetch_github_releases
144
+ from boneio.webui.routes.update import _fetch_github_releases_async
128
145
 
129
- releases, error = _fetch_github_releases()
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 interface.
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
- addrs = psutil.net_if_addrs().get("eth0", [])
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__(self, manager: Manager, update_interval: TimePeriod, **kwargs):
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
- # Perform first update immediately on startup
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)