DLMS communication packages
The DLMS communication packages are software components that greatly simplify the writing of COSEM/DLMS client applications.
The packages are written in C++, C# or Java and are delivered in source format.
Each package consists of 3 components called ezhdlc, wrapper and xmlpdu.
- ezhdlc is an HDLC components that implements a simplified variant of the HDLC layer of the ''3 layers HDLC-based communication profile'' as defined by the COSEM/DLMS ''Green Book''
- wrapper implements the WRAPPER layer of the ''TCP-UDP/IP based communication profile''
- xmlpdu implements the translation of COSEM related services, like ''Get'', ''Set'', ''Read'', ''Write'', etc.. to and from a straightforward xml presentation.
In the C++ variant, each component is implemented as a DLL. In the C# and Java variants, the components are implemented as classes.
The ezhdlc and the wrapper components rely on mechanisms provided by the the client code to ''send the bytes'' to the peer layer, respectively to ''receive the bytes'' from the peer layer. The C++ implementation relies on callback routines, the C# implementations relies on a ''System.IO.Stream'' and the Java implementation relies on a pair of ''java.io.InputStream'' and ''java.io.OutputStream''. For example, if the connection with the target equipment is via a serial line, then the client application has to ''open'' the communication first and then it has to send and receive data to and from that serial-line, as requested by the HDLC or WRAPPER layers. In this architecture, the HDLC and WRAPPER layers are completely independent of their supporting layer. Furthermore, the client application is in total control of the communication setup, for example, it may have to dial the phone number of a remote modem or to perform a wake-up or a ''MODE-E'' opening.
The xmlpdu component is purely procedural. It only translates xml formatted COSEM services into application-layer protocol data units (APDU) and vice-versa.
For example...
We assume that the our client application runs on a PC and wants to communicate with a meter via a serial-line, using the HDLC profile. Using the C++ package, we have to write two (callback) routines able to send and receive data to and from the peer layer via the serial-line. Then, to perform a COSEM/DLMS transfer we do the following:
- We open a serial-line connection and set its parameters (baud,...).
- We creates an ''HDLC instance'', using ezhdlc.HDLCCreateInstance() and set its parameters: the client address, the server addresses and the two callback routines.
- Then, we create the HDLC connection with ezhdlc.HDLCConnect()
- We fill an internal buffer with the XML-element for an AssociationReques which looks like this:
- We pass the internal buffer to xmlpdu.XmlToPdu() which translates the XML-element into a byte-sequence of the corresponding COSEM APDU.
- We pass this byte-sequence to ezhdlc.HDLCSendReceive() that sends the data to the other side, waits for a response and finally, returns another byte-sequence containing the response APDU.
- We pass this received byte-sequence to xmlpdu.PduToXml() that translates it back into a plain text XML-element. The response may look like this:
- We process the received xml.
- We repeat the steps 4 to 8, with other Request / Response exchanges.
- Then, we close the connection with ezhdlc.HDLCDisconnect().
- Finally, we destroy the HDLC instance with ezhdlc.HDLCDestroyInstance() and close the serial-connection
<AssociationRequest>
<ApplicationContextName Value="SN" />
<InitiateRequest>
<ProposedDlmsVersionNumber Value="06" />
<ProposedConformance>
<ConformanceBit Name="ParametrizedAccess" />
<ConformanceBit Name="MultipleReferences" />
<ConformanceBit Name="Write" />
<ConformanceBit Name="Read" />
</ProposedConformance>
<ProposedMaxPduSize Value="FFFF" />
</InitiateRequest>
</AssociationRequest>
<AssociationResponse>
<ApplicationContextName Value="SN" />
<AssociationResult Value="00" />
<ResultSourceDiagnostic>
<AcseServiceUser Value="00" />
</ResultSourceDiagnostic>
<InitiateResponse>
<NegotiatedDlmsVersionNumber Value="06" />
<NegotiatedConformance>
<ConformanceBit Name="ParametrizedAccess" />
<ConformanceBit Name="MultipleReferences" />
<ConformanceBit Name="Write" />
<ConformanceBit Name="Read" />
</NegotiatedConformance>
<NegotiatedMaxPduSize Value="0960" />
<VaaName Value="FA00" />
</InitiateResponse>
</AssociationResponse>
Several demo projects in C++, C# and Java are available here.