.theia | ||
docs | ||
.gitignore | ||
LICENSE | ||
linky_tic.ino | ||
ota.cpp | ||
ota.h | ||
README.md | ||
secret-generic.h | ||
serial.h | ||
tic.cpp | ||
tic.h |
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).