2

我正在尝试使用带有 GSM 屏蔽的 Arduino,使用他们的 REST API 通过 GPRS 将传感器数据发布到 www.parse.com。这就是他们的文档显示需要完成的方式:

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

我需要在 Arduino 草图中以某种方式实现这一点。这是我的起点,因为它包括我的 shield 使用的库。此示例草图连接到 Google 并显示结果。我已经对其进行了测试,并且可以正常工作。

#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();
}

我需要能够使用 App ID 和 API 密钥等将“Level”和“Temp”数据发布到 Parse.com,如上面的 API 示例所示。关于如何在草图中做到这一点的任何想法?

提前致谢!!

4

3 回答 3

2

我对此进行了一些额外的研究,似乎 Arduino 无法通过安全 (https) 连接连接到 Web 服务器。为此,我需要选择不同的硬件。

我在上面尝试了 zmo 的答案,它返回 0,因为 Arduino 无法建立连接。目前使用 Arduino 执行此操作的唯一方法似乎是将传感器数据发布到运行脚本的中间服务器,然后将数据发布到 Parse。

于 2013-07-02T02:00:38.193 回答
1

你需要 fork 库并重写httpPost()函数来添加你需要的 headers 元素:

#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;
}

您可能还想传递REST_APP_IDREST_API_KEY作为参数。并且不要忘记在标题中添加函数的原型。然后使用您的函数,您可以按如下方式调用它:

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

请注意,默认_buffer大小仅为50字符。您可能想要增加它的大小。您不妨将所有字符串都放入闪存中,以节省一些宝贵的内存F("my string")以赢得胜利!

于 2013-06-29T23:43:52.580 回答
0

现在http://www.temboo.com有可能。试一试,这里我解释了它是如何工作的: https ://stackoverflow.com/a/24213165/1862909

但我认为它仅适用于 wifi shield 和 ethernet shield。也许你可以向 temboo 的人提出要求?

于 2014-06-13T20:14:58.080 回答