diff --git a/pyomnilogic_local/cli/cli.py b/pyomnilogic_local/cli/cli.py index 7749cff..4b2cc42 100644 --- a/pyomnilogic_local/cli/cli.py +++ b/pyomnilogic_local/cli/cli.py @@ -7,7 +7,12 @@ from pyomnilogic_local import OmniLogic from pyomnilogic_local.cli.debug import commands as debug +from pyomnilogic_local.cli.filter_cmd import filter from pyomnilogic_local.cli.get import commands as get +from pyomnilogic_local.cli.heater_cmd import heater +from pyomnilogic_local.cli.light_cmd import light +from pyomnilogic_local.cli.pump_cmd import pump +from pyomnilogic_local.cli.relay_cmd import relay @click.group() @@ -60,3 +65,8 @@ def entrypoint(ctx: click.Context, host: str, port: int, timeout: int, debug: bo entrypoint.add_command(debug.debug) entrypoint.add_command(get.get) +entrypoint.add_command(heater) +entrypoint.add_command(pump) +entrypoint.add_command(filter) +entrypoint.add_command(relay) +entrypoint.add_command(light) diff --git a/pyomnilogic_local/cli/filter_cmd.py b/pyomnilogic_local/cli/filter_cmd.py new file mode 100644 index 0000000..c7d6af7 --- /dev/null +++ b/pyomnilogic_local/cli/filter_cmd.py @@ -0,0 +1,69 @@ +# mypy: disable-error-code="misc" + +from __future__ import annotations + +import asyncio +from typing import TYPE_CHECKING + +import click + +from pyomnilogic_local.cli.utils import echo_properties + +if TYPE_CHECKING: + from pyomnilogic_local import OmniLogic + + +@click.group(invoke_without_command=True) +@click.argument("system_id", type=int) +@click.pass_context +def filter(ctx: click.Context, system_id: int) -> None: + """Interact with a filter by system ID. + + If no subcommand is given, displays all properties of the filter. + + Example: + omnilogic filter 3 turn_on + omnilogic filter 3 set_speed 75 + """ + omnilogic: OmniLogic = ctx.obj["OMNILOGIC"] + + equipment = omnilogic.all_filters.get_by_id(system_id) + if equipment is None: + raise click.ClickException(f"No filter found with system_id {system_id}. Use 'omnilogic get filters' to list available filters.") + + ctx.obj["EQUIPMENT"] = equipment + + if ctx.invoked_subcommand is None: + echo_properties(equipment) + + +@filter.command("turn_on") +@click.pass_context +def turn_on(ctx: click.Context) -> None: + """Turn the filter on.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_on()) + click.echo(f"Turned on '{equipment.name}' (system_id={equipment.system_id})") + + +@filter.command("turn_off") +@click.pass_context +def turn_off(ctx: click.Context) -> None: + """Turn the filter off.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_off()) + click.echo(f"Turned off '{equipment.name}' (system_id={equipment.system_id})") + + +@filter.command("set_speed") +@click.argument("percent", type=int) +@click.pass_context +def set_speed(ctx: click.Context, percent: int) -> None: + """Set the filter speed (0-100 percent). + + Example: + omnilogic filter 3 set_speed 75 + """ + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.set_speed(percent)) + click.echo(f"Set '{equipment.name}' (system_id={equipment.system_id}) to {percent}%") diff --git a/pyomnilogic_local/cli/heater_cmd.py b/pyomnilogic_local/cli/heater_cmd.py new file mode 100644 index 0000000..bbc4017 --- /dev/null +++ b/pyomnilogic_local/cli/heater_cmd.py @@ -0,0 +1,84 @@ +# mypy: disable-error-code="misc" + +from __future__ import annotations + +import asyncio +from typing import TYPE_CHECKING + +import click + +from pyomnilogic_local.cli.utils import echo_properties + +if TYPE_CHECKING: + from pyomnilogic_local import OmniLogic + + +@click.group(invoke_without_command=True) +@click.argument("system_id", type=int) +@click.pass_context +def heater(ctx: click.Context, system_id: int) -> None: + """Interact with a heater by system ID. + + If no subcommand is given, displays all properties of the heater. + + Example: + omnilogic heater 4 + omnilogic heater 4 turn_on + omnilogic heater 4 set_temperature 82 + """ + omnilogic: OmniLogic = ctx.obj["OMNILOGIC"] + + equipment = omnilogic.all_heaters.get_by_id(system_id) + if equipment is None: + raise click.ClickException(f"No heater found with system_id {system_id}. Use 'omnilogic get heaters' to list available heaters.") + + ctx.obj["EQUIPMENT"] = equipment + + if ctx.invoked_subcommand is None: + echo_properties(equipment) + + +@heater.command("turn_on") +@click.pass_context +def turn_on(ctx: click.Context) -> None: + """Turn the heater on.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_on()) + click.echo(f"Turned on '{equipment.name}' (system_id={equipment.system_id})") + + +@heater.command("turn_off") +@click.pass_context +def turn_off(ctx: click.Context) -> None: + """Turn the heater off.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_off()) + click.echo(f"Turned off '{equipment.name}' (system_id={equipment.system_id})") + + +@heater.command("set_temperature") +@click.argument("temperature", type=int) +@click.pass_context +def set_temperature(ctx: click.Context, temperature: int) -> None: + """Set the heater target temperature (Fahrenheit). + + Example: + omnilogic heater 4 set_temperature 82 + """ + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.set_temperature(temperature)) + click.echo(f"Set '{equipment.name}' (system_id={equipment.system_id}) to {temperature}°F") + + +@heater.command("set_solar_temperature") +@click.argument("temperature", type=int) +@click.pass_context +def set_solar_temperature(ctx: click.Context, temperature: int) -> None: + """Set the solar heater target temperature (Fahrenheit). + + Example: + omnilogic heater 4 set_solar_temperature 90 + """ + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.set_solar_temperature(temperature)) + click.echo(f"Set solar temperature for '{equipment.name}' (system_id={equipment.system_id}) to {temperature}°F") diff --git a/pyomnilogic_local/cli/light_cmd.py b/pyomnilogic_local/cli/light_cmd.py new file mode 100644 index 0000000..5bf32d0 --- /dev/null +++ b/pyomnilogic_local/cli/light_cmd.py @@ -0,0 +1,55 @@ +# mypy: disable-error-code="misc" + +from __future__ import annotations + +import asyncio +from typing import TYPE_CHECKING + +import click + +from pyomnilogic_local.cli.utils import echo_properties + +if TYPE_CHECKING: + from pyomnilogic_local import OmniLogic + + +@click.group(invoke_without_command=True) +@click.argument("system_id", type=int) +@click.pass_context +def light(ctx: click.Context, system_id: int) -> None: + """Interact with a light by system ID. + + If no subcommand is given, displays all properties of the light. + + Example: + omnilogic light 5 turn_on + omnilogic light 5 turn_off + """ + omnilogic: OmniLogic = ctx.obj["OMNILOGIC"] + + equipment = omnilogic.all_lights.get_by_id(system_id) + if equipment is None: + raise click.ClickException(f"No light found with system_id {system_id}. Use 'omnilogic get lights' to list available lights.") + + ctx.obj["EQUIPMENT"] = equipment + + if ctx.invoked_subcommand is None: + echo_properties(equipment) + + +@light.command("turn_on") +@click.pass_context +def turn_on(ctx: click.Context) -> None: + """Turn the light on.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_on()) + click.echo(f"Turned on '{equipment.name}' (system_id={equipment.system_id})") + + +@light.command("turn_off") +@click.pass_context +def turn_off(ctx: click.Context) -> None: + """Turn the light off.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_off()) + click.echo(f"Turned off '{equipment.name}' (system_id={equipment.system_id})") diff --git a/pyomnilogic_local/cli/pump_cmd.py b/pyomnilogic_local/cli/pump_cmd.py new file mode 100644 index 0000000..be035e9 --- /dev/null +++ b/pyomnilogic_local/cli/pump_cmd.py @@ -0,0 +1,69 @@ +# mypy: disable-error-code="misc" + +from __future__ import annotations + +import asyncio +from typing import TYPE_CHECKING + +import click + +from pyomnilogic_local.cli.utils import echo_properties + +if TYPE_CHECKING: + from pyomnilogic_local import OmniLogic + + +@click.group(invoke_without_command=True) +@click.argument("system_id", type=int) +@click.pass_context +def pump(ctx: click.Context, system_id: int) -> None: + """Interact with a pump by system ID. + + If no subcommand is given, displays all properties of the pump. + + Example: + omnilogic pump 3 turn_on + omnilogic pump 3 set_speed 75 + """ + omnilogic: OmniLogic = ctx.obj["OMNILOGIC"] + + equipment = omnilogic.all_pumps.get_by_id(system_id) + if equipment is None: + raise click.ClickException(f"No pump found with system_id {system_id}. Use 'omnilogic get pumps' to list available pumps.") + + ctx.obj["EQUIPMENT"] = equipment + + if ctx.invoked_subcommand is None: + echo_properties(equipment) + + +@pump.command("turn_on") +@click.pass_context +def turn_on(ctx: click.Context) -> None: + """Turn the pump on.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_on()) + click.echo(f"Turned on '{equipment.name}' (system_id={equipment.system_id})") + + +@pump.command("turn_off") +@click.pass_context +def turn_off(ctx: click.Context) -> None: + """Turn the pump off.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_off()) + click.echo(f"Turned off '{equipment.name}' (system_id={equipment.system_id})") + + +@pump.command("set_speed") +@click.argument("percent", type=int) +@click.pass_context +def set_speed(ctx: click.Context, percent: int) -> None: + """Set the pump speed (0-100 percent). + + Example: + omnilogic pump 3 set_speed 75 + """ + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.set_speed(percent)) + click.echo(f"Set '{equipment.name}' (system_id={equipment.system_id}) to {percent}%") diff --git a/pyomnilogic_local/cli/relay_cmd.py b/pyomnilogic_local/cli/relay_cmd.py new file mode 100644 index 0000000..8ae5c69 --- /dev/null +++ b/pyomnilogic_local/cli/relay_cmd.py @@ -0,0 +1,55 @@ +# mypy: disable-error-code="misc" + +from __future__ import annotations + +import asyncio +from typing import TYPE_CHECKING + +import click + +from pyomnilogic_local.cli.utils import echo_properties + +if TYPE_CHECKING: + from pyomnilogic_local import OmniLogic + + +@click.group(invoke_without_command=True) +@click.argument("system_id", type=int) +@click.pass_context +def relay(ctx: click.Context, system_id: int) -> None: + """Interact with a relay by system ID. + + If no subcommand is given, displays all properties of the relay. + + Example: + omnilogic relay 6 turn_on + omnilogic relay 6 turn_off + """ + omnilogic: OmniLogic = ctx.obj["OMNILOGIC"] + + equipment = omnilogic.all_relays.get_by_id(system_id) + if equipment is None: + raise click.ClickException(f"No relay found with system_id {system_id}. Use 'omnilogic get relays' to list available relays.") + + ctx.obj["EQUIPMENT"] = equipment + + if ctx.invoked_subcommand is None: + echo_properties(equipment) + + +@relay.command("turn_on") +@click.pass_context +def turn_on(ctx: click.Context) -> None: + """Turn the relay on.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_on()) + click.echo(f"Turned on '{equipment.name}' (system_id={equipment.system_id})") + + +@relay.command("turn_off") +@click.pass_context +def turn_off(ctx: click.Context) -> None: + """Turn the relay off.""" + equipment = ctx.obj["EQUIPMENT"] + asyncio.run(equipment.turn_off()) + click.echo(f"Turned off '{equipment.name}' (system_id={equipment.system_id})")