Skip to main content
Home
for DLMS smart meters

Main navigation

  • Home
  • Products
  • About us
  • Open Source
  • Community
  • Forum
  • Downloads
User account menu
  • Log in

Breadcrumb

  1. Home
  2. Combining Several Meters' Profile Generic Data Into One

Combining several meters' profile generic data into one

Profile picture for user melvin67
By melvin67, 15 May, 2025
Forums
Gurux.DLMS

Good day
I am learning how to develop DLMS server. I am able to create a client app to read meter, and send it to a database. I used ESP32 to achieve that. Now I want to make a DLMS server to simulate a meter, let's say it's MyMeter. I want to combine/accumulate the data from two meters' profile generic into one profile generic that this MyMeter have. I plan to code in C or C++ for this. Is this possible? If it is, how to accomplish that?

Thanks in advance.
Melvin

Profile picture for user Kurumi

Kurumi

1 month 1 week ago

Hi, It’s possible, but how…

Hi,

It’s possible, but how do you plan to distinguish which meter the saved data comes from?

It's easier to implement with ANSI C++.

You can save the data something like this:

https://github.com/Gurux/Gurux.DLMS.cpp/blob/1d48796032ed936a61debc615a…

BR,
Mikko

Profile picture for user melvin67

melvin67

1 month 1 week ago

Thanks for the quick…

Thanks for the quick response.
When I collect the data from the meter, I also read the meters' ID using OBIS code 0.0.42.0.0.255 (Ch. 0 COSEM Logical device name), then I send those read data to a MySQL database. The data read from those meter is stored so each of those OBIS codes have their own column. Then there will be a logic that will read those columns of data, after that I can prepare a profile generic with those data. The data from DB would be stored inside a struct.
Inside the DB there is a column that contains this meter ID. I plan to use that.
How to fill profile generic with data stored in a struct? Should I prepare a csv or some kind of sheets that contains all profile generic LN and data to be able to do it? I noticed there is a .csv file after running the compiled program, but don't really know what kind of data inside.
At the moment I'm trying to do that thing I described earlier. Do you have any suggestion for better workflow?

Thank you
Melvin

Profile picture for user Kurumi

Kurumi

1 month ago

Hi, You need to add a column…

Hi,

You need to add a column for the meter ID. The example reads data from CSV, so you need to add needed COSEM objects and then add them to the capture objects of profile generic object. After you have done that you can get the default settings to the CSV file if you select "Capture".

I believe that your idea will work as you have planned.

BR,
Mikko

Profile picture for user melvin67

melvin67

1 month ago

Hi Mikko, thank you for the…

Hi Mikko, thank you for the answer
Before I do this whole meter data combining, first I need to be able to make a single meter. I cloned Gurux.DLMS.cpp and try run it for the first time, worked like charm.
Then I modified the main.cpp (I want to test just one server, that is LNServer) and GXDLMSBase.cpp.Currently I have tried adding three registers, they're current, voltage, and frequency.

Kindly check the code below:
// add current
CGXDLMSRegister* pRegister_curr = new CGXDLMSRegister("1.0.31.7.0.255");
pRegister_curr->SetAccess(2, DLMS_ACCESS_MODE_READ);
// set unit
// unsigned char cr_unit;
// cr_unit = 1;
// pRegister_curr->SetUnit(cr_unit);
// // set scaler
double curr_scaler;
curr_scaler = 0.001;
pRegister_curr->SetScaler(curr_scaler);
// set value
CGXDLMSVariant cr_val;
cr_val = 2233;
pRegister_curr->SetValue(cr_val);
//debug
double scaler_curr = pRegister_curr->GetScaler();
std::cout << "Scaling factor: " << scaler_curr << std::endl;
double scaled_curr = cr_val.ToDouble() * scaler_curr;
std::cout << "Scaled value: " << scaled_curr << std::endl;
GetItems().push_back(pRegister_curr);

// add voltage
CGXDLMSRegister* pRegister_volt = new CGXDLMSRegister("1.0.32.7.0.255");
pRegister_volt->SetAccess(2, DLMS_ACCESS_MODE_READ);
// set unit
// unsigned char volt_unit;
// volt_unit = 1;
// pRegister_volt->SetUnit(volt_unit);
// // set scaler
double volt_scaler;
volt_scaler = 0.1;
pRegister_volt->SetScaler(volt_scaler);
// set value
CGXDLMSVariant volt_val;
volt_val = 2233;
pRegister_volt->SetValue(volt_val);
//debug
double scaler_volt = pRegister_volt->GetScaler();
std::cout << "Scaling factor: " << scaler_volt << std::endl;
double scaled_volt = volt_val.ToDouble() * scaler_volt;
std::cout << "Scaled value: " << scaled_volt << std::endl;
GetItems().push_back(pRegister_volt);

// add frequency
CGXDLMSRegister* pRegister_freq = new CGXDLMSRegister("1.0.14.7.0.255");
pRegister_freq->SetAccess(2, DLMS_ACCESS_MODE_READ);
// set unit
// unsigned char freq_unit;
// freq_unit = 1;
// pRegister_freq->SetUnit(freq_unit);
// // set scaler
double freq_scaler;
freq_scaler = 0.01;
pRegister_freq->SetScaler(freq_scaler);
// set value
CGXDLMSVariant freq_val;
freq_val = 5000;
pRegister_freq->SetValue(freq_val);
//debug
double scaler_freq = pRegister_freq->GetScaler();
std::cout << "Scaling factor: " << scaler_freq << std::endl;
double scaled_freq = freq_val.ToDouble() * scaler_freq;
std::cout << "Scaled value: " << scaled_freq << std::endl;
GetItems().push_back(pRegister_freq);

I added the debug part so i wanna know the content and make sure the value is as intended. But after checking it in GXDLMSDirector, those values don't show correctly, either in register or profile generic.

Here's the program output:
Scaling factor: 0.001
Scaled value: 2.233
Scaling factor: 0.1
Scaled value: 223.3
Scaling factor: 0.01
Scaled value: 50
Logical Name DLMS Server in port 4061.
Example connection settings:
GuruxDLMSClientExample -h localhost -p 4061
----------------------------------------------------------
Press Enter to close application.
Connected.

Here's what's in the register, viewed using GXDLMSDirector:
https://postimg.cc/k2MKNL0R

And here's the profile generic, viewed using GXDLMSDirector:
https://postimg.cc/k2QmFpd8

Here's the trace from GXDLMS Director
14:07:16 Initializing Network connection.
14:07:16 Send SNRM request.
7E A0 07 03 21 93 0F 01 7E
14:07:16
7E A0 1E 21 03 73 C3 7A 81 80 12 05 01 80 06 01 80 07 04 00 00 00 01 08 04 00 00 00 01 53 3B 7E
14:07:16 Parsing UA reply succeeded.
14:07:16 Send AARQ request.
7E A0 2B 03 21 10 FB AF E6 E6 00 60 1D A1 09 06 07 60 85 74 05 08 01 01 BE 10 04 0E 01 00 00 00 06 5F 1F 04 00 62 1E 5D FF FF 88 55 7E
14:07:16
7E A0 3C 21 03 30 79 BC E6 E7 00 61 2E A1 09 06 07 60 85 74 05 08 01 01 A2 03 02 01 00 A3 05 A1 03 02 01 00 A7 03 02 01 00 BE 10 04 0E 08 00 06 5F 1F 04 00 40 1E 5D 04 00 00 07 F7 B7 7E
14:07:16 Parsing AARE reply succeeded.
14:07:19 Read object type ProfileGeneric index: 4
7E A0 19 03 21 32 6F D8 E6 E6 00 C0 01 C1 00 07 01 00 63 01 00 FF 04 00 84 DD 7E
14:07:19
7E A0 15 21 03 52 5D 8A E6 E7 00 C4 01 C1 00 06 00 00 00 3C 92 E3 7E
14:07:19 Read object type ProfileGeneric index: 5
7E A0 19 03 21 54 5F DE E6 E6 00 C0 01 C1 00 07 01 00 63 01 00 FF 05 00 5C C4 7E
14:07:19
7E A0 12 21 03 74 48 99 E6 E7 00 C4 01 C1 00 16 01 9A 11 7E
14:07:19 Read object type ProfileGeneric index: 6
7E A0 19 03 21 76 4F DC E6 E6 00 C0 01 C1 00 07 01 00 63 01 00 FF 06 00 34 EE 7E
14:07:19
7E A0 22 21 03 96 A6 11 E6 E7 00 C4 01 C1 00 02 04 12 00 08 09 06 00 00 01 00 00 FF 0F 00 12 00 00 C8 46 7E
14:07:19 Reading profile generic data 1.0.99.1.0.255
7E A0 2C 03 21 98 9A F0 E6 E6 00 C0 01 C1 00 07 01 00 63 01 00 FF 02 01 02 02 04 06 00 00 00 01 06 00 00 00 01 12 00 01 12 00 00 4D D6 7E
14:07:19
7E A0 2D 21 03 B8 23 6B E6 E7 00 C4 02 C1 01 00 00 00 01 00 17 01 00 02 02 09 0C 07 E8 03 1F 07 12 00 00 FF 80 00 00 05 00 00 00 02 54 0B 7E
14:07:19 Read object type ProfileGeneric index: 7
7E A0 19 03 21 BA 2F D0 E6 E6 00 C0 01 C1 00 07 01 00 63 01 00 FF 07 00 EC F7 7E
14:07:19
7E A0 15 21 03 DA 1D 82 E6 E7 00 C4 01 C1 00 06 00 00 27 10 C7 66 7E
14:07:19 Read object type ProfileGeneric index: 8
7E A0 19 03 21 DC 1F D6 E6 E6 00 C0 01 C1 00 07 01 00 63 01 00 FF 08 00 24 74 7E
14:07:19
7E A0 15 21 03 FC 29 C6 E6 E7 00 C4 01 C1 00 06 00 00 27 10 C7 66 7E
14:09:09 Send Keep Alive
7E A0 19 03 21 FE 0F D4 E6 E6 00 C0 01 C1 00 0F 00 00 28 00 00 FF 01 00 F9 79 7E
14:09:09
7E A0 18 21 03 1E BA 89 E6 E7 00 C4 01 C1 00 09 06 00 00 28 00 00 FF B6 6E 7E
14:09:47 Disconnect request
14:09:47 Disconnect request
7E A0 07 03 21 53 03 C7 7E
14:09:47
7E A0 1E 21 03 73 C3 7A 81 80 12 05 01 80 06 01 80 07 04 00 00 00 01 08 04 00 00 00 01 53 3B 7E

I dont know why the results are like those. Do I need to call PreGet method?:
if ((ret = LNServer.PreGet()) != 0)
{
return ret;
}
From the code you gave me before, should I modify the Capture() method?

Thank you for the assistance.
Melvin

  • Log in or register to post comments
  • Create new account
  • Reset your password

Hire Us!

Latest Releases

  • Thu, 06/19/2025 - 09:33
    Gurux.DLMS.Python 1.0.185
  • Wed, 06/18/2025 - 15:11
    Gurux.DLMS.Python 1.0.184
  • Wed, 06/18/2025 - 10:05
    Gurux.DLMS.Python 1.0.183
  • Wed, 06/18/2025 - 09:06
    GXDLMSDirector 9.0.2506.1801
  • Wed, 06/18/2025 - 08:41
    Gurux.DLMS.Net 9.0.2506.1801

New forum topics

  • object list not get downloaded for firmware upgrade association
  • HLS GMAC L+G 570
  • Unable to read parameter values from Landis+Gyr E550 meter using GXDLMSDirector - NoAccess status
  • data.SetComplete(false); But all data recieved
  • Crash (endless loop)
More
RSS feed
Privacy FAQ GXDN Issues Contact
Follow Gurux on Twitter Follow Gurux on Linkedin