#include "../json/cjson.h"
#include "../json/mms_json_inter.h"
#include "../json/PQSMsg.h"
#include <array>
#include <string>
#include <cstdlib>
#include <ctime>
#include <string>
#include <vector>
#include <map>

#ifndef EMPTY_FLOAT_VALUE
#define EMPTY_FLOAT_VALUE 3.14159f
#endif

extern QMutex kafka_data_list_mutex;
extern QList<Ckafka_data_t> kafka_data_list;

// statType: 0=95值, 1=平均值, 2=最大值, 3=最小值
static std::string MakeStatKey(int statType, const std::string& base)
{
    switch (statType) {
    case 0: return "G_" + base;
    case 1: return base;
    case 2: return "MAX_" + base;
    case 3: return "MIN_" + base;
    default: return base;
    }
}

static cJSON* GetObj(cJSON* parent, const char* name)
{
    if (parent == NULL || name == NULL) {
        return NULL;
    }
    return cJSON_GetObjectItem(parent, name);
}

static float GetJsonFloat(cJSON* root,
                          const char* group,
                          const char* phase,
                          const std::string& key)
{
    cJSON* value = GetObj(root, "Value");
    cJSON* g = GetObj(value, group);
    cJSON* p = GetObj(g, phase);
    cJSON* item = GetObj(p, key.c_str());

    if (item == NULL) {
        return 0.0f;
    }

    if (item && item->type == cJSON_Number) {
        return static_cast<float>(item->valuedouble);
    }

    if (item && item->type == cJSON_String && item->valuestring != NULL) {
        return static_cast<float>(atof(item->valuestring));
    }

    return 0.0f;
}

static float GetValue(cJSON* root,
                      int statType,
                      const char* group,
                      const char* phase,
                      const std::string& base)
{
    return GetJsonFloat(root, group, phase, MakeStatKey(statType, base));
}

static void FillDeviation(float val, float& up, float& low)
{
    if (val >= 0.0f) {
        up = val;
        low = 0.0f;
    } else {
        up = 0.0f;
        low = -val;
    }
}

static long long GetJsonTimeMs(cJSON* root)
{
    cJSON* value = GetObj(root, "Value");
    cJSON* item = GetObj(value, "TIME");

    if (item == NULL) {
        return 0;
    }

    if (item && item->type == cJSON_Number) {
        return static_cast<long long>(item->valuedouble);
    }

    if (item && item->type == cJSON_String && item->valuestring != NULL) {
        return atoll(item->valuestring);
    }

    return 0;
}

static tagTime MakeTagTimeFromMs(long long ms)
{
    time_t sec = static_cast<time_t>(ms / 1000);
    struct tm tmv;
    #ifdef _WIN32
        localtime_s(&tmv, &sec);
    #else
        localtime_r(&sec, &tmv);
    #endif
    return tagTime(tmv);
}

// connectionType: 0=星型, 1=角型
std::array<tagPqData_Float, 4> BuildPqFloatDataFromJson(cJSON* jsondata,
                                                        int connectionType)
{
    std::array<tagPqData_Float, 4> all_data;

    const char* PH3[3];
    const char* PH4[4];

    if (connectionType == 1) {
        // 角型
        PH3[0] = "AB";
        PH3[1] = "BC";
        PH3[2] = "CA";

        PH4[0] = "AB";
        PH4[1] = "BC";
        PH4[2] = "CA";
        PH4[3] = "T";
    }
    else {
        // 星型
        PH3[0] = "A";
        PH3[1] = "B";
        PH3[2] = "C";

        PH4[0] = "A";
        PH4[1] = "B";
        PH4[2] = "C";
        PH4[3] = "T";
    }

    long long timeMs = GetJsonTimeMs(jsondata);

    for (int stat = 0; stat < 4; ++stat) {
        tagPqData_Float& dst = all_data[stat];

        dst.name = 0;
        dst.Data_Type = 0;

        if (timeMs > 0) {
            dst.time = MakeTagTimeFromMs(timeMs);
        }

        // 1. Rms[0..8]
        // 0-2: 相电压有效值 VRMS
        // 3-5: 相电流有效值 IRMS
        // 6-8: 线电压有效值 VRMS_LVR
        // 注意：根据 ZJ.xml/jsondata，只有线电压有效值使用 LVR
        if (connectionType == 1) {
            // 角型

            // 相电压空置
            dst.Rms[0] = EMPTY_FLOAT_VALUE;
            dst.Rms[1] = EMPTY_FLOAT_VALUE;
            dst.Rms[2] = EMPTY_FLOAT_VALUE;

            // 电流
            for (int i = 0; i < 3; ++i) {
                dst.Rms[i + 3] =
                    GetValue(jsondata, stat, "I", PH3[i], "IRMS");
            }
        
            // 线电压
            for (int i = 0; i < 3; ++i) {
                dst.Rms[i + 6] =
                    GetValue(jsondata, stat, "V", PH3[i], "VRMS_LVR");
            }
        }
        else {
            // 星型
        
            // 相电压
            for (int i = 0; i < 3; ++i) {
                dst.Rms[i] =
                    GetValue(jsondata, stat, "V", PH3[i], "VRMS");
            }
        
            // 电流
            for (int i = 0; i < 3; ++i) {
                dst.Rms[i + 3] =
                    GetValue(jsondata, stat, "I", PH3[i], "IRMS");
            }
        
            // 线电压
            for (int i = 0; i < 3; ++i) {
                dst.Rms[i + 6] =
                    GetValue(jsondata, stat, "V", PH3[i], "VRMS_LVR");
            }
        }

        // 2. 电压偏差
        // 星型：转换函数取 UU/UL[0..2] 作为相电压偏差，线电压偏差空置
        // 角型：转换函数前 3 个位置空置，后面取 UU/UL[0..2] 作为线电压偏差
        // 因为 jsondata 里没有 DELTA_V_LVR，所以统一填 DELTA_V 到 [0..2]
        for (int i = 0; i < 3; ++i) {
            float dev = GetValue(jsondata, stat, "V", PH3[i], "DELTA_V");
            FillDeviation(dev, dst.UU_Deviation[i], dst.UL_Deviation[i]);
        }

        // 3. 频率偏差 + 频率
        dst.F_Deviation[0] = GetValue(jsondata, stat, "V", "T", "DELTA_FREQ");
        dst.F_Deviation[1] = GetValue(jsondata, stat, "V", "T", "FREQ");

        // 4. UI_Seq
        dst.UI_Seq[0][0] = GetValue(jsondata, stat, "V", "T", "VZSEQ");
        dst.UI_Seq[0][1] = GetValue(jsondata, stat, "V", "T", "VNSEQ");
        dst.UI_Seq[0][2] = GetValue(jsondata, stat, "V", "T", "VPSEQ");
        dst.UI_Seq[0][3] = GetValue(jsondata, stat, "V", "T", "V_UNBAN");

        dst.UI_Seq[1][0] = GetValue(jsondata, stat, "I", "T", "IZSEQ");
        dst.UI_Seq[1][1] = GetValue(jsondata, stat, "I", "T", "INSEQ");
        dst.UI_Seq[1][2] = GetValue(jsondata, stat, "I", "T", "IPSEQ");
        dst.UI_Seq[1][3] = GetValue(jsondata, stat, "I", "T", "I_UNBAN");

        // 5. 基波有效值 FuHarm[*][0]
        // 星型：FuHarm[0..2][0] 被当作 A/B/C 相电压 V1
        // 角型：FuHarm[0..2][0] 被当作 AB/BC/CA 线电压 V1
        // jsondata 中仍然使用 V1 字段，不额外使用 LVR
        for (int i = 0; i < 3; ++i) {
            dst.FuHarm[i][0]     = GetValue(jsondata, stat, "V", PH3[i], "V1");
            dst.FuHarm[i + 3][0] = GetValue(jsondata, stat, "I", PH3[i], "I1");
        }

        // 6. 基波相角 FuHarmPhase[*][0]
        for (int i = 0; i < 3; ++i) {
            dst.FuHarmPhase[i][0] =
                GetValue(jsondata, stat, "V", PH3[i], "VFUND_ANGLE");

            dst.FuHarmPhase[i + 3][0] =
                GetValue(jsondata, stat, "I", PH3[i], "IFUND_ANGLE");
        }

        // 7. 2-50 次谐波有效值
        // 星型转换：先取 FuHarm[0..2][1..49] 作为相电压，再取 FuHarm[3..5] 作为电流，线电压空置
        // 角型转换：先空置相电压，再取 FuHarm[3..5] 作为电流，再取 FuHarm[0..2] 作为线电压
        // 所以这里统一填 FuHarm[0..2]=V2..V50，FuHarm[3..5]=I2..I50
        for (int h = 1; h < HARMNUM; ++h) {
            int no = h + 1;

            for (int i = 0; i < 3; ++i) {
                dst.FuHarm[i][h] =
                    GetValue(jsondata, stat, "V", PH3[i], "V" + std::to_string(no));

                dst.FuHarm[i + 3][h] =
                    GetValue(jsondata, stat, "I", PH3[i], "I" + std::to_string(no));
            }
        }

        // 8. 2-50 次谐波相角
        for (int h = 1; h < HARMNUM; ++h) {
            int no = h + 1;

            for (int i = 0; i < 3; ++i) {
                dst.FuHarmPhase[i][h] =
                    GetValue(jsondata, stat, "V", PH3[i], "VA" + std::to_string(no));

                dst.FuHarmPhase[i + 3][h] =
                    GetValue(jsondata, stat, "I", PH3[i], "IA" + std::to_string(no));
            }
        }

        // 9. 间谐波有效值 InHarm[*][0..49]
        // 星型：InHarm[0..2] 相电压有效，InHarm[3..5] 电流有效，线电压空置
        // 角型：先空置相电压，再取 InHarm[3..5] 电流，再取 InHarm[0..2] 线电压
        // jsondata 中统一使用 SV_x / SI_x
        for (int h = 0; h < HARMNUM; ++h) {
            for (int i = 0; i < 3; ++i) {
                dst.InHarm[i][h].Val =
                    GetValue(jsondata, stat, "V", PH3[i], "SV_" + std::to_string(h));

                dst.InHarm[i + 3][h].Val =
                    GetValue(jsondata, stat, "I", PH3[i], "SI_" + std::to_string(h));
            }
        }

        // 10. 总功率 Total_Power[4][3]
        // phase: A/B/C/T
        // index: 0=P, 1=Q, 2=S
        for (int i = 0; i < 4; ++i) {
            dst.Total_Power[i][0] = GetValue(jsondata, stat, "PQ", PH4[i], "P");
            dst.Total_Power[i][1] = GetValue(jsondata, stat, "PQ", PH4[i], "Q");
            dst.Total_Power[i][2] = GetValue(jsondata, stat, "PQ", PH4[i], "S");
        }

        // 11. 谐波功率 Harm_Power[4][50]
        // h=0 对应 P1/Q1/S1，h=1..49 对应 P2..P50/Q2..Q50/S2..S50
        for (int i = 0; i < 4; ++i) {
            for (int h = 0; h < HARMNUM; ++h) {
                int no = h + 1;

                dst.Harm_Power[i][h].P =
                    GetValue(jsondata, stat, "PQ", PH4[i], "P" + std::to_string(no));

                dst.Harm_Power[i][h].Q =
                    GetValue(jsondata, stat, "PQ", PH4[i], "Q" + std::to_string(no));

                dst.Harm_Power[i][h].S =
                    GetValue(jsondata, stat, "PQ", PH4[i], "S" + std::to_string(no));
            }
        }

        // 12. 谐波含有率 Harm_Contain[6][50]
        // 0-2: 电压谐波含有率
        // 3-5: 电流谐波含有率
        // 转换函数会根据星型/角型决定这些数据输出到相电压区还是线电压区
        for (int h = 1; h < HARMNUM; ++h) {
            for (int i = 0; i < 3; ++i) {
                dst.Harm_Contain[i][h] =
                    GetValue(jsondata, stat, "V", PH3[i], "SV_" + std::to_string(h));

                dst.Harm_Contain[i + 3][h] =
                    GetValue(jsondata, stat, "I", PH3[i], "SI_" + std::to_string(h));
            }
        }

        // 13. 谐波总畸变率 Harm_Aberrance[6]
        // 0-2: 电压 THD
        // 3-5: 电流 THD
        for (int i = 0; i < 3; ++i) {
            dst.Harm_Aberrance[i] =
                GetValue(jsondata, stat, "V", PH3[i], "VTHD");

            dst.Harm_Aberrance[i + 3] =
                GetValue(jsondata, stat, "I", PH3[i], "ITHD");
        }

        // 14. 功率因数
        for (int i = 0; i < 4; ++i) {
            dst.Cos_PF[i] = GetValue(jsondata, stat, "PQ", PH4[i], "PF");
            dst.Cos_DF[i] = GetValue(jsondata, stat, "PQ", PH4[i], "DF");
        }

        // 15. 波动、短闪、长闪
        // 目前 jsondata 中没有 LVR 字段，统一填 A/B/C 三相字段
        // 星型转换函数输出三相数据，线电压位置空置
        // 角型转换函数先空置三相位置，再把这三个值输出到线电压位置
        for (int i = 0; i < 3; ++i) {
            dst.U_Fluctuation[i] = GetValue(jsondata, stat, "V", PH3[i], "FLUC");
            dst.U_Flicker[i]     = GetValue(jsondata, stat, "V", PH3[i], "PST");
            dst.UL_Flicker[i]    = GetValue(jsondata, stat, "V", PH3[i], "PLT");
        }
    }

    return all_data;
}

////////////////////////////////////////////////////实时部分

static float GetRtJsonFloat(cJSON* root,
                            const char* group,
                            const char* phase,
                            const std::string& key)
{
    cJSON* value = GetObj(root, "Value");
    cJSON* g = GetObj(value, group);
    cJSON* p = GetObj(g, phase);
    cJSON* item = GetObj(p, key.c_str());

    if (item == NULL) {
        return 0.0f;
    }

    if (item && item->type == cJSON_Number) {
        return static_cast<float>(item->valuedouble);
    }

    if (item && item->type == cJSON_String && item->valuestring != NULL) {
        return static_cast<float>(atof(item->valuestring));
    }

    return 0.0f;
}

static float GetRtValue(cJSON* root,
                        const char* group,
                        const char* phase,
                        const std::string& key)
{
    return GetRtJsonFloat(root, group, phase, key);
}

static long long GetRtJsonTimeMs(cJSON* root)
{
    cJSON* value = GetObj(root, "Value");
    cJSON* item = GetObj(value, "TIME");

    if (item == NULL) {
        return 0;
    }

    if (item && item->type == cJSON_Number) {
        return static_cast<long long>(item->valuedouble);
    }

    if (item && item->type == cJSON_String && item->valuestring != NULL) {
        return atoll(item->valuestring);
    }

    return 0;
}

static tagTime MakeRtTagTimeFromMs(long long ms)
{
    time_t sec = static_cast<time_t>(ms / 1000);
    struct tm tmv;
    #ifdef _WIN32
        localtime_s(&tmv, &sec);
    #else
        localtime_r(&sec, &tmv);
    #endif
    return tagTime(tmv);
}

static void FillRtDeviation(float val, float& up, float& low)
{
    if (val >= 0.0f) {
        up = val;
        low = 0.0f;
    } else {
        up = 0.0f;
        low = -val;
    }
}

// wiringType: 0=星型, 1=角型
RealtagPqDate_float BuildRealPqDataFromJson(cJSON* jsondata, int wiringType)
{
    RealtagPqDate_float realdata;

    const bool isDelta = (wiringType == 1);

    const char* PH3[3];
    const char* PH4[4];

    if (isDelta) {
        PH3[0] = "AB";
        PH3[1] = "BC";
        PH3[2] = "CA";

        PH4[0] = "AB";
        PH4[1] = "BC";
        PH4[2] = "CA";
        PH4[3] = "T";
    } else {
        PH3[0] = "A";
        PH3[1] = "B";
        PH3[2] = "C";

        PH4[0] = "A";
        PH4[1] = "B";
        PH4[2] = "C";
        PH4[3] = "T";
    }

    long long timeMs = GetRtJsonTimeMs(jsondata);
    if (timeMs > 0) {
        realdata.time = MakeRtTagTimeFromMs(timeMs);
    }

    // 1. Rms[0..8]
    // 实时结构注释：相电压、线电压、电流有效值
    if (isDelta) {
        // 角型：相电压空置，线电压从 AB/BC/CA 的 VRMS 取，电流也按 AB/BC/CA 取
        for (int i = 0; i < 3; ++i) {
            realdata.Rms[i]     = EMPTY_FLOAT_VALUE;
            realdata.Rms[i + 3] = GetRtValue(jsondata, "V", PH3[i], "VRMS");
            realdata.Rms[i + 6] = GetRtValue(jsondata, "I", PH3[i], "IRMS");
        }
    } else {
        // 星型：相电压 A/B/C VRMS，线电压 A/B/C VRMS_LVR，电流 A/B/C IRMS
        for (int i = 0; i < 3; ++i) {
            realdata.Rms[i]     = GetRtValue(jsondata, "V", PH3[i], "VRMS");
            realdata.Rms[i + 3] = GetRtValue(jsondata, "V", PH3[i], "VRMS_LVR");
            realdata.Rms[i + 6] = GetRtValue(jsondata, "I", PH3[i], "IRMS");
        }
    }

    // 2. 电压偏差
    // 星型序列化取 9-11 为相电压偏差；角型序列化 12-14 为线电压偏差。
    // 两种最终都从 UU/UL[0..2] 取，所以填 [0..2] 即可。
    for (int i = 0; i < 3; ++i) {
        float dev = GetRtValue(jsondata, "V", PH3[i], "DELTA_V");
        FillRtDeviation(dev, realdata.UU_Deviation[i], realdata.UL_Deviation[i]);
    }

    // 3. THD[0..5]
    // 星型：THD[0..2] 相电压，THD[3..5] 电流
    // 角型：THD[0..2] 填线电压；Delta_RtHarmV 也取 0..2
    for (int i = 0; i < 3; ++i) {
        realdata.THD[i]     = GetRtValue(jsondata, "V", PH3[i], "VTHD");
        realdata.THD[i + 3] = GetRtValue(jsondata, "I", PH3[i], "ITHD");
    }

    // 4. FREQ[0..1]
    realdata.FREQ[0] = GetRtValue(jsondata, "V", "T", "FREQ");
    realdata.FREQ[1] = GetRtValue(jsondata, "V", "T", "DELTA_FREQ");

    // 5. UI_Seq[2][5]
    // 序列化时输出 [0][0,1,2,4] 和 [1][0,1,2,4]，所以 [3] 可放零序不平衡备用，[4] 放负序不平衡
    realdata.UI_Seq[0][0] = GetRtValue(jsondata, "V", "T", "VZSEQ");
    realdata.UI_Seq[0][1] = GetRtValue(jsondata, "V", "T", "VNSEQ");
    realdata.UI_Seq[0][2] = GetRtValue(jsondata, "V", "T", "VPSEQ");
    realdata.UI_Seq[0][3] = GetRtValue(jsondata, "V", "T", "VZSEQ_UNBAN");
    realdata.UI_Seq[0][4] = GetRtValue(jsondata, "V", "T", "V_UNBAN");

    realdata.UI_Seq[1][0] = GetRtValue(jsondata, "I", "T", "IZSEQ");
    realdata.UI_Seq[1][1] = GetRtValue(jsondata, "I", "T", "INSEQ");
    realdata.UI_Seq[1][2] = GetRtValue(jsondata, "I", "T", "IPSEQ");
    realdata.UI_Seq[1][3] = GetRtValue(jsondata, "I", "T", "IZSEQ_UNBAN");
    realdata.UI_Seq[1][4] = GetRtValue(jsondata, "I", "T", "I_UNBAN");

    // 6. TOTAL_POWER[4][3], COS_PF, COS_DF
    for (int i = 0; i < 4; ++i) {
        realdata.TOTAL_POWER[i][0] = GetRtValue(jsondata, "PQ", PH4[i], "P");
        realdata.TOTAL_POWER[i][1] = GetRtValue(jsondata, "PQ", PH4[i], "Q");
        realdata.TOTAL_POWER[i][2] = GetRtValue(jsondata, "PQ", PH4[i], "S");

        realdata.COS_PF[i] = GetRtValue(jsondata, "PQ", PH4[i], "PF");
        realdata.COS_DF[i] = GetRtValue(jsondata, "PQ", PH4[i], "DF");
    }

    // 7. 基波有效值和基波相角
    // HARMV/HARMI/HARMVP/HARMIP 的 [0] 被序列化函数当作基波 V1/I1 和基波角度。
    for (int i = 0; i < 3; ++i) {
        realdata.HARMV[i][0]  = GetRtValue(jsondata, "V", PH3[i], "V1");
        realdata.HARMI[i][0]  = GetRtValue(jsondata, "I", PH3[i], "I1");

        realdata.HARMVP[i][0] = GetRtValue(jsondata, "V", PH3[i], "VFUND_ANGLE");

        // 实时 JSON 中电流基波相角字段是 I_ANGLE
        realdata.HARMIP[i][0] = GetRtValue(jsondata, "I", PH3[i], "I_ANGLE");
    }

    // 8. 2~50 次谐波、电压/电流相角
    for (int h = 1; h < HARMNUM; ++h) {
        int no = h + 1;

        for (int i = 0; i < 3; ++i) {
            realdata.HARMV[i][h] =
                GetRtValue(jsondata, "V", PH3[i], "V" + std::to_string(no));

            realdata.HARMI[i][h] =
                GetRtValue(jsondata, "I", PH3[i], "I" + std::to_string(no));

            realdata.HARMVP[i][h] =
                GetRtValue(jsondata, "V", PH3[i], "VA" + std::to_string(no));

            // 如果以后 JSON 有 IA2~IA50，这里会自动取；当前样例没有则为 0
            realdata.HARMIP[i][h] =
                GetRtValue(jsondata, "I", PH3[i], "IA" + std::to_string(no));
        }
    }

    // 9. 间谐波电压 INHARMV[3][50]
    for (int h = 0; h < HARMNUM; ++h) {
        for (int i = 0; i < 3; ++i) {
            realdata.INHARMV[i][h] =
                GetRtValue(jsondata, "V", PH3[i], "SV_" + std::to_string(h));
        }
    }

    return realdata;
}

///////////////////////////////////////////////////////通用方式，根据不同的模板到pqd查找名称建立映射然后到json中取值填入再序列化输出
struct PqdMeta {
    int idx;
    std::string name;
    std::string phase;
    int harmStart;
    int harmEnd;

    PqdMeta() : idx(-1), harmStart(0), harmEnd(0) {}
};

static int GetInt(cJSON* obj, const char* name, int defVal = 0)
{
    cJSON* item = GetObj(obj, name);
    if (!item) return defVal;
    if (item->type == cJSON_Number) return item->valueint;
    if (item->type == cJSON_String && item->valuestring) return atoi(item->valuestring);
    return defVal;
}

static std::string GetStr(cJSON* obj, const char* name)
{
    cJSON* item = GetObj(obj, name);
    if (item && item->type == cJSON_String && item->valuestring) {
        return item->valuestring;
    }
    return "";
}

static float GetJsonFloat(cJSON* root,
                          const std::string& group,
                          const std::string& phase,
                          const std::string& key)
{
    cJSON* value = GetObj(root, "Value");
    cJSON* g = GetObj(value, group.c_str());
    cJSON* p = GetObj(g, phase.c_str());
    cJSON* item = GetObj(p, key.c_str());

    if (!item) return 0.0f;

    if (item->type == cJSON_Number) {
        return static_cast<float>(item->valuedouble);
    }

    if (item->type == cJSON_String && item->valuestring) {
        return static_cast<float>(atof(item->valuestring));
    }

    return 0.0f;
}

static std::string Base64Encode(const unsigned char* bytes_to_encode, size_t in_len)
{
    static const char base64_chars[] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";

    std::string ret;
    int i = 0;
    int j = 0;
    unsigned char char_array_3[3];
    unsigned char char_array_4[4];

    while (in_len--) {
        char_array_3[i++] = *(bytes_to_encode++);
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
                              ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
                              ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; i < 4; i++) {
                ret += base64_chars[char_array_4[i]];
            }
            i = 0;
        }
    }

    if (i) {
        for (j = i; j < 3; j++) {
            char_array_3[j] = '\0';
        }

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
                          ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
                          ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (j = 0; j < i + 1; j++) {
            ret += base64_chars[char_array_4[j]];
        }

        while (i++ < 3) {
            ret += '=';
        }
    }

    return ret;
}

static std::string FloatBufferToBase64(const std::vector<float>& buffer)
{
    const unsigned char* data =
        reinterpret_cast<const unsigned char*>(buffer.data());

    return Base64Encode(data, buffer.size() * sizeof(float));
}

static std::map<int, PqdMeta> BuildPqdMetaMap(cJSON* tplRoot)
{
    std::map<int, PqdMeta> result;

    cJSON* pqdArr = GetObj(tplRoot, "Pqd");
    if (!pqdArr || !pqdArr->type == cJSON_Array){
        return result;
    }

    int size = cJSON_GetArraySize(pqdArr);
    for (int i = 0; i < size; ++i) {
        cJSON* item = cJSON_GetArrayItem(pqdArr, i);
        if (!item) continue;

        PqdMeta meta;
        meta.idx = GetInt(item, "Idx", -1);
        meta.name = GetStr(item, "Name");
        meta.phase = GetStr(item, "Phase");
        meta.harmStart = GetInt(item, "HarmStart", 0);
        meta.harmEnd = GetInt(item, "HarmEnd", 0);

        if (meta.idx >= 0) {
            result[meta.idx] = meta;
        }
    }

    return result;
}

static cJSON* FindDataSet(cJSON* tplRoot, const std::string& dataSetName)
{
    cJSON* cldevArr = GetObj(tplRoot, "Cldev");
    if (!cldevArr || !cldevArr->type == cJSON_Array){
        return NULL;
    }

    int cldevSize = cJSON_GetArraySize(cldevArr);
    for (int i = 0; i < cldevSize; ++i) {
        cJSON* cldev = cJSON_GetArrayItem(cldevArr, i);
        cJSON* dsArr = GetObj(cldev, "DataSet");
        if (!dsArr || !dsArr->type == cJSON_Array){
            continue;
        }

        int dsSize = cJSON_GetArraySize(dsArr);
        for (int j = 0; j < dsSize; ++j) {
            cJSON* ds = cJSON_GetArrayItem(dsArr, j);
            std::string name = GetStr(ds, "Name");
            if (name == dataSetName) {
                return ds;
            }
        }
    }

    return NULL;
}

static std::vector<int> GetDataArrayIdxList(cJSON* dataSet)
{
    std::vector<int> result;

    cJSON* arr = GetObj(dataSet, "DataArray");
    if (!arr || !arr->type == cJSON_Array) {
        return result;
    }

    int size = cJSON_GetArraySize(arr);
    for (int i = 0; i < size; ++i) {
        cJSON* item = cJSON_GetArrayItem(arr, i);
        int idx = GetInt(item, "Idx", -1);
        if (idx >= 0) {
            result.push_back(idx);
        }
    }

    return result;
}

static std::string StatPrefix(int statType)
{
    // 0=95, 1=平均, 2=最大, 3=最小
    switch (statType) {
    case 0: return "G_";
    case 1: return "";
    case 2: return "MAX_";
    case 3: return "MIN_";
    default: return "";
    }
}

static std::string MakeJsonKey(const std::string& baseKey,
                               bool isStat,
                               int statType)
{
    if (!isStat) {
        return baseKey;
    }
    return StatPrefix(statType) + baseKey;
}

static float GetByKey(cJSON* jsondata,
                      const std::string& group,
                      const std::string& phase,
                      const std::string& baseKey,
                      bool isStat,
                      int statType)
{
    return GetJsonFloat(jsondata, group, phase,
                        MakeJsonKey(baseKey, isStat, statType));
}

static void AppendHarmValues(std::vector<float>& out,
                             cJSON* jsondata,
                             const PqdMeta& meta,
                             const std::string& group,
                             const std::string& prefix,
                             bool isStat,
                             int statType)
{
    int start = meta.harmStart;
    int end = meta.harmEnd;

    if (start <= 0 && end <= 0) {
        out.push_back(0.0f);
        return;
    }

    for (int h = start; h <= end; ++h) {
        out.push_back(GetByKey(jsondata, group, meta.phase,
                               prefix + std::to_string(h),
                               isStat, statType));
    }
}

static void AppendInHarmValues(std::vector<float>& out,
                               cJSON* jsondata,
                               const PqdMeta& meta,
                               const std::string& group,
                               const std::string& prefix,
                               bool isStat,
                               int statType)
{
    int count = meta.harmEnd - meta.harmStart + 1;
    if (count <= 0) {
        count = 50;
    }

    for (int i = 0; i < count; ++i) {
        out.push_back(GetByKey(jsondata, group, meta.phase,
                               prefix + std::to_string(i),
                               isStat, statType));
    }
}

static float GetSingleValueByMeta(cJSON* jsondata,
                                  const PqdMeta& meta,
                                  bool isStat,
                                  int statType)
{
    const std::string& n = meta.name;
    const std::string& ph = meta.phase;

    if (n == "Pq_Freq")       return GetByKey(jsondata, "V", "T",  "FREQ",         isStat, statType);
    if (n == "Pq_FreqDev")    return GetByKey(jsondata, "V", "T",  "DELTA_FREQ",  isStat, statType);

    if (n == "Pq_RmsU")       return GetByKey(jsondata, "V", ph,   "VRMS",        isStat, statType);
    if (n == "Pq_RmsLU")      return GetByKey(jsondata, "V", ph,   "VRMS_LVR",    isStat, statType);
    if (n == "Pq_RmsI")       return GetByKey(jsondata, "I", ph,   "IRMS",        isStat, statType);

    if (n == "Pq_RmsFundU")   return GetByKey(jsondata, "V", ph,   "V1",          isStat, statType);
    if (n == "Pq_RmsFundLU")  return GetByKey(jsondata, "V", ph,   "V1",          isStat, statType);
    if (n == "Pq_RmsFundI")   return GetByKey(jsondata, "I", ph,   "I1",          isStat, statType);

    if (n == "Pq_UDev")       return GetByKey(jsondata, "V", ph,   "DELTA_V",     isStat, statType);
    if (n == "Pq_LUDev")      return GetByKey(jsondata, "V", ph,   "DELTA_V",     isStat, statType);

    if (n == "Pq_FundUAng")   return GetByKey(jsondata, "V", ph,   "VFUND_ANGLE", isStat, statType);
    if (n == "Pq_FundLUAng")  return GetByKey(jsondata, "V", ph,   "VFUND_ANGLE", isStat, statType);
    if (n == "Pq_FundIAng")   return GetByKey(jsondata, "I", ph,   "I_ANGLE",     isStat, statType);

    if (n == "Pq_ThdU")       return GetByKey(jsondata, "V", ph,   "VTHD",        isStat, statType);
    if (n == "Pq_ThdLU")      return GetByKey(jsondata, "V", ph,   "VTHD",        isStat, statType);
    if (n == "Pq_ThdI")       return GetByKey(jsondata, "I", ph,   "ITHD",        isStat, statType);

    if (n == "Pq_SeqZeroU")   return GetByKey(jsondata, "V", "T",  "VZSEQ",       isStat, statType);
    if (n == "Pq_SeqNegU")    return GetByKey(jsondata, "V", "T",  "VNSEQ",       isStat, statType);
    if (n == "Pq_SeqPosU")    return GetByKey(jsondata, "V", "T",  "VPSEQ",       isStat, statType);
    if (n == "Pq_UnbalNegU")  return GetByKey(jsondata, "V", "T",  "V_UNBAN",     isStat, statType);
    if (n == "Pq_UnbalZeroU") return GetByKey(jsondata, "V", "T",  "VZSEQ_UNBAN", isStat, statType);

    if (n == "Pq_SeqZeroI")   return GetByKey(jsondata, "I", "T",  "IZSEQ",       isStat, statType);
    if (n == "Pq_SeqNegI")    return GetByKey(jsondata, "I", "T",  "INSEQ",       isStat, statType);
    if (n == "Pq_SeqPosI")    return GetByKey(jsondata, "I", "T",  "IPSEQ",       isStat, statType);
    if (n == "Pq_UnbalNegI")  return GetByKey(jsondata, "I", "T",  "I_UNBAN",     isStat, statType);
    if (n == "Pq_UnbalZeroI") return GetByKey(jsondata, "I", "T",  "IZSEQ_UNBAN", isStat, statType);

    if (n == "Pq_P")          return GetByKey(jsondata, "PQ", ph,  "P",           isStat, statType);
    if (n == "Pq_Q")          return GetByKey(jsondata, "PQ", ph,  "Q",           isStat, statType);
    if (n == "Pq_S")          return GetByKey(jsondata, "PQ", ph,  "S",           isStat, statType);

    if (n == "Pq_TotP")       return GetByKey(jsondata, "PQ", "T", "P",           isStat, statType);
    if (n == "Pq_TotQ")       return GetByKey(jsondata, "PQ", "T", "Q",           isStat, statType);
    if (n == "Pq_TotS")       return GetByKey(jsondata, "PQ", "T", "S",           isStat, statType);

    if (n == "Pq_PF")         return GetByKey(jsondata, "PQ", ph,  "PF",          isStat, statType);
    if (n == "Pq_DF")         return GetByKey(jsondata, "PQ", ph,  "DF",          isStat, statType);
    if (n == "Pq_TotPF")      return GetByKey(jsondata, "PQ", "T", "PF",          isStat, statType);
    if (n == "Pq_TotDF")      return GetByKey(jsondata, "PQ", "T", "DF",          isStat, statType);

    if (n == "Pq_Fluct")      return GetByKey(jsondata, "V", ph,   "FLUC",        isStat, statType);
    if (n == "Pq_LFluct")     return GetByKey(jsondata, "V", ph,   "FLUC",        isStat, statType);
    if (n == "Pq_Pst")        return GetByKey(jsondata, "V", ph,   "PST",         isStat, statType);
    if (n == "Pq_LPst")       return GetByKey(jsondata, "V", ph,   "PST",         isStat, statType);
    if (n == "Pq_Plt")        return GetByKey(jsondata, "V", ph,   "PLT",         isStat, statType);
    if (n == "Pq_LPlt")       return GetByKey(jsondata, "V", ph,   "PLT",         isStat, statType);

    return 0.0f;
}

static void AppendValueByMeta(std::vector<float>& out,
                              cJSON* jsondata,
                              const PqdMeta& meta,
                              bool isStat,
                              int statType)
{
    const std::string& n = meta.name;

    if (n == "Pq_HarmU" || n == "Pq_HarmLU") {
        AppendHarmValues(out, jsondata, meta, "V", "V", isStat, statType);
        return;
    }

    if (n == "Pq_HarmI") {
        AppendHarmValues(out, jsondata, meta, "I", "I", isStat, statType);
        return;
    }

    if (n == "Pq_HarmUAng" || n == "Pq_HarmLUAng") {
        AppendHarmValues(out, jsondata, meta, "V", "VA", isStat, statType);
        return;
    }

    if (n == "Pq_HarmIAng") {
        AppendHarmValues(out, jsondata, meta, "I", "IA", isStat, statType);
        return;
    }

    if (n == "Pq_InHarmUR" || n == "Pq_InHarmLU") {
        AppendInHarmValues(out, jsondata, meta, "V", "SV_", isStat, statType);
        return;
    }

    if (n == "Pq_InHarmIAmp") {
        AppendInHarmValues(out, jsondata, meta, "I", "SI_", isStat, statType);
        return;
    }

    if (n == "Pq_HarmP" || n == "Pq_FundP" || n == "Pq_TotHarmP") {
        AppendHarmValues(out, jsondata, meta, "PQ", "P", isStat, statType);
        return;
    }

    if (n == "Pq_HarmQ" || n == "Pq_FundQ" || n == "Pq_TotHarmQ") {
        AppendHarmValues(out, jsondata, meta, "PQ", "Q", isStat, statType);
        return;
    }

    if (n == "Pq_HarmS" || n == "Pq_FundS" || n == "Pq_TotHarmS") {
        AppendHarmValues(out, jsondata, meta, "PQ", "S", isStat, statType);
        return;
    }

    out.push_back(GetSingleValueByMeta(jsondata, meta, isStat, statType));
}

// dataSetName 示例：
// "Ds$Pqd$Rt$01"
// "Ds$Pqd$Rt$HarmV$01"
// "Ds$Pqd$Stat$01"
std::string BuildBase64ByTemplate(cJSON* templateRoot,
                                  cJSON* jsondata,
                                  const std::string& dataSetName,
                                  bool isStat,
                                  int statType)
{
    std::map<int, PqdMeta> metaMap = BuildPqdMetaMap(templateRoot);

    cJSON* dataSet = FindDataSet(templateRoot, dataSetName);
    if (!dataSet) {
        return "";
    }

    std::vector<int> idxList = GetDataArrayIdxList(dataSet);

    std::vector<float> floatBuffer;
    floatBuffer.reserve(2048);

    for (size_t i = 0; i < idxList.size(); ++i) {
        int idx = idxList[i];

        std::map<int, PqdMeta>::const_iterator it = metaMap.find(idx);
        if (it == metaMap.end()) {
            floatBuffer.push_back(0.0f);
            continue;
        }

        AppendValueByMeta(floatBuffer, jsondata, it->second, isStat, statType);
    }

    return FloatBufferToBase64(floatBuffer);
}

/////////////////////////////////////////////////////////////////////////////////////发送函数
///////////////////////////////////////////////////////////////////////////////////////上送数据的json格式
// 单条 DataArray 数据
struct DataArrayItem {
    int DataAttr;
    time_t  DataTimeSec;
    time_t  DataTimeUSec;
    int DataTag;
    std::string Data;
};

// Msg 对象
struct MsgObj {
    int Cldid;
    int DataType;
    int DataAttr;
    int DsNameIdx;
    std::vector<DataArrayItem> DataArray;
};

// 整体
struct FullObj {
    std::string mac;
    int Mid;
    int Did;
    int Pri;
    int Type;
    MsgObj Msg;
};

// DataArrayItem -> cJSON
static cJSON* DataArrayItemToJson(const DataArrayItem& d)
{
    cJSON* j = cJSON_CreateObject();

    cJSON_AddNumberToObject(j, "dataAttr", d.DataAttr);
    cJSON_AddNumberToObject(j, "dataTimeSec", (double)d.DataTimeSec);
    cJSON_AddNumberToObject(j, "dataTimeUSec", (double)d.DataTimeUSec);
    cJSON_AddNumberToObject(j, "dataTag", d.DataTag);
    cJSON_AddStringToObject(j, "data", d.Data.c_str());

    return j;
}

// MsgObj -> cJSON
static cJSON* MsgObjToJson(const MsgObj& m)
{
    cJSON* j = cJSON_CreateObject();

    cJSON_AddNumberToObject(j, "clDid", m.Cldid);
    cJSON_AddNumberToObject(j, "dataType", m.DataType);
    cJSON_AddNumberToObject(j, "dataAttr", m.DataAttr);
    cJSON_AddNumberToObject(j, "dsNameIdx", m.DsNameIdx);

    // dataArray
    cJSON* arr = cJSON_CreateArray();

    for (size_t i = 0; i < m.DataArray.size(); ++i) {
        cJSON_AddItemToArray(
            arr,
            DataArrayItemToJson(m.DataArray[i]));
    }

    cJSON_AddItemToObject(j, "dataArray", arr);

    return j;
}

// FullObj -> cJSON
static cJSON* FullObjToJson(const FullObj& f)
{
    cJSON* j = cJSON_CreateObject();

    cJSON_AddStringToObject(j, "id", f.mac.c_str());

    cJSON_AddNumberToObject(j, "mid", f.Mid);
    cJSON_AddNumberToObject(j, "did", f.Did);
    cJSON_AddNumberToObject(j, "pri", f.Pri);
    cJSON_AddNumberToObject(j, "type", f.Type);

    cJSON_AddItemToObject(j, "msg",
        MsgObjToJson(f.Msg));

    return j;
}

std::string generate_json(
    const std::string mac,
    int Mid,
    int Did,
    int Pri,
    int Type,
    int Cldid,
    int DataType,
    int DataAttr,
    int DsNameIdx,
    const std::vector<DataArrayItem>& dataArray
)
{
    FullObj fobj;

    fobj.mac = mac;
    fobj.Mid = Mid;
    fobj.Did = Did;
    fobj.Pri = Pri;
    fobj.Type = Type;

    fobj.Msg.Cldid = Cldid;
    fobj.Msg.DataType = DataType;
    fobj.Msg.DataAttr = DataAttr;
    fobj.Msg.DsNameIdx = DsNameIdx;
    fobj.Msg.DataArray = dataArray;

    // 转 cJSON
    cJSON* root = FullObjToJson(fobj);

    // 输出 json 字符串
    char* jsonStr = cJSON_PrintUnformatted(root);

    std::string result;

    if (jsonStr != NULL) {
        result = jsonStr;
        free(jsonStr);
    }

    cJSON_Delete(root);

    return result;
}

//时间转换函数
time_t ConvertToTimestamp(const tagTime& time) {
    struct tm t = {};
    t.tm_year = time.DeviceYear - 1900;  // tm_year 从 1900 开始计
    t.tm_mon  = time.DeviceMonth - 1;    // tm_mon 从 0（1月）开始
    t.tm_mday = time.DeviceDay;
    t.tm_hour = time.DeviceHour;
    t.tm_min  = time.DeviceMinute;
    t.tm_sec  = time.DeviceSecond;

    // 返回时间戳（本地时间）
    return mktime(&t);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////实时数据封装发送
void enqueue_realtime_pq(const RealtagPqDate_float& realdata,
                         int nPTType,
                         unsigned char cid,
                         const std::string& mac,
                         const std::string& mpid,
                        int idx)
{
    // 先根据 devIdxMap 的配置决定编码分支：
    // 2: 基础数据  3: 谐波电压含有率  4: 谐波电流有效值  5: 间谐波电压含有率
    std::string base64;

    // 这里尝试用 mac 作为 key 获取 idx；如果项目里 devIdxMap 的 key 不是 mac，
    // 你可以把这里改成对应的设备 id（devid）。未命中则再尝试用规范化后的 mac。
    switch (idx) {
        case 2: // 基础数据（根据接线方式选择转换方法 数据全集解析）
            base64 = realdata.ConvertToBase64(nPTType);
            break;
        case 3: // 谐波电压含有率
            base64 = realdata.ConvertToBase64_RtHarmV(nPTType);
            break;
        case 4: // 谐波电流有效值（幅值）
            base64 = realdata.ConvertToBase64_RtHarmI();
            break;
        case 5: // 间谐波电压含有率
            base64 = realdata.ConvertToBase64_RtInHarmV();
            break;
        default:
            // 未知 idx，回退到基础数据
            base64 = realdata.ConvertToBase64(nPTType);
            break;
    } else {
        // 未配置 idx，回退到基础数据
        base64 = realdata.ConvertToBase64(nPTType);
    }
    //std::cout << base64 << std::endl;

    //lnk实时数据使用接口发送20250711
    time_t data_time = ConvertToTimestamp(realdata.time);

    std::vector<DataArrayItem> arr;
    arr.push_back({1,   //数据属性  -1-无， 0-“Rt”,1-“Max”,2-“Min”,3-“Avg”,4-“Cp95”
        data_time,     //数据转换出来的时间，数据时标，相对1970年的秒，无效填入“-1”
        0,             //数据时标，微秒钟，无效填入“-1”
        0,              //数据标识，1-标识数据异常
        base64});
    std::string js = generate_json(
        mac,            //设备唯一标识，规范化后的MAC地址，如“001122334455”，不带分隔符，字母大写
        -1,                 //需应答的报文订阅者收到后需以此ID应答，无需应答填入“-1”
        1,                  //设备唯一标识Ldid，填入0代表Ndid,后续根据商议决定填id还是数字
        1,                  //报文处理的优先级：1 I类紧急请求/响应 2 II类紧急请求/响应 3 普通请求/响应 4 广播报文
        0x1302,               //设备数据主动上送的数据类型
        cid,                //逻辑子设备ID，0-逻辑设备本身，无填-1
        0x04,               //数据类型固定为电能质量数据
        1,                      //数据属性：无“0”、实时“1”、统计“2”等
        idx,                      //数据集序号（以数据集方式上送），无填-1
        arr                     //数据数组
    );
    //std::cout << js << std::en
    Ckafka_data_t data;
    data.monitor_id = 1;    //上送的实时数据没有测点序号，统一填1
    data.strTopic = TOPIC_RTDATA;   //实时topic
    data.strText = js;
    data.mp_id = mpid;    //监测点id
    
    kafka_data_list_mutex.lock(); //加锁
	kafka_data_list.append(data); //添加 kafka发送链表
	kafka_data_list_mutex.unlock(); //解锁
}

////////////////////////////////////////////////////////////////////////////////统计数据打包发送

// 封装：组装统计数据并入队发送
void enqueue_stat_pq(const std::string& max_base64Str,
                     const std::string& min_base64Str,
                     const std::string& avg_base64Str,
                     const std::string& cp95_base64Str,
                     time_t data_time,
                     const std::string& mac,
                     short cid,
                     const std::string& mpid)
{
    std::vector<DataArrayItem> arr;
    arr.push_back({1,   //数据属性  -1-无， 0-“Rt”,1-“Max”,2-“Min”,3-“Avg”，4-“Cp95”
        data_time,     //数据转换出来的时间，数据时标，相对1970年的秒，无效填入“-1”
        0,             //数据时标，微秒钟，无效填入“-1”
        0,              //数据标识，1-标识数据异常
        max_base64Str});
    arr.push_back({2, data_time, 0, 0, min_base64Str});
    arr.push_back({3, data_time, 0, 0, avg_base64Str});
    arr.push_back({4, data_time, 0, 0, cp95_base64Str});

    std::string js = generate_json(
        normalize_mac(mac),
        -1,                 //需应答的报文订阅者收到后需以此ID应答，无需应答填入“-1”
        1,                  //设备唯一标识Ldid，填入0代表Ndid,后续根据商议决定填id还是数字
        1,                  //报文处理的优先级：1 I类紧急请求/响应 2 II类紧急请求/响应 3 普通请求/响应 4 广播报文
        0x1302,               //设备数据主动上送的数据类型
        cid,                //逻辑子设备ID，0-逻辑设备本身，无填-1（原：avg_data.name）
        0x04,               //数据类型固定为电能质量
        2,                      //数据属性：无“0”、实时“1”、统计“2”等
        1,                      //数据集序号（以数据集方式上送），无填-1
        arr                     //数据数组
    );

    //std::cout << js << std::endl;

    Ckafka_data_t data;
    data.monitor_no = cid;    //监测点序号（原：avg_data.name）
    data.strTopic = TOPIC_STAT;//统计topic
    data.strText = js;
    data.mp_id = mpid;    //监测点id

    kafka_data_list_mutex.lock(); //加锁
	kafka_data_list.append(data); //添加 kafka发送链表
	kafka_data_list_mutex.unlock(); //解锁

    std::cout << "Successfully assembled tagPqData for line: "
        << cid << std::endl;
}

////////////////////////////////////////////////////////////////////////////////////
//以下仅估计开发时间，不包括代码编译调试和测试
/*后续接入云平台，云平台需要根据61850协议进行台账下发：需要对比云和微服务的台账差异，看是否能统一，各取所需  一天
实时数据请求需要添加参数处理，idx区分数据集 半天
补招逻辑有差异，61850是全补招，云是事件和稳态分开，补招下发按照61850的来  徐扬添加
暂态上送逻辑基本一致，对比接口上送数据即可 半天
云需要添加映射文件接口给61850使用 徐扬添加
台账变更逻辑一样，对比台账看是否能统一 一天
请求响应、装置连接状态、前置心跳、文件上传、文件下载、文件传输、读取文件目录、文件删除、装置重启指令的处理逻辑基本一致需要对比交互json，下发的要根据61850需求来，部分肯定需要修改 五天
日志上传方案基本一致，代码基本一致，但是上送日志内容可能不一样，可以不修改
mq主题云前置有cloudtopic用于装置控制，61850是filetopic，按照61850的来 徐扬添加针对61850的装置控制逻辑
进程控制要按照61850的来，徐扬添加
上传下载接口基本一致
要添加61850到云的指标映射关系 二天
要添加动态云模板的存储（文件/内存） 和解析代码 五天+
要添加61850数据到云数据的转换、复用代码但是代码是写死的一种模板，可以先完成，后续改动态，复用代码编写数据上送和编译测试 5天+
当前基础的转换框架已搭建，需要基于61850当前的运行控制框架添加模板控制，数据转换控制，数据上送控制等，预计5天+
*/







