Publish and Subscribe to a ThingSpeak Channel Using Secure MQTT
This example shows how to use an ESP8266 board to record RSSI data in ThingSpeak™ via secure MQTT. You can modify the code as indicated in its comments to adapt it for other boards or nonsecure MQTT.
Setup
1) Create a ThingSpeak channel, as shown in Collect Data in a New Channel.
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) Add the ESP8266 Board Package:
a. Under File > Preferences, enter https://arduino.esp8266.com/stable/package_esp8266com_index.json
into Additional Board Manager URLs.
b. Select Tools > Boards > Board Manager. Enter ESP8266
in the search bar and install the package.
4) Download the libraries WiFi.h
and WiFiClientSecure.h
to your Arduino IDE.
Code
1) Define the wireless network, ThingSpeak MQTT credentials to connect your board, connection security, and include appropriate libraries. Edit this code for your particular credentials and setup.
// Ensure correct credentials to connect to your WiFi Network. char ssid[] = "ENTER_YOUR_WIFI_SSID"; char pass[] = "ENTER_YOUR_WIFI_PASSWORD"; // Ensure that the credentials here allow you to publish and subscribe to the ThingSpeak channel. #define channelID ENTER_YOUR_THINGSPEAK_CHANNEL_NUMBER const char mqttUserName[] = "ENTER_YOUR_MQTT_USERNAME"; const char clientID[] = "ENTER_YOUR_MQTT_CLIENT_ID"; const char mqttPass[] = "ENTER_YOUR_MQTT_PASSWORD"; // It is strongly recommended to use secure connections. However, certain hardware does not work with the WiFiClientSecure library. // Comment out the following #define to use non-secure MQTT connections to ThingSpeak server. #define USESECUREMQTT // Comment the following line if not using an ESP8266. #define ESP8266BOARD #include <PubSubClient.h> #ifdef ESP8266BOARD #include <ESP8266WiFi.h> const char* PROGMEM thingspeak_cert_thumbprint = "9780c25078532fc0fd03dae01bfd8c923fff9878"; #else #include <WiFi.h> const char * PROGMEM thingspeak_ca_cert = \ "-----BEGIN CERTIFICATE-----\n" \ "MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\n" \ "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \ "d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n" \ "ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\n" \ "MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n" \ "LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\n" \ "RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n" \ "+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\n" \ "PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\n" \ "xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\n" \ "Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\n" \ "hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\n" \ "EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\n" \ "MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\n" \ "FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\n" \ "nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\n" \ "eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\n" \ "hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\n" \ "Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\n" \ "vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n" \ "+OkuE6N36B9K\n" \ "-----END CERTIFICATE-----\n"; #endif #ifdef USESECUREMQTT #include <WiFiClientSecure.h> #define mqttPort 8883 WiFiClientSecure client; #else #define mqttPort 1883 WiFiClient client; #endif
2) Define connection parameters and initialize a PubSubClient
instance.
const char* server = "mqtt3.thingspeak.com"; int status = WL_IDLE_STATUS; long lastPublishMillis = 0; int connectionDelay = 1; int updateInterval = 15; PubSubClient mqttClient( client );
3) Process incoming subscription messages, subscribe to receive updates, and publish messages.
// Function to handle messages from MQTT subscription. void mqttSubscriptionCallback( char* topic, byte* payload, unsigned int length ) { // Print the details of the message that was received to the serial monitor. Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); } // Subscribe to ThingSpeak channel for updates. void mqttSubscribe( long subChannelID ){ String myTopic = "channels/"+String( subChannelID )+"/subscribe"; mqttClient.subscribe(myTopic.c_str()); } // Publish messages to a ThingSpeak channel. void mqttPublish(long pubChannelID, String message) { String topicString ="channels/" + String( pubChannelID ) + "/publish"; mqttClient.publish( topicString.c_str(), message.c_str() ); }
4) Connect to WiFi and the MQTT server.
// Connect to WiFi. void connectWifi() { Serial.print( "Connecting to Wi-Fi..." ); // Loop until WiFi connection is successful #ifdef ESP8266BOARD while ( WiFi.waitForConnectResult() != WL_CONNECTED ) { #else while ( WiFi.status() != WL_CONNECTED ) { #endif WiFi.begin( ssid, pass ); delay( connectionDelay*1000 ); Serial.print( WiFi.status() ); } Serial.println( "Connected to Wi-Fi." ); } // Connect to MQTT server. void mqttConnect() { // Loop until connected. while ( !mqttClient.connected() ) { // Connect to the MQTT broker. if ( mqttClient.connect( clientID, mqttUserName, mqttPass ) ) { Serial.print( "MQTT to " ); Serial.print( server ); Serial.print (" at port "); Serial.print( mqttPort ); Serial.println( " successful." ); } else { Serial.print( "MQTT connection failed, rc = " ); // See https://pubsubclient.knolleary.net/api.html#state for the failure code explanation. Serial.print( mqttClient.state() ); Serial.println( " Will try again in a few seconds" ); delay( connectionDelay*1000 ); } } }
5) Initialize serial data transfer, and set the MQTT broker details in the setup
method.
void setup() { Serial.begin( 115200 ); // Delay to allow serial monitor to come up. delay(3000); // Connect to Wi-Fi network. connectWifi(); // Configure the MQTT client mqttClient.setServer( server, mqttPort ); // Set the MQTT message handler function. mqttClient.setCallback( mqttSubscriptionCallback ); // Set the buffer to handle the returned JSON. NOTE: A buffer overflow of the message buffer will result in your callback not being invoked. mqttClient.setBufferSize( 2048 ); // Use secure MQTT connections if defined. #ifdef USESECUREMQTT // Handle functionality differences of WiFiClientSecure library for different boards. #ifdef ESP8266BOARD client.setFingerprint(thingspeak_cert_thumbprint); #else client.setCACert(thingspeak_ca_cert); #endif #endif }
6) Maintain the MQTT connection, and publish data to the channel at regular time intervals in the loop
method.
void loop() { // Reconnect to WiFi if it gets disconnected. if (WiFi.status() != WL_CONNECTED) { connectWifi(); } // Connect if MQTT client is not connected and resubscribe to channel updates. if (!mqttClient.connected()) { mqttConnect(); mqttSubscribe( channelID ); } // Call the loop to maintain connection to the server. mqttClient.loop(); // Update ThingSpeak channel periodically. The update results in the message to the subscriber. if ( abs(long(millis()) - lastPublishMillis) > updateInterval*1000) { mqttPublish( channelID, (String("field1=")+String(WiFi.RSSI())) ); lastPublishMillis = millis(); } }
See Also
Publish to a Channel Field Feed | Publish to a Channel Feed
Related Examples
- Publish and Subscribe to a Channel Using Desktop MQTT Client
- Publish to a ThingSpeak Channel Using a Particle Device Client via MQTT
- Publish Using WebSockets in Python on a Raspberry Pi