Go Down

Topic: Lecture compteur électrique (Read 406 times) previous topic - next topic

prophet_master

bonjour, je désire lire et transformer les données du compteur électrique chez moi... alors pour le lire et reçevoir les infos pas de souci j'ai réussi maintenant j'aimerais trier les données dans des variables et les envoyers à mon serveur domotique.

Code: [Select]
F.F(00)                Error code (always first in the list)
0.0(            2359)        Customer identification (16 character string) (Readout)
C.1.0(38451126)            ID1.1 Meter ID (8 characters)
C.1.1(        )            ID1.4 Manufacturing ID (8 characters)
1.8.1(000011.096*kWh)        Active energy import rate 1 (X = 1…6)
1.8.2(000019.999*kWh)        Active energy import rate 2 (X = 1…6)
2.8.1(000000.000*kWh)        Active energy export rate 1 (X = 1…6)
2.8.2(000000.000*kWh)        Active energy export rate 2 (X = 1…6)
5.8.1(000000.000*kvarh)        ?
5.8.2(000000.000*kvarh)        ?
6.8.1(000000.000*kvarh)        ?
6.8.2(000000.000*kvarh)        ?
7.8.1(000000.000*kvarh)        ?
7.8.2(000000.000*kvarh)        ?
8.8.1(000007.226*kvarh)        kvarh rate 1
8.8.2(000005.419*kvarh)        kvarh rate 2
1.8.0(000031.096*kWh)        Total active energy import
2.8.0(000000.000*kWh)        ?
5.8.0(000000.000*kvarh)        ?
6.8.0(000000.000*kvarh)        ?
7.8.0(000000.000*kvarh)        ?
8.8.0(000012.645*kvarh)        for the Reactive Energy Q4 Billing Totals
C.7.0(0006)            Power Fail Count
32.7(236*V)            VRMS Phase L1 (L12 in ZFFxxx meters)
52.7(235*V)            VRMS Phase L2 (not for 3-wire ZFFxxx meters)
72.7(237*V)            VRMS Phase L3 (L32 in ZFFxxx meters)
31.7(00.139*A)            IRMS Phase L1
51.7(001.60*A)            IRMS Phase L2 (not for 3-wire ZFFxxx meters)
71.7(00.457*A)            IRMS Phase L3
33.7(0.16)            Power factor phase L1 (4-wire ZMF1xx meters only)
53.7(0.90)            Power factor phase L2 (4-wire ZMF1xx meters only)
73.7(0.65)            Power factor phase L3 (4-wire ZMF1xx meters only)
13.7(0.83)            Power Factor Phase Summation
82.8.1(0001)            Terminal cover removal counter
82.8.2(0000)            DC Field Count
0.2.0(M29)            Firmware Version
C.5.0(0401)            Status Flag (Readout: "Miniflex /E350s2 status")
!                End of text,
e                Checksum


voici ce que j'ai en retour du compteur sans les descriptions à droite, ce que je veux c'est avoir le premier index qui donne le code de valeur ex : 1.8.1 et lui mètre la valeur 11.096 l'unité ne m'importe pas mais c'est un plus.

Je sais pas la meilleur magnière de procéder.

Code: [Select]
void setup(){
  char instring[] = {"F.F(00)\r\n0.0(            2359)\r\nC.1.0(38451126)\r\nC.1.1(        )\r\n1.8.1(000011.096*kWh)\r\n1.8.2(000019.999*kWh)\r\n2.8.1(000000.000*kWh)\r\n2.8.2(000000.000*kWh)\r\n5.8.1(000000.000*kvarh)\r\n5.8.2(000000.000*kvarh)\r\n6.8.1(000000.000*kvarh)\r\n6.8.2(000000.000*kvarh)\r\n7.8.1(000000.000*kvarh)\r\n7.8.2(000000.000*kvarh)\r\n8.8.1(000007.226*kvarh)\r\n8.8.2(000005.419*kvarh)\r\n1.8.0(000031.096*kWh)\r\n2.8.0(000000.000*kWh)\r\n5.8.0(000000.000*kvarh)\r\n6.8.0(000000.000*kvarh)\r\n7.8.0(000000.000*kvarh)\r\n8.8.0(000012.645*kvarh)\r\nC.7.0(0006)\r\n32.7(236*V)\r\n52.7(235*V)\r\n72.7(237*V)\r\n31.7(00.139*A)\r\n51.7(001.60*A)\r\n71.7(00.457*A)\r\n33.7(0.16)\r\n53.7(0.90)\r\n73.7(0.65)\r\n13.7(0.83)\r\n82.8.1(0001)\r\n82.8.2(0000)\r\n0.2.0(M29)\r\nC.5.0(0401)\r\n!\r\ne"};
                   
  char delimiters[] = "(*)\r\n";
  char* valPosition;

  valPosition = strtok(instring, delimiters);
 
  Serial.begin(115200);
 
  while(valPosition != NULL){

    String test = valPosition;

    if( test.length() > 0 ){
      Serial.println(test);
    }
   
    //Here we pass in a NULL value, which tells strtok to continue working with the previous string
    valPosition = strtok(NULL, delimiters);
  }
 
}

void loop() {
 
}


ce petit code simple me sort ceci :

Code: [Select]
F.F
00
0.0
            2359
C.1.0
38451126
C.1.1
       
1.8.1
000011.096
kWh
1.8.2
000019.999
kWh
2.8.1
000000.000
kWh
2.8.2
000000.000
kWh
5.8.1
000000.000
kvarh
5.8.2
000000.000
kvarh
6.8.1
000000.000
kvarh
6.8.2
000000.000
kvarh
7.8.1
000000.000
kvarh
7.8.2
000000.000
kvarh
8.8.1
000007.226
kvarh
8.8.2
000005.419
kvarh
1.8.0
000031.096
kWh
2.8.0
000000.000
kWh
5.8.0
000000.000
kvarh
6.8.0
000000.000
kvarh
7.8.0
000000.000
kvarh
8.8.0
000012.645
kvarh
C.7.0
0006
32.7
236
V
52.7
235
V
72.7
237
V
31.7
00.139
A
51.7
001.60
A
71.7
00.457
A
33.7
0.16
53.7
0.90
73.7
0.65
13.7
0.83
82.8.1
0001
82.8.2
0000
0.2.0
M29
C.5.0
0401
!
e

J-M-L

#1
Jul 08, 2018, 04:18 pm Last Edit: Jul 09, 2018, 10:47 am by J-M-L
Il semblerait qu'à part au début d'une trame la grammaire de chaque ligne soit

<etiquette>(<valeur>[*<unite>])\r\n

Avec la partie unité facultative (si vous trouvez l'étoile alors elle y est)

Faut parser avec cela
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

prophet_master

merci de la réponse, mais je suis pas un expert en programmation et je ne sait pas comment y arriver :-(

J-M-L

#3
Jul 09, 2018, 10:42 am Last Edit: Jul 09, 2018, 10:46 am by J-M-L
On remarque que le format de chaque ligne est <etiquette>(<valeur>[*<unite>])\r\n

La seule subtilité est la présence ou non de l'étoile qui introduit une unité, les autres éléments en bleus sont obligatoires dans cet ordre pour une ligne bien formée

Comme le format est répétitif, il suffit de faire une boucle sur chaque ligne, on va chercher les pointeurs sur les différents éléments et on vérifie un minimum de cohérence, par exemple que les parenthèses sont là, que si on trouve une étoile, pour qu'elle soit valable il faut qu'elle soit avant la parenthèse fermante de cette ligne etc...

Enfin on remarque que la fin d'une trame est notée par "!\r\ne" donc on commencera par tester si on en est là, si oui on a fini l'analyse, sinon on a une ligne à analyser.

Lors de l'analyse, on fait quelques tests pour s'assurer que l'on ne sature pas nos buffers de lecture des différents éléments d'une ligne.

par exemple ce bout de code
Code: [Select]
char message[] = "F.F(00)\r\n0.0(            2359)\r\nC.1.0(38451126)\r\nC.1.1(        )\r\n1.8.1(000011.096*kWh)\r\n1.8.2(000019.999*kWh)\r\n2.8.1(000000.000*kWh)\r\n2.8.2(000000.000*kWh)\r\n5.8.1(000000.000*kvarh)\r\n5.8.2(000000.000*kvarh)\r\n6.8.1(000000.000*kvarh)\r\n6.8.2(000000.000*kvarh)\r\n7.8.1(000000.000*kvarh)\r\n7.8.2(000000.000*kvarh)\r\n8.8.1(000007.226*kvarh)\r\n8.8.2(000005.419*kvarh)\r\n1.8.0(000031.096*kWh)\r\n2.8.0(000000.000*kWh)\r\n5.8.0(000000.000*kvarh)\r\n6.8.0(000000.000*kvarh)\r\n7.8.0(000000.000*kvarh)\r\n8.8.0(000012.645*kvarh)\r\nC.7.0(0006)\r\n32.7(236*V)\r\n52.7(235*V)\r\n72.7(237*V)\r\n31.7(00.139*A)\r\n51.7(001.60*A)\r\n71.7(00.457*A)\r\n33.7(0.16)\r\n53.7(0.90)\r\n73.7(0.65)\r\n13.7(0.83)\r\n82.8.1(0001)\r\n82.8.2(0000)\r\n0.2.0(M29)\r\nC.5.0(0401)\r\n!\r\ne";

// On remarque que le format est <etiquette>(<valeur>[*<unite>])\r\n

const byte maxData = 20;
char etiquette[maxData + 1];
char valeur[maxData + 1];
char unite[maxData + 1];


enum : byte {ANALYSE_OK, ERREUR_FORMAT, ERREUR_DONNEE_TROP_LONGUE} erreur;

void setup() {
  char * debutPtr = message;
  erreur = ANALYSE_OK;
  size_t nbCaracteres;

  Serial.begin(115200);

  Serial.println(F("\n------------------------------------"));
  Serial.println(F("        ANALYSE DU FLUX"));
  Serial.println(F("------------------------------------"));
  Serial.println(message);
  Serial.println(F("------------------------------------\n"));


  while (*debutPtr) {

    if (strcmp(debutPtr, "!\r\ne") == 0) break; // FIN DU MESSAGE

    // -------------------------------------------------------
    // ON TROUVE LES SEPARATEURS ET ON FAIT QUELQUES VERIFS
    // -------------------------------------------------------

    char * parentheseOuvrante = strchr (debutPtr, '(');
    char * parentheseFermante = strchr (debutPtr, ')');
    char * etoile = strchr (debutPtr, '*');
    char * finDeLigne = strchr (debutPtr, '\n');

    if ((parentheseOuvrante == NULL) || (parentheseFermante == NULL) || (finDeLigne == NULL) || (parentheseOuvrante > parentheseFermante)) {
      erreur = ERREUR_FORMAT;
      break;
    }

    nbCaracteres = parentheseOuvrante - debutPtr;

    if (nbCaracteres > maxData) {
      erreur = ERREUR_DONNEE_TROP_LONGUE;
      break;
    }

    strncpy(etiquette, debutPtr, nbCaracteres);
    etiquette[nbCaracteres] = '\0';

    // -------------------------------------------------------
    // ON SAUTE LA PARENTHESE OUVRANTE, ON LIT LES DONNEES
    // -------------------------------------------------------

    debutPtr = parentheseOuvrante + 1;

    // LES DONNES SE TERMINENT SOIT PAR UNE PARENTHESE FERMANTE, SOIT PAR UNE *

    if ((etoile == NULL) || (etoile > finDeLigne)) {
      // On est dans le cas où il n'y as pas d'unités
      nbCaracteres = parentheseFermante - debutPtr;

      if (nbCaracteres > maxData) {
        erreur = ERREUR_DONNEE_TROP_LONGUE;
        break;
      }

      strncpy(valeur, debutPtr, nbCaracteres);
      valeur[nbCaracteres] = '\0';

      unite[0] = '\0'; // pas d'unités

    } else {
      // il y a des unités
      nbCaracteres = etoile - debutPtr;

      if (nbCaracteres > maxData) {
        erreur = ERREUR_DONNEE_TROP_LONGUE;
        break;
      }

      strncpy(valeur, debutPtr, nbCaracteres);
      valeur[nbCaracteres] = '\0';

      // on saute l'étoile
      debutPtr = etoile + 1;

      nbCaracteres = parentheseFermante - debutPtr;

      if (nbCaracteres > maxData) {
        erreur = ERREUR_DONNEE_TROP_LONGUE;
        break;
      }

      strncpy(unite, debutPtr, nbCaracteres);
      unite[nbCaracteres] = '\0';
    }

    // On passe au champs suivant
    debutPtr = finDeLigne + 1;

    Serial.print(F("ETIQUETTE = \"")); Serial.print(etiquette);
    Serial.print(F("\", VALEUR = \"")); Serial.print(valeur);
    if (unite[0] != '\0') { // si on avait des unités
      Serial.print(F("\", UNITE = \"")); Serial.print(unite);
    }
    Serial.println(F("\""));
  } // FIN DU WHILE


  if (erreur != ANALYSE_OK) {
    Serial.print(F("CODE ERREUR D'ANALYSE = "));
    Serial.println(erreur);
  } else {
    Serial.print(F("FIN CORRECTE D'ANALYSE"));
  }

}

void loop() {}


(suite au message suivant)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

J-M-L

#4
Jul 09, 2018, 10:42 am Last Edit: Jul 09, 2018, 10:44 am by J-M-L
(suite du message précédent)

 Le code ci dessus donc va vous afficher dans le terminal série (réglé à 115200 bauds)


------------------------------------
        ANALYSE DU FLUX
------------------------------------
F.F(00)
0.0(            2359)
C.1.0(38451126)
C.1.1(        )
1.8.1(000011.096*kWh)
1.8.2(000019.999*kWh)
2.8.1(000000.000*kWh)
2.8.2(000000.000*kWh)
5.8.1(000000.000*kvarh)
5.8.2(000000.000*kvarh)
6.8.1(000000.000*kvarh)
6.8.2(000000.000*kvarh)
7.8.1(000000.000*kvarh)
7.8.2(000000.000*kvarh)
8.8.1(000007.226*kvarh)
8.8.2(000005.419*kvarh)
1.8.0(000031.096*kWh)
2.8.0(000000.000*kWh)
5.8.0(000000.000*kvarh)
6.8.0(000000.000*kvarh)
7.8.0(000000.000*kvarh)
8.8.0(000012.645*kvarh)
C.7.0(0006)
32.7(236*V)
52.7(235*V)
72.7(237*V)
31.7(00.139*A)
51.7(001.60*A)
71.7(00.457*A)
33.7(0.16)
53.7(0.90)
73.7(0.65)
13.7(0.83)
82.8.1(0001)
82.8.2(0000)
0.2.0(M29)
C.5.0(0401)
!
e
------------------------------------

ETIQUETTE = "F.F", VALEUR = "00"
ETIQUETTE = "0.0", VALEUR = "            2359"
ETIQUETTE = "C.1.0", VALEUR = "38451126"
ETIQUETTE = "C.1.1", VALEUR = "        "
ETIQUETTE = "1.8.1", VALEUR = "000011.096", UNITE = "kWh"
ETIQUETTE = "1.8.2", VALEUR = "000019.999", UNITE = "kWh"
ETIQUETTE = "2.8.1", VALEUR = "000000.000", UNITE = "kWh"
ETIQUETTE = "2.8.2", VALEUR = "000000.000", UNITE = "kWh"
ETIQUETTE = "5.8.1", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "5.8.2", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "6.8.1", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "6.8.2", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "7.8.1", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "7.8.2", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "8.8.1", VALEUR = "000007.226", UNITE = "kvarh"
ETIQUETTE = "8.8.2", VALEUR = "000005.419", UNITE = "kvarh"
ETIQUETTE = "1.8.0", VALEUR = "000031.096", UNITE = "kWh"
ETIQUETTE = "2.8.0", VALEUR = "000000.000", UNITE = "kWh"
ETIQUETTE = "5.8.0", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "6.8.0", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "7.8.0", VALEUR = "000000.000", UNITE = "kvarh"
ETIQUETTE = "8.8.0", VALEUR = "000012.645", UNITE = "kvarh"
ETIQUETTE = "C.7.0", VALEUR = "0006"
ETIQUETTE = "32.7", VALEUR = "236", UNITE = "V"
ETIQUETTE = "52.7", VALEUR = "235", UNITE = "V"
ETIQUETTE = "72.7", VALEUR = "237", UNITE = "V"
ETIQUETTE = "31.7", VALEUR = "00.139", UNITE = "A"
ETIQUETTE = "51.7", VALEUR = "001.60", UNITE = "A"
ETIQUETTE = "71.7", VALEUR = "00.457", UNITE = "A"
ETIQUETTE = "33.7", VALEUR = "0.16"
ETIQUETTE = "53.7", VALEUR = "0.90"
ETIQUETTE = "73.7", VALEUR = "0.65"
ETIQUETTE = "13.7", VALEUR = "0.83"
ETIQUETTE = "82.8.1", VALEUR = "0001"
ETIQUETTE = "82.8.2", VALEUR = "0000"
ETIQUETTE = "0.2.0", VALEUR = "M29"
ETIQUETTE = "C.5.0", VALEUR = "0401"
FIN CORRECTE D'ANALYSE


donc ça a l'air de fonctionner :)


en espérant que ça vous aide à y voir plus clair.

PS je n'ai pas utilisé strtok car d'une part ça détruit la chaîne d'entrée et d'autre part vous avez des besoins de cohérence dans l'analyse, par exemple chercher une parenthèse fermante ne doit pas être après la prochaine parenthèse ouvrante. --> faut travailler un peu plus finement.

en pratique cependant je ne procèderai pas comme cela, j'aurais une fonction lectureLigne() qui lit les données fournies par le compteur jusqu'à un '\n', ce qui me donne une ligne à analyser et ensuite je la passerai dans la moulinette qui est à l'intérieur du while. ça évite d'avoir à utiliser bcp trop de mémoire pour stocker un super grand message

On pourrait même avoir une machine à état qui bâtit analyse l'entrée de données caractère par caractère.
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

prophet_master

en tout cas ça m'aide beaucoup, merci pour le code qui est complétement fonctionnel ! les valeurs arrivent bien ligne après ligne dans le port série infrarouge. donc je vais essayer de me débrouiller avec votre code pour l'inclure dans mysensors et renvoyer tout ceci à mon jeedom.

Je vous tiens au courant de l'avancé...

J-M-L

super - postez votre travail à la fin, ça aidera d'autres membres qui travaillent éventuellement sur la même chose
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Go Up