Skip to main content
Home
for DLMS smart meters
Open source solutions for DLMS smart metering

Main navigation

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

Breadcrumb

  1. Home
  2. Forums
  3. Gurux.C Multiple Meters

Gurux.C multiple meters

Forum Rules

Before commenting read Forum rules

Don't comment the topic if you have a new question.

You can create a new topic selecting correct category from Gurux Forum and then create a new topic selecting "New Topic" from the top left.

By wildstray , 29 November, 2021
Forums
Gurux.DLMS

Hi,
after I gave up on C++ version of Gurux (on embedded platforms such as ESP32 cannot compile due to error: 'dynamic_cast' not permitted with -fno-rtti... impossibile to work around) I resumed working with ANSI C version. Anyway I'm happy with this cause I succeed to use findObjectByLN(), it works and I can look by LN also with che C version.
But I have the requirement to read up to 4 meters on the same serial. I hypothesized to:

1) cl_init() with meter 1 params -> read AV1 -> cache AV1 -> read meter1 registers -> cl_clear()
2) cl_init() with meter 2 params -> read AV2 -> cache AV2 -> read meter1 registers -> cl_clear()
3) cl_init() with meter 3 params -> read AV3 -> cache AV3 -> read meter1 registers -> cl_clear()
4) cl_init() with meter 4 params -> read AV4 -> cache AV4 -> read meter1 registers -> cl_clear()

And so:

1) cl_init() with meter 1 params -> load AV1 from cache AV1 -> read meter1 registers -> cl_clear()
etc.

And in case of same model of meter, AV could be the same.

Cannot (and don't want) save to (emulated...) EEPROM and use the serializer. Also, I don't want to read the AV every time because it's very very slow and I cannot have polling times of several minutes for all the meters.

Simply, I wish to deep copy settings.objects and reuse after. From the main program, from the Arduino IDE (that is C++ not ANSI C) I just tried a simple object copy:

objectArray* objects = DLMSClient.GetObjects();
objectArray copy = *objects;

Where (from the Arduino example):

objectArray* GXDLMSClient::GetObjects()
{
return &settings.objects;
}

After cl_clear() the objectArray copy contains previous size and capacity... but copy.data is gone. So I fear that i shallow copy happens, probably due to the multiple indirection due to the pointer of pointer...

for (int pos = 0; pos < copy.size; pos++) {
printf("%d", copy.data[pos]->shortName);
}

It prints shortnames if before cl_clear(), all zeros after cl_clear() and new cl_init().

I tried to explicitly copy the objects, without success:

for (int pos = 0; pos < objects->size; pos++) {
copy.data[pos] = objects->data[pos];
}

All gone with the cl_clear/cl_init... Any suggestions?

TIA, BR,
Andrea

Profile picture for user Kurumi

Kurumi

4 years 6 months ago

Hi Andrea,

Hi Andrea,

If you know what you want to read the easiest way to handle this is if you define objects that you want to read and don't read the association view at all. Something like this:

gxRegister r;
//Replace logical name with the correct one.
const unsigned char ln[6] = { 0,0,0,0,0,255 };
if ((ret = INIT_OBJECT(r, DLMS_OBJECT_TYPE_REGISTER, ln)) == 0)
{
ret = com_read(BASE(r), 2);
//Handle error.
}

BR,
Mikko

wildstray

4 years 6 months ago

Hi Mikko,

Hi Mikko,
I know, but unluckily I cannot in this way. I have to support various models of meters, I don't have the AV XML export of them all (...this would be the solution of all my problems :-p) or the meters themselves (I have only an L+G E650 for development purposes), and some of them works in SN mode but I knows the LN only... (it's a modbus protocol converter, so I have a mapping between modbus registers and OBIS codes... )

BR,
Andrea

wildstray

4 years 6 months ago

Hi, I i did it...... or a

Hi, I i did it...... or a "sort of" :-p

objectArray* objects = DLMSClient.GetObjects();
objectArray copy = *objects;
copy.data = (gxObject **) malloc (sizeof(gxObject *) * objects->size);
for (int pos = 0; pos < objects->size; pos++) {
copy.data[pos] = (gxObject*) malloc (sizeof (gxObject));
*copy.data[pos] = *objects->data[pos];
}

I can now deep copy and so load after and reuse after the AV... it "just work" but I notice a very strange issue. Data returned by obj_toString after com_read is corrupted... the index 2, the register itself, is correct but random values of indexes 3,4,5,6,7,8,9 are shown...). It happens simply copying and restoring AV as settings.objects... also without cl_clear. While indexes > 2 are correctly shown with original settings.objects.

BR
Andrea

Profile picture for user Kurumi

Kurumi

4 years 6 months ago

Hi,

Hi,

Do it like this:

objectArray* objects = DLMSClient.GetObjects();
objectArray *copy = (objectArray*) malloc (sizeof(objectArray));
oa_init(copy);
gxObject* it;
for (uint16_t pos = 0; pos < objects->size; ++pos)
{
oa_getByIndex(objects, pos, &it);
oa_push(copy, it);
}

BR,
Mikko

wildstray

4 years 6 months ago

Hi, unlucily same problem I

Hi, unlucily same problem I had before copying the objects in my way: Just tried but the objects dont' survive to cl_clear()...

BR,
Andrea

Profile picture for user Kurumi

Kurumi

4 years 6 months ago

Hi Andrea,

Hi Andrea,

Get the latest version and find com_readAllObject. Uncomment the code and it will read the association view and serialize objects to the EEPROM.

com_getAssociationView is also modified. It parses association view objects one at a time to reduce memory usage.

BR,
Mikko

BR,
Mikko

wildstray

4 years 5 months ago

I cannot make the serializer

I cannot make the serializer to compile :( Moreover, I would not use the EEPROM emulation because I found it's frail (eg. no wear leveling) and so small, totally inadeguate for this purpose. So i did the trick in this way:
1) Client.init() with a fake server number
2) for loop for every configured meter
3) Client.reuse() ** with real connection parameters
4) com_initializeConnection()
5) Client.GetObjects()
6) if objects list is empy, do com_getAssociationView() and com_readScalerAndUnits(), else do nothing
7) Client.findObjectByLN() for every configured LN
8) com_read() and so on
9) com_close()

** I added this little method:

void GXDLMSClient::reuse(bool useLogicalNameReferencing, int clientAddress, int serverAddress, DLMS_AUTHENTICATION authentication, const char* password, DLMS_INTERFACE_TYPE interfaceType)
{
settings.useLogicalNameReferencing = useLogicalNameReferencing;
settings.clientAddress = clientAddress;
settings.serverAddress = serverAddress;
settings.authentication = authentication;
bb_addString(&settings.password, password);
}

In this way I can reuse only one client instance and share only one AV, with a simplest and lighter code. I don't need to store the AV because in case of reboot, it will be read again one time only.

Obviously, all the meters on the bus has to be identical!

BR,
Andrea

Profile picture for user Kurumi

Kurumi

4 years 5 months ago

Hi,

Hi,

You don't need to serialize all objects. You can also save only the list of Logical Names and Object types (Short Names in your case) and use that.
But collectors usually are powered all the time, so your idea is working well if all the meters are the same brand and usually, they are. :-)

BR,
Mikko

  • Create new account
  • Reset your password

Hire Us!

Latest Releases

  • Tue, 06/09/2026 - 11:16
    gurux.dlms.java 4.0.95
  • Tue, 06/09/2026 - 10:03
    Gurux.DLMS.Python 1.0.199
  • Mon, 06/08/2026 - 13:39
    gurux.dlms.cpp 9.0.2606.0801
  • Mon, 06/01/2026 - 10:15
    gurux.dlms.cpp 9.0.2606.0101
  • Thu, 05/28/2026 - 16:06
    gurux.dlms.java 4.0.94

New forum topics

  • Error reading L&G Meter
  • Pass a TCP Client to GXNet
  • Australian EDMI Mk10D (Essential Energy area)
  • Strange mix of data notificiation vs get response
  • DLMS Connection
More

Who's new

  • Tuanhgg
  • Adel
  • charnon
  • Paddles
  • Miguel Ángel
RSS feed
Privacy FAQ GXDN Issues Contact
Follow Gurux on Twitter Follow Gurux on Linkedin