EDF LINKY + ESP8266

Moderator: leecollings

Post Reply
sebitop
Posts: 69
Joined: Sunday 08 June 2014 20:31
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Toulouse France
Contact:

EDF LINKY + ESP8266

Post by sebitop »

Hi all,

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
2024 Linky Domoticz_.jpg
2024 Linky Domoticz_.jpg (56.26 KiB) Viewed 1038 times
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&param=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();
  }
}
the code parses the LINKY frame and detects the SINSTS value (live consumption) and SINSTI (live injection)
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
domoticz on Raspberry Pi + RFXcom LAN moded + wifi
Blyss / DI.O / homemade / ESP / wemos
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests