I've been trying to get the Load Profile data from an L+G E355 meter based on date range, but have been unable to successfully.
The normal Read of 1.0.99.1.0.255 does work, but the entire profile data is huge and takes minutes to download, hence the need to apply date range.
So far I've come up with the code snippet below, the meter responds correctly, I've seen the responses, but the return from ReadRowsByRange in GXDLMSReader.cs throws an exception.
public object[] ReadRowsByRange(GXDLMSProfileGeneric it, DateTime start, DateTime end)
{
WriteTrace("*** ReadRowsByRange from " + start + " to " + end + " ***");
GXReplyData reply = new GXReplyData();
ReadDataBlock(Client.ReadRowsByRange(it, start, end), reply);
return (object[])Client.UpdateValue(it, 2, reply.Value); // THROWS EXCEPTION HERE
}
CODE SNIPPET from Program.cs in Gurux.DLMS.Client.Example.Net
DateTime start = DateTime.Now.AddDays(-1).Date;
DateTime end = start.AddDays(1);
GXDLMSObject dlmsObject = settings.client.Objects.FindByLN(ObjectType.None, it.Key);
GXDLMSProfileGeneric dlmsProfile = dlmsObject as GXDLMSProfileGeneric;
dlmsProfile.From = start;
dlmsProfile.To = end;
GXDLMSCaptureObject dlmsCaptureObject = new GXDLMSCaptureObject(2, 0);
dlmsProfile.CaptureObjects.Add( new GXKeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(dlmsProfile, dlmsCaptureObject) );
object[] values = reader.ReadRowsByRange(dlmsProfile, start, end);
reader.ShowValue(values, it.Value);
The EXCEPTION message is simply "The number of columns does not match."
Could you please provide feedback.
I have a feeling that this may not be the correct method, but the other posted suggestion to similar questions do not work for me.
Meter comms session to the point the exception is thrown:
*** ReadRowsByRange from 5/18/2023 12:00:00 AM to 5/19/2023 12:00:00 AM ***
TX: 2:59:50 PM 7E A0 5F 03 41 36 33 A6 E6 E6 00 C8 51 30 71 F4 D0 EB EA 0B 28 A8 F5 8F CC A1 FC 4B E4 B9 83 A3 B3 0F AF 1A CC 89 90 19 90 B8 FE 42 39 5C 2F 83 CE 17 F2 E9 C3 1E 59 16 31 35 F4 A2 AC BA 47 71 69 F1 77 76 66 FE 68 7E E4 CC C6 5C 51 18 C3 91 CB 7D 2E 8F 86 9A 20 C5 07 6B 95 94 91 D6 2F 77 7E
TX: 2:59:55 PM 7E A0 5F 03 41 36 33 A6 E6 E6 00 C8 51 30 71 F4 D0 EB EA 0B 28 A8 F5 8F CC A1 FC 4B E4 B9 83 A3 B3 0F AF 1A CC 89 90 19 90 B8 FE 42 39 5C 2F 83 CE 17 F2 E9 C3 1E 59 16 31 35 F4 A2 AC BA 47 71 69 F1 77 76 66 FE 68 7E E4 CC C6 5C 51 18 C3 91 CB 7D 2E 8F 86 9A 20 C5 07 6B 95 94 91 D6 2F 77 7E
RX: 3:00:00 PM 7E A8 89 41 03 92 C7 6A E6 E7 00 CC 82 03 1C 30 00 00 18 1C F2 17 D6 3C 79 A3 E5 41 AC CE F8 67 AB 65 F9 C5 2C C1 2F A6 53 59 41 B7 39 15 08 93 7F EF 69 9A 94 95 0F E1 68 27 ED 34 BF F7 21 67 52 DE D7 27 24 6F D7 44 B0 54 2F 1C DB D0 FE 2E AF 8D 87 07 80 AA 62 B2 00 56 A1 61 7F D7 4C 64 AA BD 6C 12 1A 05 B2 15 B0 DA B8 03 EE 9C E6 4A C6 ED AA 57 AD CC 0C CA EE 3E 87 0D 05 AB E1 C2 9B 50 11 5F BE 9D 54 47 C5 77 7E 7E A0 07 41 03 91 50 81 7E
TX: 3:00:00 PM 7E A0 07 03 41 51 44 81 7E
RX: 3:00:00 PM 7E A8 89 41 03 94 F1 0F 98 C9 4E 86 62 43 4B B0 7F 2C 89 2A 1A 41 F0 12 57 77 B2 34 07 5D AA FC C7 53 B2 64 59 A6 A0 5C C8 03 EE DA 57 D3 54 9F 09 10 21 D5 E2 C9 5F 0D E7 E4 F8 BD BB 38 E2 C4 42 6A 45 BC BF 81 92 43 2C 7F 03 13 8A 06 43 E8 D2 83 50 61 1B F4 32 1E 6A CA 60 8B 51 82 D1 47 C7 B2 23 01 5F E7 E9 C2 FD 5C 60 0A F9 44 D8 52 1D 0E 71 7B A9 EF 06 D5 90 A4 2E 0F 18 8C E4 B3 19 D7 ED 55 E1 F1 3C 10 24 E2 7E
TX: 3:00:00 PM 7E A0 07 03 41 71 46 A0 7E
RX: 3:00:00 PM 7E A8 89 41 03 96 E3 2C 2C 3D 10 98 7A A5 4A 8A CD 04 F0 4B 89 BC 20 38 6C 41 32 DA 90 D1 00 BB B0 E4 67 B9 18 21 CC 1A 1A BE F1 52 7A 2E 09 43 9A A7 3B F4 48 5E D6 E3 BD C1 F2 04 59 46 B7 0A E5 89 E7 E3 AF BF 48 CC EA D5 73 F3 2C BD 9D BD E7 2A A6 EA F9 7E 59 39 DF 93 F9 FC BF F6 35 A6 17 EE 20 B1 C5 FC A6 2D CA 68 73 99 F1 E4 0E 51 AB 5A 42 4C FA 90 67 4E AE 81 21 E6 2A D4 29 5B 2B DA 85 26 31 9E 6E 91 84 14 7E
TX: 3:00:00 PM 7E A0 07 03 41 91 48 47 7E
RX: 3:00:00 PM 7E A8 89 41 03 98 9D C5 E7 0A 0D 98 2B 21 B2 73 BB CE 19 A1 BF 1A 31 31 7E 75 17 39 E8 1B 30 EE 07 F3 D1 5D A7 F2 06 35 A7 4B B8 A7 56 BB 5F FA DD DC 33 01 2F A5 7C E5 D7 6C 38 58 3F 3B 43 23 A4 04 30 27 72 27 74 FE 2B FB DA ED B4 25 94 CE 59 00 E2 F1 C4 AC B0 F8 35 D6 29 62 33 92 DB 82 FC CF 1E BF 1A DE 5B 55 1F 45 83 BD D6 1A 54 C3 9C 33 0B 39 08 8D CD 7F A8 32 B8 73 AF 92 2E 38 33 AD 6F F7 49 39 48 1D 5B 92 7E
TX: 3:00:00 PM 7E A0 07 03 41 B1 4A 66 7E
RX: 3:00:00 PM 7E A8 89 41 03 9A 8F E6 A1 5C EB 72 F3 46 91 1C 79 C9 DA 52 EF 94 B7 D4 A5 7F 00 FA 5F 8A 05 14 D0 78 06 9C 3D 71 29 A0 F8 AD 76 89 DA F8 C8 8D F4 D4 D8 1B F6 AB 87 E7 5C 4A 14 EB 98 8B B3 EC 5D 49 60 B5 9B 2D 4C BC C5 88 2A 87 2D C4 4A B8 08 2B 39 9E 4D AA 5E B5 98 44 81 89 90 58 CD DC F0 E2 31 EA C2 13 83 CC F6 41 64 76 C9 60 6C 78 E2 8C AC 85 00 C6 85 61 9A B1 6F 57 0C 36 5A 02 1E 76 7C 47 ED 7B 03 90 2B 65 7E
TX: 3:00:00 PM 7E A0 07 03 41 D1 4C 05 7E
RX: 3:00:00 PM 7E A8 89 41 03 9C B9 83 EB D5 C5 A4 71 01 2D 78 08 50 40 27 78 27 28 2A 6D E2 52 CD 96 8C E8 BD 6A AE 4E F8 5E C6 A7 1C 59 F6 20 3F 12 FF 89 E3 5A 9E EC 9F 54 8B 55 64 C9 21 C6 A1 C1 B4 CF A4 8F BF B8 56 C5 D3 CD EB B4 24 B2 20 48 52 BC 65 CA 09 84 1B DB 2E 96 46 B2 58 50 12 64 57 BE B7 FF E9 BB 39 25 E1 D6 6A 4C DD 02 D2 7A 8E 74 5F 78 E3 61 A0 3B C0 DB 46 E1 98 BB 47 AD E3 C4 86 EE 36 02 99 75 27 36 14 66 EC 7E
TX: 3:00:00 PM 7E A0 07 03 41 F1 4E 24 7E
RX: 3:00:00 PM 7E A0 2C 41 03 9E E1 36 E8 73 6B 2E 67 46 95 F1 87 76 F7 81 DC B1 C6 CE 34 65 BB C9 C4 74 99 BF 66 91 EE 62 05 15 A5 B2 7F 88 C9 71 B1 7E
TX: 3:00:00 PM 7E A0 26 03 41 18 69 CD E6 E6 00 C8 18 30 71 F4 D0 EC 28 96 D5 3C 98 A6 A4 52 03 97 DC D6 0F 1C AF 3A 4B 2A 87 05 4A 7E
RX: 3:00:01 PM 7E A8 89 41 03 B0 D7 68 E6 E7 00 CC 82 01 49 30 00 00 18 1D 2D F2 DB FB 00 02 0B 50 1A 3A A8 CC F5 E3 90 08 31 3E 98 11 6F 94 4D 22 34 B6 BD B8 75 D3 A4 72 D0 44 61 E4 A5 FF 83 1C FA 35 D1 96 0A C7 59 B8 6B 41 99 E2 15 5C B1 CD D1 CD F2 3A 37 EC 0A ED DE 5B 18 68 84 37 38 3A 46 1F 31 57 EC BB 25 68 53 87 31 BF E1 1D 8B 96 C2 94 6B EF D5 60 C4 D5 1B 37 DF 77 93 C7 91 D2 CD EF 14 A2 6D 6C 7E E0 47 8A 62 22 E4 08 7E
TX: 3:00:01 PM 7E A0 07 03 41 31 42 E2 7E
RX: 3:00:01 PM 7E A8 89 41 03 B2 C5 4B F5 9C A9 23 B0 E9 47 F5 24 2C 9E 1A E6 5B DB 5C B8 11 A4 0A C9 5A 36 CD DA 80 E3 4D 72 74 55 FA 8B 03 B7 71 74 E1 B2 21 08 A9 A4 AA 90 47 10 DF 3C C1 6F 48 1A 28 F1 0C 81 C4 DD CA 4B AC E8 B3 59 C4 C0 F8 23 D9 A8 C1 CC E9 5C 7E 08 11 8A 58 59 62 88 C7 EC DB B9 89 EE 70 10 7E ED 85 C1 FA 40 B2 ED 4F 79 FC B2 3D 6F 82 86 FE FD 12 C1 B4 E6 6C 16 9C A7 7A FA 71 B8 4C 91 50 DB 40 A4 BA 9C CA 7E
TX: 3:00:01 PM 7E A0 07 03 41 51 44 81 7E
RX: 3:00:01 PM 7E A0 59 41 03 B4 AB 8C CD E5 B9 B9 80 75 38 AF BA 29 A0 DA 6F 74 D0 DD F1 E2 F9 F5 1B C4 C8 B1 46 CF 01 2B 68 2D 11 8D 34 FD 73 B9 30 0A 29 71 C7 D2 1E F4 C1 6B 1E 6C 0B 82 7C F4 16 87 D7 4D B7 57 01 71 75 6C 08 A1 22 DD C8 25 45 72 07 02 93 B5 49 E3 A7 AA E1 E4 52 F8 7E
Hi, All L+G meters don't…
Hi,
All L+G meters don't support deviation and it's causing problems if used with some meters.
Try to give start and end time with GXDateTime and set the Skip property something like this:
GXDateTime start = new GXDateTime(DateTime.Now.AddDays(-1).Date);
GXDateTime end = new GXDateTime(start.AddDays(1));
start.Skip = DateTimeSkips.Deviation;
end.Skip = DateTimeSkips.Deviation;
Some meters experts that seconds and minutes are zero, so try with that also.
BR,
Mikko
Hi Mikko, Many thanks for…
Hi Mikko,
Many thanks for the reply. I've tried out your suggestions, but the result is the same, either throwing an exception (when I add to dlmsCaptureObject), or getting the response 'Capture objects not read' when I don't add.
ReadRowsByRange in GXDLMSClient has a clause on entry that if CaptureObjects == 0, it throws an exception with the 'Capture objects not read', hence the reason for me attempting to add my profile request to the dlmsCaptureObject.
What I've done doesn't seem right, but it is almost working. I see the responses from the meter for the Load Profile, and setting break points I can see that the reply.value (prior to the UpdateValue call in ReadRowsByRange in the GXDLMSReader class) contains what appears to be the load profile structure, and the values look reasonable.
My derived method is nothing like what I have seen in other forum communications, so I may simply not have the fundamentals in place. I'm lacking documentation on this topic and therefore value your input in the correct approach to initiating comms with the meter, through association and onto setting up the generic profile and ultimately the load profile read and parse.
it.Key is "1.0.99.1.0.255" on entry, GetAssocitionView is complete without error.
GXDLMSObject dlmsObject = settings.client.Objects.FindByLN(ObjectType.None, it.Key);
GXDLMSProfileGeneric dlmsProfile = dlmsObject as GXDLMSProfileGeneric;
GXDateTime start = new GXDateTime(DateTime.Now.AddDays(-1).Date);
GXDateTime end = new GXDateTime(start.Value.AddDays(1));
start.Skip = DateTimeSkips.Deviation;
end.Skip = DateTimeSkips.Deviation;
//GXDLMSCaptureObject dlmsCaptureObject = new GXDLMSCaptureObject(2, 0);
//dlmsProfile.CaptureObjects.Add(new GXKeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(dlmsProfile, dlmsCaptureObject));
object[] values = reader.ReadRowsByRange(dlmsProfile, start, end);
reader.ShowValue(values, it.Value);
The commented out lines are where I added to the CaptureObjects.
Hoping you can push us forward to identifying out root cause issue.
Hi, You need to read capture…
Hi,
You need to read capture objects before you can read the buffer. You can do it like this:
reader.Read(dlmsProfile, 3)
After capture objects are read, you can read the buffer.
https://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSProfileGeneric
Hi Kurumi, Thanks, makes…
Hi Kurumi,
Thanks, makes sense now. I just hadn't made the connection between the attribute index and the read, even though in researching this I'd already seen that index 3 was indeed capture objects.
Seems I now have my own access rights issue to read back attribute index 3, but that's not your issue.
Once I've got that sorted I will send you a message to confirm that everything is working.
Again, many thanks for your assistance.
Hi Mikko. All good on my…
Hi Mikko.
All good on my last point(s) regarding our issues with profile generic, mostly lack of understanding (which you cleared up) and partly due to not having the right level of access credentials for our test meters. We can now read attribute ID 3 level which gives us the capture objects we needed.
Our code at this point is: (it.Key is "1.0.99.1.0.255", LOAD PROFILE)
GXDateTime start = new GXDateTime(DateTime.Now.Date.AddDays(-2));
GXDateTime end = new GXDateTime(start.Value.AddDays(2));
start.Skip = DateTimeSkips.Deviation;
end.Skip = DateTimeSkips.Deviation;
GXDLMSObject dlmsObject = settings.client.Objects.FindByLN(ObjectType.None, it.Key);
GXDLMSProfileGeneric dlmsProfile = dlmsObject as GXDLMSProfileGeneric;
object co = reader.Read(dlmsProfile, 3);
object lpObject = reader.ReadRowsByRange(dlmsProfile, start, end);
The lpObject comes back with 193 objects (96, 15 minute intervals = 24 hours), but only the first lpObject[0] shows data, all the other records (intervals) have the same number of channels, but the values are null.
In a different project/solution where we can sniff the traffic, the volume of data is consistent with our 193 objects, but fails to parse as such on the output of ReadRowsByRange.
Example: Visual Studio 2022 watch
lpObject {object[0x000000c1][]} object {object[][]}
>[0] {object[0x0000000e]} object[]
>[0] {5/06/2023 12:00:00 am} object {Gurux.DLMS.GXDateTime}
[1] 0x00 object {byte}
[2] 0x00000000 object {int}
[3] 0x00000000 object {int}
[4] 0x00000000 object {int}
[5] 0x00000000 object {int}
[6] 0x00000000 object {int}
[7] 0x00000000 object {int}
[8] 0x00000000 object {int}
[9] 0x00000000 object {int}
[10] 0x00000000 object {int}
[11] 0x00000000 object {int}
[12] 0x00000000 object {int}
[13] 0x00000000 object {int}
>[1] {object[0x0000000e]} object[]
>[0] null object
[1] null object
[2] null object
[3] null object
[4] null object
[5] null object
[6] null object
[7] null object
[8] null object
[9] null object
[10] null object
[11] null object
[12] null object
[13] null object
We've been stuck at this point for a number of days now, haven't solved it ourselves, so are reaching out to you for your insight and wisdom for a solution.
Test project is derived from Gurux.DLMS.Client.Example.Net.
We have another application from a third party which does read out and parse the load profile correctly.
Hi, There is a date time in…
Hi,
There is a date time in the first row and it's correct, but all other values are zero and it looks strange. Because I don't have the block cipher key, I can't check from the bytes what the meter is returning.
Are you getting the correct output if you read all the values? If you do, you need to check that the date and times are correct. Some meters are returning invalid data if the date-time is in a different format than the meter expects.
BR,
Mikko
BR,
Mikko
Hi Mikko, I've been drilling…
Hi Mikko,
I've been drilling into the library functionality around interpreting responses from our meter, and actually it looks like it's working correctly, though L+G return the first structure in the array in it's complete form and the second record padded with 'none' for zero (or empty records).
This example is slightly different to the last performing midnight read for two days and hence only two records. Much easier to trace through.
What I'm presenting here is the unencrypted, stripped down data payload from one of the lower layers (GXDLMS.cs). I would have sent a file, but I realize that it only accepts images, so apologies for the length of this post.
So, this is an array of two structures, each structure with 14 elements, and as mentioned before, appearing to parse correctly.
What I don't understand are the 24 bytes which are additional to the array/structure data. Could you tell me what they are?
0x01 Type - Array
0x02 Object Count
0x02 Type - Structure
0x0e Object Count
0x09 Type - OctetString
0x0c Length
0x07 Value - Date Structure
0xe7
0x06
0x06
0x02
0x00
0x00
0x00
0x00
0xfd
0xa8
0x00
0x11 Type - UInt8
0x00 Value - ??? Status
0x06 Type - UInt32
0x00 Value
0x00
0x99
0xd8
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x04
0xb3
0x06 Type - UInt32
0x00 Value
0x00
0x99
0xd8
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x04
0xb3
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x06 Type - UInt32
0x00 Value
0x00
0x00
0x00
0x02 Type - Structure
0x0e Object Count
0x00 None
0x11 Type - UInt8
0x80 Value
0x06 Type - UInt32
0x00 Value
0x00
0x9a
0x8b
0x00 None
0x00 None
0x06 Type - UInt32
0x00 Value
0x00
0x04
0xbc
0x06 Type - UInt32
0x00 Value
0x00
0x9a
0x8b
0x00 None
0x00 None
0x06 Type - UInt32
0x00 Value
0x00
0x04
0xbc
0x00 None
0x00 None
0x00 None
0x00 None - Last actual item in array of structures
0x00
0x00
0x00
0x00
0x84
0x34
0x5c
0x5a
0xb5
0x7b
0x0f
0x04
0x34
0x1c
0x85
0x2d
0xe6
0x6c
0xd9
0x00
0x64
0x28
0x26
0x35