Electricity power monitor hacking

A while ago, while browsing through a local Maplin store, I found a cheap wireless electricity power meter that is possible to connect to a PC via USB cable. Since I was planning to experiment with the electricity power monitoring for one of my commercial projects anyway, I decide to buy it and find out how to establish a communication with it from a custom piece of software and possibly even present the data on a website with a real time update. The Wireless electricity monitor was, and I believe still is, available for £14.99 from Maplin under code N94KQ This is what you get in the box:

The installation was very simple. The main measurement unit with the transmitter gets clamped on the live phase wire coming to your house. If you have three phase distribution you can buy extra two clamps and connect them to the transmitter. The meter can handle them 🙂 This is how I placed the transmitter next to my main power meter.

Communication with the electricity monitor

After installing the meter at home I realized the provided software for getting data from the unit was only for Widows and pretty rough to say the least. I didn't have any intention to use it anyway but I was quite surprised the manufacture didn't put more effort in it.

To find out how the host computer talks to the meter was quite simple. Plugging the USB cable to my linux machine and running dmesg command quickly revealed what I was dealing with.

jiri@mach:/$ dmesg

[337148.094624] usb 6-1: new full-speed USB device number 4 using uhci_hcd
[337148.257064] pl2303 6-1:1.0: pl2303 converter detected
[337148.269252] usb 6-1: pl2303 converter now attached to ttyUSB1

As one would expect the USB cable is a simple RS232 to USB bridge with the very common PL2303 chip. The USB cable is attached to the unit with RJ45 connector with quite large USB connector on the other side.  I believe the RS232->USB converter is built in the USB connector itself so the data on the RJ45  should be the raw RS232 but I haven't investigated that.

Second step was to find out the communication protocol. I didn't want to do any reverse engineering of the protocol so it tried to find what controller was used in the meter and obtain the protocol from the manufacturer.  The product is re-branded for Maplin and to find the manufacturer was not possible. Inside the unit is R5F2L38ACDFP microcontroller but that also didn't help.

The fastest approach appeared to be to analyse the data between the unit and the software that came with it. After and hour with a serial port sniffing tool I managed to extract a startup sequence, and two other sequences that need to be sent to the unit to make it to return data with the current power consumption.  This is how they look in the python.

START_CMD=[0xAA, 0x00, 0x00, 0xAD]
READ1_CMD=[0xAA, 0x01, 0x00, 0xAD]
READ2_CMD=[0xAA, 0x02, 0x00, 0xAD]

So far so good, I can initialize the unit and make it to return a long byte sequence with the power usage information like this.


How do I know? Well, I recorded several output sequences, each for different power consumption which I controlled by turning on/off my el. kettle 🙂 For each case I wrote down  the power usage displayed on the LCD screen of the unit. Then it was just a matter of identifying what bytes changed and determining how they are formatted. The power in Watts is stored in the bytes 69 and 70 in the sequence. This is how to read it in python.

 power = data[69] + data[70] * 256

Python application

To read the power is very simple.

  1. Open the serial port.
  2. Write the initialization sequence to the port.
  3. Write the READ1_CMD and READ2_CMD sequences.
  4. Read the data from the serial line and decode the power.

The last two steps can be repeated infinitely  Here is a python code to does exactly that. The only dependency is on the pySerial module

import sys
import time
from serial import *

START_CMD=[0xAA, 0x00, 0x00, 0xAD]
READ1_CMD=[0xAA, 0x01, 0x00, 0xAD]
READ2_CMD=[0xAA, 0x02, 0x00, 0xAD]

def write_cmd(device, cmd):

def read_data(device):
    while True:
        b = device.read()
        # Read all available bytes
        if len(b) == 0:
    return data

def exec_cmd(device, cmd):
    write_cmd(device, cmd)
    # The power meeter needs some time to deal with the command
    return read_data(device)

# Extract the current power consumption in Watts from the data
# returned by the power meter
def decode_power(data):
    power = 0
    data_len = len(data)
    if (data_len > 70):
        power = ord(data[70]) * 256 + ord(data[69])
    return power

# Returns current power in watts
def read_power(device):
    data = exec_cmd(device, READ1_CMD)
    data = exec_cmd(device, READ2_CMD)
    return decode_power(data)

def run(uart_port, period_sec=4):
    # Open the serial line
    device = serial_for_url(uart_port, timeout=1)

    # Initialize the device
    data = exec_cmd(device, START_CMD)
    print "Startup response: ",
    print data

    # Keep reading the power consumption infinitely
    while True:
        power = read_power(device)
        #print str(power) + " Watts   ",

        # Sometimes the power meter returns 0 Watts. This can happen if
        # the power meter itself fails to read data from the main unit over the RF link.
        if power == 0:
            print "  Ignoring *********************************"

        # Pause for 'period' seconds


if __name__=="__main__":
    uart_port = "/dev/ttyUSB0"

The complete code including the dependencies can be downloaded from http://code.google.com/p/electroncastle/source/checkout

Given the simplicity one can use any off the shelf hardware with the USB host port and some basic computation capabilities for example the recently very famous Raspberry PI. If the data on the RJ45 is really RS232 then one could use even more basic micro controllers to read the data.

Next time I will show how to setup very simple real time visualization of the power consumption in a web page.

This entry was posted in Home automation. Bookmark the permalink.

Leave a Reply