Set up the PyPortal's D3 pin as a DigitalInOut object and set the direction to output. 

# Set up a pin for controlling the relay
power_pin = DigitalInOut(board.D3)
power_pin.switch_to_output()

Now, set up the relay feed as a string variable named feed_relay

### Feeds ###
# Set up a feed named Relay for subscribing to the relay feed on Adafruit IO
feed_relay = secrets["aio_username"] + "/feeds/relay"

The following code snippet consists of MQTT callback methods. For an explanation of how these methods function, please see this section of the MQTT in CircuitPython guide.

### Code ###

# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connected(client, userdata, flags, rc):
    # This function will be called when the client is connected
    # successfully to the broker.
    print("Connected to Adafruit IO!")

def disconnected(client, userdata, rc):
    # This method is called when the client is disconnected
    print("Disconnected from Adafruit IO!")

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

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))

def on_message(client, topic, message):
    # Method callled when a client's subscribed feed has a new value.
    print("New message on topic {0}: {1}".format(topic, message))

When the Adafruit IO feed Your-AIO-Username/feeds/relay receives new data, the following method executes and evaluates the value on the feed.

If the value is "ON", the relay is turned on by setting the pin high. If the value is "OFF", the relay is turned off by setting the pin low. 

def on_relay_msg(client, topic, value):
    # Called when relay feed obtains a new value
    print("Turning Relay %s"%value)
    if value == "ON":
        power_pin.value = True
    elif value == "OFF":
        power_pin.value = False
    else:
        print("Unexpected value received on relay feed.")

Next, connect to the WiFi network and set up a MQTT client to connect to Adafruit IO's MQTT broker with your credentials.

MQTT.set_socket(socket, esp)

# Set up a MiniMQTT Client
client = MQTT.MQTT(
    broker="io.adafruit.com",
    username=secrets["aio_username"],
    password=secrets["aio_key"],
)

Now, set up the callback methods above by connecting them to the client's default callback properties. 

# Setup the callback methods above
client.on_connect = connected
client.on_disconnect = disconnected
client.on_subscribe = subscribe
client.on_unsubscribe = unsubscribe
client.on_message = on_message

The on_relay_message method is not a default MiniMQTT client callback, so it's added as a custom callback, which will execute on_relay_msg() when new data is received.

# Add a callback to the relay feed
client.add_topic_callback(feed_relay, on_relay_msg)

Connect to the Adafruit IO MQTT broker and subscribe to the relay feed.

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

# Subscribe to all updates on relay feed
client.subscribe(feed_relay)

The code within the while True loop will check for new messages on the relay feed every 50 milliseconds. If there's an issue with the network connection, the WiFi connection will reset and the MQTT client will reconnect to Adafruit IO.

while True:
    try: # Poll for new messages on feed_relay
        client.loop()
    except (ValueError, RuntimeError) as e:
        print("Failed to get data, retrying\n", e)
        wifi.reset()
        client.reconnect()
        continue
    time.sleep(0.05)

This guide was first published on Sep 22, 2020. It was last updated on Sep 22, 2020.

This page (Code Walkthrough) was last updated on Jun 12, 2021.

Text editor powered by tinymce.