diff --git a/adafruit_hue.py b/adafruit_hue.py index c51d41e..e6a3d39 100644 --- a/adafruit_hue.py +++ b/adafruit_hue.py @@ -29,6 +29,12 @@ from random import randint from simpleio import map_range +try: + from typing import Optional, List, Union, Sequence, Any + from circuitpython_typing.http import HTTPProtocol +except ImportError: + pass + __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Hue.git" @@ -38,7 +44,12 @@ class Bridge: HTTP Interface for interacting with a Philips Hue Bridge. """ - def __init__(self, wifi_manager, bridge_ip=None, username=None): + def __init__( + self, + wifi_manager: HTTPProtocol, + bridge_ip: Optional[str] = None, + username: Optional[str] = None, + ) -> None: """ Creates an instance of the Philips Hue Bridge Interface. :param wifi_manager wifi_manager: WiFiManager from ESPSPI_WiFiManager/ESPAT_WiFiManager @@ -51,11 +62,11 @@ def __init__(self, wifi_manager, bridge_ip=None, username=None): self._ip = bridge_ip self._username = username if bridge_ip and username is not None: - self._bridge_url = "http://{}/api".format(self._ip) + self._bridge_url = f"http://{self._ip}/api" self._username_url = self._bridge_url + "/" + self._username @staticmethod - def rgb_to_hsb(rgb): + def rgb_to_hsb(rgb: Sequence[int]) -> Sequence[int]: """Returns RGB values as a HSL tuple. :param list rgb: RGB Values """ @@ -89,7 +100,7 @@ def rgb_to_hsb(rgb): return round(hue), round(sat, 3), round(light, 2) # Hue Core API - def discover_bridge(self): + def discover_bridge(self) -> str: """Discovers Philips Hue Bridge IP from the hosted broker discovery service. Returns the bridge's IP address. """ @@ -105,16 +116,16 @@ def discover_bridge(self): ) from err self._ip = bridge_ip # set up hue bridge address path - self._bridge_url = "http://{}/api".format(self._ip) + self._bridge_url = f"http://{self._ip}/api" return self._ip - def register_username(self): + def register_username(self) -> str: """Attempts to register a Hue application username for use with your bridge. Provides a 30 second delay to press the link button on the bridge. Returns username or None. """ - self._bridge_url = "http://{}/api".format(self._ip) - data = {"devicetype": "CircuitPython#pyportal{0}".format(randint(0, 100))} + self._bridge_url = f"http://{self._ip}/api" + data = {"devicetype": f"CircuitPython#pyportal{randint(0, 100)}"} resp = self._wifi.post(self._bridge_url, json=data) connection_attempts = 1 username = None @@ -130,16 +141,17 @@ def register_username(self): return username # Lights API - def show_light_info(self, light_id): + def show_light_info(self, light_id: Union[int, str]) -> str: """Gets the attributes and state of a given light. - :param int light_id: Light identifier. + :param int|str light_id: Light identifier. """ - resp = self._get("{0}/lights/{1}".format(self._username_url, light_id)) + resp = self._get(f"{self._username_url}/lights/{light_id}") return resp - def set_light(self, light_id, **kwargs): + def set_light(self, light_id: Union[int, str], **kwargs) -> str: """Allows the user to turn the light on and off, modify the hue and effects. You can pass the following as valid kwargs into this method: + :param int|str light_id: Light identifier :param bool on: On/Off state of the light :param int bri: Brightness value of the light, 0-100% (1 to 254) :param int hue: Hue value to set the light, in degrees (0 to 360) (0 to 65535) @@ -147,34 +159,32 @@ def set_light(self, light_id, **kwargs): (more settings at: https://developers.meethue.com/develop/hue-api/lights-api/#set-light-state ) """ - resp = self._put( - "{0}/lights/{1}/state".format(self._username_url, light_id), kwargs - ) + resp = self._put(f"{self._username_url}/lights/{light_id}/state", kwargs) return resp - def toggle_light(self, light_id): + def toggle_light(self, light_id: Union[int, str]) -> str: """Gets and toggles the current state of a specified light. - :param int light_id: Light identifier. + :param int|str light_id: Light identifier. """ light_state = self.get_light(light_id) light_state = not light_state["state"]["on"] resp = self.set_light(light_id, on=light_state) return resp - def get_light(self, light_id): + def get_light(self, light_id: Union[int, str]) -> str: """Gets the attributes and state of a provided light. - :param int light_id: Light identifier. + :param int|str light_id: Light identifier. """ - resp = self._get("{0}/lights/{1}".format(self._username_url, light_id)) + resp = self._get(f"{self._username_url}/lights/{light_id}") return resp - def get_lights(self): + def get_lights(self) -> Any: """Returns all the light resources available for a bridge.""" resp = self._get(self._username_url + "/lights") return resp # Groups API - def create_group(self, lights, group_id): + def create_group(self, lights: List[Union[int, str]], group_id: str) -> Any: """Creates a new group containing the lights specified and optional name. :param list lights: List of light identifiers. :param str group_id: Optional group name. @@ -183,9 +193,9 @@ def create_group(self, lights, group_id): resp = self._post(self._username_url + "/groups", data) return resp - def set_group(self, group_id, **kwargs): + def set_group(self, group_id: Union[int, str], **kwargs) -> Any: """Allows the user to turn the light on and off, modify the hue and effects. - :param int group_id: Group identifier. + :param int|str group_id: Group identifier. You can pass the following as (optional) valid kwargs into this method: :param bool on: On/Off state of the light :param int bri: Brightness value of the light (1 to 254) @@ -194,31 +204,30 @@ def set_group(self, group_id, **kwargs): (more settings at https://developers.meethue.com/develop/hue-api/lights-api/#set-light-state ) """ - resp = self._put( - "{0}/groups/{1}/action".format(self._username_url, group_id), kwargs - ) + resp = self._put(f"{self._username_url}/groups/{group_id}/action", kwargs) return resp - def get_groups(self): + def get_groups(self) -> Any: """Returns all the light groups available for a bridge.""" resp = self._get(self._username_url + "/groups") return resp # Scene API - def set_scene(self, group_id, scene_id): + def set_scene(self, group_id: Union[int, str], scene_id: str) -> None: """Sets a group scene. + :param int|str group_id: the group identifier :param str scene: The scene identifier """ # To recall an existing scene, use the Groups API. self.set_group(group_id, scene=scene_id) - def get_scenes(self): + def get_scenes(self) -> Any: """Returns a list of all scenes currently stored in the bridge.""" resp = self._get(self._username_url + "/scenes") return resp # HTTP Helpers for the Hue API - def _post(self, path, data): + def _post(self, path: str, data: str) -> Any: """POST data :param str path: Formatted Hue API URL :param json data: JSON data to POST to the Hue API. @@ -228,7 +237,7 @@ def _post(self, path, data): resp.close() return resp_json - def _put(self, path, data): + def _put(self, path: str, data: str) -> Any: """PUT data :param str path: Formatted Hue API URL :param json data: JSON data to PUT to the Hue API. @@ -238,7 +247,7 @@ def _put(self, path, data): resp.close() return resp_json - def _get(self, path, data=None): + def _get(self, path: str, data: Optional[str] = None) -> Any: """GET data :param str path: Formatted Hue API URL :param json data: JSON data to GET from the Hue API. diff --git a/requirements.txt b/requirements.txt index f0cae8f..ac9cf14 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ Adafruit-Blinka adafruit-circuitpython-simpleio adafruit-circuitpython-esp32spi +adafruit-circuitpython-typing