At first glance reading from such a IEC 62056-21 compliant metering device seems to be fairly straightforward:
1. First we send a request for communication to the device
2. The device will send identification information back
3. In return we will acknowledge that identification message
4. And finally the metering device will start sending tariff data
In practice however, seizing the tariff data from the device is often more difficult than expected. Mostly due to lack of available documentation.
In response to some questions posted on this forum, and to save you from many hours of digging and reading, here’s a little guidance on how to read the IR port of a IEC 62056-21 compliant metering device:
The IEC 62056-21 specification states that initial communication between the requester (application) and the metering device will start at 300 baud using 7 bits, one stop bit and an even parity bit.
To inform the metering device that we would like to communicate with it, we send a “request message” to the device:

In code, this could look like this:
Code: Select all
SerialPort port = new SerialPort("COM1", 300, Parity.Even, 7, StopBits.One);
port.Open();
port.WriteLine("/?!"); // WriteLine adds CR+LF

This message can be read fairly easy:
Code: Select all
string data = port.ReadLine(); // Read data from the device
Now let's start deciphering what this message data means:

The data starts with the Start character, followed by the manufacturer identification.
The manufacturer identification consists of three upper case letters (eg. ISK), or two upper case letters plus one lower case letter (eg. ISk). If the third letter is a lower case letter this means that the metering device has a minimum response time of 20ms instead of 200ms. Aldo this might seem not that important, not obeying to the required response time can really screw up the communication with your device (trust me, been there

The Baud rate identification is used for the baud rate changeover. The "request message", the "acknowledgement/option" and the "identification message" are transmitted with an initial rate of 300 baud. Subsequent communication can be performed at higher speed. With the baud rate identification the metering device indicates the required baud rate for further communication.

In this case the metering device returns the value of 5, indicating a communication speed of 9600 baud. So we have to change our baud rate to 9600 baud in order to continue communication with the device.
The Sequence delimiter "\" (0x5c) is always followed by the mode identification character and will only occur in conjunction with the Mode identification character. This field is optional and part of the 16 characters long identification.
The Mode identification character defines the used communications protocol. Currently IEC 62056-21 compliant devices only support the High-Level Data Link Control (HDLC) mode (value of 2). The field is optional and part of the 16 characters long identification. (note: interpretation and usage of this character is unclear to me)
And finally the Device identification is manufacturer-specific and may consist of maximum 16 characters. Each character is allowed, excepted are the characters "/", "!". The character "\" is only allowed as ESC character and only in conjunction with the two optional fields "sequence delimiter" and "mode identification.
Code: Select all
string manufacturersIdentification = data.Substring(1, 3);
string baudrateIdentification = data.Substring(4, 1);
string modeIdentification = data.Substring(6, 1);
string identification = data.Substring(7);

In this "acknowledgement/option" message we confirm to the device that we will continue communication with the following parameters:
We set the Protocol control character to zero (0), indicating a normal protocol procedure

(it is unclear to me why this has to be a value of 0, but it is the only value my metering device is responding to).
We set the Baud rate identifier to a value of 5, indicating a communication speed of 9600 baud (as specified by the device in the previous “Identification message”)
And finally set the Mode control character (to a value of 0) to indicate we want to read data from the metering device:

In code, this might resemble like:
Code: Select all
char protocolControl = '0';
char modeControl = '0';
string acknowledge = (char)0x006 + protocolControl + baudrateIdentification + modeControl;
port.WriteLine(acknowledge);
Thread.Sleep(200); // Wait for 200ms (not needed for a 20ms device)
int baudRate = 300;
switch (baudrateIdentification)
{
case "0": break;
case "1": baudRate = 600; break;
case "2": baudRate = 1200; break;
case "3": baudRate = 2400; break;
case "4": baudRate = 4800; break;
case "5": baudRate = 9600; break;
case "6": baudRate = 19200; break;
default: break;
}
port.BaudRate = baudRate; // Change over baud rate
The data message is typically used for the transmission of tariff data by the metering device. Transmission starts immediately after the transmission of the "acknowledgement/option" message. A typical data message will look like:

The "Block checksum character" is the calculated length parity over the characters of the data message beginning immediately after the STX up to the included ETX .
Immediately after changing the baud rate we can start reading data from the device:
Code: Select all
const char endChar = (char)0x21;
string telegram = string.Empty;
do
{
data = port.ReadLine();
telegram = telegram + data;
} while (data.IndexOf(EndChar) == -1);
Console.WriteLine(telegram);
More on how to interpret COSEM/OBIS data can be found in the Dutch Smart Meter Specification, especially the P1 companion standard:
files.domoticaforum.eu/Smartmetering/DS ... l%20P1.pdf
Happy reading!

Regards