boneIO 0.11.0.dev6__tar.gz → 0.11.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 (274) hide show
  1. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/PKG-INFO +1 -1
  2. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/ha_discovery.py +1 -1
  3. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/loader.py +29 -5
  4. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/yaml_util.py +38 -0
  5. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/manager.py +8 -6
  6. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/mqtt.py +3 -3
  7. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/client.py +68 -65
  8. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sensor.py +3 -3
  9. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/oled.py +8 -8
  10. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/basic.py +164 -95
  11. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/runner.py +6 -8
  12. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/actions.yaml +1 -1
  13. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/schema.yaml +8 -0
  14. boneio-0.11.0.dev8/boneio/version.py +2 -0
  15. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/binary_sensor.schema.json +2 -2
  16. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/config.schema.json +14 -5
  17. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/event.schema.json +3 -3
  18. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/output.schema.json +9 -0
  19. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/pyproject.toml +2 -2
  20. boneio-0.11.0.dev6/boneio/version.py +0 -2
  21. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/LICENSE +0 -0
  22. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/README.md +0 -0
  23. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/__init__.py +0 -0
  24. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/input.yaml +0 -0
  25. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_24_16.yaml +0 -0
  26. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_32_10.yaml +0 -0
  27. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_cover.yaml +0 -0
  28. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.7/output_cover_mix.yaml +0 -0
  29. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/input.yaml +0 -0
  30. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_24_16.yaml +0 -0
  31. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_32_10.yaml +0 -0
  32. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_cover.yaml +0 -0
  33. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/boards/0.8/output_cover_mix.yaml +0 -0
  34. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/bonecli.py +0 -0
  35. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/const.py +0 -0
  36. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/__init__.py +0 -0
  37. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/cover.py +0 -0
  38. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/previous.py +0 -0
  39. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/time_based.py +0 -0
  40. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/cover/venetian.py +0 -0
  41. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/adc.yaml +0 -0
  42. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/binary_sensor.yaml +0 -0
  43. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/config.yaml +0 -0
  44. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/event.yaml +0 -0
  45. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/mqtt.yaml +0 -0
  46. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/24x16/output24x16A.yaml +0 -0
  47. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/adc.yaml +0 -0
  48. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/binary_sensor.yaml +0 -0
  49. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/config.yaml +0 -0
  50. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/event.yaml +0 -0
  51. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/mqtt.yaml +0 -0
  52. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/32x10/output32x10A.yaml +0 -0
  53. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/__init__.py +0 -0
  54. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/adc.yaml +0 -0
  55. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/binary_sensor.yaml +0 -0
  56. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/config.yaml +0 -0
  57. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/cover.yaml +0 -0
  58. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/event.yaml +0 -0
  59. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/mqtt.yaml +0 -0
  60. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover/outputCover.yaml +0 -0
  61. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/adc.yaml +0 -0
  62. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/binary_sensor.yaml +0 -0
  63. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/config.yaml +0 -0
  64. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/cover.yaml +0 -0
  65. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/event.yaml +0 -0
  66. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/mqtt.yaml +0 -0
  67. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/cover_mix/outputCoverMix.yaml +0 -0
  68. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/adc.yaml +0 -0
  69. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/all_binary_sensor.yaml +0 -0
  70. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/binary_sensor.yaml +0 -0
  71. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/binary_sensor_v_0_7.yaml +0 -0
  72. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/config_24_16.yaml +0 -0
  73. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/event_all.yaml +0 -0
  74. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/event_v_0_7.yaml +0 -0
  75. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/led32x4A.yaml +0 -0
  76. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output24x16A.yaml +0 -0
  77. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output24x16A_v0.3.yaml +0 -0
  78. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output32x10A.yaml +0 -0
  79. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/example_config/different_configs/output32x5A.yaml +0 -0
  80. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/fonts/danube__.ttf +0 -0
  81. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/group/__init__.py +0 -0
  82. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/group/output.py +0 -0
  83. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/__init__.py +0 -0
  84. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/async_updater.py +0 -0
  85. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/click_timer.py +0 -0
  86. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/config.py +0 -0
  87. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/events.py +0 -0
  88. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/exceptions.py +0 -0
  89. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/filter.py +0 -0
  90. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/gpio.py +0 -0
  91. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/gpiod.py +0 -0
  92. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/interlock.py +0 -0
  93. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/logger.py +0 -0
  94. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/mqtt.py +0 -0
  95. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/oled.py +0 -0
  96. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/W1ThermSensor.py +0 -0
  97. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/__init__.py +0 -0
  98. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/ds2482.py +0 -0
  99. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/onewire/onewire.py +0 -0
  100. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/pcf8575.py +0 -0
  101. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/queue.py +0 -0
  102. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/schema_converter.py +0 -0
  103. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/sensor/ina_219_smbus.py +0 -0
  104. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/state_manager.py +0 -0
  105. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/stats.py +0 -0
  106. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/timeperiod.py +0 -0
  107. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/helper/util.py +0 -0
  108. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/input/__init__.py +0 -0
  109. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/input/gpio.py +0 -0
  110. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/input/gpio_new.py +0 -0
  111. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/__init__.py +0 -0
  112. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/basic.py +0 -0
  113. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/message_bus/local.py +0 -0
  114. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/__init__.py +0 -0
  115. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/cwt.json +0 -0
  116. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/dts1964_3f.json +0 -0
  117. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/liquid-sensor.json +0 -0
  118. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/modbuscli.py +0 -0
  119. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/orno-or-we-517.json +0 -0
  120. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/pt100.json +0 -0
  121. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/r4dcb08.json +0 -0
  122. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sdm120.json +0 -0
  123. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sdm630.json +0 -0
  124. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sht20.json +0 -0
  125. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sht30.json +0 -0
  126. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/single_sensor.py +0 -0
  127. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/socomec_e03.json +0 -0
  128. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/socomec_e23.json +0 -0
  129. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/sofar.json +0 -0
  130. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/modbus/utils.py +0 -0
  131. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/models/__init__.py +0 -0
  132. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/models/files.py +0 -0
  133. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/models/logs.py +0 -0
  134. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/__init__.py +0 -0
  135. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/gpio.py +0 -0
  136. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/mcp.py +0 -0
  137. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/pca.py +0 -0
  138. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/relay/pcf.py +0 -0
  139. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/actions_sensor.yaml +0 -0
  140. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/actions_switch.yaml +0 -0
  141. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/filters.yaml +0 -0
  142. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/filters_adc.yaml +0 -0
  143. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/id.yaml +0 -0
  144. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/temp_unit.yaml +0 -0
  145. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/schema/update_interval.yaml +0 -0
  146. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/__init__.py +0 -0
  147. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/adc.py +0 -0
  148. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/gpio.py +0 -0
  149. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/gpio_new.py +0 -0
  150. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/ina219.py +0 -0
  151. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/serial_number.py +0 -0
  152. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/__init__.py +0 -0
  153. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/dallas.py +0 -0
  154. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/lm75.py +0 -0
  155. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/sensor/temp/mcp9808.py +0 -0
  156. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/app.py +0 -0
  157. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/abap-BrgZPUOV.js +0 -0
  158. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/apex-DyP6w7ZV.js +0 -0
  159. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/azcli-BaLxmfj-.js +0 -0
  160. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/bat-CFOPXBzS.js +0 -0
  161. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/bicep-BfEKNvv3.js +0 -0
  162. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cameligo-BFG1Mk7z.js +0 -0
  163. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/clojure-DTECt2xU.js +0 -0
  164. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/codicon-DCmgc-ay.ttf +0 -0
  165. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/coffee-CDGzqUPQ.js +0 -0
  166. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cpp-CLLBncYj.js +0 -0
  167. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/csharp-dUCx_-0o.js +0 -0
  168. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/csp-5Rap-vPy.js +0 -0
  169. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/css-D3h14YRZ.js +0 -0
  170. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cssMode-C5afUc0K.js +0 -0
  171. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/cypher-DrQuvNYM.js +0 -0
  172. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/dart-CFKIUWau.js +0 -0
  173. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/dockerfile-Zznr-cwX.js +0 -0
  174. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ecl-Ce3n6wWz.js +0 -0
  175. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/editor.worker-oRlJJsnX.js +0 -0
  176. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/elixir-deUWdS0T.js +0 -0
  177. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/flow9-i9-g7ZhI.js +0 -0
  178. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/freemarker2-emRcpycN.js +0 -0
  179. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/fsharp-CzKuDChf.js +0 -0
  180. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/go-Cphgjts3.js +0 -0
  181. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/graphql-Cg7bfA9N.js +0 -0
  182. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/handlebars-mMSD-c9g.js +0 -0
  183. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/hcl-0cvrggvQ.js +0 -0
  184. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/html-Clq5L_-r.js +0 -0
  185. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/htmlMode-CYqwdxDX.js +0 -0
  186. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/index-BcJKL9Rz.js +0 -0
  187. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/index-DzcnWIxb.css +0 -0
  188. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ini-Drc7WvVn.js +0 -0
  189. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/java-B_fMsGYe.js +0 -0
  190. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/javascript-BR7Nbw1G.js +0 -0
  191. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/json.worker-BnUULff4.js +0 -0
  192. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/jsonMode-aJvzz7xf.js +0 -0
  193. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/julia-Bqgm2twL.js +0 -0
  194. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/kotlin-BSkB5QuD.js +0 -0
  195. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/less-BsTHnhdd.js +0 -0
  196. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/lexon-YWi4-JPR.js +0 -0
  197. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/liquid-BNyvmcbu.js +0 -0
  198. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/lua-nf6ki56Z.js +0 -0
  199. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/m3-Cpb6xl2v.js +0 -0
  200. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/markdown-DSZPf7rp.js +0 -0
  201. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mdx-pWhQfMuK.js +0 -0
  202. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mips-B_c3zf-v.js +0 -0
  203. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/msdax-rUNN04Wq.js +0 -0
  204. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/mysql-DDwshQtU.js +0 -0
  205. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/objective-c-B5zXfXm9.js +0 -0
  206. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pascal-CXOwvkN_.js +0 -0
  207. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pascaligo-Bc-ZgV77.js +0 -0
  208. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/perl-CwNk8-XU.js +0 -0
  209. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pgsql-tGk8EFnU.js +0 -0
  210. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/php-CpIb_Oan.js +0 -0
  211. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pla-B03wrqEc.js +0 -0
  212. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/postiats-BKlk5iyT.js +0 -0
  213. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/powerquery-Bhzvs7bI.js +0 -0
  214. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/powershell-Dd3NCNK9.js +0 -0
  215. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/protobuf-COyEY5Pt.js +0 -0
  216. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/pug-BaJupSGV.js +0 -0
  217. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/python-CVtAQrrC.js +0 -0
  218. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/qsharp-DXyYeYxl.js +0 -0
  219. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/r-CdQndTaG.js +0 -0
  220. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/razor-BBiV-C6e.js +0 -0
  221. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/redis-CVwtpugi.js +0 -0
  222. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/redshift-25W9uPmb.js +0 -0
  223. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/restructuredtext-DfzH4Xui.js +0 -0
  224. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/ruby-Cp1zYvxS.js +0 -0
  225. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/rust-D5C2fndG.js +0 -0
  226. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sb-CDntyWJ8.js +0 -0
  227. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scala-BoFRg7Ot.js +0 -0
  228. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scheme-Bio4gycK.js +0 -0
  229. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/scss-4Ik7cdeQ.js +0 -0
  230. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/shell-CX-rkNHf.js +0 -0
  231. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/solidity-Tw7wswEv.js +0 -0
  232. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sophia-C5WLch3f.js +0 -0
  233. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sparql-DHaeiCBh.js +0 -0
  234. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/sql-CCSDG5nI.js +0 -0
  235. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/st-pnP8ivHi.js +0 -0
  236. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/swift-DwJ7jVG9.js +0 -0
  237. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/systemverilog-B9Xyijhd.js +0 -0
  238. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/tcl-DnHyzjbg.js +0 -0
  239. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/tsMode-COZIvtMx.js +0 -0
  240. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/twig-CPajHgWi.js +0 -0
  241. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/typescript-DKdGc2VX.js +0 -0
  242. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/typespec-D-MeaMDU.js +0 -0
  243. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/vb-DgyLZaXg.js +0 -0
  244. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/wgsl-BIv9DU6q.js +0 -0
  245. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/xml-CTK9ybeu.js +0 -0
  246. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/yaml-ggTgJ1wa.js +0 -0
  247. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/assets/yaml.worker-DSHdx_mx.js +0 -0
  248. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/boneio.svg +0 -0
  249. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/boneio_fav.svg +0 -0
  250. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/frontend-dist/index.html +0 -0
  251. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/adc.schema.json +0 -0
  252. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/boneio.schema.json +0 -0
  253. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/cover.schema.json +0 -0
  254. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/dallas.schema.json +0 -0
  255. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/ds2482.schema.json +0 -0
  256. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/ina219.schema.json +0 -0
  257. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/lm75.schema.json +0 -0
  258. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/logger.schema.json +0 -0
  259. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/mcp23017.schema.json +0 -0
  260. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/mcp9808.schema.json +0 -0
  261. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/modbus.schema.json +0 -0
  262. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/modbus_sensors.schema.json +0 -0
  263. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/mqtt.schema.json +0 -0
  264. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/oled.schema.json +0 -0
  265. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/output_group.schema.json +0 -0
  266. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/pca9685.schema.json +0 -0
  267. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/pcf8575.schema.json +0 -0
  268. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/sensor.schema.json +0 -0
  269. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/schema/web.schema.json +0 -0
  270. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/web_server.py +0 -0
  271. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/boneio/webui/websocket_manager.py +0 -0
  272. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/tests/32_5_config.yaml +0 -0
  273. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/tests/bandit.yaml +0 -0
  274. {boneio-0.11.0.dev6 → boneio-0.11.0.dev8}/tests/relay_32_5.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: boneio
3
- Version: 0.11.0.dev6
3
+ Version: 0.11.0.dev8
4
4
  Summary: Python App for BoneIO
5
5
  License: GNU General Public License v3.0
6
6
  Author-email: Paweł Szafer <pszafer@gmail.com>
@@ -228,7 +228,7 @@ def modbus_sensor_availabilty_message(
228
228
  ):
229
229
  """Create Modbus Sensor availability topic for HA."""
230
230
  return {
231
- "availability": [{"topic": f"{topic}/{id}{STATE}"}],
231
+ "availability": [{"topic": f"{topic}/{id}/{STATE}"}],
232
232
  "device": {
233
233
  "identifiers": [id],
234
234
  "manufacturer": "boneIO",
@@ -235,7 +235,6 @@ def create_modbus_sensors(manager: Manager, message_bus: MessageBus, sensors, **
235
235
  for sensor in sensors:
236
236
  name = sensor.get(ID)
237
237
  id = name.replace(" ", "")
238
- print("name to check", name)
239
238
  additional_data = sensor.get("data", {})
240
239
  try:
241
240
  modbus_sensors[id.lower()] = ModbusSensor(
@@ -364,8 +363,8 @@ def configure_relay(
364
363
  "output_type": output_type,
365
364
  }
366
365
  elif output_kind == GPIO:
367
- if GPIO not in manager.grouped_outputs:
368
- manager.grouped_outputs[GPIO] = {}
366
+ if GPIO not in manager.grouped_outputs_by_expander:
367
+ manager.grouped_outputs_by_expander[GPIO] = {}
369
368
  extra_args = {
370
369
  "pin": config.pop(PIN),
371
370
  }
@@ -392,8 +391,8 @@ def configure_relay(
392
391
  **extra_args,
393
392
  )
394
393
  manager._interlock_manager.register(relay, interlock_groups)
395
- manager.grouped_outputs[expander_id][relay_id] = relay
396
- if relay.virtual_power_usage is not None:
394
+ manager.grouped_outputs_by_expander[expander_id][relay_id] = relay
395
+ if relay.is_virtual_power:
397
396
  manager.send_ha_autodiscovery(
398
397
  id=f"{relay_id}_virtual_power",
399
398
  relay_id=relay_id,
@@ -418,6 +417,31 @@ def configure_relay(
418
417
  state_class="total_increasing",
419
418
  value_template="{{ value_json.energy }}"
420
419
  )
420
+ if relay.is_virtual_volume_flow_rate:
421
+ manager.send_ha_autodiscovery(
422
+ id=f"{relay_id}_virtual_volume_flow_rate",
423
+ relay_id=relay_id,
424
+ name=f"{name} Virtual Volume Flow Rate",
425
+ ha_type="sensor",
426
+ device_type="energy",
427
+ availability_msg_func=ha_virtual_energy_sensor_discovery_message,
428
+ unit_of_measurement="L/h",
429
+ device_class="volume_flow_rate",
430
+ state_class="measurement",
431
+ value_template="{{ value_json.volume_flow_rate }}"
432
+ )
433
+ manager.send_ha_autodiscovery(
434
+ id=f"{relay_id}_virtual_consumption",
435
+ relay_id=relay_id,
436
+ name=f"{name} Virtual consumption",
437
+ ha_type="sensor",
438
+ device_type="energy",
439
+ availability_msg_func=ha_virtual_energy_sensor_discovery_message,
440
+ unit_of_measurement="L",
441
+ device_class="water",
442
+ state_class="total_increasing",
443
+ value_template="{{ value_json.water }}"
444
+ )
421
445
  return relay
422
446
 
423
447
 
@@ -618,6 +618,44 @@ class CustomValidator(Validator):
618
618
  _LOGGER.debug(f"Parsed power value '{value}' as {result} W")
619
619
  return result
620
620
 
621
+ def _normalize_coerce_volume_flow_rate_to_lph(self, value):
622
+ """
623
+ Parse a volume flow rate value and return it in liters per minute (L/min).
624
+ Accepts:
625
+ - Numeric values (int, float)
626
+ - Strings with units: 'L/min', 'L/h', etc.
627
+ Example:
628
+ 9 -> 9.0
629
+ '9L/min' -> 9.0
630
+ '1L/h' -> 1000.0
631
+ Returns float (L/h) or raises ValueError if invalid.
632
+ """
633
+ if value is None:
634
+ return None
635
+ if isinstance(value, (int, float)):
636
+ return float(value)
637
+ if not isinstance(value, str):
638
+ raise ValueError(f"Unsupported type for volume flow rate value: {type(value)}")
639
+ value = value.strip().replace(' ', '').lower()
640
+ pattern = r"^([-+]?[0-9]*\.?[0-9]+)\s*([a-zA-Z/]*)$"
641
+ match = re.match(pattern, value)
642
+ if not match:
643
+ _LOGGER.warning(f"Could not parse volume flow rate value: {value}")
644
+ raise ValueError(f"Could not parse volume flow rate value: {value}")
645
+ num, unit = match.groups()
646
+ num = float(num)
647
+ multiplier = 1.0
648
+ if unit in ('lph', 'l/h', ''):
649
+ multiplier = 1.0
650
+ elif unit in ('lpm', 'l/min'):
651
+ multiplier = 60.0
652
+ else:
653
+ _LOGGER.warning(f"Unknown unit for volume flow rate value: {unit}")
654
+ raise ValueError(f"Unknown unit for volume flow rate value: {unit}")
655
+ result = num * multiplier
656
+ _LOGGER.debug(f"Parsed volume flow rate value '{value}' as {result} L/h")
657
+ return result
658
+
621
659
 
622
660
 
623
661
  def load_config_from_string(config_str: str) -> dict:
@@ -176,13 +176,13 @@ class Manager:
176
176
  dallas=dallas, ds2482=ds2482, sensors=sensors.get(ONEWIRE)
177
177
  )
178
178
 
179
- self.grouped_outputs = create_expander(
179
+ self.grouped_outputs_by_expander = create_expander(
180
180
  expander_dict=self._mcp,
181
181
  expander_config=mcp23017,
182
182
  exp_type=MCP,
183
183
  i2cbusio=self._i2cbusio,
184
184
  )
185
- self.grouped_outputs.update(
185
+ self.grouped_outputs_by_expander.update(
186
186
  create_expander(
187
187
  expander_dict=self._pcf,
188
188
  expander_config=pcf8575,
@@ -190,7 +190,7 @@ class Manager:
190
190
  i2cbusio=self._i2cbusio,
191
191
  )
192
192
  )
193
- self.grouped_outputs.update(
193
+ self.grouped_outputs_by_expander.update(
194
194
  create_expander(
195
195
  expander_dict=self._pca,
196
196
  expander_config=pca9685,
@@ -205,6 +205,7 @@ class Manager:
205
205
  _name = _config.pop(ID)
206
206
  restore_state = _config.pop(RESTORE_STATE, False)
207
207
  _id = strip_accents(_name)
208
+ _LOGGER.debug("Configuring relay: %s", _id)
208
209
  out = configure_relay( # grouped_output updated here.
209
210
  manager=self,
210
211
  message_bus=message_bus,
@@ -236,7 +237,8 @@ class Manager:
236
237
  )
237
238
  self._loop.create_task(self._delayed_send_state(out))
238
239
 
239
- self._configure_covers()
240
+ if self._outputs:
241
+ self._configure_covers()
240
242
 
241
243
  self._outputs_group = output_group
242
244
  self._configure_output_group()
@@ -261,7 +263,7 @@ class Manager:
261
263
  manager=self,
262
264
  event_bus=self._event_bus,
263
265
  enabled_screens=self._screens,
264
- output=self.grouped_outputs,
266
+ output=self.grouped_outputs_by_expander,
265
267
  inputs=self._inputs,
266
268
  temp_sensor=(self._temp_sensors[0] if self._temp_sensors else None),
267
269
  ina219=(self._ina219_sensors[0] if self._ina219_sensors else None),
@@ -271,7 +273,7 @@ class Manager:
271
273
  self._oled = Oled(
272
274
  host_data=self._host_data,
273
275
  screen_order=self._screens,
274
- grouped_outputs=list(self.grouped_outputs),
276
+ grouped_outputs_by_expander=list(self.grouped_outputs_by_expander),
275
277
  sleep_timeout=oled.get("screensaver_timeout", 60),
276
278
  event_bus=self._event_bus,
277
279
  )
@@ -128,6 +128,7 @@ class MQTTClient(MessageBus):
128
128
  params["properties"] = properties
129
129
 
130
130
  # e.g. subscribe([("my/topic", SubscribeOptions(qos=0), ("another/topic", SubscribeOptions(qos=2)])
131
+ _LOGGER.debug("Subscribing to %s", args)
131
132
  await self.asyncio_client.subscribe(
132
133
  topic=args, **params, timeout=timeout
133
134
  )
@@ -250,9 +251,8 @@ class MQTTClient(MessageBus):
250
251
  cancel_task = asyncio.create_task(wait_for_cancel())
251
252
  tasks.add(cancel_task)
252
253
 
253
- await self.subscribe(topics=self._topics)
254
- await self.subscribe(topics=list(self._mqtt_energy_listeners.keys()))
255
- await self.subscribe(topics=self._discovery_topics)
254
+ topics = self._topics + list(self._mqtt_energy_listeners.keys()) + self._discovery_topics
255
+ await self.subscribe(topics=topics)
256
256
 
257
257
  # Wait for everything to complete (or fail due to, e.g., network errors).
258
258
  await asyncio.gather(*tasks)
@@ -138,28 +138,27 @@ class Modbus:
138
138
 
139
139
  async def async_close(self) -> None:
140
140
  """Disconnect client."""
141
- async with self._lock:
142
- if self._client:
143
- try:
144
- # Run close in the executor
145
- await self._loop.run_in_executor(self._executor, self._client.close)
146
- except asyncio.CancelledError:
147
- _LOGGER.warning("modbus communication closed")
148
- pass
149
- except ModbusException as exception_error:
150
- _LOGGER.error(exception_error)
151
- finally:
152
- del self._client
153
- self._client = None
154
- self._executor.shutdown(wait=False)
155
- _LOGGER.warning("modbus communication closed")
141
+ if self._client:
142
+ try:
143
+ # Run close in the executor
144
+ await self._loop.run_in_executor(self._executor, self._client.close)
145
+ except asyncio.CancelledError:
146
+ _LOGGER.warning("modbus communication closed")
147
+ pass
148
+ except ModbusException as exception_error:
149
+ _LOGGER.error(exception_error)
150
+ finally:
151
+ del self._client
152
+ self._client = None
153
+ self._executor.shutdown(wait=False)
154
+ _LOGGER.warning("modbus communication closed")
156
155
 
157
156
  def _pymodbus_connect(self) -> bool:
158
157
  """Connect client."""
159
158
  try:
160
159
  return self._client.connect() # type: ignore[union-attr]
161
160
  except ModbusException as exception_error:
162
- _LOGGER.error(exception_error)
161
+ _LOGGER.error(f"No connection to Modbus: {exception_error}")
163
162
  return False
164
163
 
165
164
  async def read_and_decode(
@@ -181,6 +180,58 @@ class Modbus:
181
180
  )
182
181
  return decoded_value
183
182
 
183
+ def read_registers_blocking(self, unit: int | str, address: int, count: int = 2, method: str = "input") -> ModbusResponse:
184
+ start_time = time.perf_counter()
185
+ result = None
186
+ kwargs = {"unit": unit, "count": count} if unit else {}
187
+ read_method = self._read_methods[method]
188
+
189
+ try:
190
+ # Run connection in the executor
191
+ connected = self._pymodbus_connect()
192
+ if not connected:
193
+ _LOGGER.error("Can't connect to Modbus.")
194
+ return None
195
+
196
+ _LOGGER.debug(
197
+ "Reading %s registers from %s with method %s from device %s.",
198
+ count,
199
+ address,
200
+ method,
201
+ unit,
202
+ )
203
+
204
+ # Run the read operation in the executor
205
+ result: ReadInputRegistersResponse = read_method(address, **kwargs)
206
+
207
+ if not hasattr(result, REGISTERS):
208
+ _LOGGER.error("No result from read: %s", str(result))
209
+ result = None
210
+
211
+ except ValueError as exception_error:
212
+ _LOGGER.error("Error reading registers: %s", exception_error)
213
+ pass
214
+ except (ModbusException, struct.error) as exception_error:
215
+ _LOGGER.error("Error reading registers: %s", exception_error)
216
+ pass
217
+ except asyncio.TimeoutError:
218
+ _LOGGER.error("Timeout reading registers from device %s", unit)
219
+ pass
220
+ except asyncio.CancelledError as err:
221
+ _LOGGER.error("Operation cancelled reading registers from device %s with error %s", unit, err)
222
+ pass
223
+ except Exception as e:
224
+ _LOGGER.error(f"Unexpected error reading registers: {type(e).__name__} - {e}")
225
+ pass
226
+ finally:
227
+ end_time = time.perf_counter()
228
+ _LOGGER.debug(
229
+ "Read completed in %.3f seconds: %s",
230
+ end_time - start_time,
231
+ result.registers if hasattr(result, REGISTERS) else None,
232
+ )
233
+ return result
234
+
184
235
  async def read_registers(
185
236
  self,
186
237
  unit: int | str, # device address
@@ -190,56 +241,8 @@ class Modbus:
190
241
  ) -> ModbusResponse:
191
242
  """Call async pymodbus."""
192
243
  async with self._lock:
193
- start_time = time.perf_counter()
194
- result = None
244
+ return await self._loop.run_in_executor(self._executor, self.read_registers_blocking, unit, address, count, method)
195
245
 
196
- try:
197
- # Run connection in the executor
198
- connected = self._pymodbus_connect()
199
- if not connected:
200
- _LOGGER.error("Can't connect to Modbus.")
201
- return None
202
-
203
- kwargs = {"unit": unit, "count": count} if unit else {}
204
- read_method = self._read_methods[method]
205
- _LOGGER.debug(
206
- "Reading %s registers from %s with method %s from device %s.",
207
- count,
208
- address,
209
- method,
210
- unit,
211
- )
212
-
213
- # Run the read operation in the executor
214
- result: ReadInputRegistersResponse = await self._loop.run_in_executor(
215
- self._executor,
216
- lambda: read_method(address, **kwargs)
217
- )
218
-
219
- if not hasattr(result, REGISTERS):
220
- _LOGGER.error("No result from read: %s", str(result))
221
- result = None
222
-
223
- except (ModbusException, struct.error) as exception_error:
224
- _LOGGER.error("Error reading registers: %s", exception_error)
225
- pass
226
- except asyncio.TimeoutError:
227
- _LOGGER.error("Timeout reading registers from device %s", unit)
228
- pass
229
- except asyncio.CancelledError as err:
230
- _LOGGER.error("Operation cancelled reading registers from device %s with error %s", unit, err)
231
- pass
232
- except Exception as e:
233
- _LOGGER.error(f"Unexpected error reading registers: {type(e).__name__} - {e}")
234
- pass
235
- finally:
236
- end_time = time.perf_counter()
237
- _LOGGER.debug(
238
- "Read completed in %.3f seconds: %s",
239
- end_time - start_time,
240
- result.registers if hasattr(result, REGISTERS) else None,
241
- )
242
- return result
243
246
 
244
247
  def decode_value(self, payload, value_type):
245
248
  _payload_type = VALUE_TYPES[value_type]
@@ -73,7 +73,6 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
73
73
  self._additional_sensors: List[Dict[str, SingleAdditionalSensor]] = []
74
74
  self._additional_sensors_by_source_name: Dict[str, List[SingleAdditionalSensor]] = {}
75
75
  self._additional_data = additional_data
76
- print("aaa", additional_data)
77
76
  # Standard sensors
78
77
  for index, data in enumerate(self._db[REGISTERS_BASE]):
79
78
  base = data[BASE]
@@ -253,7 +252,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
253
252
  )
254
253
  self._payload_online = ONLINE
255
254
  self._message_bus.send_message(
256
- topic=f"{self._config_helper.topic_prefix}/{self._id}{STATE}",
255
+ topic=f"{self._config_helper.topic_prefix}/{self._id}/{STATE}",
257
256
  payload=self._payload_online,
258
257
  )
259
258
  if not values:
@@ -264,7 +263,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
264
263
  # Let's assume device is offline.
265
264
  self.set_payload_offline()
266
265
  self._message_bus.send_message(
267
- topic=f"{self._config_helper.topic_prefix}/{self._id}{STATE}",
266
+ topic=f"{self._config_helper.topic_prefix}/{self._id}/{STATE}",
268
267
  payload=self._payload_online,
269
268
  )
270
269
  self._discovery_sent = False
@@ -329,6 +328,7 @@ class ModbusSensor(BasicMqtt, AsyncUpdater, Filter):
329
328
  timestamp=sensor.last_timestamp,
330
329
  ),
331
330
  )
331
+
332
332
  self._timestamp = timestamp
333
333
  self._message_bus.send_message(
334
334
  topic=f"{self._send_topic}/{data[BASE]}",
@@ -54,7 +54,7 @@ class Oled:
54
54
  def __init__(
55
55
  self,
56
56
  host_data: HostData,
57
- grouped_outputs: List[str],
57
+ grouped_outputs_by_expander: List[str],
58
58
  sleep_timeout: TimePeriod,
59
59
  screen_order: List[str],
60
60
  event_bus: EventBus
@@ -62,19 +62,19 @@ class Oled:
62
62
  """Initialize OLED screen."""
63
63
  self._loop = asyncio.get_running_loop()
64
64
  self._event_bus = event_bus
65
- self._grouped_outputs = None
65
+ self.grouped_outputs_by_expander = None
66
66
  self._input_groups = []
67
67
  self._host_data = host_data
68
68
 
69
69
  def configure_outputs() -> None:
70
70
  try:
71
71
  _ind_screen = screen_order.index("outputs")
72
- if not grouped_outputs:
72
+ if not grouped_outputs_by_expander:
73
73
  _LOGGER.debug("No outputs configured. Omitting in screen.")
74
74
  return
75
75
  screen_order.pop(_ind_screen)
76
- screen_order[_ind_screen:_ind_screen] = grouped_outputs
77
- self._grouped_outputs = grouped_outputs
76
+ screen_order[_ind_screen:_ind_screen] = grouped_outputs_by_expander
77
+ self.grouped_outputs_by_expander = grouped_outputs_by_expander
78
78
  except ValueError:
79
79
  pass
80
80
 
@@ -216,8 +216,8 @@ class Oled:
216
216
  else:
217
217
  with canvas(self._device) as draw:
218
218
  if (
219
- self._grouped_outputs
220
- and self._current_screen in self._grouped_outputs
219
+ self.grouped_outputs_by_expander
220
+ and self._current_screen in self.grouped_outputs_by_expander
221
221
  ):
222
222
  self._draw_output(data, draw)
223
223
  for id in data.keys():
@@ -245,7 +245,7 @@ class Oled:
245
245
  )
246
246
 
247
247
  async def _output_callback(self, event: OutputState):
248
- if self._grouped_outputs and self._current_screen in self._grouped_outputs:
248
+ if self.grouped_outputs_by_expander and self._current_screen in self.grouped_outputs_by_expander:
249
249
  self.handle_data_update(type=self._current_screen)
250
250
 
251
251
  async def _standard_callback(self, event: SensorState):