Arduino - 获取响应和解析json数组的正确方法

时间:2014-12-09 19:34:36

标签: c arrays json arduino arduino-uno

以下是我尝试做的事情:我有一个带有REST api的django应用程序。其中一个路由器返回一个如下所示的json数组:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]并且将始终具有相同的大小并包含整数。

现在,我有一个带有Adafruit cc3000 wifi屏蔽的Arduino Uno。我设法连接到wifi,执行获取请求并打印结果,甚至将其保存在char *中。

我的第一个问题是:

我非常确定我没有以正确的方式构建我的char数组(至少,不是正确的方式,我不具备C,C ++等方面的经验)如果这是一个借口)。而且我认为这会阻止我解析json数组。

#include <ArduinoJson.h>
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include <Adafruit_NeoPixel.h>

int PIN = 6;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
StaticJsonBuffer<600> jsonBuffer;

#define ADAFRUIT_CC3000_IRQ   3  
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER);
#define WLAN_SSID       "mywifi"
#define WLAN_PASS       "mypwd"
#define WLAN_SECURITY   WLAN_SEC_WPA2
uint32_t ip = cc3000.IP2U32(00,00,00,00);


void setup(void)
{
  Serial.begin(9600);
  if (!cc3000.begin())
  {
    while(1);
  }
  strip.begin();
  strip.show();
  char *ssid = WLAN_SSID;
  Serial.print(F("\nAttempting to connect to "));
  Serial.println(ssid);
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println("Connected to WiFi network!");

  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(3000);
  }
}


void loop(void){
  int lap = 0;
  if(!cc3000.checkConnected()){
    while(1){
    }
  }
  char *result;
  result  = send_request();
  result[71] = ']';
  JsonArray& root = jsonBuffer.parseArray(result);
  if (!root.success())
  {
    Serial.println("parseObject() failed");
  }
  while(lap<61){
    for (int i=0; i<24; i++){
      long is_free = root[i];
      if (is_free == 0){
        strip.setPixelColor(i, 255, 0, 0);
      }
      if(is_free == 1){
        strip.setPixelColor(i, 0, 255, 0);
      }
      if(lap % 2 ==0){
        if(is_free == 2){
          strip.setPixelColor(i, 0, 255, 0);
        }
        if(is_free == 3){
          strip.setPixelColor(i, 0, 255, 0);
        }
      }
      else{
        if(is_free == 2){
          strip.setPixelColor(i, 0, 0, 0);
        }
        if(is_free == 3){
          strip.setPixelColor(i, 0, 0, 0);
        }
      }
    }
    strip.setBrightness(15);
    strip.show();
    lap += 1;
    delay(1000);
  }  
}


char* send_request (void)
{
  char result[100];
  Serial.print(F("Initializing SendGET request\n"));
  Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 8000);

  if (client.connected()) {
    //starts client connection, checks for connection
    Serial.println(F("Adding state to DB\n"));
    client.println("GET /myurl/?format=json"); //download text
    client.println(F("Host: xx.xx.xx.xx"));
    client.println("Connection: close");  //close 1.1 persistent connection  
    client.println(); //end of get request
    Serial.println(F("Ending connection to DB\n"));
  } 
  else {
    Serial.println("Connection to server failed"); //error message if no client connect
    Serial.println();
  }
  int i = 0;
  while (client.connected()){
    while (client.available()) {
      if (i<71){
        //Read answer
        char c = client.read();
        result[i] = c ;
        i++;
      }
      else{
        client.close();
        return result;
      }
    }
  }
}

对我来说send_request()非常脏,因为我认为i需要小于71,因为我打印的结果看起来像我想要的。但我认为数组的大小错误,这就是为什么我无法在loop()函数中解析它。

请问有什么好的,好的,清晰的,准确的方法呢?我已经尝试了很多错误的事情,但我的想法已经不多了。

第二个问题是:

如果我更换

char *result;
result[71] = ']';

result = "[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]"; 然后打印is_free,我得到随机值,如:

91
49
44
32
48
44
32
48
44
32
48
44
32
48

所以我的猜测是我不正确地使用ArduinoJson,或者我没有在正确的位置查看价值。 我正在寻找有关这方面的见解

感谢阅读和未来的最终帮助!

1 个答案:

答案 0 :(得分:1)

您的代码有多个问题,但主要问题是函数send_request返回指向局部变量的指针。变量result位于堆栈帧中,可能被下一个堆栈帧覆盖(我猜函数loop);因此你见证了垃圾。

快速而肮脏的解决方案是替换:

char result[100];

由:

static char result[100];

这会将result移动到专门的内存中,直到程序完成后才会回收。

解析可能会失败,因为你永远不会终止你的字符串;但是在上面的修复之后这可能不再是一个问题(静态变量用null初始化)。但只是为了确定,在调用parseArray之前添加此命令:

result[72] = '\0';

其他问题:

  • 缺少部分代码;调用setupsend_requestloop的主函数在哪里?感谢您的解释。
  • while(1);是一个无限循环,除了把你的Arduino变成烤面包机之外什么都不做;这是故意的吗?
  • long is_free = result[i];应该是long is_free = root[i];感谢您相应地更改代码;我很确定这会解决问题#2。