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 normal 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.  If you would like to know more about MQTT, please take a look at this excellent

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 examples.  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 usages of the Raspberry Pi will be measured and published to ThingSpeak every 20 seconds.

First you will need to install the Paho client library.  On your Raspberry Pi, open a terminal and enter this on the command line:

sudo pip install paho-mqtt

Next you will need a ThingSpeak account and you will need to create a channel with two fields.   Here are instructions for creating a new channel.  In this example, you will be using two fields named “CPU (%)” and “RAM (%)”.

Publishing to ThingSpeak Example

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

There are three MQTT connection methods 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 to only set one on 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.

# ThingSpeak Update Using MQTT
# Copyright 2016, MathWorks, Inc

# 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

from __future__ import print_function
import paho.mqtt.publish as publish
import psutil

###   Start of user configuration   ###   

#  ThingSpeak Channel Settings

# The ThingSpeak Channel ID
# Replace this with your Channel ID
channelID = "XXXX"

# The Write API Key for the channel
# Replace this with your Write API key
apiKey = "XXXXYYYYXXXXYYYY"

#  MQTT Connection Methods

# Set useUnsecuredTCP to True to use the default MQTT port of 1883
# This type of unsecured MQTT connection uses the least amount of system resources.
useUnsecuredTCP = False

# Set useUnsecuredWebSockets to True to use MQTT over an unsecured websocket on port 80.
# Try this if port 1883 is blocked on your network.
useUnsecuredWebsockets = False

# Set useSSLWebsockets to True to use MQTT over a secure websocket on port 443.
# This type of connection will use slightly more system resources, but the connection
# will be secured by SSL.
useSSLWebsockets = True

###   End of user configuration   ###

# The Hostname of the ThinSpeak MQTT service
mqttHost = "mqtt.thingspeak.com"

# Set up the connection parameters based on the connection type
if useUnsecuredTCP:
    tTransport = "tcp"
    tPort = 1883
    tTLS = None

if useUnsecuredWebsockets:
    tTransport = "websockets"
    tPort = 80
    tTLS = None

if useSSLWebsockets:
    import ssl
    tTransport = "websockets"
    tTLS = {'ca_certs':"/etc/ssl/certs/ca-certificates.crt",'tls_version':ssl.PROTOCOL_TLSv1}
    tPort = 443
        
# Create the topic string
topic = "channels/" + channelID + "/publish/" + apiKey

# Run a loop which calculates the system performance every
#   20 seconds and published that to a ThingSpeak channel
#   using MQTT.
while(True):
    
    # get the system performance data
    cpuPercent = psutil.cpu_percent(interval=20)
    ramPercent = psutil.virtual_memory().percent
    print (" CPU =",cpuPercent,"   RAM =",ramPercent)

    # build the payload string
    tPayload = "field1=" + str(cpuPercent) + "&field2=" + str(ramPercent)

    # attempt to publish this data to the topic 
    try:
        publish.single(topic, payload=tPayload, hostname=mqttHost, port=tPort, tls=tTLS, transport=tTransport)

    except (KeyboardInterrupt):
        break

    except:
        print ("There was an error while publishing the data.")