czwartek, 16 stycznia 2020

[6] ESP32 - Airly - Pobranie danych

W tym poście chciałbym opisać sposób pobrania danych z serwisu Airly.

Znalezione obrazy dla zapytania arduino esp32
[Źródło: http://paulobrien.co.nz/2017/03/16/esp32-programming-with-arduino-on-windows/]



Przygotowanie:


Na samym początku należy założyć konto oraz wygenerować klucz API na stronie Airly w części dla programistów (https://developer.airly.eu/).

Po zalogowaniu należy odczytać API key:


Następnym krokiem jest określenie szerokości i długości geograficznej. Te dane należy w celu wysłania żądania odczytania danych z serwisu. Tutaj można się posłużyć stroną www.wspolrzedne-gps.pl


Gdy już posiadamy lokalizację oraz klucz to należy przygotować ciąg znaków z jakiego pobierane będą dane za pomocą żądania http.

  1. https://airapi.airly.eu/v2/installations/nearest?lat=50.0918091&lng=19.8998826&maxDistanceKM=5&maxResults=4&apikey=API_KEY

Powyższy string pozwoli na odczytanie ID oraz danych najbliższych czujników w okolicy podanej lokalizacji.

Jako parametry należy wprowadzić:

Następnie w celu uzyskania danych z konkretnego czujnika należy posiadać jego ID. Po identyfikacji czujnika należy odczytać dane w następujący sposób:

  1. https://airapi.airly.eu/v2/measurements/installation?installationId=2903&apikey=API_KEY

W odpowiedzi otrzymujemy dane aktualne, historyczne oraz prognozy na najbliższy czas. Całość prezentuje się następująco:

  1. {
  2.     "current":{
  3.         "fromDateTime":"2020-01-13T07:03:06.902Z",
  4.         "tillDateTime":"2020-01-13T08:03:06.902Z",
  5.         "values":[
  6.             {"name":"PM1","value":18.87},
  7.             {"name":"PM25","value":28.93},
  8.             {"name":"PM10","value":57.27},
  9.             {"name":"PRESSURE","value":1024.01},
  10.             {"name":"HUMIDITY","value":85.63},
  11.             {"name":"TEMPERATURE","value":0.58}
  12.         ],
  13.         "indexes":[
  14.             {
  15.                 "name":"AIRLY_CAQI",
  16.                 "value":54.54,
  17.                 "level":"MEDIUM",
  18.                 "description":"Bywało lepiej...",
  19.                 "advice":"Lepiej ogranicz dzisiaj swoją aktywność fizyczną na powietrzu.",
  20.                 "color":"#EFBB0F"
  21.             }
  22.         ],
  23.         "standards":[
  24.             {
  25.                 "name":"WHO",
  26.                 "pollutant":"PM25",
  27.                 "limit":25.0,
  28.                 "percent":115.71
  29.             },
  30.             {
  31.                 "name":"WHO",
  32.                 "pollutant":"PM10",
  33.                 "limit":50.0,
  34.                 "percent":114.53}
  35.         ]
  36.     },
  37.     "history":[ ..... ],
  38.     "forecast":[ ..... ]
  39. }

W celu pobrania danych w postaci załączonej powyżej można skorzystać z następującego programu:

  1. #include <WiFi.h>
  2. #include <HTTPClient.h>
  3. const char* ssid = "WIFI_SSID";
  4. const char* password =  "WIFI_PASSWORD";
  5. const String ENDPOINT_STRING = "https://airapi.airly.eu/v2/measurements/installation?installationId=2903";
  6. const String API_KEY = "&apikey=API_KEY";
  7. const String SENSOR_ID = "installationId=2903";
  8. void setup() {
  9.   Serial.begin(115200);
  10.   WiFi.begin(ssid, password);
  11.   while (WiFi.status() != WL_CONNECTED) {
  12.     delay(1000);
  13.     Serial.print("Connection with WIFI Network....");
  14.   }
  15.   Serial.println("Connected!");
  16. }
  17. void loop() {
  18.   if ((WiFi.status() == WL_CONNECTED))
  19.   {
  20.     HTTPClient http;
  21.     http.begin(ENDPOINT_STRING + SENSOR_ID + API_KEY); //Specify the URL
  22.     int httpResponseCode = http.GET();  //Make the request
  23.     if (httpResponseCode > 0)
  24.     {
  25.         String readedData = http.getString();
  26.         Serial.println(httpResponseCode);
  27.         Serial.println(readedData);
  28.     }
  29.     else
  30.     {
  31.       Serial.println("Http Request Error");
  32.     }
  33.     http.end();
  34.   }
  35.   delay(100000);
  36. }

W powyższym kodzie po połączeniu się z Wifi następuje pobranie i wyświetlenie nie obrobionych danych:


Poniższy drugi program wyciągnie wszystkie aktualne dane z czytnika:

  1. #include <ArduinoJson.h>
  2. #include <WiFi.h>
  3. #include <HTTPClient.h>
  4. #define JSON_BUFF_DIMENSION 30000
  5. const char* ssid = "WIFI_SSID";
  6. const char* password =  "WIFI_PASSWORD";
  7. const String ENDPOINT_STRING = "https://airapi.airly.eu/v2/measurements/installation?";
  8. const String API_KEY = "&apikey=API_KEY";
  9. const String SENSOR_ID = "installationId=2903";
  10. String jsonStringText;
  11. void setup() {
  12.   Serial.begin(115200);
  13.   WiFi.begin(ssid, password);
  14.   while (WiFi.status() != WL_CONNECTED) {
  15.     delay(1000);
  16.     Serial.print("Connection with WIFI Network....");
  17.   }
  18.   Serial.println("Connected!");
  19.   jsonStringText.reserve(JSON_BUFF_DIMENSION);
  20. }
  21. void loop() {
  22.   if ((WiFi.status() == WL_CONNECTED))
  23.   {
  24.     HTTPClient http;
  25.     http.begin(ENDPOINT_STRING + SENSOR_ID + API_KEY); //Specify the URL
  26.     int httpResponseCode = http.GET();  //Make the request
  27.     if (httpResponseCode > 0)
  28.     {
  29.         jsonStringText = http.getString();
  30.         Serial.println(httpResponseCode);
  31.         parseJsonData(jsonStringText.c_str());
  32.     }
  33.     else
  34.     {
  35.       Serial.println("Http Request Error");
  36.     }
  37.     http.end();
  38.   }
  39.   delay(100000);
  40. }
  41. void parseJsonData(const char * jsonString)
  42. {
  43.   DynamicJsonDocument jsonBuffer(100000);
  44.   auto error = deserializeJson(jsonBuffer, jsonString);
  45.   if (error) {
  46.     Serial.println("Deserialize error");
  47.     Serial.println(error.c_str());
  48.     return;
  49.   }
  50.   else
  51.   {
  52.     Serial.println("Deserialize OK!");
  53.   }
  54.   size_t len = measureJson(jsonBuffer);
  55.   Serial.println(len);
  56.   JsonArray list = jsonBuffer["current"];
  57.   String fromDateTime = jsonBuffer["current"]["fromDateTime"];
  58.   String tillDateTime = jsonBuffer["current"]["tillDateTime"];
  59.   //----------------------------------------------------------------
  60.   String namePM1 = jsonBuffer["current"]["values"][0]["name"];
  61.   String valuePM1 = jsonBuffer["current"]["values"][0]["value"];
  62.   String namePM25 = jsonBuffer["current"]["values"][1]["name"];
  63.   String valuePM25 = jsonBuffer["current"]["values"][1]["value"];
  64.   String namePM10 = jsonBuffer["current"]["values"][2]["name"];
  65.   String valuePM10 = jsonBuffer["current"]["values"][2]["value"];
  66.   String namePressure = jsonBuffer["current"]["values"][3]["name"];
  67.   String valuePressure = jsonBuffer["current"]["values"][3]["value"];
  68.   String nameHumidity = jsonBuffer["current"]["values"][4]["name"];
  69.   String valueHumidity = jsonBuffer["current"]["values"][4]["value"];
  70.   String nameTemperature= jsonBuffer["current"]["values"][5]["name"];
  71.   String valueTemperature = jsonBuffer["current"]["values"][5]["value"];
  72.   //----------------------------------------------------------------
  73.   String indexesName = jsonBuffer["current"]["indexes"][0]["name"];
  74.   String indexesValue = jsonBuffer["current"]["indexes"][0]["value"];
  75.   String indexesLevel = jsonBuffer["current"]["indexes"][0]["level"];
  76.   String indexesDescription = jsonBuffer["current"]["indexes"][0]["description"];
  77.   String indexesAdvice = jsonBuffer["current"]["indexes"][0]["advice"];
  78.   String indexesColor = jsonBuffer["current"]["indexes"][0]["color"];
  79.   //----------------------------------------------------------------
  80.   String standardsPM25Name = jsonBuffer["current"]["standards"][0]["name"];
  81.   String standardsPM25Pollutant = jsonBuffer["current"]["standards"][0]["pollutant"];
  82.   String standardsPM25Limit = jsonBuffer["current"]["standards"][0]["limit"];
  83.   String standardsPM25Percent = jsonBuffer["current"]["standards"][0]["percent"];
  84.   //----------------------------------------------------------------
  85.   String standardsPM10Name = jsonBuffer["current"]["standards"][1]["name"];
  86.   String standardsPM10Pollutant = jsonBuffer["current"]["standards"][1]["pollutant"];
  87.   String standardsPM10Limit = jsonBuffer["current"]["standards"][1]["limit"];
  88.   String standardsPM10Percent = jsonBuffer["current"]["standards"][1]["percent"];
  89.   Serial.println("----------------------------");
  90.   /*Current fromDateTime display */
  91.   Serial.println("fromDateTime: " + fromDateTime);    
  92.   /*Current tillDateTime display */  
  93.   Serial.println("tillDateTime: " + tillDateTime);
  94.   /*Current values display */
  95.   Serial.println("*****************");
  96.   Serial.println(namePM1 + " - " + valuePM1);
  97.   Serial.println(namePM25 + " - " + valuePM25);
  98.   Serial.println(namePM10 + " - " + valuePM10);
  99.   Serial.println(namePressure + " - " + valuePressure);
  100.   Serial.println(nameHumidity + " - " + valueHumidity);
  101.   Serial.println(nameTemperature + " - " + valueTemperature);  
  102.   /*Current indexes display */  
  103.   Serial.println("*****************");
  104.   Serial.println("Indexes name: - " + indexesName);
  105.   Serial.println("Indexes value: - " + indexesValue);  
  106.   Serial.println("Indexes level: - " + indexesLevel);
  107.   Serial.println("Indexes description: - " + indexesDescription);
  108.   Serial.println("Indexes advice: - " + indexesAdvice);
  109.   Serial.println("Indexes color: - " + indexesColor);
  110.   /*Current standards display */
  111.   Serial.println("*****************");
  112.   Serial.println("Standards name: - " + standardsPM25Name);
  113.   Serial.println("Standards pollutant: - " + standardsPM25Pollutant);  
  114.   Serial.println("Limit level: - " + standardsPM25Limit);
  115.   Serial.println("Percent description: - " + standardsPM25Percent);
  116.   Serial.println("*****************");
  117.   Serial.println("Standards name: - " + standardsPM10Name);
  118.   Serial.println("Standards pollutant: - " + standardsPM10Pollutant);  
  119.   Serial.println("Limit level: - " + standardsPM10Limit);
  120.   Serial.println("Percent description: - " + standardsPM10Percent);
  121.   Serial.println("----------------------------");
  122. }

Odczytane w ten sposób dane prezentują się w następujący sposób:


W powyższym programie korzystam z biblioteki ArduinoJson. Dzięki niej można w łatwy sposób wyciągnąć dane z obiektu JSON. Aktualnie dostępna jest biblioteka w wersji 6. Natomiast dużo przykładów zastosowania jej na internecie opisuje wersję 5. Dlatego w poniższym linku opisane jest w jaki sposób przejść na wyższą wersję (https://arduinojson.org/v6/doc/upgrade/).