Skip to content
Paulo Facó edited this page Feb 15, 2018 · 8 revisions

In order to successfully communicate with a metering device using YADI you'll need, at least, the following:

A channel to transmit and receive bytes.

This is usually a serial port or a tcp connection, but you can use YADI with any channel you want (files, udp socket, etc.). The PhyLayer interface models a channel. YADI already comes with a SerialPhyLayer and TcpPhyLayer implementations.

A link layer to transport the application data unit (APDU).

The DLMS standard specifies many communication profiles using different link layer protocols. The LinkLayer interface models a link layer. YADI currently supports the HDLC protocol (normally used in serial communication oriented profiles) and the Wrapper protocol (normally used in udp/tcp oriented profiles).

The protocols are implemented in the HdlcLinkLayer and WrapperLinkLayer classes. Each protocol have a set of parameters that can be modified using the HdlcParameters and WrapperParamers classes.

The COSEM application layer

The application layer is used to generate the APDU's containing the operations to be executed in the metering device (GET / SET / ACTION) and the connection-related frames 'application association request' (AARQ) and 'application association response' (AARE).

You can use the Cosem class directly to generate the requests and parse the responses. But you would need to do all the work of calling the LinkLayer and PhyLayer of your choice to correctly encapsulate the APDU's and transmit them through the desired channel. Easier and better to use the DlmsClient class that will do all necessary steps to perform the desired operation. The parameters of the Cosem application layer can be modified using the CosemParameters class.

A descriptor of the object to be accessed

The DLMS standard describes two ways to access the objects of the metering device: short-name and long-name references. Currently YADI only supports Long-name reference. To execute the operations on the metering device it is necessary to create a descriptor of the object using the LnDescriptor class.

A small working example

Reading the clock using the HDLC protocol over a serial channel with no authentication (public mode) and no security.

package app;

import yadi.dlms.*;
import yadi.dlms.DlmsException.*;
import yadi.dlms.cosem.*;
import yadi.dlms.linklayer.*;
import yadi.dlms.phylayer.*;
import yadi.dlms.phylayer.SerialPhyLayer.*;

public class AppTest {

    public static void main(String[] args) {

        SerialPhyLayer serial = new SerialPhyLayer();
        HdlcLinkLayer hdlc = new HdlcLinkLayer();
        DlmsClient dlms = new DlmsClient(hdlc);
        LnDescriptor clockDescriptor = new LnDescriptor(8, new Obis("0.0.1.0.0.255"), 2); // class_id=8 index=2
        
        try {

            serial.open("COM1");
            serial.config(9600, DataBits._8, Parity.NONE, StopBits._1);

            dlms.connect(serial);
            dlms.get(serial, clockDescriptor);
            dlms.disconnect(serial);
            
            String dateTimeStr = DlmsParser.getString(clockDescriptor.getResponseData());
            // If the DATE_TIME is encoded as a OCTET_STRING you can force the parser to handle it like a DATE_TIME
            //dateTimrStr = DlmsParser.getDateTimeString(clockDescriptor.getResponseData());
            
            System.out.println("Date time: "+dateTimeStr);

        } catch (PhyLayerException e) {
            System.out.println(e.getReason());
        } catch (LinkLayerException e) {
            System.out.println(e.getReason());
        } catch (DlmsException e) {
            for (DlmsExceptionReason r : e.getReason()) {
                System.out.println(r);
            }
        } finally {
            serial.close();
        }
    }
}