Control a Light with TalkBack on Arduino

This example shows how to fetch commands from a ThingSpeak™ TalkBack queue and use them 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.

In this example, you write TURN_ON or TURN_OFF to a TalkBack queue and the device changes the state of the onboard LED to match the command. Use the ThingSpeak TalkBack App to store commands for your device. You can use the web interface or HTTP commands to write device commands to a list. You can store up to 8000 commands in the list. Each time the device reads the command list, it reads a single command and removes the latest command from the list.

Supported Hardware

  • Arduino UNO or similar with Wi-Fi module or Wi-Fi connectivity

  • MKR1000

Prerequisites

Set up a TalkBack to run this example. Go to Apps > TalkBacks and choose New TalkBack. Then, add commands to the queue.

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 TALKBACK_ID, YOUR_TALKBACK_API_KEY, TALKBACK_COMMAND, and POSITION_NUMBER with the appropriate values from your channel.

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

Program Your Arduino

1) Download the latest Arduino® IDE.

2) Add WiFi101 to the Library Manager, if it is not already there.

a) Select Sketch > Include Library > Manage Libraries. Search for WiFi101.

b) Select the WiFi101 library and click Install.

3) Add the WiFi101 library to the sketch.

a) Select Sketch > Include Library > Manage Libraries.

b) Select WiFi101 to add it to your sketch.

4) Add the SPI library to the sketch.

a) Select Sketch > Include Library > Manage Libraries.

b) Select SPI to add it to your sketch.

5) In the Tools menu, select the appropriate port and board in the Arduino IDE.

6) Paste the code into the Arduino IDE. Add your WiFi 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 time a command is executed, it 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.

/*
FetchCommandFromTalkBack

Description: Checks a TalkBack queue every 60 seconds and set the state of the built-in LED according
             to the latest command fetched. Turn the LED on and off by using the commands TURN_ON and TURN_OFF.
             The TalkBack documentation can be found at: https://www.mathworks.com/help/thingspeak/talkback-app.html.
             

Hardware: Arduino WiFi Shield 101 or MKR

Notes:
 - Requires WiFi101 library. Use the WiFi101 library version 0.13.0 or older. WiFi101 library versions 0.14.0 and newer have a bug
   that prevents the ThingSpeak library from working properly.
 - Make sure the WiFi Shield 101 has updated firmware. Find instructions at https://www.arduino.cc/en/Tutorial/FirmwareUpdater.

Copyright 2018, The MathWorks, Inc.
*/

#include <SPI.h>  // Required for shield communication
#include <WiFi.h>

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

WiFiClient  client;

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

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 WiFi network. Create the POST message with the correct parameters. Send the POST request, verify the result, and check for a TalkBack command. Wait 60 seconds and check the queue again.

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 TalkBack URI
  String tbURI = String("/talkbacks/") + String(myTalkBackID) + String("/commands/execute");
  
  // Create the message body for the POST out of the values
  String postMessage =  String("api_key=") + String(myTalkBackKey);                      
                       
   // Make a string for any commands in the queue
  String newCommand = String();

  // Make the POST to ThingSpeak
  int x = httpPOST(tbURI, 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));
  }

  
  delay(60000); // Wait 60 seconds to check queue again
}

4) Use the httpPOST function to read the next TalkBack command.

// General function to POST to ThingSpeak
int httpPOST(String uri, 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 ") + uri + String(" 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;
    
}