Channel Update and Light Control with ESP8266

This example shows how to update a channel and fetch commands from a ThingSpeak™ TalkBack queue. Use the commands to change the status of the onboard LED.

Use TalkBack when your application involves a machine that you want to run only when there is a command in the queue.

You can simultaneously update your channel and retrieve the latest command saved in a TalkBack queue. Add the parameter talkback_key to your POST request, and ThingSpeak returns the latest TalkBack command in the response.

Supported Hardware

  • ESP8266 and other ESP8266-based boards

  • NodeMCU

  • Wemos

Prerequisites

You must have at least one channel set up to complete this example. Create a Channel as shown in Collect Data in a New Channel, and record the write API key. You also need to set up a TalkBack. Go to Apps > TalkBacks and choose New TalkBack.

Add Commands to TalkBack Queue

You can add commands to a TalkBack queue in one of two ways.

  • Use the ThingSpeak TalkBack web interface to add commands to the TalkBack queue. You can configure TalkBack to have up to 8000 commands.

  • Use the ThingSpeak API. You can use an HTTP POST request to add a command to the queue. In the following POST, replace the TALKBACK_ID, YOUR_TALKBACK_API_KEY, TALKBACK_COMMAND, and POSITION_NUMBER.

POST https://api.thingspeak.com/talkbacks/TALKBACK_ID/commands
 api_key=YOUR_TALKBACK_API_KEY
     command_string=TALKBACK_COMMAND
     position=POSITION_NUMBER

Program Your ESP8266

1) Download the latest Arduino® IDE.

2) Add the ESP8266 Board Package.

3) Under File > Preferences, enter https://arduino.esp8266.com/stable/package_esp8266com_index.json into Additional Board Manager URLs.

4) Choose Tools > Boards > Board Manager. Enter ESP8266 in the search bar, then select and install the package.

5) In the Tools menu, select the appropriate port and board in the Arduino IDE. The hardware used to generate this example used the Node MCU 1.0 (ESP 8266–12E) option.

6) Paste the code into the Arduino IDE. Add your Wi-Fi network information, your TalkBack API key, and your TalkBack number.

7) Program the device and then watch the serial monitor and the LED to observe changes when commands are consumed. Each command that is executed is removed from the list. You need to add more commands to the list after they are consumed.

Code

1) Begin by including the appropriate libraries and defining variables. Enter your network SSID and password. Edit the channel number and TalkBack parameters for ID and API key.

/*
WriteMultipleFieldsAndFetchCommandFromTalkBack

Description: Writes values to fields 1,2,3, and 4 and checks a TalkBack queue every 20 seconds for new commands.
             The TalkBack documentation can be found at https://www.mathworks.com/help/thingspeak/talkback-app.html.
             
Hardware: ESP8266-based boards

Notes:
- Requires ESP8266WiFi library and ESP8266 board add-on. See https://github.com/esp8266/Arduino for details.
- Select the target hardware from Tools > Board

Copyright 2018, The MathWorks, Inc.
*/

#include <ESP8266WiFi.h>

char ssid[] = <enter your SSID>;   // your network SSID (name) 
char pass[] = <enter your password>;   // your network password

WiFiClient  client;

unsigned long myChannelNumber = <enter your channel ID>;
unsigned long myTalkBackID = <enter your TalkBack ID>;
const char * myTalkBackKey = <enter your TalkBack API key>;

// Initialize values for ThingSpeak updates
int number1 = 0;
int number2 = random(0,100);
int number3 = random(0,100);
int number4 = random(0,100);

2) In the setup function, initialize the LED and start the serial monitor.

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);  // Set up LED
  Serial.begin(115200);  // Initialize serial
}

3) In the main loop, start by establishing a connection to the local Wi-Fi network. Create the POST message from the randomly generated numbers. Send the POST, verify the result, and check for a TalkBack command. Then generate new random numbers for the next POST request in 20 seconds.

void loop() {

  // Connect or reconnect to Wi-Fi
  if(WiFi.status() != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(String(ssid));
    while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass);  
      Serial.print(".");
      delay(5000);     
    } 
    Serial.println("\nConnected.");
  }

  // Create the message body for the POST out of the values
  String postMessage =  String("field1=") + String(number1) +
                        String("&field2=") + String(number2) +
                        String("&field3=") + String(number3) +
                        String("&field4=") + String(number4) +
                        String("&api_key=") + String(myWriteAPIKey) +
                        String("&talkback_key=") + String(myTalkBackKey);                      
                       

   // Make a string for any commands in the queue
  String newCommand = String();

  // Make the POST to ThingSpeak
  int x = httpPOST(postMessage, newCommand);
  client.stop();
  
  // Check the result
  if(x == 200){
    Serial.println("checking queue..."); 
    // check for a command returned from TalkBack
    if(newCommand.length() != 0){

      Serial.print("  Latest command from queue: ");
      Serial.println(newCommand);
      
      if(newCommand == "TURN_ON"){
        digitalWrite(LED_BUILTIN, HIGH);  
      }

      if(newCommand == "TURN_OFF"){
        digitalWrite(LED_BUILTIN, LOW);
      }
    }
    else{
      Serial.println("  Nothing new.");  
    }
    
  }
  else{
    Serial.println("Problem checking queue. HTTP error code " + String(x));
  }

  // Confirm code works by changing values
  number1++;
  if(number1 > 99){
    number1 = 0;
  }
  number2 = random(0,100);
  number3 = random(0,100);
  number4 = random(0,100);
  
  delay(20000); // Wait 20 seconds to update the channel again
}

4) Use the httpPOST function to post data to ThingSpeak and read the next TalkBack command.

// General function to POST to ThingSpeak
int httpPOST(String postMessage, String &response){

  bool connectSuccess = false;
  connectSuccess = client.connect("api.thingspeak.com",80);

  if(!connectSuccess){
      return -301;   
  }
  
  postMessage += "&headers=false";
  
  String Headers =  String("POST /update HTTP/1.1\r\n") +
                    String("Host: api.thingspeak.com\r\n") +
                    String("Content-Type: application/x-www-form-urlencoded\r\n") +
                    String("Connection: close\r\n") +
                    String("Content-Length: ") + String(postMessage.length()) +
                    String("\r\n\r\n");

  client.print(Headers);
  client.print(postMessage);

  long startWaitForResponseAt = millis();
  while(client.available() == 0 && millis() - startWaitForResponseAt < 5000){
      delay(100);
  }

  if(client.available() == 0){       
    return -304; // Didn't get server response in time
  }

  if(!client.find(const_cast<char *>("HTTP/1.1"))){
      return -303; // Couldn't parse response (didn't find HTTP/1.1)
  }
  
  int status = client.parseInt();
  if(status != 200){
    return status;
  }

  if(!client.find(const_cast<char *>("\n\r\n"))){
    return -303;
  }

  String tempString = String(client.readString());
  response = tempString;
  
  return status;
    
}