IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Encore une question de caractères et de pointeurs


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut Encore une question de caractères et de pointeurs
    Bonjour à à tous
    Je stocke des messages d'évènements dans un tableau de pointeurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char *notif[NB_NOTIF] = {" Perte du secteur",                     //0
                      " Le groupe n'a pas démarré",                   //1
                      " Le groupe a démarré",                         //2
                      " Le secteur est rétabli",                      //3
                      " Secteur absent, groupe non opérationnel"      //4
                      " Le groupe n'est pas opérationnel",            //5
                      " Nombre d'echecs max atteint; nouvel essai dans delai REESSAI"}; //6
    Lorsqu' un ou plusieurs évènements se produisent, je souhaite ajouter devant le message, l'heure pour obtenir par exemple:
    16:34:15 Perte du secteur;
    16:34:45 Le groupe a démarré;
    Pour cela, lorsque l'évènement se produit, je passe à TRUE un drapeau valNotif[NB_NOTIF] puis j'obtiens l'heure correctement formatée que je charge dans un tableau d'heures hNotif[NB_Notif] ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char buf[11];
    valNotif[0]=true;   //Perte du secteur
    lectureHeure();
    sprintf(buf," %02d:%02d:%02d ",hr,mn,sd);
    hNotif[0]=buf;
    Puis, lorsque le moment est adéquat, je devrais pouvoir constituer un message affichant tous les évènements avec l'heure à laquelle il s'est produit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //************************préparation du message de notification***************
    void notifAEnvoyer(){ 
      String msg="";
      for(i=0;i<NB_NOTIF;i++){
        if(valNotif[i]){
          msg += hNotif[i];
          msg += notif[i];
          msg += ";";
          valNotif[i]=false;
        }
      }
      envoiNotif(msg);
    Ma question: comment déclarer le tableau qui va recevoir les heures ?

    Je sais que je pourrais utiliser un tableau de String pour hNotif, mais je souhaiterais le faire plus C++.

  2. #2
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    Hello,

    Si j'avais dû programmer cela, j'aurais opté pour cette approche avec une structure minimaliste:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    char *notif_msg[TOT_NOTIF] = {
    	" Perte du secteur",
    	" Le groupe n'a pas démarré",
    	" Le groupe a démarré",
    	" Le secteur est rétabli",
    	" Secteur absent, groupe non opérationnel",
    	" Le groupe n'est pas opérationnel",
    	" Nombre d'echecs max atteint; nouvel essai dans delai REESSAI"
    };
     
    enum notif_index {POWER_LOST, NOT_STARTED, STARTED, POWER_BACK, NOT_READY, MAX_TRIED_REACHED};
     
    #define MAX_NOTIF ....
     
    struct notif {
    	int reason;
    	int hh, mm, ss;
    } notif[MAX_NOTIF];
     
    int nbr_notif=0;
    Lorsqu'un évènement se produit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    notif[nbr_notif].reason=POWER_LOST;										// par exemple
    lectureHeure();
    notif[nbr_notif].hh=hh;
    notif[nbr_notif].mm=mm;
    notif[nbr_notif].ss=ss;
    nbr_notif++;
    Et pour l'affichage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(nbr_notif) {
    	for(int i=0; i<nbr_notif; i++)
    		printf("%02d:%02d:%02d %s\n", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    	nbr_motif=0;
    }

  3. #3
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut Peut-on se passer du String?
    Merci edgarjacobs pour cette solution en effet beaucoup plus élégante que la mienne.
    Une question concernant la partie affichage
    printf("%02d:%02d:%02d %s\n", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    Quelle est la syntaxe pour envoyer ce résultat vers ma routine d'envoi de notifications:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    //***********************Envoi notifications****************************************************
    bool envoiNotif(const String &message) {        // Push Envoyer un message
      uint32_t broadcastingTime = millis(); 
      String messagebody = R"({"type": "note", "title": "Control secteur", "body": ")" + message + R"("})";
      sClient.setInsecure();                   // en http
      while(!sClient.connect(HOST, 443)) {
        if(millis()-broadcastingTime > TIMEOUT){
          Serial.println("La connexion a echoue !");
          return false;
        }
      }
      //Serial.println("Push emis");
      //****Envoi message****
      sClient.printf("POST /v2/pushes HTTP/1.1\r\nHost: %s\r\nAuthorization: Bearer %s\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n%s\r\n"\
                      , HOST, CLE, messagebody.length(), messagebody.c_str()); 
      broadcastingTime = millis();
      while(!sClient.available()){
        delay(1);      //nécessaire au fonctionnement
        if (millis()-broadcastingTime > TIMEOUT) {
          Serial.print("Client Timeout");
          sClient.stop();
          return false;
        }
      }
      while (sClient.available()) {               //Réception d'une réponse
        //Serial.printf("Reponse en: %4ld ms\n", millis() - broadcastingTime);
        String line = sClient.readStringUntil('\n');
        if (line.startsWith("HTTP/1.1 200")) {
          sClient.stop();
          lcd.clear();
          return true;
        }
      }
      return false;
    }
    Est-ce que je peux tenter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char buf[80];
    sprintf(buf,"%02d:%02d:%02d %s\n", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    if(envoiNotif(buf)){ ..... }
    Après la mise en place de cette solution, au moment de constituer la notification complète de tous les évènements, je m'aperçois que je suis revenu à mon dilemme d'origine: comment regrouper tous les évènement pour les transmettre à la routine d'envoi des notifications?

    Je viens de trouver une solution qui fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //************************préparation du message de notification***************
    void notifAEnvoyer(){ 
      String msg="";
      char buffer[80];
      if(nbr_notif){
        for(i=0;i<nbr_notif;i++){
          sprintf(buffer,"%02d:%02d:%02d %s; ", notif[i].heure, notif[i].minute, notif[i].seconde, notif_msg[notif[i].raison]);
          msg+= buffer;
        }
      }
      nbr_notif=0;
      //Serial.println(msg);
      envoiNotif(msg);
    }
    Peut-être y-a-t'il une solution plus élégante?

    En fait, peut-on se passer d'un String (sans jeu de mots)?

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    Hello,

    Si j'avais dû programmer cela, j'aurais opté pour cette approche avec une structure minimaliste:
    [code]char *notif_msg[TOT_NOTIF] = {
    " Perte du secteur",
    " Le groupe n'a pas démarré",
    " Le groupe a démarré",
    " Le secteur est rétabli",
    " Secteur absent, groupe non opérationnel",
    " Le groupe n'est pas opérationnel",
    " Nombre d'echecs max atteint; nouvel essai dans delai REESSAI"
    };

    enum notif_index {POWER_LOST, NOT_STARTED, STARTED, POWER_BACK, NOT_READY, MAX_TRIED_REACHED};
    juste une correction minime mais qui a son importance, il faut écrire const dans le type (car c'est le type d'un string literal. sur arduino 32 bits le texte va d'ailleurs dans un segment mémoire non modifiable - sur UNO il faudrait utiliser PROGMEM)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const char *notif_msg[TOT_NOTIF] = {
    	" Perte du secteur",
    	" Le groupe n'a pas démarré",
    	" Le groupe a démarré",
    	" Le secteur est rétabli",
    	" Secteur absent, groupe non opérationnel",
    	" Le groupe n'est pas opérationnel",
    	" Nombre d'echecs max atteint; nouvel essai dans delai REESSAI"
    };




    Est-ce que je peux tenter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char buf[80];
    sprintf(buf,"%02d:%02d:%02d %s\n", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    if(envoiNotif(buf)){ ..... }
    Non car buf n'est pas un objet de type String

    si vous voulez dupliquer la mémoire et recréer une String (perte de RAM)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    char buf[80];
    sprintf(buf,"%02d:%02d:%02d %s\n", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    String bufStr = buf;
    if(envoiNotif(bufStr)){ ..... }
    mais le mieux serait d'écrire la fonction envoiNotif sans String

  5. #5
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    @Jay M

    Je dois avouer que
    1) j'oublie régulièrement (même dans des programmes non destinés à l'embarqué) le const
    2) en écrivant ces petits bouts de code, je ne pensais pas "embarqué" mais "manière de faire". J'aurais dû le préciser.

    Merci pour la remarque, qui, comme tu l'écris, à son importance.

  6. #6
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Merci pour ces remarques,
    Comme j'utilise VSCode PlateformIO, le compilateur me fait un "warning" sue ce tableau me disant que ce n'est pas du beau C++. Alors je l'ai réécrit ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //***************************Notifications************************************************
    std::vector<std::string> notif_msg {" Perte du secteur",          //0
                      " Le groupe n'a pas démarré",                   //1
                      " Le groupe a démarré",                         //2
                      " Le secteur est rétabli",                      //3
                      " Secteur absent, groupe non opérationnel",     //4
                      " Le groupe n'est pas opérationnel",            //5
                      " Nombre d'echecs max atteint; nouvel essai dans delai REESSAI",    //6
                      " Micro-coupure détectée"                       //7
                      " Le groupe a été arrêté"};                     //8
    Mais ça ne change rien dans le fonctionnement.

    mais le mieux serait d'écrire la fonction envoiNotif sans String
    Justement, c'est sur ce point que j'aimerais de l'aide car je ne vois pas comment m'y prendre!

  7. #7
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    si vous utilisez std::vector<std::string>, vous créez un vecteur contenant des string C++ (std::string) et pas des String arduino

    votre fonction bool envoiNotif(const String &message) attend une référence à un objet de type String arduino.

    ceci est du C++ propre (même si "old school")

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     const char * messageNotification[] = {
    	" Perte du secteur",
    	" Le groupe n'a pas démarré",
    	" Le groupe a démarré",
    	" Le secteur est rétabli",
    	" Secteur absent, groupe non opérationnel",
    	" Le groupe n'est pas opérationnel",
    	" Nombre d'echecs max atteint; nouvel essai dans delai REESSAI"
    };
    constexpr size_t nbNotifications = sizeof messageNotification / sizeof * messageNotification;
    et j'enlèverai les String de la fonction notification, un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    bool envoiNotif(const char * message) {
      const char * debutBody = "{\"type\": \"note\", \"title\": \"Control secteur\", \"body\": ";
      const char * finBody = "}";
      size_t longeurBody = strlen(debutBody) + strlen(finBody) + strlen(message);
      uint32_t broadcastingTime;
     
      sClient.setInsecure();
      while (!sClient.connect(HOST, 443)) {
        if (millis() - broadcastingTime > TIMEOUT) {
          Serial.println("La connexion a echoue !");
          return false;
        }
      }
     
     
      sClient.printf("POST /v2/pushes HTTP/1.1\r\nHost: %s\r\nAuthorization: Bearer %s\r\nContent-Type: application/json\r\nContent-Length: %zu\r\n\r\n%s%s%s\r\n"\
                     , HOST, CLE,longeurBody, debutBody, message, finBody);
     
      broadcastingTime = millis();
      while (!sClient.available()) {
        delay(1);      //nécessaire au fonctionnement
        if (millis() - broadcastingTime > TIMEOUT) {
          Serial.print("Client Timeout");
          sClient.stop();
          return false;
        }
      }
     
      while (sClient.available()) {               //Réception d'une réponse
        //Serial.printf("Reponse en: %4ld ms\n", millis() - broadcastingTime);
        String line = sClient.readStringUntil('\n');
        if (line.startsWith("HTTP/1.1 200")) {
          sClient.stop();
          lcd.clear();
          return true;
        }
      }
      return false;
    }
    (tapé ici sans vérifier)

  8. #8
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Merci Jay M pour cette solution; cependant ce qui me parait toujours insurmontable, c'est la façon de constituer le message, qui contient plusieurs notifications, à partir d'une boucle. Avec un String, c'est facile mais avec des caractères ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //************************préparation du message de notification***************
    void notifAEnvoyer(){ 
      String msg="";
      char buffer[80];
      if(nbr_notif){
        for(i=0;i<nbr_notif;i++){
          sprintf(buffer,"%02d:%02d:%02d %s; ", notif[i].heure, notif[i].minute, notif[i].seconde, notif_msg[notif[i].raison]);
          msg+= buffer;
        }
      }
      nbr_notif=0;
      //Serial.println(msg);
      envoiNotif(msg);
    }
    A quelle moment cette expression va être utile?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    constexpr size_t nbNotifications = sizeof notif_msg /sizeof *notif_msg;

  9. #9
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    Citation Envoyé par mormic Voir le message
    A quelle moment cette expression va être utile?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    constexpr size_t nbNotifications = sizeof notif_msg /sizeof *notif_msg;
    c'est au cas où vous aillez besoin de savoir combien il y a de notifications. Si ce n'est pas utilisé l'optimisation du code va virer la constante.

    ---

    Ok si vous n'appellez pas directement envoiNotif() avec comme paramètre un membre du tableau notif_msg et que vous êtes plus à l'aise avec les String, vous pouvez les conserver

    sinon au lieu de fabriquer une grosse chaîne vous pourriez faire une boucle avec pleins de Client.printf() mais c'est un peu plus chaud pour calculer la taille du Content

  10. #10
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    Pour n'utiliser que le type char (et char * évidemment), voici une solution, et qui permet aussi de se passer de la variable buffer (80 char de gagnés). C'est du C, mais ça compile (j'ai vérifié, la ligne 34 ne pose aucun problème):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    #include <time.h>
    #include <stdio.h>
    #include <string.h>
     
    char *notif_msg[] = {
    	" Perte du secteur",
    	" Le groupe n'a pas démarré",
    	" Le groupe a démarré",
    	" Le secteur est rétabli",
    	" Secteur absent, groupe non opérationnel",
    	" Le groupe n'est pas opérationnel",
    	" Nombre d'echecs max atteint; nouvel essai dans delai REESSAI"
    };
     
    enum notif_reason {POWER_LOST, NOT_STARTED, STARTED, POWER_BACK, NOT_READY, MAX_TRIED_REACHED};
     
    #define MAX_NOTIF 10
     
    struct notif {
    	int reason;
    	int hh, mm, ss;
    } notif[MAX_NOTIF];
     
    int nbr_notif=0;
     
     
    void SendNotif(char *msg) {
    	puts(msg);
    }
     
     
    void CreateNotifToSend() { 
    	if(nbr_notif) {
    		char notif_to_send[nbr_notif * 80], *s=notif_to_send;
    		for(int i=0; i<nbr_notif; i++) {
    			sprintf(s, "%02d:%02d:%02d %s; ", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    			s+=strlen(s);
    		}
    		nbr_notif=0;
    		SendNotif(notif_to_send);
    	}
    }
     
     
    int main(void) {
    	notif[0].reason=POWER_LOST;
    	notif[0].hh=12;
    	notif[0].mm=8;
    	notif[0].ss=52;
    	notif[1].reason=NOT_STARTED;
    	notif[1].hh=13;
    	notif[1].mm=1;
    	notif[1].ss=24;
    	notif[2].reason=POWER_BACK;
    	notif[2].hh=15;
    	notif[2].mm=28;
    	notif[2].ss=4;
    	nbr_notif=3;
    	CreateNotifToSend();
    }

  11. #11
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    oui, on pourrait utiliser snprintf() pour être sûr de ne pas déborder du tableau au lieu de sprintf()

  12. #12
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    > on pourrait utiliser snprintf() pour être sûr de ne pas déborder

    C'est une bonne idée, mais si les textes de msg_notif[] ne dépassent pas la taille de msg_notif[6], pas de danger.

  13. #13
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    C'est une bonne idée, mais si les textes de msg_notif[] ne dépassent pas la taille de msg_notif[6], pas de danger.
    Oui, juste une habitude pour ne pas laisser aux hackers un risque d'injection

  14. #14
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Voilà, la première partie de mon projet fonctionne grâce à vos conseils avisés et je vous en remercie.
    Ci-après le résultat de nos échanges:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //***************************Notifications************************************************
    const char *notif_msg[]=
                     {" Perte du secteur",                            //0
                      " Le groupe n'a pas démarré",                   //1
                      " Le groupe a démarré",                         //2
                      " Le secteur est rétabli",                      //3
                      " Secteur absent, groupe non opérationnel",     //4
                      " Le groupe n'est pas opérationnel",            //5
                      " Nb échecs max atteint; nouvel essai attendu", //6
                      " Micro-coupure détectée",                      //7
                      " Le groupe a été arrêté"};                     //8
    const int MAX_MSG_LEN = 46;
    constexpr size_t nbNotifications = sizeof notif_msg /sizeof *notif_msg;                                
     
    enum notif_index {POWER_LOST, NOT_STARTED, STARTED, POWER_BACK, DEFAUT, NOT_READY, MAX_TRIED_REACHED, MICRO_CUT,STOPPED};
    struct notif{
      int raison;
      int heure,minute,seconde;
    } notif[NB_NOTIF];
    int noEvent=0;
    Dans le programme principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gestionEvenement(POWER_LOST);     //Perte du secteur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gestionEvenement(STARTED);      //Le groupe a démarré
    Les procédures:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //******************gestion des évènements******************************
    void gestionEvenement(int index){
      notif[noEvent].raison=index;    //nbr_notif commence à zéro
      lectureHeure();
      notif[noEvent].heure=hr;
      notif[noEvent].minute=mn;
      notif[noEvent].seconde=sd;
      noEvent++;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //************************préparation du message de notification***************
    void notifAEnvoyer(void) { 
    	if(noEvent) {
    		char notif_a_envoyer[noEvent * 80], *s=notif_a_envoyer;
    		for(int j=0; j<noEvent; j++){
    			s+=sprintf(s,"%02d:%02d:%02d %s; ", notif[j].heure, notif[j].minute, notif[j].seconde, notif_msg[notif[j].raison]);
        }
        noEvent=0;
    		envoiNotif(notif_a_envoyer);
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    //***********************Envoi notifications****************************************************
    bool envoiNotif(const char *message) {        // Push Envoyer un message
      uint32_t broadcastingTime = millis();
      const char *debutBody = "{\"type\": \"note\", \"title\": \"Control secteur\", \"body\":\"";
      const char *finBody = "\"}";
      size_t lgBody = strlen(debutBody) + strlen(finBody) + strlen(message);
      sClient.setInsecure();                   // en http
      while(!sClient.connect(HOST, 443)) {
        if(millis()-broadcastingTime > TIMEOUT){
          sprintf(buf1,"%s %s",m13,m16);    //****Echec connexion****
          affic_1L(1);
          Serial.println("La connexion a echoue !");
          return false;
        }
      }
      //Serial.println("Push emis");
      sprintf(buf1,"%s %s",m17,m12);  //****message alarme
      sprintf(buf2,"%s",m18);         //****envoye
      affic_2L(1);  //****Envoi message****
      sClient.printf("POST /v2/pushes HTTP/1.1\r\nHost: %s\r\nAuthorization: Bearer %s\r\nContent-Type: application/json\r\nContent-Length: %zu\r\n\r\n%s%s%s\r\n"\
                      , HOST, CLE, lgBody, debutBody,message,finBody); 
      broadcastingTime = millis();
      while(!sClient.available()){
        delay(1);
        if (millis()-broadcastingTime > TIMEOUT) {
          Serial.print("Client Timeout");
          sClient.stop();
          return false;
        }
      }
      while (sClient.available()) {               //Réception d'une réponse
        //Serial.printf("Reponse en: %4ld ms\n", millis() - broadcastingTime);
        String line = sClient.readStringUntil('\n');
        if (line.startsWith("HTTP/1.1 200")) {
          sClient.stop();
          lcd.clear();
          return true;
        }
      }
      return false;
    }
    Résultat:
    Nom : Capture.JPG
Affichages : 115
Taille : 10,7 Ko

    Je n'ai pas utilisé snprintf car j'ai dû mal calculé la taille du buffer nécessaire, ce qui me générait une erreur.
    Je vais maintenant m'attaquer à la partie réseau, sûrement vers de nouvelles interrogations.
    Bien cordialement
    Michel

  15. #15
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Je vais essayer votre solution.
    Auparavant j'avais imaginé une solution comme cela, mais ça ne fonctionne pas! Pourquoi?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //************************préparation du message de notification***************
    void notifAEnvoyer(){
      char buffer1[]={0}, buffer2[]={0};
      int size1=0,size2=0;
      int i=0;
      while(noEvent!=0){    //tant qu'il y a des évènements à traiter
        sprintf(buffer1,"%02d:%02d:%02d %s; ", notif[i].heure, notif[i].minute, notif[i].seconde, notif_msg[notif[i].raison]); 
        size1 = sizeof(buffer1) / sizeof(buffer1[0]);
        i++;
       size2= (size2==0)? 0 : sizeof(buffer2) / sizeof(buffer2[0]);
       for(int j=size2;j<size2 + size1;j++){
         buffer2[j] = buffer1[j-size2];
       } 
      noEvent--;            //Nombre d'évènements
      }
      envoiNotif(buffer2);

  16. #16
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    > mais ça ne fonctionne pas! Pourquoi?

    Car buffer1 et buffer2 n'ont qu'une taille de 1 caractère: char buffer1[]={0}; déclare et définit un espace mémoire de la taille de ce qui se trouve entre les { }. Par exemple, char buf[]={"Hello"}; déclare et définit un espace mémoire de 6 caractères.

  17. #17
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    Il y a moyen de gagner un peu de temps (je ne m'en suis aperçu que maintenant):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void CreateNotifToSend(void) { 
    	if(nbr_notif) {
    		char notif_to_send[nbr_notif * 80], *s=notif_to_send;
    		for(int i=0; i<nbr_notif; i++)
    			s+=sprintf(s, "%02d:%02d:%02d %s; ", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    		nbr_notif=0;
    		SendNotif(notif_to_send);
    	}
    }
    Edit: en utilisant snprintf() comme préconisé par @Jay M
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #define MAX_MSG_LEN		80
     
    void CreateNotifToSend(void) { 
    	if(nbr_notif) {
    		char notif_to_send[nbr_notif * MAX_MSG_LEN], *s=notif_to_send;
    		for(int i=0; i<nbr_notif; i++)
    			s+=snprintf(s, MAX_MSG_LEN, "%02d:%02d:%02d %s; ", notif[i].hh, notif[i].mm, notif[i].ss, notif_msg[notif[i].reason]);
    		nbr_notif=0;
    		SendNotif(notif_to_send);
    	}
    }

  18. #18
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    dans gestionEvenement() il faut tester noEvent par rapport à NB_NOTIF pour être sûr de ne pas déborder du tableau.

    ---
    sinon (pas majeur comme commentaire mais...) à la lecture (au moins pour les anglophones et ceux qui ont l'habitude de coder en anglais)
    se lit "s'il n'y a pas d'évènement alors"

    je suggère d'utiliser "nbEvents" pour "nombre d'événements" (et ce sera cohérent avec l'écriture de nbNotifications)

    et pour enfoncer le clou j'écrirais

    comme ça il n'y a plus de doute sur ce que l'on teste.

    ---
    enfin, indentez votre code, ce sera plus lisible

    ==> bon boulot !

  19. #19
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 790
    Par défaut
    > sinon (pas majeur comme commentaire mais...) à la lecture (au moins pour les anglophones et ceux qui ont l'habitude de coder en anglais)
    se lit "s'il n'y a pas d'évènement alors"

    Entièrement d'accord, ce fut d'ailleurs ma première interprétation à la lecture du code. Et il y a pire dans ce code (je ne critique pas l'algorithme) ! @mormic devrait se décider sur le choix de la langue qu'il emploie pour le nom des variables: soit tout en français, soit tout en anglais ou tout en finnois s'il le souhaite, pas d'importance, mais avoir une variable qui s'appelle debutBody ou finBody Bon, c'est juste une question de bonne pratique, ça ne change rien à la valeur de la solution.

  20. #20
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    mais avoir une variable qui s'appelle debutBody ou finBody Bon, c'est juste une question de bonne pratique, ça ne change rien à la valeur de la solution.
    ça c'est ma faute

    body est le terme consacré pour une requête HTTP donc ...

    mais oui, c'est bien d'être cohérent

    PS/ signé un anglophone parlant à peu près français...

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. encore une question de pointeurs
    Par tallent_e dans le forum Débuter
    Réponses: 10
    Dernier message: 27/04/2012, 09h44
  2. Encore une question sur les ListBox !!
    Par SebRs dans le forum Windows
    Réponses: 3
    Dernier message: 09/05/2006, 15h29
  3. Encore une question, pour retrouver 2 valeur d'une table
    Par danje dans le forum Langage SQL
    Réponses: 5
    Dernier message: 15/09/2005, 00h11
  4. Encore une question licence
    Par Neilos dans le forum C++Builder
    Réponses: 4
    Dernier message: 27/01/2005, 09h48
  5. Encore une question sur malloc
    Par IG88 dans le forum C
    Réponses: 5
    Dernier message: 23/06/2004, 15h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo