Question

I am trying to use an Arduino with a GSM shield to post sensor data to www.parse.com over GPRS using their REST API. This is how their documentation shows it needs to be done:

curl -X POST \
   -H "X-Parse-Application-Id: gmOpYot0OhWGnkMojjZv9KYUHMySCSeTGyyplArZ" \
   -H "X-Parse-REST-API-Key: XQMA4Wd3SQdOsxudtKz5OdbPaVN3YE9aOKx0VSh2" \
   -H "Content-Type: application/json" \
   -d '{"Level":90, "Temp":25}' \
   https://api.parse.com/1/classes/PercentFull

I need to implement this somehow in the Arduino sketch. This is my starting point, as it includes the libraries that my shield uses. This sample sketch connects to Google and displays the result. I've tested it and it works.

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "inetGSM.h"
//#include "sms.h"
//#include "call.h"

//To change pins for Software Serial, use the two lines in GSM.cpp.

//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.

//Simple sketch to start a connection as client.

InetGSM inet;
//CallGSM call;
//SMSGSM sms;

char msg[50];
int numdata;
char inSerial[50];
int i=0;
boolean started=false;

void setup() 
{
  //Serial connection.
  Serial.begin(9600);
  Serial.println("GSM Shield testing.");
  //Start configuration of shield with baudrate.
  //For http uses is raccomanded to use 4800 or slower.
  if (gsm.begin(2400)){
    Serial.println("\nstatus=READY");
    started=true;  
  }
  else Serial.println("\nstatus=IDLE");

  if(started){
    //GPRS attach, put in order APN, username and password.
    //If no needed auth let them blank.
    if (inet.attachGPRS("internet.wind", "", ""))
      Serial.println("status=ATTACHED");
    else Serial.println("status=ERROR");
    delay(1000);

    //Read IP address.
    gsm.SimpleWriteln("AT+CIFSR");
    delay(5000);
    //Read until serial buffer is empty.
    gsm.WhileSimpleRead();


   // Change this bit!!

   //TCP Client GET, send a GET request to the server and
    //save the reply.
    numdata=inet.httpGET("www.google.co.nz", 80, "/", msg, 50);
    //Print the results.
    Serial.println("\nNumber of data received:");
    Serial.println(numdata);  
    Serial.println("\nData received:"); 
    Serial.println(msg); 
  }
};

void loop() 
{
  //Read for new byte on serial hardware,
  //and write them on NewSoftSerial.
  serialhwread();
  //Read for new byte on NewSoftSerial.
  serialswread();
};

void serialhwread(){
  i=0;
  if (Serial.available() > 0){            
    while (Serial.available() > 0) {
      inSerial[i]=(Serial.read());
      delay(10);
      i++;      
    }

    inSerial[i]='\0';
    if(!strcmp(inSerial,"/END")){
      Serial.println("_");
      inSerial[0]=0x1a;
      inSerial[1]='\0';
      gsm.SimpleWriteln(inSerial);
    }
    //Send a saved AT command using serial port.
    if(!strcmp(inSerial,"TEST")){
      Serial.println("SIGNAL QUALITY");
      gsm.SimpleWriteln("AT+CSQ");
    }
    //Read last message saved.
    if(!strcmp(inSerial,"MSG")){
      Serial.println(msg);
    }
    else{
      Serial.println(inSerial);
      gsm.SimpleWriteln(inSerial);
    }    
    inSerial[0]='\0';
  }
}

void serialswread(){
  gsm.SimpleRead();
}

I need to be able to post the "Level" and "Temp" data to Parse.com using the App ID and API key, etc, shown in the API example above. Any ideas on how to do this in the sketch?

Thanks in advance!!

Was it helpful?

Solution

I've done some additional research on this and it seems that Arduino is unable to connect to web servers over a secured (https) connection. To do this I would need to choose different hardware.

I tried zmo's answer above and it returned 0 as the Arduino couldn't make the connection. It seems the only way to do this at present with Arduino is to post sensor data to an intermediate server running a script that then posts the data to Parse.

OTHER TIPS

you need to fork the library and rewrite the httpPost() function to add the headers elements you need:

#define REST_APP_ID "gmOpYot0OhWGnkMojjZv9KYUHMySCSeTGyyplArZ"
#defnie REST_API_KEY "XQMA4Wd3SQdOsxudtKz5OdbPaVN3YE9aOKx0VSh2"

int InetGSM::parsePOST(const char* path, const char* parameters, char* result, int resultlength)
{
    const char* server = "https://api.parse.com";
    int port = 443;

    char itoaBuffer[8];
    int num_char;

    if (!gsm.connectTCP(server, port)){
        return 0;
    }

    strcpy(_buffer,"POST ");
    strcat(_buffer,path);
    strcat(_buffer," HTTP/1.0\nHost: ");
    strcat(_buffer,);
    strcat(_buffer,"\nX-Parse-Application-Id: ");
    strcat(_buffer,REST_APP_ID);
    strcat(_buffer,"\nX-Parse-REST-API-Key: ");
    strcat(_buffer,REST_API_KEY);
    strcat(_buffer,"\nContent-Type: application/json");
    strcat(_buffer,"\nContent-Length: ");
    itoa(strlen(parameters),itoaBuffer,10);  
    strcat(_buffer,itoaBuffer);
    strcat(_buffer,"\n\n");
    strcat(_buffer,parameters);
    strcat(_buffer,"\n\n");

    gsm.SimpleWrite(_buffer);

    gsm.disconnectTCP();
    return 1;
}

you may want to pass REST_APP_ID and REST_API_KEY as parameters as well. And don't forget to add the prototype of your function in the header as well. To then use your function, you can call it as follows:

inet.parsePOST("/1/classes/PercentFull", "{\"Level\":90, \"Temp\":25}", msg, 50);

be careful that per default _buffer size is only 50 characters. You may want to increase its size. You may as well want to put all strings in flash to save some precious memory F("my string") for the win!

now there is a possibility with http://www.temboo.com. Give it a try, here I explained how it works: https://stackoverflow.com/a/24213165/1862909

but I think it works only for wifi shield and ethernet shield. Maybe you can make a request to the guys at temboo?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top