Skip to content

LORA Linky

reichart edited this page Aug 23, 2026 · 13 revisions

8 dépôts github : exemples-de-montages festisol CROUS-micro-python piano visio anumby jouets developpement-voiture raspberry-pico Blog ateliers numériques Repair Café d'Orsay

Comment transmettre avec LORA les données TIC de Linky ? Il existe des solutions domotiques Zeegbee ; à nous de jouer !

image

couplage esp32 avec LINKY

https://github.com/arnaudrco/exemples/wiki/Relever-sa-comsommation-LINKY-avec-un-simple-esp

Il existe maintenant des modules tout pret comme le Denky D4

image

https://hallard.me/pitinfov12/

Emetteur

#include <LoRa.h>

#define TIC_RX 16 #define LORA_SS 5 #define LORA_RST 14 #define LORA_DIO0 26 #define LORA_FREQ 433100000 // 433.100 MHz

HardwareSerial TicSerial(2);

long EAST = 0; // Index total Wh int SINSTS = 0; // Puissance apparente instantanée VA int IRMS1 = 0; // Courant A int URMS1 = 0; // Tension V String PTEC = "";

String buffer = ""; unsigned long lastTx = 0;

bool checkChecksum(String &line) { // Format: LABEL\tVALUE\tCHECKSUM int len = line.length(); if (len < 4) return false; char chk = line.charAt(len - 2); // avant \r // Calcul checksum Linky STANDARD int sum = 0; for (int i = 0; i < len - 2; i++) { if (line.charAt(i) != '\t' && line.charAt(i) != '\r' && line.charAt(i) != '\n') { sum += line.charAt(i); } else if (line.charAt(i) == '\t') { sum += 9; } } sum = (sum % 64) + 32; return (sum == chk); }

void parseLine(String line) { line.trim(); if (line.length() < 5 || !checkChecksum(line)) return;

// On coupe par tabulation int t1 = line.indexOf('\t'); int t2 = line.indexOf('\t', t1 + 1); String label = line.substring(0, t1); String value = line.substring(t1 + 1, t2);

if (label == "EAST") EAST = value.toInt(); else if (label == "SINSTS") SINSTS = value.toInt(); else if (label == "IRMS1") IRMS1 = value.toInt(); else if (label == "URMS1") URMS1 = value.toInt(); else if (label == "PTEC") PTEC = value; }

void setup() { Serial.begin(115200); // CRITIQUE pour STANDARD: 9600 7E1 TicSerial.begin(9600, SERIAL_7E1, TIC_RX, -1);

LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0); LoRa.begin(LORA_FREQ); LoRa.setSpreadingFactor(10); LoRa.setSignalBandwidth(125E3); LoRa.setTxPower(10); // 10 dBm légal FR 433MHz

Serial.println("Linky STANDARD Ready"); }

void loop() { while (TicSerial.available()) { char c = TicSerial.read(); buffer += c; if (c == '\n') { parseLine(buffer); buffer = ""; } }

if (millis() - lastTx > 45000 && SINSTS > 0) { // Payload binaire ultra compact: 10 bytes au lieu de 60 en JSON // On envoie: EAST(4 bytes) + SINSTS(2) + IRMS1(1) + URMS1(1) // Ou en JSON si tu préfères pour debug: String json = "{"EAST":" + String(EAST) + ","S":" + String(SINSTS) + ","I":" + String(IRMS1) + ","U":" + String(URMS1) + ","P":"" + PTEC + ""}";

LoRa.beginPacket();
LoRa.print(json);
LoRa.endPacket();

Serial.println("TX LoRa: " + json + " RSSI linky OK");
lastTx = millis();

} }

Récepteur

#include <LoRa.h>

#define LORA_SCK 18 #define LORA_MISO 19 #define LORA_MOSI 23 #define LORA_SS 5 #define LORA_RST 14 #define LORA_DIO0 26 #define LORA_FREQ 433100000 // 433.1 MHz pour la France, 10mW max

// TIC Linky sur Serial2 #define TIC_RX 16 #define TIC_TX 17 // pas utilisé mais obligatoire

String ticBuffer = ""; long lastSend = 0;

// Variables que tu veux extraire long papp = 0; long iinst = 0; long base = 0; String ptec = "";

void setup() { Serial.begin(115200); Serial2.begin(9600, SERIAL_8N1, TIC_RX, TIC_TX); // Mets 1200 si Linky en HISTORIQUE // Serial2.begin(1200, SERIAL_7E1, TIC_RX, TIC_TX); // pour HISTORIQUE

SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_SS); LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0); if (!LoRa.begin(LORA_FREQ)) { Serial.println("LoRa FAIL"); while(1); }

LoRa.setSpreadingFactor(10); LoRa.setSignalBandwidth(125E3); LoRa.setTxPower(10); // 10 dBm = légal en 433MHz FR Serial.println("Emetteur Linky LoRa OK"); }

void loop() { // 1. Lire TIC while (Serial2.available()) { char c = Serial2.read(); ticBuffer += c; if (c == '\n') { parseTIC(ticBuffer); ticBuffer = ""; } }

// 2. Envoyer en LoRa toutes les 30s if (millis() - lastSend > 30000 && papp!= 0) { String json = "{"PAPP":" + String(papp) + ","IINST":" + String(iinst) + ","BASE":" + String(base) + "}";

LoRa.beginPacket();
LoRa.print(json);
LoRa.endPacket();

Serial.println("LoRa TX: " + json);
lastSend = millis();

} }

void parseTIC(String line) { // Ex: "PAPP 00320 $" ou "SINSTS 00320" line.trim(); if (line.startsWith("PAPP") || line.startsWith("SINSTS")) { papp = line.substring(line.indexOf(' ') + 1).toInt(); } if (line.startsWith("IINST")) { iinst = line.substring(line.indexOf(' ') + 1).toInt(); } if (line.startsWith("BASE") || line.startsWith("EAST")) { base = line.substring(line.indexOf(' ') + 1).toInt(); } }

LORA

Comprendre les composants

Clone this wiki locally