Tuto - Mise à jour du tarif TEMPO (Mise à jour via PDF en auto)

Bonjour à tous,

Comme promis dans le tutoriel de @mutmut : (Merci à lui pour ce tuto)

Et suite à mon tutoriel qui permets de récupérer les tarifs hors tempo :

J’ai voulu voir pour automatiser la récupération des différents coûts.

Je suis donc tomber sur ce tutoriel Jeedom (Merci à son auteur) dont je me suis fortement inspiré, avec le copie du code node-red :

Le but ici est de récupérer le fichier pdf de la grille tarifaire tempo directement sur le site d’EDF pour mettre à jour les valeurs directement dans Gladys et avoir son coût réel au kWh à la minute prêt pour pouvoir l’utiliser dans d’autres scènes :slight_smile:

Le fichier est trouvable ici :
https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille_prix_Tarif_Bleu.pdf

Il faudra juste espérer que la structure/composition du fichier ne soit pas changé par EDF :grin:

Le résultat final :

image

Voici le flux Node-Red :
( Un catch all est présent pour récupérer les erreurs et les envoyer par email )

[
    {
        "id": "670838a9edef0758",
        "type": "catch",
        "z": "d6333988d9cfb817",
        "name": "Erreurs",
        "scope": null,
        "uncaught": false,
        "x": 110,
        "y": 60,
        "wires": [
            [
                "c097dad994334b5e"
            ]
        ]
    },
    {
        "id": "c097dad994334b5e",
        "type": "e-mail",
        "z": "d6333988d9cfb817",
        "server": "monserveuremail",
        "port": "465",
        "authtype": "BASIC",
        "saslformat": false,
        "token": "oauth2Response.access_token",
        "secure": true,
        "tls": true,
        "name": "monadresse@email.fr",
        "dname": "Mail",
        "x": 250,
        "y": 60,
        "wires": []
    },
    {
        "id": "bf708d78a507d9c3",
        "type": "http request",
        "z": "d6333988d9cfb817",
        "name": "",
        "method": "GET",
        "ret": "bin",
        "paytoqs": "ignore",
        "url": "https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille_prix_Tarif_Bleu.pdf",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 430,
        "y": 140,
        "wires": [
            [
                "c6602cec6bea28ca"
            ]
        ]
    },
    {
        "id": "c6602cec6bea28ca",
        "type": "file",
        "z": "d6333988d9cfb817",
        "name": "",
        "filename": "/tmp/Grille_prix_Tarif_Bleu.pdf",
        "filenameType": "str",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 290,
        "y": 200,
        "wires": [
            [
                "866bd16b214c1d1d"
            ]
        ]
    },
    {
        "id": "a0349e7017779b4a",
        "type": "change",
        "z": "d6333988d9cfb817",
        "name": "Texte",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.text",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 670,
        "y": 200,
        "wires": [
            [
                "d23eb75a79c8996d"
            ]
        ]
    },
    {
        "id": "d23eb75a79c8996d",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Après \"Option Tempo\"",
        "func": "const regex = /Option Tempo((.|\\n)*)/gm;\nconst found = msg.payload.match(regex);\nmsg.payload = found[0];\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 480,
        "y": 280,
        "wires": [
            [
                "09faecd167fed230"
            ]
        ]
    },
    {
        "id": "09faecd167fed230",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "6 kVA",
        "func": "const regex = /6 .*/gm; // puissance souscrite\nconst found = msg.payload.match(regex);\nconst searchRegExp = /,/g; // remplace les virgules par des points\nconst replaceWith = '.';\nmsg.payload = found[0];\nmsg.payload = msg.payload.replace(searchRegExp, replaceWith);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 670,
        "y": 280,
        "wires": [
            [
                "e7ca8ee4d891c581"
            ]
        ]
    },
    {
        "id": "e7ca8ee4d891c581",
        "type": "split",
        "z": "d6333988d9cfb817",
        "name": "",
        "splt": " ",
        "spltType": "str",
        "arraySplt": 1,
        "arraySpltType": "len",
        "stream": false,
        "addname": "",
        "x": 510,
        "y": 360,
        "wires": [
            [
                "9f3df8ae0bd5d4bf"
            ]
        ]
    },
    {
        "id": "9f3df8ae0bd5d4bf",
        "type": "join",
        "z": "d6333988d9cfb817",
        "name": "",
        "mode": "custom",
        "build": "array",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "num",
        "reduceFixup": "",
        "x": 650,
        "y": 360,
        "wires": [
            [
                "88eaf52f02be48c8"
            ]
        ]
    },
    {
        "id": "88eaf52f02be48c8",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "JSON",
        "func": "msg.payload = {\n    \"puissance\": msg.payload[0],\n    \"prix_abonnement\": Number((Number(msg.payload[1]) * 12).toFixed(2)),\n    \"prix_HCJB\": Number(Number(msg.payload[2] / 100).toFixed(4)),\n    \"prix_HPJB\": Number(Number(msg.payload[3] / 100).toFixed(4)),\n    \"prix_HCJW\": Number(Number(msg.payload[4] / 100).toFixed(4)),\n    \"prix_HPJW\": Number(Number(msg.payload[5] / 100).toFixed(4)),\n    \"prix_HCJR\": Number(Number(msg.payload[6] / 100).toFixed(4)),\n    \"prix_HPJR\": Number(Number(msg.payload[7] / 100).toFixed(4)),\n}\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 790,
        "y": 360,
        "wires": [
            [
                "6e2b78e27c34c026",
                "4d19e36f157bd2c0",
                "50608e9e9bdecdc6",
                "d9fe4a5ac7c52d90",
                "b4a2b0d2177a9058",
                "c5f9959555f3e7b9"
            ]
        ]
    },
    {
        "id": "1316dbce795332d5",
        "type": "inject",
        "z": "d6333988d9cfb817",
        "name": "Tous les jours à 9h30",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "30 09 * * *",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 220,
        "y": 140,
        "wires": [
            [
                "bf708d78a507d9c3"
            ]
        ]
    },
    {
        "id": "866bd16b214c1d1d",
        "type": "pdfparse",
        "z": "d6333988d9cfb817",
        "name": "",
        "path": "/tmp/Grille_prix_Tarif_Bleu.pdf",
        "x": 520,
        "y": 200,
        "wires": [
            [
                "a0349e7017779b4a"
            ]
        ]
    },
    {
        "id": "6e2b78e27c34c026",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Jour bleu HC",
        "func": "msg.payload = msg.payload.prix_HCJB;\nmsg.payload = parseFloat(msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 960,
        "y": 300,
        "wires": [
            [
                "0a6e473635b8b423"
            ]
        ]
    },
    {
        "id": "4d19e36f157bd2c0",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Jour bleu HP",
        "func": "msg.payload = msg.payload.prix_HPJB;\nmsg.payload = parseFloat(msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 960,
        "y": 340,
        "wires": [
            [
                "69c1fb09c3ede0e0"
            ]
        ]
    },
    {
        "id": "50608e9e9bdecdc6",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Jour blanc HC",
        "func": "msg.payload = msg.payload.prix_HCJW;\nmsg.payload = parseFloat(msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 380,
        "wires": [
            [
                "467f6ce03f7ed6c0"
            ]
        ]
    },
    {
        "id": "d9fe4a5ac7c52d90",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Jour blanc HP",
        "func": "msg.payload = msg.payload.prix_HPJW;\nmsg.payload = parseFloat(msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 420,
        "wires": [
            [
                "ed628e4d71dbbc38"
            ]
        ]
    },
    {
        "id": "b4a2b0d2177a9058",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Jour rouge HC",
        "func": "msg.payload = msg.payload.prix_HCJR;\nmsg.payload = parseFloat(msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 460,
        "wires": [
            [
                "f2b3869570196614"
            ]
        ]
    },
    {
        "id": "c5f9959555f3e7b9",
        "type": "function",
        "z": "d6333988d9cfb817",
        "name": "Jour rouge HP",
        "func": "msg.payload = msg.payload.prix_HPJR;\nmsg.payload = parseFloat(msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 500,
        "wires": [
            [
                "ae1d548f6cb679aa"
            ]
        ]
    },
    {
        "id": "0a6e473635b8b423",
        "type": "mqtt out",
        "z": "d6333988d9cfb817",
        "name": "",
        "topic": "gladys/master/device/mqtt:edf/feature/mqtt:cout-abonnement-jour-bleu-hc/state",
        "qos": "2",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 300,
        "wires": []
    },
    {
        "id": "69c1fb09c3ede0e0",
        "type": "mqtt out",
        "z": "d6333988d9cfb817",
        "name": "",
        "topic": "gladys/master/device/mqtt:edf/feature/mqtt:cout-abonnement-jour-bleu-hp/state",
        "qos": "2",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 340,
        "wires": []
    },
    {
        "id": "467f6ce03f7ed6c0",
        "type": "mqtt out",
        "z": "d6333988d9cfb817",
        "name": "",
        "topic": "gladys/master/device/mqtt:edf/feature/mqtt:cout-abonnement-jour-blanc-hc/state",
        "qos": "2",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 380,
        "wires": []
    },
    {
        "id": "ed628e4d71dbbc38",
        "type": "mqtt out",
        "z": "d6333988d9cfb817",
        "name": "",
        "topic": "gladys/master/device/mqtt:edf/feature/mqtt:cout-abonnement-jour-blanc-hp/state",
        "qos": "2",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 420,
        "wires": []
    },
    {
        "id": "f2b3869570196614",
        "type": "mqtt out",
        "z": "d6333988d9cfb817",
        "name": "",
        "topic": "gladys/master/device/mqtt:edf/feature/mqtt:cout-abonnement-jour-rouge-hc/state",
        "qos": "2",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 460,
        "wires": []
    },
    {
        "id": "ae1d548f6cb679aa",
        "type": "mqtt out",
        "z": "d6333988d9cfb817",
        "name": "",
        "topic": "gladys/master/device/mqtt:edf/feature/mqtt:cout-abonnement-jour-rouge-hp/state",
        "qos": "2",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 500,
        "wires": []
    },
    {
        "id": "0ee77e0f90aa9681",
        "type": "mqtt-broker",
        "name": "GLADYS-MQTT",
        "broker": "mqtt://192.168.0.248",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthRetain": "false",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closeRetain": "false",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willRetain": "false",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    }
]

Bien penser à modifier la puissance souscrite :slight_smile:

Pré-requis :

Installer le module node-red-contrib-pdfparse :

Voici l’appareil MQTT avec les fonctionnalités :





Voici les scènes :

Jour blanc - HC :





Jour blanc - HP :





Jour bleu - HC :





Jour bleu - HP :





Jour rouge - HC :





Jour rouge - HP :





Si vous avez des questions/remarques, n’hésitez pas à m’en faire part :slight_smile:

Changelog à venir :

  • Aucun (A vos commentaires :slight_smile: )
1 « J'aime »

Super tuto ! Merci @prohand !

1 « J'aime »

Bravo @prohand , je n’avais pas eu le courage de mettre tous mes screenshots pour tous les cas HCHP&JourQuiVaBien :wink:
Petite question sur les déclencheurs, pourquoi en as-tu mis un à 00:01 ? Gladys ne gère pas le suivi d’un jour à l’autre ?

EDIT : il y a un paragraphe « Download CSV » qui traîne à la fin de ton flux (je l’ai viré car pas compris) et pour ceux qui ont un node-red un peu vierge comme le mien, j’ajouterai qu’il faut installer le pdfparse :


Bien sûr, ne pas oublier de paramétrer votre serveur MQTT (avec login/pwd).

EDIT 2 : @prohand tu as pris quoi comme module pour le mail ?
j’ai des pbs d’install :frowning:

2024-12-13T18:18:42.602Z Installer : node-red-node-email 3.0.2

2024-12-13T18:18:42.699Z npm install --no-audit --no-update-notifier --no-fund --save --save-prefix=~ --production --engine-strict node-red-node-email@3.0.2
2024-12-13T18:18:43.732Z [err] npm
2024-12-13T18:18:43.733Z [err]  WARN
2024-12-13T18:18:43.734Z [err]  config production Use `--omit=dev` instead.
2024-12-13T18:18:45.070Z [err] npm
2024-12-13T18:18:45.071Z [err]  ERR! code EBADENGINE
2024-12-13T18:18:45.075Z [err] npm
2024-12-13T18:18:45.076Z [err]  ERR!
2024-12-13T18:18:45.076Z [err]  engine Unsupported engine
2024-12-13T18:18:45.076Z [err] npm ERR!
2024-12-13T18:18:45.076Z [err]  
2024-12-13T18:18:45.076Z [err] engine Not compatible with your version of node/npm: node-red-node-email@3.0.2
2024-12-13T18:18:45.077Z [err] npm 
2024-12-13T18:18:45.077Z [err] ERR! notsup Not compatible with your version of node/npm: node-red-node-email@3.0.2
2024-12-13T18:18:45.077Z [err] npm ERR! notsup
2024-12-13T18:18:45.077Z [err]  Required: {"node":">=18.0.0"}
2024-12-13T18:18:45.077Z [err] npm 
2024-12-13T18:18:45.077Z [err] ERR! notsup Actual:   {"npm":"8.19.4","node":"v16.20.2"}
2024-12-13T18:18:45.082Z [err] 
2024-12-13T18:18:45.082Z [err] npm ERR!
2024-12-13T18:18:45.083Z [err]  A complete log of this run can be found in:
2024-12-13T18:18:45.083Z [err] npm ERR!     /data/.npm/_logs/2024-12-13T18_18_43_653Z-debug-0.log
2024-12-13T18:18:45.094Z rc=1

Effectivement le 00h01 c’est une erreur car je pensais qu’a 00h00 on changeait de jour…
Mais la preuve ici que non :grin: :

Donc il n’y en a effectivement pas besoin :slight_smile:
Je corrige les captures d’écran directement après ce message

Je corrige également le flux node red, c’est une erreur de copier coller

Je rajoute le faite d’installer le module pdfparse

Pour l’email j’ai pris celui-ci :

image

Merci pour toutes ces remontées :wink:

2 « J'aime »

Hello,
je viens de voir que j’avais pris le même module node-red-node-email que toi mais je n’ai que la 3.0.2 et tu as la 2.2.1, et le problème est qu’il faut nodeJS >18 pour ce module en version 3.x.x :frowning:
Comment as-tu fait pour avoir cette version spécifique ?

Je plussoie la mise à jour de nodeJS si c’est possible bien entendu :wink:

Hello,

J’ai surement du le télécharger lorsque c’était la dernière version tout simplement ^^
Si tu trouves comment installer une version plus ancienne, je suis preneur :slight_smile:

je galère : j’ai essayé dans une console docker de faire npm i node-red-node-email@2.2.1
Ça dit qu’un nouveau module est installé, d’autres à mettre à jour, mais rien n’arrive dans node-red, même avec un refresh de la page web.

Alors j’ai voulu désactiver l’intégration node-red depuis GLadys et l’activer de nouveau.
Résultat : j’ai tout perdu (flux et modules installés) :cry:
La désactivation supprime le conteneur mais aussi toutes les data sauvegardées sur le volume monté (/volume1/docker/gladysassistant/node-red dans mon cas sur un Syno). La loose :grimacing:

Je ne sais pas si c’est un comportement normal mais c’est très c.n surtout quand tu n’as pas sauvegardé ce rep, @pierre-gilles tu saurais nous dire ?

Aie, oui la sa sort de mes compétences ^^
C’est pour cela que je sauvegarde la VM entière tout les soirs de mon côté :slight_smile:
J’ai aussi un export de mes flux vers mon adresse email au cas ou.
Bon courage à toi :neutral_face:

Je ne suis pas le développeur de cette intégration mais oui c’est le comportement attendu :slight_smile:

Un petit message de warning pourrait être le bienvenue par contre !

J’ai créé une issue :

1 « J'aime »