#include "cJSON_Utils.h"
#include "ocpp16_ChargingProfiles.h"
#include "ocpp16_configkey.h"
#include "ccu_port.h"
#include "secc_port.h"
/***************************************************************************************************************/

ChargingProfileList_t chargingProfiles;

char* ChargingProfilePurposeType_toString(ChargingProfilePurposeType_t type)
{
    switch(type)
    {
        case ChargingProfilePurposeType_ChargePointMaxProfile: return "ChargePointMaxProfile";
        case ChargingProfilePurposeType_TxDefaultProfile: return "TxDefaultProfile";
        case ChargingProfilePurposeType_TxProfile: return "TxProfile";
        default: return "NULL";
    }
}

int ChargingProfilePurposeType_fromString(const char* string)
{
    if (strcmp(string, "ChargePointMaxProfile")==0) return ChargingProfilePurposeType_ChargePointMaxProfile;
    if (strcmp(string, "TxDefaultProfile")==0) return ChargingProfilePurposeType_TxDefaultProfile;
    if (strcmp(string, "TxProfile")==0) return ChargingProfilePurposeType_TxProfile;
    return 0;
}

char* ChargingProfileKind_toString(ChargingProfileKindType_t kind)
{
    switch(kind)
    {
        case ChargingProfileKindType_Absolute: return "Absolute";
        case ChargingProfileKindType_Recurring: return "Recurring";
        case ChargingProfileKindType_Relative: return "Relative";
        default: return "Absolute";
    }
}

int ChargingProfileKind_fromString(const char* string)
{
    if (strcmp(string, "Absolute")==0) return ChargingProfileKindType_Absolute;
    if (strcmp(string, "Recurring")==0) return ChargingProfileKindType_Recurring;
    if (strcmp(string, "Relative")==0) return ChargingProfileKindType_Relative;
    return 0;
}

char* RecurrencyKind_toString(RecurrencyKindType_t kind)
{
    switch(kind)
    {
        case RecurrencyKindType_Daily: return "Daily";
        case RecurrencyKindType_Weekly: return "Weekly";
        default: return "NULL";
    }
}

int RecurrencyKind_fromString(const char* string)
{
    if (strcmp(string, "Daily")==0) return RecurrencyKindType_Daily;
    if (strcmp(string, "Weekly")==0) return RecurrencyKindType_Daily;
    return 0;
}

char* ChargingRateUnitType_toString(ChargingRateUnitType_t type)
{
    switch(type)
    {
        case ChargingRateUnitType_W: return "W";
        case ChargingRateUnitType_A: return "A";
        default: return "W";
    }
}

int ChargingRateUnitType_fromString(const char* string)
{
    if (strcmp(string, "W")==0) return ChargingRateUnitType_W;
    if (strcmp(string, "A")==0) return ChargingRateUnitType_A;
    return 0;
}


static void ocpp16_ChargingSchedule_save(cJSON* object, ChargingSchedule_t* chargingSchedule)
{
    int i;
    char buff[128];
    cJSON_AddNumberToObject(object, "duration", chargingSchedule->duration);
    cJSON_AddStringToObject(object, "startTime", format_UTCTime(buff, chargingSchedule->startTime));
    cJSON_AddStringToObject(object, "chargingRateUnit", ChargingRateUnitType_toString(chargingSchedule->chargingRateUnit));
    cJSON_AddNumberToObject(object, "minChargingRate", chargingSchedule->minChargingRate);

    cJSON* chargingSchedulePeriod = cJSON_AddArrayToObject(object, "chargingSchedulePeriod");
    for (i=0; i<chargingSchedule->chargingSchedulePeriod.count; i++)
    {
        cJSON* items = cJSON_CreateObject();
        cJSON_AddNumberToObject(items, "startPeriod", chargingSchedule->chargingSchedulePeriod.items[i].startPeriod);
        cJSON_AddNumberToObject(items, "limit", chargingSchedule->chargingSchedulePeriod.items[i].limit);
        cJSON_AddNumberToObject(items, "numberPhases", chargingSchedule->chargingSchedulePeriod.items[i].numberPhases);
        cJSON_AddItemToArray(chargingSchedulePeriod, items);
    }
}


void ocpp16_ChargingProfiles_save(ChargingProfileList_t* list, const char* filename)
{
    int i;
    char cmdbuff[128];
    char strtime[128];
    // sprintf(cmdbuff, "mv %s %s_%s", filename, filename, format_UTCTime(strtime, time(NULL)));
    // system(cmdbuff);
    cJSON* root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "count", list->count);
    cJSON_AddNumberToObject(root, "maxLength", list->maxLength);
    cJSON* profiles = cJSON_AddArrayToObject(root, "ChargingProfiles");
    for (i=0; i<list->count; i++)
    {
        cJSON* items = cJSON_CreateObject();
        cJSON_AddNumberToObject(items, "chargingProfileId", list->items[i].chargingProfileId);
        cJSON_AddNumberToObject(items, "transactionId", list->items[i].transactionId);
        cJSON_AddNumberToObject(items, "stackLevel", list->items[i].stackLevel);

        cJSON_AddStringToObject(items, "chargingProfilePurpose", ChargingProfilePurposeType_toString(list->items[i].chargingProfilePurpose));
        cJSON_AddStringToObject(items, "chargingProfileKind", ChargingProfileKind_toString(list->items[i].chargingProfileKind));
        cJSON_AddStringToObject(items, "recurrencyKind", RecurrencyKind_toString(list->items[i].recurrencyKind));

        cJSON_AddStringToObject(items, "validFrom", format_UTCTime(strtime, list->items[i].validFrom));
        cJSON_AddStringToObject(items, "validTo", format_UTCTime(strtime, list->items[i].validTo));

        cJSON* chargingSchedule = cJSON_AddObjectToObject(items, "chargingSchedule");
        ocpp16_ChargingSchedule_save(chargingSchedule, &list->items[i].chargingSchedule);

        cJSON_AddItemToArray(profiles, items);
    }
    
    char *fbuff = cJSON_Print(root);
    FILE *fp = fopen(filename, "wb");
    if (fp != NULL)
    {
        fwrite(fbuff, 1, strlen(fbuff), fp);
        fclose(fp);
    }else{
        printd("open(%s, wb) failed.\n", filename);
    }
    free(fbuff);
    cJSON_Delete(root);
}

static void ocpp16_ChargingSchedule_load(ChargingSchedule_t *chargingSchedule, cJSON* object)
{
    int i;
    
    if (cJSON_HasObjectItem(object, "duration")) chargingSchedule->duration = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(object, "duration")); else chargingSchedule->duration = 0;
    if (cJSON_HasObjectItem(object, "startTime")) chargingSchedule->startTime = RFC3339String_to_time(cJSON_GetStringValue(cJSON_GetObjectItem(object, "startTime")), NULL, NULL); else chargingSchedule->startTime = 0;
    if (cJSON_HasObjectItem(object, "startTime")) chargingSchedule->minChargingRate = (float)cJSON_GetNumberValue(cJSON_GetObjectItem(object, "minChargingRate")); else chargingSchedule->minChargingRate = 0;
    chargingSchedule->chargingRateUnit = RecurrencyKind_fromString(cJSON_GetObjectItem(object, "chargingRateUnit")->valuestring);
    cJSON* periods = cJSON_GetObjectItem(object, "chargingSchedulePeriod");
    chargingSchedule->chargingSchedulePeriod.count = cJSON_GetArraySize(periods);
    for (i=0; i<chargingSchedule->chargingSchedulePeriod.count; i++)
    {
        cJSON* items = cJSON_GetArrayItem(periods, i);
        chargingSchedule->chargingSchedulePeriod.items[i].startPeriod = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(items, "startPeriod"));
        chargingSchedule->chargingSchedulePeriod.items[i].limit = (float)cJSON_GetNumberValue(cJSON_GetObjectItem(items, "limit"));
        if (cJSON_HasObjectItem(items, "numberPhases")) chargingSchedule->chargingSchedulePeriod.items[i].numberPhases = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(items, "numberPhases")); else chargingSchedule->chargingSchedulePeriod.items[i].numberPhases = 0;
    }
}

void ocpp16_ChargingProfiles_load(ChargingProfileList_t* list, const char* filename)
{
    int i;
    FILE* file = fopen(filename, "rb");
    if (file)
    {
        fseek(file, 0, SEEK_END);
        int flen = ftell(file);
        fseek(file, 0, SEEK_SET);
        char* fbuff = malloc(flen+1);
        if (fbuff)
        {
            fread(fbuff, flen, 1, file);
            cJSON* root = cJSON_Parse(fbuff);
            if (root)
            {
                list->count = 0;
                list->maxLength = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(root, "maxLength"));
                cJSON* profiles = cJSON_GetObjectItem(root, "ChargingProfiles");
                int size = cJSON_GetArraySize(profiles);
                if (size > list->maxLength)
                {
                    list->maxLength = size;
                }
                list->items = malloc(list->maxLength * sizeof(ChargingProfile_t));
                memset(list->items, 0, list->maxLength * sizeof(ChargingProfile_t));

                for (i=0; i< size; i++)
                {
                    cJSON* items = cJSON_GetArrayItem(profiles, i);
                    list->count++;
                    list->items[i].chargingProfileId = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(items, "chargingProfileId"));
                    list->items[i].transactionId = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(items, "transactionId"));
                    list->items[i].stackLevel = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(items, "stackLevel"));

                    list->items[i].chargingProfilePurpose = ChargingProfilePurposeType_fromString(cJSON_GetObjectItem(items, "chargingProfilePurpose")->valuestring);
                    list->items[i].chargingProfileKind = ChargingProfileKind_fromString(cJSON_GetObjectItem(items, "chargingProfileKind")->valuestring);
                    list->items[i].recurrencyKind = RecurrencyKind_fromString(cJSON_GetObjectItem(items, "recurrencyKind")->valuestring);

                    if (cJSON_HasObjectItem(items, "validFrom")) list->items[i].validFrom = RFC3339String_to_time(cJSON_GetStringValue(cJSON_GetObjectItem(items, "validFrom")), NULL, NULL); else list->items[i].validFrom = 0;
                    if (cJSON_HasObjectItem(items, "validTo")) list->items[i].validTo = RFC3339String_to_time(cJSON_GetStringValue(cJSON_GetObjectItem(items, "validTo")), NULL, NULL); else list->items[i].validTo = 0;

                    ocpp16_ChargingSchedule_load(&list->items[i].chargingSchedule, cJSON_GetObjectItem(items, "chargingSchedule"));
                }
                cJSON_Delete(root);
            }else{
                printd("cJSON_Parse(%p) failed.\n", fbuff);
            }
            free(fbuff);
        }else{
            printd("malloc(%d) failed.\n", flen);
        }
        fclose(file);
    }else{
        printd("open(%s, rb) failed.\n", filename);
    }
}

static int ocpp16_find_ChargingProfiles(ChargingProfile_t* new, int connectorId)
{
    int i;
    for (i=0; i<chargingProfiles.count; i++)
    {
        printd("step\n");
        ChargingProfile_t* items = &chargingProfiles.items[i];
        if (new->chargingProfileId == items->chargingProfileId)
        {
            printd("step\n");
            return i;
        }
        if (new->chargingProfilePurpose == items->chargingProfilePurpose && new->stackLevel == items->stackLevel && connectorId == items->transactionId)
        {
            printd("step\n");
            return i;
        }
    }
    printd("step\n");
    return -1;
}

static int ocpp16_save_Profile(ChargingProfile_t* items, ChargingProfile_t* new, int connectorId)
{
    int i;
    if (new->chargingProfilePurpose==ChargingProfilePurposeType_ChargePointMaxProfile)
    {
        items->chargingProfileId = new->chargingProfileId;
        items->stackLevel = new->stackLevel;

        items->transactionId = connectorId;
        items->chargingProfilePurpose = new->chargingProfilePurpose;
        items->chargingProfileKind = new->chargingProfileKind;
        items->recurrencyKind = new->recurrencyKind;

        items->validFrom = new->validFrom;
        items->validTo = new->validTo;

        items->chargingSchedule.duration = new->chargingSchedule.duration;
        items->chargingSchedule.minChargingRate = new->chargingSchedule.minChargingRate;
        items->chargingSchedule.chargingRateUnit = new->chargingSchedule.chargingRateUnit;
        items->chargingSchedule.startTime = new->chargingSchedule.startTime;

        for (i=0; i<new->chargingSchedule.chargingSchedulePeriod.count; i++)
        {
            items->chargingSchedule.chargingSchedulePeriod.items[i].limit = new->chargingSchedule.chargingSchedulePeriod.items[i].limit;
            items->chargingSchedule.chargingSchedulePeriod.items[i].numberPhases = new->chargingSchedule.chargingSchedulePeriod.items[i].numberPhases;
            items->chargingSchedule.chargingSchedulePeriod.items[i].startPeriod = new->chargingSchedule.chargingSchedulePeriod.items[i].startPeriod;
        }
        return 0;
    }
    return -1;
}


int ocpp16_set_ChargingProfiles(ChargingProfile_t *new, int connectorId)
{
    ccu_port_t* ccu = (ccu_port_t*)&ccu_port;
    secc_port_t* gunA = (secc_port_t*)ccu->seccA;
    secc_port_t* gunB = (secc_port_t*)ccu->seccB;

    ChargingProfile_t* items = NULL;

    printd("step\n");

    int idx = ocpp16_find_ChargingProfiles(new, connectorId);
    if (idx >= 0)
    {
        items = &chargingProfiles.items[idx];
    }else{
        printd("step\n");
        if (chargingProfiles.count < chargingProfiles.maxLength)
        {
            printd("step\n");
            items = &chargingProfiles.items[chargingProfiles.count++];
        }
    }
    if (items)
    {
        printd("step\n");
        if (new->chargingProfilePurpose==ChargingProfilePurposeType_ChargePointMaxProfile)
        {   
            //设置桩的最大充电能力，每个充电枪的max limit就是桩的最大充电能力（其他枪空闲时，当前枪获取了桩的最大充电能力）
            if (connectorId == 0)
            {
                printd("step\n");
                return ocpp16_save_Profile(items, new, connectorId);
            }
        }

        if (new->chargingProfilePurpose==ChargingProfilePurposeType_TxDefaultProfile)
        {
            if (connectorId==0 || connectorId==1 || connectorId==2)
            {
                printd("step\n");
                return ocpp16_save_Profile(items, new, connectorId);
            }
        }

        if (new->chargingProfilePurpose==ChargingProfilePurposeType_TxProfile)
        {
            //针对当前充电交易的限制
            if (new->transactionId != 0)
            {
                printd("step\n");
                if (new->transactionId == gunA->transactionId)
                {
                    return ocpp16_save_Profile(items, new, 1);
                }
                if (new->transactionId == gunB->transactionId)
                {
                    return ocpp16_save_Profile(items, new, 2);
                }
            }
        }
        printd("step\n");
        ocpp16_ChargingProfiles_save(&chargingProfiles, "/home/root/app_run/etc/ocpp16_ChargingProfiles.json");
    }
    return -1;
}

static float ocpp16_get_ChargingScheduleLimit(ChargingSchedule_t* chargingSchedule)
{
    int i;
    float minLimit = chargingSchedule->chargingSchedulePeriod.items[0].limit;
    for (i=1; i<chargingSchedule->chargingSchedulePeriod.count; i++)
    {
        if (minLimit > chargingSchedule->chargingSchedulePeriod.items[i].limit)
        {
            minLimit = chargingSchedule->chargingSchedulePeriod.items[i].limit;
        }
    }
    return minLimit;
}
/*
*************************************************************************
    ocpp16_get_SchedulePeriodLimit
    遍历每个SchedulePeriod，
    检查当前时间now是否在SchedulePeriod的duration范围内
    now在范围内，则找最小值，不在duration范围内则返回-1.0
    
    startSchedule-------------------------------------------------------------------|
            |                         <-- duration -->                              |
            |-----------------|-----------------|-----------------|-----------------|
              |  startPeriod  |  startPeriod    |  startPeriod    |  startPeriod    |

*************************************************************************
*/
static float ocpp16_get_SchedulePeriodLimit(time_t startSchedule, ChargingSchedule_t* chargingSchedule)
{
    int i;
    time_t now = time(NULL);
    float result = -1.0f;
    for (i=0; i<chargingSchedule->chargingSchedulePeriod.count; i++)
    {
        time_t startPeriod = startSchedule + chargingSchedule->chargingSchedulePeriod.items[i].startPeriod;
        if (chargingSchedule->duration == 0)
        {
            if (now >= startPeriod)
            {
                if (result < 0.0f)
                {
                    result = chargingSchedule->chargingSchedulePeriod.items[i].limit;
                }
                if (result > chargingSchedule->chargingSchedulePeriod.items[i].limit)
                {
                    result = chargingSchedule->chargingSchedulePeriod.items[i].limit;
                }
            }
        }else{
            time_t stopPeriod = startSchedule + chargingSchedule->duration;
            if (i < chargingSchedule->chargingSchedulePeriod.count-1)
            {
                stopPeriod = startSchedule + chargingSchedule->chargingSchedulePeriod.items[i+1].startPeriod;
            }
            if (startPeriod <= now && now <stopPeriod)
            {
                if (result < 0.0f)
                {
                    result = chargingSchedule->chargingSchedulePeriod.items[i].limit;
                }
                if (result > chargingSchedule->chargingSchedulePeriod.items[i].limit)
                {
                    result = chargingSchedule->chargingSchedulePeriod.items[i].limit;
                }
            }
        }
    }
    return result;
}

static float ocpp16_find_ChargingScheduleLimit(ChargingProfile_t* chargingProfile)
{
    int i;

    ChargingSchedule_t* chargingSchedule = (ChargingSchedule_t*)&chargingProfile->chargingSchedule;
    time_t now = time(NULL);
    if (chargingProfile->validFrom > 0)
    {
        if (chargingProfile->validFrom > now) return -1.0; //chargingProfile还没启用
    }
    if (chargingProfile->validTo > 0)
    {
        if (chargingProfile->validTo < now) return -1.0; //chargingProfile已经过期
    }

    if (chargingProfile->chargingProfileKind==ChargingProfileKindType_Absolute && chargingSchedule->startTime > 0)
    {
        time_t startSchedule = chargingSchedule->startTime;
        if (startSchedule > now) return -1.0;// chargingSchedule还没启用
        return ocpp16_get_SchedulePeriodLimit(startSchedule, chargingSchedule);
    }

    if (chargingProfile->chargingProfileKind==ChargingProfileKindType_Relative)
    {
        return ocpp16_get_SchedulePeriodLimit(now, chargingSchedule);
    }

    if (chargingProfile->chargingProfileKind==ChargingProfileKindType_Recurring)
    {
        if (chargingSchedule->startTime > 0)
        {
            time_t startSchedule = chargingSchedule->startTime;
            if (startSchedule > now) return -1.0;// chargingSchedule还没启用

            if (chargingProfile->recurrencyKind == RecurrencyKindType_Daily)
            {
                while(startSchedule < now) { startSchedule += 24*60*60; }
                return ocpp16_get_SchedulePeriodLimit(startSchedule - 24*60*60, chargingSchedule);
            }
            if (chargingProfile->recurrencyKind == RecurrencyKindType_Weekly)
            {
                while(startSchedule < now) { startSchedule += 7*24*60*60; }
                return ocpp16_get_SchedulePeriodLimit(startSchedule - 7*24*60*60, chargingSchedule);
            }
        }
    }
    return -1.0;
}

int ocpp16_check_ChargingProfiles(void)
{
    int i;
    int stackLevel_CP = 0;
    int stackLevel_Default = 0;
    int stackLevel_TX = 0;

    ccu_port_t* ccu = (ccu_port_t*)&ccu_port;
    secc_port_t* gunA = (secc_port_t*)ccu->seccA;
    secc_port_t* gunB = (secc_port_t*)ccu->seccB;

    //针对充电桩的充电计划置0，即不限制
    {
        ccu->limit_CPMaxPowerKW = -1.0;
        ccu->limit_CPMaxCurrent = -1.0;
    }
    //针对充电枪的默认充电计划置0，即不限制
    {
        gunA->limit_DefaultPowerKW = -1.0;
        gunA->limit_DefaultCurrent = -1.0;
        gunB->limit_DefaultPowerKW = -1.0;
        gunB->limit_DefaultCurrent = -1.0;
    }
    //针对当前交易的充电计划（充电限制）置0，即不限制
    {
        gunA->limit_TxPowerKW = -1.0;
        gunA->limit_TxCurrent = -1.0;
        gunB->limit_TxPowerKW = -1.0;
        gunB->limit_TxCurrent = -1.0;
    }

    for (i=0; i<chargingProfiles.count; i++)
    {
        ChargingProfile_t* items = &chargingProfiles.items[i];
        if (items->chargingProfilePurpose == ChargingProfilePurposeType_ChargePointMaxProfile)
        {
            if (stackLevel_CP <= items->stackLevel)
            {
                stackLevel_CP = items->stackLevel;
                if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_W)
                {
                    ccu->limit_CPMaxPowerKW = ocpp16_get_ChargingScheduleLimit(&items->chargingSchedule)/1000;
                }
                if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_A)
                {
                    ccu->limit_CPMaxCurrent = ocpp16_get_ChargingScheduleLimit(&items->chargingSchedule);
                }                
            }
        }
        if (items->chargingProfilePurpose == ChargingProfilePurposeType_TxDefaultProfile)
        {
            if (stackLevel_Default <= items->stackLevel)
            {
                stackLevel_Default = items->stackLevel;
                float minValue = ocpp16_find_ChargingScheduleLimit(items);
                if (minValue >= 0.0f)
                {
                    if (items->transactionId == 1 || items->transactionId == 0)
                    {
                        if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_W)
                        {
                            gunA->limit_DefaultPowerKW = minValue/1000;
                        }
                        if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_A)
                        {
                            gunA->limit_DefaultCurrent = minValue;
                        }
                    }
                    if (items->transactionId == 2 || items->transactionId == 0)
                    {
                        if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_W)
                        {
                            gunB->limit_DefaultPowerKW = minValue/1000;
                        }
                        if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_A)
                        {
                            gunB->limit_DefaultCurrent = minValue;
                        }
                    }
                }
            }
        }
        if (items->chargingProfilePurpose == ChargingProfilePurposeType_TxProfile)
        {
            if (items->transactionId == gunA->transactionId)
            {
                if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_W)
                {
                    gunA->limit_TxPowerKW = ocpp16_get_ChargingScheduleLimit(&items->chargingSchedule)/1000;
                }
                if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_A)
                {
                    gunA->limit_TxCurrent = ocpp16_get_ChargingScheduleLimit(&items->chargingSchedule);
                }
            }
            if (items->transactionId == gunB->transactionId)
            {
                if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_W)
                {
                    gunB->limit_TxPowerKW = ocpp16_get_ChargingScheduleLimit(&items->chargingSchedule)/1000;
                }
                if (items->chargingSchedule.chargingRateUnit == ChargingRateUnitType_A)
                {
                    gunB->limit_TxCurrent = ocpp16_get_ChargingScheduleLimit(&items->chargingSchedule);
                }
            }
        }
    }
}

void ocpp16_ChargingProfiles_init(void)
{
    if (chargingProfiles.items) { free(chargingProfiles.items); }
    memset(&chargingProfiles, 0, sizeof(ChargingProfileList_t));
    ocpp16_ChargingProfiles_load(&chargingProfiles, "/home/root/app_run/etc/ocpp16_ChargingProfiles.json");
}

void ocpp16_ChargingProfiles_exit(void)
{
    ocpp16_ChargingProfiles_save(&chargingProfiles, "/home/root/app_run/etc/ocpp16_ChargingProfiles.json");
    if (chargingProfiles.items) { free(chargingProfiles.items); }
    memset(&chargingProfiles, 0, sizeof(ChargingProfileList_t));
}
