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:
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…
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?
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?
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();
}
@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.
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
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)
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?
@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?
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
@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);
}
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