Soucis de serialisation avec ArduinoJson sur ESP32

Bonsoir,

Je cherche à créer un Json qui contient la liste des SSID WiFi accessibles.
Pour l'instant, j'ai fait un programme de simulation car j'ai un soucis de sérialisation.
Voici ce que je cherche à obtenir :

[
  {
    "ssid": "SSID_0",
    "rssi": "RSSI_0",
    "encrypt": "Encrypt_0"
  },
  {
    "ssid": "SSID_1",
    "rssi": "RSSI_1"
    "encrypt": "Encrypt_1"
  },
  {
    "ssid": "SSID_2",
    "rssi": "RSSI_2"
    "encrypt": "Encrypt_2"
  }
]

Voilà ce j'obtiens avec le programme que je joins plus bas. :

[
  {
    "ssid": "SSID_0",
    "rssi": "RSSI_0",
    "encrypt": "Encrypt_0"
  },
  {
    "ssid": "SSID_1",
    "rssi": "RSSI_1"
  }
]

Il manque la fin.
Voici le programme de test :

#include <ArduinoJson.h>

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

    const int capacity = JSON_ARRAY_SIZE(2) + 4 * JSON_OBJECT_SIZE(2);
    StaticJsonDocument<capacity> doc;

    for (int i = 0; i <= 4; i++)
    {
      JsonObject obj = doc.createNestedObject();
      obj["ssid"] = "SSID_" + String(i);
      obj["rssi"] = "RSSI_" + String(i);
      obj["encrypt"] = "Encrypt_" + String(i);
    }
 
    Serial.println("\n_________________________________________________________\n");
    Serial.println("résultat serializeJsonPretty");
    serializeJsonPretty(doc, Serial);
}

void loop()
{    
}

Là je devrais obtenir 5 SSID et je n'en ai que 1 entier.
Quelle est mon erreur ?

Merci de votre aide.

Comment avez vous obtenu cette taille ? C’est sans doute trop petit. Mettez 500 juste pour tester.

Il y a un outil sur son site pour faire le calcul. ➜ Assistant | ArduinoJson 6
(Il vous manque des virgules après le RSSI pour les 2 derniers)

L’outil en static donne 192


StaticJsonDocument<192> doc;

JsonObject doc_0 = doc.createNestedObject();
doc_0["ssid"] = "SSID_0";
doc_0["rssi"] = "RSSI_0";
doc_0["encrypt"] = "Encrypt_0";

JsonObject doc_1 = doc.createNestedObject();
doc_1["ssid"] = "SSID_1";
doc_1["rssi"] = "RSSI_1";
doc_1["encrypt"] = "Encrypt_1";

JsonObject doc_2 = doc.createNestedObject();
doc_2["ssid"] = "SSID_2";
doc_2["rssi"] = "RSSI_2";
doc_2["encrypt"] = "Encrypt_2";

serializeJson(doc, output);

Dans le programme il y a

Donc tu cherches à créer un tableau avec 5 objets.

Cette ligne est erronée puisque le json à générer doit contenir un tableau 5 objets et chaque objet ayant de 3 item ce qui donnerait

const int capacity = JSON_ARRAY_SIZE(5) + 5* JSON_OBJECT_SIZE(3);

Cependant si on fait imprimer capacity avec cette définition on trouve 192 octets alors que si on utilise le simulateur sur le site arduinojson.org avec le modèle que tu veux obtenir il indique qu'il faut réserver au moins 384 octets.

Si tu remplaces

const int capacity = JSON_ARRAY_SIZE(2) + 4 * JSON_OBJECT_SIZE(2);

par

const int capacity = 384;

Le programme fonctionne

EDIT: l'essai du programme et la simulation ont été fait sur AVR pas ESP32 d'où l'écart avec les valeurs indiquées plus bas

en l'utilisant j'ai trouvé 192 pour AVR

Si vous passez en ESP32 il donne le double

à noter d'ailleurs que le commentaire est faux, 384 n'est pas une puissance de 2

Merci messieurs pour votre aide,

J'avais bêtement recopié la formule de calcul sur un exemple.
Cependant avec 384, j'arrête à 3. Si je mets 512, j'arrive à 5.
Je vais tester quelle valeur mettre pour atteindre potentiellement 10.
L'objectif est de liste tous les SSID visibles autour de l'ESP32, dans certains quartiers, ils peut y en avoir plusieurs dizaines. Je vais me limiter à 10.
Cordialement

Je ne sais pas si cela correspond au besoin exact, mais :

un petit update.

  • avec 512, je bloque à 5 entrées dans le json,
  • avec 768, à 8 entrées et
  • avec 1024 à 10 entrées.

Encore une fois merci.

Merci pour l'info,
Je vais tester cette librairie.
Petite question, est-elle compatible avec la librairie ESPAsyncWebServer ?

il vous faut déterminer une taille max pour les 3 éléments.

Par exemple la spec WiFi dit qu'un SSDI ne peut pas avoir plus de 32 caractères.

Pour le RSSI, En Wi-Fi les valeurs usuelles de RSSI varient de −30 dBm à −90 dBm. En 2G et 3G, on varie entre -30 dBm et −120 dBm selon la distance avec l'antenne émettrice et on peut aller jusqu'à −140 dBm dans les réseaux 4G LTE. On pourrait coder cela en entier sur un octet entre 30 et 140 par exemple.

j'imagine que encrypt c'est le mot de passe ? un mot de passe fait au max 63 caractères dans la spec 802.11 et 64 pour une clé PSK

➜ si vous voulez réserver la place max pour chaque entrée et ainsi rester flexible, il vous faudra 32+1+64 octets (sans compter un caractère nul de terminaison des cStrings) = 97 octets. En rajoutant le caractère null, ça fait 99. et 100 si vous voulez coder le RSSI directement sous forme int16_t

donc pour 10 entrées, sous forme de structure, il faudrait prévoir 1000 octets

struct __attribute__((packed)) t_WiFi {
  char SSID[32+1];    // 33 octets
  char CRYPT[64+1];   // 65 octets
  int16_t RSSI;       // 2 octets
} ;

// le tableau pour stocker les 10
t_WiFi lesReseaux[10]; // 1000 octets

après ça peut se mettre en flash, pas forcément besoin de tout garder en SRAM

Je ne vois pas pourquoi elle ne le serait pas. WiFiManager s'occupe du WIFI,
ESPAsyncWebServer du HTTP.

idem

Avec WiFi Manager l'ESP32 aura deux modes de fonctionnement distincts, indépendants l'un de l'autre :

-Point d'accès faisant tourner un petit serveur HTTP (mode temporaire pour établir la configuration)

-Station faisant tourner AsyncWEbServer (mode de fonctionement principal une fois configurée la connection au point d'accès désiré)