Comment puis-je utiliser JSON pour envoyer des données

Bonjour,

Je cherche une solution pour envoyer des données avec le format JSON.

En gros, j'ai un GPS qui me collect les positions toutes les minutes.
Aussi, j'ai un module GSM qui va les envoyer.

Simplement, si je me trouve en montagne, il n'y aura pas forcement une antenne GSM mais par contre le GPS fonctionnera.

J'ai aussi une fonction qui va envoyer les données collectée via le 3G.

Quand une coordonée GPS sont collectées, il faut qu'il garde ca sous fomat JSON

{
"2003-08-16 08:00:00": {
"co": "course",
"la": "lattitude",
"lo": "longitude",
"al":"altitude",
"ve":"speed"
}
}

Mais s'il n'y a pas plus de 3G, il faut qu'il conserve les positions suivante de maniere à avoir ceci, par exempl et si ce n'est pas fau

{
"2003-08-16 08:00:00": {
"co": "course",
"la": "lattitude",
"lo": "longitude",
"al":"altitude",
"ve":"speed"
}
"2003-08-16 08:01:00": { // there is no GSM connection, then it increment to record the data, and it will send in block when GSM will be available
"co": "course",
"la": "lattitude",
"lo": "longitude",
"al":"altitude",
"ve":"speed"
}
"2003-08-16 08:02:00": {
"co": "course",
"la": "lattitude",
"lo": "longitude",
"al":"altitude",
"ve":"speed"
}
"2003-08-16 08:03:00": {
"co": "course",
"la": "lattitude",
"lo": "longitude",
"al":"altitude",
"ve":"speed"
}
}

Et une fois le 3G revenu, il envoi tout au serveur.

J'ai trouvé une librairie intéressante

mais je peine a la faire fonctionnée et j'aurais voulu savoir si vous auriez pas une autre solution avec exemple qui repondrait à mon besoin.

En attendant, voila mon code simplifié qui fonctionne avec la librairie que je vous ai donné juste dessus.
Connaitriez vous cette librairie? pourriez-vous m'aider?

A savoir que la fonction SendDATA est appelée chaque miniute. Chauqe minute cette fonction va connaitre la position, grace a la fonction gps.getPar(lon,lat,alt,time,vel); Puis s'il y a pas de 3G conserve la position si non envoi

// Send data to the sremote erver
void SendData(void){
   #ifdef DEBUG
     Serial.println(F("\nSENDING COORDS TO THE REMOTE SERVER"));
   #endif
     
    // It collect statictis and return 0,1,2 or or 3. See below
    stat=gps.getStat();
    
    #ifdef DEBUG
      if(stat==0){
        Serial.println(F("GPS OFF"));
        Serial.println(F("No coords sent"));
      }else if(stat==1){
         Serial.println(F("NOT FIXED"));
         Serial.println(F("No coords sent"));
      }else if(stat==2){
         Serial.println(F("2D FIXED"));
      }else if(stat==3){
         Serial.println(F("3D FIXED"));
      }
    #endif

     //Get data from GPS
     
     // Send the data only if the are FIXes, otherwise giveup the send function
     // This is to avoid battery consomation
     if(stat == 2 || stat == 3 || stat == 0){
     // I added stat==0 for testing, as I do not have always fixes. It does not matter if I have 0.00000, for JSON testing
      
       // That function collect the coordinate. It's works fine
       gps.getPar(lon,lat,alt,time,vel); // the 5 variable a declare above. Ex: char lon[15];
       
       
       // Convert Int to char
       char course_id[6] = {0};
       sprintf(course_id, "%d", courseid);
       puts(course_id);
       
      /* EXPLICATION:
       HERE IS MY JSON and it does not display my JSON string (value)
       Be aware and I do not know I did it correctly
       I do declared the following below my librairies, on the top of my script:
          //JSON
          aJsonObject *root,*online;
          char* value;

      In my steup(), I add this code:
         //JSON
         root=aJson.createObject();
       */
       // HERE IS MY JSON CODE

       aJson.addItemToObject(root, time, online = aJson.createObject()); 
      // the variable time come from the function  gps.getPar(lon,lat,alt,time,vel);
      
       aJson.addStringToObject(online,"co", "course"); // I will later change "course" with the varibale course_id
       aJson.addStringToObject(online,"lo", "long"); // I will later change "long" with the varibale lon
       aJson.addStringToObject(online,"la", "lat"); // I will later change "lat" with the varibale lat
       aJson.addStringToObject(online,"al", "alt"); //etc
       aJson.addStringToObject(online,"ve", "vel"); //etc
       */
       
       value = aJson.print(root);
       Serial.print("value : ");
       Serial.println(value); // that value display nothing, empty , why
       
       #ifdef DEBUG
         Serial.println(F("Sending now... . Wait for 5 to 10 seconds"));
       #endif      
       
       if(inet.httpPOST(host, port_post, path_post, value, "Result", 0)){
         // Emvoi reussi. JESON peut etre effacé
       }else{
         // Envoi pas possible, JSON doit ajouté les positions suivantes. Comment on fait?
       }
          
       #ifdef DEBUG
         Serial.print(F("Data sent : "));
         Serial.println(value);
         Serial.println(F("Wait for 10 second"));
       #endif
          
       delay(10000);
     }       
     enterCommand();
}
// End sendDATA()

Merci pour vos lumières et j'espère avoir donné assez d'info. Dites moi si ce n'est pas le cas.

Hello
Personne a une expérience pour encodee des données en JSON pour les envoyer sur un serveur distant?
Et aussi comment additionner des données dans la structure JSON si le connexion n'est pas bonne afin de les emvoyer tout en bloque quand la connecion est de nouveau disponible.
Votre aide me serait précieuse

Milles mercis

Bonjour,

  1. Garde tes informations sous format binaire dans une structure tant que tu ne les envoient pas. Encoder du json et entasser des données textuelles au fur et à mesure n'est pas une bonne façon de faire.
  2. Pour encoder du json il suffit d'aller lire la syntaxe sur wikipedia, c'est ultra simple comme syntaxe :wink:
{
"2003-08-16 08:00:00": {
  "co": "course",
  "la": "lattitude",
  "lo": "longitude",
  "al":"altitude",
  "ve":"speed"
 }
}

= 133 octets

struct gpsCoord {
  unsigned int year;
  byte month;
  byte day;
  byte hour;
  byte minute;
  byte second;

  float course;
  float lattitude;
  float longitude;
  float altitude;
  float speed;
};

= 47 octets, et seulement 17 si tu passes de nombres à virgule flottante (float) à des nombres à virgule fixe (int = float * coeff).

Bonjour

Franchement utiliser une lib là ou de simple print() font l'affaire me parait superflu....

Ceci étant dit

  1. Tu dois d'abord résoudre ton problème de stockage.
    Pour cela tu dois utiliser en variables globales soit un tableau de structure, soit N tableaux pour stocker les données
    Compte tenuque ton code est partiel que que je ne sait pas quel est le type des variables lon,lat,alt,time,vel, pour l'exemple je considère que ce sont des entiers (a adapter en fonction du type réel)

Avec structure :

typedef struct 
{
   int lon;
   int lat;
   int alt;
   int time;
   int vel;
} GPS_DATA;

#define GPS_DATA_COUNT 10

GPS_DATA GpsData[GPS_DATA_COUNT];

int NextDataIndex = 0;

Ou avec N tableaux :

#define GPS_DATA_COUNT 10

int lonData[GPS_DATA_COUNT];
int latData[GPS_DATA_COUNT];
int altData[GPS_DATA_COUNT];
int timeData[GPS_DATA_COUNT];
int velData[GPS_DATA_COUNT];

int NextDataIndex = 0;

Et comme dit par Skywodd, il faut garder les infos le plus compact possible donc en binaire plutot qu'en caractères/string.

  1. tu dois structurer ton programme pour gérer la sauvegarde en mémoire si la transmission ne fonctionne pas
    par exemple un algorithme du genre :
    Note : par principe n'appelle pas SendData une fonction qui est chargée à la fois de lire le GPS et d'envoyer les données.
    Sépare les 2 fonctions.
    La fonction SendData(void) devrait être int SendData( int lon, int lat, int alt, int time, int vel );
    Et ne comporter que le code d'emission
    Elle devrait retourner une information de bonne exécution telle que un boolean à TRUE si OK ou FALSE si NOK.
- Attendre 1 minute
- Recupérer les nouvelles données GPS
     gps.GetData( lastLon, lastLat, ... );

- S'il y a des données en mémoire d'abord chercher à les envoyer  (if NextDataIndex > 0)
    
    for ( i = 0 ; i < NextDataIndex ; i++ )
    {
      sendOk = SendData( lonData[i], latData[i], ..... )
      if ( !sendOk )  // rappel on ne compare JAMAIS un boolean à TRUE ou FALSE car un boolean est déjà une comparaison en lui même. On teste directement s'il est TRUE par if (xxx) ou FALSE par if (!xxx)
         break;
    }

    if ( sendOk  || (NextDataIndex == 0) ) // Si on a tout bien envoyé le contenu de la mémoire ou bien s'il n'y a rien en mémoire on envoie les dernieres infos directement
    {
      NextDataIndex = 0; // on a tout envoyé, donc on efface la mémoire en remettant l'index à 0
      sendOk = SendData( lastLon, lastLat, ...); // on envoi les dernière données récupérées)
      if ( !sendOk && (NextDataIndex < GPS_DATA_COUNT) )
      {
         // Si l'envoi des dernièers info pas OK et s'il reste de la place dans le tableau, on mémorise les infos
         lonData[NextDataIndex] = lastLon;
         latData[NextDataIndex] = lastLat;
         .... on fait pareil avec les autres
         ++NextDataIndex; // on avance l'index d'1 case
      }
    }

Ceci est un pseudo code de principe pour donner des idées et non pas une solution toute faite.

Ne pas oublier qu'une Arduino a peu de mémoire (Uno notamment, moins vrai s'il s'agit d'une Due) donc tu ne peut pas définit une taille de tableau trop grande.
Si tu veux stocker beaucoup de données, il va falloir passer par un fichier sur une carte SD.

Allez, hop, je retourne dans mon trou de marmotte....

Je vous remercie pour vos info.
Je vous avoue ne pas avoir le temps de me plonger a fond dans vos explications, mais le ferai evidement d'ici très peu.

Au passage, lat, lon, alt, time, vel, sont des char pas des int.

char lat[15];
char lon[15];
char alt[15];
etc...

Merci, je reviens un peu plus tard

Bonjour,
Je viens de relire vos avis.

En resumé, ne pas utlisé JSON alors et pour le moment je préfere donc me concentrer sur la mémorisation des positions GPS dans le cas ou le 3G n'était pas disponible.

Aussi je prends note de votre conseil, celui de séparer l'envoi des données et la collection des positions. Pour le moment, je vais laisser comme ceci parce que je veux pouvoir envoyer manuellement les données. Donc je souhaite pouvoir taper dans mon terminal "send" pour qu'il execute la commane sendDATA() et elle doit donc pouvoir recupérer les coordonnées. Mais je tiens compte de vos conseils et je modifirai ceci plus tard. C'est pas compliquer à le faire.

Cependant, je bloque sur l'empilation des données dans un tableau ou dans un structure. Je suis un peu débutant et je ne connais pas cette méthode
A savoir qu ce n'est pas des int mais des char car la fonction qui me retourne les positions gps

gps.getPar(lon,lat,alt,time,vel);

me retourne des char

typedef struct 
{
   int lon;
   int lat;
   int alt;
   int time;
   int vel;
} GPS_DATA;

#define GPS_DATA_COUNT 10

GPS_DATA GpsData[GPS_DATA_COUNT];

int NextDataIndex = 0;

Pourriez me donner un exemple à partir de cette exemple (j'y met des commentaires)
La variable char coords[97]; contient les positions sous format d'une URL par exemple :

co=7567&lo=45.67876&la=34.3456&al=456.87&ti=2013-08-23 12:00:00&ve=3.87683

et c'est ca que je voudrais mémorier si la connection n'est pas bonne.

//A mémoriser dans une array si la connexion n'est pas bonne et à envoyer plus tard quand elle sera rétablie
co=7567&lo=45.67876&la=34.3456&al=456.87&ti=2013-08-23 12:00:00&ve=3.87683
co=7567&lo=45.47876&la=34.4456&al=446.87&ti=2013-08-23 12:01:00&ve=3.87683
co=7567&lo=45.57876&la=34.2456&al=446.87&ti=2013-08-23 12:02:00&ve=3.8222
co=7567&lo=45.67876&la=34.3456&al=446.87&ti=2013-08-23 12:03:00&ve=3.87683

Pour info, je peux aussi prévoir simplifier ceci comme ceci (qui ne serait pas une mauvaise idée:

co=7567,45.67876,34.3456,456.87,2013-08-23 12:00:00,3.87683 // lo, la, al, ti, ve

// Ceci est déclaré au début du code, pour information
char lon[15];
char lat[15];
char alt[15];
char time[14];
char vel[15];
char co[]="co=";
char lo[]="&lo=";
char la[]="&la=";
char al[]="&al=";
char ti[]="&ti=";
char ve[]="&ve=";

// MA COMMANDE EST APPELLEE
// Send data to the sremote erver
void SendData(void){
   #ifdef DEBUG
     Serial.println(F("\nSENDING COORDS TO THE REMOTE SERVER"));
   #endif
     
    // JE DEPLACERAI LA PARTIE GPS PLUS TARD. POUR LE MOMENT, JE SOUHAITE LAISSE COMME CECI
    // It collect statictis and return 0,1,2 ou3. See below
    stat=gps.getStat();

    //Get data from GPS
     
    // Send the data only if the are FIXes, otherwise giveup the send function
    // This is to avoid battery consomation
    if(stat == 2 || stat == 3 || stat == 0){
      
       // That function collect the coordinate. It's works fine
       gps.getPar(lon,lat,alt,time,vel); // the 5 variable a declare above. Ex: char lon[15];
       
       char coords[97]; 
       
       // Convert Int to char
       char course_id[6] = {0};
       sprintf(course_id, "%d", courseid);
       puts(course_id);      

      strcpy(coords,co);
      strcat(coords,course_id);
          
      strcat(coords,lo);
      strcat(coords,lon);
   
      strcat(coords,la);
      strcat(coords,lat);
    
      strcat(coords,al);
      strcat(coords,alt);
  
       strcat(coords,ti);
       strncat(coords,time,14);
    
       strcat(coords,ve);
       strcat(coords,vel);
       
       #ifdef DEBUG
         Serial.println(F("Sending now... . Wait for 5 to 10 seconds"));
       #endif      
       
       // S IL Y A DES DONNEES MEMORISEES D'ABORD ESSAYER DE LES EVOYEZ, mais comment faire cette mémorisation
       // PUIS ENVOYER LA POSITION COLLECTEE JUSTE A L INSTENT SI

       if(inet.httpPOST(host, port_post, path_post, coords, "Result", 0)){
         // Emvoi reussi. l'Array peut etre effacé
       }else{
         // Envoi pas possible, l'array doit contenir les positions suivantes. Comment on fait?
       }
          
       #ifdef DEBUG
         Serial.print(F("Data sent : "));
         Serial.println(coords);
         Serial.println(F("Wait for 10 second"));
       #endif
          
       delay(10000);
     }       
}
// End sendDATA()

Utilise la fonction sprintf() :wink:

Tu peut t'inspirer de mon code pour faire ton sprintf() + structure.