From fbbfe8ffae49fec6b7f7850eae2d09ff4752d99a Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 12:49:40 -0500 Subject: [PATCH 01/17] add darkskies api to io python client --- Adafruit_IO/client.py | 13 ++++++++++--- examples/basics/darkskies.py | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 examples/basics/darkskies.py diff --git a/Adafruit_IO/client.py b/Adafruit_IO/client.py index 76d603b..6809371 100644 --- a/Adafruit_IO/client.py +++ b/Adafruit_IO/client.py @@ -61,10 +61,10 @@ def __init__(self, username, key, proxies=None, base_url='https://io.adafruit.co self.base_url = base_url.rstrip('/') def _compose_url(self, path, is_time=None): - if not is_time: + if is_time: # return a call to https://io.adafruit.com/api/v2/time/{unit} + return '{0}/api/{1}/{2}'.format(self.base_url, self.api_version, path) + else: return '{0}/api/{1}/{2}/{3}'.format(self.base_url, self.api_version, self.username, path) - else: # return a call to https://io.adafruit.com/api/v2/time/{unit} - return '{0}/api/{1}/{2}'.format(self.base_url, self.api_version, path) def _handle_error(self, response): @@ -161,6 +161,13 @@ def receive_time(self, time): """ timepath = "time/{0}".format(time) return self._get(timepath, is_time=True) + + def receive_weather(self, weather_id): + """Get the specified weather record with current weather and all available forecast information. + :param int id: ID for forecast + """ + weatherpath = "integrations/weather/{0}".format(weather_id) + return self._get(weatherpath) def receive(self, feed): """Retrieve the most recent value for the specified feed. Returns a Data diff --git a/examples/basics/darkskies.py b/examples/basics/darkskies.py new file mode 100644 index 0000000..0fa5b8c --- /dev/null +++ b/examples/basics/darkskies.py @@ -0,0 +1,24 @@ +""" +Example of getting a darkskies forecast +from Adafruit IO. +""" +# import Adafruit IO REST client. +from Adafruit_IO import Client, Feed, RequestError + +# Set to your Adafruit IO key. +# Remember, your key is a secret, +# so make sure not to publish it when you publish this code! +ADAFRUIT_IO_KEY = 'PASS' + +# Set to your Adafruit IO username. +# (go to https://accounts.adafruit.com to find your username) +ADAFRUIT_IO_USERNAME = 'USER' + +# Create an instance of the REST client. +aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) + + + +forecast = aio.receive_weather(2153) + +print(forecast) \ No newline at end of file From b6debfc9f1a1981d995f7ac83fc2a87e8078f0e1 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 12:57:56 -0500 Subject: [PATCH 02/17] make weather_id an optional param, update example --- Adafruit_IO/client.py | 11 ++-- examples/basics/{darkskies.py => darksky.py} | 21 +++++--- examples/basics/digital_in.py | 54 -------------------- 3 files changed, 20 insertions(+), 66 deletions(-) rename examples/basics/{darkskies.py => darksky.py} (55%) delete mode 100644 examples/basics/digital_in.py diff --git a/Adafruit_IO/client.py b/Adafruit_IO/client.py index 6809371..bd1ceb2 100644 --- a/Adafruit_IO/client.py +++ b/Adafruit_IO/client.py @@ -162,11 +162,14 @@ def receive_time(self, time): timepath = "time/{0}".format(time) return self._get(timepath, is_time=True) - def receive_weather(self, weather_id): - """Get the specified weather record with current weather and all available forecast information. - :param int id: ID for forecast + def receive_weather(self, weather_id=None): + """Adafruit IO Weather Service, Powered by Dark Sky + :param int id: optional ID for retrieving a specified weather record. """ - weatherpath = "integrations/weather/{0}".format(weather_id) + if weather_id: + weatherpath = "integrations/weather/{0}".format(weather_id) + else: + weatherpath = "integrations/weather" return self._get(weatherpath) def receive(self, feed): diff --git a/examples/basics/darkskies.py b/examples/basics/darksky.py similarity index 55% rename from examples/basics/darkskies.py rename to examples/basics/darksky.py index 0fa5b8c..9270576 100644 --- a/examples/basics/darkskies.py +++ b/examples/basics/darksky.py @@ -1,24 +1,29 @@ """ -Example of getting a darkskies forecast -from Adafruit IO. +Example of getting a forecast from Adafruit IO +Note: This functionality is for IO PLUS users ONLY. + +Author: Brent Rubell for Adafruit Industries """ # import Adafruit IO REST client. from Adafruit_IO import Client, Feed, RequestError +# Set to your Adafruit IO username. +# (go to https://accounts.adafruit.com to find your username) +ADAFRUIT_IO_USERNAME = 'USER' + # Set to your Adafruit IO key. # Remember, your key is a secret, # so make sure not to publish it when you publish this code! -ADAFRUIT_IO_KEY = 'PASS' +ADAFRUIT_IO_KEY = 'PASSWORD' -# Set to your Adafruit IO username. -# (go to https://accounts.adafruit.com to find your username) -ADAFRUIT_IO_USERNAME = 'USER' # Create an instance of the REST client. aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) +print('Get all weather integration records without their current forecast values.') +records = aio.receive_weather() +print(records) - +print('Get the specified weather record with current weather and all available forecast information.') forecast = aio.receive_weather(2153) - print(forecast) \ No newline at end of file diff --git a/examples/basics/digital_in.py b/examples/basics/digital_in.py deleted file mode 100644 index d2fdb4e..0000000 --- a/examples/basics/digital_in.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -'digital_in.py' -================================== -Example of sending button values -to an Adafruit IO feed. - -Author(s): Brent Rubell, Todd Treece -""" -# Import standard python modules -import time - -# import Adafruit Blinka -import board -import digitalio - -# import Adafruit IO REST client. -from Adafruit_IO import Client, Feed, RequestError - -# Set to your Adafruit IO key. -# Remember, your key is a secret, -# so make sure not to publish it when you publish this code! -ADAFRUIT_IO_KEY = 'YOUR_AIO_KEY' - -# Set to your Adafruit IO username. -# (go to https://accounts.adafruit.com to find your username) -ADAFRUIT_IO_USERNAME = 'YOUR_AIO_USERNAME' - -# Create an instance of the REST client. -aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) - -try: # if we have a 'digital' feed - digital = aio.feeds('digital') -except RequestError: # create a digital feed - feed = Feed(name="digital") - digital = aio.create_feed(feed) - -# button set up -button = digitalio.DigitalInOut(board.D12) -button.direction = digitalio.Direction.INPUT -button.pull = digitalio.Pull.UP -button_current = 0 - - -while True: - if not button.value: - button_current = 1 - else: - button_current = 0 - - print('Button -> ', button_current) - aio.send(digital.key, button_current) - - # avoid timeout from adafruit io - time.sleep(1) From b1ae23c78bbd25eef689343e9e94b625358ff8a2 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 12:59:36 -0500 Subject: [PATCH 03/17] bump version --- Adafruit_IO/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adafruit_IO/_version.py b/Adafruit_IO/_version.py index ab999f0..00b64fe 100644 --- a/Adafruit_IO/_version.py +++ b/Adafruit_IO/_version.py @@ -1 +1 @@ -__version__ = "2.0.18" \ No newline at end of file +__version__ = "2.0.19" \ No newline at end of file From f00bdcd06673eabfee23dad04f6545a5178ae43d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 13:15:31 -0500 Subject: [PATCH 04/17] adding MQTT API integration --- Adafruit_IO/mqtt_client.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index c032dae..99bebe3 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -197,6 +197,13 @@ def subscribe_group(self, group_id): """ self._client.subscribe('{0}/groups/{1}'.format(self._username, group_id)) + def subscribe_weather(self, weather_id, forecast_type): + """Subscribe to Adafruit IO Weather + :param int weather_id: weather record you want data for + :param string type: type of forecast data requested + """ + self._client.subscribe('{0}/integration/weather/{1}/{2}'.format(self._username, weather_id, forecast_type)) + def subscribe_time(self, time): """Subscribe to changes on the Adafruit IO time feeds. When the feed is updated, the on_message function will be called and publish a new value: From c6b9dfcca8957a4bc45b4d31eaf0782fa281447b Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 13:18:57 -0500 Subject: [PATCH 05/17] adding example of MQTT Weather API --- examples/mqtt/mqtt_weather.py | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 examples/mqtt/mqtt_weather.py diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py new file mode 100644 index 0000000..334dfc2 --- /dev/null +++ b/examples/mqtt/mqtt_weather.py @@ -0,0 +1,79 @@ +""" +Example of using the Adafruit IO MQTT Client +for subscribing to the Adafruit IO Weather Service +Note: This feature is avaliable for IO Plus Subscribers ONLY + +Author: Brent Rubell for Adafruit Industries +""" + +# Import standard python modules. +import sys + +# Import Adafruit IO MQTT client. +from Adafruit_IO import MQTTClient + +# Set to your Adafruit IO key. +# Remember, your key is a secret, +# so make sure not to publish it when you publish this code! +ADAFRUIT_IO_KEY = 'KEY' + +# Set to your Adafruit IO username. +# (go to https://accounts.adafruit.com to find your username) +ADAFRUIT_IO_USERNAME = 'USER' + +# Set to ID of the forecast to subscribe to for updates. +forecast_id = 1234 + +# Set to the ID of the feed to subscribe to for updates. +""" +Valid forecast types are: +current +forecast_minutes_5 +forecast_minutes_30 +forecast_hours_1 +forecast_hours_2 +forecast_hours_6 +forecast_hours_24 +forecast_days_1 +forecast_days_2 +forecast_days_5 +""" +forecast_type = 'current' + +# Define callback functions which will be called when certain events happen. +def connected(client): + # Connected function will be called when the client is connected to Adafruit IO. + # This is a good place to subscribe to feed changes. The client parameter + # passed to this function is the Adafruit IO MQTT client so you can make + # calls against it easily. + print('Connected to Adafruit IO! Listening for {0} changes...'.format(FEED_ID)) + # Subscribe to changes on a feed named DemoFeed. + client.subscribe_weather(forecast_id, forecast_type) + +def disconnected(client): + # Disconnected function will be called when the client disconnects. + print('Disconnected from Adafruit IO!') + sys.exit(1) + +def message(client, feed_id, payload): + # Message function will be called when a subscribed feed has a new value. + # The feed_id parameter identifies the feed, and the payload parameter has + # the new value. + print('Weather Subscription {0} received new value: {1}'.format(forecast_id, payload)) + + +# Create an MQTT client instance. +client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) + +# Setup the callback functions defined above. +client.on_connect = connected +client.on_disconnect = disconnected +client.on_message = message + +# Connect to the Adafruit IO server. +client.connect() + +# Start a message loop that blocks forever waiting for MQTT messages to be +# received. Note there are other options for running the event loop like doing +# so in a background thread--see the mqtt_client.py example to learn more. +client.loop_blocking() From 3f7a8d53f48f5591482066a6fb1e848d97a6ac33 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 13:20:35 -0500 Subject: [PATCH 06/17] update prints for forecast --- examples/mqtt/mqtt_weather.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py index 334dfc2..06826a2 100644 --- a/examples/mqtt/mqtt_weather.py +++ b/examples/mqtt/mqtt_weather.py @@ -21,7 +21,7 @@ # (go to https://accounts.adafruit.com to find your username) ADAFRUIT_IO_USERNAME = 'USER' -# Set to ID of the forecast to subscribe to for updates. +# Set to ID of the forecast to subscribe to for updates forecast_id = 1234 # Set to the ID of the feed to subscribe to for updates. @@ -46,7 +46,7 @@ def connected(client): # This is a good place to subscribe to feed changes. The client parameter # passed to this function is the Adafruit IO MQTT client so you can make # calls against it easily. - print('Connected to Adafruit IO! Listening for {0} changes...'.format(FEED_ID)) + print('Connected to Adafruit IO! Listening to forecast: {0}...'.format(forecast_id)) # Subscribe to changes on a feed named DemoFeed. client.subscribe_weather(forecast_id, forecast_type) From 6752497e58153bd3a30ea9ab4866602de6a43d46 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 13:36:52 -0500 Subject: [PATCH 07/17] enforce strict forecast types, raise error --- Adafruit_IO/mqtt_client.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index 99bebe3..3134dff 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -29,6 +29,11 @@ logger = logging.getLogger(__name__) +forecast_types = ["current", "forecast_minutes_5", + "forecast_minutes_30", "forecast_hours_1", + "forecast_hours_2", "forecast_hours_6", + "forecast_hours_24", "forecast_days_1", + "forecast_days_2", "forecast_days_5",] class MQTTClient(object): """Interface for publishing and subscribing to feed changes on Adafruit IO @@ -202,7 +207,10 @@ def subscribe_weather(self, weather_id, forecast_type): :param int weather_id: weather record you want data for :param string type: type of forecast data requested """ - self._client.subscribe('{0}/integration/weather/{1}/{2}'.format(self._username, weather_id, forecast_type)) + if forecast_type in forecast_types: + self._client.subscribe('{0}/integration/weather/{1}/{2}'.format(self._username, weather_id, forecast_type)) + else: + raise TypeError("Invalid Forecast Type Specified.") def subscribe_time(self, time): """Subscribe to changes on the Adafruit IO time feeds. When the feed is From e0904c66d78b6bb2aeb0f5e887419c67f5171e1b Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 14:37:47 -0500 Subject: [PATCH 08/17] add forecast topic to mqtt message parser --- Adafruit_IO/mqtt_client.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index 3134dff..3194f85 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -109,7 +109,10 @@ def _mqtt_message(self, client, userdata, msg): """ parsed_topic = msg.topic.split('/') if self.on_message is not None: - topic = parsed_topic[2] + topic = parsed_topic[1] + payload = '' if msg.payload is None else msg.payload.decode('utf-8') + elif self.on_message is not None and parsed_topic[2] == 'weather': + topic = parsed_topic[4] payload = '' if msg.payload is None else msg.payload.decode('utf-8') elif self.on_message is not None and parsed_topic[0] == 'time': topic = parsed_topic[0] @@ -211,6 +214,7 @@ def subscribe_weather(self, weather_id, forecast_type): self._client.subscribe('{0}/integration/weather/{1}/{2}'.format(self._username, weather_id, forecast_type)) else: raise TypeError("Invalid Forecast Type Specified.") + return def subscribe_time(self, time): """Subscribe to changes on the Adafruit IO time feeds. When the feed is From aca9f67f5a84e08bd9fbb030ad81d6d9207c2a24 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 14:48:47 -0500 Subject: [PATCH 09/17] redo parser --- Adafruit_IO/mqtt_client.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index 3194f85..30df9c5 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -108,10 +108,9 @@ def _mqtt_message(self, client, userdata, msg): assume topic looks like `username/topic/id` """ parsed_topic = msg.topic.split('/') - if self.on_message is not None: - topic = parsed_topic[1] - payload = '' if msg.payload is None else msg.payload.decode('utf-8') - elif self.on_message is not None and parsed_topic[2] == 'weather': + print(parsed_topic) # BR: Remove this + if self.on_message is not None and parsed_topic[2] == 'weather': + print('Weather Subscription') topic = parsed_topic[4] payload = '' if msg.payload is None else msg.payload.decode('utf-8') elif self.on_message is not None and parsed_topic[0] == 'time': @@ -120,6 +119,9 @@ def _mqtt_message(self, client, userdata, msg): elif self.on_message is not None and parsed_topic[1] == 'groups': topic = parsed_topic[3] payload = msg.payload.decode('utf-8') + else: + topic = parsed_topic[1] + payload = '' if msg.payload is None else msg.payload.decode('utf-8') self.on_message(self, topic, payload) def _mqtt_subscribe(client, userdata, mid, granted_qos): From 7ada7633040cb310b90a694882e509cccffc4477 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 14:52:02 -0500 Subject: [PATCH 10/17] finish parser, tested --- Adafruit_IO/mqtt_client.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index 30df9c5..2e2b158 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -108,10 +108,8 @@ def _mqtt_message(self, client, userdata, msg): assume topic looks like `username/topic/id` """ parsed_topic = msg.topic.split('/') - print(parsed_topic) # BR: Remove this if self.on_message is not None and parsed_topic[2] == 'weather': - print('Weather Subscription') - topic = parsed_topic[4] + topic = parsed_topic[4] # parse out the forecast type payload = '' if msg.payload is None else msg.payload.decode('utf-8') elif self.on_message is not None and parsed_topic[0] == 'time': topic = parsed_topic[0] From 64c42de144857c8a43cbd57af27e05b4da67bef6 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 15:01:11 -0500 Subject: [PATCH 11/17] update example to show 1, 2, 5 day forecasts --- Adafruit_IO/mqtt_client.py | 2 +- examples/mqtt/mqtt_weather.py | 42 ++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index 2e2b158..34d1147 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -117,7 +117,7 @@ def _mqtt_message(self, client, userdata, msg): elif self.on_message is not None and parsed_topic[1] == 'groups': topic = parsed_topic[3] payload = msg.payload.decode('utf-8') - else: + else: # default topic topic = parsed_topic[1] payload = '' if msg.payload is None else msg.payload.decode('utf-8') self.on_message(self, topic, payload) diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py index 06826a2..0f0fb41 100644 --- a/examples/mqtt/mqtt_weather.py +++ b/examples/mqtt/mqtt_weather.py @@ -22,7 +22,7 @@ ADAFRUIT_IO_USERNAME = 'USER' # Set to ID of the forecast to subscribe to for updates -forecast_id = 1234 +forecast_id = 2153 # Set to the ID of the feed to subscribe to for updates. """ @@ -38,7 +38,12 @@ forecast_days_2 forecast_days_5 """ -forecast_type = 'current' +# Subscribe to the current forecast +forecast_today = 'current' +# Subscribe to tomorrow's forecast +forecast_tomorrow = 'forecast_days_2' +# Subscribe to forecast in 5 days +forecast_in_5_days = 'forecast_days_5' # Define callback functions which will be called when certain events happen. def connected(client): @@ -47,20 +52,37 @@ def connected(client): # passed to this function is the Adafruit IO MQTT client so you can make # calls against it easily. print('Connected to Adafruit IO! Listening to forecast: {0}...'.format(forecast_id)) - # Subscribe to changes on a feed named DemoFeed. - client.subscribe_weather(forecast_id, forecast_type) + # Subscribe to changes on the current forecast. + client.subscribe_weather(forecast_id, forecast_today) + + # Subscribe to changes on tomorrow's forecast. + client.subscribe_weather(forecast_id, forecast_tomorrow) + + # Subscribe to changes on forecast in 5 days. + client.subscribe_weather(forecast_id, forecast_in_5_days) def disconnected(client): # Disconnected function will be called when the client disconnects. print('Disconnected from Adafruit IO!') sys.exit(1) -def message(client, feed_id, payload): - # Message function will be called when a subscribed feed has a new value. - # The feed_id parameter identifies the feed, and the payload parameter has - # the new value. - print('Weather Subscription {0} received new value: {1}'.format(forecast_id, payload)) - +def message(client, topic, payload): + """Message function will be called when any subscribed forecast has an update. + Weather data is updated at most once every 20 minutes. + """ + # Raw data from feed + print(topic) + print(payload) + # parse based on topic + if topic is 'current': + # Print out today's forecast + print('Current Forecast: {0}'.format(payload)) + elif topic is 'forecast_days_2': + # print out tomorrow's forecast + print('Forecast Tomorrow: {0}'.format(payload)) + elif topic is 'forecast_days_5': + # print out forecast in 5 days + print('Forecast in 5 Days: {0}'.format(payload)) # Create an MQTT client instance. client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) From 8914f59a310b5c724641c9354a81815737ea68c8 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 15:34:25 -0500 Subject: [PATCH 12/17] parsing 3 forecasts --- examples/mqtt/mqtt_weather.py | 42 +++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py index 0f0fb41..74dea4c 100644 --- a/examples/mqtt/mqtt_weather.py +++ b/examples/mqtt/mqtt_weather.py @@ -8,6 +8,7 @@ # Import standard python modules. import sys +import json # Import Adafruit IO MQTT client. from Adafruit_IO import MQTTClient @@ -41,7 +42,7 @@ # Subscribe to the current forecast forecast_today = 'current' # Subscribe to tomorrow's forecast -forecast_tomorrow = 'forecast_days_2' +forecast_two_days = 'forecast_days_2' # Subscribe to forecast in 5 days forecast_in_5_days = 'forecast_days_5' @@ -56,7 +57,7 @@ def connected(client): client.subscribe_weather(forecast_id, forecast_today) # Subscribe to changes on tomorrow's forecast. - client.subscribe_weather(forecast_id, forecast_tomorrow) + client.subscribe_weather(forecast_id, forecast_two_days) # Subscribe to changes on forecast in 5 days. client.subscribe_weather(forecast_id, forecast_in_5_days) @@ -70,19 +71,32 @@ def message(client, topic, payload): """Message function will be called when any subscribed forecast has an update. Weather data is updated at most once every 20 minutes. """ - # Raw data from feed - print(topic) - print(payload) - # parse based on topic - if topic is 'current': + # forecast based on mqtt topic + if topic == 'current': # Print out today's forecast - print('Current Forecast: {0}'.format(payload)) - elif topic is 'forecast_days_2': - # print out tomorrow's forecast - print('Forecast Tomorrow: {0}'.format(payload)) - elif topic is 'forecast_days_5': - # print out forecast in 5 days - print('Forecast in 5 Days: {0}'.format(payload)) + today_forecast = payload + print('\nCurrent Forecast') + parseForecast(today_forecast) + elif topic == 'forecast_days_2': + # Print out tomorrow's forecast + two_day_forecast = payload + print('\nWeather in Two Days') + parseForecast(two_day_forecast) + elif topic == 'forecast_days_5': + # Print out forecast in 5 days + five_day_forecast = payload + print('\nWeather in 5 Days') + parseForecast(five_day_forecast) + +def parseForecast(forecast_data): + """Parses incoming forecast data + """ + # incoming data is a utf-8 string, encode it as a json object + forecast = json.loads(forecast_data) + print(forecast) + print('It is {0} and {1} F.'.format(forecast['summary'], forecast['temperature'])) + print('with a humidity of {0}% and a wind speed of {1}mph.'.format(forecast['humidity'], forecast['windSpeed'])) + print('There is a {0}% chance of precipitation. It feels like {1} F'.format(forecast['precipProbability'], forecast['apparentTemperature'])) # Create an MQTT client instance. client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) From 25538f923960733aff166892c50ffd09ef492eae Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 15:43:30 -0500 Subject: [PATCH 13/17] show all 3 forecasts nicely --- examples/mqtt/mqtt_weather.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py index 74dea4c..87e9c4f 100644 --- a/examples/mqtt/mqtt_weather.py +++ b/examples/mqtt/mqtt_weather.py @@ -3,6 +3,8 @@ for subscribing to the Adafruit IO Weather Service Note: This feature is avaliable for IO Plus Subscribers ONLY +API Documentation: https://io.adafruit.com/services/weather + Author: Brent Rubell for Adafruit Industries """ @@ -93,10 +95,13 @@ def parseForecast(forecast_data): """ # incoming data is a utf-8 string, encode it as a json object forecast = json.loads(forecast_data) - print(forecast) - print('It is {0} and {1} F.'.format(forecast['summary'], forecast['temperature'])) - print('with a humidity of {0}% and a wind speed of {1}mph.'.format(forecast['humidity'], forecast['windSpeed'])) - print('There is a {0}% chance of precipitation. It feels like {1} F'.format(forecast['precipProbability'], forecast['apparentTemperature'])) + try: + print('It is {0} and of {1}F.'.format(forecast['summary'], forecast['temperature'])) + except KeyError: + # future weather forecasts return a high and low temperature, instead of 'temperature' + print('It will be {0} with a high of {1}F and a low of {2}F.'.format(forecast['summary'], forecast['temperatureLow'], forecast['temperatureHigh'])) + print('with a humidity of {0}% and a wind speed of {1}mph.'.format(forecast['humidity'], forecast['windSpeed'])) + print('There is a {0}% chance of precipitation.'.format(forecast['precipProbability'])) # Create an MQTT client instance. client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) From b2b8b18de96830f3242a9a5ecf40d4372eafbed3 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 15:55:52 -0500 Subject: [PATCH 14/17] same line on example --- examples/mqtt/mqtt_weather.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py index 87e9c4f..80a3866 100644 --- a/examples/mqtt/mqtt_weather.py +++ b/examples/mqtt/mqtt_weather.py @@ -91,17 +91,18 @@ def message(client, topic, payload): parseForecast(five_day_forecast) def parseForecast(forecast_data): - """Parses incoming forecast data + """Parses and prints incoming forecast data """ # incoming data is a utf-8 string, encode it as a json object forecast = json.loads(forecast_data) + + # Print out the forecast try: - print('It is {0} and of {1}F.'.format(forecast['summary'], forecast['temperature'])) + print('It is {0} and {1}F.'.format(forecast['summary'], forecast['temperature'])) except KeyError: # future weather forecasts return a high and low temperature, instead of 'temperature' print('It will be {0} with a high of {1}F and a low of {2}F.'.format(forecast['summary'], forecast['temperatureLow'], forecast['temperatureHigh'])) - print('with a humidity of {0}% and a wind speed of {1}mph.'.format(forecast['humidity'], forecast['windSpeed'])) - print('There is a {0}% chance of precipitation.'.format(forecast['precipProbability'])) + print('with a humidity of {0}%, a wind speed of {1}mph, and a {2}% chance of precipitation.'.format(forecast['humidity'], forecast['windSpeed'], forecast['precipProbability'])) # Create an MQTT client instance. client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) @@ -117,4 +118,4 @@ def parseForecast(forecast_data): # Start a message loop that blocks forever waiting for MQTT messages to be # received. Note there are other options for running the event loop like doing # so in a background thread--see the mqtt_client.py example to learn more. -client.loop_blocking() +client.loop_blocking() \ No newline at end of file From a85047b8b057641595ea9dbe93be4893405a2426 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 16:31:53 -0500 Subject: [PATCH 15/17] correct parsing of default topic --- Adafruit_IO/mqtt_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adafruit_IO/mqtt_client.py b/Adafruit_IO/mqtt_client.py index 34d1147..046669a 100644 --- a/Adafruit_IO/mqtt_client.py +++ b/Adafruit_IO/mqtt_client.py @@ -118,7 +118,7 @@ def _mqtt_message(self, client, userdata, msg): topic = parsed_topic[3] payload = msg.payload.decode('utf-8') else: # default topic - topic = parsed_topic[1] + topic = parsed_topic[2] payload = '' if msg.payload is None else msg.payload.decode('utf-8') self.on_message(self, topic, payload) From abad94df4c0ab5715a3470771f7c50b67c1f3442 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 17:13:45 -0500 Subject: [PATCH 16/17] pylint example --- examples/basics/darksky.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/basics/darksky.py b/examples/basics/darksky.py index 9270576..cd83a8a 100644 --- a/examples/basics/darksky.py +++ b/examples/basics/darksky.py @@ -9,12 +9,12 @@ # Set to your Adafruit IO username. # (go to https://accounts.adafruit.com to find your username) -ADAFRUIT_IO_USERNAME = 'USER' +ADAFRUIT_IO_USERNAME = 'adafruitiotester' # Set to your Adafruit IO key. # Remember, your key is a secret, # so make sure not to publish it when you publish this code! -ADAFRUIT_IO_KEY = 'PASSWORD' +ADAFRUIT_IO_KEY = '1a6995af427747d7bd4a72c97af1d05a' # Create an instance of the REST client. From dc54320ec36fee7e51c4ed7c4ba809f2ae8d3f26 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 8 Jan 2019 17:40:58 -0500 Subject: [PATCH 17/17] update weather, remove broken example --- examples/basics/darksky.py | 29 ------------------- examples/mqtt/mqtt_weather.py | 54 +++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 54 deletions(-) delete mode 100644 examples/basics/darksky.py diff --git a/examples/basics/darksky.py b/examples/basics/darksky.py deleted file mode 100644 index cd83a8a..0000000 --- a/examples/basics/darksky.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -Example of getting a forecast from Adafruit IO -Note: This functionality is for IO PLUS users ONLY. - -Author: Brent Rubell for Adafruit Industries -""" -# import Adafruit IO REST client. -from Adafruit_IO import Client, Feed, RequestError - -# Set to your Adafruit IO username. -# (go to https://accounts.adafruit.com to find your username) -ADAFRUIT_IO_USERNAME = 'adafruitiotester' - -# Set to your Adafruit IO key. -# Remember, your key is a secret, -# so make sure not to publish it when you publish this code! -ADAFRUIT_IO_KEY = '1a6995af427747d7bd4a72c97af1d05a' - - -# Create an instance of the REST client. -aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) - -print('Get all weather integration records without their current forecast values.') -records = aio.receive_weather() -print(records) - -print('Get the specified weather record with current weather and all available forecast information.') -forecast = aio.receive_weather(2153) -print(forecast) \ No newline at end of file diff --git a/examples/mqtt/mqtt_weather.py b/examples/mqtt/mqtt_weather.py index 80a3866..9d148d4 100644 --- a/examples/mqtt/mqtt_weather.py +++ b/examples/mqtt/mqtt_weather.py @@ -49,6 +49,7 @@ forecast_in_5_days = 'forecast_days_5' # Define callback functions which will be called when certain events happen. +# pylint: disable=redefined-outer-name def connected(client): # Connected function will be called when the client is connected to Adafruit IO. # This is a good place to subscribe to feed changes. The client parameter @@ -64,45 +65,48 @@ def connected(client): # Subscribe to changes on forecast in 5 days. client.subscribe_weather(forecast_id, forecast_in_5_days) +# pylint: disable=unused-argument def disconnected(client): # Disconnected function will be called when the client disconnects. print('Disconnected from Adafruit IO!') sys.exit(1) +# pylint: disable=unused-argument def message(client, topic, payload): """Message function will be called when any subscribed forecast has an update. Weather data is updated at most once every 20 minutes. """ # forecast based on mqtt topic if topic == 'current': - # Print out today's forecast - today_forecast = payload - print('\nCurrent Forecast') - parseForecast(today_forecast) + # Print out today's forecast + today_forecast = payload + print('\nCurrent Forecast') + parseForecast(today_forecast) elif topic == 'forecast_days_2': - # Print out tomorrow's forecast - two_day_forecast = payload - print('\nWeather in Two Days') - parseForecast(two_day_forecast) + # Print out tomorrow's forecast + two_day_forecast = payload + print('\nWeather in Two Days') + parseForecast(two_day_forecast) elif topic == 'forecast_days_5': - # Print out forecast in 5 days - five_day_forecast = payload - print('\nWeather in 5 Days') - parseForecast(five_day_forecast) + # Print out forecast in 5 days + five_day_forecast = payload + print('\nWeather in 5 Days') + parseForecast(five_day_forecast) def parseForecast(forecast_data): - """Parses and prints incoming forecast data - """ - # incoming data is a utf-8 string, encode it as a json object - forecast = json.loads(forecast_data) - - # Print out the forecast - try: - print('It is {0} and {1}F.'.format(forecast['summary'], forecast['temperature'])) - except KeyError: - # future weather forecasts return a high and low temperature, instead of 'temperature' - print('It will be {0} with a high of {1}F and a low of {2}F.'.format(forecast['summary'], forecast['temperatureLow'], forecast['temperatureHigh'])) - print('with a humidity of {0}%, a wind speed of {1}mph, and a {2}% chance of precipitation.'.format(forecast['humidity'], forecast['windSpeed'], forecast['precipProbability'])) + """Parses and prints incoming forecast data + """ + # incoming data is a utf-8 string, encode it as a json object + forecast = json.loads(forecast_data) + # Print out the forecast + try: + print('It is {0} and {1}F.'.format(forecast['summary'], forecast['temperature'])) + except KeyError: + # future weather forecasts return a high and low temperature, instead of 'temperature' + print('It will be {0} with a high of {1}F and a low of {2}F.'.format( + forecast['summary'], forecast['temperatureLow'], forecast['temperatureHigh'])) + print('with humidity of {0}%, wind speed of {1}mph, and {2}% chance of precipitation.'.format( + forecast['humidity'], forecast['windSpeed'], forecast['precipProbability'])) # Create an MQTT client instance. client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) @@ -118,4 +122,4 @@ def parseForecast(forecast_data): # Start a message loop that blocks forever waiting for MQTT messages to be # received. Note there are other options for running the event loop like doing # so in a background thread--see the mqtt_client.py example to learn more. -client.loop_blocking() \ No newline at end of file +client.loop_blocking()