Compare commits

..

2 commits

Author SHA1 Message Date
Correl Roush
9261f8af49 Add status command 2024-11-12 16:05:35 -05:00
Correl Roush
f72740d89a Remove switch toggle option
Toggling works for turning the switch off, but doesn't seem to work for
turning it back on.
2024-11-12 15:35:42 -05:00

View file

@ -1,17 +1,21 @@
import dataclasses import dataclasses
import enum import enum
import logging import logging
import re
import typing import typing
import bs4
import requests import requests
import requests.auth import requests.auth
import rich.console
import rich.table
import typer import typer
import yarl import yarl
class SwitchStatus(str, enum.Enum): class SwitchStatus(str, enum.Enum):
ON = "ON" on = "on"
OFF = "OFF" off = "off"
@dataclasses.dataclass @dataclasses.dataclass
@ -38,7 +42,7 @@ class Switch:
f"SW{outlet}.y": 1, f"SW{outlet}.y": 1,
} }
if from_state: if from_state:
params[f"STATUS{outlet}"] = f"{from_state.value:3s}" params[f"STATUS{outlet}"] = f"{from_state.value.upper():3s}"
logging.info("Switching outlet: %s", params) logging.info("Switching outlet: %s", params)
response = requests.post( response = requests.post(
@ -50,41 +54,63 @@ class Switch:
print(response) print(response)
def switch_on(self, switch_id: int, outlet: int) -> None: def switch_on(self, switch_id: int, outlet: int) -> None:
return self.switch(switch_id, outlet, from_state=SwitchStatus.OFF) return self.switch(switch_id, outlet, from_state=SwitchStatus.off)
def switch_off(self, switch_id: int, outlet: int) -> None: def switch_off(self, switch_id: int, outlet: int) -> None:
return self.switch(switch_id, outlet, from_state=SwitchStatus.ON) return self.switch(switch_id, outlet, from_state=SwitchStatus.on)
def switch_status(self, switch_id: int) -> dict[int, SwitchStatus]:
url = yarl.URL(f"http://{self.address}").joinpath(
f"iswitch{switch_id:02d}",
"index.htm",
)
response = requests.get(
str(url),
auth=requests.auth.HTTPBasicAuth(self.user, self.password),
)
soup = bs4.BeautifulSoup(response.content, features="html.parser")
inputs = {i["name"]: i["value"] for i in soup.find_all("input", type="hidden")}
outlets = int(inputs["OUTLET"])
return {
outlet: SwitchStatus[inputs.get(f"STATUS{outlet}", "off").strip().lower()]
for outlet in range(1, outlets + 1)
}
app = typer.Typer() app = typer.Typer()
console = rich.console.Console()
SwitchIdArgument = typing.Annotated[int, typer.Argument(min=1, max=16)] SwitchIdArgument = typing.Annotated[int, typer.Argument(min=1, max=16)]
OutletArgument = typing.Annotated[int, typer.Argument(min=1, max=8)] OutletArgument = typing.Annotated[int, typer.Argument(min=1, max=8)]
class SwitchAction(str, enum.Enum):
on = "on"
off = "off"
toggle = "toggle"
@app.command() @app.command()
def switch( def switch(
context: typer.Context, context: typer.Context,
switch_id: SwitchIdArgument, switch_id: SwitchIdArgument,
outlet: OutletArgument, outlet: OutletArgument,
action: typing.Annotated[ action: typing.Annotated[SwitchStatus, typer.Argument(case_sensitive=False)],
SwitchAction, typer.Argument(case_sensitive=False)
] = SwitchAction.toggle,
) -> None: ) -> None:
switch: Switch = context.obj switch: Switch = context.obj
match action: match action:
case SwitchAction.on: case SwitchStatus.on:
switch.switch_on(switch_id, outlet) switch.switch_on(switch_id, outlet)
case SwitchAction.off: case SwitchStatus.off:
switch.switch_off(switch_id, outlet) switch.switch_off(switch_id, outlet)
case SwitchAction.toggle:
switch.switch(switch_id, outlet)
@app.command()
def status(context: typer.Context, switch_id: SwitchIdArgument) -> None:
switch: Switch = context.obj
statuses = switch.switch_status(switch_id)
if not console.is_interactive:
for key in sorted(statuses.keys()):
console.print(f"{key}\t{statuses[key].value.upper()}")
else:
table = rich.table.Table("Outlet", "Status")
for key in sorted(statuses.keys()):
table.add_row(str(key), statuses[key].value.upper())
console.print(table)
@app.callback() @app.callback()