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. Questions and Issues of The Release "gurux.dlms.c 20201221.1"

Questions and issues of the release "gurux.dlms.c 20201221.1"

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 lara.wakim , 21 December, 2020
Forums
General discussion

Hello,

We downloaded the latest release covering the special day table and we started the testing.

- We added today as a special day in order to be able to test :
index = 0 special day date = 1/1 dayID = 3
index = 1 special day date = 6/3/2021 dayID = 3
index = 2 special day date = 12/21/2020 dayID = 2

- We reached the svr_handleActivityCalendar() function: we are looping using pos2 on the special day present in the table ((gxSpecialDaysTable*)obj)->entries.size = 3 and then comparing the special day to our current date. For the third entry the special day and current date will be equal "time_compare2(&sd->date, time) == 0". Everything is correct till now.

- But after verifying that the special day and current date are equal the logic is wrong. In fact, you used the pos3 to loop again on the special day table (useless because we already know that we are a special day) instead of looping simply on the day schedule. What you should do is that knowing that the dayId related to our special day is 2 (check above) you should looping on the schedule day of the dayId table number 2 then check the start time and trigger the svr_invoke like you did on the line 3856 in the server.c file.

So simply replace :
for (pos3 = 0; pos3 != ((gxSpecialDaysTable*)obj)->entries.size; ++pos3)
{
if ((ret = arr_getByIndex2(&((gxSpecialDaysTable*)obj)->entries, pos3, (void**)&da, sizeof(gxDayProfileAction))) != 0)

by APPROXAMITEVELY:

dp->dayId = DAY ID OF THE SPECIAL DAY (in our example dayID = 2)
for (pos4 = 0; pos4 != dp->daySchedules.size; ++pos4)
{
if ((ret = arr_getByIndex2(&dp->daySchedules, pos4, (void**)&da, sizeof(gxDayProfileAction))) != 0)

Hope it is clear enough if you need more information feel free to ask.

Best Regards,

Lara Wakim

lara.wakim

5 years 5 months ago

Hi Mikko,

Hi Mikko,

Sadly the tariffication script table write issue is still not fixed. In fact when we are initializing the tariffication script in the addTarifficationScriptTable() function, you added the following which is very clever as idea:
//Action data is register activation mask name (RATE1).
strcat(MASK1, "RATE1");
GX_OCTET_STRING(ACTIONS1[0].parameter, MASK1, 5);

But there is 2 problems (check the picture):
1- instead of making the parameters.vt = DLMS_DATA_TYPE_OCTET_STRING (9) it is equal to 137 weirdly
2 - the byteArr is giving "error reading characters of string"

So when we are triggering the tariffication script and reaching the invoke_ScriptTable() function with "sa->type == DLMS_SCRIPT_ACTION_TYPE_WRITE" the "sa->parameter.vt = 137 != DLMS_DATA_TYPE_OCTET_STRING" so the byteArr is still empty and the cosem_setValue() function is still throwing the same exception. If you please can check it again.

Let me add that hte same problem is happening with current active tariff:
cosem_setValue()-> cosem_setData() -> or value->vt = 137 != 9 -> cosem_getVariant() -> the function bb_getUInt8() is throwing the same exception.

We also noticed that after the prewrite() function in the invoke_ScriptTable() you didn't change
"if (!e->handled)". You have to check it because we are pretty sure that you should replace :
"if (!e->handled)" by "if (!e1->handled)".

Best Regards,

Lara Wakim

Image
Profile picture for user Kurumi

Kurumi

5 years 5 months ago

Hi,

Hi,

Get the latest version. It will fix your problems.
BR,
Mikko

lara.wakim

5 years 5 months ago

Hello Mikko,

Hello Mikko,

We downloaded the latest version and we are glad to say that most of the issues are solved especially the:
- Tariffication script table write issue
- Special day table checking -> check the dayId table -> check the start time -> trigger the tariffication script table with the desired selector --> trigger the writing of the active mask of the register activation and write the current tariff

One problem remains:
If our current date is not a special day, it will check the season profile then the week profile. This is working like expected. But when reaching the day profile in the function svr_handleActivityCalendar() line 3995 pos3 is looping on the day profile active table to check the correct dayId -> the pos4 will loop on the day profile schedule, compare the start time then trigger the svr_invokeScript() (line 4020). There is 2 problems:

1- First svr_invokeScript() function will again repeat the same work (loop on the dayProfile then the daySchedule then compare the start time). So we are doing the same work twice. After these same steps in the svr_invokeScript() it will finally trigger the tariffication script through invoke_ScriptTable() (line 3854). The issue is that in case we are not a special day we are never reaching the invoke_ScriptTable() due to the repetition, so we will never be able to trigger the tariffication script.

2- Second ret = svr_invokeScript(settings, &object->dayProfileTableActive, da->scriptSelector, time)
The third argument represents the active dayId or you are passing the scriptSelector

Our suggestion is to simply replace the loop pos3 in the svr_handleActivityCalendar() function by the code written in case we are a special day (check the following and the picture) to avoid the repetition and maybe check if the function svr_invokeScript() needs some optimization.

//Invoke day profile
if ((ret = svr_invokeScript(settings, &object->dayProfileTableActive, dayId, time)) != 0)
{
break;
}
return ret;

We tested with the above replacement and it worked like expected.

If you need more explanation or information feel free to ask.

Best Regards,

Lara Wakim

Image

lara.wakim

5 years 5 months ago

Hi,

Hi,

We discovered another problem concerning the season profile. In fact in order to repeat it you have to switch the season date from:
DST start = 4/1/* week name= 1
Normal start = 11/1/* week name= 2
to:
DST start = 11/1/* week name= 1
Normal start = 4/1/* week name= 2

So we expected when comparing the start time of each season, the active season should be the "DST" but surprisingly it was the "normal". So we noticed, regardless the start date of the seasons the "time_compare2(&tm, time)" is always different from 1 so it is always the last row season in the table that it is considerate as active. The logic of the active season is different from the active schedule of the day.

Taking our case, you should check each time, in which interval our current date 12/22 is included:
- if date between 11/1/* and 4/1/* (MONTHS : 11, 12, 1, 2, 3) -> active season = DST
- if date between 4/1/* and 11/1/* (MONTHS : 4, 5, 6, 7, 8, 9, 10) -> active season = Normal
=> so the active season = DST => week name= 1 => and the rest is correct

If you please correct to match the above logic.

Best Regards,

Lara Wakim

lara.wakim

5 years 5 months ago

Hello Mikko,

Hello Mikko,

First let me wish you a happy holidays!

Hope everything is well.

Second, we faced a kind of limitation in the code that we want you to solve. In fact, we are initializing the register activation object like needed, we have 56 objects in the register assignment list. When trying to read this object it is giving in access hardware fault error. So we followed the code and discovered in the cosem_getRegisterActivation() function for the index equal to 2 when reaching pos = 39 (object number 40) the bytebuffer data has its size equal to 516 > maxPDUSize = 512. So the bb_set() function -> bb_allocate() function is returning the "DLMS_ERROR_CODE_OUTOFMEMORY" because we have "(bb_getCapacity(arr) < index + dataSize)".

If it is possible to solve it so we can read all the register assignment list maybe by sending the information through multiples pdu packets.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hello Mikko, by lara.wakim

Hi,

Hi,

You are right. This is now fixed. Get the latest version.

BR,
Mikko

lara.wakim

5 years 5 months ago

Hi,

Hi,

Let me highlight another problem with the register activation.

First we changed the attribute access so we can have the right to write the active mask of the register activation directly from the GXDLMSDirector.
Then we tried to write the active mask using the client. Following the code, it reaches the cosem_setRegisterActivation() function -> index number 4 -> or value->vt == (DLMS_DATA_TYPE_OCTET_STRING | DLMS_DATA_TYPE_BYREF) so first we will clear the old active mask using "bb_clear(&object->activeMask);" and then write the new active mask using "ret = bb_set(&object->activeMask, value->pVal, value->size);" or we discovered when we are reaching this function the value->size is equal to 0 so the new active mask has a size equal to 0 so we were not able to read the new active mask on the client side due to the size.

If you please can check it and solve this problem so we will be able to write the active mask directly if needed.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hi, by lara.wakim

Hi,

Hi,

The current implementation expects that season profiles are in order. We have two possibilities here. Values are saved in order or then they are listed in the correct order. At the moment I believe that svr_handleActivityCalendar is changed so values are retrieved in order is the best way to solve this. I need to think about this a little bit.

BR,
Mikko

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hello Mikko, by lara.wakim

Hi,

Hi,

Can you increase the Max PDU size from 512? It's the fastest way to solve this. We'll modify the register activation so this is handled and this is released next week.

BR,
Mikko

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hi, by Kurumi

Hi,

Hi,

This is improved. Get the latest version.
BR,
Mikko

lara.wakim

5 years 5 months ago

Hi Mikko,

Hi Mikko,

We made some changes in the tariffication script table that leaded us to some issues.

In fact we replaced the octet string by uint8 for the currentActiveTariff object:

In the addCurrentlyActiveTariff() replaced:
GX_OCTET_STRING(currentlyActiveTariff.value, TARIFF, 0)
by
GX_UINT8(currentlyActiveTariff.value) = 1;

In the addTarifficationScriptTable() replaced:
GX_OCTET_STRING(ACTIONS1[1].parameter, MASK1, strlen(MASK1));
by
GX_UINT8(ACTIONS1[1].parameter) = 1;

So when executing the tariffication script table ID=1, first it wrote the active mask of the register activation then it tried to write the value of the current active tariff so it went to:
cosem_setValue()-> cosem_setData() -> cosem_updateVariant() or value->vt = DLMS_DATA_TYPE_UINT8 so it went to cosem_getVariant() -> so in this function it cleared the value using "var_clear" then the bb_getUInt8() throws an exception.

We believed that there is something wrong because cosem_setData has a goal to write and set the new value not to get variant. If you please check it.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hi, by lara.wakim

Hi,

Hi,

This is improved. Now you can change the active mask using write and not just with the script. Get the latest version.

BR,
Mikko

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hi Mikko, by lara.wakim

Hi,

Hi,

It fails because the active mask is octet-string and now you try to write int value. We'll add a check here to verify that the value must be an octet-string or an error is returned.

BR,
Mikko

lara.wakim

5 years 5 months ago

Hello,

Hello,

We think that you got us wrong. We are trying to write uint8 value for the current active tariff object (type gxData) and not the active mask of the register activation. Check the picture it will clear the misunderstanding.

Best regards,

Lara Wakim

Ps: in case the picture is not clear you can track the changes with [LW]

//Add Currently active tariff object.
int addCurrentlyActiveTariff()
{
int ret;
static unsigned char TARIFF[10];
const unsigned char ln[6] = { 0, 0, 96, 14, 0, 255 };
if ((ret = INIT_OBJECT(currentlyActiveTariff, DLMS_OBJECT_TYPE_DATA, ln)) == 0)
{
GX_UINT8(currentlyActiveTariff.value) = 1; // [LW]
//GX_OCTET_STRING(currentlyActiveTariff.value, TARIFF, 0); // [LW]
}
return ret;
}

///////////////////////////////////////////////////////////////////////
//Add tariffication script table object.
///////////////////////////////////////////////////////////////////////
int addTarifficationScriptTable()
{
int ret;
static gxScript SCRIPTS[4] = { 0 };
static gxScriptAction ACTIONS1[2] = { 0 };
static gxScriptAction ACTIONS2[2] = { 0 };
const unsigned char ln[6] = { 0, 0, 10, 0, 100, 255 };
static unsigned char MASK1[MAX_REGISTER_ACTIVATION_MASK_NAME_LENGTH];
static unsigned char MASK2[MAX_REGISTER_ACTIVATION_MASK_NAME_LENGTH];
if ((ret = INIT_OBJECT(tarifficationScriptTable, DLMS_OBJECT_TYPE_SCRIPT_TABLE, ln)) == 0)
{
SCRIPTS[0].id = 1; //rate 1
SCRIPTS[1].id = 2; //rate 2

ARR_ATTACH(tarifficationScriptTable.scripts, SCRIPTS, 2);
ARR_ATTACH(SCRIPTS[0].actions, ACTIONS1, 2);
ACTIONS1[0].type = DLMS_SCRIPT_ACTION_TYPE_WRITE;
ACTIONS1[0].target = BASE(registerActivation);
ACTIONS1[0].index = 4;
//Action data is register activation mask name (RATE1).
strcat(MASK1, "RATE1");
GX_OCTET_STRING(ACTIONS1[0].parameter, MASK1, 5);

ACTIONS1[1].type = DLMS_SCRIPT_ACTION_TYPE_WRITE;
ACTIONS1[1].target = BASE(currentlyActiveTariff);
ACTIONS1[1].index = 2;
//Action data is register activation mask name (RATE1).
//GX_OCTET_STRING(ACTIONS1[1].parameter, MASK1, strlen(MASK1)); // [LW]
GX_UINT8(ACTIONS1[1].parameter) = 1; // [LW]

ARR_ATTACH(SCRIPTS[1].actions, ACTIONS2, 2);
ACTIONS2[0].type = DLMS_SCRIPT_ACTION_TYPE_WRITE;
ACTIONS2[0].target = BASE(registerActivation);
ACTIONS2[0].index = 4;
//Action data is register activation mask name (RATE2).
strcat(MASK2, "RATE2");
GX_OCTET_STRING(ACTIONS2[0].parameter, MASK2, 5);

ACTIONS2[1].type = DLMS_SCRIPT_ACTION_TYPE_WRITE;
ACTIONS2[1].target = BASE(currentlyActiveTariff);
ACTIONS2[1].index = 2;
//Action data is register activation mask name (RATE2).
//GX_OCTET_STRING(ACTIONS2[1].parameter, MASK2, strlen(MASK2)); // [LW]
GX_UINT8(ACTIONS2[1].parameter) = 2; // [LW]
}

Image

lara.wakim

5 years 5 months ago

In reply to Hi, by Kurumi

Hi,

Hi,

It worked.

Thank you!

Best Regards,

Lara Wakim

lara.wakim

5 years 5 months ago

In reply to Hi, by Kurumi

Hi,

Hi,

It also worked like expected.

Thank you!

Best Regards,

Lara Wakim

lara.wakim

5 years 5 months ago

In reply to Hi, by Kurumi

Hi Mikko,

Hi Mikko,

In order to understand well what you said we made a test and it was a success. In fact, we changed the start time of the season profile like that:
DST start = 4/1/* week name= 1
Normal start = 12/29/* week name= 2
We are 12/28 so we should be in the DST season and it was successful.

Then we changed again the starting time to:
DST start = 4/1/* week name= 1
Normal start = 12/27/* week name= 2
This time it gave the normal season which is correct.

So like you said the order of the months counts, from the smaller to the bigger one, and the circular concept of the months is not implemented.

What we have till now is more than enough but we think that it will be good but not essential to implement later the circular comparison of the months after exceeding the month 12.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hi Mikko, by lara.wakim

Hi,

Hi,

The circular comparison should work if you give DTS first and Normal time after. Try to set date to 1st of January and it is Normal. The order must be correct. If Normal time (12/29/*) is before DST (4/1/*) it will fail. A new version is released in next week where this is improved.

BR,
Mikko

BR,
Mikko

lara.wakim

5 years 5 months ago

In reply to Hello, by lara.wakim

Hi Mikko,

Hi Mikko,

We tested the latest release and this issue is solved. Thank you.

We were able to switch currentlyActiveTariff from octet string to uint8 and trigger the tariffication script without problem.

Best Regards,

Lara Wakim

lara.wakim

5 years 5 months ago

Hi Mikko,

Hi Mikko,

The handling of the activity calendar is mostly done. There is only one missing piece till now. In fact, we are able to activate the passive calendar to become the active one through the "Activate button". But the activation of the passive calendar should also be time driven based. In other words, we should track the activate passive calendar date/time (attribute number 10) when this date/time is reached we should also activate the passive calendar to become the active.

Can you please implement this feature.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

Hi,

Hi,

This is implemented. Get the latest version.

BR,
Mikko

lara.wakim

5 years 5 months ago

Hi Mikko,

Hi Mikko,

There is a major bug concerning the event notification that should be solved and we think that the problem is due to the client not the server.

Simply follow these steps to repeat the problem:
- Add in the svr_prewrite() function the sendEventNotification() function like following:
if (e->target == BASE(clock1) && e->index == 2)
{
updateState(GURUX_EVENT_CODES_TIME_CHANGE);
sendEventNotification(settings);
}
- Connect the meter and try to write the current time in order to trigger the sendEventNotification() function

The bug should appears: like described before the same message containing the event notification will be send indefinitely to the GXDLMSDirector until the client crashes.

If you can please follow these steps and tell us if the problem appears.
If not, we will make more testing to follow and report the problem.
If yes, it will be easier to you to solve it.

Best Regards,

Lara Wakim

lara.wakim

5 years 5 months ago

Hello,

Hello,

We need your help for implementing an important function.
In fact, we created an object gxData with type value equal to array[2] of bit-string[256]. Now, we are in a position where we want to read the bit in each array, But we don't know how to do it and which function to use.

To remind you, we created this object in that way:
int addEventLogFilter_standardEventLog()
{
int ret;
const unsigned char ln[6] = { 0, 1, 94, 34, 105, 255 };
if ((ret = INIT_OBJECT(eventLogFilter_standardEventLog, DLMS_OBJECT_TYPE_DATA, ln)) == 0)
{
static char BUFFER[2][32];
for (int i = 0; i < 32; i++)
{
//Array[0]=default values: 1 for all bits (all events will be log into the buffer)
BUFFER[0][i] = 0xff;
//Array[1]=default values: 0 for all bit (no event will be sent as notification event)
BUFFER[1][i] = 0;
}
static dlmsVARIANT ARRAY[2];
GX_BIT_STRING(ARRAY[0], BUFFER[0], 256);
GX_BIT_STRING(ARRAY[1], BUFFER[1], 256);
static variantArray tmp;
VA_ATTACH(tmp, ARRAY, 2);
GX_ARRAY(eventLogFilter_standardEventLog.value, tmp);
}
return ret;
}

Now for example the event number 18 happened and we want to check in each array the corresponding bit 18 if it is a 0 or a 1. How are we supposed to do this and with which function? in other words to repeat the same logic but in the reverse.

If you please can guide us to solve that matter.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

Hi Lara,

Hi Lara,

You can use normal Bit handling functions like this to check is the first bit set:
Note! In Bit-string is using Most Significant Bit!

//Set first bit.
bitArray ba;
ba_attach(&ba, ARRAY[0].pVal, ARRAY[0].size, ARRAY[0].size);
ba_setByIndex(&ba, 0, 1);
//Or
BUFFER[0][0] |= 0x80;

//Check first bit.
unsigned char value;
ba_getByIndex(&ba, 0, &value);
if (value != 0)
{
//The first bit is set
}
//Or
if ((BUFFER[0][0] & 0x80) != 0)
{
//The first bit is set
}

BR,
Mikko

lara.wakim

5 years 5 months ago

In reply to Hi Lara, by Kurumi

Hi Mikko,

Hi Mikko,

Thank you for this explanation but sadly it didn't fill our need. In fact, this example is based on the ARRAY or BUFFER variable but the function that we want to write should be independent of these variables, it should only depend on the object "gxData eventLogFilter_standardEventLog" so how can we obtain the same logic but starting with the object gxdata? We are supposing that we should extract the array from the gxdata value then follow the above step but which functions should we use?

If our explanation is not clear enough feel free to ask.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

Hi,

Hi,

This will do what you want:

dlmsVARIANT* item;
//Get item from the array. Index value can be ero or one in your case.
va_getByIndex(eventLogFilter_standardEventLog.value.Arr, 1, &item);
//Attach bit-array.
bitArray ba;
ba_attach(&ba, item->pVal, item->size, item->size);
ret = ba_setByIndex(&ba, 0, 1);
unsigned char value;
ba_getByIndex(&ba, 0, &value);

BR,
Mikko

lara.wakim

5 years 5 months ago

In reply to Hi, by Kurumi

Hello,

Hello,

We followed your example and it worked in order to read the bit. Thank you!

But there is something wrong when setting the bit and especially in the behavior of the ba_setByIndex() function:
- ba1 is all 0: we tried to set some bits to 1:
ba_setByIndex(&ba1, 0, 1);
ba_setByIndex(&ba1, 1, 1);
ba_setByIndex(&ba1, 16, 1);
-> as result the bit 0, 1 and 16 became equal to 1 and all the rest stay equal to 0 like expected:
<BitStringValue="1100000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" />

- but when we tried with ba2 which is all 1: we also tried to set some bits to 0:
ba_setByIndex(&ba2, 0, 0);
ba_setByIndex(&ba2, 1, 0);
ba_setByIndex(&ba2, 16, 0);
-> as result we expected taht the bit 0, 1 and 16 to become equal to 0 and all the rest stay equal to 1
but we noticed that all the byte 1 and byte 3 is equal to 0 like following which is wrong:
<BitStringValue="0000000011111111000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" />

If you please review and correct this.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 5 months ago

In reply to Hi Mikko, by lara.wakim

Hi Lara,

Hi Lara,

This is solved and the new release is coming on Monday where this is fixed.

BR,
Mikko

lara.wakim

5 years 4 months ago

In reply to Hi Lara, by Kurumi

Hello Mikko,

Hello Mikko,

Any update concerning the event notification issue? Is there any problem in the new release or the testing?

If we can help don't hesitate.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 4 months ago

In reply to Hello Mikko, by lara.wakim

Hi,

Hi,

Tests are still in progress. We try to release it as soon as possible.

BR,
Mikko

lara.wakim

5 years 4 months ago

In reply to Hi, by Kurumi

Hi Mikko,

Hi Mikko,

Sorry to bother you, but there is any update or problem concerning the event notification issue? If we can help you don't hesitate to share.

Best Regards,

Lara Wakim

Profile picture for user Kurumi

Kurumi

5 years 4 months ago

In reply to Hi Mikko, by lara.wakim

Hi,

Hi,

That is fixed to GXDLMSDirector. We broke it some time ago. The next version is still in testing. There is a new version released where only this issue is fixed.

BR,
Mikko

lara.wakim

5 years 4 months ago

In reply to Hi, by Kurumi

Hi Mikko,

Hi Mikko,

We tested the latest version of the GXDLMSDirector and the event notification issue is solved.

Thank you!

Best Regards,

Lara Wakim

  • 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