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 :

MQTT et Données Horaires


Sujet :

Arduino

  1. #1
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut MQTT et Données Horaires
    Bonjour à tous,

    je reviens vers vous car je n'arrive pas à résoudre mon problème de données horaires reçues via une liaison Thingspeak (channel)

    pour mémoire, j'envoie des données de température et d'humidité extérieures via une liaison MQTT
    puis je renvoie ces données sur un afficheur en local (pourquoi ? tout simplement parce qu'il me parait plus facile de stocker ces données sur Thingspeak qu'en local)

    Channel 1 => Thingspeak => Channel 2 => Affichage local

    Si je reçois correctement les valeurs en local sous cette forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    15:13:46.348 -> -----------------------
    15:13:46.348 -> Message arrivé du topic: channels/2499901/subscribe
    15:13:46.348 -> Message:{"channel_id":2499901,"created_at":"2024-10-19T13:13:42Z","entry_id":49124,"field1":"23.10","field2":"52.60","field3":"94","field4":"25.19","field5":null,"field6":null,"field7":null,"field8":null,"latitude":null,"longitude":null,"elevation":null,"status":null}
    15:13:46.393 -> T° piscine = 25.19
    15:13:46.394 -> PLUS CHAUD
    15:13:46.394 -> T° Exterieur = 23
    15:13:46.394 -> Humidité Exterieure = 52
    15:13:46.394 -> Batterie = 94
    15:13:46.394 -> Mise à jour le  2024-10-19T13:13:42Z <=====================
    15:13:46.394 -> -----------------------
    Vous remarquerez que le champ "Created_at" créé par Thingspeak est lui formaté en heure UTC alors que tout le profil declaré est bien nommé "Europe/Paris"
    si j'effectue un export instantané des données via le fichier json , on remarque que les données sont bien émises sous format local et non UTC

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    99	
    created_at	"2024-10-19T15:13:42+02:00"   <=================
    entry_id	49124
    field1	"23.10"
    field2	"52.60"
    field3	"94"
    field4	"25.19"
    Tout ceci ne sera pas grave , si en plus de cela , l'émission des données ne s'arrêtait pas chaque jour à minuit (?)
    Il semblerait donc que le broker utilisé ici : mqtt3.thingspeak.com modifie la requête "subscribe" sans que je puisse en trouver la raison

    j'ai recherché sur le net toutes les solutions possibles mais je n'ai rien trouvé de concluant

    je sais que m'éloigne un peu du concept Arduino mais comme je n'arrive pas changer l'heure UTC , je me disais qu'il serait peut-être plus simple de "reformater"
    le champ "created_at" en heure locale
    c'est la raison pour laquelle je demande votre aide et vos conseils

    merci mille fois de m'avoir lu
    pascal
    Images attachées Images attachées  

  2. #2
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Salut,

    On trouve ce genre de conversions avec des librairies spécialisées et qui tiennent aussi compte de l'heure d'été/hiver :

    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
    #include <Timezone.h>
    #include <time.h>
     
    // Définir le fuseau horaire pour la France (UTC+1, UTC+2 en été)
    TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Heure d'été
    TimeChangeRule CET = {"CET", Last, Sun, Oct, 3, 60};    // Heure d'hiver
    Timezone France(CEST, CET);
     
    void setup() {
      Serial.begin(115200);
     
      // Exemple de chaîne de caractères contenant l'heure UTC
      char *utcString = "2024-10-19T15:29:37Z";
     
      time_t utc = convertToEpoch(utcString);
      time_t local = France.toLocal(utc);
     
      Serial.print("Heure UTC : ");
      Serial.println(ctime(&utc));
      Serial.print("Heure Locale : ");
      Serial.println(ctime(&local));
    }
     
    void loop() {
     
    }
     
    // Fonction pour convertir une chaîne de caractères en epoch time
    time_t convertToEpoch(const char* utcString) {
      int year, month, day, hour, minute, second;
      sscanf(utcString, "%4d-%2d-%2dT%2d:%2d:%2dZ", &year, &month, &day, &hour, &minute, &second);
     
      tmElements_t tm;
      tm.Year = year - 1970; // Année depuis 1970
      tm.Month = month;
      tm.Day = day;
      tm.Hour = hour;
      tm.Minute = minute;
      tm.Second = second;
     
      return makeTime(tm);
    }
    Heure UTC : Sat Oct 19 15:29:37 2024
    Heure Locale : Sat Oct 19 17:29:37 2024

  3. #3
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Citation Envoyé par cobra38 Voir le message
    Tout ceci ne sera pas grave , si en plus de cela , l'émission des données ne s'arrêtait pas chaque jour à minuit (?)
    Voilà qui est étonnant ! Et il se remet à publier plus tard tout seul ? Je pencherais plutôt vers un problème de connexion.
    Peut-être des pistes ici Résoudre les problèmes de publication MQTT

  4. #4
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    Salut f-leb

    Merci pour les retours

    Voilà qui est étonnant ! Et il se remet à publier plus tard tout seul ? Je pencherais plutôt vers un problème de connexion.
    non, il se bloque lors de la dernière mise à jour UTC de la journée , çà fait quelques mois je tourne avec le projet et je suis obligé de le relancer chaque jour
    je pense que çà viens du broker mais je ne comprends pas
    Ce qui est étrange c'est que seules les données publiées (publish) sont renvoyées , la localisation pourtant inscrite dans le "channel1" d'origine ne l'est pas ce qui tant à penser qu'il aurait un "formatage"
    par ailleurs j'ai testé ceci
    sous l'application Matlab Analysis
    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
     
    % Template MATLAB code for reading data from a private channel, analyzing
    % the data and storing the analyzed data in another channel.
     
    % Prior to running this MATLAB code template, assign the channel variables.
    % Set 'readChannelID' to the channel ID of the channel to read from. Since 
    % this is a private channel, also assign the read API Key to the 'readAPIKey'
    % variable. You can find the read API Key on the right side pane of this page.
     
    % To store the analyzed data, you will need to write it to a channel other
    % than the one you are reading data from. Assign this channel ID to the
    % 'writeChannelID' variable. Also assign the write API Key to the
    % 'writeAPIKey' variable below. You can find the write API Key in the right
    % side pane of this page.
     
    % TODO - Replace the [] with channel ID to read data from:
    readChannelID = [2499901];
    % TODO - Enter the Read API Key between the '' below:
    readAPIKey = 'xxxxxxxxxxxxxxx';
     
    % TODO - Replace the [] with channel ID to write data to:
    writeChannelID = [2499901];
    % TODO - Enter the Write API Key between the '' below:
    writeAPIKey = 'xxxxxxxxxxxxxxxx';
     
    %% Read Data %%
    data = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey);
     
     
    %% Analyze Data %%
    % Add code in this section to analyze data and store the result in the
    % 'analyzedData' variable.
    analyzedData = data;
     
    %% Write Data %%
    tStamp = datetime('now')
    thingSpeakWrite(writeChannelID,'Location',[45,5,200],'WriteKey', writeAPIKey);
    la réponse est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    tStamp = 
     
      datetime
     
       19-Oct-2024 18:18:13
    et j'affiche correctement le champ "created_at" sous la forme : 2024-10-19T18:18:13:+2.00
    mais je perds mes données ....

  5. #5
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Citation Envoyé par cobra38 Voir le message
    non, il se bloque lors de la dernière mise à jour UTC de la journée , çà fait quelques mois je tourne avec le projet et je suis obligé de le relancer chaque jour
    La dernière mise à jour UTC de la journée ? Je n'ai pas compris

    Je pense quand même qu'il y a moyen dans le code de tester la connexion et de la relancer si elle est coupée.

  6. #6
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Je pense aussi à un truc à rajouter dans le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mqttClient.setKeepAlive(60);
    Le client envoie des messages de "maintien en vie" toutes les 15 secondes environ par défaut pour indiquer qu'il est toujours connecté. En augmentant à 60s (voire plus), je me dis que cela réduit la charge sur le broker qui ne se déconnectera plus.

    à voir...

  7. #7
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    Citation Envoyé par f-leb Voir le message
    La dernière mise à jour UTC de la journée ? Je n'ai pas compris

    Je pense quand même qu'il y a moyen dans le code de tester la connexion et de la relancer si elle est coupée.

    En fait à partir du champ "created_at" , je détermine la date de mise à jour avec ce code :
    que j'affiche sur l'écran


    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
    61
     
    void mqttCallback(char *topic, byte *payload, unsigned int length) {
     
      Serial.println();
      Serial.println("-----------------------");
     
      Serial.print("Message arrivé du topic: ");
      Serial.println(topic);
      Serial.print("Message:");
      for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
      }
      JsonDocument doc;
      deserializeJson(doc, (unsigned char*)payload);
        Serial.println();
     
      piscine = doc["field4"];
      Serial.print("T° piscine = ");
      Serial.println(piscine);
     
      float temperatureActuelle = piscine ;
      if (temperatureActuelle > temperaturePrecedente ) {
          // on chauffe
          eteindre();
          digitalWrite(CYD_LED_RED, LOW);
          Serial.println("PLUS CHAUD");
      } else if (temperatureActuelle == temperaturePrecedente ) {
          // on est stable
          eteindre();
          digitalWrite(CYD_LED_GREEN, LOW);
          Serial.println("IDENTIQUE");
      } else {
          // on est plus froid
          eteindre();
          digitalWrite(CYD_LED_BLUE, LOW);
          Serial.println("PLUS FROID");
      }
      temperaturePrecedente = temperatureActuelle;
      //  stocker temperatureActuelle dans les préférences pour la prochaine fois si reboot
      prefs.putFloat(clef, temperatureActuelle); 
     
      TempExt = doc["field1"];
      Serial.print("T° Exterieur = ");
      Serial.println(TempExt,0);
     
      HumExt = doc["field2"];
      Serial.print("Humidité Exterieure = ");
      Serial.println(HumExt,0);
     
      Bat = doc["field3"];
      Serial.print("Batterie = ");
      Serial.println(Bat,0);
     
      const char* (maj) = doc["created_at"];
      //const char* (maj) = doc["updated_at"];
      Serial.print("Mise à jour le  ");
      Serial.println(maj);
      //strcpy(Miseajour, maj);
      strncpy(Miseajour, maj, sizeof(Miseajour));
      Miseajour[sizeof(Miseajour)-1]=0;
      Serial.println("-----------------------");
    ainsi tous les jours je constate la dernière date de mise à jour soit un peu avant 23h59 et les valeurs restent figées
    mais sur ThingSpeak , le channel1 continue à recevoir les données durant toute la nuit (?)

    Edit : j'ai aussi passé le module local en IP statique à voir ...

  8. #8
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    Citation Envoyé par f-leb Voir le message
    Je pense aussi à un truc à rajouter dans le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mqttClient.setKeepAlive(60);
    Le client envoie des messages de "maintien en vie" toutes les 15 secondes environ par défaut pour indiquer qu'il est toujours connecté. En augmentant à 60s (voire plus), je me dis que cela réduit la charge sur le broker qui ne se déconnectera plus.

    à voir...

    Ok je vais l'essai demain ....

  9. #9
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Au pire, tu as des fonctions comme connected() ou state() qui permettent de tester l'état de la connexion, et de tenter une nouvelle connexion si nécessaire.


    Au message #2,
    Il semblerait que pour ESP32, il faut la librairie Timezone_Generic :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #include <Timezone_Generic.h>  // https://github.com/khoih-prog/Timezone_Generic
    Je n'ai pas d'ESP32 sous la main, mais je n'arrive pas à l'installer à cause d'une dépendance

  10. #10
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    salut f-leb

    Il semblerait que pour ESP32, il faut la librairie Timezone_Generic :
    Oui , tu as raison l'autre librairie plante complétement à la compilation , je vais essayer ...

    EDIT : j'ai essayé de mettre cette librairie en lieu et place de "Timezone"
    mais c'est une catastrophe , je n'arrive pas à compiler , il m'indique l'absence d'un fichier Littlefs (?)

  11. #11
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Citation Envoyé par cobra38 Voir le message
    EDIT : j'ai essayé de mettre cette librairie en lieu et place de "Timezone"
    mais c'est une catastrophe , je n'arrive pas à compiler , il m'indique l'absence d'un fichier Littlefs (?)
    Une librairie qui n'est plus mise à jour depuis un moment...

    Mais il semble que la librairie standard time.h sur esp32 suffit :

    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
    #include <time.h>
     
    void setup() {
      Serial.begin(115200);
     
      // Définir manuellement le fuseau horaire (exemple pour la France)
      setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1);
      tzset();
     
      // Exemple de chaîne de caractères UTC
      const char* utcDateTime = "2024-10-20T15:43:58Z";
      Serial.printf("Date et heure UTC : %s\n", utcDateTime);
     
      // Analyser la chaîne de caractères
      struct tm tm;
      strptime(utcDateTime, "%Y-%m-%dT%H:%M:%SZ", &tm);
     
      // Convertir en temps local
      time_t t = mktime(&tm);
      struct tm *localTime = localtime(&t);
     
    Serial.printf("Date et heure locale : %04d-%02d-%02d %02d:%02d:%02d\n",
                    localTime->tm_year + 1900, localTime->tm_mon + 1, localTime->tm_mday,
                    localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
    }
     
    void loop() {
     
    }
    Date et heure UTC : 2024-10-20T15:43:58Z
    Date et heure locale : 2024-10-20 16:43:58

  12. #12
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    Merci f-leb

    Tu vas rire mais çà doit pas être mon bon jour ...
    j'ai du oublier un truc ?
    Images attachées Images attachées  

  13. #13
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Et moi j'ai un décalage d'une heure au lieu de deux...

  14. #14
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    bonjour f-leb

    Un léger progrès ....

    Je me suis dit que l'on faisait fausse route ne voulant interroger le canal "subscribe , en effet
    nous avons un canal intermédiaire appelé "publish" mais ce canal ne permet pas d'intégrer des données du style "timezone" ou autre sur Thingspeak (ou plutôt je n'ai pas trouvé ...)
    en conséquence c'est bien au moment de publier les mesures qu'il faut définir l'heure car sinon le message de retour sera éternellement en format UTC

    c'est ce que j'ai tenté de faire , j'ai ajouté à la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     String dataString = String("field1=" + String(temperature) + "&field2=" + String(humidity) + "&field3=" + String(batteryPercentage) + "&field4=" + String(piscine)+"&timezone=Europe/Paris");
    et le resultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    17:49:01.981 -> -----------------------
    17:49:01.981 -> Message arrivé du topic: channels/2499901/subscribe
    17:49:01.981 -> Message:{"channel_id":2499901,"created_at":"2024-10-21T17:49:01+02:00","entry_id":49352,"field1":"25.70","field2":"45.70","field3":"92","field4":"27.87","field5":null,"field6":null,"field7":null,"field8":null,"latitude":null,"longitude":null,"elevation":null,"status":null}
    17:49:02.024 -> T° piscine = 27.87
    17:49:02.024 -> PLUS CHAUD
    17:49:02.024 -> T° Exterieur = 25
    17:49:02.024 -> Humidité Exterieure = 45
    17:49:02.024 -> Batterie = 92
    17:49:02.024 -> Mise à jour le  2024-10-21T17:49:01+02:00
    17:49:02.024 -> -----------------------
    Ton avis stp ?

  15. #15
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Bonsoir,

    Tu veux dire que le fait d'avoir précisé le timezone=Europe/Paris au moment de publier te permet de récupérer le champ "created_at" à l'heure locale ?

    Pourquoi tu parles de "léger progrès" ? C'est bien ce que tu cherches à faire depuis le début, non ?

  16. #16
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut

    Tu veux dire que le fait d'avoir précisé le timezone=Europe/Paris au moment de publier te permet de récupérer le champ "created_at" à l'heure locale ?

    Pourquoi tu parles de "léger progrès" ? C'est bien ce que tu cherches à faire depuis le début, non ?
    Oui c'est juste mais je reste prudent , je dois vérifier le problème de coupure (?) à minuit
    mais je ne suis pas mécontent d'avoir enfin trouvé quelque chose, je commençait à désespérer ...

  17. #17
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 268
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 268
    Billets dans le blog
    48
    Par défaut
    Tu viens quand même de résoudre un sacré problème, et je retiens ta solution pour plus tard peut-être. C'est bien d'avoir trouvé l'astuce du timezone au moment de publier, mais où as-tu trouvé cette astuce ? Je ne trouve rien à ce sujet dans la doc...


    Le problème de coupure, c'est un autre problème... Surtout qu'après minuit, tu peux toujours continuer à publier sur thingspeak si j'ai bien compris. C'est juste quand tu t'abonnes au broker thingspeak pour les récupérer qu'il te coupe avant minuit. Là, je sèche... mais je reviens si j'ai une piste...

  18. #18
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    Tu viens quand même de résoudre un sacré problème, et je retiens ta solution pour plus tard peut-être. C'est bien d'avoir trouvé l'astuce du timezone au moment de publier, mais où as-tu trouvé cette astuce ? Je ne trouve rien à ce sujet dans la doc...
    je ne l'ai fait que par déduction car j'ai tout tenté coté :canal "subscribe" , le canal2 acceptait toutes les modifications comme par ex : ...
    "channels/xxxxxxx/subscribe/?timezone=Europe/Paris";
    ou
    "channels/xxxxxxx/?timezone=Europe/Paris/subscribe"; etc ...

    mais rien ne changeait ...je me suis dit que le canal1 servait de publication seulement, les modifications faites sur Thingspeak comme la location par ex je ne la voyait pas sur la chaîne de canal2 (subscribe ) en retour
    ( j'avais rentré des infos de location comme la latitude et la longitude pensant qu'il en déduirait le lieu mais rien !)
    donc en conclusion , le canal2 ( subscribe) me renvoyait ce que j'avais émis sur le canal1 (publish) il fallait donc lui envoyer aussi le "timezone"
    si je voulais avoir l'heure excte et non UTC (que Thingspeak doit mettre par défaut)
    CQFD....
    en ce qui concerne la doc , je n'ai rien trouvé sur Thingspeak m'expliquant ceci et c'est très dommage ...

    Le problème de coupure, c'est un autre problème... Surtout qu'après minuit, tu peux toujours continuer à publier sur thingspeak si j'ai bien compris. C'est juste quand tu t'abonnes au broker thingspeak pour les récupérer qu'il te coupe avant minuit. Là, je sèche... mais je reviens si j'ai une piste...
    merci encore, je te dirais demain si le problème persiste ....

    pascal

  19. #19
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 053
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 053
    Par défaut
    Bonjour à tous ,

    Je reviens vers vous car mon souci de coupure à 2h00 pour mémoire (et ceci tous les jours) trouve peut-être sa solution dans le fait qu'il ne s'agit pas d'un arrêt journalier du serveur Thingspeak mais semble-t-il ..de ma box
    en effet j'ai pu constater une coupure wifi tous les jours à 2h00 du matin sans raison apparente , mon FAI interrogé sur le sujet cherche ....(?)

    pour contourner ce problème, j'aurais besoin de votre aide pour m'orienter sur un choix
    car dans le croquis , le test Wifi ne se fait que dans le setup , l'absence de wifi entraine donc forcement une relance de l'application ( ce qui est fait tous les matins)
    il faut donc permettre :
    - soit de surveiller la présence du Wifi en permanence et de le relancer automatiquement
    - soit de faire une mise en veille ( la nuit par ex ) et de relancer l'application après une durée de sommeil programmée

    A toute fin utile , je mets le croquis le plus à jour en copie

    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
     
    /*
      ESP32-WROOM-DA
      V20241105a
    */
     
     
    #include <SPI.h>
    #include <PubSubClient.h>
    #include <ArduinoJson.h>      // https://github.com/bblanchon/ArduinoJson
    #include <WiFi.h>
    #include "config.h"
    #include <TFT_eSPI.h>     // by Bodmer ver 2.5.34
    #include <NTPClient.h>    // by F.Weinberg ver 3.2.1
    #include <HTTPClient.h>   // by A.McEwen ver 2.2.0
    #include <Preferences.h>
     
    Preferences prefs;
     
    #define CYD_LED_BLUE 17
    #define CYD_LED_RED 4
    #define CYD_LED_GREEN 16
     
    void WIFISetUp(void);
    void mqttCallback(char *topic, byte *payload, unsigned int length);
     
    ///////veuillez entrer vos données sensibles dans l'onglet Config.h
    char ssid[] = WLAN_SSID;  // le SSID (nom) de votre réseau
    char password[] = WLAN_PASSWD;  // votre mot de passe réseau 
     
    const char* metar = "https://aviationweather.gov/api/data/metar?ids=LFLL&format=json"; // LFLL = Code OACI de Lyon
    WiFiUDP ntpUDP;
    NTPClient timeClient(ntpUDP);
    int wifiTimeOutCounter = 0;
    #define TIMEOFFSET 3600 * 2  // pas d'heure d'été mais décalage de 2h par rapport à l'UTC
     
    // definition for the screen
    #define MAX_Y 240
    #define MAX_X 320
    TFT_eSPI tft = TFT_eSPI();
    TFT_eSprite spr = TFT_eSprite(&tft);  // Déclarer l'objet Sprite "spr" avec un pointeur sur l'objet "tft".
    uint16_t palette[16] = { TFT_GREENYELLOW, TFT_NAVY, TFT_ORANGE, TFT_DARKCYAN, TFT_MAROON,
                             TFT_PURPLE, TFT_PINK, TFT_LIGHTGREY, TFT_YELLOW, TFT_BLUE,
                             TFT_GREEN, TFT_CYAN, TFT_RED, TFT_MAGENTA, TFT_BLUE, TFT_WHITE };
     
     
    WiFiClient wifiClient;
    PubSubClient mqttClient(wifiClient);
     
    // update parameter for the weather data
    unsigned long previousMillis = 0;
    #define INTERVAL 60000 * 30   // 5 min
     
     
    // init parameter for iniversum simulation
    int const n = 5, m = 200;
    float const r = 0.1;
    float x = 0, v = 0, t = 0;
     
    const char mqttBroker[] = "mqtt3.thingspeak.com";
    int mqttPort = 1883;
    const char mqttTopic[] = "channels/2499901/subscribe";
     
    const char mqttClientID[] = MQTT_CLIENT;
    const char mqttUsername[] = MQTT_USER;
    const char mqttPassword[] = MQTT_PASSWORD;
     
     
    byte omm = 99, oss = 99;
    byte xcolon = 0, xsecs = 0;
    unsigned int colour = 0;
     
    // set global variables for the weather informations
    int temperature = 0;  // °C
    int dew_point = 0;    // °C
    int wind_speed_knots = 0;
    int pressure = 0;           // hPa
    int relative_humidity = 0;  // %
    int wind_speed_kmh = 0;
    int data_age_min = 0;
     
    unsigned long epochTime = 0;
    unsigned long obsTime = 0;
     
    const char* clef = "temperaturePrecedente";
    const float valeurDefaut = -100.0;  
    float temperaturePrecedente = -1000;
     
    float piscine = 0;
    int TempExt = 0;
    int HumExt = 0;
    int Bat = 0;
    char Miseajour[20]; 
     
    //*********************************************
    //  SETUP
    //*********************************************
    void setup() {
     
      Serial.begin(115200);
      while (!Serial) delay(10);
      Serial.println("Booting...");
     
      pinMode(CYD_LED_RED, OUTPUT);
      pinMode(CYD_LED_GREEN, OUTPUT);
      pinMode(CYD_LED_BLUE, OUTPUT);
     
      eteindre() ;
      prefs.begin("Memoire", false);
      // Vérifier si la clé existe
      if (prefs.getBytesLength(clef) == 0) {
        Serial.println("La clef n'existe pas. Création avec la valeur par défaut.");
        prefs.putFloat(clef, valeurDefaut);
      }
      temperaturePrecedente = prefs.getFloat(clef, valeurDefaut); 
      Serial.print("temperature Precedente: ");  Serial.println(temperaturePrecedente);
     
     
      // print debugg infos an serial
      uint32_t chipId = 0;
      for (int i = 0; i < 17; i = i + 8) chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
      Serial.printf("ESP32 Chip model = %s Rev %d\n", ESP.getChipModel(), ESP.getChipRevision());
      Serial.printf("This chip has %d cores\n", ESP.getChipCores());
      Serial.print("Chip ID: ");
      Serial.println(chipId);
      Serial.print("Connecting to ");
      Serial.print(ssid);
      Serial.print(" ");
     
       // connect to router
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
        wifiTimeOutCounter++;
        if (wifiTimeOutCounter >= 60) ESP.restart();
      }
     
      Serial.println("");
      Serial.println("WiFi connected.");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      uint8_t mac[6];
      WiFi.macAddress(mac);
      Serial.print("MAC address: ");
      for (int i = 0; i < 6; i++) {
        Serial.print(mac[i], HEX);
        if (i < 5) Serial.print(":");
      }
      Serial.println("");
      // Convert MAC address to unique identifier (UID)
      uint64_t uid = ((uint64_t)mac[0] << 40) | ((uint64_t)mac[1] << 32) | ((uint64_t)mac[2] << 24) | ((uint64_t)mac[3] << 16) | ((uint64_t)mac[4] << 8) | ((uint64_t)mac[5]);
      Serial.print("MAC unique identifier: ");
      Serial.println(uid);
      // init time system
      timeClient.begin();
      timeClient.setTimeOffset(TIMEOFFSET);
      // Init ttf
      tft.init();
      spr.setColorDepth(4);
      spr.createSprite(MAX_X, MAX_Y);
      tft.setRotation(1);
      // load first data to start with
      timeClient.update();
      weatherData();
     
      mqttClient.setServer(mqttBroker, mqttPort);
      mqttClient.setCallback(mqttCallback);
      mqttClient.setBufferSize(1024);  // <====
     
      while (!mqttClient.connected()) {
        Serial.print("Tentative de connexion au MQTT broker: ");
        Serial.println(mqttBroker);
        if (mqttClient.connect(mqttClientID, mqttUsername, mqttPassword)) {
          Serial.println("Vous êtes connecté au MQTT broker!");
          if (mqttClient.subscribe(mqttTopic)) {
            Serial.print("S'abonner au topic ");
            Serial.print(mqttTopic);
            Serial.println(": succès");
            Serial.println("En attente de messages ...");
     
          } else {
            Serial.println("L'abonnement au Topic a échoué");
          }
        } else {
          Serial.print("Failed, state=");
          Serial.print(mqttClient.state());
          Serial.println(" Nouvel essai en 5s...");
          delay(5000);
        }
      }
     
    }
     
    //*********************************************
    //  LOOP
    //********************************************* 
    void loop() {
      spr.fillSprite(0);  // init sprite 
     
      // dessiner une simulation d'univers dans un sprite vide
     
       for (int i = 0; i <= n; i++)
        for (int j = 0; j <= m; j++) {
          float u = sin(i + v) + sin(r * i + x);
          v = cos(i + v) + cos(r * i + x);
          x = u + t;
          int px = u * MAX_X / 4 + MAX_X / 2;
          int py = v * MAX_Y / 4 + MAX_Y / 2;
          uint16_t color = (i * 255) % 16;
          for (int dx = 0; dx <= 1; ++dx)
            for (int dy = 0; dy <= 1; ++dy)
              spr.drawPixel(px + dx, py + dy, color);
        }
     
      t += 0.01;
     
      // update weather information
     
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > INTERVAL) {
        previousMillis = currentMillis;
        weatherData();
      }	
     
      // Print everything
      spr.setTextColor(3);
      timeClient.update();
      String strtmp = timeClient.getFormattedTime() + "  " + getFormattedDate();
      spr.drawLine(0, 25, 319, 25,TFT_LIGHTGREY);
      spr.drawLine(0, 195, 319, 195,TFT_LIGHTGREY);    
      if (timeClient.isTimeSet()) {
        spr.drawString(timeClient.getFormattedTime(), 5, 0, 4);
        spr.drawString(getFormattedDate(), 185, 0, 4);
        spr.setTextColor(8); // 3 =
        spr.drawString("C",280,60,4);
        spr.drawString(String(piscine,2), 35, 70, 8);
     
        spr.setTextColor(3);
        String outputString ="";
        outputString = "T Ext.: "+String(TempExt) + "c    " + "H Ext.: "+String(HumExt) + "%          " +"Batterie : "+ String(Bat) + "%";
        spr.drawString(outputString, 0, 200, 2);
     
        spr.setTextColor(6); 
        outputString ="";
        String value = Miseajour;
        outputString = "Maj le : "+ value;
        spr.drawString(outputString, 0, 220, 2);
        spr.pushSprite(0, 0);
     
      }
      mqttClient.loop(); 
    }    
     
     
    //****se connecter au serveur météorologique et obtenir des données **************** 
    void weatherData() {
      if (WiFi.status() == WL_CONNECTED) {
     
        Serial.println();
        Serial.println("-----------------------");
     
        HTTPClient http;
        http.begin(metar);
        Serial.print("Envoi d'une requête HTTP à: ");
        Serial.println(metar);
        int httpCode = http.GET();            // Envoyer une requête HTTP GET
        if (httpCode > 0) {                   // Cvérifier si la demande a abouti
          DynamicJsonDocument metardoc(2048); // Créer un document JSON (ajuster la taille en conséquence)
          String payload = http.getString();  // Récupérer la réponse du site web
          Serial.print("Réponse reçue: ");
          Serial.println(payload);                                     // Sortie des données METAR vers la console série
          DeserializationError error = deserializeJson(metardoc, payload);  // Analyse des données JSON
          if (!error) {
            // commencer à extraire les données météorologiques et à mettre à jour les variables globales
            temperature =metardoc[0]["temp"];
            dew_point = metardoc[0]["dewp"];
            wind_speed_knots =metardoc[0]["wspd"];
            pressure = metardoc[0]["altim"];
            obsTime = metardoc[0]["obsTime"];
            relative_humidity = 100 * expf(17.625f * dew_point / (243.04f + dew_point)) / expf(17.625f * temperature / (243.04f + temperature));
            wind_speed_kmh = wind_speed_knots * 1.852f;
            epochTime = timeClient.getEpochTime() - TIMEOFFSET;
            data_age_min = (epochTime - obsTime) / 60;
            // montrent les données les plus importantes sur les séries
            /*
            Serial.print("Temperature: ");
            Serial.print(temperature, 0);
            Serial.println();
            Serial.print("Relative Humidity: ");
            Serial.print(relative_humidity, 0);
            Serial.println("%");
            Serial.print("Wind Speed: ");
            Serial.print(wind_speed_kmh, 0);
            Serial.println("km/h");
            Serial.print("Pressure: ");
            Serial.print(pressure, 0);
            Serial.println("hPa");
            Serial.print("Data age: ");
            Serial.print((epochTime - obsTime) / 60);
            Serial.println("min");
            */
          } else Serial.println("Erreur d'analyse des données JSON");
        } else Serial.println("Erreur dans la récupération des données METAR");
        http.end();
         }
     
      Serial.println("-----------------------");  
    }
     
     
    //********this is missing in the library ******************************************************* 
     
    String getFormattedDate() {
    #define LEAP_YEAR(Y) ((Y > 0) && !(Y % 4) && ((Y % 100) || !(Y % 400)))
      unsigned long rawTime = timeClient.getEpochTime() / 86400L;
      unsigned long days = 0, year = 1970;
      uint8_t month;
      static const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
      while ((days += (LEAP_YEAR(year) ? 366 : 365)) <= rawTime) year++;
      rawTime -= days - (LEAP_YEAR(year) ? 366 : 365);
      for (month = 0; month < 12; month++) {
        uint8_t monthLength;
        if (month == 1) monthLength = LEAP_YEAR(year) ? 29 : 28;
        else monthLength = monthDays[month];
        if (rawTime < monthLength) break;
        rawTime -= monthLength;
      }
      String monthStr = ++month < 10 ? "0" + String(month) : String(month);
      String dayStr = ++rawTime < 10 ? "0" + String(rawTime) : String(rawTime);
      return String(dayStr) + "-" + monthStr + "-" + year;
    }
     
     
    //*************************************************************** 
    void mqttCallback(char *topic, byte *payload, unsigned int length) {
     
      Serial.println();
      Serial.println("-----------------------");
     
      Serial.print("Message arrivé du topic: ");
      Serial.println(topic);
      Serial.print("Message:");
      for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
      }
      JsonDocument doc;
      deserializeJson(doc, (unsigned char*)payload);
        Serial.println();
     
      piscine = doc["field4"];
      Serial.print("T° piscine = ");
      Serial.println(piscine);
     
      float temperatureActuelle = piscine ;
      if (temperatureActuelle > temperaturePrecedente ) {
          // on chauffe
          eteindre();
          digitalWrite(CYD_LED_RED, LOW);
          Serial.println("PLUS CHAUD");
      } else if (temperatureActuelle == temperaturePrecedente ) {
          // on est stable
          eteindre();
          digitalWrite(CYD_LED_GREEN, LOW);
          Serial.println("IDENTIQUE");
      } else {
          // on est plus froid
          eteindre();
          digitalWrite(CYD_LED_BLUE, LOW);
          Serial.println("PLUS FROID");
      }
      temperaturePrecedente = temperatureActuelle;
      //  stocker temperatureActuelle dans les préférences pour la prochaine fois si reboot
      prefs.putFloat(clef, temperatureActuelle); 
     
      TempExt = doc["field1"];
      Serial.print("T° Exterieur = ");
      Serial.println(TempExt,0);
     
      HumExt = doc["field2"];
      Serial.print("Humidité Exterieure = ");
      Serial.println(HumExt,0);
     
      Bat = doc["field3"];
      Serial.print("Batterie = ");
      Serial.println(Bat,0);
     
      const char* (maj) = doc["created_at"];
      //const char* (maj) = doc["updated_at"];
      Serial.print("Mise à jour le  ");
      Serial.println(maj);
      //strcpy(Miseajour, maj);
      strncpy(Miseajour, maj, sizeof(Miseajour));
      Miseajour[sizeof(Miseajour)-1]=0;
      Serial.println("-----------------------");
     
    } 
     
    void eteindre() {
      digitalWrite(CYD_LED_RED, HIGH);
      digitalWrite(CYD_LED_GREEN, HIGH);
      digitalWrite(CYD_LED_BLUE, HIGH);
    }

    merci par avance pour vos precieux conseils

    pascal

  20. #20
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 933
    Par défaut
    sur ESP32 j'utilise un code avec les callback du système pour suivre l'état de la connexion

    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
    #include <WiFi.h>
     
    const char *wifiSSID = "*******";
    const char *wifiPassword = "******";
    bool wifiConnected = false;
     
    void onWiFiConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
      Serial.println("...Network connection established");
    }
     
    void onWiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
      Serial.print("Obtained IP address = ");
      Serial.println(WiFi.localIP());
      wifiConnected = true;
    }
     
    void onWiFiDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
      wifiConnected = false;
      Serial.print("Network disconnected (reason: ");
      Serial.println(info.wifi_sta_disconnected.reason);
      Serial.println(")\nAttempting to reconnect.");
      WiFi.begin(wifiSSID, wifiPassword);
    }
     
    void setup() {
      Serial.begin(115200);
      Serial.println("Connecting to WiFi network");
      WiFi.onEvent(onWiFiConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED);
      WiFi.onEvent(onWiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
      WiFi.onEvent(onWiFiDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
      WiFi.begin(wifiSSID, wifiPassword);
    }
     
    void loop() {
      if (wifiConnected) {
        // code requiring WiFi connection
        // ...
      }
      // code that does not require WiFi
    }

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

Discussions similaires

  1. [VB.NET] Import donnes d'excel : chiffres et lettres
    Par JohnGT dans le forum Windows Forms
    Réponses: 5
    Dernier message: 19/10/2004, 18h53
  2. est il possible de faire un trie sur un paramètre donné
    Par chtiboss dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 17/03/2004, 11h51
  3. CComboBox::setCurSel ne donne rien
    Par jul54 dans le forum MFC
    Réponses: 5
    Dernier message: 11/02/2004, 13h55
  4. TreeView -> ajouter un child à un noeud donné
    Par fake dans le forum Composants VCL
    Réponses: 6
    Dernier message: 26/03/2003, 17h14
  5. connexion base de donné
    Par saidi dans le forum MFC
    Réponses: 3
    Dernier message: 07/08/2002, 22h22

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