boneIO 1.0.0.dev6__tar.gz → 1.0.0.dev8__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 (388) hide show
  1. {boneio-1.0.0.dev6/boneio.egg-info → boneio-1.0.0.dev8}/PKG-INFO +1 -1
  2. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/cover/previous.py +12 -2
  3. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/cover/time_based.py +10 -2
  4. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/cover/venetian.py +12 -6
  5. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/group/output_group.py +8 -2
  6. boneio-1.0.0.dev8/boneio/components/output/basic.py +229 -0
  7. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/sensor/__init__.py +2 -0
  8. boneio-1.0.0.dev8/boneio/components/sensor/virtual_energy.py +292 -0
  9. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/const.py +1 -0
  10. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/config_helper.py +12 -0
  11. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/yaml_util.py +15 -0
  12. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/covers.py +47 -28
  13. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/inputs.py +86 -6
  14. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/manager.py +19 -1
  15. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/modbus.py +1 -1
  16. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/outputs.py +25 -63
  17. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/sensors.py +485 -2
  18. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/state/manager.py +63 -9
  19. boneio-1.0.0.dev8/boneio/hardware/gpio/expanders/mcp23017.py +291 -0
  20. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/expanders/pca9685.py +69 -46
  21. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/expanders/pcf8575.py +44 -11
  22. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/i2c/bus.py +38 -33
  23. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/integration/__init__.py +2 -0
  24. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/integration/homeassistant.py +60 -8
  25. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/cli.py +2 -2
  26. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/coordinator.py +10 -15
  27. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/energy_meters/socomec_e03.json +1 -0
  28. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/energy_meters/socomec_e23.json +1 -0
  29. boneio-1.0.0.dev8/boneio/modbus/devices/inverters/sofar.json +267 -0
  30. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/sensors/dts1964_3f.json +60 -54
  31. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/sensors/pt100.json +3 -3
  32. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/base.py +11 -19
  33. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/derived/numeric.py +2 -2
  34. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/derived/select.py +0 -1
  35. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/derived/switch.py +0 -1
  36. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/derived/text.py +0 -1
  37. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/sensor/numeric.py +14 -15
  38. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/sensor/text.py +2 -6
  39. boneio-1.0.0.dev8/boneio/modbus/utils.py +6 -0
  40. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/runner.py +5 -2
  41. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/schema.yaml +84 -16
  42. boneio-1.0.0.dev8/boneio/version.py +2 -0
  43. boneio-1.0.0.dev8/boneio/webui/app.py +621 -0
  44. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/cssMode-28wsodaN.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/cssMode-BKR9s_Lh.js +1 -1
  45. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/freemarker2-DBoUEFeV.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/freemarker2-Culjpl1V.js +1 -1
  46. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/handlebars-BMPQqMuK.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/handlebars-DvFXDtCi.js +1 -1
  47. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/html-C-J4vGDC.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/html-CRZebHSg.js +1 -1
  48. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/htmlMode-DLqnuXCj.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/htmlMode-w52oBlKZ.js +1 -1
  49. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/index-CiuOrRV8.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/index-CrPqznir.js +222 -222
  50. boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/index-DYGCuZw-.css +1 -0
  51. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/javascript-DjAp6HFu.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/javascript-1_d307wM.js +1 -1
  52. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/jsonMode-DuoTNxT6.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/jsonMode-SK3Ov5KI.js +1 -1
  53. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/liquid-1wqDC8lY.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/liquid-BY2M9Ltg.js +1 -1
  54. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/mdx-ou-zvMhp.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/mdx-CYoqZppc.js +1 -1
  55. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/python--YMY2ScQ.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/python-BRjt52qX.js +1 -1
  56. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/razor-BRc3lsvv.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/razor-CM_wFXDY.js +1 -1
  57. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/tsMode-D54D1lK6.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/tsMode-DyZ1xUFQ.js +1 -1
  58. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/typescript-DLyjvYVj.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/typescript-CeE-9TVF.js +1 -1
  59. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/xml-Cd_YftAm.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/xml-DYrg3tVz.js +1 -1
  60. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/yaml-BhCMO_W9.js → boneio-1.0.0.dev8/boneio/webui/frontend-dist/assets/yaml-CKAkvRms.js +1 -1
  61. boneio-1.0.0.dev8/boneio/webui/frontend-dist/index.html +21 -0
  62. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/adc.schema.json +8 -8
  63. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/areas.schema.json +4 -4
  64. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/binary_sensor.schema.json +26 -26
  65. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/boneio.schema.json +2 -2
  66. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/config.schema.json +292 -220
  67. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/cover.schema.json +4 -4
  68. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/ds2482.schema.json +4 -4
  69. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/event.schema.json +36 -36
  70. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/ina219.schema.json +14 -14
  71. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/lm75.schema.json +10 -10
  72. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/logger.schema.json +2 -2
  73. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/mcp23017.schema.json +6 -6
  74. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/mcp9808.schema.json +10 -10
  75. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/modbus.schema.json +8 -8
  76. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/modbus_devices.schema.json +20 -20
  77. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/mqtt.schema.json +6 -6
  78. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/oled.schema.json +8 -8
  79. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/output.schema.json +10 -20
  80. {boneio-1.0.0.dev6/boneio/webui/schema → boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem}/output_group.schema.json +6 -6
  81. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/pca9685.schema.json +6 -6
  82. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/pcf8575.schema.json +6 -6
  83. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/sensor.schema.json +8 -8
  84. boneio-1.0.0.dev8/boneio/webui/frontend-dist/schem/virtual_energy_sensor.schema.json +79 -0
  85. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/web.schema.json +15 -6
  86. boneio-1.0.0.dev8/boneio/webui/middleware/__init__.py +5 -0
  87. boneio-1.0.0.dev8/boneio/webui/middleware/auth.py +155 -0
  88. boneio-1.0.0.dev8/boneio/webui/routes/__init__.py +21 -0
  89. boneio-1.0.0.dev8/boneio/webui/routes/auth.py +61 -0
  90. boneio-1.0.0.dev8/boneio/webui/routes/config.py +479 -0
  91. boneio-1.0.0.dev8/boneio/webui/routes/covers.py +122 -0
  92. boneio-1.0.0.dev8/boneio/webui/routes/modbus.py +466 -0
  93. boneio-1.0.0.dev8/boneio/webui/routes/outputs.py +109 -0
  94. boneio-1.0.0.dev8/boneio/webui/routes/sensors.py +118 -0
  95. boneio-1.0.0.dev8/boneio/webui/routes/system.py +161 -0
  96. boneio-1.0.0.dev8/boneio/webui/routes/update.py +461 -0
  97. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/adc.schema.json +8 -8
  98. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/areas.schema.json +4 -4
  99. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/binary_sensor.schema.json +26 -26
  100. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/boneio.schema.json +2 -2
  101. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/config.schema.json +292 -220
  102. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/cover.schema.json +4 -4
  103. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/ds2482.schema.json +4 -4
  104. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/event.schema.json +36 -36
  105. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/ina219.schema.json +14 -14
  106. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/lm75.schema.json +10 -10
  107. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/logger.schema.json +2 -2
  108. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/mcp23017.schema.json +6 -6
  109. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/mcp9808.schema.json +10 -10
  110. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/modbus.schema.json +8 -8
  111. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/modbus_devices.schema.json +20 -20
  112. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/mqtt.schema.json +6 -6
  113. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/oled.schema.json +8 -8
  114. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/output.schema.json +10 -20
  115. {boneio-1.0.0.dev6/boneio/webui/frontend-dist/schem → boneio-1.0.0.dev8/boneio/webui/schema}/output_group.schema.json +6 -6
  116. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/pca9685.schema.json +6 -6
  117. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/pcf8575.schema.json +6 -6
  118. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/sensor.schema.json +8 -8
  119. boneio-1.0.0.dev8/boneio/webui/schema/virtual_energy_sensor.schema.json +79 -0
  120. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/web.schema.json +15 -6
  121. boneio-1.0.0.dev8/boneio/webui/services/__init__.py +15 -0
  122. boneio-1.0.0.dev8/boneio/webui/services/logs.py +242 -0
  123. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8/boneio.egg-info}/PKG-INFO +1 -1
  124. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio.egg-info/SOURCES.txt +33 -17
  125. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/pyproject.toml +4 -0
  126. boneio-1.0.0.dev6/boneio/components/output/basic.py +0 -399
  127. boneio-1.0.0.dev6/boneio/hardware/gpio/expanders/mcp23017.py +0 -200
  128. boneio-1.0.0.dev6/boneio/modbus/devices/inverters/sofar.json +0 -150
  129. boneio-1.0.0.dev6/boneio/modbus/utils.py +0 -73
  130. boneio-1.0.0.dev6/boneio/version.py +0 -2
  131. boneio-1.0.0.dev6/boneio/webui/app.py +0 -2602
  132. boneio-1.0.0.dev6/boneio/webui/frontend-dist/assets/index-CaOLuaDD.css +0 -1
  133. boneio-1.0.0.dev6/boneio/webui/frontend-dist/index.html +0 -14
  134. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/LICENSE +0 -0
  135. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/MANIFEST.in +0 -0
  136. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/README.md +0 -0
  137. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/__init__.py +0 -0
  138. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.4/input.yaml +0 -0
  139. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.4/output_24_16.yaml +0 -0
  140. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.4/output_32_10.yaml +0 -0
  141. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.4/output_32_5.yaml +0 -0
  142. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.4/output_cover.yaml +0 -0
  143. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.4/output_cover_mix.yaml +0 -0
  144. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.7/input.yaml +0 -0
  145. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.7/output_24_16.yaml +0 -0
  146. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.7/output_32_10.yaml +0 -0
  147. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.7/output_cover.yaml +0 -0
  148. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
  149. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.8/input.yaml +0 -0
  150. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.8/output_24_16.yaml +0 -0
  151. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.8/output_32_10.yaml +0 -0
  152. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.8/output_cover.yaml +0 -0
  153. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
  154. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/bonecli.py +0 -0
  155. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/__init__.py +0 -0
  156. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/cover/__init__.py +0 -0
  157. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/cover/cover.py +0 -0
  158. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/group/__init__.py +0 -0
  159. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/input/__init__.py +0 -0
  160. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/input/binary_sensor.py +0 -0
  161. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/input/detectors.py +0 -0
  162. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/input/event.py +0 -0
  163. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/output/__init__.py +0 -0
  164. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/output/mcp.py +0 -0
  165. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/output/pca.py +0 -0
  166. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/output/pcf.py +0 -0
  167. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/components/sensor/system.py +0 -0
  168. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/__init__.py +0 -0
  169. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/__init__.py +0 -0
  170. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/loader.py +0 -0
  171. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/package-lock.json +0 -0
  172. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/package.json +0 -0
  173. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/config/schema_converter.py +0 -0
  174. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/events/__init__.py +0 -0
  175. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/events/bus.py +0 -0
  176. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/__init__.py +0 -0
  177. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/manager/display.py +0 -0
  178. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/messaging/__init__.py +0 -0
  179. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/messaging/basic.py +0 -0
  180. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/messaging/basic_mqtt.py +0 -0
  181. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/messaging/local.py +0 -0
  182. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/messaging/mqtt.py +0 -0
  183. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/messaging/queue.py +0 -0
  184. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/sensor/__init__.py +0 -0
  185. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/sensor/base.py +0 -0
  186. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/sensor/system.py +0 -0
  187. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/state/__init__.py +0 -0
  188. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/system/__init__.py +0 -0
  189. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/system/host_data.py +0 -0
  190. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/system/monitor.py +0 -0
  191. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/__init__.py +0 -0
  192. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/async_updater.py +0 -0
  193. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/filter.py +0 -0
  194. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/font_util.py +0 -0
  195. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/logger.py +0 -0
  196. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/timeperiod.py +0 -0
  197. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/core/utils/util.py +0 -0
  198. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/24x16/adc.yaml +0 -0
  199. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
  200. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/24x16/config.yaml +0 -0
  201. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/24x16/event.yaml +0 -0
  202. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/24x16/mqtt.yaml +0 -0
  203. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/24x16/output24x16A.yaml +0 -0
  204. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/32x10/adc.yaml +0 -0
  205. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
  206. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/32x10/config.yaml +0 -0
  207. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/32x10/event.yaml +0 -0
  208. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/32x10/mqtt.yaml +0 -0
  209. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/32x10/output32x10A.yaml +0 -0
  210. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/__init__.py +0 -0
  211. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/adc.yaml +0 -0
  212. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/binary_sensor.yaml +0 -0
  213. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/config.yaml +0 -0
  214. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/cover.yaml +0 -0
  215. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/event.yaml +0 -0
  216. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/mqtt.yaml +0 -0
  217. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover/outputCover.yaml +0 -0
  218. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/adc.yaml +0 -0
  219. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
  220. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/config.yaml +0 -0
  221. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/cover.yaml +0 -0
  222. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/event.yaml +0 -0
  223. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
  224. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
  225. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/adc.yaml +0 -0
  226. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
  227. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
  228. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
  229. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
  230. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/event_all.yaml +0 -0
  231. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
  232. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
  233. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
  234. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
  235. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
  236. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
  237. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/exceptions.py +0 -0
  238. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/__init__.py +0 -0
  239. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/analog/__init__.py +0 -0
  240. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/analog/adc.py +0 -0
  241. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/display/__init__.py +0 -0
  242. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/display/fonts/danube__.ttf +0 -0
  243. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/display/oled.py +0 -0
  244. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/__init__.py +0 -0
  245. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/expanders/__init__.py +0 -0
  246. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/input/__init__.py +0 -0
  247. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/input/base.py +0 -0
  248. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/gpio/input/manager.py +0 -0
  249. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/i2c/__init__.py +0 -0
  250. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/i2c/ina219.py +0 -0
  251. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/i2c/ina219_driver.py +0 -0
  252. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/i2c/mcp9808.py +0 -0
  253. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/i2c/pct2075.py +0 -0
  254. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/onewire/__init__.py +0 -0
  255. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/onewire/bus.py +0 -0
  256. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/onewire/dallas.py +0 -0
  257. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/onewire/ds2482.py +0 -0
  258. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/sensor/__init__.py +0 -0
  259. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/sensor/temperature/__init__.py +0 -0
  260. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/sensor/temperature/base.py +0 -0
  261. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/sensor/temperature/mcp9808.py +0 -0
  262. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/hardware/sensor/temperature/pct2075.py +0 -0
  263. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/integration/interlock.py +0 -0
  264. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/__init__.py +0 -0
  265. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/client.py +0 -0
  266. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/__init__.py +0 -0
  267. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/energy_meters/orno-or-we-517.json +0 -0
  268. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/energy_meters/sdm120.json +0 -0
  269. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/energy_meters/sdm630.json +0 -0
  270. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/hvac/fujitsu-ac.json +0 -0
  271. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/hvac/ventclear.json +0 -0
  272. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/inverters/thessla.json +0 -0
  273. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/other/r4dcb08.json +0 -0
  274. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/other/wanas415.json +0 -0
  275. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/sensors/cwt.json +0 -0
  276. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/sensors/liquid-sensor.json +0 -0
  277. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/sensors/sht20.json +0 -0
  278. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/devices/sensors/sht30.json +0 -0
  279. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/__init__.py +0 -0
  280. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/derived/__init__.py +0 -0
  281. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/sensor/__init__.py +0 -0
  282. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/sensor/binary.py +0 -0
  283. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/writeable/__init__.py +0 -0
  284. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/writeable/binary.py +0 -0
  285. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/modbus/entities/writeable/numeric.py +0 -0
  286. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/__init__.py +0 -0
  287. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/actions.py +0 -0
  288. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/events.py +0 -0
  289. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/files.py +0 -0
  290. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/logs.py +0 -0
  291. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/mqtt.py +0 -0
  292. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/models/state.py +0 -0
  293. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/actions.yaml +0 -0
  294. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/actions_sensor.yaml +0 -0
  295. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/actions_switch.yaml +0 -0
  296. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/filters.yaml +0 -0
  297. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/filters_adc.yaml +0 -0
  298. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/id.yaml +0 -0
  299. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/temp_unit.yaml +0 -0
  300. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/schema/update_interval.yaml +0 -0
  301. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/abap-CRCWOmpq.js +0 -0
  302. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/apex-DnsZk_dE.js +0 -0
  303. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/azcli-1IWB1ccx.js +0 -0
  304. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/bat-DPkNLes8.js +0 -0
  305. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/bicep-Corcdgou.js +0 -0
  306. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/cameligo-CGrWLZr3.js +0 -0
  307. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/clojure-D9WOWImG.js +0 -0
  308. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
  309. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/coffee-B7EJu28W.js +0 -0
  310. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/cpp-SEyurbux.js +0 -0
  311. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/csharp-BoL64M5l.js +0 -0
  312. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/csp-C46ZqvIl.js +0 -0
  313. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/css-DQU6DXDx.js +0 -0
  314. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/cypher-D84EuPTj.js +0 -0
  315. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/dart-D8lhlL1r.js +0 -0
  316. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/dockerfile-DLk6rpji.js +0 -0
  317. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/ecl-BO6FnfXk.js +0 -0
  318. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/editor.worker-DsAeyiJ5.js +0 -0
  319. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/elixir-BRjLKONM.js +0 -0
  320. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/flow9-Cac8vKd7.js +0 -0
  321. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/fsharp-fd1GTHhf.js +0 -0
  322. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/go-O9LJTZXk.js +0 -0
  323. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/graphql-LQdxqEYJ.js +0 -0
  324. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/hcl-DxDQ3s82.js +0 -0
  325. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/ini-BvajGCUy.js +0 -0
  326. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/java-SYsfObOQ.js +0 -0
  327. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/json.worker-DaRII17c.js +0 -0
  328. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/julia-DQXNmw_w.js +0 -0
  329. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/kotlin-qQ0MG-9I.js +0 -0
  330. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/less-GGFNNJHn.js +0 -0
  331. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/lexon-Canl7DCW.js +0 -0
  332. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/lua-D28Ae8-K.js +0 -0
  333. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/m3-DPitgjJI.js +0 -0
  334. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/markdown-B811l8j2.js +0 -0
  335. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/mips-CdjsipkG.js +0 -0
  336. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/msdax-CYqgjx_P.js +0 -0
  337. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/mysql-BHd6q0vd.js +0 -0
  338. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/objective-c-B1aVtJYH.js +0 -0
  339. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/pascal-BhNW15KB.js +0 -0
  340. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/pascaligo-5jv8CcQD.js +0 -0
  341. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/perl-DlYyT36c.js +0 -0
  342. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/pgsql-Dy0bjov7.js +0 -0
  343. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/php-120yhfDK.js +0 -0
  344. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/pla-CjnFlu4u.js +0 -0
  345. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/postiats-CQpG440k.js +0 -0
  346. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/powerquery-DdJtto1Z.js +0 -0
  347. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/powershell-Bu_VLpJB.js +0 -0
  348. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/protobuf-IBS6jZEB.js +0 -0
  349. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/pug-kFxLfcjb.js +0 -0
  350. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/qsharp-q7JyzKFN.js +0 -0
  351. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/r-BIFz-_sK.js +0 -0
  352. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/redis-CHOsPHWR.js +0 -0
  353. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/redshift-CBifECDb.js +0 -0
  354. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/restructuredtext-CghPJEOS.js +0 -0
  355. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/ruby-CYWGW-b1.js +0 -0
  356. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/rust-DMDD0SHb.js +0 -0
  357. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/sb-BYAiYHFx.js +0 -0
  358. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/scala-Bqvq8jcR.js +0 -0
  359. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/scheme-Dhb-2j9p.js +0 -0
  360. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/scss-CTwUZ5N7.js +0 -0
  361. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/shell-CsDZo4DB.js +0 -0
  362. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/solidity-CME5AdoB.js +0 -0
  363. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/sophia-RYC1BQQz.js +0 -0
  364. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/sparql-KEyrF7De.js +0 -0
  365. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/sql-BdTr02Mf.js +0 -0
  366. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/st-C7iG7M4S.js +0 -0
  367. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/swift-D7IUmUK8.js +0 -0
  368. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/systemverilog-DgMryOEJ.js +0 -0
  369. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/tcl-PloMZuKG.js +0 -0
  370. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/twig-BfRIq3la.js +0 -0
  371. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/typespec-CzxlYoT_.js +0 -0
  372. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/vb-BwAE3J76.js +0 -0
  373. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/wgsl-B_1kOXbF.js +0 -0
  374. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/assets/yaml.worker-BTE-_K6g.js +0 -0
  375. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/boneio.svg +0 -0
  376. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
  377. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/frontend-dist/schem/dallas.schema.json +0 -0
  378. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/schema/dallas.schema.json +0 -0
  379. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/web_server.py +0 -0
  380. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio/webui/websocket_manager.py +0 -0
  381. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio.egg-info/dependency_links.txt +0 -0
  382. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio.egg-info/entry_points.txt +0 -0
  383. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio.egg-info/requires.txt +0 -0
  384. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/boneio.egg-info/top_level.txt +0 -0
  385. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/setup.cfg +0 -0
  386. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/setup.py +0 -0
  387. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/tests/test_i2c_smbus2.py +0 -0
  388. {boneio-1.0.0.dev6 → boneio-1.0.0.dev8}/tests/test_py313_compatibility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boneio
3
- Version: 1.0.0.dev6
3
+ Version: 1.0.0.dev8
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
@@ -340,5 +340,15 @@ class PreviousCover(BasicMqtt):
340
340
  return "previous"
341
341
 
342
342
  def update_config_times(self, config: dict) -> None:
343
- self._open_duration = config.get("open_duration", self._open_duration)
344
- self._close_duration = config.get("close_duration", self._close_duration)
343
+ """Update cover timing configuration.
344
+
345
+ Args:
346
+ config: Dictionary with timing values as TimePeriod objects.
347
+ Keys: open_time, close_time
348
+ """
349
+ if "open_time" in config:
350
+ self._open_time = config["open_time"]
351
+ self._open = RelayHelper(relay=self._open.relay, time=config["open_time"])
352
+ if "close_time" in config:
353
+ self._close_time = config["close_time"]
354
+ self._close = RelayHelper(relay=self._close.relay, time=config["close_time"])
@@ -111,6 +111,14 @@ class TimeBasedCover(BaseCover):
111
111
  return "time"
112
112
 
113
113
  def update_config_times(self, config: dict) -> None:
114
- self._open_duration = config.get("open_duration", self._open_duration)
115
- self._close_duration = config.get("close_duration", self._close_duration)
114
+ """Update cover timing configuration.
115
+
116
+ Args:
117
+ config: Dictionary with timing values as TimePeriod objects.
118
+ Keys: open_time, close_time
119
+ """
120
+ if "open_time" in config:
121
+ self._open_time = config["open_time"].total_milliseconds
122
+ if "close_time" in config:
123
+ self._close_time = config["close_time"].total_milliseconds
116
124
 
@@ -260,12 +260,18 @@ class VenetianCover(BaseCover, BaseVenetianCoverABC):
260
260
  await self.set_tilt(tilt_position=0)
261
261
 
262
262
  def update_config_times(self, config: dict) -> None:
263
- self._open_duration = config.get("open_duration", self._open_duration)
264
- self._close_duration = config.get("close_duration", self._close_duration)
265
- self._actuator_activation_duration = config.get(
266
- "actuator_activation_duration", self._actuator_activation_duration
267
- )
268
- self._tilt_duration = config.get("tilt_duration", self._tilt_duration)
263
+ """Update cover timing configuration.
264
+
265
+ Args:
266
+ config: Dictionary with timing values as TimePeriod objects.
267
+ Keys: open_time, close_time, tilt_duration
268
+ """
269
+ if "open_time" in config:
270
+ self._open_time = config["open_time"].total_milliseconds
271
+ if "close_time" in config:
272
+ self._close_time = config["close_time"].total_milliseconds
273
+ if "tilt_duration" in config and config["tilt_duration"]:
274
+ self._tilt_duration = config["tilt_duration"].total_milliseconds
269
275
 
270
276
  async def run_cover(
271
277
  self,
@@ -86,20 +86,26 @@ class OutputGroup(BasicOutput):
86
86
  async def async_turn_on(self, timestamp=None) -> None:
87
87
  """Turn on all members in the group.
88
88
 
89
+ Executes turn_on sequentially to prevent I2C bus contention
90
+ when multiple outputs are on the same GPIO expander.
91
+
89
92
  Args:
90
93
  timestamp: Optional timestamp for the operation
91
94
  """
92
95
  for x in self._group_members:
93
- self._loop.create_task(x.async_turn_on(timestamp=timestamp))
96
+ await x.async_turn_on(timestamp=timestamp)
94
97
 
95
98
  async def async_turn_off(self, timestamp=None) -> None:
96
99
  """Turn off all members in the group.
97
100
 
101
+ Executes turn_off sequentially to prevent I2C bus contention
102
+ when multiple outputs are on the same GPIO expander.
103
+
98
104
  Args:
99
105
  timestamp: Optional timestamp for the operation
100
106
  """
101
107
  for x in self._group_members:
102
- self._loop.create_task(x.async_turn_off(timestamp=timestamp))
108
+ await x.async_turn_off(timestamp=timestamp)
103
109
 
104
110
  @property
105
111
  def is_active(self) -> bool:
@@ -0,0 +1,229 @@
1
+ """Basic Output module (formerly BasicRelay)."""
2
+ from __future__ import annotations
3
+
4
+ import asyncio
5
+ import logging
6
+ import time
7
+
8
+ from boneio.const import COVER, LIGHT, NONE, OFF, ON, RELAY, STATE, SWITCH
9
+ from boneio.core.messaging import BasicMqtt
10
+ from boneio.models.events import OutputEvent
11
+ from boneio.core.events import EventBus, async_track_point_in_time, utcnow
12
+ from boneio.integration.interlock import SoftwareInterlockManager
13
+ from boneio.core.utils import callback
14
+ from boneio.models import OutputState
15
+
16
+ _LOGGER = logging.getLogger(__name__)
17
+
18
+
19
+ class BasicOutput(BasicMqtt):
20
+ """Basic output class (relay, switch, light, PWM).
21
+
22
+ Formerly known as BasicRelay. This class represents any controllable
23
+ output device in the BoneIO system.
24
+ """
25
+
26
+ # Subclasses (e.g. MCPOutput) will override these
27
+ _pin_id: int = -1
28
+ _expander_id: str | None = None
29
+
30
+ def __init__(
31
+ self,
32
+ id: str,
33
+ event_bus: EventBus,
34
+ topic_prefix: str,
35
+ name: str | None = None,
36
+ output_type=SWITCH,
37
+ restored_state: bool = False,
38
+ topic_type: str = RELAY,
39
+ interlock_manager: SoftwareInterlockManager | None = None,
40
+ interlock_groups: list[str] = [],
41
+ **kwargs,
42
+ ) -> None:
43
+ """Initialize Basic output."""
44
+ self._momentary_turn_on = kwargs.pop("momentary_turn_on", None)
45
+ self._momentary_turn_off = kwargs.pop("momentary_turn_off", None)
46
+ super().__init__(id=id, name=name or id, topic_type=topic_type, topic_prefix=topic_prefix, **kwargs)
47
+ self._output_type: str = output_type
48
+ self._event_bus: EventBus = event_bus
49
+ self._interlock_manager: SoftwareInterlockManager | None = interlock_manager
50
+ self._interlock_groups: list[str] = interlock_groups
51
+ if output_type == COVER:
52
+ self._momentary_turn_on = None
53
+ self._momentary_turn_off = None
54
+ self._state = ON if restored_state else OFF
55
+ self._momentary_action = None
56
+ self._last_timestamp = 0.0
57
+ self._loop = asyncio.get_running_loop()
58
+
59
+ # HA area/room assignment (set by OutputManager)
60
+ self.area: str | None = None
61
+
62
+ def set_interlock(self, interlock_manager: SoftwareInterlockManager, interlock_groups: list[str]):
63
+ """Set interlock manager and groups."""
64
+ self._interlock_manager = interlock_manager
65
+ self._interlock_groups = interlock_groups
66
+
67
+ @property
68
+ def is_mcp_type(self) -> bool:
69
+ """Check if relay is mcp type."""
70
+ return False
71
+
72
+ @property
73
+ def output_type(self) -> str:
74
+ """HA type."""
75
+ return self._output_type
76
+
77
+ @property
78
+ def is_light(self) -> bool:
79
+ """Check if HA type is light"""
80
+ return self._output_type == LIGHT
81
+
82
+ @property
83
+ def id(self) -> str:
84
+ """Id of the relay.
85
+ Has to be trimmed out of spaces because of MQTT handling in HA."""
86
+ return self._id or str(self._pin_id) or ""
87
+
88
+ @property
89
+ def name(self) -> str:
90
+ """Not trimmed id."""
91
+ return self._name or str(self._pin_id) or ""
92
+
93
+ @property
94
+ def pin_id(self) -> str | None:
95
+ """Pin ID as string for OutputState model."""
96
+ return str(self._pin_id) if self._pin_id is not None else None
97
+
98
+ @property
99
+ def state(self) -> str:
100
+ """Is relay active."""
101
+ return self._state
102
+
103
+
104
+ @property
105
+ def last_timestamp(self) -> float:
106
+ return self._last_timestamp
107
+
108
+ def payload(self) -> dict[str, str | float | int | None]:
109
+ """Return payload for MQTT message.
110
+
111
+ Returns:
112
+ Dictionary with state information for MQTT publishing.
113
+ """
114
+ return {STATE: self.state}
115
+
116
+ async def async_send_state(self, optimized_value: str | None = None) -> None:
117
+ """Send state to Mqtt on action asynchronously."""
118
+ if optimized_value:
119
+ state = optimized_value
120
+ else:
121
+ state = ON if self.is_active else OFF
122
+ self._state = state
123
+ if self.output_type not in (COVER, NONE):
124
+ self._message_bus.send_message(
125
+ topic=self._send_topic,
126
+ payload={STATE: state},
127
+ retain=True,
128
+ )
129
+ if optimized_value:
130
+ return
131
+ self._last_timestamp = time.time()
132
+ output_state = OutputState(
133
+ id=self.id,
134
+ name=self.name,
135
+ state=state,
136
+ type=self.output_type,
137
+ pin=self.pin_id,
138
+ timestamp=self.last_timestamp,
139
+ expander_id=self.expander_id,
140
+ area=self.area,
141
+ interlock_groups=self._interlock_groups,
142
+ )
143
+
144
+ output_event = OutputEvent(
145
+ entity_id=self.id,
146
+ state=output_state,
147
+ )
148
+ self._event_bus.trigger_event(output_event)
149
+
150
+
151
+ def check_interlock(self) -> bool:
152
+ if self._interlock_manager is not None and self._interlock_groups:
153
+ return self._interlock_manager.can_turn_on(self, self._interlock_groups)
154
+ return True
155
+
156
+ async def async_turn_on(self, timestamp=None) -> None:
157
+ """Turn on the relay asynchronously."""
158
+ can_turn_on = self.check_interlock()
159
+ if can_turn_on:
160
+ await self._loop.run_in_executor(None, self.turn_on, timestamp)
161
+ else:
162
+ _LOGGER.warning(f"Interlock active: cannot turn on {self.id}.")
163
+ #Workaround for HA is sendind state ON/OFF without physically changing the relay.
164
+ asyncio.create_task(self.async_send_state(optimized_value=ON))
165
+ await asyncio.sleep(0.01)
166
+ asyncio.create_task(self.async_send_state())
167
+
168
+
169
+ async def async_turn_off(self, timestamp=None) -> None:
170
+ """Turn off the relay asynchronously."""
171
+ await self._loop.run_in_executor(None, self.turn_off, timestamp)
172
+ await self.async_send_state()
173
+
174
+
175
+ async def async_toggle(self, timestamp=None) -> None:
176
+ """Toggle relay."""
177
+ now = time.time()
178
+ _LOGGER.debug("Toggle relay %s, state: %s, at %s.", self.name, self.state, now)
179
+ if self.state == ON:
180
+ await self.async_turn_off(timestamp=timestamp)
181
+ else:
182
+ await self.async_turn_on(timestamp=timestamp)
183
+
184
+ def turn_on(self, timestamp=None) -> None:
185
+ """Call turn on action."""
186
+ raise NotImplementedError
187
+
188
+ def turn_off(self, timestamp=None) -> None:
189
+ """Call turn off action."""
190
+ raise NotImplementedError
191
+
192
+ def set_brightness(self, value: int) -> None:
193
+ """Set brightness (only supported on PWM outputs like PCA9685)."""
194
+ _LOGGER.warning("set_brightness not supported for %s output type", self.output_type)
195
+
196
+ def _execute_momentary_turn(self, momentary_type: str) -> None:
197
+ """Execute momentary action."""
198
+ if self._momentary_action:
199
+ _LOGGER.debug("Cancelling momentary action for %s", self.name)
200
+ self._momentary_action()
201
+ (action, delayed_action) = (
202
+ (self.async_turn_off, self._momentary_turn_on)
203
+ if momentary_type == ON
204
+ else (self.async_turn_on, self._momentary_turn_off)
205
+ )
206
+ if delayed_action:
207
+ _LOGGER.debug("Applying momentary action for %s in %s", self.name, delayed_action.as_timedelta)
208
+ self._momentary_action = async_track_point_in_time(
209
+ loop=self._loop,
210
+ job=self._momentary_callback,
211
+ point_in_time=utcnow() + delayed_action.as_timedelta,
212
+ action=action,
213
+ )
214
+
215
+ @callback
216
+ async def _momentary_callback(self, timestamp, action):
217
+ _LOGGER.info("Momentary callback at %s for output %s", timestamp, self.name)
218
+ await action(timestamp=timestamp)
219
+ self._momentary_action = None
220
+
221
+ @property
222
+ def is_active(self) -> bool:
223
+ """Is active check."""
224
+ raise NotImplementedError
225
+
226
+ @property
227
+ def expander_id(self) -> str | None:
228
+ """Retrieve parent Expander ID (set by subclasses like MCPOutput)."""
229
+ return self._expander_id
@@ -5,7 +5,9 @@ hardware drivers with business logic.
5
5
  """
6
6
 
7
7
  from boneio.components.sensor.system import SerialNumberSensor
8
+ from boneio.components.sensor.virtual_energy import VirtualEnergySensor
8
9
 
9
10
  __all__ = [
10
11
  "SerialNumberSensor",
12
+ "VirtualEnergySensor",
11
13
  ]
@@ -0,0 +1,292 @@
1
+ """Virtual Energy Sensor module.
2
+
3
+ Creates virtual power/energy or water flow sensors linked to outputs.
4
+ When the linked output is ON, the sensor calculates consumption based on
5
+ configured power_usage or flow_rate.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import json
11
+ import logging
12
+ import time
13
+ from typing import TYPE_CHECKING
14
+
15
+ from boneio.const import ON
16
+ from boneio.models import SensorState
17
+ from boneio.models.events import SensorEvent
18
+
19
+ if TYPE_CHECKING:
20
+ from boneio.core.messaging.basic import MessageBus
21
+ from boneio.core.events.bus import EventBus
22
+ from boneio.components.output.basic import BasicOutput
23
+
24
+ _LOGGER = logging.getLogger(__name__)
25
+
26
+
27
+ class VirtualEnergySensor:
28
+ """Virtual energy/water sensor linked to an output.
29
+
30
+ Tracks energy consumption (Wh) or water consumption (L) based on
31
+ configured power_usage (W) or flow_rate (L/h) when the linked output is ON.
32
+
33
+ Args:
34
+ id: Unique sensor identifier
35
+ name: Display name for Home Assistant
36
+ output: The output to track
37
+ message_bus: MessageBus for MQTT communication
38
+ loop: Event loop
39
+ topic_prefix: MQTT topic prefix
40
+ sensor_type: 'power' or 'water'
41
+ power_usage: Power consumption in Watts (for sensor_type='power')
42
+ flow_rate: Flow rate in L/h (for sensor_type='water')
43
+ area: Optional area ID for HA sub-device
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ id: str,
49
+ name: str,
50
+ output: BasicOutput,
51
+ message_bus: MessageBus,
52
+ event_bus: "EventBus",
53
+ loop: asyncio.AbstractEventLoop,
54
+ topic_prefix: str,
55
+ sensor_type: str,
56
+ power_usage: float | None = None,
57
+ flow_rate: float | None = None,
58
+ area: str | None = None,
59
+ ):
60
+ self._id = id
61
+ self._name = name
62
+ self._output = output
63
+ self._loop = loop or asyncio.get_running_loop()
64
+ self._message_bus = message_bus
65
+ self._event_bus = event_bus
66
+ self._topic_prefix = topic_prefix
67
+ self._sensor_type = sensor_type
68
+ self._power_usage = power_usage
69
+ self._flow_rate = flow_rate
70
+ self._area = area
71
+
72
+ self._virtual_sensors_task = None
73
+
74
+ # Counters
75
+ self._energy_consumed_Wh = 0.0
76
+ self._water_consumed_L = 0.0
77
+ self._last_on_timestamp = time.time() if self._output.state == ON else None
78
+
79
+ # MQTT topic for this sensor
80
+ self._sensor_topic = f"{topic_prefix}/energy/{id}"
81
+
82
+ # Subscribe to restore state from MQTT
83
+ self._subscribe_restore_state()
84
+
85
+ _LOGGER.info(
86
+ "Initialized VirtualEnergySensor: id=%s, name=%s, output=%s, type=%s",
87
+ id, name, output.id, sensor_type
88
+ )
89
+
90
+ @property
91
+ def id(self) -> str:
92
+ """Get sensor ID."""
93
+ return self._id
94
+
95
+ @property
96
+ def name(self) -> str:
97
+ """Get sensor name."""
98
+ return self._name
99
+
100
+ @property
101
+ def output_id(self) -> str:
102
+ """Get linked output ID."""
103
+ return self._output.id
104
+
105
+ @property
106
+ def sensor_type(self) -> str:
107
+ """Get sensor type ('power' or 'water')."""
108
+ return self._sensor_type
109
+
110
+ @property
111
+ def area(self) -> str | None:
112
+ """Get area ID."""
113
+ return self._area
114
+
115
+ @property
116
+ def power_usage(self) -> float | None:
117
+ """Get power usage in Watts."""
118
+ return self._power_usage
119
+
120
+ @property
121
+ def flow_rate(self) -> float | None:
122
+ """Get flow rate in L/h."""
123
+ return self._flow_rate
124
+
125
+ @property
126
+ def last_on_timestamp(self) -> float | None:
127
+ """Get timestamp when output was last turned ON."""
128
+ return self._last_on_timestamp
129
+
130
+ def start_tracking(self):
131
+ """Start tracking consumption (called when output turns ON)."""
132
+ self._last_on_timestamp = time.time()
133
+ if self._virtual_sensors_task is not None and not self._virtual_sensors_task.done():
134
+ return # Already running
135
+ self._virtual_sensors_task = self._loop.create_task(self._tracking_loop())
136
+ _LOGGER.debug("Started tracking for virtual sensor %s", self._id)
137
+
138
+ def stop_tracking(self):
139
+ """Stop tracking consumption (called when output turns OFF)."""
140
+ # Update one last time before stopping
141
+ self._update_consumption()
142
+ self._last_on_timestamp = None
143
+
144
+ if self._virtual_sensors_task is not None:
145
+ self._virtual_sensors_task.cancel()
146
+ self._virtual_sensors_task = None
147
+
148
+ # Send final state
149
+ self._send_state()
150
+ _LOGGER.debug("Stopped tracking for virtual sensor %s", self._id)
151
+
152
+ async def _tracking_loop(self):
153
+ """Periodically update and send state every 30 seconds while output is ON."""
154
+ try:
155
+ while self._output.state == ON:
156
+ self._update_consumption()
157
+ self._send_state()
158
+ await asyncio.sleep(30)
159
+ except asyncio.CancelledError:
160
+ pass
161
+
162
+ def _update_consumption(self):
163
+ """Update consumption counters based on elapsed time."""
164
+ now = time.time()
165
+ if self._output.state == ON and self._last_on_timestamp is not None:
166
+ elapsed = now - self._last_on_timestamp
167
+
168
+ if self._sensor_type == "power" and self._power_usage is not None:
169
+ self._energy_consumed_Wh += (self._power_usage * elapsed) / 3600.0
170
+ _LOGGER.debug(
171
+ "Energy updated for %s: %.4f Wh",
172
+ self._id, self._energy_consumed_Wh
173
+ )
174
+ elif self._sensor_type == "water" and self._flow_rate is not None:
175
+ self._water_consumed_L += (self._flow_rate * elapsed) / 3600.0
176
+ _LOGGER.debug(
177
+ "Water updated for %s: %.4f L",
178
+ self._id, self._water_consumed_L
179
+ )
180
+
181
+ self._last_on_timestamp = now
182
+
183
+ def _subscribe_restore_state(self):
184
+ """Subscribe to retained MQTT topic to restore state on startup."""
185
+ async def on_message(_topic, payload):
186
+ try:
187
+ data = json.loads(payload)
188
+ if isinstance(data, dict):
189
+ if "energy" in data:
190
+ self._energy_consumed_Wh = float(data["energy"])
191
+ _LOGGER.info(
192
+ "Restored energy state for %s: %.4f Wh",
193
+ self._id, self._energy_consumed_Wh
194
+ )
195
+ if "water" in data:
196
+ self._water_consumed_L = float(data["water"])
197
+ _LOGGER.info(
198
+ "Restored water state for %s: %.4f L",
199
+ self._id, self._water_consumed_L
200
+ )
201
+ except Exception as e:
202
+ _LOGGER.warning("Failed to restore state for %s: %s", self._id, e)
203
+ finally:
204
+ await self._message_bus.unsubscribe_and_stop_listen(self._sensor_topic)
205
+
206
+ if self._message_bus is not None:
207
+ asyncio.create_task(
208
+ self._message_bus.subscribe_and_listen(self._sensor_topic, on_message)
209
+ )
210
+
211
+ def get_current_power(self) -> float:
212
+ """Get current power usage in W (0 if output is OFF)."""
213
+ if self._sensor_type != "power":
214
+ return 0.0
215
+ return (self._power_usage or 0.0) if self._output.state == ON else 0.0
216
+
217
+ def get_total_energy(self) -> float:
218
+ """Get total energy consumed in Wh."""
219
+ return round(self._energy_consumed_Wh, 3)
220
+
221
+ def get_current_flow_rate(self) -> float:
222
+ """Get current flow rate in L/h (0 if output is OFF)."""
223
+ if self._sensor_type != "water":
224
+ return 0.0
225
+ return (self._flow_rate or 0.0) if self._output.state == ON else 0.0
226
+
227
+ def get_total_water(self) -> float:
228
+ """Get total water consumed in L."""
229
+ return round(self._water_consumed_L, 3)
230
+
231
+ def _send_state(self):
232
+ """Send current state to MQTT and EventBus (for WebSocket/frontend)."""
233
+ payload = {}
234
+ timestamp = int(time.time())
235
+
236
+ if self._sensor_type == "power":
237
+ payload["power"] = self.get_current_power()
238
+ payload["energy"] = self.get_total_energy()
239
+
240
+ # Send SensorEvents to frontend via EventBus
241
+ self._event_bus.trigger_event(SensorEvent(
242
+ entity_id=f"{self._id}_power",
243
+ state=SensorState(
244
+ id=f"{self._id}_power",
245
+ name=f"{self._name} Power",
246
+ state=self.get_current_power(),
247
+ unit="W",
248
+ timestamp=timestamp,
249
+ )
250
+ ))
251
+ self._event_bus.trigger_event(SensorEvent(
252
+ entity_id=f"{self._id}_energy",
253
+ state=SensorState(
254
+ id=f"{self._id}_energy",
255
+ name=f"{self._name} Energy",
256
+ state=self.get_total_energy(),
257
+ unit="Wh",
258
+ timestamp=timestamp,
259
+ )
260
+ ))
261
+ elif self._sensor_type == "water":
262
+ payload["volume_flow_rate"] = self.get_current_flow_rate()
263
+ payload["water"] = self.get_total_water()
264
+
265
+ # Send SensorEvents to frontend via EventBus
266
+ self._event_bus.trigger_event(SensorEvent(
267
+ entity_id=f"{self._id}_flow",
268
+ state=SensorState(
269
+ id=f"{self._id}_flow",
270
+ name=f"{self._name} Flow Rate",
271
+ state=self.get_current_flow_rate(),
272
+ unit="L/h",
273
+ timestamp=timestamp,
274
+ )
275
+ ))
276
+ self._event_bus.trigger_event(SensorEvent(
277
+ entity_id=f"{self._id}_water",
278
+ state=SensorState(
279
+ id=f"{self._id}_water",
280
+ name=f"{self._name} Water",
281
+ state=self.get_total_water(),
282
+ unit="L",
283
+ timestamp=timestamp,
284
+ )
285
+ ))
286
+
287
+ self._message_bus.send_message(
288
+ topic=self._sensor_topic,
289
+ payload=payload,
290
+ retain=True,
291
+ )
292
+ _LOGGER.debug("Sent state for %s: %s", self._id, payload)
@@ -166,6 +166,7 @@ cover_actions = {
166
166
  }
167
167
 
168
168
  INA219 = "ina219"
169
+ VIRTUAL_ENERGY_SENSOR = "virtual_energy_sensor"
169
170
  PINS = {
170
171
  # Based on boneio/boards/0.8/input.yaml
171
172
  "P8_37": {"chip": 1, "line": 14},
@@ -38,6 +38,7 @@ class ConfigHelper:
38
38
  network_info: dict = {},
39
39
  is_web_active: bool = False,
40
40
  web_port: int = 8090,
41
+ nginx_proxy_port: int | None = None,
41
42
  config_file_path: str | None = None,
42
43
  ):
43
44
  self._name = name
@@ -47,6 +48,7 @@ class ConfigHelper:
47
48
  self._ha_discovery_prefix = ha_discovery_prefix
48
49
  self._device_type = device_type
49
50
  self._web_port = web_port
51
+ self._nginx_proxy_port = nginx_proxy_port
50
52
  self._fetch_old_discovery = None
51
53
  self._autodiscovery_messages = {
52
54
  SWITCH: {},
@@ -113,6 +115,16 @@ class ConfigHelper:
113
115
  def web_port(self) -> int:
114
116
  return self._web_port
115
117
 
118
+ @property
119
+ def nginx_proxy_port(self) -> int | None:
120
+ """Get nginx proxy port if configured."""
121
+ return self._nginx_proxy_port
122
+
123
+ @property
124
+ def ha_configuration_port(self) -> int:
125
+ """Get port for HA discovery URL. Uses nginx_proxy_port if set, otherwise web_port."""
126
+ return self._nginx_proxy_port if self._nginx_proxy_port else self._web_port
127
+
116
128
  @property
117
129
  def topic_prefix(self) -> str:
118
130
  return self._topic_prefix