Recupérer données reçues en json sur esp8266

Bonjour,
J'ai installé une station météo Ecowitt WS90 et récupère les données via une passerelle GW1100.
Cette passerelle permet via l'envoi d'une requête du type http://192.168.1.23/get_livedata_info de récupérer les données des capteurs sur cette forme :

{"common_list":[{ "id": "0x02", "val": "3.3", "unit": "C" }, { "id": "0x07", "val": "81%" }, { "id": "3", "val": "2.0", "unit": "C" }, { "id": "0x03", "val": "0.4", "unit": "C" }, { "id": "0x0B", "val": "5.40 km/h" }, { "id": "0x0C", "val": "5.40 km/h" }, { "id": "0x19", "val": "11.88 km/h" }, { "id": "0x15", "val": "123.05 W/m2" }, { "id": "0x17", "val": "1" }, { "id": "0x0A", "val": "120" }],"piezoRain":[{ "id": "srain_piezo", "val": "0" }, { "id": "0x0D", "val": "0.0 mm" }, { "id": "0x0E", "val": "0.0 mm/Hr" }, { "id": "0x10", "val": "0.0 mm" }, { "id": "0x11", "val": "1.5 mm" }, { "id": "0x12", "val": "1.5 mm" }, { "id": "0x13", "val": "59.1 mm", "battery": "5", "voltage": "" }],"wh25":[{ "intemp": "18.5", "unit": "C", "inhumi": "33%", "abs": "968.1 hPa", "rel": "1018.1 hPa" }],"ch_aisle":[{ "channel": "1", "name": "", "battery": "0", "temp": "2.2", "unit": "C", "humidity": "89%" }],"debug":[{ "heap": "26484", "runtime": "1206799", "usr_interval": "30", "is_cnip": false }]}

je voudrais pouvoir récupérer les différentes valeurs séparément pour pouvoir les exploiter sur un wemos d1 mini pro à base d'esp8266.

Pouvez vous m'aider ?
Bien cordialement
Phil

Il y a la librairie ArduinoJSON que tu trouveras dans le gestionnaire de librairies.
L'auteur propose un assistant qui te génère un modèle de code si tu lui passes un jeu de données que tu veux traiter.

@fdufnews merci pour votre réponse rapide et votre intérêt pour mon sujet.
l'assistant semble être intéressant mais pour l'instant je ne sais même pas comment récupérer cette trame de données depuis l'url 192..... ?

Il y a des exemples installés avec les librairies du package esp8266.
Par exemple, il y a la librairie ESP8266HTTPClient qui propose un exemple nommé BasicHttpClient qui récupère les infos retournées par une requête http. Commence avec ce code en remplaçant l'URL de l'exemple par l'URL de ta station météo.

J'ai bien réussi à récupérer la trame de données avec l'exemple que vous m'avez indiqué et un code 200.
Comment affecter les données à des variables exemple temperature, humidity, pressure etc... l'assistant jason ne m'aide pas pour çà ou bien je ne sais pas l'utiliser ?

  1. Tu ouvres un onglet sur l'assistant d'Arduino JSON
  2. Tu réponds aux quelques questions (choix du processeur, Deserialize, Stream), tu cliques Next et tu arrives à la fenêtre qui te propose de copier un JSON
  3. Tu ouvres un nouvel onglet. Tu colles l'URL de ta station météo dans la barre d'adresse de ton navigateur.
  4. Tu copies le contenu de la fenêtre qui contient la réponse de la station.
  5. Tu reviens dans l'onglet de l'assistant et tu colles le JSON
  6. Tu cliques Next et tu as les exemples de code pour extraire les champs de ton JSON

merci de bien détailler votre réponse, voici ce que j'obtiens :

// Stream& input;

JsonDocument doc;

DeserializationError error = deserializeJson(doc, input);

if (error) {
  Serial.print("deserializeJson() failed: ");
  Serial.println(error.c_str());
  return;
}

JsonArray common_list = doc["common_list"];

JsonObject common_list_0 = common_list[0];
const char* common_list_0_id = common_list_0["id"]; // "0x02"
const char* common_list_0_val = common_list_0["val"]; // "3.1"
const char* common_list_0_unit = common_list_0["unit"]; // "C"

const char* common_list_1_id = common_list[1]["id"]; // "0x07"
const char* common_list_1_val = common_list[1]["val"]; // "83%"

JsonObject common_list_2 = common_list[2];
const char* common_list_2_id = common_list_2["id"]; // "3"
const char* common_list_2_val = common_list_2["val"]; // "3.1"
const char* common_list_2_unit = common_list_2["unit"]; // "C"

JsonObject common_list_3 = common_list[3];
const char* common_list_3_id = common_list_3["id"]; // "0x03"
const char* common_list_3_val = common_list_3["val"]; // "0.5"
const char* common_list_3_unit = common_list_3["unit"]; // "C"

const char* common_list_4_id = common_list[4]["id"]; // "0x0B"
const char* common_list_4_val = common_list[4]["val"]; // "4.32 km/h"

const char* common_list_5_id = common_list[5]["id"]; // "0x0C"
const char* common_list_5_val = common_list[5]["val"]; // "5.40 km/h"

const char* common_list_6_id = common_list[6]["id"]; // "0x19"
const char* common_list_6_val = common_list[6]["val"]; // "11.88 km/h"

const char* common_list_7_id = common_list[7]["id"]; // "0x15"
const char* common_list_7_val = common_list[7]["val"]; // "0.00 W/m2"

const char* common_list_8_id = common_list[8]["id"]; // "0x17"
const char* common_list_8_val = common_list[8]["val"]; // "0"

const char* common_list_9_id = common_list[9]["id"]; // "0x0A"
const char* common_list_9_val = common_list[9]["val"]; // "135"

JsonArray piezoRain = doc["piezoRain"];

const char* piezoRain_0_id = piezoRain[0]["id"]; // "srain_piezo"
const char* piezoRain_0_val = piezoRain[0]["val"]; // "0"

const char* piezoRain_1_id = piezoRain[1]["id"]; // "0x0D"
const char* piezoRain_1_val = piezoRain[1]["val"]; // "0.0 mm"

const char* piezoRain_2_id = piezoRain[2]["id"]; // "0x0E"
const char* piezoRain_2_val = piezoRain[2]["val"]; // "0.0 mm/Hr"

const char* piezoRain_3_id = piezoRain[3]["id"]; // "0x10"
const char* piezoRain_3_val = piezoRain[3]["val"]; // "0.0 mm"

const char* piezoRain_4_id = piezoRain[4]["id"]; // "0x11"
const char* piezoRain_4_val = piezoRain[4]["val"]; // "1.5 mm"

const char* piezoRain_5_id = piezoRain[5]["id"]; // "0x12"
const char* piezoRain_5_val = piezoRain[5]["val"]; // "1.5 mm"

JsonObject piezoRain_6 = piezoRain[6];
const char* piezoRain_6_id = piezoRain_6["id"]; // "0x13"
const char* piezoRain_6_val = piezoRain_6["val"]; // "59.1 mm"
const char* piezoRain_6_battery = piezoRain_6["battery"]; // "5"
const char* piezoRain_6_voltage = piezoRain_6["voltage"]; // nullptr

JsonObject wh25_0 = doc["wh25"][0];
const char* wh25_0_intemp = wh25_0["intemp"]; // "18.6"
const char* wh25_0_unit = wh25_0["unit"]; // "C"
const char* wh25_0_inhumi = wh25_0["inhumi"]; // "41%"
const char* wh25_0_abs = wh25_0["abs"]; // "970.9 hPa"
const char* wh25_0_rel = wh25_0["rel"]; // "1020.9 hPa"

JsonObject ch_aisle_0 = doc["ch_aisle"][0];
const char* ch_aisle_0_channel = ch_aisle_0["channel"]; // "1"
const char* ch_aisle_0_name = ch_aisle_0["name"]; // nullptr
const char* ch_aisle_0_battery = ch_aisle_0["battery"]; // "0"
const char* ch_aisle_0_temp = ch_aisle_0["temp"]; // "3.6"
const char* ch_aisle_0_unit = ch_aisle_0["unit"]; // "C"
const char* ch_aisle_0_humidity = ch_aisle_0["humidity"]; // "81%"

JsonObject debug_0 = doc["debug"][0];
const char* debug_0_heap = debug_0["heap"]; // "26904"
const char* debug_0_runtime = debug_0["runtime"]; // "1238074"
const char* debug_0_usr_interval = debug_0["usr_interval"]; // "30"
bool debug_0_is_cnip = debug_0["is_cnip"]; // false

j'intègre ce bout de code au code exemple mais comment je retrouve mes variables temperature, pressure etc.... ?

Regarde les commentaires en fin de ligne tu as le contenu du champ extrait. Il ne faut conserver que les lignes qui t'intéressent.

supposons que cette ligne corresponde à la temperature exterieure, je peux mettre alors à la place ?
const char* temperature = common_list_0["val"]; // "3.1"

bien sûr

Cool je teste ça demain, merci déjà :+1:
Est ce que je peux mettre les variables en float plutot qu'en constant char ?

@fdufnews resultat du test, j'ai mis ceci dans le code :

JsonObject common_list_0 = common_list[0];
const char* common_list_0_id = common_list_0["id"]; // "0x02"
const char* temperature = common_list_0["val"]; // "3.1"
Serial.print("temperature:");
Serial.println(temperature);
const char* common_list_0_unit = common_list_0["unit"]; // "C"

le moniteur serie ne me retourne pas de valeur pour temperature !

Mets le code complet, s'il te plait.



#include <Arduino.h>
#include <ArduinoJson.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#include <WiFiClient.h>

ESP8266WiFiMulti WiFiMulti;

void setup() {

  Serial.begin(115200);
  // Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("Livebox-06A8", "xxxx");
}

void loop() {
  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    WiFiClient client;

    HTTPClient http;

    Serial.print("[HTTP] begin...\n");
    if (http.begin(client, "http://192.168.1.23/get_livedata_info")) {  // HTTP


      Serial.print("[HTTP] GET...\n");
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }

      http.end();
    } else {
      Serial.println("[HTTP] Unable to connect");
    }
    // Stream& input;

JsonDocument doc;
/*
DeserializationError error = deserializeJson(doc, input);

if (error) {
  Serial.print("deserializeJson() failed: ");
  Serial.println(error.c_str());
  return;
}
*/
JsonArray common_list = doc["common_list"];

JsonObject common_list_0 = common_list[0];
const char* common_list_0_id = common_list_0["id"]; // "0x02"
const char* temperature = common_list_0["val"]; // "3.1"
Serial.print("temperature:");
Serial.println(temperature);
const char* common_list_0_unit = common_list_0["unit"]; // "C"

const char* common_list_1_id = common_list[1]["id"]; // "0x07"
const char* common_list_1_val = common_list[1]["val"]; // "83%"

JsonObject common_list_2 = common_list[2];
const char* common_list_2_id = common_list_2["id"]; // "3"
const char* common_list_2_val = common_list_2["val"]; // "3.1"
const char* common_list_2_unit = common_list_2["unit"]; // "C"

JsonObject common_list_3 = common_list[3];
const char* common_list_3_id = common_list_3["id"]; // "0x03"
const char* common_list_3_val = common_list_3["val"]; // "0.5"
const char* common_list_3_unit = common_list_3["unit"]; // "C"

const char* common_list_4_id = common_list[4]["id"]; // "0x0B"
const char* common_list_4_val = common_list[4]["val"]; // "4.32 km/h"

const char* common_list_5_id = common_list[5]["id"]; // "0x0C"
const char* common_list_5_val = common_list[5]["val"]; // "5.40 km/h"

const char* common_list_6_id = common_list[6]["id"]; // "0x19"
const char* common_list_6_val = common_list[6]["val"]; // "11.88 km/h"

const char* common_list_7_id = common_list[7]["id"]; // "0x15"
const char* common_list_7_val = common_list[7]["val"]; // "0.00 W/m2"

const char* common_list_8_id = common_list[8]["id"]; // "0x17"
const char* common_list_8_val = common_list[8]["val"]; // "0"

const char* common_list_9_id = common_list[9]["id"]; // "0x0A"
const char* common_list_9_val = common_list[9]["val"]; // "135"

JsonArray piezoRain = doc["piezoRain"];

const char* piezoRain_0_id = piezoRain[0]["id"]; // "srain_piezo"
const char* piezoRain_0_val = piezoRain[0]["val"]; // "0"

const char* piezoRain_1_id = piezoRain[1]["id"]; // "0x0D"
const char* piezoRain_1_val = piezoRain[1]["val"]; // "0.0 mm"

const char* piezoRain_2_id = piezoRain[2]["id"]; // "0x0E"
const char* piezoRain_2_val = piezoRain[2]["val"]; // "0.0 mm/Hr"

const char* piezoRain_3_id = piezoRain[3]["id"]; // "0x10"
const char* piezoRain_3_val = piezoRain[3]["val"]; // "0.0 mm"

const char* piezoRain_4_id = piezoRain[4]["id"]; // "0x11"
const char* piezoRain_4_val = piezoRain[4]["val"]; // "1.5 mm"

const char* piezoRain_5_id = piezoRain[5]["id"]; // "0x12"
const char* piezoRain_5_val = piezoRain[5]["val"]; // "1.5 mm"

JsonObject piezoRain_6 = piezoRain[6];
const char* piezoRain_6_id = piezoRain_6["id"]; // "0x13"
const char* piezoRain_6_val = piezoRain_6["val"]; // "59.1 mm"
const char* piezoRain_6_battery = piezoRain_6["battery"]; // "5"
const char* piezoRain_6_voltage = piezoRain_6["voltage"]; // nullptr

JsonObject wh25_0 = doc["wh25"][0];
const char* wh25_0_intemp = wh25_0["intemp"]; // "18.6"
const char* wh25_0_unit = wh25_0["unit"]; // "C"
const char* wh25_0_inhumi = wh25_0["inhumi"]; // "41%"
const char* wh25_0_abs = wh25_0["abs"]; // "970.9 hPa"
const char* wh25_0_rel = wh25_0["rel"]; // "1020.9 hPa"

JsonObject ch_aisle_0 = doc["ch_aisle"][0];
const char* ch_aisle_0_channel = ch_aisle_0["channel"]; // "1"
const char* ch_aisle_0_name = ch_aisle_0["name"]; // nullptr
const char* ch_aisle_0_battery = ch_aisle_0["battery"]; // "0"
const char* ch_aisle_0_temp = ch_aisle_0["temp"]; // "3.6"
const char* ch_aisle_0_unit = ch_aisle_0["unit"]; // "C"
const char* ch_aisle_0_humidity = ch_aisle_0["humidity"]; // "81%"

JsonObject debug_0 = doc["debug"][0];
const char* debug_0_heap = debug_0["heap"]; // "26904"
const char* debug_0_runtime = debug_0["runtime"]; // "1238074"
const char* debug_0_usr_interval = debug_0["usr_interval"]; // "30"
bool debug_0_is_cnip = debug_0["is_cnip"]; // false
  }

  delay(30000);
}

Ça ne peut pas fonctionner puisque tu as mis en commentaire l'extraction du JSON. Du coup, doc ne contient rien.
Il faut faire

DeserializationError error = deserializeJson(doc, payload);

if (error) {
  Serial.print("deserializeJson() failed: ");
  Serial.println(error.c_str());
  return;
}

Il est inutile d'extraire tout les champs si tu ne les utilises pas.
Si tu ne veux que la température il te suffit de faire

JsonArray common_list = doc["common_list"];

JsonObject common_list_0 = common_list[0];
const char* temperature = common_list_0["val"]; // "3.1"
Serial.print("temperature: ");
Serial.println(temperature);

merci de prendre le temps de me répondre et suivre mon sujet même un dimanche :+1:

j'avais mis cette partie en commentaire car j'obtenais un message d'erreur comme celui ci maintenant :

Arduino : 1.8.19 (Linux), Carte : "Generic ESP8266 Module, 80 MHz, Flash, Disabled (new aborts on oom), Disabled, All SSL ciphers (most compatible), 32KB cache + 32KB IRAM (balanced), Use pgm_read macros for IRAM/PROGMEM, dtr (aka nodemcu), 26 MHz, 40MHz, DOUT (compatible), 4MB (FS:none OTA:~1019KB), 2, nonos-sdk 2.2.1+100 (190703), v2 Lower Memory, Disabled, None, Only Sketch, 115200"

/home/philippe/Arduino/sketch_feb08a/sketch_feb08a.ino: In function 'void loop()':
sketch_feb08a:74:51: error: 'payload' was not declared in this scope
   74 | DeserializationError error = deserializeJson(doc, payload);
      |                                                   ^~~~~~~
Plusieurs bibliothèque trouvées pour "ArduinoJson.h"
Utilisé : /home/philippe/Arduino/libraries/ArduinoJson
Non utilisé : /home/philippe/Arduino/libraries/arduino_418296
exit status 1
'payload' was not declared in this scope

et je ne peux pas compiler !

payload est déclarée dans un if donc cette variable est locale à ce bloc de code et elle est inconnue ailleurs dans le code.
il faudrait mettre String payload; après if ((WiFiMulti.run() == WL_CONNECTED)) {
et remplacer l'actuelle String payload = http.getString(); par payload = http.getString();

trop bien , ça fonctionne :
image

Super , j'ai bien la valeur de la température, :+1: et pour vous répondre je vais récolter plusieurs données comme la pression, l'humidité, les valeurs de vent etc... mais je vais donc sélectionner que les lignes correspondantes.
Encore une question est ce que je peux mettre ces valeurs en float au lieu de const char ?

Elle sont sous forme de chaînes de caractères dans le JSON. Donc il faudrait les convertir en flottants. Tu peux utiliser atof() pour convertir une c-string en flottant.

certaines valeurs viennent avec hPa ou % ou km/h comme celles ci :

15:00:51.355 -> Température:6.3
15:00:51.355 -> Humidité:75%
15:00:51.355 -> Pression:1024.5 hPa

est ce que cela ne sera pas un problème lorsque je voudrai renvoyer ces données sur mon serveur ?
est ce que ce serait pas mieux d'avoir les données seules 6.3, 75, et 1024.5 ?