O Ouvrir le menu
Les notes d'Ailothaen

Mesures et graphiques d'un compteur Linky avec un Raspberry Pi et Grafana – Partie 2/2 (logiciel)

Articles techniques

Suite de l'article sur comment lire les données d'un compteur Linky avec un Raspberry Pi.
La première partie était dédiée à la connexion physique entre le Raspberry et le Linky, dans cette deuxième partie nous allons lire les données et les exploiter.

Se connecter au compteur

Le protocole de communication est simple : il s'agit d'une simple transmission série RS232. Le compteur crache en permanence ses informations, il suffit donc de se mettre à écouter et récupérer ce qui nous intéresse.

Si vous avez branché correctement la carte électronique sur les broches du Raspberry Pi, vous devriez la voir apparaître en tant que /dev/ttyS0 (ou similaire) :

root@hephaistos:~ # ls /dev/ttyS*
/dev/ttyS0

(Si /dev/ttyS0 n'apparaît pas, vérifiez que vous avez bien activé la transmission série dans raspi-config)

Les paramètres sont normalement : 1200 bauds, 7 bits de données et pas de contrôle de flux.
Si tout est fait correctement, vous devriez voir ceci apparaître (pour quitter picocom, il faut faire Ctrl+A puis Ctrl+X, oui c'est tordu) :

root@hephaistos:~ # picocom -b 1200 -d 7 -f n /dev/ttyS0
picocom v3.1

port is        : /dev/ttyS0
flowcontrol    : none
baudrate is    : 1200
parity is      : even
databits are   : 7
stopbits are   : 1
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
hangup is      : no
nolock is      : no
send_cmd is    : sz -vv
receive_cmd is : rz -vv -E
imap is        :
omap is        :
emap is        : crcrlf,delbs,
logfile is     : none
initstring     : none
exit_after is  : not set
exit is        : no

Type [C-a] [C-h] to see available commands
Terminal ready
002078240 "
PTEC TH.. $
IINST 000 W
IMAX 090 H
PAPP 00070 (
HHPHC A ,
MOTDETAT 000000 B
ADCO xxxxxxxxxxxx O
OPTARIF BASE 0
ISOUSC 30 9
BASE 002078240 "
PTEC TH.. $
IINST 000 W
IMAX 090 H
Terminating...
Thanks for using picocom

Ça marche ! On voit apparaître des données qui nous intéressent : IMAX est la puissance maximale de l'abonnement, BASE est le compteur en Wh, PAPP est la puissance en kVA utilisée actuellement... Le dernier caractère est la somme de contrôle.
La liste complète des champs est dans la même documentation que celle en partie 1.

Parfait, cela fonctionne ! Prochaine étape, mettre ces données dans une base de données !

Un service pour tout récupérer (et enregistrer)

À partir de là, il est possible d'exploiter ces données en faisant un script avec le langage de votre choix, tant qu'il peut écouter une transmission série.

J'ai réalisé un service Python qui se connecte à cette transmission, et enregistre toutes les minutes les données qui nous intéressent (compteur et puissance instantanée notamment) dans une base de données MySQL. Une fois par jour, le service fait également un « résumé » de la journée, et le stocke dans une autre table (cela permet de grandement simplifier la suite).
Le dépôt Github se trouve ici. Je vais utiliser ce code pour la suite, mais vous pouvez faire le vôtre si vous n'aimez pas Python 🙂

D'abord, nous allons installer le serveur MariaDB et créer une base ainsi qu'un utilisateur associé à cette base. Je ne vais pas m'étendre là-dessus, il y a beaucoup d'autres articles expliquant comment faire, comme celui-là ou celui-là.

Ensuite, placez le code du Github dans un répertoire sur votre Raspberry (j'ai choisi /srv/linky, donc il faudra le changer dans les fichiers de configuration si vous le mettez ailleurs). Installez les dépendances avec python3 -m pip install -r requirements.txt, puis éditez le fichier config.yml pour mettre les bons paramètres pour la connexion à la base et au port série.

Enfin, placez le fichier linky.service dans /etc/systemd/system (en éditant éventuellement l'utilisateur et le répertoire spécifiés à l'intérieur), puis lancez les commandes suivantes :

systemctl daemon-reload
systemctl enable linky
systemctl start linky

Cela permet de créer un service qui va faire tourner notre script en continu.

Attendez quelques minutes, et si tout fonctionne normalement, la base de données devrait commencer à se remplir :

root@hephaistos:/srv/linky # mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
(...)
MariaDB [(none)]> use linky;
(...)
MariaDB [linky]> select * from stream;
+---------------------+---------+------+-----------+
| clock               | BASE    | PAPP | BASE_diff |
+---------------------+---------+------+-----------+
| 2022-07-14 17:02:55 | 2086442 |   70 |         0 |
| 2022-07-14 17:03:57 | 2086443 |   70 |         1 |
| 2022-07-14 17:04:58 | 2086443 |   70 |         0 |
+---------------------+---------+------+-----------+
4 rows in set (0.002 sec)

Si cela ne fonctionne pas, regardez soit dans les logs du script Python (dossier logs), soit dans les logs du service (journalctl -u linky)

Affichage dans de jolis graphiques

Nous avons maintenant une table dans une base de données qui se remplit automatiquement. Mais des données brutes, c'est compliqué à visualiser... Il nous faudrait donc une interface de visualisation.

Nous pouvons pour cela utiliser Grafana. Il s'agit d'un logiciel côté serveur qui se connecte à une source de données (une base de données, un fichier texte, un service) et qui peut générer des graphiques selon les paramètres qu'on veut. Il est initialement prévu pour de la métrologie : supervision de serveurs, de sondes de température, etc. Cela tombe bien, c'est exactement notre cas d'utilisation.

Vous trouverez ici les instructions officielles sur comment installer Grafana. La partie compliquée est de choisir la bonne architecture. Si comme moi vous avez un Raspberry Pi Zero, c'est l'architecture « ARMv6 ».
Une fois installé, vous devez installer le service, et attendre une ou deux minutes le temps que Grafana s'initialise pour la première fois :

systemctl daemon-reload
systemctl enable grafana-server
systemctl start grafana-server

Ensuite, allez sur http://IP_DE_VOTRE_RASPBERRY:3000. Vous devriez voir la fenêtre de connexion (par défaut les identifiants sont admin / admin)

grafana1.png, juil. 2022

Pour créer des graphiques, il faut d'abord dire à Grafana où trouver les données. Allez dans Configuration > Data Sources :

grafana2.png, juil. 2022
... puis ajoutez la base de données en sélectionnant le type « MySQL ».

Ensuite, créons un nouveau dashboard (c'est une vue qui affiche un ou plusieurs graphiques) :

grafana3.png, juil. 2022

... et créez un panel (une boîte qui contient un graphique).

grafana4.png, juil. 2022

Vous pouvez soit utiliser l'éditeur de requêtes, soit écrire une requête SQL à la main. Personnellement j'ai écrit cette requête SQL qui permet de récupérer la puissance instantanée sur une période et de l'afficher :

SELECT
  clock AS "time",
  PAPP
FROM stream
WHERE
  $__timeFilter(clock)
ORDER BY clock

Une fois la requête indiquée, Grafana sait chercher automatiquement les données et les affiche. (La période peut se régler en haut à gauche).

notice.png, juil. 2022
La classe, non ?

Enregistrez le graphique. Il sera désormais visible sur votre dashboard quand vous y accéderez. Vous avez la possibilité de changer le panel de taille/place, et de créer plusieurs panels sur un dashboard.

Vous savez maintenant comment ça marche. Vous pouvez vous amuser avec l'interface pour générer d'autres types de graphiques, changer la couleur de la ligne, changer la période pour comparer des journées par exemple...
Un autre exemple de graphique intéressant est la consommation sur une journée entière (SELECT clock AS "time", BASE_diff/1000 AS "kWh" FROM `dailies` WHERE $__timeFilter(clock);).
Ensuite, vous pouvez découvrir les possibilités de Grafana en générant plusieurs dashboards, autoriser à voir certains dashboards/graphiques sans avoir à se connecter...

Amusez-vous bien ! 🦉

T 10 commentaires
Partager:      
Jlinkyraspberryélectronique
Vous voulez sauvegarder cet article ?
Imprimez cette page vers un PDF !

10 commentaires

id
kristof
27/10/2022

Bonjour. Tres bon travail mais j'ai un probleme d'heure. Le python prend le fuseau UTC du coup mes enregistrement sont décalé de deux heures.
Mon raspberry et MariaDB sont correct sur le fuseau horaire.
Le python, je maitrise pas.
Merci

id
Ailothaen
20/11/2022

Salut kristof,

En effet, j'avais à l'origine fait le programme en partant du principe que toutes les dates/heures soient enregistrées en UTC (cela permet de ne pas se prendre la tête avec les changements d'heures, les conversions, et c'est un standard en général) et que l'utilisateur pouvait configurer le Grafana pour le prendre en compte.
Cependant, je comprends que ça puisse ajouter une contrainte si jamais on utilise la base de données directement...

Je viens donc de faire une mise à jour du programme, il y a maintenant une option "use_utc" dans la configuration qu'on peut mettre à true ou false selon si on veut utiliser l'heure UTC ou locale. Attention, j'ai dû changer le schéma de la base de données, il faut donc en recréer une nouvelle.

Bon dimanche !

id
eliobuo
28/10/2023

Bonjour, je ne reçois pas de code BASE en regardant défiler les logs. Il n'y a donc aucune donnée qui se stock dans la base mariaDB. Est-ce qu'il y a quelque chose à activer ?

id
Ailothaen
29/10/2023

Bonjour @eliobuo,
Normalement il n'y a rien de particulier à activer. Est-ce que les câbles sont branchés au bon endroit (bornes I1 et I2) et correctement branchés ?
Également, est-ce que le mode TIC (visible en faisant défiler les informations sur le compteur) est bien en mode "HISTORIQUE" ? (c'est aussi possible de lire les données en mode "STANDARD", mais je n'ai pas accès à un compteur dans ce mode, donc je ne peux pas expérimenter avec ça)

id
Bats
30/01/2024

Bonjour,

Je me suis lancé dans ce projet. Tout roule pour moi jusqu'à la mise en place du code Python.
Je n'arrive pas à créer les dossiers ni à copier dedans les fichiers du git.
Je débute alors sans doute je passe à coté de choses très basiques.
J'ai créé l'arborescence avec mkdir (\srv\linky).
Comment copier les fichiers dedans ensuite?
Merci de ton aide.
b

id
Bats
30/01/2024

Salut
J'aurai du attendre un peu car j'ai fini par trouver.
Cependant j'ai l'impression que j'ai fait une cagade en macant le script en python.
La BDD ne se remplit pas.
Le journal du scirpt indique une erreur
bapti@linky:~ $ journalctl -u linky
-- Journal begins at Tue 2023-12-05 04:07:44 CET, ends at Tue 2024-01-30 21:55:44 CET. --
Jan 30 21:51:12 linky systemd[1]: Started Python service fetching Linky and putting data into MySQL.
Jan 30 21:51:12 linky systemd[3317]: linky.service: Changing to the requested working directory failed: No such file or directory
Jan 30 21:51:12 linky systemd[3317]: linky.service: Failed at step CHDIR spawning /usr/bin/python3: No such file or directory
Jan 30 21:51:12 linky systemd[1]: linky.service: Main process exited, code=exited, status=200/CHDIR
Jan 30 21:51:12 linky systemd[1]: linky.service: Failed with result 'exit-code'.

Là je suis super loin de mes bases, python, je ne connias pas du tout.

id
Ailothaen
01/02/2024

Salut Bats,
Le message "Failed at step CHDIR spawning /usr/bin/python3: No such file or directory" me fait penser à une erreur dans le fichier linky.service. Est-ce que WorkingDirectory et ExecStart sont bien renseignés ?
Il faut s'assurer que les répertoires existent bien et que les scripts sont bien à cet endroit.

id
Bats
05/02/2024

J'avoue que c'est la partie que je maitrise le moins...

J'ai créé les dossier srv et etc/systemd/system avec des mkdir.
Ensuite j'ai cloné le git dans srv.
Dans le dossier srv/linky ainsi créé j'ai effectué la commande pour installer les dépendances Python
J'ai édité config.yml pour changer le mdp et mettre UTC en False.
Première question: je n'ai pas changé le paramètre server (127.0.0.1 chez toi). est ce ok? comment trouver l'adresse chez moi s'il faut la changer?

J'ai ensuite fait un "move" vers etc/systemd/system du fichier linky.service puis un "cp". Mais apparemment ca ne marche pas. Il faut que je fouille. Je débute en Linux.

Je n'ai en effet pas toucher à WorkingDirectory et Execstart. Où les trouve t on?

Merci de ton aide ;-)

id
Ailothaen
06/02/2024

Tout d'abord, attention aux dossiers : c'est bien "/srv/linky" et "/etc/systemd/system" (avec un / au début). /srv/linky est l'endroit où on met le contenu du dépôt GitHub. Pour /etc/systemd/system, c'est là où (sur Debian) on met les fichiers .service (c'est ce qui permet de pouvoir taper "systemctl start linky" et d'avoir le programme qui démarre, notamment)

Le fichier "linky.service" est donc à mettre dans /etc/systemd/system, mais il faut peut-être le modifier pour s'assurer que WorkingDirectory et ExecStart sont bien corrects (pointent bien vers les bons répertoires et fichiers)

Concernant le 127.0.0.1, pas besoin de le changer normalement.

(J'en profite pour le dire ici : attention car pour l'instant le programme ne marche que si on a contrat "standard", si on a un contrat heures pleines/creuses ou Tempo ça ne fonctionnera pas - mais je prévois de corriger ça prochainement)

id
Bats
11/02/2024

Merci des retours.

J'ai réglé deux trois soucis mais je bloque tjrs sur les dossiers du script en python.
J'ai bien les dossiers qui apparaissent lorsque je fais un "ls" mais je ne les vois pas dans l'explorateur windows quand je mets la carte SD sur mon ordi.

Je suis super preneur du script heure creuse/pleine pour la maison des parents ;-)

Ajouter un commentaire

Comments are disabled on this article.

Cet article a été imprimé (ou sauvegardé en PDF) du blog « Les notes d'Ailothaen ». Lien original de l'article : https://notes.ailothaen.fr/post/2022/07/Mesures-et-graphiques-d-un-compteur-Linky-avec-un-Raspberry-Pi-et-Grafana-%E2%80%93-Partie-2/2-%28logiciel%29