/ adafruit_lifx.py
adafruit_lifx.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2019 Brent Rubell for Adafruit Industries 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 """ 23 `adafruit_lifx` 24 ================================================================================ 25 26 A CircuitPython/Python library for communicating with the LIFX HTTP Remote API. 27 28 * Author(s): Brent Rubell for Adafruit Industries 29 30 Implementation Notes 31 -------------------- 32 33 **Software and Dependencies:** 34 35 * Adafruit CircuitPython firmware for the supported boards: 36 https://github.com/adafruit/circuitpython/releases 37 38 * Adafruit ESP32SPI or ESP_ATcontrol library: 39 https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI 40 https://github.com/adafruit/Adafruit_CircuitPython_ESP_ATcontrol 41 """ 42 43 __version__ = "0.0.0-auto.0" 44 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_lifx.git" 45 46 LIFX_URL = "https://api.lifx.com/v1/lights/" 47 48 49 class LIFX: 50 """ 51 HTTP Interface for interacting with the LIFX API 52 """ 53 54 def __init__(self, wifi_manager, lifx_token): 55 """ 56 Creates an instance of the LIFX HTTP API client. 57 :param wifi_manager wifi_manager: WiFiManager from ESPSPI_WiFiManager/ESPAT_WiFiManager 58 :param str lifx_token: LIFX API token (https://api.developer.lifx.com/docs/authentication) 59 """ 60 wifi_type = str(type(wifi_manager)) 61 if "ESPSPI_WiFiManager" in wifi_type or "ESPAT_WiFiManager" in wifi_type: 62 self._wifi = wifi_manager 63 else: 64 raise TypeError("This library requires a WiFiManager object.") 65 self._lifx_token = lifx_token 66 self._auth_header = { 67 "Authorization": "Bearer %s" % self._lifx_token, 68 } 69 70 @staticmethod 71 def _parse_resp(response): 72 """Parses and returns the JSON response returned 73 from the LIFX HTTP API. 74 """ 75 if response.status_code == 422: 76 raise Exception( 77 "Error: light(s) could not be toggled: " + response["error"] 78 ) 79 try: 80 for res in response.json()["results"]: 81 return res["status"] 82 except KeyError: 83 raise KeyError(response.json()["error"]) 84 85 # HTTP Requests 86 def _post(self, path, data): 87 """POST data to the LIFX API. 88 :param str path: Formatted LIFX API URL 89 :param json data: JSON data to POST to the LIFX API. 90 """ 91 response = self._wifi.post(path, json=data, headers=self._auth_header) 92 response = self._parse_resp(response) 93 return response 94 95 def _put(self, path, data): 96 """PUT data to the LIFX API. 97 :param str path: Formatted LIFX API URL 98 :param json data: JSON data to PUT to the LIFX API. 99 """ 100 response = self._wifi.put(path, json=data, headers=self._auth_header) 101 response = self._parse_resp(response) 102 return response 103 104 def _get(self, path, data): 105 """GET data from the LIFX API. 106 :param str path: Formatted LIFX API URL 107 :param json data: JSON data to GET from the LIFX API. 108 """ 109 response = self._wifi.get(path, json=data, headers=self._auth_header) 110 return response.json() 111 112 def toggle_light(self, selector, all_lights=False, duration=0): 113 """Toggles current state of LIFX light(s). 114 :param dict selector: Selector to control which lights are requested. 115 :param bool all: Toggle all lights at once. Defaults to false. 116 :param double duration: Time (in seconds) to spend performing a toggle. Defaults to 0. 117 """ 118 if all_lights: 119 selector = "all" 120 data = {"duration": duration} 121 return self._post(LIFX_URL + selector + "/toggle", data) 122 123 def move_effect(self, selector, move_direction, period, power_on): 124 """Performs a linear move effect on a light, or lights. 125 :param str move_direction: Move direction, forward or backward. 126 :param double period: Time in second per effect cycle. 127 :param bool power_on: Turn on a light before performing the move. 128 """ 129 data = {"direction": move_direction, "period": period, "power_on": power_on} 130 return self._post(LIFX_URL + selector + "/effects/move", data) 131 132 def effects_off(self, selector, power_off=False): 133 """Turns off any running effects on the selected device. 134 :param dict selector: Selector to control which lights are requested. 135 :param bool power_off: If true, the devices will also be turned off. 136 """ 137 data = {"power_off", power_off} 138 return self._post(LIFX_URL + selector + "/effects/off", data) 139 140 def set_brightness(self, selector, brightness): 141 """Sets the state of the lights within the selector. 142 :param dict selector: Selector to control which lights are requested. 143 :param double brightness: Brightness level of the light, from 0.0 to 1.0. 144 """ 145 data = {"brightness": brightness} 146 return self._put(LIFX_URL + selector + "/state", data) 147 148 def set_color(self, selector, **kwargs): 149 """Sets the state of the light's color within the selector. 150 Valid arguments: https://api.developer.lifx.com/docs/set-state 151 """ 152 return self._put(LIFX_URL + selector + "/state", kwargs) 153 154 def list_lights(self): 155 """Enumerates all the lights associated with the LIFX Cloud Account 156 """ 157 response = self._wifi.get(url=LIFX_URL + "all", headers=self._auth_header) 158 resp = response.json() 159 response.close() 160 return resp