boneIO 1.1.1.dev1__tar.gz → 1.2.0.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 (428) hide show
  1. {boneio-1.1.1.dev1/boneio.egg-info → boneio-1.2.0.dev1}/PKG-INFO +1 -1
  2. boneio-1.2.0.dev1/boneio/core/cloud/__init__.py +5 -0
  3. boneio-1.2.0.dev1/boneio/core/cloud/data/init-certs-cloud.sh +154 -0
  4. boneio-1.2.0.dev1/boneio/core/cloud/registration.py +454 -0
  5. boneio-1.2.0.dev1/boneio/core/cloud/secrets.py +56 -0
  6. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/config/config_helper.py +32 -0
  7. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/config/yaml_util.py +96 -0
  8. boneio-1.2.0.dev1/boneio/example_config/__init__.py +0 -0
  9. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/runner.py +27 -0
  10. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/schema.yaml +30 -0
  11. boneio-1.2.0.dev1/boneio/version.py +2 -0
  12. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/app.py +74 -5
  13. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/cssMode-SLqjH3qK.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/cssMode-CiCRy8oh.js +1 -1
  14. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/freemarker2-DXMvZO7c.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/freemarker2-CTpscDup.js +1 -1
  15. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/handlebars-DldmTvGn.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/handlebars-CT6ctFwd.js +1 -1
  16. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/html-BeFUXNc_.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/html-De15ux6k.js +1 -1
  17. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/htmlMode-D4OnYTmf.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/htmlMode-DEBxJqOc.js +1 -1
  18. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/index-AE1j15fF.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/index-BmBRIx27.js +212 -212
  19. boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/index-jeVCQb5d.css +1 -0
  20. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/javascript-tD5AV0w8.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/javascript-DLPEXty3.js +1 -1
  21. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/jsonMode-D8KZNSNi.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/jsonMode-Bq6LVq6M.js +1 -1
  22. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/liquid-B4w537sW.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/liquid-CyAziv-e.js +1 -1
  23. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/mdx-DB1izvJl.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/mdx-rdvLT30i.js +1 -1
  24. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/python-CG6dl7EF.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/python-IsDchUF3.js +1 -1
  25. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/razor-BqVac-Wv.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/razor-Dqhz4KTK.js +1 -1
  26. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/tsMode-CvBEEAxI.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/tsMode-BPlRYnYg.js +1 -1
  27. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/typescript-BIvQiQJr.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/typescript-gTU2cHDi.js +1 -1
  28. boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/workbox-window.prod.es5-vqzQaGvo.js +2 -0
  29. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/xml-BtFDS-MH.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/xml-BhXsIMpb.js +1 -1
  30. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/yaml-D0Bwrhp9.js → boneio-1.2.0.dev1/boneio/webui/frontend-dist/assets/yaml-BA6LfVaz.js +1 -1
  31. boneio-1.2.0.dev1/boneio/webui/frontend-dist/boneio-192.png +0 -0
  32. boneio-1.2.0.dev1/boneio/webui/frontend-dist/boneio-512.png +0 -0
  33. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/index.html +9 -2
  34. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/adc.schema.json +2 -2
  35. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/binary_sensor.schema.json +22 -22
  36. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/boneio.schema.json +2 -2
  37. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/config.schema.json +236 -194
  38. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/cover.schema.json +8 -8
  39. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/event.schema.json +78 -78
  40. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/ina219.schema.json +4 -4
  41. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/lm75.schema.json +4 -4
  42. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/mcp23017.schema.json +4 -4
  43. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/mcp9808.schema.json +4 -4
  44. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/modbus.schema.json +6 -6
  45. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/modbus_devices.schema.json +8 -8
  46. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/mqtt.schema.json +2 -2
  47. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/oled.schema.json +2 -2
  48. {boneio-1.1.1.dev1/boneio/webui/schema → boneio-1.2.0.dev1/boneio/webui/frontend-dist/schem}/output.schema.json +8 -8
  49. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/pca9685.schema.json +4 -4
  50. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/pcf8575.schema.json +4 -4
  51. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/remote_devices.schema.json +26 -26
  52. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/sensor.schema.json +2 -2
  53. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/web.schema.json +46 -4
  54. boneio-1.2.0.dev1/boneio/webui/frontend-dist/sw.js +1 -0
  55. boneio-1.2.0.dev1/boneio/webui/frontend-dist/workbox-226dbdbf.js +1 -0
  56. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/system.py +92 -1
  57. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/adc.schema.json +2 -2
  58. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/binary_sensor.schema.json +22 -22
  59. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/boneio.schema.json +2 -2
  60. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/config.schema.json +236 -194
  61. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/cover.schema.json +8 -8
  62. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/event.schema.json +78 -78
  63. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/ina219.schema.json +4 -4
  64. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/lm75.schema.json +4 -4
  65. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/mcp23017.schema.json +4 -4
  66. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/mcp9808.schema.json +4 -4
  67. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/modbus.schema.json +6 -6
  68. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/modbus_devices.schema.json +8 -8
  69. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/mqtt.schema.json +2 -2
  70. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/oled.schema.json +2 -2
  71. {boneio-1.1.1.dev1/boneio/webui/frontend-dist/schem → boneio-1.2.0.dev1/boneio/webui/schema}/output.schema.json +8 -8
  72. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/pca9685.schema.json +4 -4
  73. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/pcf8575.schema.json +4 -4
  74. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/remote_devices.schema.json +26 -26
  75. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/sensor.schema.json +2 -2
  76. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/web.schema.json +46 -4
  77. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1/boneio.egg-info}/PKG-INFO +1 -1
  78. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio.egg-info/SOURCES.txt +27 -17
  79. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/pyproject.toml +1 -1
  80. boneio-1.1.1.dev1/boneio/version.py +0 -2
  81. boneio-1.1.1.dev1/boneio/webui/frontend-dist/assets/index-D0XGmf2O.css +0 -1
  82. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/LICENSE +0 -0
  83. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/MANIFEST.in +0 -0
  84. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/README.md +0 -0
  85. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/__init__.py +0 -0
  86. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.2/input.yaml +0 -0
  87. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.2/output_24_16.yaml +0 -0
  88. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.2/output_32_10.yaml +0 -0
  89. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.2/output_32_5.yaml +0 -0
  90. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.2/output_cover.yaml +0 -0
  91. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.2/output_cover_mix.yaml +0 -0
  92. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.3/input.yaml +0 -0
  93. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.3/output_24_16.yaml +0 -0
  94. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.3/output_32_10.yaml +0 -0
  95. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.3/output_32_5.yaml +0 -0
  96. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.3/output_cover.yaml +0 -0
  97. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.3/output_cover_mix.yaml +0 -0
  98. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.4/input.yaml +0 -0
  99. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.4/output_24_16.yaml +0 -0
  100. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.4/output_32_10.yaml +0 -0
  101. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.4/output_32_5.yaml +0 -0
  102. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.4/output_cover.yaml +0 -0
  103. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
  104. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.5/input.yaml +0 -0
  105. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.5/output_24_16.yaml +0 -0
  106. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.5/output_32_10.yaml +0 -0
  107. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.5/output_cover.yaml +0 -0
  108. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.5/output_cover_mix.yaml +0 -0
  109. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.6/input.yaml +0 -0
  110. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.6/output_24_16.yaml +0 -0
  111. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.6/output_32_10.yaml +0 -0
  112. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.6/output_cover.yaml +0 -0
  113. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.6/output_cover_mix.yaml +0 -0
  114. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.7/input.yaml +0 -0
  115. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.7/output_24_16.yaml +0 -0
  116. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.7/output_32_10.yaml +0 -0
  117. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.7/output_cover.yaml +0 -0
  118. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
  119. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.8/input.yaml +0 -0
  120. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.8/output_24_16.yaml +0 -0
  121. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.8/output_32_10.yaml +0 -0
  122. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.8/output_cover.yaml +0 -0
  123. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
  124. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/bonecli.py +0 -0
  125. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/__init__.py +0 -0
  126. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/cover/__init__.py +0 -0
  127. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/cover/cover.py +0 -0
  128. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/cover/previous.py +0 -0
  129. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/cover/time_based.py +0 -0
  130. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/cover/venetian.py +0 -0
  131. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/group/__init__.py +0 -0
  132. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/group/output_group.py +0 -0
  133. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/input/__init__.py +0 -0
  134. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/input/binary_sensor.py +0 -0
  135. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/input/detectors.py +0 -0
  136. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/input/event.py +0 -0
  137. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/output/__init__.py +0 -0
  138. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/output/basic.py +0 -0
  139. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/output/mcp.py +0 -0
  140. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/output/pca.py +0 -0
  141. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/output/pcf.py +0 -0
  142. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/sensor/__init__.py +0 -0
  143. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/components/sensor/virtual_energy.py +0 -0
  144. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/const.py +0 -0
  145. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/__init__.py +0 -0
  146. {boneio-1.1.1.dev1/boneio/example_config → boneio-1.2.0.dev1/boneio/core/cloud/data}/__init__.py +0 -0
  147. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/config/__init__.py +0 -0
  148. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/config/package-lock.json +0 -0
  149. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/config/package.json +0 -0
  150. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/config/schema_converter.py +0 -0
  151. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/discovery.py +0 -0
  152. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/events/__init__.py +0 -0
  153. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/events/bus.py +0 -0
  154. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/__init__.py +0 -0
  155. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/covers.py +0 -0
  156. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/display.py +0 -0
  157. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/inputs.py +0 -0
  158. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/manager.py +0 -0
  159. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/modbus.py +0 -0
  160. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/outputs.py +0 -0
  161. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/remote.py +0 -0
  162. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/sensors.py +0 -0
  163. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/manager/update.py +0 -0
  164. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/messaging/__init__.py +0 -0
  165. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/messaging/basic.py +0 -0
  166. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/messaging/basic_mqtt.py +0 -0
  167. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/messaging/local.py +0 -0
  168. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/messaging/mqtt.py +0 -0
  169. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/messaging/queue.py +0 -0
  170. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/remote/__init__.py +0 -0
  171. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/remote/base.py +0 -0
  172. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/remote/esphome.py +0 -0
  173. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/remote/mqtt.py +0 -0
  174. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/remote/wled.py +0 -0
  175. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/sensor/__init__.py +0 -0
  176. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/sensor/base.py +0 -0
  177. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/sensor/system.py +0 -0
  178. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/state/__init__.py +0 -0
  179. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/state/manager.py +0 -0
  180. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/system/__init__.py +0 -0
  181. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/system/host_data.py +0 -0
  182. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/system/monitor.py +0 -0
  183. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/__init__.py +0 -0
  184. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/async_updater.py +0 -0
  185. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/filter.py +0 -0
  186. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/font_util.py +0 -0
  187. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/logger.py +0 -0
  188. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/timeperiod.py +0 -0
  189. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/core/utils/util.py +0 -0
  190. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/24x16/adc.yaml +0 -0
  191. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
  192. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/24x16/config.yaml +0 -0
  193. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/24x16/event.yaml +0 -0
  194. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/24x16/mqtt.yaml +0 -0
  195. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/24x16/output24x16A.yaml +0 -0
  196. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/32x10/adc.yaml +0 -0
  197. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
  198. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/32x10/config.yaml +0 -0
  199. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/32x10/event.yaml +0 -0
  200. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/32x10/mqtt.yaml +0 -0
  201. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/32x10/output32x10A.yaml +0 -0
  202. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/adc.yaml +0 -0
  203. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/binary_sensor.yaml +0 -0
  204. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/config.yaml +0 -0
  205. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/cover.yaml +0 -0
  206. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/event.yaml +0 -0
  207. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/mqtt.yaml +0 -0
  208. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover/outputCover.yaml +0 -0
  209. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/adc.yaml +0 -0
  210. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
  211. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/config.yaml +0 -0
  212. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/cover.yaml +0 -0
  213. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/event.yaml +0 -0
  214. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
  215. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
  216. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/adc.yaml +0 -0
  217. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
  218. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
  219. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
  220. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
  221. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/event_all.yaml +0 -0
  222. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
  223. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
  224. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
  225. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
  226. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
  227. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
  228. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/exceptions.py +0 -0
  229. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/__init__.py +0 -0
  230. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/analog/__init__.py +0 -0
  231. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/analog/adc.py +0 -0
  232. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/display/__init__.py +0 -0
  233. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/display/fonts/danube__.ttf +0 -0
  234. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/display/oled.py +0 -0
  235. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/__init__.py +0 -0
  236. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/expanders/__init__.py +0 -0
  237. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/expanders/mcp23017.py +0 -0
  238. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/expanders/pca9685.py +0 -0
  239. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/expanders/pcf8575.py +0 -0
  240. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/input/__init__.py +0 -0
  241. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/input/base.py +0 -0
  242. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/gpio/input/manager.py +0 -0
  243. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/i2c/__init__.py +0 -0
  244. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/i2c/bus.py +0 -0
  245. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/i2c/ina219.py +0 -0
  246. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/i2c/ina219_driver.py +0 -0
  247. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/i2c/mcp9808.py +0 -0
  248. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/i2c/pct2075.py +0 -0
  249. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/onewire/__init__.py +0 -0
  250. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/onewire/bus.py +0 -0
  251. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/onewire/dallas.py +0 -0
  252. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/onewire/ds2482.py +0 -0
  253. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/sensor/__init__.py +0 -0
  254. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/sensor/temperature/__init__.py +0 -0
  255. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/sensor/temperature/base.py +0 -0
  256. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
  257. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
  258. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/integration/__init__.py +0 -0
  259. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/integration/homeassistant.py +0 -0
  260. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/integration/interlock.py +0 -0
  261. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/__init__.py +0 -0
  262. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/cli.py +0 -0
  263. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/client.py +0 -0
  264. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/coordinator.py +0 -0
  265. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/__init__.py +0 -0
  266. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/le-03mw.json +0 -0
  267. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/le-03mwct.json +0 -0
  268. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
  269. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
  270. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
  271. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/socomec_e03.json +0 -0
  272. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/energy_meters/socomec_e23.json +0 -0
  273. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
  274. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/hvac/ventclear.json +0 -0
  275. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/inverters/sofar.json +0 -0
  276. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/inverters/thessla.json +0 -0
  277. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/other/n4dsc08.json +0 -0
  278. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/other/r4dcb08.json +0 -0
  279. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/other/wanas415.json +0 -0
  280. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/cwt.json +0 -0
  281. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/dts1964_3f.json +0 -0
  282. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/dyp-a12-ultrasonic.json +0 -0
  283. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
  284. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/pt100.json +0 -0
  285. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/sht20.json +0 -0
  286. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/devices/sensors/sht30.json +0 -0
  287. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/__init__.py +0 -0
  288. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/base.py +0 -0
  289. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/derived/__init__.py +0 -0
  290. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/derived/numeric.py +0 -0
  291. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/derived/select.py +0 -0
  292. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/derived/switch.py +0 -0
  293. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/derived/text.py +0 -0
  294. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/sensor/__init__.py +0 -0
  295. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/sensor/binary.py +0 -0
  296. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/sensor/numeric.py +0 -0
  297. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/sensor/text.py +0 -0
  298. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/writeable/__init__.py +0 -0
  299. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/writeable/binary.py +0 -0
  300. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/entities/writeable/numeric.py +0 -0
  301. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/modbus/utils.py +0 -0
  302. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/__init__.py +0 -0
  303. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/actions.py +0 -0
  304. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/events.py +0 -0
  305. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/files.py +0 -0
  306. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/logs.py +0 -0
  307. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/mqtt.py +0 -0
  308. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/models/state.py +0 -0
  309. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/actions.yaml +0 -0
  310. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/actions_sensor.yaml +0 -0
  311. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/actions_switch.yaml +0 -0
  312. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/filters.yaml +0 -0
  313. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/filters_adc.yaml +0 -0
  314. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/id.yaml +0 -0
  315. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/remote_devices.yaml +0 -0
  316. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/temp_unit.yaml +0 -0
  317. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/schema/update_interval.yaml +0 -0
  318. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/abap-CRCWOmpq.js +0 -0
  319. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/apex-DnsZk_dE.js +0 -0
  320. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/azcli-1IWB1ccx.js +0 -0
  321. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/bat-DPkNLes8.js +0 -0
  322. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/bicep-Corcdgou.js +0 -0
  323. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/cameligo-CGrWLZr3.js +0 -0
  324. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/clojure-D9WOWImG.js +0 -0
  325. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
  326. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/coffee-B7EJu28W.js +0 -0
  327. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/cpp-SEyurbux.js +0 -0
  328. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/csharp-BoL64M5l.js +0 -0
  329. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/csp-C46ZqvIl.js +0 -0
  330. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/css-DQU6DXDx.js +0 -0
  331. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/cypher-D84EuPTj.js +0 -0
  332. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/dart-D8lhlL1r.js +0 -0
  333. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/dockerfile-DLk6rpji.js +0 -0
  334. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/ecl-BO6FnfXk.js +0 -0
  335. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/editor.worker-DsAeyiJ5.js +0 -0
  336. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/elixir-BRjLKONM.js +0 -0
  337. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/flow9-Cac8vKd7.js +0 -0
  338. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/fsharp-fd1GTHhf.js +0 -0
  339. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/go-O9LJTZXk.js +0 -0
  340. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/graphql-LQdxqEYJ.js +0 -0
  341. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/hcl-DxDQ3s82.js +0 -0
  342. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/ini-BvajGCUy.js +0 -0
  343. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/java-SYsfObOQ.js +0 -0
  344. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/json.worker-DaRII17c.js +0 -0
  345. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/julia-DQXNmw_w.js +0 -0
  346. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/kotlin-qQ0MG-9I.js +0 -0
  347. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/less-GGFNNJHn.js +0 -0
  348. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/lexon-Canl7DCW.js +0 -0
  349. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/lua-D28Ae8-K.js +0 -0
  350. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/m3-DPitgjJI.js +0 -0
  351. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/markdown-B811l8j2.js +0 -0
  352. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/mips-CdjsipkG.js +0 -0
  353. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/msdax-CYqgjx_P.js +0 -0
  354. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/mysql-BHd6q0vd.js +0 -0
  355. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/objective-c-B1aVtJYH.js +0 -0
  356. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/pascal-BhNW15KB.js +0 -0
  357. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/pascaligo-5jv8CcQD.js +0 -0
  358. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/perl-DlYyT36c.js +0 -0
  359. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/pgsql-Dy0bjov7.js +0 -0
  360. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/php-120yhfDK.js +0 -0
  361. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/pla-CjnFlu4u.js +0 -0
  362. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/postiats-CQpG440k.js +0 -0
  363. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/powerquery-DdJtto1Z.js +0 -0
  364. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/powershell-Bu_VLpJB.js +0 -0
  365. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/protobuf-IBS6jZEB.js +0 -0
  366. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/pug-kFxLfcjb.js +0 -0
  367. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/qsharp-q7JyzKFN.js +0 -0
  368. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/r-BIFz-_sK.js +0 -0
  369. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/redis-CHOsPHWR.js +0 -0
  370. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/redshift-CBifECDb.js +0 -0
  371. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/restructuredtext-CghPJEOS.js +0 -0
  372. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/ruby-CYWGW-b1.js +0 -0
  373. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/rust-DMDD0SHb.js +0 -0
  374. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/sb-BYAiYHFx.js +0 -0
  375. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/scala-Bqvq8jcR.js +0 -0
  376. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/scheme-Dhb-2j9p.js +0 -0
  377. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/scss-CTwUZ5N7.js +0 -0
  378. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/shell-CsDZo4DB.js +0 -0
  379. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/solidity-CME5AdoB.js +0 -0
  380. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/sophia-RYC1BQQz.js +0 -0
  381. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/sparql-KEyrF7De.js +0 -0
  382. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/sql-BdTr02Mf.js +0 -0
  383. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/st-C7iG7M4S.js +0 -0
  384. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/swift-D7IUmUK8.js +0 -0
  385. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/systemverilog-DgMryOEJ.js +0 -0
  386. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/tcl-PloMZuKG.js +0 -0
  387. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/twig-BfRIq3la.js +0 -0
  388. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/typespec-CzxlYoT_.js +0 -0
  389. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/vb-BwAE3J76.js +0 -0
  390. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/wgsl-B_1kOXbF.js +0 -0
  391. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/assets/yaml.worker-BTE-_K6g.js +0 -0
  392. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/boneio.svg +0 -0
  393. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
  394. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/areas.schema.json +0 -0
  395. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/dallas.schema.json +0 -0
  396. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/ds2482.schema.json +0 -0
  397. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/logger.schema.json +0 -0
  398. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/output_group.schema.json +0 -0
  399. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/frontend-dist/schem/virtual_energy_sensor.schema.json +0 -0
  400. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/middleware/__init__.py +0 -0
  401. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/middleware/auth.py +0 -0
  402. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/__init__.py +0 -0
  403. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/auth.py +0 -0
  404. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/caddy.py +0 -0
  405. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/config.py +0 -0
  406. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/covers.py +0 -0
  407. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/modbus.py +0 -0
  408. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/outputs.py +0 -0
  409. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/remote_devices.py +0 -0
  410. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/sensors.py +0 -0
  411. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/routes/update.py +0 -0
  412. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/areas.schema.json +0 -0
  413. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/dallas.schema.json +0 -0
  414. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/ds2482.schema.json +0 -0
  415. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/logger.schema.json +0 -0
  416. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/output_group.schema.json +0 -0
  417. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/schema/virtual_energy_sensor.schema.json +0 -0
  418. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/services/__init__.py +0 -0
  419. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/services/logs.py +0 -0
  420. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/web_server.py +0 -0
  421. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio/webui/websocket_manager.py +0 -0
  422. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio.egg-info/dependency_links.txt +0 -0
  423. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio.egg-info/entry_points.txt +0 -0
  424. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio.egg-info/requires.txt +0 -0
  425. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/boneio.egg-info/top_level.txt +0 -0
  426. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/setup.cfg +0 -0
  427. {boneio-1.1.1.dev1 → boneio-1.2.0.dev1}/setup.py +0 -0
  428. {boneio-1.1.1.dev1 → boneio-1.2.0.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.1.1.dev1
3
+ Version: 1.2.0.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
@@ -0,0 +1,5 @@
1
+ """Cloud registration module for boneIO Black PWA support."""
2
+
3
+ from boneio.core.cloud.registration import CloudRegistration
4
+
5
+ __all__ = ["CloudRegistration"]
@@ -0,0 +1,154 @@
1
+ #!/bin/sh
2
+ # Script for Caddy with cloud wildcard SSL certificate (PWA mode)
3
+ # This version adds a *.black.boneio.app HTTPS block using the wildcard cert
4
+ # downloaded by boneIO Cloud Registration.
5
+ #
6
+ # Used when cloud_registration is enabled in boneio config.
7
+ # Falls back to self-signed cert for hostname-based access.
8
+
9
+ HOSTNAME_FILE="/data/last_hostname"
10
+ CURRENT_HOSTNAME="${HOST_HOSTNAME:-$(cat /etc/host_hostname 2>/dev/null || hostname)}"
11
+
12
+ echo "Current hostname: $CURRENT_HOSTNAME"
13
+ echo "Cloud mode: wildcard SSL cert for *.black.boneio.app"
14
+
15
+ # Check if hostname changed (for self-signed cert regeneration)
16
+ if [ -f "$HOSTNAME_FILE" ]; then
17
+ LAST_HOSTNAME=$(cat "$HOSTNAME_FILE")
18
+ if [ "$LAST_HOSTNAME" != "$CURRENT_HOSTNAME" ]; then
19
+ echo "Hostname changed from $LAST_HOSTNAME to $CURRENT_HOSTNAME"
20
+ echo "Removing old self-signed certificates..."
21
+ rm -rf /data/caddy/certificates/local/*
22
+ rm -rf /data/caddy/pki/*
23
+ rm -rf /config/caddy/*
24
+ fi
25
+ else
26
+ echo "First run on this device, clearing any existing certificates..."
27
+ rm -rf /data/caddy/certificates/local/*
28
+ rm -rf /data/caddy/pki/*
29
+ rm -rf /config/caddy/*
30
+ fi
31
+
32
+ echo "$CURRENT_HOSTNAME" > "$HOSTNAME_FILE"
33
+
34
+ # Check if wildcard cert exists
35
+ if [ -f "/data/ssl/fullchain.pem" ] && [ -f "/data/ssl/privkey.pem" ]; then
36
+ echo "Wildcard SSL certificate found, enabling PWA HTTPS block"
37
+ CLOUD_BLOCK="
38
+ # HTTPS with wildcard cert for PWA (*.black.boneio.app)
39
+ *.black.boneio.app {
40
+ tls /data/ssl/fullchain.pem /data/ssl/privkey.pem
41
+
42
+ handle_errors {
43
+ @502-504 expression {err.status_code} >= 502 && {err.status_code} <= 504
44
+ handle @502-504 {
45
+ root * /srv
46
+ rewrite * /502.html
47
+ file_server
48
+ }
49
+ }
50
+
51
+ handle /nodered-status {
52
+ header Content-Type application/json
53
+ header X-NodeRed-Available \"true\"
54
+ header Access-Control-Expose-Headers \"X-NodeRed-Available\"
55
+ respond \`{\"available\": true}\` 200
56
+ }
57
+
58
+ handle /nodered/* {
59
+ reverse_proxy node-red:1880 {
60
+ header_up X-Forwarded-Proto {scheme}
61
+ header_down X-NodeRed-Available \"true\"
62
+ }
63
+ }
64
+
65
+ handle {
66
+ reverse_proxy host.docker.internal:8090 {
67
+ header_up X-Forwarded-Proto {scheme}
68
+ }
69
+ }
70
+ }
71
+ "
72
+ else
73
+ echo "WARNING: Wildcard SSL certificate not found at /data/ssl/"
74
+ echo "PWA HTTPS block will not be enabled until certificate is downloaded"
75
+ CLOUD_BLOCK=""
76
+ fi
77
+
78
+ # Generate Caddyfile
79
+ cat > /tmp/Caddyfile << EOF
80
+ {
81
+ # Global options
82
+ }
83
+
84
+ # HTTP - serve directly
85
+ :80 {
86
+ handle_errors {
87
+ @502-504 expression {err.status_code} >= 502 && {err.status_code} <= 504
88
+ handle @502-504 {
89
+ root * /srv
90
+ rewrite * /502.html
91
+ file_server
92
+ }
93
+ }
94
+
95
+ handle /nodered-status {
96
+ header Content-Type application/json
97
+ header X-NodeRed-Available "true"
98
+ header Access-Control-Expose-Headers "X-NodeRed-Available"
99
+ respond \`{"available": true}\` 200
100
+ }
101
+
102
+ handle /nodered/* {
103
+ reverse_proxy node-red:1880 {
104
+ header_up X-Forwarded-Proto {scheme}
105
+ header_down X-NodeRed-Available "true"
106
+ }
107
+ }
108
+
109
+ handle {
110
+ reverse_proxy host.docker.internal:8090 {
111
+ header_up X-Forwarded-Proto {scheme}
112
+ }
113
+ }
114
+ }
115
+
116
+ # HTTPS with hostname-based self-signed certificate (always available)
117
+ https://, ${CURRENT_HOSTNAME} {
118
+ tls internal
119
+
120
+ handle_errors {
121
+ @502-504 expression {err.status_code} >= 502 && {err.status_code} <= 504
122
+ handle @502-504 {
123
+ root * /srv
124
+ rewrite * /502.html
125
+ file_server
126
+ }
127
+ }
128
+
129
+ handle /nodered-status {
130
+ header Content-Type application/json
131
+ header X-NodeRed-Available "true"
132
+ header Access-Control-Expose-Headers "X-NodeRed-Available"
133
+ respond \`{"available": true}\` 200
134
+ }
135
+
136
+ handle /nodered/* {
137
+ reverse_proxy node-red:1880 {
138
+ header_up X-Forwarded-Proto {scheme}
139
+ header_down X-NodeRed-Available "true"
140
+ }
141
+ }
142
+
143
+ handle {
144
+ reverse_proxy host.docker.internal:8090 {
145
+ header_up X-Forwarded-Proto {scheme}
146
+ }
147
+ }
148
+ }
149
+
150
+ ${CLOUD_BLOCK}
151
+ EOF
152
+
153
+ # Start Caddy with generated config
154
+ exec caddy run --config /tmp/Caddyfile --adapter caddyfile
@@ -0,0 +1,454 @@
1
+ """
2
+ Cloud registration module for boneIO Black.
3
+
4
+ Handles DNS registration with boneIO Cloud API and SSL certificate management
5
+ for PWA support with custom subdomains.
6
+ """
7
+
8
+ import asyncio
9
+ import base64
10
+ import hashlib
11
+ import hmac
12
+ import logging
13
+ import os
14
+ import shutil
15
+ import subprocess
16
+ from pathlib import Path
17
+ from typing import Optional
18
+
19
+ import aiohttp
20
+
21
+ from boneio.core.cloud.secrets import MASTER_SECRET as DEFAULT_MASTER_SECRET
22
+
23
+ _LOGGER = logging.getLogger(__name__)
24
+
25
+ # Cloud API configuration
26
+ CLOUD_API_URL = "https://api.boneio.app"
27
+
28
+ # SSL certificate paths (relative to home dir, writable by boneio app)
29
+ _DOCKER_DIR = Path.home() / "docker" / "nodered"
30
+ CERT_DIR = _DOCKER_DIR / "caddy" / "ssl"
31
+ CERT_FILE = CERT_DIR / "fullchain.pem"
32
+ KEY_FILE = CERT_DIR / "privkey.pem"
33
+
34
+ # Caddy configuration paths
35
+ CADDY_CONFIG_DIR = _DOCKER_DIR / "caddy"
36
+ CADDY_DEFAULT_CONFIG = CADDY_CONFIG_DIR / "Caddyfile"
37
+ CADDY_CLOUD_CONFIG = CADDY_CONFIG_DIR / "Caddyfile.cloud"
38
+ CADDY_ACTIVE_CONFIG = CADDY_CONFIG_DIR / "Caddyfile"
39
+
40
+ # Registration interval (1 hour)
41
+ REGISTRATION_INTERVAL = 3600
42
+
43
+
44
+ class CloudRegistration:
45
+ """
46
+ Manages cloud registration for boneIO Black devices.
47
+
48
+ Registers device DNS with cloud API and downloads SSL certificates
49
+ for PWA support.
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ serial_number: str,
55
+ local_ip: str,
56
+ master_secret: str = DEFAULT_MASTER_SECRET,
57
+ enabled: bool = True,
58
+ ) -> None:
59
+ """
60
+ Initialize cloud registration.
61
+
62
+ Args:
63
+ serial_number: Device serial number (e.g., 'blkf8dc18')
64
+ local_ip: Local IP address of the device
65
+ master_secret: Shared secret for HMAC device authentication.
66
+ Defaults to the build-time injected secret from secrets.py.
67
+ enabled: Whether cloud registration is enabled
68
+ """
69
+ self._serial = serial_number
70
+ self._local_ip = local_ip
71
+ self._master_secret = master_secret
72
+ self._enabled = enabled
73
+ self._domain: Optional[str] = None
74
+ self._task: Optional[asyncio.Task] = None
75
+ self._session: Optional[aiohttp.ClientSession] = None
76
+ self._last_error: Optional[str] = None
77
+
78
+ @property
79
+ def domain(self) -> Optional[str]:
80
+ """Get the registered domain name."""
81
+ return self._domain
82
+
83
+ @property
84
+ def enabled(self) -> bool:
85
+ """Check if cloud registration is enabled."""
86
+ return self._enabled
87
+
88
+ @property
89
+ def last_error(self) -> Optional[str]:
90
+ """Get the last error message, if any."""
91
+ return self._last_error
92
+
93
+ async def start(self) -> None:
94
+ """Start the cloud registration service."""
95
+ if not self._enabled:
96
+ _LOGGER.info("Cloud registration is disabled")
97
+ return
98
+
99
+ _LOGGER.info("Starting cloud registration for %s", self._serial)
100
+ _LOGGER.debug(
101
+ "Master secret starts with: '%s...' (len=%d)",
102
+ self._master_secret[:4] if self._master_secret else "NONE",
103
+ len(self._master_secret) if self._master_secret else 0,
104
+ )
105
+
106
+ # Create SSL directory if it doesn't exist
107
+ CERT_DIR.mkdir(parents=True, exist_ok=True)
108
+
109
+ # Start registration loop
110
+ self._task = asyncio.create_task(self._registration_loop())
111
+
112
+ async def stop(self) -> None:
113
+ """Stop the cloud registration service."""
114
+ if self._task:
115
+ self._task.cancel()
116
+ try:
117
+ await self._task
118
+ except asyncio.CancelledError:
119
+ pass
120
+ self._task = None
121
+
122
+ if self._session:
123
+ await self._session.close()
124
+ self._session = None
125
+
126
+ def _compute_token(self) -> str:
127
+ """Compute HMAC-SHA256 auth token from master secret and serial.
128
+
129
+ Returns:
130
+ Hex-encoded HMAC token string
131
+ """
132
+ return hmac.new(
133
+ self._master_secret.encode(),
134
+ self._serial.encode(),
135
+ hashlib.sha256,
136
+ ).hexdigest()
137
+
138
+ def _auth_headers(self) -> dict[str, str]:
139
+ """Get authorization headers for cloud API requests.
140
+
141
+ Returns:
142
+ Dict with Authorization header
143
+ """
144
+ return {"Authorization": f"Bearer {self._compute_token()}"}
145
+
146
+ async def _get_session(self) -> aiohttp.ClientSession:
147
+ """Get or create aiohttp session."""
148
+ if self._session is None or self._session.closed:
149
+ self._session = aiohttp.ClientSession(
150
+ timeout=aiohttp.ClientTimeout(total=30)
151
+ )
152
+ return self._session
153
+
154
+ async def _registration_loop(self) -> None:
155
+ """Main registration loop - registers DNS and fetches cert periodically."""
156
+ while True:
157
+ try:
158
+ # Register DNS
159
+ success = await self._register_dns()
160
+ if success:
161
+ _LOGGER.info("DNS registration successful: %s", self._domain)
162
+
163
+ # Fetch certificate if not present or needs refresh
164
+ if not self._cert_exists() or await self._cert_needs_refresh():
165
+ cert_fetched = await self._fetch_certificate()
166
+
167
+ # Switch to cloud Caddy config if cert was fetched and not already active
168
+ if cert_fetched and not self.is_cloud_config_active():
169
+ _LOGGER.info("Switching Caddy to cloud configuration...")
170
+ await self._switch_to_cloud_config()
171
+ else:
172
+ _LOGGER.warning("DNS registration failed, will retry")
173
+
174
+ except asyncio.CancelledError:
175
+ raise
176
+ except Exception as e:
177
+ _LOGGER.error("Cloud registration error: %s", e)
178
+
179
+ # Wait before next registration
180
+ await asyncio.sleep(REGISTRATION_INTERVAL)
181
+
182
+ async def _register_dns(self) -> bool:
183
+ """
184
+ Register device DNS with cloud API.
185
+
186
+ Returns:
187
+ True if registration was successful
188
+ """
189
+ try:
190
+ session = await self._get_session()
191
+
192
+ payload = {
193
+ "serial": self._serial,
194
+ "ip": self._local_ip,
195
+ }
196
+
197
+ async with session.post(
198
+ f"{CLOUD_API_URL}/register",
199
+ json=payload,
200
+ headers=self._auth_headers(),
201
+ ) as response:
202
+ if response.status == 200:
203
+ data = await response.json()
204
+ self._domain = data.get("domain")
205
+ return True
206
+ elif response.status == 429:
207
+ # Rate limited - wait longer
208
+ data = await response.json()
209
+ retry_after = data.get("retryAfter", 3600)
210
+ _LOGGER.warning(
211
+ "Rate limited, retry after %d seconds", retry_after
212
+ )
213
+ return False
214
+ else:
215
+ body = await response.text()
216
+ _LOGGER.error(
217
+ "DNS registration failed (HTTP %d): %s",
218
+ response.status,
219
+ body,
220
+ )
221
+ return False
222
+
223
+ except aiohttp.ClientError as e:
224
+ _LOGGER.error("Failed to connect to cloud API: %s", e)
225
+ return False
226
+
227
+ async def _fetch_certificate(self) -> bool:
228
+ """
229
+ Fetch SSL certificate from cloud API.
230
+
231
+ Returns:
232
+ True if certificate was fetched successfully
233
+ """
234
+ try:
235
+ session = await self._get_session()
236
+
237
+ async with session.get(
238
+ f"{CLOUD_API_URL}/cert",
239
+ params={"serial": self._serial},
240
+ headers=self._auth_headers(),
241
+ ) as response:
242
+ if response.status == 200:
243
+ data = await response.json()
244
+
245
+ # Decode and save certificate
246
+ cert_data = base64.b64decode(data["cert"])
247
+ key_data = base64.b64decode(data["key"])
248
+
249
+ CERT_FILE.write_bytes(cert_data)
250
+ KEY_FILE.write_bytes(key_data)
251
+
252
+ # Set proper permissions for key file
253
+ os.chmod(KEY_FILE, 0o600)
254
+
255
+ _LOGGER.info(
256
+ "SSL certificate saved, expires: %s",
257
+ data.get("expiresAt", "unknown")
258
+ )
259
+ return True
260
+ elif response.status == 503:
261
+ _LOGGER.warning("Certificate not yet available from cloud")
262
+ return False
263
+ else:
264
+ _LOGGER.error("Failed to fetch certificate: %d", response.status)
265
+ return False
266
+
267
+ except aiohttp.ClientError as e:
268
+ _LOGGER.error("Failed to fetch certificate: %s", e)
269
+ return False
270
+ except Exception as e:
271
+ _LOGGER.error("Error saving certificate: %s", e)
272
+ return False
273
+
274
+ def _cert_exists(self) -> bool:
275
+ """Check if certificate files exist."""
276
+ return CERT_FILE.exists() and KEY_FILE.exists()
277
+
278
+ async def _cert_needs_refresh(self) -> bool:
279
+ """
280
+ Check if certificate needs to be refreshed.
281
+
282
+ Returns:
283
+ True if cert is older than 30 days or doesn't exist
284
+ """
285
+ if not self._cert_exists():
286
+ return True
287
+
288
+ try:
289
+ # Check cert file age
290
+ import time
291
+ cert_age = time.time() - CERT_FILE.stat().st_mtime
292
+ # Refresh if older than 30 days
293
+ return cert_age > (30 * 24 * 3600)
294
+ except Exception:
295
+ return True
296
+
297
+ def update_ip(self, new_ip: str) -> None:
298
+ """
299
+ Update local IP address.
300
+
301
+ Args:
302
+ new_ip: New local IP address
303
+ """
304
+ if new_ip != self._local_ip:
305
+ _LOGGER.info("Local IP changed: %s -> %s", self._local_ip, new_ip)
306
+ self._local_ip = new_ip
307
+
308
+ def _ensure_cloud_script(self) -> None:
309
+ """
310
+ Copy init-certs-cloud.sh from package data to the Caddy config directory.
311
+
312
+ This ensures the script is always up-to-date after a pip upgrade,
313
+ even if the user never re-clones the full repo.
314
+ """
315
+ dest = CADDY_CONFIG_DIR / "init-certs-cloud.sh"
316
+ try:
317
+ from importlib.resources import files
318
+
319
+ src = files("boneio.core.cloud.data").joinpath("init-certs-cloud.sh")
320
+ src_bytes = src.read_bytes()
321
+
322
+ # Only write if content differs or file missing
323
+ if not dest.exists() or dest.read_bytes() != src_bytes:
324
+ dest.write_bytes(src_bytes)
325
+ dest.chmod(0o755)
326
+ _LOGGER.info("Deployed init-certs-cloud.sh to %s", dest)
327
+ except Exception as e:
328
+ _LOGGER.warning("Could not deploy init-certs-cloud.sh: %s", e)
329
+
330
+ async def _switch_to_cloud_config(self) -> bool:
331
+ """
332
+ Switch Caddy to cloud mode by updating docker-compose.yaml.
333
+
334
+ Changes:
335
+ - Deploys init-certs-cloud.sh from package to caddy dir
336
+ - Swaps init-certs.sh for init-certs-cloud.sh in docker-compose
337
+ - Adds SSL volume mount for wildcard certificate
338
+ - Recreates Caddy container with new config
339
+
340
+ Returns:
341
+ True if switch was successful
342
+ """
343
+ # Ensure cloud script is deployed from package
344
+ self._ensure_cloud_script()
345
+
346
+ compose_file = _DOCKER_DIR / "docker-compose.yaml"
347
+ try:
348
+ if not compose_file.exists():
349
+ _LOGGER.error("docker-compose.yaml not found: %s", compose_file)
350
+ return False
351
+
352
+ content = compose_file.read_text()
353
+
354
+ # Already switched?
355
+ if "init-certs-cloud.sh" in content:
356
+ _LOGGER.debug("Cloud config already active in docker-compose.yaml")
357
+ return await self._recreate_caddy()
358
+
359
+ # Swap init-certs.sh -> init-certs-cloud.sh
360
+ if "init-certs.sh" not in content:
361
+ _LOGGER.error("init-certs.sh not found in docker-compose.yaml")
362
+ return False
363
+
364
+ # Backup original
365
+ backup = compose_file.with_suffix(".yaml.bak")
366
+ if not backup.exists():
367
+ shutil.copy2(compose_file, backup)
368
+ _LOGGER.info("Backed up docker-compose.yaml to %s", backup)
369
+
370
+ new_content = content.replace("init-certs.sh", "init-certs-cloud.sh")
371
+
372
+ # Add SSL volume if not present
373
+ if "./caddy/ssl:/data/ssl:ro" not in new_content:
374
+ new_content = new_content.replace(
375
+ " - /etc/hostname:/etc/host_hostname:ro",
376
+ " - /etc/hostname:/etc/host_hostname:ro\n"
377
+ " - ./caddy/ssl:/data/ssl:ro",
378
+ )
379
+
380
+ compose_file.write_text(new_content)
381
+ _LOGGER.info("Updated docker-compose.yaml for cloud mode")
382
+
383
+ return await self._recreate_caddy()
384
+
385
+ except PermissionError as e:
386
+ compose_path = str(compose_file)
387
+ self._last_error = (
388
+ f"Permission denied writing {compose_path}. "
389
+ f"Run via SSH: sudo chown $USER {compose_path}"
390
+ )
391
+ _LOGGER.error(
392
+ "Permission denied for %s. Fix with: sudo chown $USER %s",
393
+ compose_path,
394
+ compose_path,
395
+ )
396
+ return False
397
+ except Exception as e:
398
+ self._last_error = str(e)
399
+ _LOGGER.error("Failed to switch to cloud config: %s", e)
400
+ return False
401
+
402
+ async def _recreate_caddy(self) -> bool:
403
+ """
404
+ Recreate Caddy container to apply new docker-compose config.
405
+
406
+ Uses 'docker compose up -d caddy' to pick up volume and entrypoint changes.
407
+
408
+ Returns:
409
+ True if recreate was successful
410
+ """
411
+ compose_dir = str(_DOCKER_DIR)
412
+ try:
413
+ result = await asyncio.get_event_loop().run_in_executor(
414
+ None,
415
+ lambda: subprocess.run(
416
+ ["docker", "compose", "up", "-d", "caddy"],
417
+ cwd=compose_dir,
418
+ capture_output=True,
419
+ timeout=60,
420
+ )
421
+ )
422
+
423
+ if result.returncode == 0:
424
+ _LOGGER.info("Caddy container recreated successfully")
425
+ return True
426
+ else:
427
+ _LOGGER.error(
428
+ "Failed to recreate Caddy: %s",
429
+ result.stderr.decode() if result.stderr else "Unknown error"
430
+ )
431
+ return False
432
+
433
+ except subprocess.TimeoutExpired:
434
+ _LOGGER.error("Caddy recreate timed out")
435
+ return False
436
+ except Exception as e:
437
+ _LOGGER.error("Failed to recreate Caddy: %s", e)
438
+ return False
439
+
440
+ def is_cloud_config_active(self) -> bool:
441
+ """
442
+ Check if cloud init-certs script is active in docker-compose.
443
+
444
+ Returns:
445
+ True if cloud config is active
446
+ """
447
+ try:
448
+ compose_file = _DOCKER_DIR / "docker-compose.yaml"
449
+ if not compose_file.exists():
450
+ return False
451
+ content = compose_file.read_text()
452
+ return "init-certs-cloud.sh" in content
453
+ except Exception:
454
+ return False
@@ -0,0 +1,56 @@
1
+ """
2
+ Cloud API secrets for boneIO Black.
3
+
4
+ The MASTER_SECRET is resolved in this order:
5
+ 1. Environment variable BONEIO_MASTER_SECRET (already set in shell/systemd)
6
+ 2. BONEIO_MASTER_SECRET from .env file in working directory or /home/boneio/
7
+ 3. Build-time injected value (replaced by GitHub Actions during PyPI build)
8
+
9
+ For local development, set BONEIO_MASTER_SECRET in your .env file or shell.
10
+ DO NOT commit real secrets to this file.
11
+ """
12
+
13
+ import os
14
+ from pathlib import Path
15
+
16
+ # This placeholder is replaced by GitHub Actions during build.
17
+ # See .github/workflows/publish-to-pypi.yaml
18
+ _BUILD_SECRET = "cd75f3bab398cf8a245e627a94bda915580eba8b6eddeb4a76b95a286ea2e8b5"
19
+
20
+
21
+ def _load_env_secret() -> str:
22
+ """Load BONEIO_MASTER_SECRET from environment or .env file.
23
+
24
+ Checks environment first, then looks for .env file in common locations.
25
+
26
+ Returns:
27
+ The master secret string (may be placeholder if not configured).
28
+ """
29
+ # 1. Already in environment?
30
+ env_val = os.environ.get("BONEIO_MASTER_SECRET")
31
+ if env_val:
32
+ return env_val
33
+
34
+ # 2. Try .env files
35
+ env_paths = [
36
+ Path.cwd() / ".env",
37
+ Path.home() / ".env",
38
+ ]
39
+ for env_path in env_paths:
40
+ if env_path.is_file():
41
+ try:
42
+ for line in env_path.read_text().splitlines():
43
+ line = line.strip()
44
+ if line.startswith("#") or "=" not in line:
45
+ continue
46
+ key, _, value = line.partition("=")
47
+ if key.strip() == "BONEIO_MASTER_SECRET":
48
+ return value.strip().strip("'\"")
49
+ except OSError:
50
+ continue
51
+
52
+ # 3. Fallback to build-time placeholder
53
+ return _BUILD_SECRET
54
+
55
+
56
+ MASTER_SECRET = _load_env_secret()