1919# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020# SOFTWARE.
2121import json
22- import pkg_resources
2322import platform
23+ import pkg_resources
2424# import logging
2525
2626import requests
@@ -52,21 +52,50 @@ def __init__(self, username, key, proxies=None, base_url='https://io.adafruit.co
5252 self .username = username
5353 self .key = key
5454 self .proxies = proxies
55- # self.logger = logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
55+ # self.logger = logging.basicConfig(level=logging.DEBUG,
56+ # format='%(asctime)s - %(levelname)s - %(message)s')
5657
5758 # Save URL without trailing slash as it will be added later when
5859 # constructing the path.
5960 self .base_url = base_url .rstrip ('/' )
6061
62+ @staticmethod
63+ def to_red (data ):
64+ """Hex color feed to red channel.
65+ :param int data: Color value, in hexadecimal.
66+ """
67+ return ((int (data [1 ], 16 ))* 16 ) + int (data [2 ], 16 )
6168
62- def _compose_url (self , path , is_time = None ):
63- if is_time : # return a call to https://io.adafruit.com/api/v2/time/{unit}
64- return '{0}/api/{1}/{2}' .format (self .base_url , 'v2' , path )
65- else :
66- return '{0}/api/{1}/{2}/{3}' .format (self .base_url , 'v2' , self .username , path )
69+ @staticmethod
70+ def to_green (data ):
71+ """Hex color feed to green channel.
72+ :param int data: Color value, in hexadecimal.
73+ """
74+ return (int (data [3 ], 16 ) * 16 ) + int (data [4 ], 16 )
6775
76+ @staticmethod
77+ def to_blue (data ):
78+ """Hex color feed to blue channel.
79+ :param int data: Color value, in hexadecimal.
80+ """
81+ return (int (data [5 ], 16 ) * 16 ) + int (data [6 ], 16 )
82+
83+ @staticmethod
84+ def _headers (given ):
85+ headers = default_headers .copy ()
86+ headers .update (given )
87+ return headers
88+
89+ @staticmethod
90+ def _create_payload (value , metadata ):
91+ if metadata is not None :
92+ payload = Data (value = value , lat = metadata ['lat' ], lon = metadata ['lon' ],
93+ ele = metadata ['ele' ], created_at = metadata ['created_at' ])
94+ return payload
95+ return Data (value = value )
6896
69- def _handle_error (self , response ):
97+ @staticmethod
98+ def _handle_error (response ):
7099 # Throttling Error
71100 if response .status_code == 429 :
72101 raise ThrottlingError ()
@@ -78,10 +107,10 @@ def _handle_error(self, response):
78107 raise RequestError (response )
79108 # Else do nothing if there was no error.
80109
81- def _headers (self , given ):
82- headers = default_headers . copy ()
83- headers . update ( given )
84- return headers
110+ def _compose_url (self , path , is_time = None ):
111+ if is_time : # return a call to https://io.adafruit.com/api/v2/time/{unit}
112+ return '{0}/api/{1}/{2}' . format ( self . base_url , 'v2' , path )
113+ return '{0}/api/{1}/{2}/{3}' . format ( self . base_url , 'v2' , self . username , path )
85114
86115 def _get (self , path , is_time = None ):
87116 response = requests .get (self ._compose_url (path , is_time ),
@@ -90,8 +119,7 @@ def _get(self, path, is_time=None):
90119 self ._handle_error (response )
91120 if not is_time :
92121 return response .json ()
93- else : # time doesn't need to serialize into json, just return text
94- return response .text
122+ return response .text
95123
96124 def _post (self , path , data ):
97125 response = requests .post (self ._compose_url (path ),
@@ -105,20 +133,28 @@ def _post(self, path, data):
105133 def _delete (self , path ):
106134 response = requests .delete (self ._compose_url (path ),
107135 headers = self ._headers ({'X-AIO-Key' : self .key ,
108- 'Content-Type' : 'application/json' }),
136+ 'Content-Type' : 'application/json' }),
109137 proxies = self .proxies )
110138 self ._handle_error (response )
111139
112140 # Data functionality.
113- def send_data (self , feed , value ):
141+ def send_data (self , feed , value , metadata = None , precision = None ):
114142 """Helper function to simplify adding a value to a feed. Will append the
115143 specified value to the feed identified by either name, key, or ID.
116144 Returns a Data instance with details about the newly appended row of data.
117145 Note that send_data now operates the same as append.
118146 :param string feed: Name/Key/ID of Adafruit IO feed.
119147 :param string value: Value to send.
148+ :param dict metadata: Optional metadata associated with the value.
149+ :param int precision: Optional amount of precision points to send.
120150 """
121- return self .create_data (feed , Data (value = value ))
151+ if precision :
152+ try :
153+ value = round (value , precision )
154+ except NotImplementedError :
155+ raise NotImplementedError ("Using the precision kwarg requires a float value" )
156+ payload = self ._create_payload (value , metadata )
157+ return self .create_data (feed , payload )
122158
123159 send = send_data
124160
@@ -144,42 +180,32 @@ def append(self, feed, value):
144180 """
145181 return self .create_data (feed , Data (value = value ))
146182
147- def send_location_data (self , feed , lat , lon , ele , value = None ):
148- """Sends locational data to a feed.
149- :param string feed: Name/Key/ID of Adafruit IO feed.
150- :param int lat: Latitude.
151- :param int lon: Longitude.
152- :param int ele: Elevation.
153- :param int value: Optional value to send, defaults to None.
154- """
155- return self .create_data (feed , Data (value = value ,lat = lat , lon = lon , ele = ele ))
156-
157183 def receive_time (self , time ):
158184 """Returns the time from the Adafruit IO server.
159185 :param string time: Time to be returned: `millis`, `seconds`, `ISO-8601`.
160186 """
161187 timepath = "time/{0}" .format (time )
162188 return self ._get (timepath , is_time = True )
163-
189+
164190 def receive_weather (self , weather_id = None ):
165191 """Adafruit IO Weather Service, Powered by Dark Sky
166192 :param int id: optional ID for retrieving a specified weather record.
167193 """
168194 if weather_id :
169- weather_path = "integrations/weather/{0}" .format (weather_id )
195+ weather_path = "integrations/weather/{0}" .format (weather_id )
170196 else :
171- weather_path = "integrations/weather"
197+ weather_path = "integrations/weather"
172198 return self ._get (weather_path )
173-
174- def receive_random (self , id = None ):
199+
200+ def receive_random (self , randomizer_id = None ):
175201 """Access to Adafruit IO's Random Data
176202 service.
177- :param int id : optional ID for retrieving a specified randomizer.
203+ :param int randomizer_id : optional ID for retrieving a specified randomizer.
178204 """
179- if id :
180- random_path = "integrations/words/{0}" .format (id )
205+ if randomizer_id :
206+ random_path = "integrations/words/{0}" .format (randomizer_id )
181207 else :
182- random_path = "integrations/words"
208+ random_path = "integrations/words"
183209 return self ._get (random_path )
184210
185211 def receive (self , feed ):
@@ -191,7 +217,7 @@ def receive(self, feed):
191217 return Data .from_dict (self ._get (path ))
192218
193219 def receive_next (self , feed ):
194- """Retrieve the next unread value from the specified feed. Returns a Data
220+ """Retrieve the next unread value from the specified feed. Returns a Data
195221 instance whose value property holds the retrieved value.
196222 :param string feed: Name/Key/ID of Adafruit IO feed.
197223 """
@@ -215,16 +241,15 @@ def data(self, feed, data_id=None):
215241 if data_id is None :
216242 path = "feeds/{0}/data" .format (feed )
217243 return list (map (Data .from_dict , self ._get (path )))
218- else :
219- path = "feeds/{0}/data/{1}" .format (feed , data_id )
220- return Data .from_dict (self ._get (path ))
244+ path = "feeds/{0}/data/{1}" .format (feed , data_id )
245+ return Data .from_dict (self ._get (path ))
221246
222247 def create_data (self , feed , data ):
223248 """Create a new row of data in the specified feed.
224- Returns a Data instance with details about the newly
249+ Returns a Data instance with details about the newly
225250 appended row of data.
226251 :param string feed: Name/Key/ID of Adafruit IO feed.
227- :param Data data: Instance of the Data class. Must have a value property set.
252+ :param Data data: Instance of the Data class. Must have a value property set.
228253 """
229254 path = "feeds/{0}/data" .format (feed )
230255 return Data .from_dict (self ._post (path , data ._asdict ()))
@@ -237,24 +262,6 @@ def delete(self, feed, data_id):
237262 path = "feeds/{0}/data/{1}" .format (feed , data_id )
238263 self ._delete (path )
239264
240- def toRed (self , data ):
241- """Hex color feed to red channel.
242- :param int data: Color value, in hexadecimal.
243- """
244- return ((int (data [1 ], 16 ))* 16 ) + int (data [2 ], 16 )
245-
246- def toGreen (self , data ):
247- """Hex color feed to green channel.
248- :param int data: Color value, in hexadecimal.
249- """
250- return (int (data [3 ], 16 ) * 16 ) + int (data [4 ], 16 )
251-
252- def toBlue (self , data ):
253- """Hex color feed to blue channel.
254- :param int data: Color value, in hexadecimal.
255- """
256- return (int (data [5 ], 16 ) * 16 ) + int (data [6 ], 16 )
257-
258265 # feed functionality.
259266 def feeds (self , feed = None ):
260267 """Retrieve a list of all feeds, or the specified feed. If feed is not
@@ -264,9 +271,8 @@ def feeds(self, feed=None):
264271 if feed is None :
265272 path = "feeds"
266273 return list (map (Feed .from_dict , self ._get (path )))
267- else :
268- path = "feeds/{0}" .format (feed )
269- return Feed .from_dict (self ._get (path ))
274+ path = "feeds/{0}" .format (feed )
275+ return Feed .from_dict (self ._get (path ))
270276
271277 def create_feed (self , feed ):
272278 """Create the specified feed.
@@ -290,9 +296,8 @@ def groups(self, group=None):
290296 if group is None :
291297 path = "groups/"
292298 return list (map (Group .from_dict , self ._get (path )))
293- else :
294- path = "groups/{0}" .format (group )
295- return Group .from_dict (self ._get (path ))
299+ path = "groups/{0}" .format (group )
300+ return Group .from_dict (self ._get (path ))
296301
297302 def create_group (self , group ):
298303 """Create the specified group.
@@ -306,4 +311,4 @@ def delete_group(self, group):
306311 :param string group: Name/Key/ID of Adafruit IO Group.
307312 """
308313 path = "groups/{0}" .format (group )
309- self ._delete (path )
314+ self ._delete (path )
0 commit comments