Project: Arduino YUN and sending data to ThingSpeak with POST

Arduino YUN is very powerful tool especially with data acquisition services like ThingSpeak. Today we had urgent need to get some data from sensors, and running simple sketch and making data available through ThingSpeak was a breeze:

Project: Arduino Yun sending data to TS

First, documentation for Bridge library leaves out a lot details, so getting curl to work was not an instant hit. Nothing specially hard, just required few tries.

You need a ThingSpeak account, and create there new channel for a data. ThingSpeak is a service for collecting data from many sources, right now (Apr 2014) it looks like it is free to use, but how long it will last? I’ve seen few similar services, and at some point You need to get money for a such service… Anyway, I’ll show You how to connect to ThingSpeak, but if You need to connect to different service You will have all needed information, probably You will have to change URL format.

On OpenWRT side You don’t have change anything, just configure it to have access to internet. Using Bridge Process class we will curl to pass our data to web service. What is curl?

curl is a command line tool for transferring data with URL syntax

or in other words, with this simple program You can call any URL, pass data and read response – all that goodies from shell level. And curl is a part of OpenWRT on Arduino YUN.

Arduino YUN: sending POST requests

Bridge library has HttpClient class for dealing with HTTP GET methods, however most webservices require You to send data with POST (GET is for retrieving data). We will use Process class to run curl command on OpenWRT, and this command will send our request.

curl syntax is: curl OPTIONS URL. URL for our API is http://api.thingspeak.com/upload/ (BTW it looks like TS does not provide HTTPS for uploading data…). OPTIONS has include two information: data we want to send to API and fact it should be POST. It will be enough to use --data PAYLOAD as an option. PAYLOAD has carry information about data, and switch --data tells curl to send POST request instead of default GET. ThingSpeak expects for each channel data set, and without any configuration on TS side first data should be encoded as field1, second as field2 and so on… URL encoding rules are (as long we talk about numeric values): NAME=VALUE&NAME2=VALUE2, so it is a list of pairs NAME/VALUE with = between. Sign of & is used as field separator.

Let’s look at example. Two values to send to ThingSpeak – -20.2 and 34.2 will be encoded as field1=-20.2&field2=34.2. To allow ThingSpeak which channel You want to write to You have to provide API write key (You can read it on API Keys tab on channel page on ThingSpeak) and provide it encoded in PAYLOAD with name key. Whole curl command will be: curl --data "key=XYZ123ABC&field1=-20.2&field2=34.2" http://api.thingspeak.com/upload/. Did You notice ” surrounding encoded parameters? It is important to add them, otherwise & sign will be interpreted by OpenWRT shell as a special character.

Function to send values to ThingSpeak will be:

void postToThingSpeak(String key, float value[]) {
  Process p;
  String cmd = "curl --data \"key="+key;
  for (int i=0;i<ARRAY_SIZE;i++) {
    cmd = cmd + "&field"+ (i+1) + "=" + value[i];
  }
  cmd = cmd + "\" http://api.thingspeak.com/update";
  p.runShellCommand(cmd);
  Console.println(cmd);
  p.close();
}

As You probably see it expects two arguments. First is ThingSpeak channel API write key, second one is array of numeric values. In case You need more values to send to TS just change ARRAY_SIZE define to have it done.

Whole sketch code reads humidity and temperature from DHT22 sensor and environmental information from gas sensors MQ5 and MQ9, and You can examine it on this gist.

Sensors getting data for this example or power of Internet of Things with Arduino YUN

If You are curious here is a quick look at sensors providing data for that channel, take a look:

Sensors providing data for ThingSpeak

Sensors providing data for ThingSpeak

There will be more sensors soon, and we will deploy similar devices in few places – this is ongoing project, it was quickly started it took less than two days from idea of this station to finishing this article. Of course – not two days working on this, we were doing other things too, so this was side project, I guess it can be completed in few hours. This is really demonstration how fast You can prototype with Arduino YUN…

12 thoughts on “Project: Arduino YUN and sending data to ThingSpeak with POST

  1. Pingback: Starter Kit » Blog Archive Logging float values using Strings on Arduino » Starter Kit

  2. Piotr

    Hi I’m trying to compile this code but ending with the following errors:
    env_station.ino: In function ‘void setup()’:
    env_station.ino:17:7: error: expected unqualified-id before ‘=’ token
    env_station.ino: In function ‘void loop()’:
    env_station.ino:39:15: error: expected primary-expression before ‘.’ token
    env_station.ino:40:15: error: expected primary-expression before ‘.’ token
    Error compiling.

    Any advice?

    Reply
    1. nettigo Post author

      Hi!
      All errors are in lines related to DHT librarry. Did You install this library correctly? Does example from File/Examples/DHT/DHTtester work with connected sensor?

      Reply
  3. krishna

    hi i am using curl to send both humidity and temperature to google app engine server i am able to send only one data at a time following code gives you a view
    ===
    i need to send the humidity value so provide me solution

    void loop()
    {
    DHT.read11(dht_dpin);
    runCurl(DHT.temperature);
    delay(5000);
    }

    void runCurl(int temp)
    {
    Process p;
    Serial.print(temp);
    String cmd = “curl –data \”temp=”;
    cmd +=temp;
    cmd = cmd +”\” http://marchcheck.appspot.com/arduino_post“;
    Serial.println(“cmd”);
    ip.runShellCommand(cmd)
    p.close();
    }

    Reply
  4. nettigo Post author

    @krishna
    I’m not sure what is Your DHT library inteface, but assuming that DHT.humidity returns value as int You should:

    First – change runCurl call and interface
    runCurl(DHT.temperature, DHT.humidity)
    […]
    void runCurl (int temp, int humidity) {
    [..]
    cmd += temp;
    cmd+= “&humidity=”;
    cmd += humidity

    where […] means some code from Your example I have skipped. Hope that will help You.

    Reply
  5. krishna

    i am using dht11 sensor you can check the results in the marchcheck.appspot.com
    i am getting only temperature data but not humidity in the above code you mentioned for loop for what you used that loop

    please mail to my personal mail id i can send you the full code of google app engine

    Reply
  6. sarathkumark77

    I am trying to send temp and humidity data by post request method to python server which I attached below. I dono how to write code in arduino yun for post request to the python server. Can anybody help me what I need to include for post request method in arduino code. I have attached my python code.

    import os
    import cherrypy
    from cherrypy.lib.static import serve_file
    import urllib2

    path = os.path.abspath(os.path.dirname(“__file__”))
    config = {
    ‘global’ : {
    ‘server.socket_host’ : ‘192.168.0.51’,
    ‘server.socket_port’ : 8080,
    ‘server.thread_pool’ : 8
    }
    }

    class App:
    @cherrypy.expose
    def index(self):
    return serve_file(os.path.join(path, ‘index.html’))

    @cherrypy.expose
    @cherrypy.tools.json_out()
    def getData(self):
    response = urllib2.urlopen(“http://”)
    page_source = response.read()
    str = unicode(page_source, errors=’replace’)
    #print(page_source)
    return {
    ‘sensorData’ : str
    }
    if __name__ == ‘__main__’:
    cherrypy.quickstart(App(), ‘/’, config)

    Reply
  7. Vincenzo

    Hi thanks for your work
    I’ve been using your code for month and suddenly stopped working ???
    Any idea I’ve also tried to use the new library provided by thingspeak but nothing works!!!
    What about your code … is still working?

    Reply
    1. nettigo Post author

      @Vincenzo
      We have stopped our instance recently so, I don’t know what could happen. If You paste this curl command to some linux box what response You get? Any error with code?
      Did You check thingspeak if they have changed something in theirs API?

      Reply
  8. nino

    hi
    sketch work but when i put this in my sketch

    (with array 4) 4 sensor put value in TS.

    if i use other sensor total 8 (with array 8) in console, url is truncate and so nothing post to TS

    Maybe that yun haven’t time or haven’t memory or other

    Reply
    1. nettigo Post author

      @nino
      What length it has? What returns Console.println(cmd.length()) ? String class should not have fixed length limit. Does Yun work after first operation? How much free RAM You have in that moment? This should get free ram:
      int freeRam ()
      {
      extern int __heap_start, *__brkval;
      int v;
      return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
      }

      Reply
  9. nino

    the length is for 8 fields…
    yun work after curl,

    i truncate in 3 curl
    1. 3 sensor
    delay 16000
    2. 3 sensor
    delay 16000
    3. 2 sensor
    delay 16000

    in this way work but i have a delay too big

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *