#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include "deviceLayer.h"
#include "../common.h"
#include "main.h"
#include "../adapter/pe_adapter.h"
#include <math.h>
#include "../proto_forward.h"
#include "automatic.h"
#include "pub_fun.h"
#include <stdio.h>
#include "lc_system.h"
#include "power_manage.h"
ems_base_variant_t lc_base_variant[] =
    {
        // (设置动作)
        //使能BMS告警
        {DEV_NO_LC, EN_BMS_ALARM, "Enable BMS alarms", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //使能DOD防护
        {DEV_NO_LC, EN_PROTECT_DOD, "Enable DOD protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //使能BMS功率限制
        {DEV_NO_LC, BMS_POWER_LIMIT, "Enable BMS power limitation", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //自动PCS关机
        {DEV_NO_LC, PCS_AUTO_TURN, "PCS auto-shutdown", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //自动PCS关机时间
        {DEV_NO_LC, PCS_AUTO_TURN_OFF_TIME, "PCS auto-shutdown time(s)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //开关机
        {DEV_NO_LC, ON_OFF_STATE, "Power on/off", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:Off;1:On;"},
        //设置有功功率
        {DEV_NO_LC, SET_ACT_POWER, "Set active power(kW)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 0, ""},
        //设置无功功率
        {DEV_NO_LC, SET_REACTPOWER, "Set reactive power(kvar)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 0, ""},
        //设置并离网模式
        {DEV_NO_LC, SET_CONNECT, "Set on/off-grid mode", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "both", 0, "0:Off-grid;1:On-grid;"},
        //清除保护
        {DEV_NO_LC, CLEAR_ALARM, "Clear all protections", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, ""},
        //使能动环保护
        {DEV_NO_LC, EN_IO_PROTECT, "Enable dynamic environment protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //最大充电SOC
        {DEV_NO_LC, EMS_SOCMAX, "Maximum charging SOC(%)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 1, ""},
        //最小放电SOC
        {DEV_NO_LC, EMS_SOCMIN, "Minimum discharge SOC(%)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 1, ""},
        //限制功率
        {DEV_NO_LC, POWER_LIMIT, "Limited power", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 1, ""},
        //脱扣
        {DEV_NO_LC, TRIP, "Trip", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, ""},
        //清除手动保护
        {DEV_NO_LC, LC_CLR_MANUAL_PROTECT, "Clear manual protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, ""},
        //BMS上下高压
        {DEV_NO_LC, BMS_UPPER, "Set BMS HV_Connect", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:HV connect;1:HV disconnect;"},
        //使能无功-功率因数补偿
        {DEV_NO_LC, EN_RP_COMP,       "enable repower compensate",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,    "off",1, "0:Disabled;1:Enabled;"},     
        // 设置功率因数
        {DEV_NO_LC, SET_POWER_FACTOR,        "Set power factor",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA,  "off",1, ""},

        //制热启动温度
        {DEV_NO_LC, WORK_START_HOT_TEMP, "Heating start-up temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //制热停止温度
        {DEV_NO_LC, WORK_END_HOT_TEMP, "Heating stop temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //制冷启动温度
        {DEV_NO_LC, WORK_START_COOL_TEMP, "Cooling start-up temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //制冷停止温度
        {DEV_NO_LC, WORK_END_COOL_TEMP, "Cooling stop temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //制热目标温度
        {DEV_NO_LC, WORK_DIST_HOT_TEMP, "Heating target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //制冷目标温度
        {DEV_NO_LC, WORK_DIST_COOL_TEMP, "Cooling target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //输出制冷目标温度
        {DEV_NO_LC, TMS_CTRL_DIST_TEMP_COLD, "Output cooling target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //输出制热目标温度
        {DEV_NO_LC, TMS_CTRL_DIST_TEMP_HOT, "Output heating target temperature(℃)", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, ""},
        //液冷机控制
        {DEV_NO_LC, TMS_CTRL_STATE, "Liquid cooling control", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Standby;1:Cooling;2:Heating;3:Pump circulation;"},
        //启动自循环温差
        {DEV_NO_EMS, SELF_LOOP_DIFF, "Start self circulating TEMP difference(℃)",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", 1, ""},
        //空调启停控制
        {DEV_NO_LC, AIR_COND_STARTSTOP_CTRL, "AC control",O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Off;1:On;"},
        //使能空调控制
        {DEV_NO_LC, ENABLE_AIR_COND, "Enable AC control", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //使能液冷机管理
        {DEV_NO_LC, ENABLE_AUTO_COOL, "Enable liquid cooling MGT", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //使能间隙自循环
        {DEV_NO_LC, EN_SELF_LOOP_DIFF,         "Enable gap self circulation",    O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", 1, "0:Disabled;1:Enabled;"},
        //单体过压保护阈值(V)
        {DEV_NO_LC, SINGLE_MAX_VOLTAGE, "Single cell Over-V protect threshold(V)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 1, ""},
        //单体欠压保护阈值(V)
        {DEV_NO_LC, SINGLE_MIN_VOLTAGE, "Single cell Under-V protect threshold(V)", O_WRONLY | O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 1, ""},
        //使能单体电压保护
        {DEV_NO_LC, EN_CELL_VOLT_PROTECT, "Enable single cell voltage protection", O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 1, "0:Disabled;1:Enabled;"},
        //单体过压保护偏差
        {DEV_NO_LC, SINGLE_MAX_VOLTAGE_ERR,   "Single cell Over-V protect difference(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", 1, ""},
        //单体欠压保护偏差
        {DEV_NO_LC, SINGLE_MIN_VOLTAGE_ERR,   "Single cell Under-V protect difference(V)",      O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,    PROPERTY_REALDATA, "off", 1, ""},
        //禁止放电SOC偏差
        {DEV_NO_LC, EMS_SOCMINERR,            "SOC Prohibited discharging difference(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", 1, ""},
        //禁止充电SOC偏差
        {DEV_NO_LC, EMS_SOCMAXERR,            "SOC Prohibited charging difference(%)",   O_WRONLY | O_RDONLY, EMS_POINT_FLOAT,  PROPERTY_REALDATA, "off", 1, ""},
        //使能风机跟随功率
        {DEV_NO_LC, EN_DRAUG_FLOW_POWER   , "Enable fan to follow power",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", 1, "0:Disabled;1:Enabled;"},
        //风机跟随功率门限
        {DEV_NO_LC, EN_DRAUG_FLOW_POWER_T , "Fan following power threshold(kW)",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,       "off", 1, ""},
        //使能风机跟随温度
        {DEV_NO_LC, EN_DRAUG_FLOW_TEM     , "Enable fan to follow TEMP",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", 1, "0:Disabled;1:Enabled;"},
        //风机跟随温度门限
        {DEV_NO_LC, EN_DRAUG_FLOW_TEM_T   , "Fan following TEMP threshold(℃)",  O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", 1, ""},
        //跟随时间死区
        {DEV_NO_LC, DRAUG_DEAE_TIME       , "Follow time deadband(s)",      O_WRONLY | O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA,      "off", 1, ""},
         //风机
        {DEV_NO_LC, FAN,                   "Fan",      O_WRONLY | O_RDONLY, EMS_POINT_INT,    PROPERTY_REALDATA, "off", 0, "0:Off;1:On;"},
        
        // 只读点位
        //系统运行状态
        {DEV_NO_LC, SYSTEM_STATUS, "System operating status", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:Normal;1:Abnormal;"},
        //系统运行状态字
        {DEV_NO_LC, SYSTEM_STATUS_W, "System operation status word", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, ""},
        //期望有功功率
        {DEV_NO_LC, EXPECT_ACT_POWER, "Expected active power(kW)", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "off", 0, ""},
        //禁充保护
        {DEV_NO_LC, PROHIBITE_CHARGE, "Prohibited charging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Unprotected;1:Protected;"},
        //禁放保护
        {DEV_NO_LC, PROHIBITE_DISCHARGE, "Discharging prohibited protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Unprotected;1:Protected;"},
        //DOD保护
        {DEV_NO_LC, DOD_LIMITED, "DOD protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Unprotected;1:Protected;"},
        //DOD禁充保护
        {DEV_NO_LC, DOD_LIMITED_CH, "DOD prohibited charging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Unprotected;1:Protected;"},
        //DOD禁放保护
        {DEV_NO_LC, DOD_LIMITED_DC, "DOD prohibited discharging protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Unprotected;1:Protected;"},
        //直流总压异常
        {DEV_NO_LC, DC_TOTAL_VOL_LOW, "Abnormal total DC voltage", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Normal;1:Abnormal;"},
        {DEV_NO_EMS, SINGLE_CELL_VOL_THRESHOLD_ALARM, "Single cell voltage threshold alarm", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Normal;1:Abnormal;"},
        //EMS限功率运行
        // {DEV_NO_LC, POWER_LIMITED, "EMS running in limited power", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:Unrestricted;1:Restricted;"},
        //EMS逆流运行
        // {DEV_NO_LC, POWER_REFLUX, "EMS running in backflow", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:No backflow;1:Backflow occurred;"},
        //动环保护
        {DEV_NO_LC, IO_PROTECT, "Dynamic environment protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Unprotected;1:Protected;"},
        //BMS最大可充功率
        {DEV_NO_LC, MAX_CHARGE_POWER, "BMS Maximum Charging Power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", 0, ""},
        //BMS最大可放功率
        {DEV_NO_LC, MAX_DISCHA_POWER, "BMS Maximum Discharging Power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", 0, ""},
        //PCS开关机状态
        {DEV_NO_LC, GET_ON_OFF, "Get on off", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:Off;1:On;"},
        //PCS并离网状态
        {DEV_NO_LC, GET_CONNECT, "Get connect", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, "0:Off-grid;1:On-grid;"},
        //PCS当前有功功率
        {DEV_NO_LC, GET_ACT_POWER, "Get act power", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", 0, ""},
        //PCS当前无功功率
        {DEV_NO_LC, GET_REACTPOWER, "Get RePower", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", 0, ""},
        //当前SOC
        {DEV_NO_LC, GET_SOC, "Get soc", O_RDONLY, EMS_POINT_FLOAT, PROPERTY_REALDATA, "both", 0, ""},
        //手动保护
        {DEV_NO_LC, LC_MANUAL_PROTECT, "Manual protection", O_RDONLY, EMS_POINT_INT, PROPERTY_REALDATA, "off", 0, ""},
        //自定义提示1
        {DEV_NO_LC, USER_ALARM1, "Custom Tip 1", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, ""},
        //自定义提示2
        {DEV_NO_LC, USER_ALARM2, "Custom Tip 2", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, ""},
        //自定义提示3
        {DEV_NO_LC, USER_ALARM3, "Custom Tip 3", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, ""},
        //本机消防
        {DEV_NO_LC, FIRE, "Local fire protection", O_RDONLY, EMS_POINT_INT, PROPERTY_ALARM, "off", 0, "0:Normal;1:Abnormal;"},
        //自定义停机1
        {DEV_NO_EMS, USER_STOP1 ,        "Custom Shutdown 1",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", 0,"0:Normal;1:Abnormal;"},
        //自定义停机2
        {DEV_NO_EMS, USER_STOP2 ,        "Custom Shutdown 2",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", 0,"0:Normal;1:Abnormal;"},
        //自定义停机3
        {DEV_NO_EMS, USER_STOP3 ,        "Custom Shutdown 3",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", 0,"0:Normal;1:Abnormal;"},
        //自定义告警
        {DEV_NO_EMS, USER_ALARM ,        "Custom alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", 0,"0:Normal;1:Abnormal;"},
        //自定义提示告警
        {DEV_NO_EMS, USER_NOTICE_ALARM , "Custom prompt alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", 0,"0:Normal;1:Abnormal;"},
        //自定义重要告警
        {DEV_NO_EMS, USER_VITAL_ALARM ,  "Custom important alarm",    O_RDONLY,  EMS_POINT_INT,   PROPERTY_ALARM, "off", 0,"0:Normal;1:Abnormal;"},
};
const int lc_base_variant_num = sizeof(lc_base_variant) / sizeof(lc_base_variant[0]);
static char *creat_lc_template(void)
{
    int size = 1024;
    char *ret = NULL;
    char *proto_arr[] = {"opcua", "lc", NULL};
    template_info_t info = {.protocol = proto_arr, .vendor="Lnxall", .model = "LC", .version = "", .type = "EMS"};
    ems_base_variant_t **p = calloc(size, sizeof(ems_base_variant_t *));
    int cur = 0;
    for (int i = 0; i < sizeof(lc_base_variant) / sizeof(lc_base_variant[0]); i++)
    {
        if (cur < size)
        {
            p[cur] = calloc(1, sizeof(ems_base_variant_t));
            *p[cur] = lc_base_variant[i];
            p[cur]->variant = strdup(lc_base_variant[i].variant); // 为了后面统一释放
            p[cur]->name = strdup(lc_base_variant[i].name);
            cur++;
        }
    }

    ret = create_ems_template(&info, p, cur);
    //
    for (int i = 0; i < cur; i++)
    {
        free(p[i]->variant);
        free(p[i]->name);
        free(p[i]);
    }
    free(p);

    return ret;
}

int load_lc_device_cfg(proto_forward_t *proto)
{
    int ret = 0;
    char *temp = creat_lc_template();
    if (temp == NULL)
    {
        ems_syslog(LOG_ERR, "creat lc template error");
        return -1;
    }
    char *lc_template = read_file_data(TEMPLATE_DIR "/lc_template.json");
    if (lc_template == NULL)
    {
        ems_syslog(LOG_ERR, "read lc template error");
        lc_template = strdup("NULL");
    }
    if (strcmp(temp, lc_template) != 0)
    {
        write_file_data(TEMPLATE_DIR "/lc_template.json", temp, strlen(temp));
    }
    char *lc_dev_cfg = "{\"dev_class\":[{\"type\":\"EMS\",\"devs\":[{\"no\":\"LC\",\"name\":\"LC\",\"channel\":\"LC\",\"protocol\":\"lc\",\"template\":\"lc_template.json\"}]}]}";
    ret = load_device_cfg(proto, lc_dev_cfg, 0);
    lc_cfg_to_nod_sync(LC_CFG_FILE); // 必须在LC点位生成完成后才能够调用
    free(temp);
    free(lc_template);
    return ret;
}

int lc_nod_to_cfg_sync(const char *cfg_file)
{
    char nod[TAG_NAME_LEN + DEV_NO_LEN] = {0};
    cJSON *root = cJSON_CreateObject();
    cJSON *data = NULL;
    double double_data = 0;
    int int_data = 0;
    if (root == NULL)
    {
        ems_syslog(LOG_ERR, "lc nod to cfg sync cJSON_CreateObject error");
        return -1;
    }
    for (int i = 0; i < sizeof(lc_base_variant) / sizeof(lc_base_variant[0]); i++)
    {
        if (lc_base_variant[i].is_cfg == 0)
        {
            continue;
        }

        snprintf(nod, sizeof(nod), "%s.%s", lc_base_variant[i].dev, lc_base_variant[i].variant);
        if (lc_base_variant[i].data_type == EMS_POINT_INT) // 整形
        {
            if (0 != collector_read_one_int_data(nod, &int_data))
            {
                continue;
            }
            data = cJSON_CreateNumber(int_data);
        }
        else
        {
            if (0 != collector_read_one_float_data(nod, &double_data))
            {
                continue;
            }
            data = cJSON_CreateNumber(double_data);
        }
        cJSON_AddItemToObject(root, lc_base_variant[i].variant, data);
    }

    char *json_str = cJSON_Print(root);
    int_data = -1;
    if (json_str != NULL)
    {
        write_file_data(cfg_file, json_str, strlen(json_str));
        cJSON_free(json_str);
        int_data = 0;
    }
    cJSON_Delete(root);
    return int_data;
}

int lc_cfg_to_nod_sync(const char *cfg_file)
{
    char nod[TAG_NAME_LEN + DEV_NO_LEN] = {0};
    cJSON *root = NULL;
    cJSON *data = NULL;
    char *cfg = read_file_data(cfg_file);
    if (cfg == NULL)
    {
        ems_syslog(LOG_ERR, "read cfg %s error", cfg_file);
        return -1;
    }

    root = cJSON_Parse(cfg);
    free(cfg);
    if (root == NULL)
    {
        ems_syslog(LOG_ERR, "cJSON_Parse error:%s", cfg_file);
        return -1;
    }
    for (int i = 0; i < sizeof(lc_base_variant) / sizeof(lc_base_variant[0]); i++)
    {
        if (lc_base_variant[i].is_cfg == 0)
        {
            continue;
        }

        data = cJSON_GetObjectItemCaseSensitive(root, lc_base_variant[i].variant);
        if (data == NULL)
        {
            continue;
        }

        snprintf(nod, sizeof(nod), "%s.%s", lc_base_variant[i].dev, lc_base_variant[i].variant);
        if (lc_base_variant[i].data_type == EMS_POINT_INT) // 整形
        {
            if (0 == collector_write_one_int_data(nod, data->valueint))
            {
                continue;
            }
        }
        else
        {
            if (0 == collector_write_one_float_data(nod, data->valuedouble))
            {
                continue;
            }
        }
        ems_syslog(LOG_ERR, "write nod error:%s", nod);
    }
    cJSON_Delete(root);
    return 0;
}

/*******************************************一些回调*********************************************************8*/
const char* lc_contrl_tab[] =
    {
        DEV_NO_LC "." ON_OFF_STATE,
        DEV_NO_LC "." CLEAR_ALARM,
        DEV_NO_LC "." SET_CONNECT,
        DEV_NO_LC "." LC_CLR_MANUAL_PROTECT,
        DEV_NO_LC "." SET_ACT_POWER,
        DEV_NO_LC "." BMS_UPPER,
        DEV_NO_LC "." EN_RP_COMP,
        DEV_NO_LC "." SET_POWER_FACTOR,
        DEV_NO_LC "." PCS_FAULT_RESET,
};

const char *dod_protect[] =
    {
        DEV_NO_BMS "." CURRENT_SOC,
};

// 处理欠压故障
const char *lc_stop_discharge_tab[] =
    {
        DEV_NO_BMS "." RACK_MIN_VOLT,
        //我是分界线，上面是特殊处理，加的时候看看回调函数逻辑，这儿有个坑
        DEV_NO_BMS "." CELL_UNDER_VOL2,
        DEV_NO_BMS "." CELL_UNDER_VOL3,
        DEV_NO_BMS "." RACK_UNDER_VOL2,
        DEV_NO_BMS "." RACK_UNDER_VOL3,
        DEV_NO_LC "." DOD_LIMITED_DC,
        
};

// 处理过压故障
const char *lc_stop_charge_tab_mul[] =
    {
        DEV_NO_BMS "." RACK_MAX_VOLT,
        //我是分界线，上面是特殊处理，加的时候看看回调函数逻辑，这儿有个坑
        DEV_NO_BMS "." CELL_OVER_VOL2,
        DEV_NO_BMS "." CELL_OVER_VOL3,
        DEV_NO_BMS "." RACK_OVER_VOL2,
        DEV_NO_BMS "." RACK_OVER_VOL3,
        DEV_NO_LC "." DOD_LIMITED_CH,
};
// 系统异常
const char *lc_stop_cab_state_tab_mul[] =
    {
        DEV_NO_BMS "." CELL_OVER_VOL3,
        DEV_NO_BMS "." RACK_OVER_VOL3,
        DEV_NO_BMS "." CELL_UNDER_VOL3,
        DEV_NO_BMS "." RACK_UNDER_VOL3,
        DEV_NO_PCS "." PCS_FAULT,
        DEV_NO_LC "." IO_PROTECT,
        EMS_CONNECT_STATE,
        USER_STOP1,
        USER_STOP2,
        USER_STOP3,
};

//消防报警
const char* lc_stop_fire_tab[] = {
    DEV_NO_LC "." FIRE,
};

// 系统异常反逻辑(1为正常，0为异常的点位)
const char *lc_stop_cab_state_tab_mul_not[] =
    {
        DEV_NO_BMS "." STATE_ONLINE,
        DEV_NO_PCS "." STATE_ONLINE,
};

static void lc_contrl_cb(char *nod, tag_value *data_value);
static void lc_dod_protect(char *nod, tag_value *data_value);
static void lc_stop_cab_state_tab_mul_cb(char *nod, tag_value *data_value);
static void lc_stop_discharge_tab_mul_cb(char *nod, tag_value *data_value);
static void lc_stop_charge_tab_mul_cb(char *nod, tag_value *data_value);
static void lc_cfg_nod_change_cb(char *nod, tag_value *data_value);
static void lc_stop_fire_cb(char *nod, tag_value *data_value);
static int lc_regester_cfg_nod_change_cb(pcs_ctrl_var_t *var, void (*cb)(char *nod, tag_value *data_value));
int lc_clean_prohibite_chag_and_dischag(int cur_rack_sum);

int variant_cb_register_mul(pcs_ctrl_var_t *var)
{
    collector_variant_monitor_add(var, lc_contrl_tab, ARRAY_SIZE(lc_contrl_tab), lc_contrl_cb);
    lc_regester_cfg_nod_change_cb(var, lc_cfg_nod_change_cb);
    collector_flush_variant_monitor_add(var, dod_protect, ARRAY_SIZE(dod_protect), lc_dod_protect);
    collector_variant_monitor_add(var, lc_stop_discharge_tab, ARRAY_SIZE(lc_stop_discharge_tab), lc_stop_discharge_tab_mul_cb);
    collector_variant_monitor_add(var, lc_stop_charge_tab_mul, ARRAY_SIZE(lc_stop_charge_tab_mul), lc_stop_charge_tab_mul_cb);
    collector_variant_monitor_add(var, lc_stop_cab_state_tab_mul, ARRAY_SIZE(lc_stop_cab_state_tab_mul), lc_stop_cab_state_tab_mul_cb);
    collector_variant_monitor_add(var, lc_stop_cab_state_tab_mul_not, ARRAY_SIZE(lc_stop_cab_state_tab_mul_not), lc_stop_cab_state_tab_mul_cb);
    collector_variant_monitor_add(var, lc_stop_fire_tab, ARRAY_SIZE(lc_stop_fire_tab), lc_stop_fire_cb);
    automatic_init(CONFIG_PATH "/lc/" AUTOMATIC_CONFIG);

    return 0;
}

static void lc_contrl_cb(char *nod, tag_value *data_value)
{
    if ((strcmp(nod, DEV_NO_LC "." CLEAR_ALARM) == 0) && (data_value->type == 0) && (data_value->value.to_int != 0))
    {
        dev_set_dev_tag_int(DEV_NO_LC, PROHIBITE_CHARGE, 0);
        dev_set_dev_tag_int(DEV_NO_LC, PROHIBITE_DISCHARGE, 0);
        dev_set_dev_tag_int(DEV_NO_LC, CLEAR_ALARM, 0);
    }
    else if ((strcmp(nod, DEV_NO_LC "." ON_OFF_STATE) == 0) && (data_value->type == 0))
    {
        if (data_value->value.to_int == 0)
        {
            dev_set_dev_tag_int(DEV_NO_LC, SET_ACT_POWER, 0);
            pe_set_onoff(DEV_NO_PCS, 0);
        }
        else
        {
            if ((dev_get_dev_tag_int(DEV_NO_LC, PCS_AUTO_TURN) == 0))
            {
                pe_set_onoff(DEV_NO_PCS, 1);
            }
        }
    }
    else if ((strcmp(nod, DEV_NO_LC "." SET_CONNECT) == 0) && (data_value->type == 0))
    {
        pe_set_connect(DEV_NO_PCS, data_value->value.to_int);
    }
    else if ((strcmp(nod, DEV_NO_LC "." LC_CLR_MANUAL_PROTECT) == 0) && (data_value->type == 0))
    {
        dev_set_dev_tag_int(DEV_NO_LC, LC_CLR_MANUAL_PROTECT, 0);
        dev_set_dev_tag_int(DEV_NO_LC, LC_MANUAL_PROTECT, 0);
    }
    else if (strcmp(nod, DEV_NO_LC "." SET_ACT_POWER) == 0)
    {
        sem_post_power_update();
    }
    else if (strcmp(nod, DEV_NO_EMS "." BMS_UPPER) == 0)
    {
        set_total_bms_connect(data_value->value.to_int);
    }
    else if (strcmp(nod, DEV_NO_EMS "." EN_RP_COMP ) == 0) // PCS 无功功率补偿,设置功率因数
    {
        set_total_pcs_repower_comp(data_value->value.to_int);
    }
    else if (strcmp(nod, DEV_NO_EMS "." SET_POWER_FACTOR ) == 0) // PCS 无功功率补偿,设置功率因数
    {
        set_total_pcs_power_factor(data_value->value.to_float);
    }
    else if (strcmp(nod, DEV_NO_LC "." PCS_FAULT_RESET ) == 0) // PCS故障复位
    {
        set_total_pcs_fault_reset(data_value->value.to_int);
    }
}

static void lc_cfg_nod_change_cb(char *nod, tag_value *data_value) // 配置文件中的点位被改变的回调
{
    lc_nod_to_cfg_sync(LC_CFG_FILE);
}

static int lc_regester_cfg_nod_change_cb(pcs_ctrl_var_t *var, void (*cb)(char *nod, tag_value *data_value))
{
    char nod[TAG_NAME_LEN + DEV_NO_LEN] = {0};
    for (int i = 0; i < sizeof(lc_base_variant) / sizeof(lc_base_variant[0]); i++)
    {
        if (lc_base_variant[i].is_cfg != 0)
        {
            snprintf(nod, sizeof(nod), "%s.%s", lc_base_variant[i].dev, lc_base_variant[i].variant);
            if (0 != collector_variant_monitor_add_one(var, nod, cb))
            {
                ems_syslog(LOG_ERR, "collector_variant_monitor_add_one error:%s", nod);
            }
        }
    }
    return 0;
}

static void lc_dod_protect(char *nod, tag_value *data_value)
{
    double value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
    int en_dod = dev_get_dev_tag_int(DEV_NO_LC, EN_PROTECT_DOD);
    if (en_dod)
    {
        double soc_max = dev_get_dev_tag_float(DEV_NO_LC, EMS_SOCMAX);
        double soc_min = dev_get_dev_tag_float(DEV_NO_LC, EMS_SOCMIN);
        double soc_max_err = dev_get_dev_tag_float(DEV_NO_LC, EMS_SOCMAXERR);
        double soc_min_err = dev_get_dev_tag_float(DEV_NO_LC, EMS_SOCMINERR);
        if (value <= soc_min)
        {
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_CH, 0);
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_DC, 1);
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED, 1);
        }
        else if (value >= soc_max)
        {
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_DC, 0);
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_CH, 1);
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED, 1);
        }
        else if ((value > (soc_min + soc_min_err)) && (value < (soc_max - soc_max_err)))
        {
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_DC, 0);
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_CH, 0);
            dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED, 0);
        }
    }
    else
    {
        dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_DC, 0);
        dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED_CH, 0);
        dev_set_dev_tag_int(DEV_NO_LC, DOD_LIMITED, 0);
    }
    ems_syslog(LOG_NOTICE, "%s -> lc dod protect, value:%f", nod, value); 
}

static void lc_stop_discharge_tab_mul_cb(char *nod, tag_value *data_value)
{
    static uint32_t flag = 0x00;
    //
    if ((strstr(nod, RACK_MIN_VOLT) != NULL) && (dev_get_dev_tag_int(DEV_NO_LC, EN_CELL_VOLT_PROTECT) != 0)) // 我是特殊处理的坑
    {
        double dv = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
        double min_dv = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MIN_VOLTAGE) * 1000.0;
        double min_err = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MIN_VOLTAGE_ERR) * 1000.0;
        double max_dv = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MAX_VOLTAGE) * 1000.0;
        double max_err = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MAX_VOLTAGE_ERR) * 1000.0;
        if (dv <= min_dv)
        {
            SET_AMASK_BIT(flag, 0);
            dev_set_dev_tag_int(DEV_NO_LC, SINGLE_CELL_VOL_THRESHOLD_ALARM, 1);
        }
        else if (dv > (min_dv + min_err))
        {
            CLR_AMASK_BIT(flag, 0);
            if (dv < (max_dv - max_err))
            {
                dev_set_dev_tag_int(DEV_NO_LC, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
            }
        }
        ems_syslog(LOG_WARNING, "%s -> lc stop discharge, value:%f, min:%f, err:%f", nod, dv, min_dv, min_err);
        goto lc_stop_discharge_tab_mul_cb_set_value;
    }
    //
    if (strstr(nod, DEV_NO_BMS) == nod)
    {
        if (0 == dev_get_dev_tag_int(DEV_NO_LC, EN_BMS_ALARM)) // 没有使能BMS告警
        {
            ems_syslog(LOG_WARNING, "ignore, %s", nod);
            return;
        }
    }
    //
    int value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
    for (int i = 1; i < (sizeof(lc_stop_discharge_tab) / sizeof(lc_stop_discharge_tab[0])); i++)
    {
        if (strcmp(nod, lc_stop_discharge_tab[i]) == 0)
        {
            if (value != 0)
            {
                SET_AMASK_BIT(flag, i);
            }
            else
            {
                CLR_AMASK_BIT(flag, i);
            }
        }
    }
    //
lc_stop_discharge_tab_mul_cb_set_value:
    ems_syslog(LOG_WARNING, "%s -> lc stop discharge, value:[int:%ld, float:%f], flag:0x%x", nod, data_value->value.to_int, data_value->value.to_float, flag);
    if (flag != 0)
    {
        if (dev_get_dev_tag_int(DEV_NO_LC, PROHIBITE_DISCHARGE) == 0)
        {
            dev_set_dev_tag_int(DEV_NO_LC, PROHIBITE_DISCHARGE, 1);
        }
    }
    else
    {
        if (dev_get_dev_tag_int(DEV_NO_LC, PROHIBITE_DISCHARGE) != 0)
        {
            dev_set_dev_tag_int(DEV_NO_LC, PROHIBITE_DISCHARGE, 0);
        }
    }
}

static void lc_stop_charge_tab_mul_cb(char *nod, tag_value *data_value)
{
    static uint32_t flag = 0x00;
    //
    if ((strstr(nod, RACK_MAX_VOLT) != NULL) && (dev_get_dev_tag_int(DEV_NO_LC, EN_CELL_VOLT_PROTECT) != 0)) // 我是特殊处理的坑
    {
        double dv = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
        double max_dv = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MAX_VOLTAGE) * 1000.0;
        double max_err = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MAX_VOLTAGE_ERR) * 1000.0;
        double min_dv = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MIN_VOLTAGE) * 1000.0;
        double min_err = dev_get_dev_tag_float(DEV_NO_LC, SINGLE_MIN_VOLTAGE_ERR) * 1000.0;
        if (dv >= max_dv)
        {
            SET_AMASK_BIT(flag, 0);
            dev_set_dev_tag_int(DEV_NO_LC, SINGLE_CELL_VOL_THRESHOLD_ALARM, 1);
        }
        else if (dv < (max_dv - max_err))
        {
            CLR_AMASK_BIT(flag, 0);
            if (dv > (min_dv + min_err))
            {
                dev_set_dev_tag_int(DEV_NO_LC, SINGLE_CELL_VOL_THRESHOLD_ALARM, 0);
            }
        }
        ems_syslog(LOG_WARNING, "%s -> lc stop discharge, value:%f, max:%f, err:%f", nod, dv, max_dv, max_err);
        goto lc_stop_charge_tab_mul_cb_set_value;
    }
    //
    if (strstr(nod, DEV_NO_BMS) == nod)
    {
        if (0 == dev_get_dev_tag_int(DEV_NO_LC, EN_BMS_ALARM)) // 没有使能BMS告警
        {
            ems_syslog(LOG_WARNING, "ignore, %s", nod);
            return;
        }
    }
    //
    int value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
    for (int i = 1; i < (sizeof(lc_stop_charge_tab_mul) / sizeof(lc_stop_charge_tab_mul[0])); i++)
    {
        if (strcmp(nod, lc_stop_charge_tab_mul[i]) == 0)
        {
            if (value != 0)
            {
                SET_AMASK_BIT(flag, i);
            }
            else
            {
                CLR_AMASK_BIT(flag, i);
            }
        }
    }
    //
lc_stop_charge_tab_mul_cb_set_value:
    ems_syslog(LOG_WARNING, "%s -> lc stop charge, value:[int:%ld, float:%f], flag:0x%x", nod, data_value->value.to_int, data_value->value.to_float, flag);
    if (flag != 0)
    {
        if (dev_get_dev_tag_int(DEV_NO_LC, PROHIBITE_CHARGE) == 0)
        {
            dev_set_dev_tag_int(DEV_NO_LC, PROHIBITE_CHARGE, 1);
        }
    }
    else
    {
        if (dev_get_dev_tag_int(DEV_NO_LC, PROHIBITE_CHARGE) != 0)
        {
            dev_set_dev_tag_int(DEV_NO_LC, PROHIBITE_CHARGE, 0);
        }
    }
}

static void lc_stop_cab_state_tab_mul_cb(char *nod, tag_value *data_value)
{
    int value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
    static int status = 0;

    if (strstr(nod, DEV_NO_BMS) == nod)
    {
        if (0 == dev_get_dev_tag_int(DEV_NO_LC, EN_BMS_ALARM)) // 没有使能BMS告警
        {
            ems_syslog(LOG_WARNING, "lc system fault, %s:%d", nod, value);
            return;
        }
    }
    //
    int not_size = sizeof(lc_stop_cab_state_tab_mul_not) / sizeof(lc_stop_cab_state_tab_mul_not[0]);
    if (value != 0)
    {

        for (int i = 0; i < not_size; i++)
        {
            if (strcmp(nod, lc_stop_cab_state_tab_mul_not[i]) == 0)
            {
                status &= (~(0x01 << i));
                break;
            }
        }
        //
        for (int i = 0; i < sizeof(lc_stop_cab_state_tab_mul) / sizeof(lc_stop_cab_state_tab_mul[0]); i++)
        {
            if (strcmp(nod, lc_stop_cab_state_tab_mul[i]) == 0)
            {
                status |= (0x01 << (i + not_size));
                break;
            }
        }
    }
    else
    {
        for (int i = 0; i < not_size; i++)
        {
            if (strcmp(nod, lc_stop_cab_state_tab_mul_not[i]) == 0)
            {
                status |= (0x01 << i);
                break;
            }
        }
        //
        for (int i = 0; i < sizeof(lc_stop_cab_state_tab_mul) / sizeof(lc_stop_cab_state_tab_mul[0]); i++)
        {
            if (strcmp(nod, lc_stop_cab_state_tab_mul[i]) == 0)
            {
                status &= (~(0x01 << (i + not_size)));
                break;
            }
        }
    }
    //
    dev_set_dev_tag_int(DEV_NO_LC, SYSTEM_STATUS_W, status);
    if (status != 0)
    {
        dev_set_dev_tag_int(DEV_NO_LC, SYSTEM_STATUS, 1);
    }
    else
    {
        dev_set_dev_tag_int(DEV_NO_LC, SYSTEM_STATUS, 0);
    }
    ems_syslog(LOG_WARNING, "%s -> lc stste fault, value:%d", nod, value);
}

static void lc_stop_fire_cb(char* nod, tag_value* data_value)
{
    // 从机消防告警，触发脱扣
    int value = (data_value->type == 0) ? data_value->value.to_int : data_value->value.to_float;
    if (value > 0)
        do_trip();
}

int check_ems_offline(void)
{
    static tag_value tag = {.type = 0};
    int cur = (!get_ems_online());
    if (tag.value.to_int != cur)
    {
        tag.value.to_int = cur;
        lc_stop_cab_state_tab_mul_cb(EMS_CONNECT_STATE, &tag);
    }
    return 0;
}

int get_lc_stop_charge_tab(void)
{
    for (int i = 0; i < sizeof(lc_stop_charge_tab_mul) / sizeof(lc_stop_charge_tab_mul[0]); i++)
    {
        int value = dev_get_nodeid_int(lc_stop_charge_tab_mul[i]);
        if (value != 0)
        {
            return 1;
        }
    }
    return 0;
}

int get_lc_stop_discharge_tab(void)
{
    for (int i = 0; i < sizeof(lc_stop_discharge_tab) / sizeof(lc_stop_discharge_tab[0]); i++)
    {
        int value = dev_get_nodeid_int(lc_stop_discharge_tab[i]);
        if (value != 0)
        {
            return 1;
        }
    }
    return 0;
}
