Filtrage d'une trame sur port série à la volée

Bonjour,

Je travail actuellement sur un projet dans lequel je reçois et affiche cycliquement sur le moniteur série de ma Mega 2560 la trame suivante :


841975000339 >
VTIC 02 J
DATE E200826103755 E
NGTF H PLEINE-CREUSE Z
LTARF H CREUSE Z
EAST 000003302 W
EASF01 000003302 *
EASF02 000000000 #
EASF03 000000000 $
EASF04 000000000 %
EASF05 000000000 &
EASF06 000000000 '
EASF07 000000000 (
EASF08 000000000 )
EASF09 000000000 *
EASF10 000000000 "
EASD01 000003302 (
EASD02 000000000 !
EASD03 000000000 "
EASD04 000000000 #
IRMS1 010 /
URMS1 230 ?
PREF 09 H
PCOUP 09 "
SINSTS 02326 S
SMAXSN E200826103755 00360 :
SMAXSN-1 E200825101418 00000 H
UMOY1 E200826093000 235 3
STGE 000A0011 8
MSG1 PAS DE MESSAGE <
PRM 00000000000000 A
RELAIS 000 B
NTARF 01 N
NJOURF 00 &
NJOURF+1 00 B
PJOURF+1 00000001 10000002 NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE F

J'aimerais pouvoir filtrer cette trame "à la volée" c'est à dire en même temps que je la lis et n'afficher que les informations que je souhaite conserver.
J'ai déjà plus ou moins réussi en stockant chaque caractère dans un tableau de + 600 caractère.

Le problème étant que je suis limité en terme de mémoire et je voudrais éviter d'utiliser des tableaux.

Je voudrais aussi mettre à jour certaines variables associée à la trame pendant la lecture de celle-ci. Je prends l'exemple de la ligne 25 :

J'ai déclaré la variable suivante :

int SINSTS = 0;

Or on voit que dans la trame ci-dessus à la première lecture on a SINSTS = 02326 donc j'aimerais que cette variable après la première lecture prenne la valeur de 2326, si quelqu'un a une idée de comment je pourrais faire je suis preneur,

Merci d'avance.

vous avez une grammaire de ce langage ?

Bonsoir,

C'est de la téléinformation client (TIC) Linky nouvelle version.
La description est ici Enedis-NOI-CPT_54E.pdf.

Pour le programme, j'ai publié un décodeur décodeur TIC historique qui fait exactement ce que demande elkilleros (décodage à la volée, non bloquant, minimum de mémoire, etc.) , mais pour la version "historique" de la TIC.
Il lui suffit de s'en inspirer et de l'adapter à la nouvelle version de la TIC.

Bonne soirée et bonne bidouille,

Microquettas

@J_M_L c'est à dire une grammaire de ce langage ? quel langage ? le C ?

@MicroQuettas oui j'ai déjà lu et essayé de comprendre votre code, je suis débutant et pas familiarisé avec les notions de buffer, flag, pointer etc qui sont plus que largement utilisé dans votre code, je me demandais s'il existait un moyen plus "simple" de faire la même chose ; en gros enregistrer la trame dans une variable de type string et peut être la découper en plusieurs string et garder seulement ce que j'ai envie ? Je ne vois pas trop comment faire.

@J_M_L c'est à dire une grammaire de ce langage ? quel langage ? le C ?

Non le langage de ce qui est affiché. faut pouvoir l'interpréter.

J-M-L:
Non le langage de ce qui est affiché. faut pouvoir l'interpréter.

Oui, j'ai déjà lu plusieurs fois la doc Enedis je sais à quoi correspond chaque lignes, étiquettes, valeurs, comment est fait le calcul des checksums etc...

Mais pour l'instant impossible de faire ce que je veux, je ne cherche pas une solution servie sur un plateau, mais juste une méthode à suivre.

il faut écrire un "parser", quelque chose qui analyse à la volée ce qui arrive.
Donc pour cela il faut savoir ce qui peut arriver, d'où la notion de "grammaire".

c'est sans doute ce qu'a écrit @MicroQuettas (je n'ai pas regardé).

Tout conserver dans une grosse string n'est pas forcément faisable car la mémoire est limitée

@J-M-L oui comme déjà dis au dessus, je suis incapable de comprendre le code de @MicroQuettas avec mon niveau actuel, c'est pour ça que je cherche plus à ce qu'on m'expliquer la méthodo plutôt que de déchiffrer un code, bien trop complexe pour moi.

Est-tu capable d'interpréter ces informations "à la main" , c-à-d avec papier, crayon et calculatrice ?
Pour ce faire il faut lire et assimiler la documentation de la trame.

Par exemple je vois une ligne qui commence par DATE, il est probable que la donnée qui suit représente une date, encodée dans la chaîne de caractères E200826103755, où l'on devine le 26 octobre 2008... ou pas. La documentation de la trame te donnera la méthode pour analyser ces caractères et en tirer une date.

Pareils pour toutes les lignes.

Ensuite, et seulement une fois que tu as compris comment faire pour chaque donnée, tu peux commencer à coder toi-même, extrayant donnée par donnée du texte reçu.

@biggil Bonjour, comme dit au dessus, je sais à quoi correspond chaque ligne, chaque donnée etc.. pas besoin de calculatrice, je me suis déjà lu une dizaine de fois la doc Enedis qui décrit la trame.

"Ensuite, et seulement une fois que tu as compris comment faire pour chaque donnée, tu peux commencer à coder toi-même, extrayant donnée par donnée du texte reçu." => c'est la tout le soucis, comme dis dès le début je ne vois pas comment faire, je cherche une méthode pour parser cette trame et enregistrer certaines données uniquement dans des variables, j'ai déjà essayé pas mal de truc :

  • Enregistrer chaque caractères de la trame dans un tableau => trop gourmand en mémoire
  • Enregistrer toute la trame dans une string => trop gourmand en mémoire

Je cherche donc a enregistrer seulement certaines données à la volée dans des variables string mais la encore une fois je manque d'expérience et je ne vois pas trop comment faire...

edit : juste pour info l'étiquette date indique que la donnée qui suit est la date et l'heure donc pour le coup ici : E200826103755, => 20 08 26 10 37 55 => Année/Mois/Jour/Heure/minutes/secondes => 26 Août 2020 à 10h 37 min et 55 sec.

la boucle d'analyse doit faire:

lire une ligne
trouver à quelle partie de la spec elle correspond
si elle ne vous intéresse pas, ne rien faire
sinon extraire la donnée

@J-M-L

Yes, j'avais pensé à la même chose, le problème c'est "lire une ligne"

en fait j'utilise un serial.read() pour lire caractère par caractère la trame je ne sais pas comment programmer en C l'instruction suivante : "cette suite de caractère m'intéresse donc je les garde"

Si vous voulez analyser comment écouter le port série (ou gérer un flux asynchrone genre keypad) vous pouvez jeter un oeil à mon petit tuto sur le sujet

il y a des fonctions comme strstr() qui permettent de chercher une chaîne dans la ligne reçue par exemple.

@J-M-L Yes j'avais déjà lu le tuto, le truc c'est que dans mon cas je ne reçois pas une chaîne de caractère mais bien des caractères à la suite, que je ne peux pas enregistrer dans une seule chaine pour des soucis de mémoire (+ 700 caractère), ce qui complique un peu tout....

Tu peux faire l'acquisition de la trame d'information ligne par ligne. Donc tu n'as pas besoin d'une aussi grande capacité de stockage.

@fdufnews oui ! ligne par ligne ce serait le top à faire le truc c'est que j'ai vraiment aucune idée de comment faire.

elkilleros:
@J-M-L Yes j'avais déjà lu le tuto, le truc c'est que dans mon cas je ne reçois pas une chaîne de caractère mais bien des caractères à la suite, que je ne peux pas enregistrer dans une seule chaine pour des soucis de mémoire (+ 700 caractère), ce qui complique un peu tout....

des caractères à la suite c'est une chaîne de caractère...

elkilleros:
ligne par ligne ce serait le top à faire le truc c'est que j'ai vraiment aucune idée de comment faire.

On dirait qu'il y a clairement des retours à la ligne donc on peut lire jusqu'à ce marqueur, faire le traitement, puis aller continuer à lire.

c'est ce qu'explique mon tuto... l'avez vous vraiment lu ? je donne même une fonction qui fait ça..

pour lire une ligne, tu lis les caractères ... jusqu'à ce que tu trouve le caractère "fin de ligne".
Si tu les lis 1 par 1, tu les stockes dans un tableau de char. Un fois trouvé le caractère "fin de ligne", tu ajoutes un octet nul à la suite de ton tableau (tu ne stockes pas le caractère fin de ligne, tu stockes un zéro à la place).

Voilà. Tu as une ligne, tu peux commencer à l'analyer, la reconnaître. Techniquement, c'est une "C string null-terminated". Parfait pour utiliser les fonctions du C comme strlen(), etc...

C'est quoi le caractère "fin de ligne" ? Ce peut être '\r' ou '\n' ou les deux. Ca devrait être dit dans la doc de la trame.