[JSON] Parser l'API d'openweathermap

Bonjour à tous,

J’essaye désespérément d’utiliser l’api d’openweathermap dans un de mes sktech sur un ESP8266 (Wemos D1 mini Pro).

Voici le code que j’utilise:

// Importation des librairies
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

// Définition des constantes
const char* SSID     = "*****"; // Le nom de votre réseau Wifi
const char* SSID_MDP = "*****"; // Le mot de passe de vôtre réseau Wifi
const char* LANGUE = "fr"; // Langue (ar,bg,ca,cz,de,el,en,fa,fi,fr,gl,hr,hu,it,ja,kr,la,lt,mk,nl,pl,pt,ro,ru,se,sk,sl,es,tr,ua,vi,zh_cn,zh_tw)
const char* EMPLACEMENT = "cherbourg-octeville"; // Le nom de votre ville
const char* API = "*****"; // Votre numéro d'API pour OpenWeatherMap

// Déclaration des objets
HTTPClient http;
StaticJsonBuffer<32000> jsonBuffer;

void setup()
{
  Serial.begin(115200);
  Serial.println();

  WiFi.begin(SSID, SSID_MDP);

  Serial.print("Connection");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.print("Connecté, adresse IP: ");
  Serial.println(WiFi.localIP());
}

void loop() 
{


  if(WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi non connecté !");
  }
  else {  
      Serial.println("Envoi de la requête");
      String url = "http://api.openweathermap.org/data/2.5/forecast?q=";
      url += String(EMPLACEMENT);
      url += "&lang=";
      url += String(LANGUE);
      url += "&appid=";
      url += String(API);
      http.begin(url);
      int httpCode = http.GET();
      if (httpCode == 200) {
        String reponse = http.getString();
        
        JsonObject& root = jsonBuffer.parseObject(reponse);

        const char* cod = root["cod"]; // "200"
        float message = root["message"]; // 0.0036
        int cnt = root["cnt"]; // 40        

        JsonArray& list = root["list"];

        JsonObject& list0 = list[0];
        long list0_dt = list0["dt"]; // 1485799200
        
        JsonObject& list0_main = list0["main"];
        float list0_main_temp = list0_main["temp"]; // 261.45
        float list0_main_temp_min = list0_main["temp_min"]; // 259.086
        float list0_main_temp_max = list0_main["temp_max"]; // 261.45
        float list0_main_pressure = list0_main["pressure"]; // 1023.48
        float list0_main_sea_level = list0_main["sea_level"]; // 1045.39
        float list0_main_grnd_level = list0_main["grnd_level"]; // 1023.48
        int list0_main_humidity = list0_main["humidity"]; // 79
        float list0_main_temp_kf = list0_main["temp_kf"]; // 2.37
        
        JsonObject& list0_weather0 = list0["weather"][0];
        int list0_weather0_id = list0_weather0["id"]; // 800
        const char* list0_weather0_main = list0_weather0["main"]; // "Clear"
        const char* list0_weather0_description = list0_weather0["description"]; // "clear sky"
        const char* list0_weather0_icon = list0_weather0["icon"]; // "02n"
        
        Serial.println(list0_weather0_description);
      }
      else {
        Serial.print("Erreur HTTP: ");
        Serial.println(httpCode);
        }
        
      http.end();
      
    }

  delay (5000000);
}

Et voici la réponse sur le moniteur série:

⸮⸮
Connection..
Connecté, adresse IP: 192.168.1.15
Envoi de la requête

Donc pour le wifi c’est ok, je suppose donc que je me viande sur le JSON.

Pour info voici la réponse attendue de l’API en JSON (je l’ai tronquée pour faciliter la lecture):

{
  "cod": "200",
  "message": 0.0027,
  "cnt": 40,
  "list": [
    {
      "dt": 1513620000,
      "main": {
        "temp": 278.99,
        "temp_min": 278.99,
        "temp_max": 281.422,
        "pressure": 1044.42,
        "sea_level": 1046.04,
        "grnd_level": 1044.42,
        "humidity": 100,
        "temp_kf": -2.43
      },
      "weather": [
        {
          "id": 800,
          "main": "Clear",
          "description": "ciel dégagé",
          "icon": "01n"
        }
      ],
      "clouds": {
        "all": 0
      },
      "wind": {
        "speed": 3.77,
        "deg": 33.003
      },
      "rain": {},
      "sys": {
        "pod": "n"
      },
      "dt_txt": "2017-12-18 18:00:00"
    },
    {
      "dt": 1513630800,
      "main": {
        "temp": 279.39,
        "temp_min": 279.39,
        "temp_max": 281.21,
        "pressure": 1045.78,
        "sea_level": 1047.39,
        "grnd_level": 1045.78,
        "humidity": 100,
        "temp_kf": -1.82
      },
      "weather": [
        {
          "id": 800,
          "main": "Clear",
          "description": "ciel dégagé",
          "icon": "01n"
        }
      ],
      "clouds": {
        "all": 0
      },
      "wind": {
        "speed": 2.06,
        "deg": 43.0059
      },
      "rain": {},
      "sys": {
        "pod": "n"
      },
      "dt_txt": "2017-12-18 21:00:00"
    },

Merci de votre aide!

Bonsoir

https://arduinojson.org/assistant/

donne le code dans les deux sens il suffit de coller le json a decoder ou a coder

cordialement

PS arrivez vous a écrire le json reçu sur le moniteur série ?

Bonsoir, effectivement quand je fait un println de la variable reponse contenant le JSON, rien ne s'affiche sur le moniteur série. Peut-être est-ce du à la taille du JSON? Si je remplace api.openweathermap.org/data/2.5/forecast?q=London par api.openweathermap.org/data/2.5/weather?q=London qui me transmet un JSON beaucoup plus petit j'ai bien le contenu de "reponse" qui s'affiche dans le moniteur série.

Pour info voici un exemple de réponse en JSON: http://samples.openweathermap.org/data/2.5/forecast?id=524901&appid=b6907d289e10d714a6e88b30761fae22

Bonjour

La différence de taille de la réponse est très importante. la requête weather renvoie les seules conditions actuelles et forecast les prévisions (testé à l'instant : environ 500 octets contre 14800). Les prévisions sont pour 5 jours avec un intervalle de 3h

De quoi as tu besoin : conditions actuelles ou prévisions ? Dans le premier cas l'affichage de la réponse dans le terminal devrait faciliter la mise au point du parsing

la ligne StaticJsonBuffer<32000> jsonBuffer;définit la taille du buffer. Si elle est trop faible, le code ne fonctionnera pas. La page indiquée par jfs59 te donnera aussi la taille adaptée à ton cas.

Avec un buffer de 32000 octets, on a déjà droit à un avertisement quand à la RAM restante...la voie est étroite !!

En cas de pb pour traiter la réponse volumineuse à la requête *'forecast' *il faudra peut être avoir recours à un traitement de la réponse 'au fil de l'eau' donc en extrayant des données au fûr et à mesure de leur arrivée dans le flux de la réponse.

Pour ses diverses 'stations meteo' Squix utilise sa librairie json_streaming_parser pour parser la réponse de l'API du site meteo Wunderground, (prévisions météo incluses)

Son github permet de voir la mise en oeuvre de sa librairie pour 2 stations méteo de son cru