Creating DLMS compliant meter using Gurux DLMS Components
We have made DLMS server easy to use and we have hide all DLMS spesific stuff.You just add DLMS Objects like Data, Register and Clock to the list.
When Client sends data to the server you just give received byte stream to the Gurux DMLS server component that parses data and returns data that you return to the client. There might be several methods that are not needed in your application. If method is not needed, you can return default value. Read this if you are implementing your DLMS for microcontrollers First you should derive your own server class from GXDLMSSecureServer or GXDLMSServer and implement pre and post methods. Framework calls those methods when needed.
Then you must create Media component and start listen its events. When Media receives new data it is forwarded to HandleRequest -method. So basically you initialize settings like this:
public class GXDLMSServerExample extends GXDLMSSecureServer2 implements IGXMediaListener, gurux.net.IGXNetListener { }
class GXDLMSServerExample : GXDLMSSecureServer { }
//Delphi do not support server functionality at the moment.
class GXDLMSServerExample : public GXDLMSSecureServer, IGXMediaListener, IGXNetListener { }
connection snHdlc; svr_init(&snHdlc.settings, 0, DLMS_INTERFACE_TYPE_HDLC);
IsTarget
There might be several meters using same connection, example RS-485 or UDP. Purpose of IsTarget method is that server checks is client connecting to this server and is client accepted. If server is not interested from this client, return false. On development phase it's usually easier to accept all client and return true.ValidateAuthentication
Validate authentication is called to validate can client access the meter. Authentication parameter tells used client's authentication level and password. Validate authentication is called all authentications, but only Low authentication is checked here. High authentication password is checked on next step.Connected
Connected is called if authentication is succeeded.InvalidConnection
Connected is called if authentication is failed. This can be used to save IP address to find out if some one tries to connect using brute force methods.Disconnected
Disconnected is called when client has close the DLMS connection. TCP/IP connection is still up.PreGet
Pre Get is called when example profile generic's capture action is called. In profile generic's capture action current values are saved to the buffer. Pre Get can be used if values are not in memory, or server is acting like DCU and values are read from other meter.Note! If you update your values here, set Handled to true, so framework do't try to update it.
PostGet
Post Get is called after value is updated. Here server can close connections, etc.FindObject
FindObject is called if object is not found on server's object list. If all objects are there NULL can return here. It's recommendable keep all objects in server's object list, but sometimes there might be so little memory that it's no possible. If object is not found and null is returned "undefined object" -error is returned to the client.GetAttributeAccess
GetAttributeAccess is called to check can client access COSEM object's attribute. If client do not have permissions for the given object return AccessMode's NoAccess and "Read Write denied" -error is returned to the client.PreRead
PreRead is called before client try to read COSEM object. PreRead can be used if values are not in memory, or server is acting like DCU and values are read from other meter.Note! If you update your values here, set Handled to true, so framework do't try to update it.
PostRead
PostRead is called after value is retrieved. Here server can close connections, release memory, etc.PreWrite
PreWrite is called before client try to write COSEM object. Here server can example validate the data before updating.PostWrite
PostWrite is called after value is written. Here server can example save new value to the file or DB.GetMethodAccess
GetMethodAccess is called to check can client access COSEM object's action. If client do not have permissions for the given object return MethodAccessMode's NoAccess and "Read Write denied" -error is returned to the client.PreAction
PreAction is called before client try to call COSEM object's action. Here server can example pass given action to other device.PostAction
PostAction is called after action is executed. Here server can example handle file or DB operations. Example profile generic's capture can done here after values are updated. When you receive data from the client you simply give it to the server component and return received data like this:/* * Client has send data. */ @Override public void onReceived(Object sender, ReceiveEventArgs e) { try { synchronized (this) { byte[] reply = handleRequest((byte[])e.getData()); //Reply is null if we do not want to send any data to the client. //This is done if client try to make connection with wrong server or client address. if (reply != null) { Media.send(reply, e.getSenderInfo()); } } } catch (Exception ex) { System.out.println(ex.getMessage()); } }
void OnReceived(object sender, Gurux.Common.ReceiveEventArgs e) { try { lock (Server) { Gurux.Common.IGXMedia media = sender as Gurux.Common.IGXMedia; byte[] reply = Server.HandleRequest((byte[])e.Data); media.Send(reply, e.SenderInfo); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
//Delphi is not supporting this functionality at the moment.
/// Handle received data that Media sent. void OnReceived(object sender, Gurux.Common.ReceiveEventArgs e) { try { lock (this) { byte[] reply = HandleRequest((byte[])e.Data); //Reply is null if we do not want to send any data to the client. //This is done if client try to make connection with wrong device ID. if (reply != null) { Media.Send(reply, e.SenderInfo); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
if (svr_handleRequest(&con->settings, &bb, &reply) != 0) { #if defined(_WIN32) || defined(_WIN64)//If Windows closesocket(socket); socket = INVALID_SOCKET; #else //If Linux close(socket); socket = -1; #endif } bb.size = 0;