Parsing serial data from smart meter

In a previous post, I prepared a Raspberry Pi to connect through serial with my smart electricity meter. I used a USB to serial converter for this (P1 cable).

Processing data

Now the next step for me is to convert the serial information into something usefull, I want to know my net energy consumption.

First, i will have a look at the format of the information to decide what I will do next.

tio /dev/ttyUSB0

This is what a package looks like. I also measured the delay between two packages. They seem to be ten seconds apart.

/XMX5LGBBFG1009014527

1-3:0.2.8(42)
0-0:1.0.0(220817191837S)
0-0:96.1.1(4530303331303033303031333033393135)
1-0:1.8.1(011267.665*kWh)
1-0:1.8.2(009787.785*kWh)
1-0:2.8.1(000178.513*kWh)
1-0:2.8.2(000398.832*kWh)
0-0:96.14.0(0002)
1-0:1.7.0(00.238*kW)
1-0:2.7.0(00.000*kW)
0-0:96.7.21(00001)
0-0:96.7.9(00001)
1-0:99.97.0(1)(0-0:96.7.19)(190727010335S)(0000006280*s)
1-0:32.32.0(00000)
1-0:32.36.0(00000)
0-0:96.13.1()
0-0:96.13.0()
1-0:31.7.0(001*A)
1-0:21.7.0(00.238*kW)
1-0:22.7.0(00.000*kW)
!969C

There seem to be two lines that indicate my net power consumption.

These lines start with 1-0:1.7.0 and 1-0:21.7.0 followed by the actual values. The difference between those two are the ways in which they are measured. Doing some quick reading on the internet regarding these prefixes does not immediately sway me into preferring one over the other. I will stick with the first for now.

After both these lines, there is a second zero value. These are the other of two different power tariffs my meter can track. In weekends and at night it is these numbers I need to read (only if I have such an energy contract of course). So to be correct all the time, I should extract both numbers and add them to get my final net power consumption at all moments of the day.

Python and serial

I will start with a simple program to read serial data line by line and dumping it to the console.

Hanging Raspberry

Well, it seems that my Raspberry keeps hanging my remote connection. Let’s try a new power supply first.

Now it is not even starting… Third power supply!

Still, I have a “Low voltage warning”, but it stopped hanging/crashing.

Code

while True:
    l = ser.readline()
    print(l)
        port='/dev/ttyUSB0',
        baudrate = 115200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=1
)

while True:
    l = ser.readline()
    print(l)

This creates a serial connection (object) with my serial device and the main loop after that reads and prints the lines one by one.

b'/XMX5LGBBFG1009014527\r\n'
b'\r\n'
b'1-3:0.2.8(42)\r\n'
b'0-0:1.0.0(220817195018S)\r\n'
b'0-0:96.1.1(4530303331303033303031333033393135)\r\n'
b'1-0:1.8.1(011267.665*kWh)\r\n'
b'1-0:1.8.2(009787.926*kWh)\r\n'
b'1-0:2.8.1(000178.513*kWh)\r\n'
b'1-0:2.8.2(000398.832*kWh)\r\n'
b'0-0:96.14.0(0002)\r\n'
b'1-0:1.7.0(00.347*kW)\r\n'
b'1-0:2.7.0(00.000*kW)\r\n'
b'0-0:96.7.21(00001)\r\n'
b'0-0:96.7.9(00001)\r\n'
b'1-0:99.97.0(1)(0-0:96.7.19)(190727010335S)(0000006280*s)\r\n'
b'1-0:32.32.0(00000)\r\n'
b'1-0:32.36.0(00000)\r\n'
b'0-0:96.13.1()\r\n'
b'0-0:96.13.0()\r\n'
b'1-0:31.7.0(002*A)\r\n'
b'1-0:21.7.0(00.347*kW)\r\n'
b'1-0:22.7.0(00.000*kW)\r\n'
b'!C581\r\n'

Extraction time

I took the output of the meter to https://regex101.com and create a regular expression to find the two numbers for my power consumption. A regular expression is a powerful way to describe exactly what you are looking for in a string.

These are the two expressions I created.

:1\.7\.0\((.*)\*kW\)
:2\.7\.0\((.*)\*kW\)

More code

import re
import time
import serial

ser = serial.Serial(
        port='/dev/ttyUSB0',
        baudrate = 115200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=1
)


power = 0
while True:
    l = str(ser.readline())
       
    result = re.findall(':1\.7\.0\((.*)\*kW\)',l)
    if len(result):
        power = float(result[0])
       
    result = re.findall(':2\.7\.0\((.*)\*kW\)',l)
    if len(result):
        power += float(result[0])
        
        print(power)

First in the main loop I did a str() on the line last read to convert the binary line into a Python string, otherwise regex doesn’t like it.

Then I added two regex (regular expression) searches two the main loop. Because the data always arrives in the same order, the first expression sets the power and the second one adds, so I end up with a total.

Now every then seconds it outputs a floating point number, which is the current power usage in kw/h. Quite simple, actually.

In a future post, I will save these numbers to a database outside the Raspberry, so I can use the numbers elsewhere.

Leave a Reply

Your email address will not be published. Required fields are marked *