From 66541220bf556234eaf70d03864182dab8175878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller=20=28ChaoticByte=29?= Date: Fri, 21 Jul 2023 22:35:31 +0200 Subject: [PATCH] Created a documentation and updated the README --- DOCUMENTATION.md | 354 +++++++++++++++++++++++++++++++++++++++++ README.md | 28 ++++ pydoc-markdown.yml | 9 ++ yahuelib/controller.py | 72 +++++++-- yahuelib/exceptions.py | 2 + yahuelib/utils.py | 3 +- 6 files changed, 451 insertions(+), 17 deletions(-) create mode 100644 DOCUMENTATION.md create mode 100644 pydoc-markdown.yml diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 0000000..aa521fa --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,354 @@ +# Table of Contents + +* [yahuelib](#yahuelib) +* [yahuelib.utils](#yahuelib.utils) + * [rgb\_to\_hsv](#yahuelib.utils.rgb_to_hsv) +* [yahuelib.controller](#yahuelib.controller) + * [LightController](#yahuelib.controller.LightController) + * [reachable](#yahuelib.controller.LightController.reachable) + * [on](#yahuelib.controller.LightController.on) + * [on](#yahuelib.controller.LightController.on) + * [brightness](#yahuelib.controller.LightController.brightness) + * [brightness](#yahuelib.controller.LightController.brightness) + * [hue](#yahuelib.controller.LightController.hue) + * [hue](#yahuelib.controller.LightController.hue) + * [saturation](#yahuelib.controller.LightController.saturation) + * [saturation](#yahuelib.controller.LightController.saturation) + * [alert](#yahuelib.controller.LightController.alert) + * [alert\_long](#yahuelib.controller.LightController.alert_long) + * [GroupController](#yahuelib.controller.GroupController) + * [any\_on](#yahuelib.controller.GroupController.any_on) + * [all\_on](#yahuelib.controller.GroupController.all_on) + * [all\_on](#yahuelib.controller.GroupController.all_on) + * [brightness](#yahuelib.controller.GroupController.brightness) + * [brightness](#yahuelib.controller.GroupController.brightness) + * [hue](#yahuelib.controller.GroupController.hue) + * [hue](#yahuelib.controller.GroupController.hue) + * [saturation](#yahuelib.controller.GroupController.saturation) + * [saturation](#yahuelib.controller.GroupController.saturation) + * [alert](#yahuelib.controller.GroupController.alert) + * [alert\_long](#yahuelib.controller.GroupController.alert_long) +* [yahuelib.exceptions](#yahuelib.exceptions) + * [LightOrGroupNotFound](#yahuelib.exceptions.LightOrGroupNotFound) + * [APIError](#yahuelib.exceptions.APIError) + + + +# yahuelib + + + +# yahuelib.utils + + + +#### rgb\_to\_hsv + +```python +def rgb_to_hsv(r: int, g: int, b: int) -> tuple +``` + +Convert RGB colors `(255, 220, 100)` to HSV `(0.129, 0.608, 1.0)` + + + +# yahuelib.controller + + + +## LightController Objects + +```python +class LightController(_BaseController) +``` + +Control a Philips Hue Light using the API of your Hue Bridge. + +**Arguments**: + + - `number: int` - The number of your light + - `bridge_ip_address: str` - The IP address of your Hue Bridge + - `bridge_api_user: str` - The user used to authenticate to the API + + Use the class method `.from_name(name:str, ...)` to use the name of a light instead of the number. + + + +#### reachable + +```python +@property +def reachable() -> bool +``` + +Check if the light is reachable using `LightController.reachable` + + + +#### on + +```python +@property +def on() -> bool +``` + +Check if the light is on using `LightController.on` + + + +#### on + +```python +@on.setter +def on(on: bool) +``` + +Turn the light on/off using `LightController.on = ...` + + + +#### brightness + +```python +@property +def brightness() -> int +``` + +Get the brightness using `LightController.brightness` + + + +#### brightness + +```python +@brightness.setter +def brightness(brightness: float) +``` + +Set the brightness using `LightController.brightness = ...` + + + +#### hue + +```python +@property +def hue() -> int +``` + +Get the hue using `LightController.hue` + + + +#### hue + +```python +@hue.setter +def hue(hue: float) +``` + +Set the hue using `LightController.hue = ...` + + + +#### saturation + +```python +@property +def saturation() -> int +``` + +Get the saturation using `LightController.saturation` + + + +#### saturation + +```python +@saturation.setter +def saturation(saturation: float) +``` + +Set the saturation using `LightController.saturation = ...` + + + +#### alert + +```python +def alert() +``` + +Flash the light once. + + + +#### alert\_long + +```python +def alert_long() +``` + +Flash the light for 10 seconds. + + + +## GroupController Objects + +```python +class GroupController(_BaseController) +``` + +Control a Philips Hue Light Group (Room/Zone) using the API of your Hue Bridge. + +**Arguments**: + + - `number: int` - The number of your light group + - `bridge_ip_address: str` - The IP address of your Hue Bridge + - `bridge_api_user: str` - The user used to authenticate to the API + + Use the class method `.from_name(name:str, ...)` to use the name of a group instead of the number. + + + +#### any\_on + +```python +@property +def any_on() -> bool +``` + +Check if any light in this group is on using `GroupController.any_on` + + + +#### all\_on + +```python +@property +def all_on() -> bool +``` + +Check if all lights in this group are on using `GroupController.all_on` + + + +#### all\_on + +```python +@all_on.setter +def all_on(on: bool) +``` + +Turn on/off all lights in this group using `GroupController.all_on = ...` + + + +#### brightness + +```python +@property +def brightness() -> int +``` + +Get the last set brightness in this group using `GroupController.brightness` + + + +#### brightness + +```python +@brightness.setter +def brightness(brightness: float) +``` + +Set the brightness of all lights in this group using `GroupController.brightness = ...` + + + +#### hue + +```python +@property +def hue() -> int +``` + +Get the last set hue in this group using `GroupController.hue` + + + +#### hue + +```python +@hue.setter +def hue(hue: float) +``` + +Set the hue of all lights in this group using `GroupController.hue = ...` + + + +#### saturation + +```python +@property +def saturation() -> int +``` + +Get the last set saturation in this group using `GroupController.saturation` + + + +#### saturation + +```python +@saturation.setter +def saturation(saturation: float) +``` + +Set the saturation of all lights in this group using `GroupController.saturation = ...` + + + +#### alert + +```python +def alert() +``` + +Flash all lights in the group once. + + + +#### alert\_long + +```python +def alert_long() +``` + +Flash all lights in the group for 10 seconds. + + + +# yahuelib.exceptions + + + +## LightOrGroupNotFound Objects + +```python +class LightOrGroupNotFound(Exception) +``` + +`LightOrGroupNotFound` Exception + + + +## APIError Objects + +```python +class APIError(Exception) +``` + +Generic `APIError` Exception + diff --git a/README.md b/README.md index aad3c82..abf0d97 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,31 @@ # YaHue Lib Yet Another Philips Hue API Library for Python. This project only implements a subset of the API. + +## Getting Started + +Before you can use the API of your Hue Bridge, you have to create an API user for it. +See https://developers.meethue.com/develop/get-started-2/ + +## Supported Features + +- 💡 Lights + - reachable + - on + - brightness + - hue + - saturation + - alert + - alert_long +- 🏠 Groups (Zones and Rooms) + - any_on + - all_on + - brightness + - hue + - saturation + - alert + - alert_long + +## Documentation + +see [DOCUMENTATION.md](DOCUMENTATION.md) diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml new file mode 100644 index 0000000..8d2bcc7 --- /dev/null +++ b/pydoc-markdown.yml @@ -0,0 +1,9 @@ +loaders: + - type: python +processors: + - type: filter + - type: smart + - type: crossref +renderer: + type: markdown + render_toc: true diff --git a/yahuelib/controller.py b/yahuelib/controller.py index e7d9cbe..e3cd0fb 100644 --- a/yahuelib/controller.py +++ b/yahuelib/controller.py @@ -63,120 +63,160 @@ class _BaseController: class LightController(_BaseController): + '''Control a Philips Hue Light using the API of your Hue Bridge. + + Args: + - `number: int` - The number of your light + - `bridge_ip_address: str` - The IP address of your Hue Bridge + - `bridge_api_user: str` - The user used to authenticate to the API + + Use the class method `.from_name(name:str, ...)` to use the name of a light instead of the number. + ''' _api_endpoint_all = "https://{bridge_ip_address}/api/{bridge_api_user}/lights" _api_endpoint_specific = "https://{bridge_ip_address}/api/{bridge_api_user}/lights/{number}" @property def reachable(self) -> bool: + '''Check if the light is reachable using `LightController.reachable`''' data = self._api_request() return data["state"]["reachable"] @property def on(self) -> bool: + '''Check if the light is on using `LightController.on`''' data = self._api_request() return data["state"]["on"] @on.setter def on(self, on:bool): + '''Turn the light on/off using `LightController.on = ...`''' assert type(on) == bool self._api_request("PUT", "/state", {"on": on}) - + @property - def brightness(self): + def brightness(self) -> int: + '''Get the brightness using `LightController.brightness`''' data = self._api_request() return data["state"]["bri"] - + @brightness.setter def brightness(self, brightness:float): + '''Set the brightness using `LightController.brightness = ...`''' assert type(brightness) == float or type(brightness) == int bri_ = min(max(int(brightness * 254), 0), 254) self._api_request("PUT", "/state", {"bri": bri_}) - + @property - def hue(self): + def hue(self) -> int: + '''Get the hue using `LightController.hue`''' data = self._api_request() return data["state"]["hue"] - + @hue.setter def hue(self, hue:float): + '''Set the hue using `LightController.hue = ...`''' assert type(hue) == float or type(hue) == int hue_ = min(max(int(hue * 65535), 0), 65535) self._api_request("PUT", "/state", {"hue": hue_}) @property - def saturation(self): + def saturation(self) -> int: + '''Get the saturation using `LightController.saturation`''' data = self._api_request() return data["state"]["sat"] - + @saturation.setter def saturation(self, saturation:float): + '''Set the saturation using `LightController.saturation = ...`''' assert type(saturation) == float or type(saturation) == int sat_ = min(max(int(saturation * 254), 0), 254) self._api_request("PUT", "/state", {"sat": sat_}) - + def alert(self): + '''Flash the light once.''' self._api_request("PUT", "/state", {"alert": "select"}) def alert_long(self): + '''Flash the light for 10 seconds.''' self._api_request("PUT", "/state", {"alert": "lselect"}) class GroupController(_BaseController): + '''Control a Philips Hue Light Group (Room/Zone) using the API of your Hue Bridge. + + Args: + - `number: int` - The number of your light group + - `bridge_ip_address: str` - The IP address of your Hue Bridge + - `bridge_api_user: str` - The user used to authenticate to the API + + Use the class method `.from_name(name:str, ...)` to use the name of a group instead of the number. + ''' _api_endpoint_all = "https://{bridge_ip_address}/api/{bridge_api_user}/groups" _api_endpoint_specific = "https://{bridge_ip_address}/api/{bridge_api_user}/groups/{number}" @property def any_on(self) -> bool: + '''Check if any light in this group is on using `GroupController.any_on`''' data = self._api_request() return data["state"]["any_on"] @property def all_on(self) -> bool: + '''Check if all lights in this group are on using `GroupController.all_on`''' data = self._api_request() return data["state"]["all_on"] @all_on.setter def all_on(self, on:bool): + '''Turn on/off all lights in this group using `GroupController.all_on = ...`''' assert type(on) == bool self._api_request("PUT", "/action", {"on": on}) @property - def brightness(self): + def brightness(self) -> int: + '''Get the last set brightness in this group using `GroupController.brightness`''' data = self._api_request() return data["action"]["bri"] - + @brightness.setter def brightness(self, brightness:float): + '''Set the brightness of all lights in this group using `GroupController.brightness = ...`''' assert type(brightness) == float or type(brightness) == int bri_ = min(max(int(brightness * 254), 0), 254) self._api_request("PUT", "/action", {"bri": bri_}) @property - def hue(self): + def hue(self) -> int: + '''Get the last set hue in this group using `GroupController.hue`''' data = self._api_request() return data["action"]["hue"] - + @hue.setter def hue(self, hue:float): + '''Set the hue of all lights in this group using `GroupController.hue = ...`''' assert type(hue) == float or type(hue) == int hue_ = min(max(int(hue * 65535), 0), 65535) self._api_request("PUT", "/action", {"hue": hue_}) @property - def saturation(self): + def saturation(self) -> int: + '''Get the last set saturation in this group using `GroupController.saturation`''' data = self._api_request() return data["action"]["sat"] - + @saturation.setter def saturation(self, saturation:float): + '''Set the saturation of all lights in this group using `GroupController.saturation = ...`''' assert type(saturation) == float or type(saturation) == int sat_ = min(max(int(saturation * 254), 0), 254) self._api_request("PUT", "/action", {"sat": sat_}) - + def alert(self): + '''Flash all lights in the group once.''' self._api_request("PUT", "/action", {"alert": "select"}) def alert_long(self): + '''Flash all lights in the group for 10 seconds.''' self._api_request("PUT", "/action", {"alert": "lselect"}) diff --git a/yahuelib/exceptions.py b/yahuelib/exceptions.py index a977f7d..00184fb 100644 --- a/yahuelib/exceptions.py +++ b/yahuelib/exceptions.py @@ -1,7 +1,9 @@ # Copyright (c) 2023 Julian Müller (ChaoticByte) class LightOrGroupNotFound(Exception): + '''`LightOrGroupNotFound` Exception''' pass class APIError(Exception): + '''Generic `APIError` Exception''' pass diff --git a/yahuelib/utils.py b/yahuelib/utils.py index a588dec..8d300db 100644 --- a/yahuelib/utils.py +++ b/yahuelib/utils.py @@ -4,7 +4,8 @@ from colorsys import rgb_to_hsv as _rgb_to_hsv -def rgb_to_hsv(r:int, g:int, b:int) -> float: +def rgb_to_hsv(r:int, g:int, b:int) -> tuple: + '''Convert RGB colors `(255, 220, 100)` to HSV `(0.129, 0.608, 1.0)`''' assert type(r) == int assert type(g) == int assert type(b) == int