Environment:
- Gurux.DLMS.NET 9.0.2605.2801 (latest release at time of writing), Gurux.Net 8.4.2604.201, .NET 8
- HDLC over TCP, SN (short-name) referencing (UseLogicalNameReferencing = false)
- Landis+Gyr E650, HDLC negotiated MaxInfoTX=128 / MaxInfoRX=62, window size 1
Symptom:
A single ReadList/Read-Request with a list of ~12 or more short names comes back with every value null — no per-item DataAccessResult error, no exception, TotalCount correct, just every entry in the returned object[] is null. The same call with a smaller list (e.g. 2–3 items) returns correct, real values every time.
Confirmed this is not a meter/network issue:
I captured the raw HDLC bytes for a failing 30-item read and decoded them independently in GXDLMSDirector's DLMS Translator. The meter's response is complete and correct — ReadResponse Qty="1E" with 30 valid Data elements (real Int32/UInt32/UInt8 values, no DataAccessError entries). So the meter is answering correctly; the client is misparsing a good reply.
I also reproduced this from a bare-metal script driving GXDLMSClient directly (no application code of ours in the loop) against the same meter, with the exact 30 short names from the capture — same result: correct request goes out, meter responds correctly (confirmed via the translator decode of the same session), client-side result comes back all-null.
Suspected root cause (reading through Gurux.DLMS.GXDLMS.HandleReadResponse in this version):
private static bool HandleReadResponse(GXDLMSSettings settings, GXReplyData reply, int index)
{
int num = reply.TotalCount;
bool flag = num == 0 || reply.CommandType == 2;
if (flag)
{
num = (reply.TotalCount = GXCommon.GetObjectCount(reply.Data));
}
...
if (num != 1)
{
if (reply.IsMoreData)
{
GetDataFromBlock(reply.Data, 0);
return false;
}
if (!flag)
{
reply.Data.Position = 0;
}
...
}
...
for (int i = 0; i != num; i++)
{
SingleReadResponse singleReadResponse;
if (flag)
{
singleReadResponse = (SingleReadResponse)reply.Data.GetUInt8(); // consumes per-item tag
reply.CommandType = (byte)singleReadResponse;
}
else
{
singleReadResponse = (SingleReadResponse)reply.CommandType; // does NOT consume it
}
...
}
When the response arrives in one HDLC frame, flag is true on the (only) call, TotalCount is parsed, and each item's SingleReadResponse tag byte is correctly consumed per-iteration.
When the response is segmented across multiple frames, HandleReadResponse is invoked once per frame. On the first call (IsMoreData == true), it only extracts TotalCount and returns early — no items are parsed yet. On the final call (IsMoreData == false), flag is now false (since TotalCount is already nonzero from the earlier call), which means:
reply.Data.Position = 0 resets the cursor to the start of the entire accumulated buffer (including the already-consumed count-prefix byte from the first call), and
the per-item loop takes the else branch for every iteration, which never consumes the per-item tag byte — it just reuses whatever reply.CommandType was cached from the very first call.
The net effect looks like a stream misalignment: the loop ends up reading GetValueFromData at the wrong offsets for the whole pass, and every item decodes as null/garbage rather than the correct value. This matches what I'm seeing exactly: batches small enough to arrive in one HDLC frame always work; batches that force segmentation always come back all-null, regardless of the actual values on the wire.
This looks structurally related to the HandleGetResponseWithList bug fixed in commit 918b84a (a segmented list response misparsing null values due to a position-tracking issue) — but that fix only touches HandleGetResponseWithList, the LN Get-Request-With-List path. HandleReadResponse, the SN Read-Request path, doesn't appear to have received an equivalent fix and still shows this behavior in the current 9.0.2605.2801 release.
Repro conditions, if useful for a test case:
SN referencing, any meter/simulator that supports multi-item Read-Request
A list of short names large enough that the reply requires more than one HDLC frame (in my case, a small negotiated MaxInfoRX of 62 bytes made this easy to hit at ~12 items with 6-byte-per-item Int32 responses)
Compare a request that fits in one frame vs. one that doesn't — the former always works, the latter always returns nulls
Happy to share the exact capture bytes and my trace if that helps track it down
I'm looking into…
I'm looking into implementing a fix. Will send PR if I get it working.
PR created: https://github…
PR created: https://github.com/Gurux/Gurux.DLMS.Net/pull/13
What is the status of this…
What is the status of this PR? Do you accept PRs? Do I need to fix the format? What can I do to get this fix merged sooner?
Hi, This is now been tested…
Hi,
This is now been tested with the Landis+Gyr E650 and it worked without problems. Can you add the communication hex trace so this can be verified?
Regards,
Mikko
Sure, here they are2026-09…
Sure, here they are
The decoded messages (using GXDLMSDirector's DLMS Translator tool):
The decoded multiple register read request (assembled from message 13 and 15):
The decoded response (assembled from messages 16, 18, 20 and 22):
Let me know if you need more information.
Hi Kurumi I really need this…
Hi Kurumi
I really need this fix to land to complete my project. Did I misunderstand you? Did you need something else? What is blocking the merge of this PR?
Hi, This is under testing,…
Hi,
This is under testing, and it's in the next release.
Because the Gurux libraries are dual-licensed, all changes must be checked carefully and it takes time.
Regards,
Mikko
Hi, The reason this hasn't…
Hi,
The reason this hasn't been released is that you didn't send the meter reply. There is only a read request, and the meter reply messages are missing. It's not possible to verify this without that information.
We can read the Landis+Gyr E650 without problems, so your meter must have different firmware.
Please, add the hex trace so this can be verified.
BR,
Mikko
Hi Mikko. Understood. Let me…
Hi Mikko. Understood. Let me try to give you more details.
First, the device details: It's a Landis+Gyr E650 meter running B32 firmware.
0.0.96.240.0.255 => B32.G 12.09.04
1.0.0.2.0.255 => B32
Then, I'm not sure I understand what you need in the hex trace. The first code block I sent does contain the hex trace, but you need to scroll to the right since it's at the end of the log line. I will clean up and remove the prefixes a bit so it's clearer.
Just to be clear: the issue is not the DLMS communication and trace on the wire. The issue is when the response is parsed after the final packet came in. Even before the change GXDLMSDirector decoded the data fine in the Messages tab of the Gurux DLMS Translator. When I manually copied all the parts of the segmented message into the Pdu tab and decoded, I got the expected decoded 23 values. The issue was the parse loop for SN referencing with MultipleReferences. That loop had an issue causing all the values to be returned as null even though the meter responded with valid values.
Hi, I'm sorry. My mistake. I…
Hi,
I'm sorry. My mistake. I'll check this tomorrow and let you know the outcome.
BR,
Mikko
Thank you. Please let me…
Thank you. Please let me know if you require anything else from me.
Hi, Good news. We were able…
Hi,
Good news. We were able to reproduce the issue, and it has now been fixed. The tests are running, and a new version will be released later today.
BR,
Mikko
Hi, This is fixed in version…
Hi,
This is fixed in version 9.0.2609.2201.
BR,
Mikko
Thank you, can confirm: it's…
Thank you, can confirm: it's fixed.