P1 smart meter Adruino LAN gateway

Others (MiLight, Hue, Toon etc...)

Moderator: leecollings

Post Reply
RFMuser
Posts: 11
Joined: Wednesday 13 April 2016 13:03
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

P1 smart meter Adruino LAN gateway

Post by RFMuser »

Good day all,

I connected an Adruino UNO to the P1 port of my landis & gyr e350 smart meter. Data is successfully extracted from the meter.

/XMX5LGBBFG1009232820

1-3:0.2.8(42)
0-0:1.0.0(161010004339S)
0-0:96.1.1(4530303330303033313630363237323135)
1-0:1.8.1(000084.040*kWh)
1-0:1.8.2(000000.000*kWh)
1-0:2.8.1(000000.000*kWh)
1-0:2.8.2(000000.000*kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.960*kW)
1-0:2.7.0(00.000*kW)
0-0:96.7.21(00003)
0-0:96.7.9(00000)
1-0:99.97.0(0)(0-0:96.7.19)
1-0:32.32.0(00000)
1-0:52.32.0(00000)
1-0:72.32.0(00000)
1-0:32.36.0(00000)
1-0:52.36.0(00000)
1-0:72.36.0(00000)
0-0:96.13.1()
0-0:96.13.0()
1-0:31.7.0(002*A)
1-0:51.7.0(000*A)
1-0:71.7.0(003*A)
1-0:21.7.0(00.252*kW)
1-0:41.7.0(00.000*kW)
1-0:61.7.0(00.708*kW)
1-0:22.7.0(00.000*kW)
1-0:42.7.0(00.000*kW)
1-0:62.7.0(00.000*kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303331303033323836353937303135)
0-1:24.2.1(161010000000S)(00038.385*m3)
!00F8

I made a quick test setup to forward the received P1 message to an Ethernet client if it connects to the Adruino. When I use a browser to connect to the Adruino it shows me the above message. The next step is to get this message in Domoticz. When I add "P1 Smart Meter with LAN interface" it connects to the Adruino but it will show the next error in the log "p1 hardware (12) thread seems to have ended unexpectedly".

Code: Select all

#include <Ethernet.h>

// assign a MAC address for the Ethernet controller.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
IPAddress ip(192, 168, 1, 20);
EthernetServer server(80);

char inputString[900];         // a string to hold incoming data
int x = 0;
boolean stringComplete = false;  // whether the string is complete
boolean lastline = false;

void setup() {

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  // initialize serial:
  Serial.begin(115200);

  // give the sensor and Ethernet shield time to set up:
  delay(1000);

}

void loop() {

  // listen for incoming Ethernet connections:
  listenForEthernetClients();
}



void listenForEthernetClients() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          client.print(inputString);
          Serial.println(inputString);
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1000);
    // close the connection:
    client.stop();
  }
}
void serialEvent() {
  while (Serial.available()) {
    // get the new byte
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString[x]= inChar;
    x += 1;
    //When ! is received continue until end of line and start over filling the var
    if (inChar == '!') { 
      lastline = true;
    }
      if (inChar == '\n' && lastline == true){
      lastline = false;
      x = 0;
      }
    }
  }


The meter is located in another building, therefore I like to use the LAN connection to send the data to Domoticz. I can use JSON and virtual sensor as alternative but I like to send the full message at once and it seems that Domoticz is prepared for that.

So my question is. Is the Domoticz P1 LAN device expecting the same message structure as the Serial version? Or is forwarding the P1 message from serial to LAN not enough?
RFMuser
Posts: 11
Joined: Wednesday 13 April 2016 13:03
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: P1 smart meter Adruino LAN gateway

Post by RFMuser »

Thanks for looking into this. So you are saying I should continue to send data. What I do now is wait for domoticz to request data and answer back once, like the browser. Because you have to fill in the ip address and port of the device I figured out that Domoticz is requesting data at a set interval. I never received any data in domoticz. It only shows the hardware but no devices. It says the device is connected but later the error message shows up every time.

I saw the ESP8266 P1-Wifi gateway using the idx of the domoticz P1 lan interface. I that case the datagram should also include this. Not sure how Domoticz is expecting to receive the data and communicates on the P1 LAN device. Can't find any documentation for it either.

It would be convenient to use it in this way, instead of creating virtual devices and format the data in the adruino then send json data.
RFMuser
Posts: 11
Joined: Wednesday 13 April 2016 13:03
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: P1 smart meter Adruino LAN gateway

Post by RFMuser »

Thanks for the hints. I managed to get it working. I now use the Adruino UNO as serial to LAN P1 gateway for the meter. Domoticz is indeed connecting once without sending data. So I changed the code who will now just send data to all connected clients every 10 seconds if there are any.

Code: Select all

#include <Ethernet.h>

// assign a MAC address for the Ethernet controller.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
IPAddress ip(192, 168, 1, 20);
EthernetServer server(80);

char inputString[900];// a string to hold incoming data
int x = 0;//counter for incoming data
boolean lastline = false; //lastline of incoming data 
boolean Update = false; // Flag when a full message is received 

void setup() {
  
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  // initialize serial:
  Serial.begin(115200);

  // give the sensor and Ethernet shield time to set up:
  delay(1000);

}

void loop() {
      EthernetClient client = server.available(); // gets client object if available and put it in the var
      client.flush(); //flush input buffer if there is any data
      //looks like domoticz is not sending data only setting up the connection. Therefore you need to start 
      //sending data to all connected clients every set interval.Not wait for a request.

//only send data if P1 message is fully updated. Every 10 seconds
      if (Update == true){
      server.write(inputString);      
      Serial.write(inputString);
      Update = false;
      }
//    }
  }


void serialEvent() {
  while (Serial.available()) {
    // get the new byte
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString[x]= inChar;
    x += 1;
    //When ! is received continue until end of line and start over filling the var, the ! is followed by an CRC. Used by Domoticz.
    if (inChar == '!') { 
      lastline = true;
    }
      if (inChar == '\n' && lastline == true){
      lastline = false;
      x = 0;
      Update = true;
      }
    }
  }

The client part can probably be adapted but will try it later.

I use this with the landis gyr e350 meter. The cable connection is as follows.

cable schematic
http://gofile.me/6pMd1/6V4I86Umv

Used info from this site,

https://thinkpad.tweakblogs.net/blog/10 ... l-database
michaelb
Posts: 14
Joined: Wednesday 25 January 2017 19:37
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: P1 smart meter Adruino LAN gateway

Post by michaelb »

Hi all,

I've tried to make this solution as described, and loaded the code from the previous post.

However, no data seems to be published on the webserver-end.

Domoticz log:

Code: Select all

2017-01-25 19:30:46.137 P1 Smart Meter: connected to: 192.168.1.245:80 
.....
.....
2017-01-25 19:32:00.005 Error: Energie hardware (7) thread seems to have ended unexpectedly
Between the start and the error no data is received by Domoticz.

If I read-out com8 with a simple Arduino-project (using AltSoftSerial, see code below) it gives me the datagrams, however some of them seem corrupted.

Code: Select all

#include <AltSoftSerial.h>
// AltSoftSerial always uses these pins:
//
// Board          Transmit  Receive   PWM Unusable
// -----          --------  -------   ------------
// Teensy 2.0         9        10       (none)
// Teensy++ 2.0      25         4       26, 27
// Arduino Uno        9         8         10
// Arduino Mega      46        48       44, 45
// Wiring-S           5         6          4
// Sanguino          13        14         12
 
AltSoftSerial altSerial;
 
char input; // inkomende seriele data (byte)
bool readnextLine = false;
#define BUFSIZE 75
char buffer[BUFSIZE]; //Buffer voor seriele data om \n te vinden.
int bufpos = 0;
long mEVLT = 0; //Meterstand Elektra - verbruik laag tarief
long mEVHT = 0; //Meterstand Elektra - verbruik hoog tarief
long mETLT = 0; //Meterstand Elektra - teruglevering laag tarief
long mETHT = 0; //Meterstand Elektra - teruglevering hoog tarief
long mEAV = 0;  //Meterstand Elektra - actueel verbruik
long mEAT = 0;  //Meterstand Elektra - actueel teruglevering
float mG = 0;   //Meterstand Gas
 
void setup() {
  Serial.begin(9600);
  altSerial.begin(115200);
}
 
void loop() {
long tl = 0;
long tld =0;
 
  if (altSerial.available()) {
    input = altSerial.read();
   
    // --- 7 bits instelling ---
    input &= ~(1 << 7);
    char inChar = (char)input;
    // --- 7 bits instelling ---
 
    Serial.print(input); //Debug
    
    // Vul buffer tot en met een nieuwe lijn (\n)
    buffer[bufpos] = input&127;
    bufpos++;
 
    if (input == '\n') { // we hebben een lijn binnen (gegevens tot \n)
 
      // 1-0:1.8.1 = Elektra verbruik laag tarief (DSMR v4.0)
      if (sscanf(buffer,"1-0:1.8.1(%ld%.%ld%*s" , &tl, &tld) >0 ) {
        mEVLT = tl * 1000 + tld;
        if (mEVLT > 0) {
          Serial.print("Elektra - meterstand verbruik LAAG tarief (Wh): ");
          Serial.println(mEVLT);
          mEVLT = 0;
        }
      }
 
      // 1-0:1.8.2 = Elektra verbruik hoog tarief (DSMR v4.0)
      if (sscanf(buffer,"1-0:1.8.2(%ld%.%ld%*s" , &tl, &tld) >0 ) {
        mEVHT = tl * 1000 + tld;
        if (mEVHT > 0) {
          Serial.print("Elektra - meterstand verbruik HOOG tarief (Wh): ");
          Serial.println(mEVHT);
          mEVHT = 0;
        }
      }
 
      // 1-0:1.7.0 = Elektra actueel verbruik (DSMR v4.0)
      if (sscanf(buffer,"1-0:1.7.0(%ld.%ld%*s" , &tl , &tld) >0 ) {
        mEAV = tl * 1000 + tld * 10;
        if (mEAV > 0) {
          Serial.print("Elektra - actueel verbruik (W): ");
          Serial.println(mEAV);
          mEAV = 0;
        }
      }
 
      // 1-0:2.8.1 = Elektra teruglevering hoog tarief (DSMR v4.0)
      if (sscanf(buffer,"1-0:2.8.1(%ld%.%ld%*s" , &tl, &tld) >0 ) {
        mETLT = tl * 1000 + tld;
        if (mETLT > 0) {
          Serial.print("Elektra - meterstand teruglevering LAAG tarief (Wh): ");
          Serial.println(mETLT);
          mETLT = 0;
        }
      }
 
      // 1-0:2.8.2 = Elektra teruglevering hoog tarief (DSMR v4.0)
      if (sscanf(buffer,"1-0:2.8.2(%ld%.%ld%*s" , &tl, &tld) >0 ) {
        mETHT = tl * 1000 + tld;
        if (mETHT > 0) {
          Serial.print("Elektra - meterstand teruglevering HOOG tarief (Wh): ");
          Serial.println(mETHT);
          mETHT = 0;
        }
      }
 
      // 1-0:2.7.0 = Elektra actueel teruglevering (DSMR v4.0)
      if (sscanf(buffer,"1-0:2.7.0(%ld.%ld%*s" , &tl , &tld) >0  ) {
        mEAT = tl * 1000 + tld * 10;
        if (mEAT > 0) {
          Serial.print("Elektra - actueel teruglevering (W): ");
          Serial.println(mEAT);
          mEAT = 0;
        }
      }
 
      // 0-1:24.3.0 = Gas (DSMR v4.0)
      if (sscanf(buffer,"0-1:24.3.0(%6ld%4ld%*s" , &tl, &tld) > 0  ) {
        readnextLine = true; // we moeten de volgende lijn hebben
      }
      if (readnextLine){
        if (sscanf(buffer,"(%ld.%ld%*s" , &tl, &tld) >0  ) {
          mG = float ( tl * 1000 + tld ) / 1000;
          Serial.print("Gas - meterstand (m3): ");
          Serial.println(mG);
          Serial.println("");
          readnextLine = false;
        }
      }
 
      // Maak de buffer weer leeg (hele array)
      for (int i=0; i<75; i++)
      { buffer[i] = 0;}
      bufpos = 0;
    }
  }
}


When I configure the Arduino as a webserver with the same MAC/IP it gives me output. So the hardware seems to be working.

Any ideas?
Thanks in advance.
michaelb
Posts: 14
Joined: Wednesday 25 January 2017 19:37
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: P1 smart meter Adruino LAN gateway

Post by michaelb »

Ha All,

Sometimes rethinking the whole setup gives you the insight needed :roll:
As an Arduino UNO only has one 'physical' COM port (shared with the USB connection). one cannot readout pin 8 with the hardware serial device, only with software ports (this explains why it worked with AltSoftSerial). Hence the SerialEvent trigger is never activated and the data is not captured.

The hardware port is ion PIN 0 (Rx) and 1 (Tx).

So: connecting the yellow wire from the diagram to PIN 0 instead of 8 solved my problem.

Regards,
Michael
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest