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. DLMS.c Client Association View Reduce RAM Memory For Microcontroller

DLMS.c Client Association View reduce RAM memory for microcontroller

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 alex_engine , 14 April, 2020
Forums
Gurux.DLMS

When requesting an information model, a complete accumulation of useful data (PDU) in RAM occurs, and then parsing of all objects. At the same time, my project does not have enough memory to store the entire buffer of useful data. Is there a way to parse objects one at a time with freeing useful data (PDU) from the buffer?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

I propose that you don't read association view at all. Create objects what you want to read and read only them. Something like this:

gxRegister r;
const unsigned char ln[6] = { 1,1,21,25,0,255 };
INIT_OBJECT(r, DLMS_OBJECT_TYPE_REGISTER, ln);

You need to know the OBIS code and object type.
BR,
Mikko

alex_engine

6 years 1 month ago

Reading an information model

Reading an information model is a project requirement. I see the output only in object-by-object parsing of the model with clearing the processed part of the buffer.

alex_engine

6 years 1 month ago

Is it possible to change the

Is it possible to change the program to implement the following algorithm: Receive the next portion of useful data (PDU), start the dlms_getValueFromData function, if at least one whole object is received, then we clear the processed useful data buffer and the procedure is repeated.?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

Can you use malloc with your compiler? We have use cl_parseObjectCount and cl_parseNextObject methods when we have use compiler where is no malloc. Get the latest version and try this:
BR,
Mikko

int ret;
message data;
gxReplyData reply;

mes_init(&data);
reply_init(&reply);
unsigned short pos, count;
gxObject obj;
//We are not interested from the access modes.
//If you want to know the access modes allocate enought space for them.
obj.access = NULL;

if ((ret = cl_getObjectsRequest(&connection->settings, &data)) != 0 ||
(ret = com_readDataBlock(connection, &data, &reply)) != 0 ||
(ret = cl_parseObjectCount(&reply.data, &count)) != 0)
{
printf("GetObjects failed %s\r\n", hlp_getErrorMessage(ret));
}
if (ret == 0)
{
for (pos = 0; pos != count; ++pos)
{
if ((ret = cl_parseNextObject(&reply.data, &obj)) != 0)
{
break;
}
//Read object data.
///////////////////////////////////////////////////////////////////////////////////
// Profile generics are read later because they are special cases.
// (There might be so lots of data and we so not want waste time to read all the data.)
if (obj.objectType == DLMS_OBJECT_TYPE_PROFILE_GENERIC)
{
continue;
}
}
}

BR,
Mikko

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

In reply to Is it possible to change the by alex_engine

Hi,

Hi,

This is supported by other programming languages, but we are removing support for this at some point. This is not possible to use when ciphering is used and companies are moving to start use ciphering.

BR,
Mikko

alex_engine

6 years 1 month ago

Can you use malloc with your

Can you use malloc with your compiler? - yes. Maybe it makes sense to abandon the dynamic allocation of memory? But then how to properly configure static buffers?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

It's great if you can use malloc because it makes everything easier. If you can't use malloc, you need to use static buffers and it's a pain when you are reading historical (profile generics) or complex data.

Use the code above and start to read the values.

BR,
Mikko

alex_engine

6 years 1 month ago

//Read object data.

//Read object data.
/////////////////////////////////////////////////////////////////////////////////// -
what function for this operation?

alex_engine

6 years 1 month ago

Your solution allows to parse

Your solution allows to parse objects after receiving a full buffer of useful data (PDU). The my problem is getting the entire amount of data of the info model from the counter in the com_readDataBlock function. Is it possible to parse objects "on the fly" parsing the response from the meter?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

It's not possible to parse objects "on the fly". You need to read all data. Is this problem with historical data (Profile Generics). If it is, you can use readByEntry and readByRange methods to read data from the buffer example day by day.

BR,
Mikko
BR,
Mikko

alex_engine

6 years 1 month ago

Good afternoon! My task is to

Good afternoon! My task is to obtain an information model in the form of a table containing only class types and obis codes and store it in the microcontroller's RAM. I do not need to have fully filled objects. Maybe this can be somehow implemented without parsing a completely read buffer, and checking for the presence of an entire object in the buffer, parse it and clear the buffer, read on?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

If you want to only handle association view it might be possible because the structure is not too complicated. Try with this:

int ret;
message data;
gxReplyData reply;

mes_init(&data);
reply_init(&reply);
unsigned short position = 0, pos = 0, count = 0;
gxObject obj;
//We are not interested from the access modes.
//If you want to know the access modes allocate enought space for them.
obj.access = NULL;
if ((ret = cl_getObjectsRequest(&connection->settings, &data)) != 0)
{
printf("GetObjects failed %s\r\n", hlp_getErrorMessage(ret));
}
gxByteBuffer rr;
bb_init(&rr);
//Send data.
if ((ret = readDLMSPacket(connection, data.data[0], &reply)) != DLMS_ERROR_CODE_OK)
{
return ret;
}
//Get object count on the first time.
if (count == 0)
{
if ((ret = cl_parseObjectCount(&reply.data, &count)) != 0)
{
return ret;
}
bb_trim(&reply.data);
}
//Check is there errors or more data from server
do
{
for (; pos != count; ++pos)
{
reply.data.position = 0;
if ((ret = cl_parseNextObject(&reply.data, &obj)) != 0)
{
reply.data.position = reply.data.size;
break;
}
else
{
bb_trim(&reply.data);
}
}
if ((ret = cl_receiverReady(&connection->settings, reply.moreData, &rr)) != DLMS_ERROR_CODE_OK)
{
bb_clear(&rr);
return ret;
}
if ((ret = readDLMSPacket(connection, &rr, &reply)) != DLMS_ERROR_CODE_OK)
{
bb_clear(&rr);
return ret;
}
bb_clear(&rr);
} while (reply_isMoreData(&reply));
for (; pos != count; ++pos)
{
reply.data.position = 0;
if ((ret = cl_parseNextObject(&reply.data, &obj)) != 0)
{
reply.data.position = reply.data.size;
break;
}
else
{
bb_trim(&reply.data);
}
}
mes_clear(&data);
reply_clear(&reply);

BR,
Mikko

alex_engine

6 years 1 month ago

for (; pos != count; ++pos)

for (; pos != count; ++pos)
{
reply.data.position = 0;
if ((ret = cl_parseNextObject(&reply.data, &obj)) != 0)
{
reply.data.position = reply.data.size;
break;
}
else
{
// It never goes into this part of the code. And the memory is not freed
bb_trim(&reply.data);
}
}

alex_engine

6 years 1 month ago

// It never goes into this

// It never goes into this part of the code. And the memory is not freed
bb_trim(&reply.data);

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

What is the object count? Can you post first reply from the meter?

BR,
Mikko

alex_engine

6 years 1 month ago

object count is 432!

object count is 432!

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

Can you post the first reply from the meter?

BR,
Mikko

alex_engine

6 years 1 month ago

first answer from meter is:

first answer from meter is: 7E A0 83 41 02 21 52 1C 14 E6 E7 00 C4 02 81 00 00 00 00 01 00 6C 01 82 01 B0 02 04 12 00 08 11 01 09 06 00 00 01 00 00 FF 02 02 01 09 02 03 0F 01 16 01 00 02 03 0F 02 16 01 00 02 03 0F 03 16 01 00 02 03 0F 04 16 01 00 02 03 0F 05 16 01 00 02 03 0F 06 16 01 00 02 03 0F 07 16 01 00 02 03 0F 08 16 01 00 02 03 0F 09 16 01 00 01 06 02 02 0F 01 03 00 02 02 0F 02 03 00 02 02 0F 03 03 03 02 02 42 7B 7E

alex_engine

6 years 1 month ago

from this code: //Send data.

from this code: //Send data.
if ((ret = readDLMSPacket(connection, data.data[0], &reply)) != DLMS_ERROR_CODE_OK)
{
return ret;
}
//Get object count on the first time.

alex_engine

6 years 1 month ago

Hi! I think that function "cl

Hi! I think that function "cl_parseNextObject" work not right.

alex_engine

6 years 1 month ago

Hi!

Hi!
Maybe you need some more information on the responses from the counter?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

This is fixed. Get the latest version from the source codes. Let me know if you have any problems.

BR,
Mikko

alex_engine

6 years 1 month ago

You fixed the address size

You fixed the address size check. This has already been fixed in my code. The problem in parsing the info model in the code you proposed remains.
for (; pos != count; ++pos)
{
reply.data.position = 0;
if ((ret = cl_parseNextObject(&reply.data, &obj)) != 0)
{
reply.data.position = reply.data.size;
break;
}
else
{
bb_trim(&reply.data); //In the debug it is clear that we never get here.!!!!!!!!!!!!!!
}
}

alex_engine

6 years 1 month ago

cl_parseNextObject never

cl_parseNextObject never return 0....

alex_engine

6 years 1 month ago

And you have not seen a

And you have not seen a program dlms meter emulator?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

This is tested with DLMS meters and it works like expected. cl_parseNextObject fails on the first time because all the data is not received to parse the first object. Amount of access rights is huge.

If you paste the second row in the trace I can check this.

BR,

Mikko

alex_engine

6 years 1 month ago

first packet:

first packet:
00> 7E A0 83 41 02 21 52 1C 14 E6
00> E7 00 C4 02 81 00 00 00 00 01
00> 00 6C 01 82 01 B0 02 04 12 00
00> 08 11 01 09 06 00 00 01 00 00
00> FF 02 02 01 09 02 03 0F 01 16
00> 01 00 02 03 0F 02 16 01 00 02
00> 03 0F 03 16 01 00 02 03 0F 04
00> 16 01 00 02 03 0F 05 16 01 00
00> 02 03 0F 06 16 01 00 02 03 0F
00> 07 16 01 00 02 03 0F 08 16 01
00> 00 02 03 0F 09 16 01 00 01 06
00> 02 02 0F 01 03 00 02 02 0F 02
00> 03 00 02 02 0F 03 03 03 02 02
00> 42 7B 7E
parse count 432
cl_parseNextObject = (DLMS_ERROR_CODE)ret DLMS_ERROR_CODE_INVALID_PARAMETER

packet 2:
00> 7E A0 83 41 02 21 74 28 50 E6
00> E7 00 C4 02 81 00 00 00 00 02
00> 00 6C 0F 04 03 00 02 02 0F 05
00> 03 00 02 02 0F 06 03 03 02 04
00> 12 00 0F 11 01 09 06 00 00 28
00> 00 00 FF 02 02 01 08 02 03 0F
00> 01 16 01 00 02 03 0F 02 16 01
00> 01 04 0F 01 0F 02 0F 03 0F 04
00> 02 03 0F 03 16 01 00 02 03 0F
00> 04 16 01 00 02 03 0F 05 16 01
00> 00 02 03 0F 06 16 01 00 02 03
00> 0F 07 16 01 00 02 03 0F 08 16
00> 01 00 01 04 02 02 0F 01 03 00
00> 81 EF 7E
cl_parseNextObject = (DLMS_ERROR_CODE)ret DLMS_ERROR_CODE_INVALID_PARAMETER

packet 3:
00> 7E A0 83 41 02 21 96 34 94 E6
00> E7 00 C4 02 81 00 00 00 00 03
00> 00 6C 02 02 0F 02 03 00 02 02
00> 0F 03 03 00 02 02 0F 04 03 00
00> 02 04 12 00 0F 11 01 09 06 00
00> 00 28 00 01 FF 02 02 01 08 02
00> 03 0F 01 16 01 00 02 03 0F 02
00> 16 01 01 04 0F 01 0F 02 0F 03
00> 0F 04 02 03 0F 03 16 01 00 02
00> 03 0F 04 16 01 00 02 03 0F 05
00> 16 01 00 02 03 0F 06 16 01 00
00> 02 03 0F 07 16 00 00 02 03 0F
00> 08 16 01 00 01 04 02 02 0F 01
00> CA FE 7E
cl_parseNextObject = (DLMS_ERROR_CODE)ret DLMS_ERROR_CODE_INVALID_PARAMETER

packet4:
00> 7E A0 83 41 02 21 B8 48 5C E6
00> E7 00 C4 02 81 00 00 00 00 04
00> 00 6C 03 00 02 02 0F 02 03 00
00> 02 02 0F 03 03 00 02 02 0F 04
00> 03 00 02 04 12 00 0F 11 01 09
00> 06 00 00 28 00 02 FF 02 02 01
00> 08 02 03 0F 01 16 01 00 02 03
00> 0F 02 16 01 01 04 0F 01 0F 02
00> 0F 03 0F 04 02 03 0F 03 16 01
00> 00 02 03 0F 04 16 01 00 02 03
00> 0F 05 16 01 00 02 03 0F 06 16
00> 01 00 02 03 0F 07 16 00 00 02
00> 03 0F 08 16 00 00 01 04 02 02
00> B9 1C 7E
cl_parseNextObject = (DLMS_ERROR_CODE)ret DLMS_ERROR_CODE_INVALID_PARAMETER

packet 5:
00> 7E A0 83 41 02 21 DA 5C 1C E6
00> E7 00 C4 02 81 00 00 00 00 05
00> 00 6C 0F 01 03 00 02 02 0F 02
00> 03 00 02 02 0F 03 03 00 02 02
00> 0F 04 03 00 02 04 12 00 17 11
00> 01 09 06 00 00 16 00 00 FF 02
00> 02 01 09 02 03 0F 01 16 01 00
00> 02 03 0F 02 16 01 00 02 03 0F
00> 03 16 01 00 02 03 0F 04 16 01
00> 00 02 03 0F 05 16 01 00 02 03
00> 0F 06 16 01 00 02 03 0F 07 16
00> 01 00 02 03 0F 08 16 01 00 02
00> 03 0F 09 16 01 00 01 00 02 04
00> 8C 3D 7E
cl_parseNextObject = (DLMS_ERROR_CODE)ret DLMS_ERROR_CODE_INVALID_PARAMETER

packet 6:
00> 7E A0 83 41 02 21 FC 68 58 E6
00> E7 00 C4 02 81 00 00 00 00 06
00> 00 6C 12 00 13 11 01 09 06 00
00> 00 14 00 00 FF 02 02 01 09 02
00> 03 0F 01 16 01 00 02 03 0F 02
00> 16 01 00 02 03 0F 03 16 01 00
00> 02 03 0F 04 16 01 00 02 03 0F
00> 05 16 01 00 02 03 0F 06 16 00
00> 00 02 03 0F 07 16 00 00 02 03
00> 0F 08 16 00 00 02 03 0F 09 16
00> 00 00 01 00 02 04 12 00 07 11
00> 01 09 06 00 00 5E 07 00 FF 02
00> 02 01 08 02 03 0F 01 16 01 00
00> 55 C2 7E
cl_parseNextObject = (DLMS_ERROR_CODE)ret DLMS_ERROR_CODE_INVALID_PARAMETER

alex_engine

6 years 1 month ago

more packets?

more packets?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

I know the reason. Your meter is using version 0 from Association LN. It returns access_mode as boolean where other versions return enum. Because Association LN is not the first item in the association view we don't know the used version and this fails.

This is now improved and tests are started. New version is released today.

BR,
Mikko

alex_engine

6 years 1 month ago

However, with a full poll of

However, with a full poll of the info model, the com_getAssociationView function worked!

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

Yes, as I told in the previous post, in full read we know the Association LN version. Now it's unknown because it's not the first item. The first item is the clock.

BR,
Mikko

alex_engine

6 years 1 month ago

Good! How soon can I expect

Good! How soon can I expect fix?

Profile picture for user Kurumi

Kurumi

6 years 1 month ago

Hi,

Hi,

The new version is released just a few minutes ago.

BR,
Mikko

alex_engine

6 years 1 month ago

Cool! Thank you for

Cool! Thank you for efficiency!

alex_engine

6 years 1 month ago

Everything works, thanks for

Everything works, thanks for the help! The topic can be closed.

  • 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