I'm using the gurux C library for an AMR project and I'm having problems with writing attributes when the data is too long and needs to be broken into more than one frame (we're using block transfer for get/read and set/write operations).
Here's an example of a complete operation.
DLMS>Connect
TX >>> 7EA01E03CD93F47B8180120501AF0601AF0704000000010804000000015E127E
RX >>> 7EA020CD03737134818014050200AF060200AF070400000001080400000001D20B7E
TX >>> 7EA04603CD10A9FDE6E6006038A1090607608574050801018A0207808B0760857405080201AC0C800A32323232323232323232BE10040E01000000065F1F0400001E1D00A9D4027E
RX >>> 7EA037CD03306ED0E6E7006129A109060760857405080101A203020100A305A103020100BE10040E0800065F1F040000181D00AC000782667E
DLMS>WriteObjComplexAttr 0.128.21.0.1.255 1 2 18
TX >>> 7EA0B503CD325FADE6E600C102C100010080150001FF02000000000001819501120911010100000902FF020030303120202020200911010100000901FF020030303220202020200911030100010800FF020030303320202020200911030100010801FF020030303420202020200911030100010802FF020030303820202020200911030100010804FF020030303920202020200911030100020800FF020031303320202020200911030100020801FF020031303495EE7E
RX >>> 7EA013CD0352C56DE6E700C502C1000000010F037E
TX >>> 7EA0B503CD546FABE6E600C103C100010080150001FF02000000000002819520202020200911030100020802FF020031303820202020200911030100020803FF020031303620202020200911030100020804FF020031303920202020200911030100050800FF020030323420202020200911030100070802FF02003132342020202020091101000060321AFF0200303838202020202009110301800C2080FF0200000000000000000009110301800C2480FF02006C707E
RX >>> 7EA014CD0374D07EE6E700C503C111000000010C207E
TX >>> 7EA04D03CD768C3BE6E600C103C100010080150001FF020001000000032E00000000000000000911030180202480FF020000000000000000000911030180342480FF0200000000000000000055657E
RX >>> 7EA014CD0396CCBAE6E700C503C1120100801512FB7E
DLMS>Disconnect
TX >>> 7EA00703CD533A877E
RX >>> 7EA007CD037303EC7E
The meter is aborting the operation after the second frame is sent, when I translate this second frame it's possible to see something wrong with the block number (it should be 00000002):
<HDLC len="B4" >
<TargetAddress Value="1" />
<SourceAddress Value="66" />
<!--I frame.-->
<FrameType Value="54" />
<PDU>
<SetRequest>
<SetRequestWithDataBlock>
<!--Priority: HIGH ServiceClass: CONFIRMED invokeID: 1-->
<InvokeIdAndPriority Value="C1" />
<DataBlock>
<LastBlock Value="00" />
<BlockNumber Value="01008015" />
<RawData Value="01FF02000000000002819520202020200911030100020802FF020031303820202020200911030100020803FF020031303620202020200911030100020804FF020031303920202020200911030100050800FF020030323420202020200911030100070802FF02003132342020202020091101000060321AFF0200303838202020202009110301800C2080FF0200000000000000000009110301800C2480FF0200" />
</DataBlock>
</SetRequestWithDataBlock>
</SetRequest>
</PDU>
</HDLC>
Comparing this to an operation using the meter's oficial software I noticed something, the software only adds the attributeDescriptor data to the first frame, but using gurux(C) this attributeDescriptor is being added to every frame.
Second frame from meter's software:
7EA0B503CD546FABE6E600C103C10000000002...
Second frame from gurux C:
7EA0B503CD546FABE6E600C103C100010080150001FF02000000000002...
The wrong block number we're seeing on the translator is actually a piece of this attributeDescriptor (that should not be there).
This is the piece of code on the gurux library where this attributeDescriptor is added to the frame: (file: dlms.c on function: dlms_getLNPdu)
// Add attribute descriptor.
if (ret == 0 && p->attributeDescriptor != NULL)
{
ret = bb_set(reply, p->attributeDescriptor->data, p->attributeDescriptor->size);
}
Since the attributeDescriptor is not being cleared between one frame and the next, nor there's any condition so it's only set on the first frame, the code is always entering this condition and writing the attributeDescriptor on every frame. I added a line to clear the attributeDescriptor buffer after its use and now the operation works properly.
// Add attribute descriptor.
if (ret == 0 && p->attributeDescriptor != NULL)
{
ret = bb_set(reply, p->attributeDescriptor->data, p->attributeDescriptor->size);
bb_clear(p->attributeDescriptor);
}
DLMS>Connect
TX >>> 7EA01E03CD93F47B8180120501AF0601AF0704000000010804000000015E127E
RX >>> 7EA020CD03737134818014050200AF060200AF070400000001080400000001D20B7E
TX >>> 7EA04603CD10A9FDE6E6006038A1090607608574050801018A0207808B0760857405080201AC0C800A32323232323232323232BE10040E01000000065F1F0400001E1D00A9D4027E
RX >>> 7EA037CD03306ED0E6E7006129A109060760857405080101A203020100A305A103020100BE10040E0800065F1F040000181D00AC000782667E
DLMS>WriteObjComplexAttr 0.128.21.0.1.255 1 2 18
TX >>> 7EA0B503CD325FADE6E600C102C100010080150001FF02000000000001819501120911010100000902FF020030303120202020200911010100000901FF020030303220202020200911030100010800FF020030303320202020200911030100010801FF020030303420202020200911030100010802FF020030303820202020200911030100010804FF020030303920202020200911030100020800FF020031303320202020200911030100020801FF020031303495EE7E
RX >>> 7EA013CD0352C56DE6E700C502C1000000010F037E
TX >>> 7EA0B503CD546FABE6E600C103C10000000002819F20202020200911030100020802FF020031303820202020200911030100020803FF020031303620202020200911030100020804FF020031303920202020200911030100050800FF020030323420202020200911030100070802FF02003132342020202020091101000060321AFF0200303838202020202009110301800C2080FF0200000000000000000009110301800C2480FF020000000000000000000911C80E7E
RX >>> 7EA013CD0374F129E6E700C502C10000000294317E
TX >>> 7EA03903CD762513E6E600C103C1010000000324030180202480FF020000000000000000000911030180342480FF02000000000000000000C96E7E
RX >>> 7EA014CD0396CCBAE6E700C503C100000000031ABC7E
DLMS>Disconnect
TX >>> 7EA00703CD533A877E
RX >>> 7EA007CD037303EC7E
Note: When you open the guruxDLMSTranslator 'messages' tab there's an example of an operation and it is a block transfer operation, there it's possible to see that the attributeDescriptor is only present on the first frame of data.
Is this an actual bug or am I missing something?
Hi, Are you using malloc?…
Hi,
Are you using malloc? Can you share the data that you want to write so I can check it?
BR,
Mikko
Hello, Yes, we are using…
Hello,
Yes, we are using malloc. It happens on every operation that needs LongSetOrWrite, for example:
Writing Activity Calendar passive day table:
Data being written: (formatted as "Time LN scriptSelector")
DayType: 1
00:00:00 0.0.10.0.100.255 1
01:01:00 0.0.10.0.100.255 1
01:03:00 0.0.10.0.100.255 3
01:10:00 0.0.10.0.100.255 1
01:11:00 0.0.10.0.100.255 2
01:12:00 0.0.10.0.100.255 3
DayType: 2
02:01:00 0.0.10.0.100.255 1
11:29:00 0.0.10.0.100.255 2
02:20:00 0.0.10.0.100.255 1
02:21:00 0.0.10.0.100.255 2
Operation with bb_clear(p->attributeDescriptor):
DLMS>Connect
TX >>> 7EA00703CD9336417E
RX >>> 7EA020CD037371348180140502008006020080070400000001080400000001CE6A7E
TX >>> 7EA04603CD10A9FDE6E6006038A1090607608574050801018A0207808B0760857405080201AC0C800A32323232323232323232BE10040E01000000065F1F0400001E1DFFFFA7CA7E
RX >>> 7EA037CD03306ED0E6E7006129A109060760857405080101A203020100A305A103020100BE10040E0800065F1F040000181D00AC000782667E
DLMS>WriteObjAttr 0.0.13.0.0.255 20 9
TX >>> 7EA88603CD966E7DE6E600C102C1001400000D0000FF09000000000001819801020202110101060203090400000000090600000A0064FF1200010203090401010000090600000A0064FF1200010203090401030000090600000A0064FF12000302030904010A0000090600000A0064FF12000102030904010B0000090600000A0064FF120022E47E
RX >>> 7EA007CD03911F287E
TX >>> 7EA03B03CD9823240202030904010C0000090600000A0064FF1200030202110201040203090402010000090600000A0064FF120001020309040BAFEC7E
RX >>> 7EA013CD03B89125E6E700C502C1000000010F037E
TX >>> 7EA04903CDBA0045E6E600C103C10100000002341D0000090600000A0064FF1200020203090402140000090600000A0064FF1200010203090402150000090600000A0064FF120002784B7E
RX >>> 7EA014CD03DAA432E6E700C503C1000000000293AD7E
DLMS>Disconnect
TX >>> 7EA00703CD533A877E
RX >>> 7EA007CD037303EC7E
Operation without bb_clear(p->attributeDescriptor):
DLMS>Connect
TX >>> 7EA00703CD9336417E
RX >>> 7EA020CD037371348180140502008006020080070400000001080400000001CE6A7E
TX >>> 7EA04603CD10A9FDE6E6006038A1090607608574050801018A0207808B0760857405080201AC0C800A32323232323232323232BE10040E01000000065F1F0400001E1DFFFFA7CA7E
RX >>> 7EA037CD03306ED0E6E7006129A109060760857405080101A203020100A305A103020100BE10040E0800065F1F040000181D00AC000782667E
DLMS>WriteObjAttr 0.0.13.0.0.255 20 9
TX >>> 7EA88603CD966E7DE6E600C102C1001400000D0000FF09000000000001819801020202110101060203090400000000090600000A0064FF1200010203090401010000090600000A0064FF1200010203090401030000090600000A0064FF12000302030904010A0000090600000A0064FF12000102030904010B0000090600000A0064FF120022E47E
RX >>> 7EA007CD03911F287E
TX >>> 7EA03B03CD9823240202030904010C0000090600000A0064FF1200030202110201050203090402010000090600000A0064FF120001020309040BD4E87E
RX >>> 7EA013CD03B89125E6E700C502C1000000010F037E
TX >>> 7EA06603CDBAAA78E6E600C103C1001400000D0000FF09000100000002471D0000090600000A0064FF1200020203090402140000090600000A0064FF1200010203090402150000090600000A0064FF1200020203090402160000090600000A0064FF12000339107E
RX >>> 7EA014CD03DAA432E6E700C503C111000000010C207E
DLMS>Disconnect
TX >>> 7EA00703CD533A877E
RX >>> 7EA007CD037303EC7E
Note that the second operation ends with LongSetOrWriteAborted (just before the disconnect)