Upload Data to Thingspeak through MQTT with an ESP8266

SendingĀ  values to Thingspeak via the Thingspeak API is well known. There is another way as well: through MQTT. Thingspeak has recently (5 dec 2016) added a (one way) MQTT broker for this at mqtt.thingspeak.com:1883.

There are two topics one can use:
To upload more than 1 field in one session use:
channels/<channelID/publish/<channelAPI>

To upload an individual channel use:
channels/<channelID>/publish/fields/field1/<channelAPI> (just using field1 as example)

In the first case, the payload string is as follows:
field1=<value1>&field2=<value2>&status=MQTTPUBLISH

In the second case the payload string is just <value1>

In the program below I am using the PubSubClient from Knolleary. The “credentials.h” file is a file that defines my WiFi credentials, you can either create such a file yourself or just insert your wificredentials.

I am using an ESP8266 to make the connection but ofcourse it is also possible to use an Arduino with Ethernet connection when you make the proper changesĀ  in this file in order to connect to Ethernet.

To avoid using again a DHT11 as an example, I show uploading variables by using micros() and a counter

#include "PubSubClient.h" //Knolleary
#include  <ESP8266WiFi.h> //ESP8266WiFi.h
#include   <credentials.h> //This is a personal file containing web credentials

const char* ssid = WAN_SSID;// this constant is defined in my credentials file
const char* password = WAN_PW;// ditto
//char* topic="channels/<channelID/publish/<channelAPI>
char* topic = "channels/123456/publish/T8I9IO457BAJE386"; 
char* server = "mqtt.thingspeak.com";

WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

String clientName="ESP-Thingspeak";
  Serial.print("Connecting to ");
  Serial.print(server);
  Serial.print(" as ");
  Serial.println(clientName);
  
  if (client.connect((char*) clientName.c_str())) {
    Serial.println("Connected to MQTT broker");
    Serial.print("Topic is: ");
    Serial.println(topic);
    
    if (client.publish(topic, "hello from ESP8266")) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish failed");
    }
  }
  else {
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    abort();
  }
}

void loop() {
  static int counter = 0;
  String payload="field1=";
  payload+=micros();
  payload+="&field2=";
  payload+=counter;
  payload+="&status=MQTTPUBLISH";
  
  if (client.connected()){
    Serial.print("Sending payload: ");
    Serial.println(payload);
    
    if (client.publish(topic, (char*) payload.c_str())) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish failed");
    }
  }
  ++counter;
  delay(20000);
}

The file is available for download here. Whether this is a better method than with the api remains to be seen.
Currently the connection time is limited because of the limited number of sockets on Thingspeak so it is ‘connect->upload->disconnect’. Thingspeak currently cannot be used as a ‘broker’. The traffic is one way only. If your client is already connected to an MQTT network on your own private or public broker, then this method cannot be used without ‘bridging’ the two ‘networks’

Advertisements