Parsuj JSON z arduino, aby włączyć LED

18

Cześć, próbuję parsować JSON resposne z serwera WWW w moim arduino, aby włączyć lub wyłączyć światło LED. Korzystam z powtarzającego się przykładu klienta Wi-Fi, aby wysłać żądanie do mojego serwera:

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

Oto, co otrzymuję z portu szeregowego

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

Jak parsować część JSON tej odpowiedzi tylko po to, abym mógł jej użyć do sterowania moją diodą LED?

Dzięki

użytkownik 1424508
źródło

Odpowiedzi:

11

Znam kilka bibliotek parsujących JSON dla Arduino.

Nigdy nie użyłem żadnego z nich, ale wykonałem kilka prostych analiz JSON w projekcie, nad którym pracuję, więc pokażę ci, jak to zrobiłem.

UWAGA: Czytam dane szeregowe za pomocą biblioteki oprogramowania szeregowego. Musisz zmienić ten kod, aby działał dla Ciebie. Działa to tylko na bardzo prostych ciągach JSON. Jest bardzo ograniczony, ale jeśli to wszystko, co analizujesz, to zadziała.

Przykład odpowiedzi JSON z serwera:

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

Po pierwsze, czytaj tylko dane między nawiasami klamrowymi.

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

Ten kod odczytuje dane jeden bajt na raz, a kiedy otrzyma otwarty nawias klamrowy, zaczyna zapisywać go response. Kiedy dostaje nawias zamykający, kończy go. Oto wyraźne ograniczenie, możesz mieć tylko jeden zestaw nawiasów otwierających / zamykających w swoim ciągu.

Po otrzymaniu ciągu używam indexOfi substringwyodrębniam odpowiednie informacje:

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

Ten kod ustawia startpoczątek id":"+ 5 znaków w ciągu. To +5, bo tyle id":"trwa. startWskazuje więc TEST1na ciąg JSON. W moim systemie identyfikator ma zawsze 5 znaków, więc koniec start + 5. Następnie używam substringdo wyodrębnienia tego.

Ponownie, zanim ktokolwiek zacznie głosować za tym okropnym rozwiązaniem: jeśli dokładnie wiesz, nad czym pracujesz i rozumiesz ograniczenia tego kodu, nie jest to złe rozwiązanie. To rozwiązanie pozwala wykonać zadanie.

sachleen
źródło
Podany przykład JSON nie wygląda jak „dobry” JSON, np. Wartości liczbowych zwykle nie należy cytować jako ciągów znaków.
jfpoilpret
+1 za listę potencjalnie użytecznych bibliotek dla JSON. Dziwi mnie, że żadna biblioteka nie opiera się na funkcji wywołania zwrotnego, która byłaby wywoływana podczas analizowania (znacznie bardziej wydajna pod względem pamięci).
jfpoilpret
Przynajmniej zdajesz sobie sprawę, że twoja próbka kodu jest okropna :-) Oczywiście wykonuje zadanie, ale nie jest czytelna (przez kogoś innego nawet przez ciebie w ciągu 6 miesięcy), a zatem nie do utrzymania.
jfpoilpret
@ jfpoilpret Brakuje mi pamięci na chipie, więc w niektórych miejscach musiałem skracać rogi. Przynajmniej jest mocno komentowany.
sachleen
Rozumiem; ale zastanawiam się, czy Stringużycie nie pogorszy sytuacji w pamięci (tak, Stringw Arduino jest mój wkurzony zwierzak).
jfpoilpret
7

Zaprogramowałem klasę, która otrzyma char przez char dokument JSON. Będzie przechowywać tylko w pamięci kilka bajtów dla znanej struktury JSON przy użyciu maszyny stanów i potrzebnych wyników. Możesz więc zapytać klasę o pożądane wyniki i przetworzy JSON.

Jest idealny do Twoich celów. Użyłem połączenia z usługą pogodową, która zwraca 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;

Sprawdź ten post na blogu, który właśnie napisałem: http://web.biicode.com/blog/big-json-on-arduino .

Kod źródłowy jest tutaj w Biicode.

lasote
źródło
2

Napisałem parser dla PIC, który ma bardzo niskie wykorzystanie pamięci RAM, ponieważ działa bezpośrednio z wskaźnikami char i nie buduje struktury drzewa. Jeśli poprosisz o pobranie elementu N z listy, otrzymasz rzeczywisty wskaźnik do bezpośredniego pliku JSON na początku elementu N z listy. Następnie możesz zapytać, jaki typ obiektu reprezentuje wskaźnik itp. Jest błędny i nie obsługuje pływaków, i myślę, że ma kilka innych ograniczeń (dawno temu), ale wszystko jest na github: https://github.com / EternityForest / OpenFortune-fortune-like-text-generator Musisz zajrzeć do libfortune, który jest częścią wersji C.

EternityForest
źródło