Skip to content

Commit

Permalink
Merge pull request #46 from brentru/add-callback-feed
Browse files Browse the repository at this point in the history
Add feed callback mechanism
  • Loading branch information
brentru committed Sep 28, 2020
2 parents 2d3de68 + aff8b4c commit e458105
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 17 deletions.
44 changes: 27 additions & 17 deletions adafruit_io/adafruit_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ def __exit__(self, exception_type, exception_value, traceback):
self.disconnect()

def reconnect(self):
"""Attempts to reconnect to the Adafruit IO MQTT Broker.
"""
"""Attempts to reconnect to the Adafruit IO MQTT Broker."""
try:
self._client.reconnect()
except Exception as err:
Expand All @@ -118,8 +116,7 @@ def connect(self):
raise AdafruitIO_MQTTError("Unable to connect to Adafruit IO.") from err

def disconnect(self):
"""Disconnects from Adafruit IO MQTT Broker.
"""
"""Disconnects from Adafruit IO MQTT Broker."""
if self._connected:
self._client.disconnect()

Expand All @@ -130,8 +127,7 @@ def is_connected(self):

# pylint: disable=not-callable, unused-argument
def _on_connect_mqtt(self, client, userdata, flags, return_code):
"""Runs when the client calls on_connect.
"""
"""Runs when the client calls on_connect."""
if self._logger:
self._client._logger.debug("Client called on_connect.")
if return_code == 0:
Expand All @@ -144,8 +140,7 @@ def _on_connect_mqtt(self, client, userdata, flags, return_code):

# pylint: disable=not-callable, unused-argument
def _on_disconnect_mqtt(self, client, userdata, return_code):
"""Runs when the client calls on_disconnect.
"""
"""Runs when the client calls on_disconnect."""
if self._logger:
self._client._logger.debug("Client called on_disconnect")
self._connected = False
Expand Down Expand Up @@ -195,22 +190,39 @@ def _on_message_mqtt(self, client, topic, payload):

# pylint: disable=not-callable
def _on_subscribe_mqtt(self, client, user_data, topic, qos):
"""Runs when the client calls on_subscribe.
"""
"""Runs when the client calls on_subscribe."""
if self._logger:
self._client._logger.debug("Client called on_subscribe")
if self.on_subscribe is not None:
self.on_subscribe(self, user_data, topic, qos)

# pylint: disable=not-callable
def _on_unsubscribe_mqtt(self, client, user_data, topic, pid):
"""Runs when the client calls on_unsubscribe.
"""
"""Runs when the client calls on_unsubscribe."""
if self._logger:
self._client._logger.debug("Client called on_unsubscribe")
if self.on_unsubscribe is not None:
self.on_unsubscribe(self, user_data, topic, pid)

def add_feed_callback(self, feed_key, callback_method):
"""Executes callback_method whenever a message is
received on feed_key.
:param str feed_key: Adafruit IO feed key.
:param str callback_method: Name of callback method.
"""
self._client.add_topic_callback(
"{0}/feeds/{1}".format(self._user, feed_key), callback_method
)

def remove_feed_callback(self, feed_key):
"""Removes a previously registered callback method
from executing whenever feed_key receives new data.
:param str feed_key: Adafruit IO feed key.
"""
self._client.remove_topic_callback("{0}/feeds/{1}".format(self._user, feed_key))

def loop(self):
"""Manually process messages from Adafruit IO.
Call this method to check incoming subscription messages.
Expand Down Expand Up @@ -464,16 +476,14 @@ def __init__(self, adafruit_io_username, adafruit_io_key, wifi_manager):

@staticmethod
def _create_headers(io_headers):
"""Creates http request headers.
"""
"""Creates http request headers."""
headers = CLIENT_HEADERS.copy()
headers.update(io_headers)
return headers

@staticmethod
def _create_data(data, metadata):
"""Creates JSON data payload
"""
"""Creates JSON data payload"""
if metadata is not None:
return {
"value": data,
Expand Down
132 changes: 132 additions & 0 deletions examples/adafruit_io_mqtt/adafruit_io_feed_callback.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import time

import board
import busio
from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
import neopixel
import adafruit_minimqtt.adafruit_minimqtt as MQTT
from adafruit_io.adafruit_io import IO_MQTT

### WiFi ###

# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise

# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
"""Use below for Most Boards"""
status_light = neopixel.NeoPixel(
board.NEOPIXEL, 1, brightness=0.2
) # Uncomment for Most Boards
"""Uncomment below for ItsyBitsy M4"""
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Uncomment below for an externally defined RGB LED
# import adafruit_rgbled
# from adafruit_esp32spi import PWMOut
# RED_LED = PWMOut.PWMOut(esp, 26)
# GREEN_LED = PWMOut.PWMOut(esp, 27)
# BLUE_LED = PWMOut.PWMOut(esp, 25)
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)

# Define callback functions which will be called when certain events happen.
# pylint: disable=unused-argument
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 DemoFeed changes...")


def subscribe(client, userdata, topic, granted_qos):
# This method is called when the client subscribes to a new feed.
print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))


def unsubscribe(client, userdata, topic, pid):
# This method is called when the client unsubscribes from a feed.
print("Unsubscribed from {0} with PID {1}".format(topic, pid))


# pylint: disable=unused-argument
def disconnected(client):
# Disconnected function will be called when the client disconnects.
print("Disconnected from Adafruit IO!")


# pylint: disable=unused-argument
def on_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("Feed {0} received new value: {1}".format(feed_id, payload))


def on_battery_msg(client, topic, message):
# Method called whenever user/feeds/battery has a new value
print("Battery level: {}v".format(message))


# Connect to WiFi
print("Connecting to WiFi...")
wifi.connect()
print("Connected!")

# Initialize MQTT interface with the esp interface
MQTT.set_socket(socket, esp)

# Initialize a new MQTT Client object
mqtt_client = MQTT.MQTT(
broker="io.adafruit.com",
username=secrets["aio_username"],
password=secrets["aio_key"],
)

# Initialize an Adafruit IO MQTT Client
io = IO_MQTT(mqtt_client)

# Connect the callback methods defined above to Adafruit IO
io.on_connect = connected
io.on_disconnect = disconnected
io.on_subscribe = subscribe
io.on_unsubscribe = unsubscribe
io.on_message = on_message

# Connect to Adafruit IO
print("Connecting to Adafruit IO...")
io.connect()

# Set up a message handler for the battery feed
io.add_feed_callback("battery", on_battery_msg)

# Subscribe to all messages on the battery feed
io.subscribe("battery")

# Start a blocking loop to check for new messages
while True:
try:
io.loop()
except (ValueError, RuntimeError) as e:
print("Failed to get data, retrying\n", e)
wifi.reset()
io.reconnect()
continue
time.sleep(0.5)

0 comments on commit e458105

Please sign in to comment.