Parse JSON con arduino para encender el LED

18

Hola, estoy tratando de analizar el depósito JSON del servidor web en mi arduino para encender y apagar una luz LED. Estoy usando el ejemplo de repetición del cliente wifi para hacer una solicitud de obtención a mi servidor:

http://arduino.cc/en/Tutorial/WiFiWebClientRepeating

Esto es lo que recibo impreso desde el puerto serie

connecting...
HTTP/1.1 200 OK
Date: Sun, 06 Apr 2014 01:14:37 GMT
Server: Apache
X-Powered-By: PHP/5.5.10
Cache-Control: no-cache
X-Frame-Options: SAMEORIGIN
Set-Cookie: expires=Sun, 06-Apr-2014 03:14:37 GMT; Max-Age=7200; path=/; httponly
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json

19
{"lightstatus":"on"}
0

¿Cómo analizo la parte JSON de esta respuesta solo para poder usarla para controlar mi LED?

Gracias

usuario1424508
fuente

Respuestas:

11

Conozco algunas bibliotecas de análisis JSON para Arduino.

Nunca he usado ninguno de estos, pero hice un análisis JSON simple en un proyecto en el que estoy trabajando, así que te mostraré cómo lo hice.

NOTA: Estoy leyendo datos en serie usando la biblioteca en serie del software. Tendrá que cambiar este código para que funcione para usted. Esto solo funcionará en cadenas JSON muy simples. Es muy limitado, pero si eso es todo lo que está analizando, funcionará.

Ejemplo de respuesta JSON del servidor:

{"id":"TEST1","lat":"38.56050207","lng":"-121.42158374","total":"3","available":"2"}

Primero, solo lea los datos entre llaves.

String response = "";
bool begin = false;
while (SIM900.available() || !begin) {

    char in = SIM900.read();

    if (in == '{') {
        begin = true;
    }

    if (begin) response += (in);

    if (in == '}') {
        break;
    }

    delay(1);
}

Este código lee los datos un byte a la vez y una vez que obtiene una llave abierta, comienza a guardarlos response. Cuando obtiene una llave de cierre, la termina. Así que aquí hay una clara limitación, solo puede tener un conjunto de llaves de apertura / cierre en su cadena.

Una vez que tengo la cadena, uso indexOfy substringpara extraer información relevante:

start = response.indexOf("id\":\"") + 5;
end = start + 5;
nodeId = response.substring(start, end);

Este código se establece startal comienzo de id":"+ 5 caracteres en la cadena. Es +5 porque así de largo id":"es. Entonces startapunta a TEST1la cadena JSON. En mi sistema, la identificación siempre tendrá 5 caracteres, así que el final es start + 5. Luego uso substringpara extraer eso.

Nuevamente, antes de que alguien empiece a votar por esta horrible solución: si sabe exactamente con qué está trabajando y comprende las limitaciones de este código, entonces esta no es una mala solución. Es una solución que hace el trabajo.

Sachleen
fuente
El ejemplo de JSON que da no se parece a un JSON "bueno", por ejemplo, los valores numéricos normalmente no se deben citar como cadenas.
jfpoilpret
+1 para la lista de bibliotecas potencialmente utilizables para JSON. Me sorprende que ninguna biblioteca se base en un enfoque de función de devolución de llamada, que se llamaría durante el análisis (mucho más eficiente en cuanto a memoria).
jfpoilpret
Al menos eres consciente de que tu muestra de código es horrible :-) Por supuesto, hace el trabajo, pero no es legible (por alguien más e incluso por ti mismo en 6 meses) y, por lo tanto, no es mantenible.
jfpoilpret
@jfpoilpret No tengo memoria en el chip, así que tuve que cortar esquinas en algunos lugares. Al menos está muy comentado.
sachleen
Entiendo; pero me pregunto si el Stringuso no empeora la situación de la memoria (sí, Stringen Arduino es mi motivo favorito).
jfpoilpret
7

He programado una clase que recibirá char by char el documento JSON. Solo almacenará en la memoria unos pocos bytes para la estructura JSON conocida utilizando una máquina de estado y los resultados que necesita. Para que pueda consultar en la clase los resultados que desea y procesará el JSON.

Es ideal para su propósito. Lo he usado para conectarme a un servicio meteorológico que devuelve un json:

static const char* queries[] = { "list.0.deg", "list.0.weather.0.main"};
StreamJsonReader jsonreader(queries, 2); // 2 queries    
while(char c  =  read()){
      jsonreader.process_char(c);
}

cout << jsonreader.results[0] << endl;
cout << jsonreader.results[1] << endl;

Mira esta publicación de blog que acabo de escribir: http://web.biicode.com/blog/big-json-on-arduino .

El código fuente está aquí en Biicode.

lasote
fuente
2

Escribí un analizador para el PIC que tiene un uso de RAM muy bajo porque funciona directamente con punteros de caracteres y no construye una estructura de árbol. Si solicita obtener el elemento N de una lista, le proporciona un puntero real en el archivo JSON directo justo al comienzo del elemento N de la lista. Luego puede preguntar qué tipo de objeto representa el puntero, etc. Tiene errores y no admite flotadores y creo que tiene algunas otras limitaciones (hace mucho tiempo), pero todo está en github: https://github.com / EternityForest / OpenFortune-fortune-like-text-generator Necesitará buscar en libfortune, que es parte de la versión C.

EternidadBosque
fuente