or smart electricity meter if you prefer English..

It is the meter that will get installed in every dutch home in the near future, and because my meter got swapped the other day, I already own one. It looks like this:

slimmemeter

They call it smart because it is able to send its readouts to the electricity company by GSM/GPRS.. smart heh?

It can show 4 readouts on its display, peak/off-peak usage kWh and peak/off-peak production (if you own solar panels).. it knows the current watts you are using.. but does not show that on the display... very 'smart'.

I want this data, and I don't want it on the display, I want it on my computer... in JSON preferably, so I can make a nice webpage showing the currently used watts. The 'smart' meter does not have a network port, but it does have a what they call P1 port.

The P1 port is RJ11 connector on which you can get a serial signal of the readings (if you supply a certain pin with 5V), this serial signal is inverted, so to get it right you need a 74HC04 to invert it.
To interface between this serial and the network, I will use a Netduino plus 1 that I had laying around. Soldered the 7404 on a shield, and added an USB cable so my cable modem can power all this. It looks like this:

netduino

By opening this serial port on the Netduino

[csharp]_serialP1 = new SerialPort(SerialPorts.COM2, 9600, Parity.Even, 7, StopBits.One);
_serialP1.Open();
_serialP1.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);[/csharp]

you will start to receive this kind of messages:

/XMX5XMXABCE000021701

0-0:96.1.1(39373936373738392020202020202020)
1-0:1.8.1(000002.384*kWh)
1-0:1.8.2(000006.840*kWh)
1-0:2.8.1(000000.000*kWh)
1-0:2.8.2(000000.000*kWh)
0-0:96.14.0(0002)
1-0:1.7.0(00000.11*kW)
1-0:2.7.0(00000.00*kW)
0-0:17.0.0(999*A)
0-0:96.3.10(1)
0-0:96.13.1()
0-0:96.13.0()
0-1:96.1.0(3238303131303038323131303036333132)
0-1:24.1.0(03)
0-1:24.3.0(120802100000)(08)(60)(1)(0-1:24.2.0)(m3)
(00000.803)
0-1:24.4.0(2)
!

Using this code on the Netduino, I 'decode' the P1 message into variables in my program:

[code language="csharp"]
private static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
if (_serialP1.CanRead && _serialP1.BytesToRead > 0)
{
_led1.Write(true);
byte[] bytes = new byte[_serialP1.BytesToRead];
_serialP1.Read(bytes, 0, bytes.Length);

foreach (var b in bytes)
{
var c = (char)b;
_msg += c;
if (c == '!')
{
_msgComplete = true;
break;
}
}

if (_msgComplete && _msg.Length > 0)
{
//Debug.Print(_msg);

_currentUsagekW = getFromMessage(_msg, "1-0:1.7.0");
_currentProductionkW = getFromMessage(_msg, "1-0:2.7.0");

_usageHighkWh = getFromMessage(_msg, "1-0:1.8.1");
_usageLowkWh = getFromMessage(_msg, "1-0:1.8.2");

_productionHighkWh = getFromMessage(_msg, "1-0:2.8.1");
_productionLowkWh = getFromMessage(_msg, "1-0:2.8.2");

_msg = string.Empty;
_msgComplete = false;
}

_led1.Write(false);
}
}
catch (Exception)
{
Debug.Print("Serial receive fail!!");
}
}

public static string getFromMessage(string message, string key)
{
var test = "Error";
try
{
int startIndex = message.IndexOf(key);
test = message.Substring(startIndex + key.Length + 1,
message.IndexOf("*kW", startIndex) - startIndex - key.Length - 1);
}
catch
{
}
return test;
}

[/code]

Next is to open up a Socket and listen for requests on it:

[csharp]
public static void ListenForRequest()
{
while (true)
{
using (Socket clientSocket = _socket.Accept())
{
try
{
while (!clientSocket.Poll(10, SelectMode.SelectRead)) ;

int bytesReceived = clientSocket.Available;
if (bytesReceived > 0)
{
Debug.Print("resrquest received");
//Get request
byte[] buffer = new byte[bytesReceived];
int byteCount = clientSocket.Receive(buffer, bytesReceived, SocketFlags.None);
string request = new string(Encoding.UTF8.GetChars(buffer));
//Compose a response
var sb = new StringBuilder();
sb.AppendLine("{");
sb.AppendLine(""usageHighkWh":"" + _usageHighkWh + "",");
sb.AppendLine(""usageLowkWh":"" + _usageLowkWh +"",");
sb.AppendLine(""productionHighkWh":"" + _productionHighkWh + "",");
sb.AppendLine(""productionLowkWh":"" + _productionLowkWh + "",");
sb.AppendLine(""currentUsagekW":"" + _currentUsagekW + "",");
sb.AppendLine(""currentProductionkW":"" + _currentProductionkW + """ );
sb.AppendLine("}");

string response = sb.ToString();
string header = "HTTP/1.0 200 OKrnContent-Type: text; charset=utf-8rnContent-Length: " + response.Length.ToString() + "rnConnection: closernrn";
clientSocket.Send(Encoding.UTF8.GetBytes(header), header.Length, SocketFlags.None);
clientSocket.Send(Encoding.UTF8.GetBytes(response), response.Length, SocketFlags.None);
}
}
catch (Exception)
{
Debug.Print("This may fail somtimes for unknown reasons.. large amount of req/s for instance");
}
}
}
}
[/csharp]

And now a request in the browser to the netduino's IP will get you this:

json

Your meter's readings in a JSON format.

Next up will be posting this data to Azure storage tables.. stay tuned for part II.

Related articles

  • Cloud Native
  • Application Navigator
  • Kubernetes Platform
  • Digital Workspace
  • Cloud Infrastructure
  • ITTS (IT Transformation Services)
  • Managed Security Operations
  • Multi-Cloud Platform
  • Backup & Disaster Recovery
Visit our knowledge hub
Visit our knowledge hub
ITQ

Let's talk!

Knowledge is key for our existence. This knowledge we use for disruptive innovation and changing organizations. Are you ready for change?

"*" indicates required fields

First name*
Last name*
Hidden