Skip to content

Commit 552b407

Browse files
authored
MQTT/REST Time Helpers (#54)
Add ability to subscribe to time topics via MQTT Client or REST/API Client. Add examples for each.
1 parent ffce772 commit 552b407

File tree

5 files changed

+144
-8
lines changed

5 files changed

+144
-8
lines changed

Diff for: Adafruit_IO/client.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2014 Adafruit Industries
1+
# Copyright (c) 2018 Adafruit Industries
22
# Authors: Justin Cooper & Tony DiCola
33

44
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -60,8 +60,11 @@ def __init__(self, username, key, proxies=None, base_url='https://io.adafruit.co
6060
# constructing the path.
6161
self.base_url = base_url.rstrip('/')
6262

63-
def _compose_url(self, path):
64-
return '{0}/api/{1}/{2}/{3}'.format(self.base_url, self.api_version, self.username, path)
63+
def _compose_url(self, path, is_time=None):
64+
if not is_time:
65+
return '{0}/api/{1}/{2}/{3}'.format(self.base_url, self.api_version, self.username, path)
66+
else: # return a call to https://io.adafruit.com/api/v2/time/{unit}
67+
return '{0}/api/{1}/{2}'.format(self.base_url, self.api_version, path)
6568

6669

6770
def _handle_error(self, response):
@@ -78,12 +81,15 @@ def _headers(self, given):
7881
headers.update(given)
7982
return headers
8083

81-
def _get(self, path):
82-
response = requests.get(self._compose_url(path),
84+
def _get(self, path, is_time=None):
85+
response = requests.get(self._compose_url(path, is_time),
8386
headers=self._headers({'X-AIO-Key': self.key}),
8487
proxies=self.proxies)
8588
self._handle_error(response)
86-
return response.json()
89+
if not is_time:
90+
return response.json()
91+
else: # time doesn't need to serialize into json, just return text
92+
return response.text
8793

8894
def _post(self, path, data):
8995
response = requests.post(self._compose_url(path),
@@ -141,6 +147,15 @@ def send_location_data(self, feed, value, lat, lon, ele):
141147
"""
142148
return self.create_data(feed, Data(value = value,lat=lat, lon=lon, ele=ele))
143149

150+
def receive_time(self, time):
151+
"""Returns the time from the Adafruit IO server.
152+
153+
args:
154+
- time (string): millis, seconds, ISO-8601
155+
"""
156+
timepath = "time/{0}".format(time)
157+
return self._get(timepath, is_time=True)
158+
144159
def receive(self, feed):
145160
"""Retrieve the most recent value for the specified feed. Feed can be a
146161
feed ID, feed key, or feed name. Returns a Data instance whose value

Diff for: Adafruit_IO/mqtt_client.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ def _mqtt_message(self, client, userdata, msg):
100100
if self.on_message is not None and self._username == parsed_topic[0]:
101101
feed = parsed_topic[2]
102102
payload = '' if msg.payload is None else msg.payload.decode('utf-8')
103-
self.on_message(self, feed, payload)
103+
elif self.on_message is not None and parsed_topic[0] == 'time':
104+
feed = parsed_topic[0]
105+
payload = msg.payload.decode('utf-8')
106+
self.on_message(self, feed, payload)
104107

105108
def connect(self, **kwargs):
106109
"""Connect to the Adafruit.IO service. Must be called before any loop
@@ -163,6 +166,22 @@ def subscribe(self, feed_id):
163166
"""
164167
self._client.subscribe('{0}/feeds/{1}'.format(self._username, feed_id))
165168

169+
def subscribe_time(self, time):
170+
"""Subscribe to changes on the Adafruit IO time feeds. When the feed is
171+
updated, the on_message function will be called and publish a new value:
172+
time =
173+
millis: milliseconds
174+
seconds: seconds
175+
iso: ISO-8601 (https://en.wikipedia.org/wiki/ISO_8601)
176+
"""
177+
if time == 'millis' or time == 'seconds':
178+
self._client.subscribe('time/{0}'.format(time))
179+
elif time == 'iso':
180+
self._client.subscribe('time/ISO-8601')
181+
else:
182+
print('ERROR: Invalid time type specified')
183+
return
184+
166185
def publish(self, feed_id, value):
167186
"""Publish a value to a specified feed.
168187

Diff for: examples/aio_basics/adafruitio_17_time.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
adafruitio_17_time.py
3+
====================================
4+
Don't have a RTC handy and need
5+
accurate time measurements?
6+
7+
Let Adafruit IO serve real-time values!
8+
9+
Author: Brent Rubell
10+
"""
11+
# Import Adafruit IO REST client.
12+
from Adafruit_IO import Client, Feed, Data, RequestError
13+
14+
# Set to your Adafruit IO key.
15+
# Remember, your key is a secret,
16+
# so make sure not to publish it when you publish this code!
17+
ADAFRUIT_IO_KEY = 'YOUR_AIO_KEY'
18+
19+
# Set to your Adafruit IO username.
20+
# (go to https://accounts.adafruit.com to find your username)
21+
ADAFRUIT_IO_USERNAME = 'YOUR_AIO_USERNAME'
22+
23+
# Create an instance of the REST client.
24+
aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)
25+
26+
print('---Adafruit IO REST API Time Helpers---')
27+
28+
print('Seconds: aio.receive_time(seconds)')
29+
secs_val = aio.receive_time('seconds')
30+
print('\t' + secs_val)
31+
32+
print('Milliseconds: aio.receive_time(millis)')
33+
ms_val = aio.receive_time('millis')
34+
print('\t' + ms_val)
35+
36+
print('ISO-8601: aio.receive_time(ISO-8601)')
37+
iso_val = aio.receive_time('ISO-8601')
38+
print('\t' + iso_val)

Diff for: examples/mqtt/mqtt_time.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
mqtt_time.py
3+
============================================
4+
example of utilizing MQTT time topics to grab
5+
the time from the Adafruit IO server.
6+
7+
Author: Brent Rubell
8+
"""
9+
10+
# Import standard python modules.
11+
import sys
12+
import time
13+
14+
# Import Adafruit IO MQTT client.
15+
from Adafruit_IO import MQTTClient
16+
17+
# Set to your Adafruit IO key.
18+
# Remember, your key is a secret,
19+
# so make sure not to publish it when you publish this code!
20+
ADAFRUIT_IO_KEY = 'YOUR_AIO_KEY'
21+
22+
# Set to your Adafruit IO username.
23+
# (go to https://accounts.adafruit.com to find your username)
24+
ADAFRUIT_IO_USERNAME = 'YOUR_AIO_USERNAME'
25+
26+
def disconnected(client):
27+
# Disconnected function will be called when the client disconnects.
28+
print('Disconnected from Adafruit IO!')
29+
sys.exit(1)
30+
31+
def message(client, feed_id, payload):
32+
# Message function will be called when a subscribed feed has a new value.
33+
# The feed_id parameter identifies the feed, and the payload parameter has
34+
# the new value.
35+
print('\t Feed {0} received new value: {1}'.format(feed_id, payload))
36+
37+
38+
# Create a SECURE MQTT client instance
39+
# Note: This client will default to secure, an optional parameter can be added
40+
# to make it insecure, comment out the below line
41+
# client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY, secure=False)
42+
client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)
43+
44+
# Setup the callback functions defined above.
45+
client.on_disconnect = disconnected
46+
client.on_message = message
47+
48+
# Connect to the Adafruit IO server.
49+
client.connect()
50+
51+
# time per loop
52+
loop_time = 2
53+
54+
client.loop_background()
55+
while True:
56+
print('* Subscribing to /time/seconds')
57+
client.subscribe_time('seconds')
58+
time.sleep(loop_time)
59+
print('* Subscribing to /time/millis')
60+
client.subscribe_time('millis')
61+
time.sleep(loop_time)
62+
print('* Subscribing to iso-8601')
63+
client.subscribe_time('iso')
64+
time.sleep(loop_time)

Diff for: setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@
3535
keywords = 'Adafruit IO',
3636
classifiers = classifiers,
3737
description = 'Client library for Adafruit IO (http://io.adafruit.com/).',
38-
long_description = open('README.md').read(),
38+
long_description = open('README.rst').read(),
3939
install_requires = ["requests", "paho-mqtt"]
4040
)

0 commit comments

Comments
 (0)