Hi, i'm trying to make dlms server. i have a piece of code below for adding Instanttaneous Profile Generic:
void addCaptureObject(gxProfileGeneric *pg, gxObject *obj, unsigned char attrIndex)
{
gxTarget *capture;
capture = (gxTarget *)malloc(sizeof(gxTarget));
capture->attributeIndex = attrIndex;
capture->dataIndex = 0;
arr_push(&pg->captureObjects, key_init(obj, capture));
}
///////////////////////////////////////////////////////////////////////
// Add profile generic - instant profile object.
///////////////////////////////////////////////////////////////////////
int addInstantProfileProfileGeneric(dlmsSettings *settings)
{
int ret;
const unsigned char ln[6] = {1, 96, 98, 128, 0, 255};
if ((ret = INIT_OBJECT(instantProfile, DLMS_OBJECT_TYPE_PROFILE_GENERIC, ln)) == 0)
{
instantProfile.sortMethod = DLMS_SORT_METHOD_FIFO;
gxTarget *capture;
addCaptureObject(&instantProfile, BASE(clock1), 2);
addCaptureObject(&instantProfile, BASE(ecuId), 2);
addCaptureObject(&instantProfile, BASE(reg_volt_R_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_volt_S_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_volt_T_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_curr_R_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_curr_S_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_curr_T_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_curr_N_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_pf_R_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_pf_S_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_pf_T_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_pf_all_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_ang_uu_RR_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_ang_uu_SR_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_ang_uu_TR_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_ang_iu_RR_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_ang_iu_SS_LN), 2);
addCaptureObject(&instantProfile, BASE(reg_ang_iu_TT_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_ang_iu_NR_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_power_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_power_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_power_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_power_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_power_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_power_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_power_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_power_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_power_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_power_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_power_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_power_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_power_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_power_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_power_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_power_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_app_power_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_app_power_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_app_power_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_app_power_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_app_power_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_app_power_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_app_power_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_app_power_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_energy_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_energy_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_energy_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_act_energy_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_energy_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_energy_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_energy_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_act_energy_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_energy_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_energy_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_energy_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_exp_react_energy_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_energy_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_energy_S_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_energy_T_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_imp_react_energy_all_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_freq_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_curr_thd_R_LN), 2);
// addCaptureObject(&instantProfile, BASE(reg_curr_tdd_R_LN), 2);
printf("instant profile object count : %u\n", (unsigned int)instantProfile.captureObjects.size);
instantProfile.sortObject = BASE(clock1);
instantProfile.sortObjectAttributeIndex = 2;
setProfileGenericEntries(&instantProfile, INSTANT_PROFILE_MAX_ENTRIES);
instantProfile.capturePeriod = 0;
}
return 0;
}I use GuruxDLMSServerExample as base, then extending it to my needs. as you can see there are many objects that are commented for this profile. if i uncomment it, the capture object failed to load and show nothing when i refresh the profile. how to work around this?
And also, how to set maximum entries allowed for some profile? some profile need to contains thousands of data, e.g Load Profile, while some profiles like alarm and event only need to store max 100 entries.
Thank you
jack
Hi, Check what the size of…
Hi,
Check what the size of your INSTANT_PROFILE_MAX_ENTRIES is.
It must be bigger than the number of capture objects you try to add.
It's good to check what addCaptureObject returns.
Regards,
Mikko
Hi Mikko, The INSTANT…
Hi Mikko,
The INSTANT_PROFILE_MAX_ENTRIES is 1. addCaptureObject is a void, so it doesn't return anything. by checking the return type, do you mean the return of arr->push?
Why should the INSTANT_PROFILE_MAX_ENTRIES be bigger than num. of capture objects? isn't Row the entry of the buffer and the capture objects is the columns?
btw i got error when i uncomment those :
"Access Error : Device reports a hardware fault"
and here is the debugging print to see if the capture objects are added:
INIT
eventLog object count : 1
loadProfile1 object count : 21
instant profile object count : 63
as you can see, the object count is correct, i assume the addInstantProfileProfileGeneric is working. but when reading the column, i got the previously mentioned error. help me fix this error
Additional info
I mainly use wrapper, and i left the HDLC untouched
For the auth, i use Low and HighGMAC. for the HighGMAC, it's for setting some of the Data (IC 1) and profile generics' parameter.
Here's some memory size info
```
#define HDLC_HEADER_SIZE 17
#define HDLC_BUFFER_SIZE 128
#define PDU_BUFFER_SIZE 1024
#define WRAPPER_BUFFER_SIZE 8 + PDU_BUFFER_SIZE
const static uint16_t SERIALIZATION_VERSION = 2;
// TODO: Allocate space where profile generic row values are serialized.
#define PDU_MAX_PROFILE_GENERIC_COLUMN_SIZE 500
// Buffer where frames are saved.
static unsigned char frameBuff[HDLC_BUFFER_SIZE + HDLC_HEADER_SIZE];
// Buffer where PDUs are saved.
static unsigned char pduBuff[PDU_BUFFER_SIZE];
static unsigned char replyFrame[HDLC_BUFFER_SIZE + HDLC_HEADER_SIZE];
```
and here are the row size:
```
#define EVENT_LOG_MAX_ENTRIES 200
#define LOAD_PROFILE_MAX_ENTRIES 8640 // 90 days @ 15 min (or ~184 days @ 30 min)
#define INSTANT_PROFILE_MAX_ENTRIES 1 // single most-recent snapshot
#define HOURLY_PROFILE_MAX_ENTRIES 744 // 31 days * 24h
#define DAILY_PROFILE_MAX_ENTRIES 62 // ~2 months with +-1 day buffer
#define LOAD_PROFILE_UC_DATA_MAX_ENTRIES 365 // 365 days, sampled every 1 day
```
Thank you in advance
jack
Hi, At first, check that you…
Hi,
At first, check that you have enough heap memory.
Add this check to addCaptureObject:
capture = (gxTarget *)malloc(sizeof(gxTarget));
if (capture == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
BR,
Mikko
Hi Mikko, i added that, so…
Hi Mikko, i added that, so my addCaptureObject become:
but the program runs fine, here's the output at boot:
loadProfile1 object count : 21
instant profile object count : 63
OA_VERIFY COMPLETE
[SERVER] begin initialize
Meter started.
then when i refresh capture object, it doesnt show error in the shell window, and the GXDLMSDirector throws "Access Error : Device reports a hardware fault". help me fix this please, i can provide more info if needed.
additional information : i run this in my raspberry pi 4 with 16GB of storage, of which 1GBytes are free
Thank you
jack
Hi, Are you getting any…
Hi,
Are you getting any error in load? This has been tested with 50 objects and it succeeded. What is your PDU size?
BR,
Mikko
Hi Mikko, if by loading you…
Hi Mikko,
if by loading you mean calling the addInstantProfileProfileGeneric, it works fine. i added many prints in the addCaptureObject, addInstantProfileProfileGeneric, even modified the library to add the print just to be sure. shows no error, and the meter started, like i stated in previous reply:
I use 512 bytes. also tried 1024, doesnt work. when i use 2048, it works. but i check some meters, they use below 1024 bytes. some one-phase meters even use less than 512 bytes (i checked the AARE).
when i try to refresh their capture object, i see the data is read using block transfer. can you guide me on how to do block transfer? maybe there is example in the repo that i can look up. i assume this will help fixing the issue.
Thank you
jack
Hi, This is fixed and the…
Hi,
This is fixed and the new version is released on Monday.
BR,
Mikko
Hi Mikko, thank you for the…
Hi Mikko, thank you for the update. looking forward for the new release
Regards
jack
Hi, The reason is not in the…
Hi,
The reason is not in the library. I believe the heap is full. Use this code and check all error codes. This was tested by adding 100 capture objects, and everything works without problems if there is enough heap available.
BR,
Mikko
int addCaptureObject(gxProfileGeneric* pg, gxObject* obj, unsigned char attrIndex)
{
if (pg == NULL || obj == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
gxTarget* capture;
capture = (gxTarget*)malloc(sizeof(gxTarget));
if (capture == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
capture->attributeIndex = attrIndex;
capture->dataIndex = 0;
gxKey* k = key_init(obj, capture);
if (k == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return arr_push(&pg->captureObjects, k);
}