Good day. I am trying to access Profile Generics with obis code 1.0.99.1.0.255 on EDMI Mk7MI meter. I use ESP32 to communicate with it. I can read data in register (voltage, current, wattage, power factor, etc.), but i cannot read profile generics. I tried using both readRowsByEntry and readRowsByRange, but have not succeeded yet. Is there anything wrong in the code or is it the meter that doesn't support the method?
Here's the code I use to read profile generic
int com_readPg()
{
int ret;
int len, month = 0, day = 0, year = 0, hour = 0, minute = 0, second = 0, value = 0;
ret = com_initializeConnection();
if (ret != DLMS_ERROR_CODE_OK)
{
GXTRACE_INT(GET_STR_FROM_EEPROM("com_initializeConnection failed"), ret);
return ret;
}
GXTRACE_INT(GET_STR_FROM_EEPROM("com_initializeConnection SUCCEEDED"), ret);
GXTRACE_INT(GET_STR_FROM_EEPROM("\n"), ret);
char *data = NULL;
char obis[6] = {1,0,99,1,0,255};
gxProfileGeneric pg;
cosem_init(BASE(pg), DLMS_OBJECT_TYPE_PROFILE_GENERIC, obis);
com_read(BASE(pg), 3);
com_read(BASE(pg), 2);
com_readRowsByEntry(&pg, 1, 1);
obj_toString(BASE(pg),&data);
GXTRACE(GET_STR_FROM_EEPROM("Profile register"),data);
gxtime start1, end1;
time_now(&end1);
time_init(&start1,2023,1,1,00,00,00,0000,0);
com_readRowsByRange (&pg, &start1, &end1);
obj_toString(BASE(pg), &data);
GXTRACE(PSTR("Load profile"), data);
// Release dynamically allocated objects.
Client.ReleaseObjects();
com_close();
return ret;
}
Using the code above gives me :
com_read failed. 4 :com_readRowsByEntry failed. 4 :Profile registerIndex: 2 Value: [
]
Index: 3 Value: []
Index: 4 Value: 0
Index: 5 Value: 0
Index: 6 Value:
Index: 7 Value: 0
Index: 8 Value: 0
:com_readRowsByRange failed. 4 :Load profileIndex: 2 Value: [
]
Index: 3 Value: []
Index: 4 Value: 0
Index: 5 Value: 0
Index: 6 Value:
Index: 7 Value: 0
Index: 8 Value: 0
Here's the code I use to read register data (for example i'm going to access voltage value)
gxRegister volt;
cosem_init(BASE(volt), DLMS_OBJECT_TYPE_REGISTER, "1.0.32.7.0.255");
com_read(BASE(volt), 3);
com_read(BASE(volt), 2);
obj_toString(BASE(volt), &data);
datameter.volt = var_toDouble(&volt.value) * pow(10, volt.scaler);
Serial.printf("Volt : %.3f\n", datameter.volt);
obj_clear(BASE(volt));
free(data);
I have success using above code, it will give me something like
Volt: 235.154
in serial monitor.
Hi, Try to read your meter…
Hi,
Try to read your meter with GXDLMSDirector and make sure that there is a data.
Some meters expect that the start and end time are given in exact format.
For example, the seconds and minutes must be zero, etc.
At first, try to change start and end time like this:
time_init(&start1,2023,1,1,00,00,00,0000,0);
time_init(&end1,2023,1,2,00,00,00,0000,0);
This try to read data from one day. Also you don't have enough memory to read values for one year with one request. It's better to read max one day at the time.
BR,
Mikko
Hi Mikko, thank you for the…
Hi Mikko, thank you for the rapid response. I did check the GXDLMSDirector first before developing the client app, and there is a row of data.
After modifying the code, there's some content inside Index 3. Below is the modified code, kindly check the code.
int com_readPg()
{
int ret;
int len, month = 0, day = 0, year = 0, hour = 0, minute = 0, second = 0, value = 0;
ret = com_initializeConnection();
if (ret != DLMS_ERROR_CODE_OK)
{
GXTRACE_INT(GET_STR_FROM_EEPROM("com_initializeConnection failed"), ret);
return ret;
}
GXTRACE_INT(GET_STR_FROM_EEPROM("com_initializeConnection SUCCEEDED"), ret);
GXTRACE_INT(GET_STR_FROM_EEPROM("\n"), ret);
char *data = NULL;
gxProfileGeneric pg;
cosem_init(BASE(pg), DLMS_OBJECT_TYPE_PROFILE_GENERIC, "1.0.99.1.0.255");
com_read(BASE(pg), 3);
com_read(BASE(pg), 2);
// by range
gxtime start1, end1;
time_init(&start1,2023,1,1,00,00,00,0000,0);
time_init(&end1,2023,1,2,00,00,00,0000,0);
com_readRowsByRange (&pg, &start1, &end1);
obj_toString(BASE(pg), &data);
// obj_toString(pg.buffer, &data);
GXTRACE(PSTR("Load profile (range) : "), data);
obj_clear(BASE(pg));
free(data);
// Release dynamically allocated objects.
Client.ReleaseObjects();
com_close();
return ret;
}
At first there are bunch of data send failures, after that there is some content in Index 3, I assume these are the registers which is used for this profile, is that correct? Take a look at the output:
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1 :com_initializeConnection SUCCEEDED 0 :
0 :Received bytes:
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1 :com_read failed. 260 :com_readRowsByRange failed. 130 :Load profile (range)Index: 2 Value: [
]
Index: 3 Value: [Register 1.0.32.7.0.255, Register 1.0.31.7.0.255, Register 1.0.91.7.0.255, Register 1.0.13.7.0.255, Register 1.0.1.7.0.255, Register 1.0.3.7.0.255, Register 1.0.9.7.0.255, Register 1.0.1.9.0.255, Register 1.0.2.9.0.255, Register 1.0.3.9.0.255, Register 1.0.4.9.0.255, Register 1.0.9.8.0.255, Register 1.0.10.8.0.255]
Index: 4 Value: 0
Index: 5 Value: 0
Index: 6 Value:
Index: 7 Value: 0
Index: 8 Value: 0
After some tinkering, i…
After some tinkering, i found that commenting
com_readRowsByRange (&pg, &start1, &end1);
will give the same output (bunch of failure, then read Index 2 to Index 8 with Index 3 having some content), and there is also failure in executing the code (see below)
:com_readRowsByRange failed. 130
Is the code/function that i use wrong? Or is it anything else?
Thanks in advance.
Hi, Some meters return an…
Hi,
Some meters return an error if there are no rows between the start and end time.
Check with GXDLMSDirector what time zone your meter is using.
It might be that your meter expects that start and end time are using the same time zone. Time zone in Finland is 120 so time must initialize like this:
time_init(&start1,2023,1,1,00,00,00,0000,-120);
I don't know what meter you try to read so it might be that you must give time zone as a positive value like this:
time_init(&start1,2023,1,1,00,00,00,0000,120);
You can read more from deviation:
https://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSClock#deviation
All meters don't implement com_readRowsByRange.
Test that with GXDLMSDirector.
I believe that after your settings are the same as your meter expects you can read your meter.
BR,
Mikko
Hi Mikko, I am using EDMI…
Hi Mikko, I am using EDMI Mk7MI meter.
1. Where can I get information about time deviation of a country?
2. What are the settings I should check so I could adjust the settings to match the meter? Since we don't get the document for reference
3. I once had success reading the profile using index (read index = 1, Count = 1), can I use that method instead? Do you have code that can achieve this in C/Arduino code?
I use below code to read by index entry, but no success. Please take a look.
//=============================================
// by entry
com_readRowsByEntry(&pg, 1, 1);
// com_readValues();
// com_readProfileGenericColumns();
// com_readProfileGenerics();
obj_toString(BASE(pg),&data);
// GXTRACE(GET_STR_FROM_EEPROM("Profile register : \n"),data);
Serial.printf("Load profile (entry) : ", &data);
obj_clear(BASE(pg));
free(data);
Thanks in advance.
Hi, 1. The deviation …
Hi,
1. The deviation depends from the meter and how it's configured. Check this:
https://gurux.fi/Gurux.DLMS.Objects.GXDLMSClock#deviation
2. Each meter has different settings.
3. Yes, you can use it, Check com_readRowsByEntry.
https://github.com/Gurux/GuruxDLMS.c/blob/dd80bffc57d89d2826fc6b8647249…
In general, I believe it's easiest if you read your meter with GuruxDLMSClientExample
You can see the correct command line settings in GXDLMSDirector when you select the meter.
You need to call com_readProfileGenericColumns before calling com_readRowsByEntry
BR,
Mikko
Hi Mikko, thank you for the…
Hi Mikko, thank you for the guidance, after I add
com_readProfileGenericColumns()
the values showed. Here are the output, it still give some "data send failed" message :
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1 :Received bytes:
0 :Data send failed. Try to resend. 1Index: 2 Value: [
10/01/2024 00:00:00 | 33 39 30 30 30 30 38 34 32 35 | 1149619 | 1149619 | 0 | 0 | 0 | 5887 | 0 | 846129 | 0 | 0 | 1149605 | 0 | 14 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 26 | 5
07/01/2024 00:00:00 | 33 39 30 30 30 30 38 34 32 35 | 1149619 | 1149619 | 0 | 0 | 0 | 5887 | 0 | 846129 | 0 | 0 | 1149605 | 0 | 14 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 23 | 4
06/01/2024 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 1149619 | 1149619 | 36746 | 0 | 0 | 5887 | 615 | 846129 | 26097 | 26712 | 1149605 | 0 | 14 | 0 | 0 | 0 | 36746 | 0 | 0 | 0 | 0 | 0 | 0 | 169 | 22 | 3
05/01/2024 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 1112873 | 1112873 | 68685 | 0 | 0 | 5272 | 0 | 820032 | 50971 | 50971 | 1112859 | 0 | 14 | 0 | 0 | 0 | 68685 | 0 | 0 | 0 | 0 | 0 | 16 | 179799 | 22 | 3
04/01/2024 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 1044188 | 1044188 | 71502 | 0 | 0 | 5272 | 0 | 769061 | 54676 | 54676 | 1044174 | 0 | 14 | 0 | 0 | 0 | 71502 | 0 | 0 | 0 | 0 | 0 | 15 | 174430 | 22 | 3
03/01/2024 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 972686 | 972686 | 66514 | 0 | 0 | 5272 | 0 | 714385 | 55655 | 55655 | 972672 | 0 | 14 | 0 | 0 | 0 | 66513 | 0 | 1 | 0 |
0 | 0 | 16 | 180534 | 22 | 3
02/01/2024 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 906172 | 906172 | 76117 | 0 | 0 | 5272 | 0 | 658730 | 61951 | 61951 | 906159 | 0 | 13 | 0 | 0 | 0 | 76113 | 0 | 4 | 0 |
0 | 0 | 16 | 140516 | 22 | 3
01/01/2024 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 830055 | 830055 | 76743 | 0 | 0 | 5272 | 0 | 596779 | 61438 | 61438 | 830046 | 0 | 9 | 0 | 0 | 0 | 76743 | 0 | 0 | 0 | 0 | 0 | 16 | 182512 | 22 | 3
12/01/2023 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 753312 | 753312 | 68967 | 0 | 0 | 5272 | 0 | 535341 | 55201 | 55201 | 753303 | 0 | 9 | 0 | 0 | 0 | 68967 | 0 | 0 | 0 | 0 | 0 | 16 | 185565 | 22 | 3
11/01/2023 00:00:00 UTC+00:00 | 33 39 30 30 30 30 38 34 32 35 | 684345 | 684345 | 70646 | 0 | 0 | 5272 | 0 | 480140 | 54801 | 54801 | 684336 | 0 | 9 | 0 | 0 | 0 | 70646 | 0 | 0 | 0 | 0 | 0 | 15 | 159055 | 22 | 3
]
Index: 3 Value: [Clock 0.0.1.0.0.255, Data 0.0.96.1.0.255, Register 1.0.16.8.0.255, Register 1.0.1.8.0.255, Register 1.0.1.9.0.255, Register 1.0.2.8.0.255, Register 1.0.2.9.0.255, Register 1.0.3.8.0.255, Register 1.0.3.9.0.255, Register 1.0.4.8.0.255, Register 1.0.4.9.0.255, Register 1.0.128.8.0.255, Register 1.0.2.8.1.255, Register 1.0.1.8.1.255, Register 1.0.2.8.2.255, Register 1.0.1.8.2.255, Register 1.0.2.8.3.255, Register 1.0.1.8.3.255, Register 1.0.2.9.1.255, Register 1.0.1.9.1.255, Register 1.0.2.9.2.255, Register 1.0.1.9.2.255, Register 1.0.2.9.3.255, Register 1.0.1.9.3.255, ExtendedRegister 1.0.9.6.0.255, Data 0.1.96.7.0.255, Data 0.1.96.20.46.255, Register 0.0.96.6.3.255]
Index: 4 Value: 0
Index: 5 Value: 0
Index: 6 Value:
Index: 7 Value: 0
Index: 8 Value: 0
1. If i understand correctly, the values shown are the value of pg of gxProfileGeneric, is it right?
2. How to print just the content of index 2, as it is what I needed?
3. If I want to save it to a struct so I can use it for another thing, how to accomplish this? For the register data, first I created this struct :
struct dataCollection
{
uint32_t timeUnix;
String serialnumber;
float volt;
float current;
float watt;
float battery;
}
Then i use this to read the register data (again for example I'm going to access voltage value)
gxRegister volt;
cosem_init(BASE(volt), DLMS_OBJECT_TYPE_REGISTER, "1.0.32.7.0.255");
com_read(BASE(volt), 3);
com_read(BASE(volt), 2);
obj_toString(BASE(volt), &data);
datameter.volt = var_toDouble(&volt.value) * pow(10, volt.scaler);
Serial.printf("Volt : %.3f\n", datameter.volt);
obj_clear(BASE(volt));
free(data);
Using gxRegister I can just access the value via volt.value, but in gxProfileGeneric there isn't, so I can't get the data.
It doesn't have to be a struct though, I use it because I think it is simpler. An example of code in C would be greatly appreciated.
Again, thank you for the help and guidance
Hi, 1. Shown values are…
Hi,
1. Shown values are buffer rows.
2. You need to loop all rows and get only wanted data.
3. You need to access the profile generic buffer.
https://gurux.fi/Gurux.DLMS.Objects.GXDLMSProfileGeneric
Check this example:
https://github.com/Gurux/GuruxDLMS.c/blob/dd80bffc57d89d2826fc6b8647249…
BR,
Mikko
Hi, Mikko, I tried using the…
Hi, Mikko, I tried using the example you provided, but it give me Guru Meditation Error : Core 1 panic'ed (StoreProhibited).Here's the code I use
gxProfileGeneric *pg;
gxByteBuffer ba;
gxtime start1, end1;
time_init(&start1,2023,1,1,00,00,00,0000,0);
time_init(&end1,2023,12,1,00,00,00,0000,0);
cosem_init((gxObject*) pg, DLMS_OBJECT_TYPE_PROFILE_GENERIC, "1.0.98.1.0.255");
Serial.println("READ PROFILE INDEX 3");
com_read((gxObject *)pg, 3);
Serial.println("READ PROFILE INDEX 2");
com_read((gxObject *)pg, 2);
com_readProfileGenericColumns();
com_readRowsByEntry(pg, 1,10);
// com_readRowsByRange(&pg, &start1, &end1);
ret = obj_toString((gxObject*)pg,&data);
if (data != NULL)
{
bb_Init(&ba);
obj_rowsToString(&ba, &pg->buffer);
data = bb_toString(&ba);
printf("%s", data);
free(data);
data = NULL;
}
obj_clear((gxObject*)pg);
Client.ReleaseObjects();
com_close();
return ret;
And here's the output
~DEBUG: RX: 7E A0 21 F1 02 47 73 C2 88 81 80 14 05 02 01 60 06 02 01 60 07 04 00 00 00 01 08 04 00 00 00 01 DE 89 7E
~DEBUG: TX: 7E A0 6C 02 47 F1 10 9A 67 E6 E6 00 60 5D A1 09 06 07 60 85 74 05 08 01 03 A6 0A 04 08 41 42 43 44 45 46 47 48 8A 02 07 80 8B 07 60 85 74 05 08 02 05 AC 12 80 10 70 38 9C CE 67 B3 59 AC 56 AB 55 2A 15 8A 45 22 BE 23 04 21 21 1F 30 00 00 00 00 5A 79 55 9D 8F D5 16 E1 67 D4 83 A6 2F 83 48 FD 20 92 45 02 18 2E 43 61 A4 BB A0 E9 7E
~DEBUG: RX: 7E A0 78 F1 02 47 30 5B DC E6 E7 00 61 69 A1 09 06 07 60 85 74 05 08 01 03 A4 0A 04 08 45 44 4D 4D 6B 37 4D 49 A2 03 02 01 00 A3 05 A1 03 02 01 0E 88 02 07 80 89 07 60 85 74 05 08 02 05 AA 12 80 10 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 BE 23 04 21 28 1F 30 00 00 0E 2A 49 6A EE 3F F0 54 1E 9C 86 9F 89 B5 57 32 AF CC 27 25 01 7D 10 63 E4 11 78 5E 35 A1 7E
~DEBUG: TX: 7E A0 40 02 47 F1 32 2B 72 E6 E6 00 CB 31 30 00 00 00 01 99 D8 BD 09 C8 67 7C B6 26 B0 98 49 15 65 93 E1 74 CF BF CA 0C C1 37 FB 25 C5 69 8D B5 92 BF 26 E2 16 39 81 C6 2E 78 AB 43 7F 31 D4 56 B4 7E
~DEBUG: RX: 7E A0 39 F1 02 47 52 29 56 E6 E7 00 CF 2A 30 00 00 0E 2A 86 6B 29 60 EE 50 17 8D 8E 82 88 DF 7D 71 8F B2 1B 92 A3 F3 92 51 FA 0D 20 44 9B 91 F0 75 0A 7B 43 B0 52 65 3C 8B 5F 7E
:com_initializeConnection SUCCEEDED 0 :
0~DEBUG: TX: 7E A0 2D 02 47 F1 54 DC A9 E6 E6 00 C8 1E 30 00 00 00 02 E9 F1 37 DC 49 13 F8 19 AF 9B C1 E3 94 96 4D C9 49 06 83 8E 86 E4 12 13 6F 43 A2 7E
~DEBUG: RX: 7E A0 31 F1 02 47 74 3D 48 E6 E7 00 CC 22 30 00 00 0E 2B 62 71 22 D3 44 2C BA 65 73 CD 5F 89 3D 0F AD D2 47 EE 0D 50 A9 68 77 76 59 4B D6 7C 88 FF C6 7E
----------------------------
3339303030303132303738
39000012078
----------------------------
Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x4008611c PS : 0x00060e30 A0 : 0x800d6cc9 A1 : 0x3ffb20c0
A2 : 0x00000000 A3 : 0x00000000 A4 : 0x00000044 A5 : 0x00000000
A6 : 0x00000001 A7 : 0x00000004 A8 : 0x00000044 A9 : 0x3ffb2090
A10 : 0x3ffb8000 A11 : 0x3ffb929c A12 : 0x3ffb929c A13 : 0x00000007
A14 : 0x00000005 A15 : 0x00000001 SAR : 0x0000001a EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000 LBEG : 0x4008611c LEND : 0x40086127 LCOUNT : 0x00000003
Backtrace: 0x40086119:0x3ffb20c0 0x400d6cc6:0x3ffb20d0 0x400d6dbe:0x3ffb20f0 0x400d6e36:0x3ffb2110 0x400d2306:0x3ffb2140 0x400d249e:0x3ffb2250 0x400e6162:0x3ffb2290
ELF file SHA256: 42b9987977c60309
Rebooting...
Hi, Can you add the block…
Hi,
Can you add the block cipher key here so I can check what is happening?
I can't decrypt the data without that.
BR,
Mikko
Hi, sorry for late reply, I…
Hi, sorry for late reply, I was in hospital for treatment. Here are the block cipher key and other relevant properties
System title : ABCDEFGH
Block Cipher Key : FFFFFFFFFFFFFFFF (46464646464646464646464646464646)
Authentication Key : FFFFFFFFFFFFFFFF (46464646464646464646464646464646)
Using HighGMAC for the authentication, Security suite Suite0, using AuthenticationEncryption. The rest are default.
Thank you.
Melvin