
#include "cJSON.h"
#include "ccu_config.h"
#include "interface.h"
#include "ocpp16_configkey.h"
#include "ocpp16_authorization.h"
#include "ocpp16_ChargingProfiles.h"
#include "ocpp16_OfflineChargingRecords.h"

ccu_config_t ccu_config;

static void ccu_default_config(ccu_config_t *config)
{
    if (config)
    {
        config->TCU_ID = 0;
        sprintf(config->CCU_SN, "TC2025010210002");
        sprintf(config->CCU_ProductID, "YT800KW");
        sprintf(config->CCU_VendorID, "TCharge Co.,Ltd");
        config->CCU_Available = 1;

        config->BoxOverTemp_Stopping = 100;
        config->BoxOverTemp_Warning = 90;
        sprintf(config->username, "test");
        sprintf(config->password, "HCYhMPmnSS8M5id6");        
        config->GUN_Numb = 2;

        config->GUN_config[0].connectorId = 1;
        config->GUN_config[0].GUN_Type = GUN_TYPE_GBDC;
        config->GUN_config[0].GUN_Available = 1;
        config->GUN_config[0].GUN_maxI = 250;
        sprintf(config->GUN_config[0].slac_ifname, "eth3");
        sprintf(config->GUN_config[0].can_ifname, "can0"); 
        config->GUN_config[0].QRCode_enable = 0;
        sprintf(config->GUN_config[0].QRCode_URL, "https://abc");
        config->GUN_config[0].requestPowerByMinutes = 1;
        config->GUN_config[0].requestPowerByPowerKW = 0;
        config->GUN_config[0].requestPowerBySOC = 0;
        config->GUN_config[0].GUNOverTemp_Warning = 90;
        config->GUN_config[0].GUNOverTemp_Stopping = 100;
        sprintf(config->GUN_config[0].root_cert_path_v2g, "~/app_run/certs/ca/v2g/");
        sprintf(config->GUN_config[0].root_cert_path_mo, "~/app_run/certs/ca/mo/");

        config->GUN_config[1].connectorId = 2;
        config->GUN_config[1].GUN_Type = GUN_TYPE_CCS1;
        config->GUN_config[1].GUN_Available = 1;
        config->GUN_config[1].GUN_maxI = 250;
        sprintf(config->GUN_config[1].slac_ifname, "eth3");
        sprintf(config->GUN_config[1].can_ifname, "can0");  
        config->GUN_config[1].QRCode_enable = 0;
        sprintf(config->GUN_config[1].QRCode_URL, "https://abc");
        config->GUN_config[1].requestPowerByMinutes = 1;
        config->GUN_config[1].requestPowerByPowerKW = 0;
        config->GUN_config[1].requestPowerBySOC = 0;
        config->GUN_config[1].GUNOverTemp_Warning = 90;
        config->GUN_config[1].GUNOverTemp_Stopping = 100;
        sprintf(config->GUN_config[1].root_cert_path_v2g, "~/app_run/certs/ca/v2g/");
        sprintf(config->GUN_config[1].root_cert_path_mo, "~/app_run/certs/ca/mo/");

        config->pcuhw.enable = 0;
        config->pcuhw.connect_port = 502;
        sprintf(config->pcuhw.connect_ip_string, "192.168.11.1");
        config->pcuhw.enable_ssl = 1;
        // sprintf(config->pcuhw.ssl_ca_filepath, "~/app_run/ca_pcuhw/ca.crt");
        // sprintf(config->pcuhw.ssl_cert_filepath, "~/app_run/ca_pcuhw/client.crt");
        // sprintf(config->pcuhw.ssl_private_key_filepath, "~/app_run/ca_pcuhw/client.key");

        config->pcutc.enable = 1;
        config->pcutc.connect_port = 502;
        sprintf(config->pcutc.connect_ip_string, "eth0");
        config->pcutc.enable_ssl = 0;
        // sprintf(config->pcutc.ssl_ca_filepath, "~/app_run/ca_pcutc/ca.crt");
        // sprintf(config->pcutc.ssl_cert_filepath, "~/app_run/ca_pcutc/client.crt");
        // sprintf(config->pcutc.ssl_private_key_filepath, "~/app_run/ca_pcutc/client.key");

        config->qttcu.enable = 1;
        config->qttcu.connect_port = 3001;
        sprintf(config->qttcu.connect_ip_string, "eth0");
        config->qttcu.enable_ssl = 0;
        // sprintf(config->qttcu.ssl_ca_filepath, "~/app_run/ca_qttcu/ca.crt");
        // sprintf(config->qttcu.ssl_cert_filepath, "~/app_run/ca_qttcu/client.crt");
        // sprintf(config->qttcu.ssl_private_key_filepath, "~/app_run/ca_qttcu/client.key");

        config->ocpp16[0].enable = 1;
        sprintf(config->ocpp16[0].connect_ip_string, "47.102.124.18");
        config->ocpp16[0].connect_port = 80;
        sprintf(config->ocpp16[0].ssl_ca_filepath, "~/app_run/ca_ocpp16/ca.crt");
        sprintf(config->ocpp16[0].ssl_cert_filepath, "~/app_run/ca_ocpp16/client.crt");
        sprintf(config->ocpp16[0].ssl_private_key_filepath, "~/app_run/ca_ocpp16/client.key");

        config->ocpp16[1].enable = 0;
        sprintf(config->ocpp16[1].connect_ip_string, "47.102.124.18");
        config->ocpp16[1].connect_port = 80;
        sprintf(config->ocpp16[1].ssl_ca_filepath, "~/app_run/ca_ocpp16/ca.crt");
        sprintf(config->ocpp16[1].ssl_cert_filepath, "~/app_run/ca_ocpp16/client.crt");
        sprintf(config->ocpp16[1].ssl_private_key_filepath, "~/app_run/ca_ocpp16/client.key");

        config->ocpp21[0].enable = 1;
        sprintf(config->ocpp21[0].connect_ip_string, "47.102.124.18");
        config->ocpp21[0].connect_port = 80;
        sprintf(config->ocpp21[0].ssl_ca_filepath, "~/app_run/ca_ocpp16/ca.crt");
        sprintf(config->ocpp21[0].ssl_cert_filepath, "~/app_run/ca_ocpp16/client.crt");
        sprintf(config->ocpp21[0].ssl_private_key_filepath, "~/app_run/ca_ocpp16/client.key");

        config->ocpp21[1].enable = 0;
        sprintf(config->ocpp21[1].connect_ip_string, "47.102.124.18");
        config->ocpp21[1].connect_port = 80;
        sprintf(config->ocpp21[1].ssl_ca_filepath, "~/app_run/ca_ocpp16/ca.crt");
        sprintf(config->ocpp21[1].ssl_cert_filepath, "~/app_run/ca_ocpp16/client.crt");
        sprintf(config->ocpp21[1].ssl_private_key_filepath, "~/app_run/ca_ocpp16/client.key");
    }
}

static void ccu_load_pcuhw_config(cJSON *object, pcuhw_config_t* config)
{
    if (cJSON_HasObjectItem(object, "enable"))
    config->enable = cJSON_IsTrue(cJSON_GetObjectItem(object, "enable"));
    if (cJSON_HasObjectItem(object, "connect_ip_string"))
    sprintf(config->connect_ip_string, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(object, "connect_ip_string")));
    if (cJSON_HasObjectItem(object, "connect_port"))
    config->connect_port = (short)cJSON_GetNumberValue(cJSON_GetObjectItem(object, "connect_port"));
    if (cJSON_HasObjectItem(object, "enable_ssl"))
    config->enable_ssl = cJSON_IsTrue(cJSON_GetObjectItem(object, "enable_ssl"));
}

static void ccu_save_pcuhw_config(cJSON *object, pcuhw_config_t* config)
{
    if (cJSON_HasObjectItem(object, "enable"))
    cJSON_AddBoolToObject(object, "enable", config->enable);
    if (cJSON_HasObjectItem(object, "connect_ip_string"))
    cJSON_AddStringToObject(object, "connect_ip_string", config->connect_ip_string);
    if (cJSON_HasObjectItem(object, "connect_port"))
    cJSON_AddNumberToObject(object, "connect_port", config->connect_port);
    if (cJSON_HasObjectItem(object, "enable_ssl"))
    cJSON_AddBoolToObject(object, "enable_ssl", config->enable_ssl);
}

static void ccu_load_pcutc_config(cJSON *object, pcutc_config_t* config)
{
    if (cJSON_HasObjectItem(object, "enable"))
    config->enable = cJSON_IsTrue(cJSON_GetObjectItem(object, "enable"));
    if (cJSON_HasObjectItem(object, "connect_ip_string"))
    sprintf(config->connect_ip_string, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(object, "connect_ip_string")));
    if (cJSON_HasObjectItem(object, "connect_port"))
    config->connect_port = (short)cJSON_GetNumberValue(cJSON_GetObjectItem(object, "connect_port"));
    if (cJSON_HasObjectItem(object, "enable_ssl"))
    config->enable_ssl = cJSON_IsTrue(cJSON_GetObjectItem(object, "enable_ssl"));
}

static void ccu_save_pcutc_config(cJSON *object, pcutc_config_t* config)
{
    if (cJSON_HasObjectItem(object, "enable"))
    cJSON_AddBoolToObject(object, "enable", config->enable);
    if (cJSON_HasObjectItem(object, "connect_ip_string"))
    cJSON_AddStringToObject(object, "connect_ip_string", config->connect_ip_string);
    if (cJSON_HasObjectItem(object, "connect_port"))
    cJSON_AddNumberToObject(object, "connect_port", config->connect_port);
    if (cJSON_HasObjectItem(object, "enable_ssl"))
    cJSON_AddBoolToObject(object, "enable_ssl", config->enable_ssl);
}

static void ccu_load_qttcu_config(cJSON *object, qttcu_config_t* config)
{
    config->enable = cJSON_IsTrue(cJSON_GetObjectItem(object, "enable"));
    sprintf(config->connect_ip_string, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(object, "connect_ip_string")));
    config->connect_port = (short)cJSON_GetNumberValue(cJSON_GetObjectItem(object, "connect_port"));
    config->enable_ssl = cJSON_IsTrue(cJSON_GetObjectItem(object, "enable_ssl"));
}

static void ccu_save_qttcu_config(cJSON *object, qttcu_config_t* config)
{
    if (cJSON_HasObjectItem(object, "enable"))
    cJSON_AddBoolToObject(object, "enable", config->enable);
    if (cJSON_HasObjectItem(object, "connect_ip_string"))
    cJSON_AddStringToObject(object, "connect_ip_string", config->connect_ip_string);
    if (cJSON_HasObjectItem(object, "connect_port"))
    cJSON_AddNumberToObject(object, "connect_port", config->connect_port);
    if (cJSON_HasObjectItem(object, "enable_ssl"))
    cJSON_AddBoolToObject(object, "enable_ssl", config->enable_ssl);
}


static void ccu_load_ocpp_config(cJSON *object, ocpp16_config_t* config)
{
    if (cJSON_IsArray(object))
    {
        if (cJSON_GetArraySize(object)==2)
        {
            cJSON *item0 = cJSON_GetArrayItem(object, 0);
            if (item0)
            {
                if (cJSON_HasObjectItem(item0, "enable"))
                config[0].enable = cJSON_IsTrue(cJSON_GetObjectItem(item0, "enable"));
                if (cJSON_HasObjectItem(item0, "connect_ip_string"))
                sprintf(config[0].connect_ip_string, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "connect_ip_string")));
                if (cJSON_HasObjectItem(item0, "connect_port"))
                config[0].connect_port = (short)cJSON_GetNumberValue(cJSON_GetObjectItem(item0, "connect_port"));
                if (cJSON_HasObjectItem(item0, "enable_ssl"))
                config[0].enable_ssl = cJSON_IsTrue(cJSON_GetObjectItem(item0, "enable_ssl"));
                if (cJSON_HasObjectItem(item0, "ssl_ca_filepath"))
                sprintf(config[0].ssl_ca_filepath, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "ssl_ca_filepath")));
                if (cJSON_HasObjectItem(item0, "ssl_cert_filepath"))
                sprintf(config[0].ssl_cert_filepath, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "ssl_cert_filepath")));
                if (cJSON_HasObjectItem(item0, "ssl_private_key_filepath"))
                sprintf(config[0].ssl_private_key_filepath, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "ssl_private_key_filepath")));
            }
            cJSON *item1 = cJSON_GetArrayItem(object, 1);
            if (item1)
            {
                if (cJSON_HasObjectItem(item1, "enable"))
                config[1].enable = cJSON_IsTrue(cJSON_GetObjectItem(item1, "enable"));
                if (cJSON_HasObjectItem(item1, "connect_ip_string"))
                sprintf(config[1].connect_ip_string, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "connect_ip_string")));
                if (cJSON_HasObjectItem(item1, "connect_port"))
                config[1].connect_port = (short)cJSON_GetNumberValue(cJSON_GetObjectItem(item1, "connect_port"));
                if (cJSON_HasObjectItem(item1, "enable_ssl"))
                config[1].enable_ssl = cJSON_IsTrue(cJSON_GetObjectItem(item1, "enable_ssl"));
                if (cJSON_HasObjectItem(item1, "ssl_ca_filepath"))
                sprintf(config[1].ssl_ca_filepath, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "ssl_ca_filepath")));
                if (cJSON_HasObjectItem(item1, "ssl_cert_filepath"))
                sprintf(config[1].ssl_cert_filepath, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "ssl_cert_filepath")));
                if (cJSON_HasObjectItem(item1, "ssl_private_key_filepath"))
                sprintf(config[1].ssl_private_key_filepath, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "ssl_private_key_filepath")));
            }
        }
    }
}

static void ccu_save_ocpp_config(cJSON *array, ocpp16_config_t* config)
{
    cJSON *item0 = cJSON_CreateObject();
    cJSON_AddBoolToObject(item0, "enable", config[0].enable);
    cJSON_AddStringToObject(item0, "connect_ip_string", config[0].connect_ip_string);
    cJSON_AddNumberToObject(item0, "connect_port", config[0].connect_port);
    cJSON_AddBoolToObject(item0, "enable_ssl", config[0].enable_ssl);
    cJSON_AddStringToObject(item0, "ssl_ca_filepath", config[0].ssl_ca_filepath);
    cJSON_AddStringToObject(item0, "ssl_cert_filepath", config[0].ssl_cert_filepath);
    cJSON_AddStringToObject(item0, "ssl_private_key_filepath", config[0].ssl_private_key_filepath);
    cJSON_AddItemToArray(array, item0);
    cJSON *item1 = cJSON_CreateObject();
    cJSON_AddBoolToObject(item1, "enable", config[1].enable);
    cJSON_AddStringToObject(item1, "connect_ip_string", config[1].connect_ip_string);
    cJSON_AddNumberToObject(item1, "connect_port", config[1].connect_port);
    cJSON_AddBoolToObject(item1, "enable_ssl", config[1].enable_ssl);
    cJSON_AddStringToObject(item1, "ssl_ca_filepath", config[1].ssl_ca_filepath);
    cJSON_AddStringToObject(item1, "ssl_cert_filepath", config[1].ssl_cert_filepath);
    cJSON_AddStringToObject(item1, "ssl_private_key_filepath", config[1].ssl_private_key_filepath);
    cJSON_AddItemToArray(array, item1);
}

static int GUN_TYPE_fromString(const char* string)
{
    if (strcmp(string, "CHADEMO")==0) return GUN_TYPE_CHADEMO;
    if (strcmp(string, "GBDC")==0) return GUN_TYPE_GBDC;
    if (strcmp(string, "CCS2")==0) return GUN_TYPE_CCS2;
    if (strcmp(string, "CCS1")==0) return GUN_TYPE_CCS1;
    return GUN_TYPE_NACS;
}

static const char* GUN_TYPE_toString(gun_type_t type)
{
    switch(type)
    {
        case GUN_TYPE_CHADEMO : return "CHADEMO";
        case GUN_TYPE_GBDC : return "GBDC";
        case GUN_TYPE_CCS2 : return "CCS2";
        case GUN_TYPE_CCS1 : return "CCS1";
        default: return "NACS";
    }
    return "NACS";
}

static void ccu_load_GUN_config(cJSON *object, GUN_config_t* config)
{
    if (cJSON_IsArray(object))
    {
        if (cJSON_GetArraySize(object)==2)
        {
            cJSON *item0 = cJSON_GetArrayItem(object, 0);
            if (item0)
            {
                if (cJSON_HasObjectItem(item0, "connectorId"))
                config[0].connectorId = cJSON_GetNumberValue(cJSON_GetObjectItem(item0, "connectorId"));
                if (cJSON_HasObjectItem(item0, "GUN_Type"))
                config[0].GUN_Type = GUN_TYPE_fromString(cJSON_GetStringValue(cJSON_GetObjectItem(item0, "GUN_Type")));
                printi("config[0].GUN_Type=%d\n", config[0].GUN_Type);
                if (cJSON_HasObjectItem(item0, "GUN_Available"))
                config[0].GUN_Available = cJSON_IsTrue(cJSON_GetObjectItem(item0, "GUN_Available"));
                if (cJSON_HasObjectItem(item0, "GUN_maxI"))
                config[0].GUN_maxI = cJSON_GetNumberValue(cJSON_GetObjectItem(item0, "GUN_maxI"));

                if (cJSON_HasObjectItem(item0, "slac_ifname"))
                sprintf(config[0].slac_ifname, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "slac_ifname")));
                if (cJSON_HasObjectItem(item0, "can_ifname"))
                sprintf(config[0].can_ifname, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "can_ifname")));

                if (cJSON_HasObjectItem(item0, "QRCode_enable"))
                config[0].QRCode_enable = cJSON_IsTrue(cJSON_GetObjectItem(item0, "QRCode_enable"));
                if (cJSON_HasObjectItem(item0, "QRCode_URL"))
                sprintf(config[0].QRCode_URL, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item0, "QRCode_URL")));

                if (cJSON_HasObjectItem(item0, "requestPowerByMinutes"))
                config[0].requestPowerByMinutes = cJSON_IsTrue(cJSON_GetObjectItem(item0, "requestPowerByMinutes"));
                if (cJSON_HasObjectItem(item0, "requestPowerByPowerKW"))
                config[0].requestPowerByPowerKW = cJSON_IsTrue(cJSON_GetObjectItem(item0, "requestPowerByPowerKW"));
                if (cJSON_HasObjectItem(item0, "requestPowerBySOC"))
                config[0].requestPowerBySOC = cJSON_IsTrue(cJSON_GetObjectItem(item0, "requestPowerBySOC"));

                if (cJSON_HasObjectItem(item0, "GUNOverTemp_Warning"))
                config[0].GUNOverTemp_Warning = cJSON_GetNumberValue(cJSON_GetObjectItem(item0, "GUNOverTemp_Warning"));
                if (cJSON_HasObjectItem(item0, "GUNOverTemp_Stopping"))
                config[0].GUNOverTemp_Stopping = cJSON_GetNumberValue(cJSON_GetObjectItem(item0, "GUNOverTemp_Stopping"));

            }
            cJSON *item1 = cJSON_GetArrayItem(object, 1);
            if (item1)
            {
                if (cJSON_HasObjectItem(item1, "connectorId"))
                config[1].connectorId = cJSON_GetNumberValue(cJSON_GetObjectItem(item1, "connectorId"));
                if (cJSON_HasObjectItem(item0, "GUN_Type"))
                config[1].GUN_Type = GUN_TYPE_fromString(cJSON_GetStringValue(cJSON_GetObjectItem(item1, "GUN_Type")));
                if (cJSON_HasObjectItem(item1, "GUN_Available"))
                config[1].GUN_Available = cJSON_IsTrue(cJSON_GetObjectItem(item1, "GUN_Available"));
                if (cJSON_HasObjectItem(item1, "GUN_maxI"))
                config[1].GUN_maxI = cJSON_GetNumberValue(cJSON_GetObjectItem(item1, "GUN_maxI"));

                if (cJSON_HasObjectItem(item1, "slac_ifname"))
                sprintf(config[1].slac_ifname, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "slac_ifname")));
                if (cJSON_HasObjectItem(item1, "can_ifname"))
                sprintf(config[1].can_ifname, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "can_ifname")));

                if (cJSON_HasObjectItem(item1, "QRCode_enable"))
                config[1].QRCode_enable = cJSON_IsTrue(cJSON_GetObjectItem(item1, "QRCode_enable"));
                if (cJSON_HasObjectItem(item1, "QRCode_URL"))
                sprintf(config[1].QRCode_URL, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(item1, "QRCode_URL")));

                if (cJSON_HasObjectItem(item1, "requestPowerByMinutes"))
                config[1].requestPowerByMinutes = cJSON_IsTrue(cJSON_GetObjectItem(item1, "requestPowerByMinutes"));
                if (cJSON_HasObjectItem(item1, "requestPowerByPowerKW"))
                config[1].requestPowerByPowerKW = cJSON_IsTrue(cJSON_GetObjectItem(item1, "requestPowerByPowerKW"));
                if (cJSON_HasObjectItem(item1, "requestPowerBySOC"))
                config[1].requestPowerBySOC = cJSON_IsTrue(cJSON_GetObjectItem(item1, "requestPowerBySOC"));
                
                if (cJSON_HasObjectItem(item1, "GUNOverTemp_Warning"))
                config[1].GUNOverTemp_Warning = cJSON_GetNumberValue(cJSON_GetObjectItem(item1, "GUNOverTemp_Warning"));
                if (cJSON_HasObjectItem(item1, "GUNOverTemp_Stopping"))
                config[1].GUNOverTemp_Stopping = cJSON_GetNumberValue(cJSON_GetObjectItem(item1, "GUNOverTemp_Stopping"));
            }
        }
    }

}

static void ccu_save_GUN_config(cJSON *array, GUN_config_t* config)
{
    cJSON *item0 = cJSON_CreateObject();
    cJSON_AddNumberToObject(item0, "connectorId", config[0].connectorId);
    cJSON_AddStringToObject(item0, "GUN_Type", GUN_TYPE_toString(config[0].GUN_Type));
    cJSON_AddBoolToObject(item0, "GUN_Available", config[0].GUN_Available);
    cJSON_AddNumberToObject(item0, "GUN_maxI", config[0].GUN_maxI);

    cJSON_AddStringToObject(item0, "slac_ifname", config[0].slac_ifname);
    cJSON_AddStringToObject(item0, "can_ifname", config[0].can_ifname);
    
    cJSON_AddBoolToObject(item0, "QRCode_enable", config[0].QRCode_enable);
    cJSON_AddStringToObject(item0, "QRCode_URL", config[0].QRCode_URL);

    cJSON_AddBoolToObject(item0, "requestPowerByMinutes", config[0].requestPowerByMinutes);
    cJSON_AddBoolToObject(item0, "requestPowerByPowerKW", config[0].requestPowerByPowerKW);
    cJSON_AddBoolToObject(item0, "requestPowerBySOC", config[0].requestPowerBySOC);

    cJSON_AddNumberToObject(item0, "GUNOverTemp_Warning", config[0].GUNOverTemp_Warning);
    cJSON_AddNumberToObject(item0, "GUNOverTemp_Stopping", config[0].GUNOverTemp_Stopping);
    cJSON_AddItemToArray(array, item0);

    cJSON *item1 = cJSON_CreateObject();
    cJSON_AddNumberToObject(item1, "connectorId", config[1].connectorId);
    cJSON_AddStringToObject(item1, "GUN_Type", GUN_TYPE_toString(config[1].GUN_Type));
    cJSON_AddBoolToObject(item1, "GUN_Available", config[1].GUN_Available);
    cJSON_AddNumberToObject(item1, "GUN_maxI", config[1].GUN_maxI);

    cJSON_AddStringToObject(item1, "slac_ifname", config[1].slac_ifname);
    cJSON_AddStringToObject(item1, "can_ifname", config[1].can_ifname);
    
    cJSON_AddBoolToObject(item1, "QRCode_enable", config[1].QRCode_enable);
    cJSON_AddStringToObject(item1, "QRCode_URL", config[1].QRCode_URL);

    cJSON_AddBoolToObject(item1, "requestPowerByMinutes", config[1].requestPowerByMinutes);
    cJSON_AddBoolToObject(item1, "requestPowerByPowerKW", config[1].requestPowerByPowerKW);
    cJSON_AddBoolToObject(item1, "requestPowerBySOC", config[1].requestPowerBySOC);

    cJSON_AddNumberToObject(item1, "GUNOverTemp_Warning", config[1].GUNOverTemp_Warning);
    cJSON_AddNumberToObject(item1, "GUNOverTemp_Stopping", config[1].GUNOverTemp_Stopping);
    cJSON_AddItemToArray(array, item1);
}

void ccu_config_save(ccu_config_t* config, const char* filename)
{
    cJSON* root = cJSON_CreateObject();

    cJSON_AddNumberToObject(root, "TCU_ID", config->TCU_ID);
    cJSON_AddStringToObject(root, "CCU_SN", config->CCU_SN);
    cJSON_AddStringToObject(root, "CCU_ProductID", config->CCU_ProductID);
    cJSON_AddStringToObject(root, "CCU_VendorID", config->CCU_VendorID);
    cJSON_AddBoolToObject(root, "CCU_Available", config->CCU_Available);
    cJSON_AddNumberToObject(root, "BoxOverTemp_Warning", config->BoxOverTemp_Warning);
    cJSON_AddNumberToObject(root, "BoxOverTemp_Stopping", config->BoxOverTemp_Stopping);
    cJSON_AddStringToObject(root, "username", config->username);
    cJSON_AddStringToObject(root, "password", config->password);

    cJSON_AddNumberToObject(root, "GUN_Numb", config->GUN_Numb);
    cJSON* gun_config = cJSON_AddArrayToObject(root, "GUN_Config");
    ccu_save_GUN_config(gun_config, config->GUN_config);

    cJSON* pcuhw = cJSON_AddObjectToObject(root, "pcuhw");
    ccu_save_pcuhw_config(pcuhw, &config->pcuhw);

    cJSON* pcutc = cJSON_AddObjectToObject(root, "pcutc");
    ccu_save_pcutc_config(pcutc, &config->pcutc);

    cJSON* qttcu = cJSON_AddObjectToObject(root, "qttcu");
    ccu_save_qttcu_config(qttcu, &config->qttcu);

    cJSON* ocpp16 = cJSON_AddArrayToObject(root, "ocpp16");
    ccu_save_ocpp_config(ocpp16, config->ocpp16);

    cJSON* ocpp21 = cJSON_AddArrayToObject(root, "ocpp21");
    ccu_save_ocpp_config(ocpp21, config->ocpp21);

    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);
}

void ccu_config_load(ccu_config_t* config, const char* filename)
{
    memset(config, 0, sizeof(ccu_config));
    ccu_default_config(config);
    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!=NULL)
        {
            fread(fbuff, flen, 1, file);
            cJSON *root = cJSON_Parse(fbuff);
            if (root != NULL)
            {
                if (cJSON_HasObjectItem(root, "TCU_ID"))
                config->TCU_ID = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(root, "TCU_ID"));
                if (cJSON_HasObjectItem(root, "CCU_SN"))
                sprintf(config->CCU_SN, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "CCU_SN")));
                if (cJSON_HasObjectItem(root, "CCU_ProductID"))
                sprintf(config->CCU_ProductID, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "CCU_ProductID")));
                if (cJSON_HasObjectItem(root, "CCU_VendorID"))
                sprintf(config->CCU_VendorID, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "CCU_VendorID")));
                if (cJSON_HasObjectItem(root, "CCU_Available"))
                config->CCU_Available = cJSON_IsTrue(cJSON_GetObjectItem(root, "CCU_Available"));
                if (cJSON_HasObjectItem(root, "BoxOverTemp_Warning"))
                config->BoxOverTemp_Warning = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(root, "BoxOverTemp_Warning"));
                if (cJSON_HasObjectItem(root, "BoxOverTemp_Stopping"))
                config->BoxOverTemp_Stopping = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(root, "BoxOverTemp_Stopping"));
                if (cJSON_HasObjectItem(root, "username"))
                sprintf(config->username, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "username")));
                if (cJSON_HasObjectItem(root, "password"))
                sprintf(config->password, "%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "password")));

                if (cJSON_HasObjectItem(root, "password"))
                config->GUN_Numb = (int)cJSON_GetNumberValue(cJSON_GetObjectItem(root, "GUN_Numb"));
                if (cJSON_HasObjectItem(root, "password"))
                ccu_load_GUN_config(cJSON_GetObjectItem(root,"GUN_config"), config->GUN_config);

                if (cJSON_HasObjectItem(root, "pcuhw"))
                ccu_load_pcuhw_config(cJSON_GetObjectItem(root,"pcuhw"), &config->pcuhw);
                if (cJSON_HasObjectItem(root, "pcutc"))
                ccu_load_pcutc_config(cJSON_GetObjectItem(root,"pcutc"), &config->pcutc);
                if (cJSON_HasObjectItem(root, "qttcu"))
                ccu_load_qttcu_config(cJSON_GetObjectItem(root,"qttcu"), &config->qttcu);

                if (cJSON_HasObjectItem(root, "ocpp16"))
                ccu_load_ocpp_config(cJSON_GetObjectItem(root,"ocpp16"), config->ocpp16);
                if (cJSON_HasObjectItem(root, "ocpp21"))
                ccu_load_ocpp_config(cJSON_GetObjectItem(root,"ocpp21"), config->ocpp21);

                cJSON_Delete(root);
            }else{
                printd("cJSON_Parse(%p) failed.\n", fbuff);
                printf("%s\n", fbuff);
            }
            free(fbuff);
        }else{
            printd("malloc(%d) failed.\n", flen);
        }
        fclose(file);
    }else{
        printd("open(%s, rb) failed.\n", filename);
    }
}

void ccu_config_init(void)
{
    ccu_config_load(&ccu_config, "/home/root/app_run/etc/ccu_config.json");
}

void ccu_config_exit(void)
{
    ccu_config_save(&ccu_config, "/home/root/app_run/etc/ccu_config.json");
}
