Energy Monitoring with Python

Every month I had to open the cover of switch box and get the readings from unbearable display of energy meter which also has blinding LED.

So I was dreaming about the way to get the readings keeping the cover closed. Like that:

$ ssh mercury206_readings
3518.55 kWh;1486.62 kWh;0.0 kWh
$ ssh mercury206_vcp
238.1 V;2.05 A;0.477 kW

Mercury 206 is the name of my energy meter and it looks like that:

Mercury 206 with USB IR adapter

УСО-2 is IR adapter magnetically attached to the optical port of Mercury with USB connector on the other end.

CD accompanying the adapter contains only Windows driver and manufacturer of the meter provided only Windows software to interact with device.

Reverse-Engineering Serial Protocol

Luckily I stumbled on the article about reverse-engineering Mercury 230 (RUS). It encouraged me to repeat it for Mercury 206.

Reverse engineering required Windows machine running Incotex software and serial ports monitor. I triggered different commands in configurator of Incotex and saved data captured by serial monitor. After that I needed only to decipher the protocol and it was easy having the clues from the above mentioned article.

Good description of Mercury 206 protocol was published later by mrkrasser @ github

Teaching Python speak to energy meter in Linux

Linux detected adapter out of the box:

usbcore: registered new interface driver ftdi_sio
usbserial: USB Serial support registered for FTDI USB Serial Device
ftdi_sio 2-1:1.0: FTDI USB Serial Device converter detected
usb 2-1: Detected FT232BM
usb 2-1: Number of endpoints 2
usb 2-1: Endpoint 1 MaxPacketSize 64
usb 2-1: Endpoint 2 MaxPacketSize 64
usb 2-1: Setting MaxPacketSize 64
usb 2-1: FTDI USB Serial Device converter now attached to ttyUSB0

So teaching Python speak to the meter was just a matter of giving pyserial the path to the serial device (and fixing the access rights for device). There were two technical obstacles, though:

# calculation of CRC, resolved with minimalmodbus library. # unreliable communications over serial interface, some sent commands didn't get responses, so they had to be repeated until the meter hear and respond.

The result of this work is published on Github as pip-friendly package energy-meter-mercury206. It implements just a subset of protocol, but allows to get the readings and actual parameters (Voltage, Current, Power). Want to mention also nice cookiecutter-pypackage which greately simplified creating skeleton of Python package.

Energy Monitoring Setup

Getting readings over SSH is nice, but I wanted to see history of the actual energy consumption on the graph. rrdtool seemed to be the easiest option, so I decided to setup two round-robin databases. One for keeping the actual values added every minute and aggregated with 5 minute resolution for last 2 days and 1 hour resolution for 28 days:

# add data every 60 seconds
rrdtool create pcv.rrd --step 60 \
DS:power:GAUGE:120:0:100 \
DS:current:GAUGE:120:0:100 \
DS:voltage:GAUGE:120:0:300 \
RRA:AVERAGE:0.5:5:576 \
RRA:MAX:0.5:5:576 \
RRA:AVERAGE:0.5:60:672 \

and another one for tracking last values of readings on display added every 10 minutes and aggregated with 1 hour resolution for 2 weeks and 1 day resolution for the last year:

rrdtool create tariffs.rrd  --step 600 \
DS:tariff1:GAUGE:1200:0:U \
DS:tariff2:GAUGE:1200:0:U \
RRA:LAST:0.5:6:336 \

Actual values are stored every minute and display readings every 10 minutes. Implemented that as separate script and added to crontab:

*/1 * * * * ~/ 2>&1 | /usr/bin/logger -t mercury206
*/1 * * * * ~/ 2>&1 | /usr/bin/logger -t rrdgraph

Another script generates PNG graph with actual power consumption for the last 24 hours.

The graph is published via HTTP using the following nginx config directive:

location /power.png {
        root /home/ubuntu;

and looks like that today

Mercury 206 actual 24 hours power graph