Update a ThingSpeak Channel using MQTT on a Raspberry Pi

ThingSpeak has added MQTT as a method to accept channel updates.  MQTT is different from HTTP/REST. It is specifically designed to be lightweight and intended for embedded devices with low RAM and CPU performance.  Also, in most cases, MQTT uses less bandwidth.

MQTT operates under a publish/subscribe model in which clients connect to the MQTT broker and either publish data or subscribe to topics to receive data from other clients.  MQTT messages can be sent using unsecured TCP, which is the easiest and has the lower RAM, CPU, and bandwidth requirements.  MQTT messages can also be sent using WebSockets.  This may be needed for situations when the standard port for MQTT, 1883, is blocked on the network.  When using MQTT over WebSockets, it is possible to encrypt the communication with SSL.  If your hardware is capable of using SSL over a WebSocket, that is the recommended method.

On the Raspberry Pi, an MQTT client library is required to send data to ThingSpeak.  Paho is an open-source MQTT client library that will be used for this example.  It has been adapted to many languages, including Python.

This example will demonstrate how to publish data to a ThingSpeak channel using the Paho library.  The CPU and RAM usage of the Raspberry Pi will be measured and published to ThingSpeak every 20 seconds.

Setup

1) Create a new channel as shown in Collect Data in a New Channel with two fields named “CPU (%)” and “RAM (%)”.

2) Create an MQTT device by clicking Devices > MQTT at the top of the ThingSpeak page, then Add Device. When setting up the device and adding the new channel to its authorized list, click Download Credentials > Plain Text. For details, see Create a ThingSpeak MQTT Device. Use the saved credentials in the Code section below.

3) Download the Paho MQTT client library for Python. You can use the command line to install the libraries. If you are using Python 2, use this code:

sudo pip install paho-mqtt
sudo pip install psutil

If you use Python 3, use this code:

sudo pip3 install paho-mqtt
sudo pip3 install psutil

Publishing to ThingSpeak Example

This example shows how simple it can be to send data to ThingSpeak using MQTT.

Three MQTT connection methods are demonstrated in this example: TCP, WebSockets, and SSL. To use a conventional TCP socket on port 1883, set useUnsecuredTCP=True.  This connection method is the simplest and requires the least system resources.  To use WebSockets on port 80, set useUnsecuredWebsockets=True.  Websockets are helpful when the default MQTT port is blocked on the local network.  Finally, if encryption is required, set useSSLWebsockets=True.   Be sure only to set one of the connection method variables to True and leave the other two False.

Also, be sure to change the channel ID and API key to your channel’s settings.

# Publich to a ThingSpeak Channel Using MQTT
# 
# This is an example of publishing to multiple fields simultaneously.
# Connections over standard TCP, websocket or SSL are possible by setting
# the parameters below.
#
# CPU and RAM usage is collected every 20 seconds and published to a
# ThingSpeak channel using an MQTT Publish
#
# This example requires the Paho MQTT client package which
# is available at: http://eclipse.org/paho/clients/python
import paho.mqtt.publish as publish
import psutil
import string

# The ThingSpeak Channel ID.
# Replace <YOUR-CHANNEL-ID> with your channel ID.
channel_ID = "<YOUR-CHANNEL-ID>"

# The hostname of the ThingSpeak MQTT broker.
mqtt_host = "mqtt3.thingspeak.com"

# Your MQTT credentials for the device
mqtt_client_ID = "<YOUR-CLIENT-ID>"
mqtt_username  = "<YOUR-USERNAME>"
mqtt_password  = "<YOUR-MQTT-PASSWORD>"

t_transport = "websockets"
t_port = 80

# Create the topic string.
topic = "channels/" + channel_ID + "/publish"

while (True):

    # get the system performance data over 20 seconds.
    cpu_percent = psutil.cpu_percent(interval=20)
    ram_percent = psutil.virtual_memory().percent

    # build the payload string.
    payload = "field1=" + str(cpu_percent) + "&field2=" + str(ram_percent)

    # attempt to publish this data to the topic.
    try:
        print ("Writing Payload = ", payload," to host: ", mqtt_host, " clientID= ", mqtt_client_ID, " User ", mqtt_username, " PWD ", mqtt_password)
        publish.single(topic, payload, hostname=mqtt_host, transport=t_transport, port=t_port, client_id=mqtt_client_ID, auth={'username':mqtt_username,'password':mqtt_password})
    except (keyboardInterrupt)
        break
    except Exception as e:
        print (e)