Go to file
2025-04-30 00:06:33 +02:00
.theia Add OTA through ElegantOTA lite. OTA is accessible via IP_ADRESS/update 2025-04-13 23:38:36 +02:00
docs implment CRCcheck 2025-04-26 23:55:28 +02:00
.gitignore initiate MQTT interface 2025-04-14 22:28:49 +02:00
LICENSE Initial commit 2025-03-24 22:06:58 +01:00
linky_tic.ino enhance valus update and mqtt refresh. implements status in mqtt. Confirm horodate OK. Update parameter list 2025-04-29 00:06:24 +02:00
ota.cpp initiate MQTT interface 2025-04-14 22:28:49 +02:00
ota.h initiate MQTT interface 2025-04-14 22:28:49 +02:00
README.md complete README with sleepmode 2025-03-25 22:50:45 +01:00
secret-generic.h Add OTA through ElegantOTA lite. OTA is accessible via IP_ADRESS/update 2025-04-13 23:38:36 +02:00
serial.h Initial commit 2025-03-24 22:11:49 +01:00
tic.cpp add new parameters CCANS and CCAIN 2025-04-30 00:06:33 +02:00
tic.h add new parameters CCANS and CCAIN 2025-04-30 00:06:33 +02:00

Linky tic

Interface basique pour lire les données TIC d'un compteur Linky et les partager au format JSON via un ESP8266/NodeMCU. L'ensemble est fonctionnel avec Home Assistant en définissant une interface REST.

Configuration

À partir du fichier secret-generic.h, créez un fichier secret.h pour définir les identifiants et mots de passe du Wi-Fi.

// ssid and passPhrase can be used when compiling for a specific environment as a 2. option.
// add you wifi network name and PassPhrase or use WiFi Manager
#ifndef STASSID
#define STASSID "Wifi_Id"
#define STAPSK "Wifi_pwd"
#endif

const char *ssid = STASSID;
const char *passPhrase = STAPSK;

Le code est prévu pour un Linky en mode standard. Il devrait également fonctionner en mode historique en changeant la vitesse du port (1500 bps en historique, 9600 bps en standard).

Interface

Un simple optocoupleur suffit. Le schéma disponible sur https://hallard.me/demystifier-la-teleinfo/ fonctionne chez moi (sans ajout du transistor).

Documents

Enedis-NOI-CPT_54E version 3 (01/06/2018)

Intégration dans Home Assistant

Les informations Linky sont récupérées en définissant une interface REST. Pour faciliter la lecture du fichier configuration.yaml, j'ai intégré la définition dans un fichier spécifique que j'appelle via la commande :

rest: !include NOM_FICHIER.yaml

Le contenu du fichier de configuration REST est présenté ci-dessous. Remplacez ADRESSE_IP par l'adresse IP de l'ESP8266 (ou son chemin réseau si le DNS est correctement configuré).
Dans mon cas, le fichier contient de nombreux paramètres, mais il peut être simplifié pour se concentrer sur l'essentiel, comme le suivi de la consommation. Étant en triphasé, je surveille la consommation et la puissance sur chaque phase. Ayant des panneaux solaires, je contrôle également l'injection d'énergie. De plus, en participant à l'"effacement jour de pointe", je vérifie le tarif pour adapter ma domotique aux conditions actuelles.
Les informations de puissance et de courant sont scannées toutes les 30 secondes, tandis que les informations tarifaires le sont toutes les minutes.
Note : Pour cette utilisation, je trouve l'interface REST plus simple à mettre en œuvre que MQTT (ou d'autres protocoles). Modifier la fréquence de scan se fait facilement dans la configuration de Home Assistant. Cependant, la solution MQTT est aussi pertinente sur certains aspects.

  - scan_interval: 30
    resource: http://ADRESSE_IP/ticbasic
    sensor:
      - name: "Index Conso totale"
        value_template: "{{ value_json.EAST | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 01 Conso"
        value_template: "{{ value_json.EASF01 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 02 Conso"
        value_template: "{{ value_json.EASF02 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 03 Conso"
        value_template: "{{ value_json.EASF03 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 04 Conso"
        value_template: "{{ value_json.EASF04 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Energie injectee total"
        value_template: "{{ value_json.EAIT | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 01 Generation"
        value_template: "{{ value_json.ERQ1 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 02 Generation"
        value_template: "{{ value_json.ERQ2 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 03 Generation"
        value_template: "{{ value_json.ERQ3 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Index 04 Generation"
        value_template: "{{ value_json.ERQ4 | int / 1000 | round(1) }}"
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
      - name: "Puissance instantanée injectée"
        value_template: "{{ value_json.SINSTI | int / 1000 | round(1) }}"
        unit_of_measurement: VA
        device_class: energy
        state_class: measurement
      - name: "Courant Efficace Phase 1"
        value_template: "{{ value_json.IRMS1 }}"
        unit_of_measurement: A
        device_class: current
        state_class: measurement
      - name: "Courant Efficace Phase 2"
        value_template: "{{ value_json.IRMS2 }}"
        unit_of_measurement: A
        device_class: current
        state_class: measurement
      - name: "Courant Efficace Phase 3"
        value_template: "{{ value_json.IRMS3 }}"
        unit_of_measurement: A
        device_class: current
        state_class: measurement
      - name: "Tension Efficace Phase 1"
        value_template: "{{ value_json.URMS1 }}"
        unit_of_measurement: V
        device_class: voltage
        state_class: measurement
      - name: "Tension Efficace Phase 2"
        value_template: "{{ value_json.URMS2 }}"
        unit_of_measurement: V
        device_class: voltage
        state_class: measurement
      - name: "Tension Efficace Phase 3"
        value_template: "{{ value_json.URMS3 }}"
        unit_of_measurement: V
        device_class: voltage
        state_class: measurement
      - name: "Puissance apparente totale conso"
        value_template: "{{ value_json.SINSTS | round(1) }}"
        unit_of_measurement: VA
        device_class: apparent_power
        state_class: measurement
      - name: "Puissance apparente Phase 1 conso"
        value_template: "{{ value_json.SINSTS1 | round(1) }}"
        unit_of_measurement: VA
        device_class: apparent_power
        state_class: measurement
      - name: "Puissance apparente Phase 2 conso"
        value_template: "{{ value_json.SINSTS2 | round(1) }}"
        unit_of_measurement: VA
        device_class: apparent_power
        state_class: measurement
      - name: "Puissance apparente Phase 3 conso"
        value_template: "{{ value_json.SINSTS3 | round(1) }}"
        unit_of_measurement: VA
        device_class: apparent_power
        state_class: measurement
  - scan_interval: 10
    resource: http://ADRESSE_IP/ticdata
    sensor:
      - unique_id: Elec_Tarif_Code
        name: "Code Tarif"
        value_template: "{{ value_json.NTARF }}"
  - scan_interval: 60
    resource: http://ADRESSE_IP/ticdata
    sensor:
      - unique_id: Elec_Tarif
        name: "Tarif"
        value_template: "{{ value_json.LTARF }}"
      - name: "Message 1"
        value_template: "{{ value_json.MSG1 }}"
      - name: "Message 2"
        value_template: "{{ value_json.MSG2 }}"

Compilation

J'utilise Arduino IDE.
Il faut ajouter http://arduino.esp8266.com/stable/package_esp8266com_index.json dans les paramétres.
Ensuite, sélectionner la board "Noce MCU 1.0" (ou autre suivant votre technologie).

Configuration

La liste des paramètres à récupérer est définie dans tic.h sous SelectedEtiquette[NB_ETIQUETTE]. Il vous faudra aussi mettre à jour NB_ETIQUETTE.
Les étiquettes sont celles définies dans le document ENEDIS.
L'objectif initial de cette liste est de n'inclure dans le JSON que les informations pertinentes, permettant ainsi de gagner quelques millisecondes de traitement, quelques kilo-octets de données et quelques milliwatts de consommation. Bien que le JSON puisse contenir toutes les informations lues, cela n'est pas nécessairement utile pour un utilisateur standard, car jusqu'à 50 % des champs peuvent être vides ou sans réelle utilité domotique.
En résumé, vous pouvez adapter cette liste selon vos besoins.

Mode sleep

L'ESP est mis en mode deep sleep, via la fonction goToDeepSleep, pendant un temps 'sleepDuration' configurable. L'ESP8266 se réveille ainsi ériodiquement pour vérifier s'il y a des requêtes en attente. Cette approche permet de réduire la consommation d'énergie en mettant l'ESP8266 en veille lorsqu'il n'est pas utilisé.
Attention à bien paramétrer le 'timeout' et le 'scan_interval' dans Home Assistant ainsi que le 'sleepDuration' pour ne pas avoir de timeout intempestif.
La configuration par défaut (5 secondes) ne demande pas de modification du 'timeout' de Home Assistant (10 secondes par défault).
La mise en place du deep sleep occasione un délai de réponse (ici, 5 secondes au max), faisant apparaître un 'jitter'. J'estime qu'une valeur 'sleepDuration' entre 10 et 20% du scan_interval est approprié (sachant que le refresh du Linky est de l'ordre de la seconde).