diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 1e1fa21..fcab5d4 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -30,11 +30,22 @@ * [set\_color\_temperature](#yahuelib.controller.GroupController.set_color_temperature) * [alert](#yahuelib.controller.GroupController.alert) * [alert\_long](#yahuelib.controller.GroupController.alert_long) + * [MotionSensor](#yahuelib.controller.MotionSensor) + * [check\_on](#yahuelib.controller.MotionSensor.check_on) + * [set\_on](#yahuelib.controller.MotionSensor.set_on) + * [check\_reachable](#yahuelib.controller.MotionSensor.check_reachable) + * [get\_battery](#yahuelib.controller.MotionSensor.get_battery) + * [get\_sensitivity](#yahuelib.controller.MotionSensor.get_sensitivity) + * [set\_sensitivity](#yahuelib.controller.MotionSensor.set_sensitivity) + * [get\_sensitivitymax](#yahuelib.controller.MotionSensor.get_sensitivitymax) + * [get\_ledindication](#yahuelib.controller.MotionSensor.get_ledindication) + * [set\_ledindication](#yahuelib.controller.MotionSensor.set_ledindication) + * [get\_presence](#yahuelib.controller.MotionSensor.get_presence) * [yahuelib.utils](#yahuelib.utils) * [rgb\_to\_hsv](#yahuelib.utils.rgb_to_hsv) * [kelvin\_to\_mired](#yahuelib.utils.kelvin_to_mired) * [yahuelib.exceptions](#yahuelib.exceptions) - * [LightOrGroupNotFound](#yahuelib.exceptions.LightOrGroupNotFound) + * [DeviceNotFound](#yahuelib.exceptions.DeviceNotFound) * [APIError](#yahuelib.exceptions.APIError) @@ -108,10 +119,10 @@ Get the brightness #### set\_brightness ```python -def set_brightness(brightness: float) +def set_brightness(brightness: int) ``` -Set the brightness +Set the brightness (`0` - `254`) @@ -128,10 +139,10 @@ Get the hue #### set\_hue ```python -def set_hue(hue: float) +def set_hue(hue: int) ``` -Set the hue +Set the hue (0 - 65535) @@ -148,17 +159,17 @@ Get the saturation #### set\_saturation ```python -def set_saturation(saturation: float) +def set_saturation(saturation: int) ``` -Set the saturation +Set the saturation (`0` - `254`) #### get\_color\_temperature ```python -def get_color_temperature() +def get_color_temperature() -> int ``` Get the white color temperature in Mired @@ -246,7 +257,7 @@ Turn on/off all lights in this group #### get\_brightness ```python -def get_brightness() -> int +def get_brightness() ``` Get the last set brightness in this group @@ -256,10 +267,10 @@ Get the last set brightness in this group #### set\_brightness ```python -def set_brightness(brightness: float) +def set_brightness(brightness: int) ``` -Set the brightness of all lights in this group +Set the brightness (`0` - `254`) of all lights in this group @@ -276,10 +287,10 @@ Get the last set hue in this group #### set\_hue ```python -def set_hue(hue: float) +def set_hue(hue: int) ``` -Set the hue of all lights in this group +Set the hue (`0` - `65535`) of all lights in this group @@ -296,17 +307,17 @@ Get the last set saturation in this group #### set\_saturation ```python -def set_saturation(saturation: float) +def set_saturation(saturation: int) ``` -Set the saturation of all lights in this group +Set the saturation (`0` - `254`) of all lights in this group #### get\_color\_temperature ```python -def get_color_temperature() +def get_color_temperature() -> int ``` Get the last set white color temperature in Mired @@ -341,6 +352,114 @@ def alert_long() Flash all lights in the group for 10 seconds. + + +## MotionSensor Objects + +```python +class MotionSensor(_BaseController) +``` + + + +#### check\_on + +```python +def check_on() -> bool +``` + +Check if the sensor is on + + + +#### set\_on + +```python +def set_on(on: bool) +``` + +Turn the sensor on/off + + + +#### check\_reachable + +```python +def check_reachable() -> bool +``` + +Check if the sensor is reachable + + + +#### get\_battery + +```python +def get_battery() -> int +``` + +Get the current charge of the battery in percent + + + +#### get\_sensitivity + +```python +def get_sensitivity() -> int +``` + +Get the sensitivity of the sensor + + + +#### set\_sensitivity + +```python +def set_sensitivity(sensitivity: int) +``` + +Set the sensitivity of the sensor + + + +#### get\_sensitivitymax + +```python +def get_sensitivitymax() -> int +``` + +Get the maximum sensititvity of the sensor + + + +#### get\_ledindication + +```python +def get_ledindication() -> bool +``` + +Get the maximum sensititvity of the sensor + + + +#### set\_ledindication + +```python +def set_ledindication(on: bool) +``` + +Turn the LED indicator on/off + + + +#### get\_presence + +```python +def get_presence() -> bool +``` + +Check if the motion sensor detected the presence of someone in it's reach + # yahuelib.utils @@ -353,7 +472,7 @@ Flash all lights in the group for 10 seconds. 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)` +Convert RGB colors `(255, 220, 100)` to Philips Hue's hue, saturation and brightness values `(8456, 149, 245)` imprecisely @@ -369,15 +488,15 @@ Convert the color temperature from Kelvin to Mired # yahuelib.exceptions - + -## LightOrGroupNotFound Objects +## DeviceNotFound Objects ```python -class LightOrGroupNotFound(Exception) +class DeviceNotFound(Exception) ``` -`LightOrGroupNotFound` Exception +`DeviceNotFound` Exception diff --git a/README.md b/README.md index 2d476cf..e2c2cdf 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,14 @@ See https://developers.meethue.com/develop/get-started-2/ - white color temperature - alert - alert_long +- 👋 Motion Sensors + - reachable + - on + - battery + - sensitivity + - sensitivitymax + - ledindication + - presence ## Documentation @@ -48,6 +56,6 @@ if __name__ == "__main__": color = rgb_to_hsv(255, 220, 100) home.set_hue(color[0]) home.set_saturation(color[1]) - home.set_brightness(1.0) + home.set_brightness(254) home.alert() ``` diff --git a/yahuelib/controller.py b/yahuelib/controller.py index 044014e..e899053 100644 --- a/yahuelib/controller.py +++ b/yahuelib/controller.py @@ -40,7 +40,7 @@ class _BaseController: for n in data: if data[n]["name"] == name: return cls(int(n), bridge_ip_address, bridge_api_user) - raise LightOrGroupNotFound() + raise DeviceNotFound() def _api_request(self, method="GET", path:str="", data:dict={}): assert type(method) == str @@ -78,13 +78,13 @@ class LightController(_BaseController): def check_reachable(self) -> bool: '''Check if the light is reachable''' - data = self._api_request() - return data["state"]["reachable"] + data = self._api_request()["state"]["reachable"] + return data def check_on(self) -> bool: '''Check if the light is on''' - data = self._api_request() - return data["state"]["on"] + data = self._api_request()["state"]["on"] + return data def set_on(self, on:bool): '''Turn the light on/off''' @@ -93,41 +93,41 @@ class LightController(_BaseController): def get_brightness(self) -> int: '''Get the brightness''' - data = self._api_request() - return data["state"]["bri"] + data = self._api_request()["state"]["bri"] + return data - def set_brightness(self, brightness:float): - '''Set the brightness''' - assert type(brightness) == float or type(brightness) == int - bri_ = min(max(int(brightness * 254), 0), 254) + def set_brightness(self, brightness:int): + '''Set the brightness (`0` - `254`)''' + assert type(brightness) == int + bri_ = min(max(brightness, 0), 254) self._api_request("PUT", "/state", {"bri": bri_}) def get_hue(self) -> int: '''Get the hue''' - data = self._api_request() - return data["state"]["hue"] + data = self._api_request()["state"]["hue"] + return data - def set_hue(self, hue:float): - '''Set the hue''' - assert type(hue) == float or type(hue) == int - hue_ = min(max(int(hue * 65535), 0), 65535) + def set_hue(self, hue:int): + '''Set the hue (0 - 65535)''' + assert type(hue) == int + hue_ = min(max(hue, 0), 65535) self._api_request("PUT", "/state", {"hue": hue_}) def get_saturation(self) -> int: '''Get the saturation''' - data = self._api_request() - return data["state"]["sat"] + data = self._api_request()["state"]["sat"] + return data - def set_saturation(self, saturation:float): - '''Set the saturation''' - assert type(saturation) == float or type(saturation) == int - sat_ = min(max(int(saturation * 254), 0), 254) + def set_saturation(self, saturation:int): + '''Set the saturation (`0` - `254`)''' + assert type(saturation) == int + sat_ = min(max(saturation, 0), 254) self._api_request("PUT", "/state", {"sat": sat_}) - def get_color_temperature(self): + def get_color_temperature(self) -> int: '''Get the white color temperature in Mired''' - data = self._api_request() - return data["state"]["ct"] + data = self._api_request()["state"]["ct"] + return data def set_color_temperature(self, mired:int): '''Set the white color temperature in Mired (`154` - `500`)''' @@ -160,56 +160,56 @@ class GroupController(_BaseController): def check_any_on(self) -> bool: '''Check if any light in this group is on''' - data = self._api_request() - return data["state"]["any_on"] + data = self._api_request()["state"]["any_on"] + return data def check_all_on(self) -> bool: '''Check if all lights in this group are on''' - data = self._api_request() - return data["state"]["all_on"] + data = self._api_request()["state"]["all_on"] + return data def set_all_on(self, on:bool): '''Turn on/off all lights in this group''' assert type(on) == bool self._api_request("PUT", "/action", {"on": on}) - def get_brightness(self) -> int: + def get_brightness(self): '''Get the last set brightness in this group''' - data = self._api_request() - return data["action"]["bri"] + data = self._api_request()["action"]["bri"] + return data - def set_brightness(self, brightness:float): - '''Set the brightness of all lights in this group''' - assert type(brightness) == float or type(brightness) == int - bri_ = min(max(int(brightness * 254), 0), 254) + def set_brightness(self, brightness:int): + '''Set the brightness (`0` - `254`) of all lights in this group''' + assert type(brightness) == int + bri_ = min(max(brightness, 0), 254) self._api_request("PUT", "/action", {"bri": bri_}) def get_hue(self) -> int: '''Get the last set hue in this group''' - data = self._api_request() - return data["action"]["hue"] + data = self._api_request()["action"]["hue"] + return data - def set_hue(self, hue:float): - '''Set the hue of all lights in this group''' - assert type(hue) == float or type(hue) == int - hue_ = min(max(int(hue * 65535), 0), 65535) + def set_hue(self, hue:int): + '''Set the hue (`0` - `65535`) of all lights in this group''' + assert type(hue) == int + hue_ = min(max(hue, 0), 65535) self._api_request("PUT", "/action", {"hue": hue_}) def get_saturation(self) -> int: '''Get the last set saturation in this group''' - data = self._api_request() - return data["action"]["sat"] + data = self._api_request()["action"]["sat"] + return data - def set_saturation(self, saturation:float): - '''Set the saturation of all lights in this group''' - assert type(saturation) == float or type(saturation) == int - sat_ = min(max(int(saturation * 254), 0), 254) + def set_saturation(self, saturation:int): + '''Set the saturation (`0` - `254`) of all lights in this group''' + assert type(saturation) == int + sat_ = min(max(saturation, 0), 254) self._api_request("PUT", "/action", {"sat": sat_}) - def get_color_temperature(self): + def get_color_temperature(self) -> int: '''Get the last set white color temperature in Mired''' - data = self._api_request() - return data["action"]["ct"] + data = self._api_request()["action"]["ct"] + return data def set_color_temperature(self, mired:int): '''Set the white color temperature in Mired (`154` - `500`) for all lights in this group''' @@ -224,3 +224,60 @@ class GroupController(_BaseController): def alert_long(self): '''Flash all lights in the group for 10 seconds.''' self._api_request("PUT", "/action", {"alert": "lselect"}) + + +class MotionSensor(_BaseController): + + _api_endpoint_all = "https://{bridge_ip_address}/api/{bridge_api_user}/sensors" + _api_endpoint_specific = "https://{bridge_ip_address}/api/{bridge_api_user}/sensors/{number}" + + def check_on(self) -> bool: + '''Check if the sensor is on''' + data = self._api_request()["config"]["on"] + return data + + def set_on(self, on:bool): + '''Turn the sensor on/off''' + assert type(on) == bool + self._api_request("PUT", "/config", {"on": on}) + + def check_reachable(self) -> bool: + '''Check if the sensor is reachable''' + data = self._api_request()["config"]["reachable"] + return data + + def get_battery(self) -> int: + '''Get the current charge of the battery in percent''' + data = self._api_request() + return data["config"]["battery"] + + def get_sensitivity(self) -> int: + '''Get the sensitivity of the sensor''' + data = self._api_request()["config"]["sensitivity"] + return data + + def set_sensitivity(self, sensitivity:int): + '''Set the sensitivity of the sensor''' + assert type(sensitivity) == int + sensitivity_ = min(max(sensitivity, 0), int(self.get_sensitivitymax())) + self._api_request("PUT", "/config", {"sensitivity": sensitivity_}) + + def get_sensitivitymax(self) -> int: + '''Get the maximum sensititvity of the sensor''' + data = self._api_request()["config"]["sensitivitymax"] + return data + + def get_ledindication(self) -> bool: + '''Get the maximum sensititvity of the sensor''' + data = self._api_request()["config"]["ledindication"] + return data + + def set_ledindication(self, on:bool): + '''Turn the LED indicator on/off''' + assert type(on) == bool + self._api_request("PUT", "/config", {"ledindication": on}) + + def get_presence(self) -> bool: + '''Check if the motion sensor detected the presence of someone in it's reach''' + data = self._api_request()["state"]["presence"] + return data diff --git a/yahuelib/exceptions.py b/yahuelib/exceptions.py index 00184fb..56617e8 100644 --- a/yahuelib/exceptions.py +++ b/yahuelib/exceptions.py @@ -1,7 +1,7 @@ # Copyright (c) 2023 Julian Müller (ChaoticByte) -class LightOrGroupNotFound(Exception): - '''`LightOrGroupNotFound` Exception''' +class DeviceNotFound(Exception): + '''`DeviceNotFound` Exception''' pass class APIError(Exception): diff --git a/yahuelib/utils.py b/yahuelib/utils.py index e290714..a0d0f7e 100644 --- a/yahuelib/utils.py +++ b/yahuelib/utils.py @@ -5,14 +5,16 @@ from colorsys import rgb_to_hsv as _rgb_to_hsv 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)`''' + '''Convert RGB colors `(255, 220, 100)` to Philips Hue's hue, saturation and brightness values `(8456, 149, 245)` imprecisely''' assert type(r) == int assert type(g) == int assert type(b) == int r_ = r / 255.0 g_ = g / 255.0 b_ = b / 255.0 - return _rgb_to_hsv(r_, g_, b_) + h_, s_, v_ = _rgb_to_hsv(r_, g_, b_) + hsv = (round(h_ * 65535.0), round(s_ * 245.0), round(v_ * 245.0)) + return hsv def kelvin_to_mired(kelvin:int): '''Convert the color temperature from Kelvin to Mired'''