|
5 | 5 |
|
6 | 6 | import asyncio |
7 | 7 | from pathlib import Path |
8 | | -from typing import TYPE_CHECKING |
| 8 | +from typing import TYPE_CHECKING, cast |
9 | 9 |
|
10 | 10 | import click |
11 | 11 |
|
|
15 | 15 |
|
16 | 16 | if TYPE_CHECKING: |
17 | 17 | from pyomnilogic_local.api.api import OmniLogicAPI |
| 18 | + from pyomnilogic_local.models.telemetry import TelemetryChlorinator |
18 | 19 |
|
19 | 20 |
|
20 | 21 | @click.group() |
@@ -209,3 +210,122 @@ def set_equipment(ctx: click.Context, bow_id: int, equip_id: int, is_on: str) -> |
209 | 210 | except Exception as e: |
210 | 211 | click.echo(f"Error setting equipment: {e}", err=True) |
211 | 212 | raise click.Abort from e |
| 213 | + |
| 214 | + |
| 215 | +@debug.command() |
| 216 | +@click.argument("bow_id", type=int) |
| 217 | +@click.argument("equip_id", type=int) |
| 218 | +@click.argument("timed_percent", type=int) |
| 219 | +@click.argument("op_mode", type=int) |
| 220 | +@click.pass_context |
| 221 | +def set_chlor_params(ctx: click.Context, bow_id: int, equip_id: int, timed_percent: int, op_mode: int) -> None: |
| 222 | + """Set chlorinator parameters with explicit control over configuration. |
| 223 | +
|
| 224 | + This command sets chlorinator parameters using the current chlorinator's |
| 225 | + configuration for cell_type, sc_timeout, bow_type, and orp_timeout, while |
| 226 | + allowing you to specify timed_percent and op_mode. The cfg_state is derived |
| 227 | + from the chlorinator's current on/off state. |
| 228 | +
|
| 229 | + BOW_ID: The Body of Water (pool/spa) system ID |
| 230 | + EQUIP_ID: The chlorinator equipment system ID |
| 231 | + TIMED_PERCENT: Chlorine generation percentage (0-100) |
| 232 | + OP_MODE: Operating mode (0=DISABLED, 1=TIMED, 2=ORP_AUTO, 3=ORP_TIMED_RW) |
| 233 | +
|
| 234 | + Examples: |
| 235 | + # Set chlorinator to 75% in TIMED mode |
| 236 | + omnilogic --host 192.168.1.100 debug set-chlor-params 7 12 75 1 |
| 237 | +
|
| 238 | + # Disable chlorinator |
| 239 | + omnilogic --host 192.168.1.100 debug set-chlor-params 7 12 0 0 |
| 240 | +
|
| 241 | + # Set to ORP AUTO mode with 50% generation |
| 242 | + omnilogic --host 192.168.1.100 debug set-chlor-params 7 12 50 2 |
| 243 | +
|
| 244 | + """ |
| 245 | + ensure_connection(ctx) |
| 246 | + omni: OmniLogicAPI = ctx.obj["OMNI"] |
| 247 | + |
| 248 | + # Validate timed_percent |
| 249 | + if not 0 <= timed_percent <= 100: |
| 250 | + click.echo(f"Error: timed_percent must be between 0-100, got {timed_percent}", err=True) |
| 251 | + raise click.Abort |
| 252 | + |
| 253 | + # Validate op_mode |
| 254 | + if not 0 <= op_mode <= 2: |
| 255 | + click.echo(f"Error: op_mode must be between 0-3, got {op_mode}", err=True) |
| 256 | + raise click.Abort |
| 257 | + |
| 258 | + # Get MSPConfig and Telemetry to find the chlorinator |
| 259 | + try: |
| 260 | + mspconfig_raw = asyncio.run(omni.async_get_mspconfig(raw=False)) |
| 261 | + telemetry_raw = asyncio.run(omni.async_get_telemetry(raw=False)) |
| 262 | + except Exception as e: |
| 263 | + click.echo(f"Error retrieving configuration: {e}", err=True) |
| 264 | + raise click.Abort from e |
| 265 | + |
| 266 | + # Find the BOW |
| 267 | + bow = None |
| 268 | + if mspconfig_raw.backyard.bow: |
| 269 | + for candidate_bow in mspconfig_raw.backyard.bow: |
| 270 | + if candidate_bow.system_id == bow_id: |
| 271 | + bow = candidate_bow |
| 272 | + break |
| 273 | + |
| 274 | + if bow is None: |
| 275 | + click.echo(f"Error: Body of Water with ID {bow_id} not found", err=True) |
| 276 | + raise click.Abort |
| 277 | + |
| 278 | + # Find the chlorinator |
| 279 | + if bow.chlorinator is None or bow.chlorinator.system_id != equip_id: |
| 280 | + click.echo(f"Error: Chlorinator with ID {equip_id} not found in BOW {bow_id}", err=True) |
| 281 | + raise click.Abort |
| 282 | + |
| 283 | + chlorinator = bow.chlorinator |
| 284 | + |
| 285 | + # Get telemetry for the chlorinator to determine is_on state |
| 286 | + chlorinator_telemetry = telemetry_raw.get_telem_by_systemid(equip_id) |
| 287 | + if chlorinator_telemetry is None: |
| 288 | + click.echo(f"Warning: No telemetry found for chlorinator {equip_id}, defaulting cfg_state to 3 (on)", err=True) |
| 289 | + cfg_state = 3 |
| 290 | + else: |
| 291 | + # Cast to TelemetryChlorinator to access enable attribute |
| 292 | + chlorinator_telem = cast("TelemetryChlorinator", chlorinator_telemetry) |
| 293 | + # Determine cfg_state from enable flag in telemetry |
| 294 | + cfg_state = 3 if chlorinator_telem.enable else 2 |
| 295 | + |
| 296 | + # Determine bow_type from equipment type (0=pool, 1=spa) |
| 297 | + bow_type = 0 if bow.equip_type == "BOW_POOL" else 1 |
| 298 | + |
| 299 | + # Get parameters from chlorinator config |
| 300 | + cell_type = chlorinator.cell_type.value |
| 301 | + sc_timeout = chlorinator.superchlor_timeout |
| 302 | + orp_timeout = chlorinator.orp_timeout |
| 303 | + |
| 304 | + # Execute the command |
| 305 | + try: |
| 306 | + asyncio.run( |
| 307 | + omni.async_set_chlorinator_params( |
| 308 | + pool_id=bow_id, |
| 309 | + equipment_id=equip_id, |
| 310 | + timed_percent=timed_percent, |
| 311 | + cell_type=cell_type, |
| 312 | + op_mode=op_mode, |
| 313 | + sc_timeout=sc_timeout, |
| 314 | + bow_type=bow_type, |
| 315 | + orp_timeout=orp_timeout, |
| 316 | + cfg_state=cfg_state, |
| 317 | + ) |
| 318 | + ) |
| 319 | + click.echo( |
| 320 | + f"Sent command to chlorinator {equip_id} in BOW {bow_id}:\n" |
| 321 | + f" Timed Percent: {timed_percent}%\n" |
| 322 | + f" Operating Mode: {op_mode}\n" |
| 323 | + f" Config State: {cfg_state} ({'on' if cfg_state == 3 else 'off'})\n" |
| 324 | + f" Cell Type: {cell_type}\n" |
| 325 | + f" SC Timeout: {sc_timeout}\n" |
| 326 | + f" BOW Type: {bow_type}\n" |
| 327 | + f" ORP Timeout: {orp_timeout}" |
| 328 | + ) |
| 329 | + except Exception as e: |
| 330 | + click.echo(f"Error setting chlorinator parameters: {e}", err=True) |
| 331 | + raise click.Abort from e |
0 commit comments