boneIO 1.3.0.dev5__py3-none-any.whl → 1.3.0.dev13__py3-none-any.whl

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 (235) hide show
  1. boneio/bonecli.py +34 -0
  2. boneio/components/cover/cover.py +16 -8
  3. boneio/components/cover/time_based.py +2 -2
  4. boneio/components/cover/venetian.py +1 -1
  5. boneio/components/group/output_group.py +5 -0
  6. boneio/components/input/binary_sensor.py +1 -2
  7. boneio/components/input/detectors.py +2 -2
  8. boneio/components/input/event.py +2 -2
  9. boneio/components/irrigation/__init__.py +6 -0
  10. boneio/components/irrigation/controller.py +853 -0
  11. boneio/components/irrigation/water_source.py +64 -0
  12. boneio/components/output/basic.py +99 -9
  13. boneio/components/output/mcp.py +2 -2
  14. boneio/components/output/pca.py +1 -1
  15. boneio/components/sensor/virtual_energy.py +3 -3
  16. boneio/components/template/__init__.py +1 -1
  17. boneio/components/template/alarm_panel.py +7 -7
  18. boneio/components/template/gate_cover.py +10 -10
  19. boneio/components/template/thermostat.py +6 -6
  20. boneio/const.py +6 -0
  21. boneio/core/cloud/registration.py +7 -7
  22. boneio/core/config/config_helper.py +13 -3
  23. boneio/core/config/migrations/__init__.py +6 -4
  24. boneio/core/config/migrations/v1_proxy_port.py +1 -1
  25. boneio/core/config/migrations/v2_transition.py +1 -1
  26. boneio/core/config/schema_converter.py +2 -4
  27. boneio/core/config/yaml_util.py +5 -12
  28. boneio/core/discovery.py +20 -1
  29. boneio/core/events/__init__.py +1 -1
  30. boneio/core/events/bus.py +1 -1
  31. boneio/core/manager/__init__.py +2 -0
  32. boneio/core/manager/action_conditions.py +351 -0
  33. boneio/core/manager/canopen.py +4 -3
  34. boneio/core/manager/covers.py +9 -2
  35. boneio/core/manager/display.py +65 -1
  36. boneio/core/manager/inputs.py +7 -5
  37. boneio/core/manager/irrigation.py +582 -0
  38. boneio/core/manager/manager.py +98 -34
  39. boneio/core/manager/modbus.py +1 -1
  40. boneio/core/manager/outputs.py +64 -1
  41. boneio/core/manager/remote.py +1 -1
  42. boneio/core/manager/sensors.py +9 -9
  43. boneio/core/manager/templates/__init__.py +2 -2
  44. boneio/core/manager/templates/alarm.py +3 -3
  45. boneio/core/manager/templates/gate_cover.py +2 -2
  46. boneio/core/manager/templates/thermostat.py +2 -2
  47. boneio/core/manager/templates.py +4 -4
  48. boneio/core/manager/update.py +9 -22
  49. boneio/core/messaging/basic.py +2 -2
  50. boneio/core/messaging/local.py +2 -2
  51. boneio/core/messaging/mqtt.py +19 -7
  52. boneio/core/remote/esphome.py +2 -1
  53. boneio/core/remote/wled.py +2 -2
  54. boneio/core/state/manager.py +2 -2
  55. boneio/core/system/__init__.py +1 -1
  56. boneio/core/system/host_data.py +1 -1
  57. boneio/core/utils/async_updater.py +3 -3
  58. boneio/core/utils/conditions.py +3 -2
  59. boneio/core/utils/util.py +2 -2
  60. boneio/hardware/analog/adc.py +3 -3
  61. boneio/hardware/can/client.py +5 -4
  62. boneio/hardware/can/interface.py +1 -1
  63. boneio/hardware/can/node.py +2 -2
  64. boneio/hardware/can/sudoers.py +2 -2
  65. boneio/hardware/display/__init__.py +27 -1
  66. boneio/hardware/display/early_oled.py +238 -0
  67. boneio/hardware/display/oled.py +1 -1
  68. boneio/hardware/gpio/input/base.py +12 -1
  69. boneio/hardware/gpio/input/manager.py +11 -11
  70. boneio/hardware/i2c/bus.py +5 -5
  71. boneio/hardware/onewire/__init__.py +1 -1
  72. boneio/integration/__init__.py +1 -1
  73. boneio/integration/homeassistant.py +264 -2
  74. boneio/modbus/cli.py +2 -1
  75. boneio/modbus/devices/other/esp32_relay_x4_modbus.json +172 -0
  76. boneio/modbus/entities/__init__.py +4 -4
  77. boneio/modbus/entities/derived/numeric.py +0 -1
  78. boneio/modbus/entities/derived/select.py +2 -2
  79. boneio/modbus/entities/derived/switch.py +2 -2
  80. boneio/modbus/entities/derived/text.py +1 -1
  81. boneio/modbus/entities/sensor/binary.py +0 -1
  82. boneio/modbus/entities/sensor/text.py +1 -2
  83. boneio/modbus/utils.py +0 -1
  84. boneio/models/__init__.py +3 -1
  85. boneio/models/actions.py +1 -0
  86. boneio/models/state.py +6 -0
  87. boneio/runner.py +28 -49
  88. boneio/schema/schema.yaml +412 -8
  89. boneio/version.py +1 -1
  90. boneio/webui/app.py +28 -8
  91. boneio/webui/frontend-dist/assets/ConfigEditor-CrqODtD9.js +1 -0
  92. boneio/webui/frontend-dist/assets/aiConfig-DCT969oj.js +2 -0
  93. boneio/webui/frontend-dist/assets/aiWizardPrompt-Dpts0jpN.js +2 -0
  94. boneio/webui/frontend-dist/assets/editor.worker-BVjSvWeP.js +12 -0
  95. boneio/webui/frontend-dist/assets/index-CCPsr7-u.css +2 -0
  96. boneio/webui/frontend-dist/assets/index-Cdw9RS1j.js +39 -0
  97. boneio/webui/frontend-dist/assets/json.worker-CqOJL4FD.js +51 -0
  98. boneio/webui/frontend-dist/assets/monaco-B9WiNxkw.css +1 -0
  99. boneio/webui/frontend-dist/assets/monaco-CAZoGZNF.js +1047 -0
  100. boneio/webui/frontend-dist/assets/rolldown-runtime-Dw2cE7zH.js +1 -0
  101. boneio/webui/frontend-dist/assets/useTranslation-xq1ST8U-.js +13 -0
  102. boneio/webui/frontend-dist/assets/vendor-BD5Ml_Uz.js +55 -0
  103. boneio/webui/frontend-dist/assets/workbox-window.prod.es5-BJd1pjeW.js +2 -0
  104. boneio/webui/frontend-dist/assets/yaml.worker-nZQZSRZ7.js +375 -0
  105. boneio/webui/frontend-dist/index.html +8 -5
  106. boneio/webui/frontend-dist/schema/config.schema.json +710 -11
  107. boneio/webui/frontend-dist/schema/irrigation.schema.json +352 -0
  108. boneio/webui/frontend-dist/schema/modbus_devices.schema.json +3 -0
  109. boneio/webui/frontend-dist/schema/output.schema.json +62 -0
  110. boneio/webui/frontend-dist/schema/template.schema.json +299 -11
  111. boneio/webui/frontend-dist/sw.js +1 -1
  112. boneio/webui/frontend-dist/workbox-4eca85ba.js +1 -0
  113. boneio/webui/middleware/auth.py +3 -3
  114. boneio/webui/routes/__init__.py +3 -1
  115. boneio/webui/routes/caddy.py +14 -14
  116. boneio/webui/routes/can.py +5 -5
  117. boneio/webui/routes/config.py +77 -17
  118. boneio/webui/routes/irrigation.py +316 -0
  119. boneio/webui/routes/modbus.py +1 -1
  120. boneio/webui/routes/outputs.py +62 -0
  121. boneio/webui/routes/remote_devices.py +3 -3
  122. boneio/webui/routes/system.py +1 -1
  123. boneio/webui/routes/timezone_sudoers.py +2 -2
  124. boneio/webui/routes/update.py +70 -38
  125. boneio/webui/schema/config.schema.json +710 -11
  126. boneio/webui/schema/irrigation.schema.json +352 -0
  127. boneio/webui/schema/modbus_devices.schema.json +3 -0
  128. boneio/webui/schema/output.schema.json +62 -0
  129. boneio/webui/schema/template.schema.json +299 -11
  130. boneio/webui/services/__init__.py +2 -2
  131. boneio/webui/web_server.py +3 -1
  132. boneio/webui/websocket_manager.py +2 -2
  133. {boneio-1.3.0.dev5.dist-info → boneio-1.3.0.dev13.dist-info}/METADATA +1 -1
  134. {boneio-1.3.0.dev5.dist-info → boneio-1.3.0.dev13.dist-info}/RECORD +138 -210
  135. boneio/webui/frontend-dist/assets/ConfigEditor-BWHZGmYg.js +0 -1
  136. boneio/webui/frontend-dist/assets/abap-CRCWOmpq.js +0 -1
  137. boneio/webui/frontend-dist/assets/aiWizardPrompt-C1vdmyeb.js +0 -2
  138. boneio/webui/frontend-dist/assets/apex-DnsZk_dE.js +0 -1
  139. boneio/webui/frontend-dist/assets/azcli-1IWB1ccx.js +0 -1
  140. boneio/webui/frontend-dist/assets/bat-DPkNLes8.js +0 -1
  141. boneio/webui/frontend-dist/assets/bicep-Corcdgou.js +0 -2
  142. boneio/webui/frontend-dist/assets/cameligo-CGrWLZr3.js +0 -1
  143. boneio/webui/frontend-dist/assets/clojure-D9WOWImG.js +0 -1
  144. boneio/webui/frontend-dist/assets/coffee-B7EJu28W.js +0 -1
  145. boneio/webui/frontend-dist/assets/cpp-SEyurbux.js +0 -1
  146. boneio/webui/frontend-dist/assets/csharp-BoL64M5l.js +0 -1
  147. boneio/webui/frontend-dist/assets/csp-C46ZqvIl.js +0 -1
  148. boneio/webui/frontend-dist/assets/css-DQU6DXDx.js +0 -3
  149. boneio/webui/frontend-dist/assets/cssMode-DShylJqh.js +0 -4
  150. boneio/webui/frontend-dist/assets/cypher-D84EuPTj.js +0 -1
  151. boneio/webui/frontend-dist/assets/dart-D8lhlL1r.js +0 -1
  152. boneio/webui/frontend-dist/assets/dockerfile-DLk6rpji.js +0 -1
  153. boneio/webui/frontend-dist/assets/ecl-BO6FnfXk.js +0 -1
  154. boneio/webui/frontend-dist/assets/editor.worker-B4pQIWZD.js +0 -12
  155. boneio/webui/frontend-dist/assets/elixir-BRjLKONM.js +0 -1
  156. boneio/webui/frontend-dist/assets/flow9-Cac8vKd7.js +0 -1
  157. boneio/webui/frontend-dist/assets/freemarker2-CdX7KyE5.js +0 -3
  158. boneio/webui/frontend-dist/assets/fsharp-fd1GTHhf.js +0 -1
  159. boneio/webui/frontend-dist/assets/go-O9LJTZXk.js +0 -1
  160. boneio/webui/frontend-dist/assets/graphql-LQdxqEYJ.js +0 -1
  161. boneio/webui/frontend-dist/assets/handlebars-C3LDizRo.js +0 -1
  162. boneio/webui/frontend-dist/assets/hcl-DxDQ3s82.js +0 -1
  163. boneio/webui/frontend-dist/assets/html-z-YV0Mzh.js +0 -1
  164. boneio/webui/frontend-dist/assets/htmlMode-D7IIR2va.js +0 -4
  165. boneio/webui/frontend-dist/assets/index-BZZGqf-N.css +0 -1
  166. boneio/webui/frontend-dist/assets/index-DXEKDEyX.js +0 -105
  167. boneio/webui/frontend-dist/assets/ini-BvajGCUy.js +0 -1
  168. boneio/webui/frontend-dist/assets/java-SYsfObOQ.js +0 -1
  169. boneio/webui/frontend-dist/assets/javascript-CH6jkTQ0.js +0 -1
  170. boneio/webui/frontend-dist/assets/json.worker-aFakAbRR.js +0 -44
  171. boneio/webui/frontend-dist/assets/jsonMode-CLzeI5HJ.js +0 -10
  172. boneio/webui/frontend-dist/assets/julia-DQXNmw_w.js +0 -1
  173. boneio/webui/frontend-dist/assets/kotlin-qQ0MG-9I.js +0 -1
  174. boneio/webui/frontend-dist/assets/less-GGFNNJHn.js +0 -2
  175. boneio/webui/frontend-dist/assets/lexon-Canl7DCW.js +0 -1
  176. boneio/webui/frontend-dist/assets/liquid-DuoI_Tv0.js +0 -1
  177. boneio/webui/frontend-dist/assets/lua-D28Ae8-K.js +0 -1
  178. boneio/webui/frontend-dist/assets/m3-DPitgjJI.js +0 -1
  179. boneio/webui/frontend-dist/assets/markdown-B811l8j2.js +0 -1
  180. boneio/webui/frontend-dist/assets/mdx-C2KSoPE6.js +0 -1
  181. boneio/webui/frontend-dist/assets/mips-CdjsipkG.js +0 -1
  182. boneio/webui/frontend-dist/assets/monaco-DVn9mNSL.js +0 -739
  183. boneio/webui/frontend-dist/assets/monaco-xnhJeWAr.css +0 -1
  184. boneio/webui/frontend-dist/assets/msdax-CYqgjx_P.js +0 -1
  185. boneio/webui/frontend-dist/assets/mysql-BHd6q0vd.js +0 -1
  186. boneio/webui/frontend-dist/assets/objective-c-B1aVtJYH.js +0 -1
  187. boneio/webui/frontend-dist/assets/pascal-BhNW15KB.js +0 -1
  188. boneio/webui/frontend-dist/assets/pascaligo-5jv8CcQD.js +0 -1
  189. boneio/webui/frontend-dist/assets/perl-DlYyT36c.js +0 -1
  190. boneio/webui/frontend-dist/assets/pgsql-Dy0bjov7.js +0 -1
  191. boneio/webui/frontend-dist/assets/php-120yhfDK.js +0 -1
  192. boneio/webui/frontend-dist/assets/pla-CjnFlu4u.js +0 -1
  193. boneio/webui/frontend-dist/assets/postiats-CQpG440k.js +0 -1
  194. boneio/webui/frontend-dist/assets/powerquery-DdJtto1Z.js +0 -1
  195. boneio/webui/frontend-dist/assets/powershell-Bu_VLpJB.js +0 -1
  196. boneio/webui/frontend-dist/assets/protobuf-IBS6jZEB.js +0 -2
  197. boneio/webui/frontend-dist/assets/pug-kFxLfcjb.js +0 -1
  198. boneio/webui/frontend-dist/assets/python-Dh7Kzq6D.js +0 -1
  199. boneio/webui/frontend-dist/assets/qsharp-q7JyzKFN.js +0 -1
  200. boneio/webui/frontend-dist/assets/r-BIFz-_sK.js +0 -1
  201. boneio/webui/frontend-dist/assets/razor-CJwYmOfy.js +0 -1
  202. boneio/webui/frontend-dist/assets/redis-CHOsPHWR.js +0 -1
  203. boneio/webui/frontend-dist/assets/redshift-CBifECDb.js +0 -1
  204. boneio/webui/frontend-dist/assets/restructuredtext-CghPJEOS.js +0 -1
  205. boneio/webui/frontend-dist/assets/ruby-CYWGW-b1.js +0 -1
  206. boneio/webui/frontend-dist/assets/rust-DMDD0SHb.js +0 -1
  207. boneio/webui/frontend-dist/assets/sb-BYAiYHFx.js +0 -1
  208. boneio/webui/frontend-dist/assets/scala-Bqvq8jcR.js +0 -1
  209. boneio/webui/frontend-dist/assets/scheme-Dhb-2j9p.js +0 -1
  210. boneio/webui/frontend-dist/assets/scss-CTwUZ5N7.js +0 -3
  211. boneio/webui/frontend-dist/assets/shell-CsDZo4DB.js +0 -1
  212. boneio/webui/frontend-dist/assets/solidity-CME5AdoB.js +0 -1
  213. boneio/webui/frontend-dist/assets/sophia-RYC1BQQz.js +0 -1
  214. boneio/webui/frontend-dist/assets/sparql-KEyrF7De.js +0 -1
  215. boneio/webui/frontend-dist/assets/sql-BdTr02Mf.js +0 -1
  216. boneio/webui/frontend-dist/assets/st-C7iG7M4S.js +0 -1
  217. boneio/webui/frontend-dist/assets/swift-D7IUmUK8.js +0 -1
  218. boneio/webui/frontend-dist/assets/systemverilog-DgMryOEJ.js +0 -1
  219. boneio/webui/frontend-dist/assets/tcl-PloMZuKG.js +0 -1
  220. boneio/webui/frontend-dist/assets/tsMode-VSMpyycN.js +0 -11
  221. boneio/webui/frontend-dist/assets/twig-BfRIq3la.js +0 -1
  222. boneio/webui/frontend-dist/assets/typescript-C4HjhnfC.js +0 -1
  223. boneio/webui/frontend-dist/assets/typespec-CzxlYoT_.js +0 -1
  224. boneio/webui/frontend-dist/assets/vb-BwAE3J76.js +0 -1
  225. boneio/webui/frontend-dist/assets/vendor-8TE4Uyqi.js +0 -3
  226. boneio/webui/frontend-dist/assets/wgsl-B_1kOXbF.js +0 -298
  227. boneio/webui/frontend-dist/assets/workbox-window.prod.es5-BIl4cyR9.js +0 -2
  228. boneio/webui/frontend-dist/assets/xml-ByUHJiRO.js +0 -1
  229. boneio/webui/frontend-dist/assets/yaml-CTy8Ej0Q.js +0 -1
  230. boneio/webui/frontend-dist/assets/yaml.worker-DBeHcBRc.js +0 -411
  231. boneio/webui/frontend-dist/workbox-226dbdbf.js +0 -1
  232. {boneio-1.3.0.dev5.dist-info → boneio-1.3.0.dev13.dist-info}/WHEEL +0 -0
  233. {boneio-1.3.0.dev5.dist-info → boneio-1.3.0.dev13.dist-info}/entry_points.txt +0 -0
  234. {boneio-1.3.0.dev5.dist-info → boneio-1.3.0.dev13.dist-info}/licenses/LICENSE +0 -0
  235. {boneio-1.3.0.dev5.dist-info → boneio-1.3.0.dev13.dist-info}/top_level.txt +0 -0
boneio/bonecli.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import time as _boot_time
6
+
6
7
  _BOOT_T0 = _boot_time.monotonic()
7
8
 
8
9
  import logging
@@ -20,6 +21,7 @@ print(f"[BOOT TIMING] stdlib imports: {_boot_time.monotonic() - _BOOT_T0:.2f}s",
20
21
  # startup time. Only version is imported here for --version CLI flag.
21
22
  _t_ver = _boot_time.monotonic()
22
23
  from boneio.version import __version__
24
+
23
25
  print(f"[BOOT TIMING] ALL imports: {_boot_time.monotonic() - _BOOT_T0:.2f}s", flush=True)
24
26
 
25
27
  TASK_CANCELATION_TIMEOUT = 1
@@ -205,7 +207,9 @@ def run(
205
207
  ) -> int:
206
208
  """Run BoneIO."""
207
209
  import time as _time
210
+
208
211
  from yaml import MarkedYAMLError
212
+
209
213
  from boneio.core.config import load_config_from_file
210
214
  from boneio.core.events import GracefulExit
211
215
  from boneio.core.utils.logger import configure_logger, setup_logging
@@ -214,12 +218,33 @@ def run(
214
218
  setup_logging(debug_level=debug)
215
219
  _LOGGER.info("BoneIO %s starting.", __version__)
216
220
  _LOGGER.debug("[STARTUP TIMING] after setup_logging: %.2fs", _time.monotonic() - _t0)
221
+
222
+ # --- Initialize OLED before anything else (independent of config) ---
223
+ # This is wrapped in try/except so the app always starts even if
224
+ # OLED hardware is missing, broken, or display libraries aren't installed.
225
+ try:
226
+ from boneio.hardware.display.early_oled import (
227
+ draw_config_error,
228
+ draw_crash,
229
+ draw_status,
230
+ init_early_oled,
231
+ )
232
+ init_early_oled()
233
+ draw_status("Loading config...")
234
+ except Exception:
235
+ # OLED is optional — define no-op stubs so rest of the function works
236
+ _LOGGER.debug("Early OLED not available, continuing without display")
237
+ def draw_status(msg: str) -> None: pass # noqa: E731
238
+ def draw_config_error(msg: str) -> None: pass # noqa: E731
239
+ def draw_crash(exc: BaseException) -> None: pass # noqa: E731
240
+
217
241
  try:
218
242
  _t1 = _time.monotonic()
219
243
  _config = load_config_from_file(config_file=config)
220
244
  _LOGGER.debug("[STARTUP TIMING] load_config_from_file: %.2fs", _time.monotonic() - _t1)
221
245
  if not _config:
222
246
  _LOGGER.error("Config not loaded. Exiting.")
247
+ draw_config_error("Config file is empty or missing")
223
248
  return 1
224
249
  configure_logger(log_config=_config.get("logger") or {}, debug=debug)
225
250
  # Granular timing of runner sub-imports to find the bottleneck
@@ -242,6 +267,9 @@ def run(
242
267
  from boneio.runner import async_run
243
268
  _LOGGER.debug("[RUNNER IMPORT] boneio.runner (rest): %.2fs", _time.monotonic() - _t_a)
244
269
  _LOGGER.debug("[STARTUP TIMING] total before async_run: %.2fs", _time.monotonic() - _t0)
270
+
271
+ draw_status("Starting...")
272
+
245
273
  ret = asyncio.run(
246
274
  async_run(
247
275
  config=_config,
@@ -260,6 +288,11 @@ def run(
260
288
  return 0
261
289
  except (ConfigurationException, MarkedYAMLError) as err:
262
290
  _LOGGER.error("Failed to load config. %s Exiting.", err)
291
+ draw_config_error(str(err)[:100])
292
+ return 1
293
+ except Exception as err:
294
+ _LOGGER.error("Unexpected error during startup: %s", err, exc_info=True)
295
+ draw_crash(err)
263
296
  return 1
264
297
 
265
298
 
@@ -268,6 +301,7 @@ def run_modbus_command(
268
301
  ) -> int:
269
302
  """Run BoneIO."""
270
303
  from yaml import MarkedYAMLError
304
+
271
305
  from boneio.core.events import GracefulExit
272
306
  from boneio.core.utils.logger import configure_logger, setup_logging
273
307
  from boneio.exceptions import ConfigurationException, RestartRequestException
@@ -1,13 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- import logging
5
4
  import json
5
+ import logging
6
6
  import threading
7
7
  import time
8
8
  from abc import ABC, abstractmethod
9
9
  from collections.abc import Callable
10
10
 
11
+ from boneio.components.output import BasicOutput
11
12
  from boneio.const import (
12
13
  CLOSED,
13
14
  CLOSING,
@@ -20,7 +21,6 @@ from boneio.core.events import EventBus
20
21
  from boneio.core.messaging import BasicMqtt
21
22
  from boneio.core.utils import TimePeriod
22
23
  from boneio.models import CoverState, PositionDict
23
- from boneio.components.output import BasicOutput
24
24
  from boneio.models.events import CoverEvent
25
25
 
26
26
  _LOGGER = logging.getLogger(__name__)
@@ -267,9 +267,7 @@ class BaseCover(BaseCoverABC, BasicMqtt):
267
267
  await self.stop()
268
268
  elif self._position >= 100:
269
269
  await self.close()
270
- elif self._position <= 0:
271
- await self.open()
272
- elif self._last_operation == CLOSING:
270
+ elif self._position <= 0 or self._last_operation == CLOSING:
273
271
  await self.open()
274
272
  else:
275
273
  await self.close()
@@ -309,9 +307,7 @@ class BaseCover(BaseCoverABC, BasicMqtt):
309
307
  await self.open()
310
308
  elif self._position >= 100:
311
309
  await self.close()
312
- elif self._position <= 0:
313
- await self.open()
314
- elif self._last_operation == CLOSING:
310
+ elif self._position <= 0 or self._last_operation == CLOSING:
315
311
  await self.open()
316
312
  else:
317
313
  await self.close()
@@ -325,6 +321,18 @@ class BaseCover(BaseCoverABC, BasicMqtt):
325
321
  else:
326
322
  return CLOSED if self._position == 0 else OPEN
327
323
 
324
+ @property
325
+ def is_open(self) -> bool:
326
+ """Whether the cover is currently open (position > 0).
327
+
328
+ Used by the action conditions system to evaluate ``is_open`` / ``is_closed``
329
+ checks for covers.
330
+
331
+ Returns:
332
+ True if the cover is not fully closed.
333
+ """
334
+ return self._position > 0
335
+
328
336
  @property
329
337
  def position(self) -> int:
330
338
  return round(self._position, 0)
@@ -6,11 +6,11 @@ import threading
6
6
  import time
7
7
  from collections.abc import Callable
8
8
 
9
- from boneio.const import CLOSE, CLOSING, IDLE, OPEN, OPENING, STOP
10
9
  from boneio.components.cover.cover import BaseCover
10
+ from boneio.components.output import BasicOutput
11
+ from boneio.const import CLOSE, CLOSING, IDLE, OPEN, OPENING, STOP
11
12
  from boneio.core.events import EventBus
12
13
  from boneio.core.utils import TimePeriod
13
- from boneio.components.output import BasicOutput
14
14
 
15
15
  _LOGGER = logging.getLogger(__name__)
16
16
  DEFAULT_RESTORED_STATE = {"position": 100}
@@ -5,8 +5,8 @@ import logging
5
5
  import threading
6
6
  import time
7
7
 
8
- from boneio.const import CLOSE, CLOSING, IDLE, OPEN, OPENING, STOP
9
8
  from boneio.components.cover.cover import BaseCover, BaseVenetianCoverABC
9
+ from boneio.const import CLOSE, CLOSING, IDLE, OPEN, OPENING, STOP
10
10
  from boneio.core.utils import TimePeriod
11
11
  from boneio.models import PositionDict
12
12
 
@@ -112,6 +112,11 @@ class OutputGroup(BasicOutput):
112
112
  """Check if group is active (ON state)."""
113
113
  return self._state == ON
114
114
 
115
+ @property
116
+ def group_members(self) -> list[BasicOutput]:
117
+ """Return list of member outputs."""
118
+ return self._group_members
119
+
115
120
  @override
116
121
  async def async_send_state(self, optimized_value: str | None = None) -> None:
117
122
  """Send state to message bus and event bus for WebSocket."""
@@ -3,12 +3,11 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import logging
6
-
7
6
  import time
8
7
  from typing import cast
9
8
 
10
9
  from boneio.components.input.detectors import BinarySensorDetector
11
- from boneio.const import BinaryStateTypes, ClickTypes, PRESSED, RELEASED
10
+ from boneio.const import PRESSED, RELEASED, BinaryStateTypes, ClickTypes
12
11
  from boneio.hardware.gpio.input import GpioBaseClass, get_gpio_manager
13
12
  from boneio.models import InputState
14
13
  from boneio.models.events import InputEvent
@@ -11,8 +11,6 @@ from typing import cast
11
11
  import gpiod
12
12
 
13
13
  from boneio.const import (
14
- BinaryStateTypes,
15
- ClickTypes,
16
14
  CLICK_SEQUENCES,
17
15
  DEFAULT_SEQUENCE_WINDOW_MS,
18
16
  DOUBLE,
@@ -21,6 +19,8 @@ from boneio.const import (
21
19
  RELEASED,
22
20
  SINGLE,
23
21
  TRIPLE,
22
+ BinaryStateTypes,
23
+ ClickTypes,
24
24
  )
25
25
 
26
26
  _LOGGER = logging.getLogger(__name__)
@@ -5,10 +5,10 @@ from __future__ import annotations
5
5
  import logging
6
6
  import time
7
7
 
8
- from boneio.const import ClickTypes
9
8
  from boneio.components.input.detectors import MultiClickDetector
10
- from boneio.hardware.gpio.input import GpioBaseClass, get_gpio_manager
9
+ from boneio.const import ClickTypes
11
10
  from boneio.core.utils import TimePeriod
11
+ from boneio.hardware.gpio.input import GpioBaseClass, get_gpio_manager
12
12
 
13
13
  _LOGGER = logging.getLogger(__name__)
14
14
 
@@ -0,0 +1,6 @@
1
+ """Irrigation components."""
2
+
3
+ from .controller import IrrigationController, IrrigationZone
4
+ from .water_source import WaterSource
5
+
6
+ __all__ = ["IrrigationController", "IrrigationZone", "WaterSource"]