Initial commit

This commit is contained in:
Correl Roush 2024-11-12 10:13:08 -05:00
commit e224438cf3
4 changed files with 141 additions and 0 deletions

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
.DS_Store
.idea
*.log
tmp/
__pycache__/
*.py[cod]
*.egg
build
htmlcov
poetry.lock

0
README.md Normal file
View file

106
ipowerswitch.py Normal file
View file

@ -0,0 +1,106 @@
import dataclasses
import enum
import logging
import typing
import requests
import requests.auth
import typer
import yarl
class SwitchStatus(str, enum.Enum):
ON = "ON"
OFF = "OFF"
@dataclasses.dataclass
class Switch:
address: str
user: str
password: str
def switch(
self,
switch_id: int,
outlet: int,
from_state: SwitchStatus | None = None,
) -> None:
url = yarl.URL(f"http://{self.address}").joinpath(
"cgi-bin",
f"iswitch{switch_id:02d}",
"irswitch.exe",
)
params = {
"CURRENT": f"{switch_id:02d}",
f"SW{outlet}.x": 1,
f"SW{outlet}.y": 1,
}
if from_state:
params[f"STATUS{outlet}"] = f"{from_state.value:3s}"
logging.info("Switching outlet: %s", params)
response = requests.post(
str(url),
auth=requests.auth.HTTPBasicAuth(self.user, self.password),
data=params,
allow_redirects=False,
)
print(response)
def switch_on(self, switch_id: int, outlet: int) -> None:
return self.switch(switch_id, outlet, from_state=SwitchStatus.OFF)
def switch_off(self, switch_id: int, outlet: int) -> None:
return self.switch(switch_id, outlet, from_state=SwitchStatus.ON)
app = typer.Typer()
SwitchIdArgument = typing.Annotated[int, typer.Argument(min=1, max=16)]
OutletArgument = typing.Annotated[int, typer.Argument(min=1, max=8)]
class SwitchAction(str, enum.Enum):
on = "on"
off = "off"
toggle = "toggle"
@app.command()
def switch(
context: typer.Context,
switch_id: SwitchIdArgument,
outlet: OutletArgument,
action: typing.Annotated[
SwitchAction, typer.Argument(case_sensitive=False)
] = SwitchAction.toggle,
) -> None:
switch: Switch = context.obj
match action:
case SwitchAction.on:
switch.switch_on(switch_id, outlet)
case SwitchAction.off:
switch.switch_off(switch_id, outlet)
case SwitchAction.toggle:
switch.switch(switch_id, outlet)
@app.callback()
def main(
context: typer.Context,
address: str,
user: str = "admin",
password: str = "admin",
) -> None:
logging.basicConfig(level=logging.INFO)
context.obj = Switch(
address=address,
user=user,
password=password,
)
if __name__ == "__main__":
app()

24
pyproject.toml Normal file
View file

@ -0,0 +1,24 @@
[tool.poetry]
name = "ipowerswitch"
version = "0.1.0"
description = ""
authors = ["Correl Roush <correl@gmail.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.12"
requests = "^2.32.3"
bs4 = "^0.0.2"
typer = "^0.13.0"
yarl = "^1.17.1"
[tool.poetry.group.dev.dependencies]
black = "^24.10.0"
types-requests = "^2.32.0.20241016"
[tool.poetry.scripts]
ips = "ipowerswitch:app"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"