from typing import Optional import aiohttp from flickerstrip_py.models.pattern import Pattern, PatternData from flickerstrip_py.models.status import Status class Api: def __init__(self, host: str, port: Optional[int] = None) -> None: self.url = f"http://{host}:{port or 80}" self.client = aiohttp.ClientSession(self.url) async def __aenter__(self): return self async def __aexit__(self, *args): await self.close() async def close(self): """ Close the API client. """ await self.client.close() async def status(self) -> Status: """ Get the status of the flickerstrip. """ async with self.client.get("status") as resp: return Status.from_json(await resp.json()) async def power_on(self) -> None: """ Power on the flickerstrip. """ async with self.client.get("power/on") as resp: resp.raise_for_status() async def power_off(self) -> None: """ Power off the flickerstrip. """ async with self.client.get("power/off") as resp: resp.raise_for_status() async def power_toggle(self) -> None: """ Toggle the power of the flickerstrip. """ async with self.client.get("power/toggle") as resp: resp.raise_for_status() async def next_pattern(self) -> None: """ Switch to the next pattern. """ async with self.client.get("pattern/next") as resp: resp.raise_for_status() async def freeze_frame(self, frame: int) -> None: """ Freeze the animation at the specified frame. """ async with self.client.get("pattern/freeze", params={"value": frame}) as resp: resp.raise_for_status() async def download_pattern(self, id: int) -> PatternData: """ Download the pattern with the specified ID. """ async with self.client.get("pattern/download", params={"id": id}) as resp: return PatternData( data=await resp.read(), ) async def select_pattern_by_id(self, id: int) -> None: """ Select the pattern with the specified ID. """ async with self.client.get("pattern/select", params={"id": id}) as resp: resp.raise_for_status() async def select_pattern_by_index(self, index: int) -> None: """ Select the pattern with the specified index. """ async with self.client.get("pattern/select", params={"index": index}) as resp: resp.raise_for_status() async def delete_pattern_by_index(self, index: int) -> None: """ Delete the pattern with the specified index. """ async with self.client.get("pattern/delete", params={"index": index}) as resp: resp.raise_for_status() async def delete_pattern_by_id(self, id: int) -> None: """ Delete the pattern with the specified ID. """ async with self.client.get("pattern/delete", params={"id": id}) as resp: resp.raise_for_status() async def create_pattern( self, pattern: Pattern, data: PatternData, preview: bool = False ) -> None: """ Create a new pattern. Args: pattern (Pattern): The pattern to create. data (PatternData): The data of the pattern. preview (bool): Whether to only preview the pattern. This is useful for testing purposes. Defaults to False. """ async with self.client.post( "pattern/create", params={ "name": pattern.name, "fps": str(pattern.fps), "frames": str(pattern.frames), "pixels": str(pattern.pixels), "preview": str(1 if preview else 0), }, data=data.data, ) as resp: resp.raise_for_status() async def preview_pattern(self, pattern: Pattern, data: PatternData) -> None: """ Preview a new pattern. Args: pattern (Pattern): The pattern to preview. data (PatternData): The data of the pattern. """ await self.create_pattern(pattern, data, preview=True) async def set_brightness(self, brightness: int) -> None: """Set the brightness of the flickerstrip. Args: value (int): The brightness level as an int from 0 to 100. """ async with self.client.get( "brightness", params={"value": str(brightness)} ) as resp: resp.raise_for_status() async def set_name(self, name: str) -> None: """Set the name of the flickerstrip. Args: value (string): The new name. """ async with self.client.post("config/name", params={"name": str(name)}) as resp: resp.raise_for_status() async def set_group(self, name: str) -> None: """Set the group of the flickerstrip. Args: value (string): The new group. """ async with self.client.post("config/group", params={"name": str(name)}) as resp: resp.raise_for_status() async def set_cycle(self, value: int) -> None: """Set the cycle timer of the flickerstrip. Args: value (int): How long to cycle to next pattern. Value is handled in seconds. """ async with self.client.get( "config/cycle", params={"value": str(value)} ) as resp: resp.raise_for_status() async def set_fade(self, value: int) -> None: """Set the fade duration of the flickerstrip. Args: value (int): How long to fade between patterns. Value is handled in seconds. """ async with self.client.get("config/fade", params={"value": str(value)}) as resp: resp.raise_for_status() async def set_length(self, value: int) -> None: """Set the length of the strip. Args: value (int): How long the strip is. Value is handled in pixels. """ async with self.client.get( "config/length", params={"value": str(value)} ) as resp: resp.raise_for_status() async def set_start(self, value: int) -> None: """Set the start of the strip. This will make the flickerstrip ignore all pixels before the given number, set to 0 for the first pixel. Args: value (int): Where the strip starts. Value is handled in pixels. """ async with self.client.get( "config/start", params={"value": str(value)} ) as resp: resp.raise_for_status() async def set_end(self, value: int) -> None: """Set the end of the strip. This will make the flickerstrip ignore all pixels after the given number, set to 0 for the last pixel. Args: value (int): Where the strip ends. Value is handled in pixels. """ async with self.client.get("config/end", params={"value": str(value)}) as resp: resp.raise_for_status() async def set_reversed(self, value: bool) -> None: """Set the reversed state of the strip. Args: value (bool): Whether the strip is reversed. """ async with self.client.get( "config/reversed", params={"value": str(1 if value else 0)} ) as resp: resp.raise_for_status()