Analise JSON com arduino para ativar o LED

18

Oi, eu estou tentando analisar resposne JSON do servidor web no meu arduino, a fim de ligar e desligar uma luz LED. Estou usando o exemplo de repetição do cliente wifi para fazer uma solicitação de obtenção ao meu servidor:

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

Aqui está o que eu imprimo de volta da porta serial

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

Como analiso a parte JSON dessa resposta apenas para que eu possa usá-la para controlar meu LED?

obrigado

user1424508
fonte

Respostas:

11

Estou ciente de algumas bibliotecas de análise JSON para Arduino.

Eu nunca usei nenhum desses, mas fiz uma análise JSON simples em um projeto em que estou trabalhando, por isso vou mostrar como fiz isso.

NOTA: Estou lendo dados seriais usando a biblioteca serial do software. Você precisará alterar esse código para trabalhar para você. Isso funcionará apenas em cadeias JSON muito simples. É muito limitado, mas se é tudo o que você está analisando, funcionará.

Exemplo de resposta JSON do servidor:

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

Primeiro, leia apenas os dados entre chaves.

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

Esse código lê os dados um byte de cada vez e, quando recebe uma chave aberta, começa a salvá-la response. Quando recebe uma chave de fechamento, ela termina. Portanto, aqui está uma limitação clara: você pode ter apenas um conjunto de chaves de abertura / fechamento em sua string.

Depois de obter a string, uso indexOfe substringpara extrair informações relevantes:

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

Esse código define starto início de id":"+ 5 caracteres na string. É +5 porque é quanto tempo id":"é. Então, startaponta para TEST1na cadeia JSON. No meu sistema, o ID sempre terá 5 caracteres, assim como o fim start + 5. Eu então uso substringpara extrair isso.

Novamente, antes que alguém comece a votar em mim para esta solução horrível: se você sabe exatamente com o que está trabalhando e entende as limitações deste código, essa não é uma solução ruim. É uma solução que faz o trabalho.

sachleen
fonte
O exemplo JSON que você fornece não parece JSON "bom", por exemplo, valores numéricos normalmente não devem ser citados como seqüências de caracteres.
Jfpoilpret 06/04
+1 para a lista de bibliotecas potencialmente utilizáveis ​​para JSON. Surpreende-me que nenhuma biblioteca seja baseada em uma abordagem de função de retorno de chamada, que seria chamada durante a análise (muito mais eficiente em termos de memória).
Jfpoilpret
Pelo menos, você está consciente de que seu exemplo de código é horrível :-) Obviamente, ele faz o trabalho, mas não é legível (por outra pessoa nem por si mesmo em 6 meses) e, portanto, não pode ser mantido.
Jfpoilpret 06/04
@jfpoilpret Estou com pouca memória no chip, então tive que cortar cantos em alguns lugares. Pelo menos é muito comentado.
Sachleen
Compreendo; mas me pergunto se o Stringuso não piora a situação da memória (sim, Stringno Arduino está minha irritação).
Jfpoilpret 6/04
7

Programei uma classe que receberá char por char o documento JSON. Ele armazenará apenas alguns bytes na estrutura JSON conhecida, usando uma máquina de estado e os resultados necessários. Portanto, você pode consultar os resultados da classe e processar o JSON.

É ideal para o seu propósito. Eu usei para conectar a um serviço meteorológico que retorna um 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;

Confira este post que acabei de escrever: http://web.biicode.com/blog/big-json-on-arduino .

O código fonte está aqui no Biicode.

lasote
fonte
2

Eu escrevi um analisador para o PIC que tem uso de memória RAM muito baixo, porque funciona diretamente com ponteiros de char e não constrói uma estrutura de árvore. Se você solicitar o item N de uma lista, ele fornecerá um ponteiro real para o arquivo JSON direto logo no início do item N da lista. Então você pode perguntar que tipo de objeto o ponteiro representa, etc. É buggy e não suporta flutuadores. Acho que tem algumas outras limitações (há muito tempo), mas está tudo no github: https://github.com / EternityForest / OpenFortune-fortune-like-text-generator Você precisará procurar no libfortune que faz parte da versão C.

EternityForest
fonte