Just wanted to share a DIY hardware + arduino code I made to retreieve the power consumption + power injection (in case of solar panel production) from the french EDF LINKY electric counter
I struggled to get this kind of project on internet so decided to create my version which now workd like a charm since several weeks
Step 1:
in order to use the following script you need to request the STANDARD mode to EDF
by default HISTORIQUE mode is activated (I created also a script for HISTORIQUE mode but STANDARD works better)
the STANDARD mode offers a more precise measure and allow to retreive the injection live value (if you produce energy with solar panels)
to request this just log on EDF website and ask for this change, it tooks me 2 days to get it done
Step 2:
then I used an ESP8266 on which I plugged an optocoupler LTV 814 + 2 leds
the LTV optocoupler can be found on aliexpress at 1 to 2€ for 10 parts
the hardware is conected to the I1 I2 on the LINKY counter
Step 3:
on domoticz you need to create 2 dummy devices one for consumption one for injection
Step 4:
then I created the following INO code
you just need to update it with your data and send it to your ESP8266 using the ARDUINO IDE interface
Code: Select all
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <SoftwareSerial.h>
// ** WIFI à AJUSTER **
const char* ssid = "XXXX";
const char* password = "XXXXX";
const bool IPfixe = true;
IPAddress local_IP(192, 168, 0, XX);
IPAddress gateway(192, 168, 0, XX);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);
//linky
const char* host = "192.168.0.XX";
const int httpPort = 8080;
const int idxConso = 1636;
const int idxInject = 1645;
int check = 0;
#define RX_PIN D6
#define TX_PIN D5
#define LED1_PIN D1
#define LED2_PIN D7
SoftwareSerial teleinfoSerial(RX_PIN, TX_PIN);
void setup() {
Serial.print("setup");
Serial.begin(115200);
teleinfoSerial.begin(9600, SWSERIAL_7E1);
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
// Initialiser les LEDs
digitalWrite(LED1_PIN, HIGH);
digitalWrite(LED2_PIN, HIGH);
// Configuration IP statique et connexion WiFi commentées
if (IPfixe) {
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
digitalWrite(LED1_PIN, LOW);
digitalWrite(LED2_PIN, LOW);
}
void processFrame(String frame) {
// Traitement de la valeur SINSTS
int posSINSTS = frame.indexOf("SINSTS\t");
if (posSINSTS != -1) {
int endPos = frame.indexOf("\t", posSINSTS + 7);
if (endPos == -1) {
endPos = frame.length();
}
String valueString = frame.substring(posSINSTS + 7, endPos);
long sinstsValue = valueString.toInt();
// Afficher la valeur de sinstsValue dans le Moniteur Série
Serial.print("SINSTS Value: ");
Serial.println(sinstsValue);
envoiaDomoticz(sinstsValue, idxConso);
digitalWrite(LED2_PIN, HIGH);
delay(1000);
digitalWrite(LED2_PIN, LOW);
}
// Traitement de la valeur SINSTI (s'il existe)
int posSINSTI = frame.indexOf("SINSTI\t");
if (posSINSTI != -1) {
int endPos = frame.indexOf("\t", posSINSTI);
String valueString = frame.substring(posSINSTI + 7, endPos);
long sinstiValue = valueString.toInt();
// Afficher la valeur de sinstiValue dans le Moniteur Série
Serial.print("SINSTI Value: ");
Serial.println(sinstiValue);
envoiaDomoticz(sinstiValue, idxInject);
digitalWrite(LED2_PIN, HIGH);
delay(1000);
digitalWrite(LED2_PIN, LOW);
}
delay(15000);
}
void envoiaDomoticz(int PW, int idxPower) {
// on remet check a zero
check = 0;
//Fonction pour envoyer les données à Domoticz commentée
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
WiFiClient client;
String url = "http://" + String(host) + ":" + String(httpPort) + "/json.htm?type=command¶m=udevice&idx=" + String(idxPower) + "&nvalue=0&svalue=" + String(PW) + ";0";
http.begin(client, url);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("HTTP GET success, code: %d\n", httpCode);
} else {
Serial.printf("HTTP GET failed, code: %d\n", httpCode);
}
http.end();
}
}
void loop() {
static bool inFrame = false;
static String frameBuffer = "";
while (teleinfoSerial.available()) {
char c = teleinfoSerial.read();
if (c == 0x02) { // Début de trame
inFrame = true;
frameBuffer = "";
Serial.println("Début de trame détecté"); // Indiquer le début de la trame
digitalWrite(LED1_PIN, HIGH); // Allumer LED1 au début de la trame
check = check +1;
} else if (c == 0x03) { // Fin de trame
if (inFrame) {
inFrame = false;
Serial.println("Fin de trame détectée"); // Indiquer la fin de la trame
Serial.print("Trame complète : ");
Serial.println(frameBuffer); // Afficher la trame complète
digitalWrite(LED1_PIN, LOW); // Éteindre LED1 à la fin de la trame
// Appeler la fonction de traitement de la trame ici si nécessaire
processFrame(frameBuffer);
}
} else if (inFrame) {
frameBuffer += c; // Ajouter le caractère à la trame
}
}
//delay(10); // Ajouter un petit délai pour stabiliser la lecture série
//Vérification de la connexion WiFi commentée
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
ESP.restart();
}
if (check > 20){
ESP.restart();
}
}
once it detects the frame the yellow led turns on and turn off as soon as the frame end is detected
once the complete frame is retrieved the code gets the 2 values and send them to domoticz
each time a value is sent to domoticz a blue led turns on
the rest are tests to ensure the robustness of the code
feel free to ask if you need any more info or help regarding this code
hope it will help you