# Part 3: Adafruit IO (MQTT & Webhooks) ###### tags: `TA Stuff RP2` `Raspberry Pi Pico` This tutorial covers how to work with Adafruit IO, the IoT platform made by Adafruit. You will learn: + How to register and set up a dashboard in Adafruit IO. + How to send data over **MQTT** to your dashboard in Adafruit IO and visualize it on a chart. + How to control your board LED from your Adafruit IO control panel. + How to trigger an event captured by Adafruit and send a **Webhook** message to your Discord server. As always, we'll continuously update this walkthrough. **Is there anything that needs to be clarified, or have you experienced some issues? Please add a comment.** You do this by highlighting the text and then you can write a comment on the highlighted part. You need to log in/create an account on HackMD first. Before we dive into the how-to-make such a connection we should get familiar with Adafruit **Terms** in the next section. ## Adafruit IO terms Each IoT cloud platform uses its terminology for different actions and It would be valuable to know them before starting working with them. So before signing up and using Adafruit IO read the following terms, we gathered from Adafruit documentation. **Devices:** You can connect your devices without writing a single line of code using Adafruit custom WipperSnapper firmware. Simply load the WipperSnapper firmware onto your board, add credentials, and plug it into power. Your board will automatically register itself with your Adafruit IO account. **We suggest you not to use this, although it is available for Raspberry Pi Pico W. The reason is that you do not learn coding by using pre made code.** **Feed:** Feeds are the core of the Adafruit IO system. The feed contains the sensor data values that get pushed to Adafruit IO from your device, like temperature value. It also could be the value you need to send from your control panel to the device to control it, like turning on a lamp. **Blocks:** Blocks are widgets that you can use to visualize feeds. It could be a gauge, a table, or a line chart to visualize data pushed from your device to the feed. Or it could be a toggle switch or a slider to send your commands from the Adafruit control panel to your device. **Dashboard:** Dashboards allow you to visualize data and control Adafruit IO-connected projects from any modern web browser. Before being able to add any block to visualize your data you need a dashboard, and basically, it is a place to hold several blocks for each project. **Action:** Actions will initiate a triggered action on a condition. There are two types of actions in Adagruit IO: * **Reactive Action:** *It will be activated by a condition met from a feed value, like if the temperature reached a certain threshold send an alarm.* **(This is what we learn in this tutorial)** * **Schedule Action:** *It will periodically trigger a command and work as a scheduler, like sending an open/close valve command to our board.* Adafruit IO supports the following three trigger reactions: * **Email me:** *It will email the triggered action to your desired email address.* * **Send a Webhook message to:** *It can send a webhook message to a platform like sending a message to your Discord.* **(This is what we learn in this tutorial)** * **Publish a message to:** *It could also change the state of a feed value so your development board can subscribe to the MQTT and read it.* ## Setting Environment in Adafruit IO In this part we show how to set up **Feeds** and **Blocks** to receive a random value and visualize it on a chart plus define a button to control our onboard LED (On/OFF). follow these steps: + **Step 1:** Visit [**this link**](https://accounts.adafruit.com/users/sign_up) to register an account on Adafruit IO. You should provide a **UserName** which is a unique value and need it later to log in and send data to your control panel. + **Step 2:** Visit [**this link**](https://io.adafruit.com/) to sign in to your control panel. + **Step 3:** Choose **IO** on top of the page and if you can not see any settings press on **Sign in** on the top right corner to see your control panel. + **Step 4:** In the IO top panel navigate to: `Feeds` >> `+ New Feed` to create a feed. We basically give a feed a `Name` and `Description` then click on `Create`. **We will create the two following feeds:** - `randoms`: A random value generated from the development board (between 0 - 100) and pushed to Adafuit to show it in a line chart. It is a temperature simulation and you can use the same technique to show temperature value. - `lights`: this feed controls the development board LED and you can turn it on/off from the Adafruit control panel. It is useful when you need to hold something remotely. Your control panel should look like this after creating feeds: ![](https://i.imgur.com/K0w4V9M.jpg) <br> + **Step 5:** In your control panel navigate to: `Dashboards` >> `+ New Dashboard` to create a dashboard. Then click on it and from the right panel like the following screenshot we will add two `Blocks` to our dashboard. ![](https://hackmd.io/_uploads/BJIKbrP8n.jpg) <br> + **Step 6:** We create a `Toggle Block` and connect it to `lights Feed` then create a `Line Chart Block` and connect it to `randoms Feed`. - **Line Chart:** As mentioned above they use a line chart to connect it to the “randoms” feed to show pushed values from your device. - **Toggle Switch:** This switch is used to send “ON/OFF” commands to the “lights” feed then your development board can subscribe to the feed and based on the state of the “lights” feed turn on/off your board LED. ![](https://hackmd.io/_uploads/Hk-8Mrw8h.png) <br> + **Step 7:** After making feeds you can click on the setting `Edit Layout` to make the size of charts and toggle button according to your need. Your dashboard should look like this: ![](https://i.imgur.com/2GN2Z5b.jpg) <br> + **Step 8:** We are ready now, we need to copy our credentials (**`Username and Active Key`**) which we can fetch from the `My Key` on the top right in our control panel. ![](https://hackmd.io/_uploads/BJl7BrDIh.png) + **Step 9:** We also need the address to our `lights` and `ransoms` Feed which we can get from (`Feeds` >> `Selected Feed` >> `Feed Info` >> `MQTT by key` value. We will paste them into our code to be able to `Publish` and `Subscribe` for the Adafruit **MQTT** server. <br> ![](https://hackmd.io/_uploads/r1v8LSvLn.png) <br> ## Project Code (Publish & Subscribe) To Adafruit MQTT Server Now we are set to make our project in Atom and run it. (**Note we have used the PyCom device RGB LED in this project you can adjust it for your development board**). Follow these steps: + **Step 1:** Create a project in VS Code, create a file named `mqtt.py` and copy the content of the file in [**this link**](https://github.com/iot-lnu/pico-w/blob/main/network-examples/N2_WiFi_MQTT_Webhook_Adafruit/lib/mqtt.py). Do the same for `wifiConnection.py`([code here](https://github.com/iot-lnu/pico-w/blob/main/network-examples/N2_WiFi_MQTT_Webhook_Adafruit/lib/wifiConnection.py)) and `keys.py`([code here](https://github.com/iot-lnu/pico-w/blob/main/network-examples/N2_WiFi_MQTT_Webhook_Adafruit/lib/keys.py)) and be sure to update the keys to match your WiFi and Adafruit IO credentials. + **Step 2:** Make `main.py` and copy the following lines in it. Read the code thoroughly it is self-commented: ```python= import time # Allows use of time.sleep() for delays from mqtt import MQTTClient # For use of MQTT protocol to talk to Adafruit IO import machine # Interfaces with hardware components import micropython # Needed to run any MicroPython code import random # Random number generator from machine import Pin # Define pin import keys # Contain all keys used here import wifiConnection # Contains functions to connect/disconnect from WiFi # BEGIN SETTINGS # These need to be change to suit your environment RANDOMS_INTERVAL = 20000 # milliseconds last_random_sent_ticks = 0 # milliseconds led = Pin("LED", Pin.OUT) # led pin initialization for Raspberry Pi Pico W # Callback Function to respond to messages from Adafruit IO def sub_cb(topic, msg): # sub_cb means "callback subroutine" print((topic, msg)) # Outputs the message that was received. Debugging use. if msg == b"ON": # If message says "ON" ... led.on() # ... then LED on elif msg == b"OFF": # If message says "OFF" ... led.off() # ... then LED off else: # If any other message is received ... print("Unknown message") # ... do nothing but output that it happened. # Function to generate a random number between 0 and the upper_bound def random_integer(upper_bound): return random.getrandbits(32) % upper_bound # Function to publish random number to Adafruit IO MQTT server at fixed interval def send_random(): global last_random_sent_ticks global RANDOMS_INTERVAL if ((time.ticks_ms() - last_random_sent_ticks) < RANDOMS_INTERVAL): return; # Too soon since last one sent. some_number = random_integer(100) print("Publishing: {0} to {1} ... ".format(some_number, keys.AIO_RANDOMS_FEED), end='') try: client.publish(topic=keys.AIO_RANDOMS_FEED, msg=str(some_number)) print("DONE") except Exception as e: print("FAILED") finally: last_random_sent_ticks = time.ticks_ms() # Try WiFi Connection try: ip = wifiConnection.connect() except KeyboardInterrupt: print("Keyboard interrupt") # Use the MQTT protocol to connect to Adafruit IO client = MQTTClient(keys.AIO_CLIENT_ID, keys.AIO_SERVER, keys.AIO_PORT, keys.AIO_USER, keys.AIO_KEY) # Subscribed messages will be delivered to this callback client.set_callback(sub_cb) client.connect() client.subscribe(keys.AIO_LIGHTS_FEED) print("Connected to %s, subscribed to %s topic" % (keys.AIO_SERVER, keys.AIO_LIGHTS_FEED)) try: # Code between try: and finally: may cause an error # so ensure the client disconnects the server if # that happens. while 1: # Repeat this loop forever client.check_msg()# Action a message if one is received. Non-blocking. send_random() # Send a random number to Adafruit IO if it's time. finally: # If an exception is thrown ... client.disconnect() # ... disconnect the client and clean up. client = None wifiConnection.disconnect() print("Disconnected from Adafruit IO.") ``` :::info The above code sends a random value (between 0 and 100) at random time intervals to your Adafruit control panel by publishing it to their MQTT server. It also subscribes to the same server and while you change the toggle button state (ON/OFF) it turns the LED on your Raspberry Pi Pico accordingly. ::: <br/><br/> ## Webhooks in Adafruit and sending messages to the Discord server In this simple tutorial, we will activate the webhook link in our Discord channel, and based on the `randoms` values pushed from the development board if the value is above `80` we forward the value to the Discord. Following we first create a webhook in the Discord and then send the triggered value from Adafruit IO to it. ### Creating a server and activating webhook on a channel in Discord **Step 1:** Open Discord and from the left pane click on `+` to **Add a Server**. **Step 2:** From the pop-up window choose **Create My Own**. **Step 3:** Next window choose **For me and my friends**. **Step 4:** Give it a name like `LNU Project` and click on **Create**. **Step 5:** By default you have a `general` channel click on the `gear` sign close to it. ![](https://i.imgur.com/2BXIez3.jpg) **Step 6:** Click on `Integrations` then on `Create Webhook`. ![](https://i.imgur.com/eRehzeY.jpg) **Step 7:** Click on `Copy Webhook URL` and save the link somewhere that you need later. ![](https://i.imgur.com/X6xFaTA.jpg) **Step 8:** Finally click on `ESC` in the top right corner to close the window. We are done in Discord. ### Adding a trigger in Adafruit and connect it to your webhook **Step 1:** Login to your Adafruit IO control panel >> click on `Actions` >> click on `+ New Action` ![](https://hackmd.io/_uploads/SJexKwdU3.png) </br> **Step 2:** Choose `Reactive` action in the next page. ![](https://hackmd.io/_uploads/ByisKP_In.png) **Step 2:** Do the following steps: 1. Choose `randoms` 2. Choose `greater than` 3. Enter `80` 4. Choose `send a webhook message to:` 5. Paste the webhook link you got from Discord 6. choose `randoms` 7. choose `Discord Template` 8. choose `Limit every fifteen minutes` 9. click on `Submit` ![](https://hackmd.io/_uploads/ryJXovdL2.png) </br> **Step 3:** Everything is set and you can see a new action in the actions’ list. ![](https://hackmd.io/_uploads/SkkZ2vOLn.png) ### Results Now you can run your code and if your board uploaded a value greater than `80` it will forward it to your Discord. You also can turn on/off led on Raspberry Pi Pico with toggle button in Adafruit dashboard. ![](https://hackmd.io/_uploads/ByxsJCvUn.png) <br/> :::warning **⚠️Attention⚠️ Don’t bug Discord by sending too many Webhooks, Adafruit will disable it if recognize too many requests.** ::: </br></br> :::success If you reach here, it means you have successfully tested MQTT and Webhooks on Adafruit IO. You are ready for your project, Good Luck! ::: *[MQTT]: Message Queuing Telemetry Transport <style> html, body, .ui-content { background-color: #333; color: #ddd; } body > .ui-infobar { display: none; } .ui-view-area > .ui-infobar { display: block; } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { color: #ddd; } .markdown-body h1, .markdown-body h2 { border-bottom-color: #ffffff69; } .markdown-body h1 .octicon-link, .markdown-body h2 .octicon-link, .markdown-body h3 .octicon-link, .markdown-body h4 .octicon-link, .markdown-body h5 .octicon-link, .markdown-body h6 .octicon-link { color: #fff; } .markdown-body img { background-color: transparent; } .ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a { color: white; border-left: 2px solid white; } .expand-toggle:hover, .expand-toggle:focus, .back-to-top:hover, .back-to-top:focus, .go-to-bottom:hover, .go-to-bottom:focus { color: white; } .ui-toc-dropdown { background-color: #333; } .ui-toc-label.btn { background-color: #191919; color: white; } .ui-toc-dropdown .nav>li>a:focus, .ui-toc-dropdown .nav>li>a:hover { color: white; border-left: 1px solid white; } .markdown-body blockquote { color: #fff; } .markdown-body table tr { background-color: #5f5f5f; } .markdown-body table tr:nth-child(2n) { background-color: #4f4f4f; } .markdown-body code, .markdown-body tt { color: #f; background-color: rgba(230, 230, 230, 0.36); } a, .open-files-container li.selected a { color: #5EB7E0; } .markdown-body pre { color: black; } </style>