DIY monitor for Smartmeter

It has been a while since my last post. But I have been working on something I waited for so long. I have a real smKaifa-MA105-MA304art-meter (instead of my previous Iskra ME162  digital meter that has no I/O ports that are active (infrared) or any other useable way to read out the meter without breaking the seal)

 

 

My power and gas meter have been replaced with a KAIFA MA105 meter that is connected via GPRS to the Vodafone Network. On the left side of this meter is a P1 bus which can be hooked up via a serial cable to the raspberry (in my case) (P1 protocol description here)

I made a simple serial cable following this design :

pin nr
RJ11
signal sub-D pin nr.
2 request (RTS) 4
3 ground (GND) 5
4 N.C. N.C.
5 data (RxD) 2

And a USB to Serial converter with a PL2303 chip since I read that the signal can be inverted and this device can handle that automatically.

My meter communicates on a higher then normal (other meters) baudrate (115200 baud)

cu -l /dev/ttyUSB0 -s 115200 --parity=none

Resulted in a nice summary

/KFM5KAIFA-METER

1-3:0.2.8(40)
0-0:1.0.0(XXXXXXXW)
0-0:96.1.1(45303XXXXXXXXXXXXXXXXX)
1-0:1.8.1(000018.947*kWh)
1-0:1.8.2(000000.000*kWh)
1-0:2.8.1(000000.714*kWh)
1-0:2.8.2(000000.000*kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.860*kW)
1-0:2.7.0(00.000*kW)
0-0:17.0.0(999.9*kW)
0-0:96.3.10(1)
0-0:96.7.21(00006)
0-0:96.7.9(00005)
1-0:99.97.0(1)(0-0:96.7.19)(000101000001W)(2147483647*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(004*A)
1-0:21.7.0(00.856*kW)
1-0:22.7.0(00.000*kW)
0-1:24.1.0(003)
0-1:96.1.0(473XXXXXXXXXXXXXXXXXXXXXXXXX)
0-1:24.2.1(140125220000W)(00008.116*m3)
0-1:24.4.0(1)
!04F0

I removed some details that might reveal serials numbers e.t.c  but this is to get an idea. I wanted to present this output in a nice graph and combine it with the output of my solar inverter. I decided to use my MYSQL Database that runs on my Synology NAS to be the main storage for my smart-meter output.

I read-out the Smartmeter with a cron and a python script (every minute) and dump the result as a txt file on my NAS so I can further process it from my Raspberry upstairs. I tried several techniques to netcat the TTY port over TCP/IP to my other Raspberry (The Raspberry connected to the smartmeter is not my webserver) but this one was the most resilient.

Crontab :

*/1 * * * * /usr/bin/python /nas/smartmeter/P1uitlezen.py > /dev/null
# Smartmeter Readout
import sys
import serial

#Main program

#Set COM port config
ser = serial.Serial()
ser.baudrate = 115200
ser.bytesize=serial.EIGHTBITS
ser.parity=serial.PARITY_NONE
ser.stopbits=serial.STOPBITS_ONE
ser.xonxoff=0
ser.rtscts=0
ser.timeout=20
ser.port="/dev/ttyUSB0"

#Open COM port
try:
    ser.open()
except:
    sys.exit ("Cannot open  %s."  % ser.name)

#Init
p1_raw=''
sys.stdout = open('/nas/smartmeter/P1output.txt','w')

#Loop until the checksum bit is printed (i.e. !602D)
while not "!" in p1_raw:

#Read serial port output per line.
    try:
        p1_raw = ser.readline()
        sys.stdout.write(p1_raw)

    except:
        sys.exit ("Serial port %s can't be read." % ser.name )

#Close port and show status
try:
    ser.close()
    sys.stdout.close()
except:
    sys.exit ("%s. Unexpected exit." % ser.name )

Notice the last  !04F0 , this is the CRC check 🙂 handy to check if the data you have received is correct!
I used PHP and regular expressions to convert the data above in human readable data. You can find the details of the numbers in the protocol description above, or on many places on the net.

First I read the generate txt file from the python script above, in PHP :

$path = '/var/www/nas/smartmeter/P1output.txt';
while( filesize($path)==0)
{
    sleep(1);
    clearstatcache();
}

$handle = fopen($path, "r");
if($data = fread($handle, filesize($path))) {

fclose ($handle);

Since it takes while for the script to output, i used a while loop to detect if the file was not 0 bytes to prevent invalid data. Works flawless for me. My NAS is the “shared” storage, and frankly I think it might be the best thing to do since making writes on a SD card every minute, i don’t know if this is a good idea.

To match the right data I used PHP and regular expressions.

//Power
preg_match_all("/[0-9]-[0-9]:1.8.1([0]{1,}(.*)*kWh)/", $data, $T1_received);
preg_match_all("/[0-9]-[0-9]:1.8.2([0]{1,}(.*)*kWh)/", $data, $T2_received);
preg_match_all("/[0-9]-[0-9]:2.8.1([0]{1,}(.*)*kWh)/", $data, $T1_send);
preg_match_all("/[0-9]-[0-9]:2.8.2([0]{1,}(.*)*kWh)/", $data, $T2_send);

//Live
preg_match_all("/[0-9]-[0-9]:1.7.0(([0-9.]{1,})*kW)/", $data, $actual_received); //To Net
preg_match_all("/[0-9]-[0-9]:2.7.0(([0-9.]{1,})*kW)/", $data, $actual_deliverd); //From Net

//Gas
preg_match_all("/[0-9]-[0-9]:96.1.0((.*))/", $data, $gas_serial);
preg_match_all("/[0-9]-[0-9]:24.2.1(([0-9]{12}[S,W]))/", $data, $gas_logtime); //YYMMDDhhmmssX( X=S) DST active, or DST is not active (X=W).
preg_match_all("/[0-9]-[0-9]:24.2.1([0-9]{12}[S,W])([0]{1,}(.*)*m3)/", $data, $gas_used);

//Rate
preg_match_all("/[0-9]-[0-9]:96.14.0(000([1-2]))/", $data, $rate); //1 Low , 2 High

//CRC Check
preg_match_all("/!([0-9A-F]{4})/", $data, $crc);

To perform a good CRC check I use this function as the result is a pure CRC16 check (PHP)

/*
 * Returns CRC16 of a string as int value
 */
    function crc16($string, $crc = 0)
    {
            for ($x = 0; $x < strlen($string); $x++)
            {
                    $crc = $crc ^ ord($string[$x]);
                    for ($y = 0; $y < 8; $y++)
                    {
                            if (($crc & 0x0001) == 0x0001)
                            {
                                    $crc = ($crc >> 1) ^ 0xA001;
                            }
                            else
                            {
                                    $crc = $crc >> 1;
                            }
                    }
            }
            return $crc;
    }

If you store the variables in a database you can make nice graphs. Here are 2 screenshots from my environment :

Screenshot 2014-02-02 15.19.20
Screenshot 2014-02-02 15.19.47

I am not done, as I want to provide a better insight with gas-usage and outside temperature, and many other ideas. But its a start and it is fun to do 🙂

 

 

One thought on “DIY monitor for Smartmeter”

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.