Monitoring électricité avec la téléinfo et Node Red

Hi !
Je vais vous expliquer un peu ce que j’ai fais pour monitorer ma consommation d’élec :slight_smile:

:warning: Disclaimer : Ne touchez pas si vous ne savez pas ce que vous faites ! Risque d’électrocution ! On parle quand même du compteur ! Si vous faites une mauvaise manip vous pouvez vous cramer la tête ou cramer le compteur (qu’Enedis s’empressera de vous facturer !)
Ne déplombez pas votre compteur ! Ca vous coutera cher !
Ne mettez pas le feu chez vous, c’est pas marrant !

Le contexte :
J’ai un compteur linky en limite de propriété. Malheureusement me brancher sur la prise téléinfo de ce dernier n’était pas envisageable parce que hors de portée wifi et impossible de passer des câbles dans la gaine déjà en place (elle est sûrement écrasée entre le compteur et le sous sol de ma maison).
Je suis en contrat double tarif (HP/ HC).

La solution : Mettre un autre compteur dans le sous sol en tête de tableau élec ! J’ai donc acheté un compteur électrique d’occasion sur Ebay, un sagemcom s10c4. (Modèle utilisé par EDF pendant des années avant le linky). Branché l’arrivée de courant en provenance de mon disjoncteur principal sur ce compteur puis à la sortie de ce compteur mon tableau électrique. Du coup chaque Wh consommé par mon installation domestique passe dans ce compteur. J’utilise donc les bornes téléinfo de ce compteur :smiley:

La mise en place : 2 simples fils d’un paire d’un câble PTT298 entre le compteur et un boitier de téléinfo GCE electronics : http://gce-electronics.com/fr/usb/655-module-teleinfo-usb.html et le boitier branché en USB sur mon NUC. Passage de ce boitier en passthrough à ma VM ou hassio est installé. et hop un nouveau port série est détecté :slight_smile:
J’ai décidé de faire la relève via nodered en m’inspirant très fortement de ce qui est fait par Charles sur Hallard.me. => http://hallard.me/pitinfo/

Voici le détail du flow pour récupérer, décoder et envoyer les infos de la téléinfo : (code du flow dans le second post !)

Le premier noeud récupère les trames sur le port série, le second limite le nombre de trames (sinon c’est trop !) le 3ème valide la trame (calcul de checksum) le 4ème mets tout ça en forme. Les suivants ne récupèrent qu’une certaine partie de la trame pour au final envoyer cette info dans un topic MQTT.
De l’autre côté, hassio récupère les données via des sensors MQTT.

Add :
Version pour le tarif BASE : (code dans le second post)

Puis un autre flow (code dans le second post) se charge de faire le calcul de puissance consommée par échantillons de 2 minutes :

En effet cette puissance réelle consommée basée sur l’index du compteur n’existe pas dans la téléinfo. Il faut la calculer. On fait simplement la différence entre l’index de l’instant T et de l’instant T-environ.2.minutes ce qui nous donne le nombre de Wh consommés pendant ces environ 2 minutes. Puis on divise ce nombre par le nombre de secondes écoulées entre les 2 relevés divisé par 3600 (1) (2).
Soit en gros (IndexT - IndexT-2min) / (Tps écoulé entre le relevé T et T-environ.2.minutes / 3600)
Le résultat en W est ensuite envoyé dans un topic MQTT là aussi récupéré via un sensor MQTT dans hassio.

Au final dans hassio (j’ai encore un peu de travail, c’est pas définitif) :

(1) On est en Wh (Watts heures), donc n secondes divisées par 3600 pour avoir ça en heures !
(2) Important de ne pas assumer que les trames sont pile poil distantes de 2 minutes. Quelques secondes de plus ou de moins faussent beaucoup le résultat !

Petite foot note : J’ai quand même un downside, le contrat HP/HC. En effet, pour déclencher les heures pleines/heures creuses Enedis à longtemps utilisé un truc appelé PULSADIS. Avec les linky Enedis à changé de techno pour du CPL 3. Malheuresement ils n’ont pas jugé nécessaire de synchroniser les signaux de ces 2 technos. Mon compteur Linky passe en HC à 1h20 et 12h20 alors que mon compteur sagemcom lui passe à 1h36 et 12h36. Oui, il y à 16 minutes de différence entre le signal PULSADIS et CPL… Du coup ma télérelève des indexs HP et HC et faussée.
Mais en faisant mes calculs, je me rends compte que ce contrat HP/HC n’est pas avantageux au final. Je vais donc repasser en tarif simple. Je ferai un ajout des flows pour le tarif simple. C’est ajouté pour le tarif BASE.

Suite certaines demandes voici le détail de comment récupérer les valeurs extraites de la Téléinfo dans Home Assistant via MQTT :

Dans le 1er flow qui récolte la trame et va la décoder, à la toute fin vous avez soit

  • pour les contrats HP/HC 4 indexs (HP+HC en Wh et kWh) + Puissance instantanée + Période tarifaire en cours (PTEC)
  • pour les contrats base 2 indexs (Wh et kWh) et la puissance instantanée.

Je vous donne l’exemple pour le tarif base :

Vous devez commencer par configurer un « config node » MQTT dans votre nodered :

  • Ajoutez un noeud MQTT out.
  • Cliquez sur le petit crayon juste à droite de « Add new MQTT broker »
  • Renseignez l’IP de votre broker MQTT + le port et dans l’onglet security le login et le mot de passe pour s’y connecter.

Ensuite la configuration des noeuds + sensors HA associés comme suit :

  • Le noeud MQTT pour l’index en Wh est configuré comme suit :
    image
    Donc pour récupérer cette valeur dans HA vous devez créer un sensor MQTT :
sensor:
- platform: mqtt
  name: index_edf_wh
  state_topic: "edf/index_wh"
  unit_of_measurement: "Wh"

  • Pour les kWh le noeud MQTT dans nodered :
    image
    Puis le sensor qui va bien dans HA :
- platform: mqtt
  name: index_edf_kwh
  state_topic: "edf/index_kwh"
  unit_of_measurement: "kWh"

  • Pour la puissance :
    image
    Et le sensor dans HA :
- platform: mqtt
  name: iinst_edf
  state_topic: "edf/iinst"
  unit_of_measurement: "A"

Ainsi vous pourrez créer des sensors Utility meters qui comptent votre consommation journalière, mensuelle, annuelle :

utility_meter:
#Compteur journalier
  edf_daily:
    source: sensor.index_edf_kwh
    cycle: daily
#Compteur mensuel
  edf_monthly:
    source: sensor.index_edf_kwh
    cycle: monthly
#Compteur annuel
  edf_yearly:
    source: sensor.index_edf_kwh
    cycle: yearly

Carte lovelace

entities:
  - label: Journalier
    type: section
  - entity: sensor.edf_daily
    name: Aujourd'hui
  - label: Mensuel
    type: section
  - entity: sensor.edf_monthly
    name: Mois en cours
  - label: Annuel
    type: section
  - entity: sensor.edf_yearly
    name: Année en cours
  - label: Temps réel
    type: section
  - entity: sensor.pinst_edf
    icon: 'mdi:flash'
    name: Puissance instantanée
  - entity: sensor.iinst_edf
    icon: 'mdi:flash-circle'
    name: Intensité instantanée
show_header_toggle: false
title: Compteurs consommation électrique
type: entities

Code à importer dans nodered pour avoir les flows tout faits

Flow de récup et validation des trames pour le mode HP/HC : :warning: Pensez à changer la conf des noeuds MQTT et serial !

[{"id":"86c82f25.87ce8","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":540,"wires":[]},{"id":"dc5193dd.31241","type":"function","z":"31754ffc.c5547","name":"Structure payload","func":"function isNumeric(n) { \n      return !isNaN(parseFloat(n)) && isFinite(n); \n}\n\n// Pour tous les labels \nfor (var label in msg.payload ) {\n    var value = msg.payload[label];\n    \n\t// Correction des valeurs type string en numérique \t\t\n\tif (label == \"OPTARIF\")\t{\n  \t\t// L'option tarifaire choisie (Groupe \"OPTARIF\") est codée sur 4 caractères alphanumériques \n  \t\t// J'ai pris un nombre arbitraire codé dans l'ordre ci-dessous \n  \t\t// je mets le 4eme char à 0, trop de possibilités \n      \tvalue = value.substring(0, 3);\n    \n       \tif      (value==\"BAS\") value=1;// BASE => Option Base. \n  \t\telse if (value==\"HC.\") value=2;// HC.. => Option Heures Creuses. \n  \t\telse if (value==\"EJP\") value=3;// EJP. => Option EJP. \n  \t\telse if (value==\"BBR\") value=4;// BBRx => Option Tempo\n  \t\telse value = 0;\n  \t\t\n  \t\tmsg.payload[label] = value;\n\t} else if (label==\"HHPHC\") {\n      // L'horaire heures pleines/heures creuses (Groupe \"HHPHC\") est codé par un caractère A à Y \n      // J'ai choisi de prendre son code ASCII\n      msg.payload[label] = value.charCodeAt();\n    } else if ( label == \"PTEC\") {\n      // La période tarifaire en cours (Groupe \"PTEC\"), est codée sur 4 caractères \n      // J'ai pris un nombre arbitraire codé dans l'ordre ci-dessous\n      if      (value==\"TH..\") value= 1; // Toutes les Heures. \n      else if (value==\"HC..\") value= \"Heures Creuses\"; // Heures Creuses. \n      else if (value==\"HP..\") value= \"Heures Pleines\"; // Heures Pleines. \n      else if (value==\"HN..\") value= 4; // Heures Normales. \n      else if (value==\"PM..\") value= 5; // Heures de Pointe Mobile. \n      else if (value==\"HCJB\") value= 6; // Heures Creuses Jours Bleus. \n      else if (value==\"HCJW\") value= 7; // Heures Creuses Jours Blancs (White). \n      else if (value==\"HCJR\") value= 8; // Heures Creuses Jours Rouges. \n      else if (value==\"HPJB\") value= 9; // Heures Pleines Jours Bleus. \n      else if (value==\"HPJW\") value= 10;// Heures Pleines Jours Blancs (White). \n      else if (value==\"HPJR\") value= 11;// Heures Pleines Jours Rouges. \n      else value = 0;\n      \n      msg.payload[label] = value;\n    } else if ( label == \"IINST\") {\n        delete msg.payload.IINST;\n        msg.payload.IINST = Number(value)\n    } else if ( label == \"IMAX\") {\n        delete msg.payload.IMAX;\n        msg.payload.IMAX1 = Number(value);\n    } else if ( isNumeric(value) && label != \"ADCO\" ) {\n        // Transformer les valeurs numériques\n        msg.payload[label] = Number(value);\n    }\n}\n\n// Sauvegarde dans le contexte global\ncontext.global.teleinfo = msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":560,"wires":[["f979933e.c7032","81b457bd.720e28","ca2f3cb3.ced7c","2075f662.e977ca","79d460da.de8aa","6ddb61d.7de3da","a7352aec.7cc578"]]},{"id":"bb4e5cce.d4804","type":"mqtt out","z":"31754ffc.c5547","name":"edf/index_wh","topic":"edf/index_wh","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1330,"y":580,"wires":[]},{"id":"25183aa6.a19c36","type":"mqtt out","z":"31754ffc.c5547","name":"edf/index_kwh","topic":"edf/index_kwh","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1340,"y":680,"wires":[]},{"id":"936873da.10b6c","type":"mqtt out","z":"31754ffc.c5547","name":"edf/iinst","topic":"edf/iinst","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1320,"y":780,"wires":[]},{"id":"a36e7648.2f6928","type":"serial in","z":"31754ffc.c5547","name":"","serial":"3b2a542e.d3dabc","x":90,"y":560,"wires":[["310addc1.ff9122"]]},{"id":"f979933e.c7032","type":"function","z":"31754ffc.c5547","name":"INDEX TOTAL WH","func":"var INDEX = msg.payload.HCHC + msg.payload.HCHP\n\nmsg.payload = INDEX\nreturn msg;","outputs":1,"noerr":0,"x":930,"y":560,"wires":[["2ef2da60.8a7d76"]]},{"id":"25c2fa1d.b33cf6","type":"function","z":"31754ffc.c5547","name":"valide trame","func":"// La trame complète est reçue dans 'msg'\nvar teleinfo={};\n\n// Enlever les codes début et fin de trame et récupérer les lignes 1 à 1\nvar lines = msg.payload.toString().replace(\"\\u0002\\n\",\"\").replace(\"\\r\\u0003\",\"\");\nlines = lines.split(\"\\r\\n\");\n\n// Pour chaque ligne\nfor (var line in lines) {\n\tvar i;\n  \tvar checksum = 32;\n  \t\n  \t// Recupérer le label, la valeur et la checksum\n  \t// si la checksum est un espace on le remplace par un caractère non \n  \t// autorisé en checksum (ici 's') pour eviter pb de split\n  \t// donc espace espace devient espace s\n\tvar myline = lines[line].toString().replace(\"  \",\" s\").split(\" \");\n\t\n\t// on dépile nos 3 valeurs\n\tvar check = myline.pop();\n\tvar value = myline.pop();\n\tvar label = myline.pop();\n\t\n\t// On peu repositionner la checksum à espace si c'était le cas\n\tif (check == \"s\") check = \" \";\n\n\t// Calcul de la checksum sur ce qu'on a reçu, on balaye tous les caractères\t\t\n  \tfor (i = 0; i < label.length; i++) checksum += label.charCodeAt(i);\n  \tfor (i = 0; i < value.length; i++) checksum += value.charCodeAt(i);\n \tchecksum = ((checksum%256) & 63) + 32;\n \tchecksum = String.fromCharCode(checksum);\n\t\n\t// Checksum correcte ?\n \tif (checksum == check ) {\n\t\tteleinfo[label] = value;\n\t} else {\n\t\tconsole.log(\"'%s' '%s' '%s' => Bad Checksum '%s'\", label, value, check, checksum );\n\t}\n}\nreturn [ { payload: teleinfo } ];","outputs":1,"noerr":0,"x":470,"y":560,"wires":[["dc5193dd.31241","de235fb7.a9233"]]},{"id":"2ef2da60.8a7d76","type":"rbe","z":"31754ffc.c5547","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":560,"wires":[["86c82f25.87ce8","bb4e5cce.d4804"]]},{"id":"81b457bd.720e28","type":"function","z":"31754ffc.c5547","name":"INDEX TOTAL KWH","func":"var INDEX = msg.payload.HCHC + msg.payload.HCHP\n\nmsg.payload = INDEX / 1000\nreturn msg;","outputs":1,"noerr":0,"x":940,"y":620,"wires":[["15fdcbab.7ea5c4"]]},{"id":"15fdcbab.7ea5c4","type":"rbe","z":"31754ffc.c5547","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":620,"wires":[["6b463144.db1fc","25183aa6.a19c36"]]},{"id":"6b463144.db1fc","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":640,"wires":[]},{"id":"6ddb61d.7de3da","type":"function","z":"31754ffc.c5547","name":"IINST","func":"var IINST = msg.payload.IINST\n\nmsg.payload = IINST\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":680,"wires":[["125a0354.b2905d"]]},{"id":"edc388bb.f12798","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":740,"wires":[]},{"id":"125a0354.b2905d","type":"rbe","z":"31754ffc.c5547","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":680,"wires":[["edc388bb.f12798","936873da.10b6c"]]},{"id":"310addc1.ff9122","type":"delay","z":"31754ffc.c5547","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"15","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":280,"y":560,"wires":[["25c2fa1d.b33cf6","a89a85b8.4b8098"]]},{"id":"ca2f3cb3.ced7c","type":"function","z":"31754ffc.c5547","name":"INDEX HC KWH","func":"var INDEX = msg.payload.HCHC\n\nmsg.payload = INDEX / 1000\nreturn msg;","outputs":1,"noerr":0,"x":920,"y":500,"wires":[["2002cc8b.516b44"]]},{"id":"2075f662.e977ca","type":"function","z":"31754ffc.c5547","name":"INDEX HP KWH","func":"var INDEX = msg.payload.HCHP\n\nmsg.payload = INDEX / 1000\nreturn msg;","outputs":1,"noerr":0,"x":920,"y":440,"wires":[["1cf856c6.bdfdb9","1d37c2c6.46802d"]]},{"id":"1d37c2c6.46802d","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":340,"wires":[]},{"id":"586cc235.f9756c","type":"mqtt out","z":"31754ffc.c5547","name":"edf/index_hp_kwh","topic":"edf/index_hp_kwh","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1350,"y":380,"wires":[]},{"id":"47a40206.b69c8c","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":440,"wires":[]},{"id":"d1cd6f9c.39734","type":"mqtt out","z":"31754ffc.c5547","name":"edf/index_hc_wh","topic":"edf/index_hc_kwh","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1350,"y":480,"wires":[]},{"id":"2002cc8b.516b44","type":"rbe","z":"31754ffc.c5547","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":500,"wires":[["d1cd6f9c.39734","47a40206.b69c8c"]]},{"id":"1cf856c6.bdfdb9","type":"rbe","z":"31754ffc.c5547","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":440,"wires":[["586cc235.f9756c","1d37c2c6.46802d"]]},{"id":"79d460da.de8aa","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":670,"y":460,"wires":[]},{"id":"de235fb7.a9233","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":470,"y":460,"wires":[]},{"id":"a89a85b8.4b8098","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":290,"y":460,"wires":[]},{"id":"a7352aec.7cc578","type":"function","z":"31754ffc.c5547","name":"PTEC","func":"var PTEC = msg.payload.PTEC\n\nmsg.payload = PTEC\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":740,"wires":[["78f8cd7e.408f24"]]},{"id":"523f3dd0.734f34","type":"mqtt out","z":"31754ffc.c5547","name":"edf/ptec","topic":"edf/ptec","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1320,"y":880,"wires":[]},{"id":"941b507d.8f041","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":840,"wires":[]},{"id":"78f8cd7e.408f24","type":"rbe","z":"31754ffc.c5547","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":740,"wires":[["941b507d.8f041","523f3dd0.734f34"]]},{"id":"7512dcc2.be07d4","type":"mqtt-broker","z":"","name":"mosquitto","broker":"192.168.1.3","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"3b2a542e.d3dabc","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"1200","databits":"7","parity":"even","stopbits":"1","waitfor":"","newline":"0x3","bin":"false","out":"char","addchar":"","responsetimeout":"10000"}]

Flow de récup et validation des trames pour le mode BASE : :warning: Pensez à changer la conf des noeuds MQTT et serial !

[{"id":"6928a039.118cf","type":"debug","z":"6834f0bf.c570c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":440,"wires":[]},{"id":"3014527a.81e22e","type":"function","z":"6834f0bf.c570c","name":"Structure payload","func":"function isNumeric(n) { \n      return !isNaN(parseFloat(n)) && isFinite(n); \n}\n\n// Pour tous les labels \nfor (var label in msg.payload ) {\n    var value = msg.payload[label];\n    \n\t// Correction des valeurs type string en numérique \t\t\n\tif (label == \"OPTARIF\")\t{\n  \t\t// L'option tarifaire choisie (Groupe \"OPTARIF\") est codée sur 4 caractères alphanumériques \n  \t\t// J'ai pris un nombre arbitraire codé dans l'ordre ci-dessous \n  \t\t// je mets le 4eme char à 0, trop de possibilités \n      \tvalue = value.substring(0, 3);\n    \n       \tif      (value==\"BAS\") value=1;// BASE => Option Base. \n  \t\telse if (value==\"HC.\") value=2;// HC.. => Option Heures Creuses. \n  \t\telse if (value==\"EJP\") value=3;// EJP. => Option EJP. \n  \t\telse if (value==\"BBR\") value=4;// BBRx => Option Tempo\n  \t\telse value = 0;\n  \t\t\n  \t\tmsg.payload[label] = value;\n\t} else if (label==\"HHPHC\") {\n      // L'horaire heures pleines/heures creuses (Groupe \"HHPHC\") est codé par un caractère A à Y \n      // J'ai choisi de prendre son code ASCII\n      msg.payload[label] = value.charCodeAt();\n    } else if ( label == \"PTEC\") {\n      // La période tarifaire en cours (Groupe \"PTEC\"), est codée sur 4 caractères \n      // J'ai pris un nombre arbitraire codé dans l'ordre ci-dessous\n      if      (value==\"TH..\") value= 1; // Toutes les Heures. \n      else if (value==\"HC..\") value= \"Heures Creuses\"; // Heures Creuses. \n      else if (value==\"HP..\") value= \"Heures Pleines\"; // Heures Pleines. \n      else if (value==\"HN..\") value= 4; // Heures Normales. \n      else if (value==\"PM..\") value= 5; // Heures de Pointe Mobile. \n      else if (value==\"HCJB\") value= 6; // Heures Creuses Jours Bleus. \n      else if (value==\"HCJW\") value= 7; // Heures Creuses Jours Blancs (White). \n      else if (value==\"HCJR\") value= 8; // Heures Creuses Jours Rouges. \n      else if (value==\"HPJB\") value= 9; // Heures Pleines Jours Bleus. \n      else if (value==\"HPJW\") value= 10;// Heures Pleines Jours Blancs (White). \n      else if (value==\"HPJR\") value= 11;// Heures Pleines Jours Rouges. \n      else value = 0;\n      \n      msg.payload[label] = value;\n    } else if ( label == \"IINST\") {\n        delete msg.payload.IINST;\n        msg.payload.IINST = Number(value)\n    } else if ( label == \"IMAX\") {\n        delete msg.payload.IMAX;\n        msg.payload.IMAX1 = Number(value);\n    } else if ( isNumeric(value) && label != \"ADCO\" ) {\n        // Transformer les valeurs numériques\n        msg.payload[label] = Number(value);\n    }\n}\n\n// Sauvegarde dans le contexte global\ncontext.global.teleinfo = msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":670,"y":560,"wires":[["f7b399b4.fe1048","beedb3e3.ddcb3","4b54c8ee.4a6428","ec2451b3.dcbb7"]]},{"id":"fbbe122e.9d309","type":"mqtt out","z":"6834f0bf.c570c","name":"edf/index_wh","topic":"edf/index_wh","qos":"","retain":"true","broker":"f06b0b28.42ba68","x":1330,"y":480,"wires":[]},{"id":"2a41b6e9.cb5c9a","type":"mqtt out","z":"6834f0bf.c570c","name":"edf/index_kwh","topic":"edf/index_kwh","qos":"","retain":"true","broker":"f06b0b28.42ba68","x":1340,"y":580,"wires":[]},{"id":"58383bac.be6804","type":"mqtt out","z":"6834f0bf.c570c","name":"edf/iinst","topic":"edf/iinst","qos":"","retain":"true","broker":"f06b0b28.42ba68","x":1320,"y":680,"wires":[]},{"id":"75f15514.01245c","type":"serial in","z":"6834f0bf.c570c","name":"","serial":"40ca77b1.eab5e8","x":90,"y":560,"wires":[["2c0ea20f.204abe"]]},{"id":"f7b399b4.fe1048","type":"function","z":"6834f0bf.c570c","name":"INDEX WH","func":"var INDEX = msg.payload.BASE\n\nmsg.payload = INDEX\nreturn msg;","outputs":1,"noerr":0,"x":910,"y":500,"wires":[["7a3bf371.a625ec"]]},{"id":"35183b6f.805564","type":"function","z":"6834f0bf.c570c","name":"valide trame","func":"// La trame complète est reçue dans 'msg'\nvar teleinfo={};\n\n// Enlever les codes début et fin de trame et récupérer les lignes 1 à 1\nvar lines = msg.payload.toString().replace(\"\\u0002\\n\",\"\").replace(\"\\r\\u0003\",\"\");\nlines = lines.split(\"\\r\\n\");\n\n// Pour chaque ligne\nfor (var line in lines) {\n\tvar i;\n  \tvar checksum = 32;\n  \t\n  \t// Recupérer le label, la valeur et la checksum\n  \t// si la checksum est un espace on le remplace par un caractère non \n  \t// autorisé en checksum (ici 's') pour eviter pb de split\n  \t// donc espace espace devient espace s\n\tvar myline = lines[line].toString().replace(\"  \",\" s\").split(\" \");\n\t\n\t// on dépile nos 3 valeurs\n\tvar check = myline.pop();\n\tvar value = myline.pop();\n\tvar label = myline.pop();\n\t\n\t// On peu repositionner la checksum à espace si c'était le cas\n\tif (check == \"s\") check = \" \";\n\n\t// Calcul de la checksum sur ce qu'on a reçu, on balaye tous les caractères\t\t\n  \tfor (i = 0; i < label.length; i++) checksum += label.charCodeAt(i);\n  \tfor (i = 0; i < value.length; i++) checksum += value.charCodeAt(i);\n \tchecksum = ((checksum%256) & 63) + 32;\n \tchecksum = String.fromCharCode(checksum);\n\t\n\t// Checksum correcte ?\n \tif (checksum == check ) {\n\t\tteleinfo[label] = value;\n\t} else {\n\t\tconsole.log(\"'%s' '%s' '%s' => Bad Checksum '%s'\", label, value, check, checksum );\n\t}\n}\nreturn [ { payload: teleinfo } ];","outputs":1,"noerr":0,"x":470,"y":560,"wires":[["3014527a.81e22e","c7c900a6.c32dc"]]},{"id":"7a3bf371.a625ec","type":"rbe","z":"6834f0bf.c570c","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":500,"wires":[["6928a039.118cf","fbbe122e.9d309"]]},{"id":"beedb3e3.ddcb3","type":"function","z":"6834f0bf.c570c","name":"INDEX KWH","func":"var INDEX = msg.payload.BASE\n\nmsg.payload = INDEX / 1000\nreturn msg;","outputs":1,"noerr":0,"x":910,"y":560,"wires":[["13648db0.51fa62"]]},{"id":"13648db0.51fa62","type":"rbe","z":"6834f0bf.c570c","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":560,"wires":[["26a4a917.34de86","2a41b6e9.cb5c9a"]]},{"id":"26a4a917.34de86","type":"debug","z":"6834f0bf.c570c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":540,"wires":[]},{"id":"ec2451b3.dcbb7","type":"function","z":"6834f0bf.c570c","name":"IINST","func":"var IINST = msg.payload.IINST\n\nmsg.payload = IINST\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":620,"wires":[["a86647d.43bcab8"]]},{"id":"d8850e24.32a2e","type":"debug","z":"6834f0bf.c570c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1310,"y":640,"wires":[]},{"id":"a86647d.43bcab8","type":"rbe","z":"6834f0bf.c570c","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":1130,"y":620,"wires":[["d8850e24.32a2e","58383bac.be6804"]]},{"id":"2c0ea20f.204abe","type":"delay","z":"6834f0bf.c570c","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"15","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":280,"y":560,"wires":[["35183b6f.805564","95b88432.b45b78"]]},{"id":"4b54c8ee.4a6428","type":"debug","z":"6834f0bf.c570c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":670,"y":460,"wires":[]},{"id":"c7c900a6.c32dc","type":"debug","z":"6834f0bf.c570c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":470,"y":460,"wires":[]},{"id":"95b88432.b45b78","type":"debug","z":"6834f0bf.c570c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":290,"y":460,"wires":[]},{"id":"f06b0b28.42ba68","type":"mqtt-broker","z":"","name":"mosquitto","broker":"192.168.1.3","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"40ca77b1.eab5e8","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"1200","databits":"7","parity":"even","stopbits":"1","waitfor":"","newline":"0x3","bin":"false","out":"char","addchar":"","responsetimeout":"10000"}]

Code du flow du calcul de puissance instantanée :

[{"id":"5d80b82d.bdc808","type":"api-get-history","z":"31754ffc.c5547","name":"index edf -2mn","server":"7b44b840.df2a18","startdate":"","enddate":"","entityid":"sensor.index_edf_wh","entityidtype":"is","useRelativeTime":true,"relativeTime":"2m","flatten":true,"output_type":"array","output_location_type":"msg","output_location":"payload","x":380,"y":160,"wires":[["6a20a0c2.f9be1"]]},{"id":"5691f229.95948c","type":"api-current-state","z":"31754ffc.c5547","name":"index edf now","server":"7b44b840.df2a18","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":true,"entity_id":"sensor.index_edf_wh","state_type":"num","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":380,"y":260,"wires":[["5fc9af9.c7d3a5"]]},{"id":"6a20a0c2.f9be1","type":"function","z":"31754ffc.c5547","name":"","func":"msg2 = {};\nmsg2.payload = {};\ntopic = 'old';\nmsg2.payload.old_state = parseFloat(msg.payload[0].state);\nmsg2.payload.old_date = Date.parse(msg.payload[0].last_changed)/1000|0;\nmsg2.topic = topic;\nreturn msg2;","outputs":1,"noerr":0,"x":550,"y":160,"wires":[["7e6fce86.3e948","95675d11.94cf8"]]},{"id":"7e6fce86.3e948","type":"join","z":"31754ffc.c5547","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":200,"wires":[["18c65f3.5663da1"]]},{"id":"18c65f3.5663da1","type":"function","z":"31754ffc.c5547","name":"","func":"old = msg.payload.old.old_state;\ncurrent = msg.payload.new.new_state;\ndiff_index = current - old;\ndiff_seconds = msg.payload.new.new_date - msg.payload.old.old_date;\ncoeff = diff_seconds / 3600\nconso = diff_index / coeff\nconso = Math.round(conso*100)/100\nmsg2 = {};\nmsg2.payload = {};\nmsg2.payload.conso = conso;\nreturn msg2;","outputs":1,"noerr":0,"x":870,"y":200,"wires":[["3c07458d.aecd7a"]]},{"id":"78162bff.2c2ee4","type":"inject","z":"31754ffc.c5547","name":"","topic":"","payload":"","payloadType":"date","repeat":"120","crontab":"","once":true,"onceDelay":"30","x":210,"y":220,"wires":[["5d80b82d.bdc808","5691f229.95948c"]]},{"id":"5fc9af9.c7d3a5","type":"function","z":"31754ffc.c5547","name":"","func":"msg3 = {};\nmsg3.payload = {};\ntopic = 'new';\nmsg3.payload.new_state = parseFloat(msg.payload);\nmsg3.payload.new_date = Date.parse(msg.data.last_changed)/1000|0;\nmsg3.topic = topic;\nreturn msg3;","outputs":1,"noerr":0,"x":550,"y":260,"wires":[["7e6fce86.3e948","f2d3db47.03d508"]]},{"id":"98252990.1417f8","type":"mqtt out","z":"31754ffc.c5547","name":"puissance instantanée","topic":"edf/puissance_inst","qos":"","retain":"true","broker":"7512dcc2.be07d4","x":1380,"y":200,"wires":[]},{"id":"3c07458d.aecd7a","type":"function","z":"31754ffc.c5547","name":"transforme en nombre","func":"\nmsg.payload= parseFloat(msg.payload.conso);\n\nreturn msg;\n\n\n","outputs":1,"noerr":0,"x":1120,"y":200,"wires":[["98252990.1417f8"]]},{"id":"95675d11.94cf8","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":685,"y":115,"wires":[]},{"id":"f2d3db47.03d508","type":"debug","z":"31754ffc.c5547","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":690,"y":280,"wires":[]},{"id":"7b44b840.df2a18","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open"},{"id":"7512dcc2.be07d4","type":"mqtt-broker","z":"","name":"mosquitto","broker":"192.168.1.3","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]
2 J'aimes

j’adore !! en gros pas besoin d’attendre mon linky?

En gros ça dépend de ton compteur d’aujourd’hui. C’est un mécanique ? Pas de sortie téléinfo.
Un électronique ? Alors tu peux mettre ça en place.
La différence avec le composant linky existant, c’est que ce composant va chercher les datas sur le site Enedis. Ces données ne sont pas en temps réel (24h de délai). Là c’est du temps réel. Le compteur donne les infos toutes les secondes ! Je mets la plaque à induction en boost, et je le vois tout de suite sur les courbes !

Mais même une fois un linky posé, tu as aussi les bornes de téléinfo dessus donc c’est possible de se brancher sur le linky. Moi je ne l’ai pas fait à causes de contraintes physiques (gaine écrasée).

actuellement un mécanique avec la roue crantée… :confused:
si je mets le sagem entre mon compteur méca et mon tableau j’aurais la sortie teleinfo avec la conso en temps réelle?

Yes :slight_smile:
C’est bien ça. Mais gaffe hein ! Acheter un compteur de qualité. Et ne pas faire mumuse si on ne sait pas exactement ce qu’on fait. C’est dangereux. Et respecter les normes électriques (sections et longueurs de câbles, isolation…)

yesss tu as raison de le dire, faut pas faire n’importe quoi avec ca !!! :wink: pas sur que le consuel soit fan lol et puis on s’improvise pas l’electricien :wink:
du coup je vais faire ca chez un voisin d’abord mouhahahahaha

Du lourd ! Merci pour le partage Mr @SNoof.