Skip to content

Commit d694464

Browse files
authored
Feed sharing (#64)
Adding Feed Sharing into IO Python MQTT_Client
1 parent 1765438 commit d694464

File tree

4 files changed

+126
-10
lines changed

4 files changed

+126
-10
lines changed

Adafruit_IO/mqtt_client.py

+37-10
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __init__(self, username, key, service_host='io.adafruit.com', secure=True):
5252
self.on_connect = None
5353
self.on_disconnect = None
5454
self.on_message = None
55+
self.on_subscribe = None
5556
# Initialize MQTT client.
5657
self._client = mqtt.Client()
5758
if secure:
@@ -66,6 +67,7 @@ def __init__(self, username, key, service_host='io.adafruit.com', secure=True):
6667
self._client.on_message = self._mqtt_message
6768
self._connected = False
6869

70+
6971
def _mqtt_connect(self, client, userdata, flags, rc):
7072
logger.debug('Client on_connect called.')
7173
# Check if the result code is success (0) or some error (non-zero) and
@@ -75,7 +77,7 @@ def _mqtt_connect(self, client, userdata, flags, rc):
7577
self._connected = True
7678
print('Connected to Adafruit IO!')
7779
else:
78-
# handle RC errors within `errors.py`'s MQTTError class
80+
# handle RC errors within MQTTError class
7981
raise MQTTError(rc)
8082
# Call the on_connect callback if available.
8183
if self.on_connect is not None:
@@ -88,6 +90,7 @@ def _mqtt_disconnect(self, client, userdata, rc):
8890
# log the RC as an error. Continue on to call any disconnect handler
8991
# so clients can potentially recover gracefully.
9092
if rc != 0:
93+
print("Unexpected disconnection.")
9194
raise MQTTError(rc)
9295
print('Disconnected from Adafruit IO!')
9396
# Call the on_disconnect callback if available.
@@ -99,13 +102,17 @@ def _mqtt_message(self, client, userdata, msg):
99102
# Parse out the feed id and call on_message callback.
100103
# Assumes topic looks like "username/feeds/id"
101104
parsed_topic = msg.topic.split('/')
102-
if self.on_message is not None and self._username == parsed_topic[0]:
105+
if self.on_message is not None:
103106
feed = parsed_topic[2]
104107
payload = '' if msg.payload is None else msg.payload.decode('utf-8')
105108
elif self.on_message is not None and parsed_topic[0] == 'time':
106109
feed = parsed_topic[0]
107110
payload = msg.payload.decode('utf-8')
108111
self.on_message(self, feed, payload)
112+
113+
def _mqtt_subscribe(client, userdata, mid, granted_qos):
114+
"""Called when broker responds to a subscribe request."""
115+
109116

110117
def connect(self, **kwargs):
111118
"""Connect to the Adafruit.IO service. Must be called before any loop
@@ -162,16 +169,24 @@ def loop(self, timeout_sec=1.0):
162169
"""
163170
self._client.loop(timeout=timeout_sec)
164171

165-
def subscribe(self, feed_id):
172+
def subscribe(self, feed_id, feed_user=None):
166173
"""Subscribe to changes on the specified feed. When the feed is updated
167174
the on_message function will be called with the feed_id and new value.
175+
176+
Params:
177+
- feed_id: The id of the feed to update.
178+
- feed_user (optional): The user id of the feed. Used for feed sharing.
168179
"""
169-
self._client.subscribe('{0}/feeds/{1}'.format(self._username, feed_id))
180+
if feed_user is not None:
181+
(res, mid) = self._client.subscribe('{0}/feeds/{1}'.format(feed_user, feed_id))
182+
else:
183+
(res, mid) = self._client.subscribe('{0}/feeds/{1}'.format(self._username, feed_id))
184+
return res, mid
170185

171186
def subscribe_time(self, time):
172187
"""Subscribe to changes on the Adafruit IO time feeds. When the feed is
173188
updated, the on_message function will be called and publish a new value:
174-
time =
189+
time feeds:
175190
millis: milliseconds
176191
seconds: seconds
177192
iso: ISO-8601 (https://en.wikipedia.org/wiki/ISO_8601)
@@ -181,15 +196,27 @@ def subscribe_time(self, time):
181196
elif time == 'iso':
182197
self._client.subscribe('time/ISO-8601')
183198
else:
184-
print('ERROR: Invalid time type specified')
199+
raise TypeError('Invalid Time Feed Specified.')
185200
return
201+
202+
def unsubscribe(self, feed_id):
203+
"""Unsubscribes from a specified MQTT feed.
204+
Note: this does not prevent publishing to a feed, it will unsubscribe
205+
from receiving messages via on_message.
206+
"""
207+
(res, mid) = self._client.unsubscribe('{0}/feeds/{1}'.format(self._username, feed_id))
186208

187-
def publish(self, feed_id, value):
209+
def publish(self, feed_id, value=None, feed_user=None):
188210
"""Publish a value to a specified feed.
189211
190-
Required parameters:
212+
Params:
191213
- feed_id: The id of the feed to update.
214+
- feed_user (optional): The user id of the feed. Used for feed sharing.
192215
- value: The new value to publish to the feed.
193216
"""
194-
self._client.publish('{0}/feeds/{1}'.format(self._username, feed_id),
195-
payload=value)
217+
if feed_user is not None:
218+
(res, self._pub_mid) = self._client.publish('{0}/feeds/{1}'.format(feed_user, feed_id),
219+
payload=value)
220+
else:
221+
(res, self._pub_mid) = self._client.publish('{0}/feeds/{1}'.format(self._username, feed_id),
222+
payload=value)

docs/feed-sharing.rst

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Feed Sharing
2+
------------
3+
Feed sharing is a feature of Adafruit IO which allows you to share your feeds with people you specify.
4+
5+
If you want to share a feed on your Adafruit IO Account with another user, visit the `Sharing a feed page <https://learn.adafruit.com/adafruit-io-basics-feeds/sharing-a-feed>`_
6+
on the Adafruit Learning System.
7+
8+
The Adafruit IO Python client supports Feed Sharing in the mqtt_client.py class.
9+
10+
Usage Example
11+
~~~~~~~~~~~~~
12+
13+
14+
.. literalinclude:: ../examples/mqtt/mqtt_shared_feeds.py

docs/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Table of Contents
2222
:maxdepth: 6
2323

2424
feeds
25+
feed-sharing
2526
data
2627
groups
2728

examples/mqtt/mqtt_shared_feeds.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
`mqtt_shared_feeds.py`
3+
---------------------------------------------------------
4+
Example of reading and writing to a shared Adafruit IO Feed.
5+
6+
learn.adafruit.com/adafruit-io-basics-feeds/sharing-a-feed
7+
8+
Author: Brent Rubell for Adafruit Industries 2018
9+
"""
10+
11+
# Import standard python modules.
12+
import sys
13+
import time
14+
import random
15+
16+
# Import Adafruit IO MQTT client.
17+
from Adafruit_IO import MQTTClient
18+
19+
# Set to your Adafruit IO key.
20+
# Remember, your key is a secret,
21+
# so make sure not to publish it when you publish this code!
22+
ADAFRUIT_IO_KEY = 'YOUR_AIO_KEY'
23+
24+
# Set to your Adafruit IO username.
25+
# (go to https://accounts.adafruit.com to find your username)
26+
ADAFRUIT_IO_USERNAME = 'YOUR_AIO_USERNAME'
27+
28+
# Shared IO Feed
29+
# Make sure you have read AND write access to this feed to publish.
30+
IO_FEED = 'SHARED_AIO_FEED_NAME'
31+
32+
# IO Feed Owner's username
33+
IO_FEED_USERNAME = 'SHARED_AIO_FEED_USERNAME'
34+
35+
36+
# Define callback functions which will be called when certain events happen.
37+
def connected(client):
38+
"""Connected function will be called when the client connects.
39+
"""
40+
client.subscribe(IO_FEED, IO_FEED_USERNAME)
41+
42+
def disconnected(client):
43+
"""Disconnected function will be called when the client disconnects.
44+
"""
45+
print('Disconnected from Adafruit IO!')
46+
sys.exit(1)
47+
48+
def message(client, feed_id, payload):
49+
"""Message function will be called when a subscribed feed has a new value.
50+
The feed_id parameter identifies the feed, and the payload parameter has
51+
the new value.
52+
"""
53+
print('Feed {0} received new value: {1}'.format(feed_id, payload))
54+
55+
56+
# Create an MQTT client instance.
57+
client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)
58+
59+
# Setup the callback functions defined above.
60+
client.on_connect = connected
61+
client.on_disconnect = disconnected
62+
client.on_message = message
63+
64+
# Connect to the Adafruit IO server.
65+
client.connect()
66+
67+
client.loop_background()
68+
print('Publishing a new message every 10 seconds (press Ctrl-C to quit)...')
69+
70+
while True:
71+
value = random.randint(0, 100)
72+
print('Publishing {0} to {1}.'.format(value, IO_FEED))
73+
client.publish(IO_FEED, value, IO_FEED_USERNAME)
74+
time.sleep(10)

0 commit comments

Comments
 (0)