#include "../common.h"
#include "../ems/emsctrlProc.h"
#include "../log_module/log_module.h"
#include "lz4.h"
#include <math.h>
#include "north_mqtt.h"
#include "north_jsonct.h"
#include "../ems/lc.h"
#include "../automatic_north/north_automatic.h"
#include "../ems/main.h"
#include "../business_log/business_log.h"

extern all_plan north_g_all_plan[NORTH_CHANNEL_CONRTOL_CNT][MAX_DAY_YEAR+1];
extern int north_control;

int north_parse_all_plan(cJSON *messages, int channel_index)
{
    if(channel_index >= NORTH_CHANNEL_CONRTOL_CNT)
    {
        return -1;
    }
    int message_num = cJSON_GetArraySize(messages);
    message_num = message_num>MAX_DAY_YEAR?MAX_DAY_YEAR:message_num;
    for (size_t i = 0; i < message_num; i++)
    {
        int tmp_1,tmp_2,tmp_3;
        cJSON *message = cJSON_GetArrayItem(messages,i);
        cJSON *date = cJSON_GetObjectItem(message, "Date");
        if (date!=NULL)
        {
            if(sscanf(date->valuestring,"%d-%d-%d",&tmp_1,&tmp_2,&tmp_3)!=3)
            {
                return -1;
            }
            north_g_all_plan[channel_index][i].year = tmp_1;
            north_g_all_plan[channel_index][i].mounth = tmp_2;
            north_g_all_plan[channel_index][i].date = tmp_3;

            for (int total_time=0;total_time<get_tou_max_num();total_time++)
            {
                memset(&north_g_all_plan[channel_index][i].schedule[total_time],0,sizeof(north_g_all_plan[channel_index][i].schedule[total_time]));
                north_g_all_plan[channel_index][i].schedule[total_time].SocUp = -1;
                north_g_all_plan[channel_index][i].schedule[total_time].SocLower = -1;
            }

            cJSON *Schedules = cJSON_GetObjectItem(message, "Schedule");
            int Schedule_num = cJSON_GetArraySize(Schedules);
            for (int j = 0; j < Schedule_num; j++)
            {
                cJSON *Schedule = cJSON_GetArrayItem(Schedules,j);
                if (Schedule!=NULL)
                {   
                    cJSON *StartTime = cJSON_GetObjectItem(Schedule, "StartTime");
                    cJSON *EndTime = cJSON_GetObjectItem(Schedule, "EndTime");
                    cJSON *Power = cJSON_GetObjectItem(Schedule, "Power");
                    cJSON *RePower = cJSON_GetObjectItem(Schedule, "RePower");
                    cJSON *Soc_up = cJSON_GetObjectItem(Schedule, "SOCUpperLimit");
                    cJSON *Soc_lower = cJSON_GetObjectItem(Schedule, "SOCLowerLimit");

                    if ((!StartTime)||(!EndTime)||(!Power)) return -1;
                    
                    int start_hour,start_min,end_hour,end_min,power,repower,soc_up,soc_lower;
                    sscanf(StartTime->valuestring,"%d:%d",&start_hour,&start_min);
                    sscanf(EndTime->valuestring,"%d:%d",&end_hour,&end_min);
                    power = Power->valueint;
                    repower = (RePower) ? RePower->valueint : 0;
                    soc_up = (Soc_up) ? Soc_up->valueint : (-1);
                    soc_lower = (Soc_lower) ? Soc_lower->valueint : (-1);

                    ems_syslog(LOG_INFO, "schedule %d, %d.%d -> %d.%d [%d] [%d] [%d] [%d]",j,start_hour,start_min,end_hour,end_min,power,repower, soc_up, soc_lower);  
                    north_g_all_plan[channel_index][i].schedule[j].StHour = start_hour;
                    north_g_all_plan[channel_index][i].schedule[j].StMin = start_min;
                    north_g_all_plan[channel_index][i].schedule[j].EnHour = end_hour;
                    north_g_all_plan[channel_index][i].schedule[j].EnMin = end_min;
                    north_g_all_plan[channel_index][i].schedule[j].Power = power;
                    north_g_all_plan[channel_index][i].schedule[j].RePower = repower;
                    north_g_all_plan[channel_index][i].schedule[j].SocUp = soc_up;
                    north_g_all_plan[channel_index][i].schedule[j].SocLower = soc_lower;
                }
            };
        }
    }
    return 0;
}

void north_save_all_plan_to_file(cJSON *plan, int channel_index)
{
    if(channel_index >= NORTH_CHANNEL_CONRTOL_CNT)
    {
        return;
    }
    char *string = cJSON_Print(plan);
    ems_syslog(LOG_INFO,"%s\n",string);
    if (string != NULL)
    {
        char filename[256] = {0};
        // 生成带通道编号的文件名
        snprintf(filename, sizeof(filename), "/app/config/north/mqtt_north_plan_channel%d.json", channel_index);
        write_file_data(filename, string, strlen(string));
        free(string);
        string=NULL;
        server_add_new_log(LOG_CODE_SAVE_FILE,"EMS",LOG_MODE_TRIG,1,filename);
    }
}

void north_get_all_plan_from_file(void)
{
    for (int channel_index = 0; channel_index < NORTH_CHANNEL_CONRTOL_CNT; channel_index++)
    {
        char filename[256] = {0};
        char no_str[32];
        snprintf(no_str, sizeof(no_str), "%d", channel_index);
        
        // 生成对应通道的文件名
        snprintf(filename, sizeof(filename), "/app/config/north/mqtt_north_plan_channel%d.json", channel_index);
        char *pdata = read_file_data(filename);
        
        // 如果文件不存在，跳过该通道
        if (pdata == NULL)
        {
            ems_syslog(LOG_ERR, "read cfg file %s error or file not exist, skip\n", filename);
            continue;
        }

        cJSON *root = cJSON_Parse(pdata);
        if (!root)
        {
            ems_syslog(LOG_ERR, "json parse error for file: %s", filename);
            BUSINESS_LOG(BLOG_ERR, NORTH_ID_0040, no_str, "[北向]:索引[%s]策略文件读取失败! 文件名:[%s]", no_str, filename);
            free(pdata);
            continue;
        }
        else
        {
            BUSINESS_LOG(BLOG_NOTICE, NORTH_ID_0040, no_str, "[北向]:索引[%s]策略文件读取成功! 文件名:[%s]", no_str, filename);
        }
        
        // 解析该通道的计划数据
        int parse_ret = north_parse_all_plan(root, channel_index);
        if(parse_ret == 0)
        {
            BUSINESS_LOG(BLOG_NOTICE, NORTH_ID_0041, no_str, "[北向]:索引[%s]策略文件解析成功! 文件名:[%s]", no_str, filename);
        }
        else
        {
            BUSINESS_LOG(BLOG_ERR, NORTH_ID_0041, no_str, "[北向]:索引[%s]策略文件解析失败! 文件名:[%s]", no_str, filename);
        }
        
        if (root != NULL)
        {
            cJSON_Delete(root);
        }
        if (pdata != NULL)
        {
            free(pdata);
        }
    }
}

int save_modbus_plan_to_file(int north_channel_id)
{
    cJSON *plan_array = NULL;
    time_t t = time(NULL);
    
    struct tm target_time = {};  
    localtime_r(&t, &target_time);
    struct tm *current_time = &target_time;

    // 创建临时数组存储96段策略
    tou_seg_t segments[NUM_TOU_SEG_MAX] = {0};
    for (int j = 0; j < get_tou_max_num(); j++)
    {
        char name[64];
        snprintf(name, sizeof(name), "S%dStHour", j+1);
        segments[j].StHour = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dStMin", j+1);
        segments[j].StMin = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dEnHour", j+1);
        segments[j].EnHour = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dEnMin", j+1);
        segments[j].EnMin = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dPower", j+1);
        segments[j].Power = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dRePower", j+1);
        segments[j].RePower = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dSOCUpperLimit", j+1);
        segments[j].SocUp = dev_get_dev_tag_int(DEV_NO_EMS, name);
        snprintf(name, sizeof(name), "S%dSOCLowerLimit", j+1);
        segments[j].SocLower = dev_get_dev_tag_int(DEV_NO_EMS, name);
    }

    plan_array = cJSON_CreateArray();
    if (plan_array == NULL)
    {
        ems_syslog(LOG_NOTICE, "cJSON_CreateArray plan_array NULL");
        goto end;
    }

    // 生成366天的计划数据
    struct tm day_time = *current_time;
    for (size_t i = 0; i < MAX_DAY_YEAR; i++)
    {
        mktime(&day_time); 
        north_g_all_plan[north_channel_id][i].year = day_time.tm_year + 1900;
        north_g_all_plan[north_channel_id][i].mounth = day_time.tm_mon + 1;
        north_g_all_plan[north_channel_id][i].date = day_time.tm_mday;

        // 复制策略数据
        for (int j = 0; j < get_tou_max_num(); j++)
        {
            north_g_all_plan[north_channel_id][i].schedule[j] = segments[j];
        }

        // 创建当天的JSON对象
        cJSON *day_object = cJSON_CreateObject();
        if (day_object == NULL)
        {
            ems_syslog(LOG_NOTICE, "cJSON_CreateObject day_object NULL");
            continue;
        }

        // 添加日期字段
        char date_str[36];
        snprintf(date_str, sizeof(date_str), "%04d-%02d-%02d",
                 day_time.tm_year + 1900, day_time.tm_mon + 1, day_time.tm_mday);
        cJSON_AddStringToObject(day_object, "Date", date_str);

        // 创建策略数组
        cJSON *schedule_array = cJSON_CreateArray();
        if (schedule_array == NULL)
        {
            ems_syslog(LOG_NOTICE, "cJSON_CreateArray schedule_array NULL");
            cJSON_Delete(day_object);
            continue;
        }

        // 添加有效策略段
        for (int j = 0; j < get_tou_max_num(); j++)
        {
            // 跳过无效策略
            if (segments[j].StHour == 0 && segments[j].StMin == 0 && segments[j].EnHour == 0 && segments[j].EnMin == 0 &&
                segments[j].Power == 0 && segments[j].RePower == 0 && segments[j].SocUp == 0 && segments[j].SocLower == 0)
            {
                continue;
            }

            cJSON *schedule_object = cJSON_CreateObject();
            if (schedule_object == NULL)
            {
                ems_syslog(LOG_NOTICE, "cJSON_CreateObject schedule_object NULL");
                continue;
            }

            // 格式化开始和结束时间
            char start_time[12], end_time[12];
            snprintf(start_time, sizeof(start_time), "%02d:%02d", segments[j].StHour, segments[j].StMin);
            snprintf(end_time, sizeof(end_time), "%02d:%02d", segments[j].EnHour, segments[j].EnMin);

            cJSON_AddStringToObject(schedule_object, "StartTime", start_time);
            cJSON_AddStringToObject(schedule_object, "EndTime", end_time);
            cJSON_AddNumberToObject(schedule_object, "Power", segments[j].Power);
            cJSON_AddNumberToObject(schedule_object, "RePower", segments[j].RePower);
            cJSON_AddNumberToObject(schedule_object, "SOCUpperLimit", segments[j].SocUp);
            cJSON_AddNumberToObject(schedule_object, "SOCLowerLimit", segments[j].SocLower);

            cJSON_AddItemToArray(schedule_array, schedule_object);
        }

        cJSON_AddItemToObject(day_object, "Schedule", schedule_array);
        cJSON_AddItemToArray(plan_array, day_object);

        // 递增日期
        day_time.tm_mday++;
        mktime(&day_time);
    }

    // 保存数据到文件
    char *json_string = cJSON_Print(plan_array);
    if (json_string != NULL)
    {
        ems_syslog(LOG_INFO, "%s\n", json_string);
        char filename[256];
        snprintf(filename, sizeof(filename), "/app/config/north/mqtt_north_plan_channel%d.json", north_channel_id);
        write_file_data(filename, json_string, strlen(json_string));
        free(json_string);
        server_add_new_log(LOG_CODE_SAVE_FILE, "EMS", LOG_MODE_TRIG, 1, filename);
    }

end:
    if (plan_array != NULL)
    {
        cJSON_Delete(plan_array);
    }
    return 0;
}

char *_report_SingleDev_data_print(mqt_north_channel_t *channel, char *device_type, char *no, char* function_id, int mi)
{
    char *string = NULL;
    char class_type[DEV_NO_LEN] = {0};
    mqt_north_var_t *var = channel->var;

    time_t timestamp = time(NULL);
    char value_str[30];
    double value;
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        goto end;
    }

    cJSON_AddStringToObject(root, "funcId", function_id);
    cJSON_AddStringToObject(root, "stationno", var->cab_id);
    cJSON_AddStringToObject(root, "stationname", var->cab_station_name);
    cJSON_AddStringToObject(root, "deviceType", device_type);
    cJSON_AddStringToObject(root, "no", no);
    cJSON_AddNumberToObject(root, "mi", mi);
    cJSON_AddNumberToObject(root, "time", timestamp);
    cJSON *tags = cJSON_CreateObject();
    if (tags == NULL)
    {
        goto end;
    }
    cJSON_AddItemToObject(root, "tags", tags);

    if (strcmp(device_type, DEV_NO_METER) == 0){ // 电表特殊处理
        if (strstr(no, "GRID_METER")){
            snprintf(class_type, DEV_NO_LEN, "%s", "GRID_METER");
        }
        else if (strstr(no, "PCS_METER")){
            snprintf(class_type, DEV_NO_LEN, "%s", "PCS_METER");
        }
    }else
        snprintf(class_type, DEV_NO_LEN, "%s", device_type);

    for(int i = 0; i < var->num; i++)
    {
        if (strcmp(class_type, var->mqt_north_class[i]->class_type) == 0){

                mqt_north_class_t *mqt_north_class = var->mqt_north_class[i];
                for(int j = 0; j < mqt_north_class->num; j++){

                    if (strcmp(no, mqt_north_class->mqt_north_dev[j]->no) == 0){

                        mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[j];
                        for(int m = 0; m < mqt_north_dev->realdata_num; m++){
                            
                                mqt_north_tag_t *mqt_north_tag = mqt_north_dev->realdata_tags[m];
                                ems_syslog(LOG_ERR, "tag:%s data_type:%d", mqt_north_tag->name, mqt_north_tag->data_type);
                                if (mqt_north_tag->data_type) // 0 int 1 float
                                {
                                snprintf(value_str, sizeof(value_str), "%.2f", dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name));
                                value = atof(value_str);
                                cJSON_AddNumberToObject(tags, mqt_north_tag->name, round(value*100)/100);
                                }
                                else
                                    cJSON_AddNumberToObject(tags, mqt_north_tag->name, dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name));
                        }
                        break;
                    }
                }
                break;
        }
    }

    string = cJSON_PrintUnformatted(root);

end:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    return string;
}

char *_report_AllDev_data_print(mqt_north_var_t *var, int *cnt, int mi)
{  
    char *string = NULL;
    char class_type[32] = {0}; 
    proto_forward_t *dev_var = get_proto_forward_var();

    time_t timestamp = time(NULL);
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        goto end;
    }
	
    cJSON_AddStringToObject(root, "funcId", FUNCTION_PeriodReport);
    cJSON_AddStringToObject(root, "stationno", var->cab_id);
    cJSON_AddStringToObject(root, "stationname", var->cab_station_name);
    cJSON_AddNumberToObject(root, "mi", mi); 
    cJSON_AddNumberToObject(root, "time", timestamp);
    cJSON *data = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "data", data);

    for (int i = 0; i < dev_var->channels_size; i++)
    {
        //ems_syslog(LOG_DEBUG, "channel:%s", dev_var->channels[i]->channel);
        for (int j = 0; j < dev_var->channels[i]->devs_size; j++)
        {
            device_t *dev = dev_var->channels[i]->devs[j];
            //template_t *p = dev->use_template;
            //ems_syslog(LOG_DEBUG, "dev: %s->template info:model->%s, adapter->%s", dev->no, p->model, p->adapter);

            if (strcmp(dev->dev_type, DEV_NO_METER) == 0){
                snprintf(class_type, 32, "%s_%s", dev->dev_child_type, dev->dev_type);
            }
            else
                snprintf(class_type, 32, "%s", dev->dev_type);

            for(int m = 0; m < var->num; m++)
            {
                char **compatible = external_match_by_class_type(var->mqt_north_class[m]->class_type);
                if (compatible == NULL){
                    continue;
                }
                while(*compatible != NULL){
                    if (strcmp(class_type, *compatible) == 0){
                        break;
                    }
                    compatible++;
                }
                if (*compatible != NULL){
                    mqt_north_class_t *mqt_north_class = var->mqt_north_class[m];
                    for(int n = 0; n < mqt_north_class->num; n++){

                        if (strcmp(dev->no, mqt_north_class->mqt_north_dev[n]->no) == 0){

                            mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[n];

                            if (timestamp < mqt_north_dev->last_ts + mqt_north_class->interval)
                            {
                                goto next_dev; // 时间没到
                            }
                            mqt_north_dev->last_ts = timestamp;
                            (*cnt)++;
                            cJSON *_dev = cJSON_CreateObject();
                            cJSON_AddItemToArray(data, _dev);
                            cJSON_AddStringToObject(_dev, "no", dev->no); 
                            cJSON_AddStringToObject(_dev, "deviceType", dev->dev_type); 
                            cJSON *tags = cJSON_CreateObject();
                            cJSON_AddItemToObject(_dev, "tags", tags);
                            char value_str[30];
                            double value;
                            for(int o = 0; o < mqt_north_dev->realdata_num; o++){

                                    mqt_north_tag_t *mqt_north_tag = mqt_north_dev->realdata_tags[o];
                                    if (mqt_north_tag->data_type) // 0 int 1 float
                                {
                                    snprintf(value_str, sizeof(value_str), "%.2f", dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name));
                                    value = atof(value_str);
                                    cJSON_AddNumberToObject(tags, mqt_north_tag->name, round(value*100)/100);
                                    }
                                    else
                                        cJSON_AddNumberToObject(tags, mqt_north_tag->name, dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name));
                            }
                            break;
                        }
                    }
                    break;
                }
            }
next_dev:
        ;	//>>检查下一个设备
        }
    }
#ifdef EN_EMS
    pcs_ctrl_var_t *_var = get_pcs_ctrl_var();
    for (int i = 0; i < _var->lc_list_len; i++)
	{
        lc_it *lc_single = &(_var->lc_list[i]);
        
		slave_ems *slave = lc_single->slave;
		if (slave == NULL) continue;  // lc vlc
        for (int j = 0; j < slave->dev_sum; j++)
        {
            device_t *dev = &(slave->devs[j]);
            if (strcmp(dev->dev_type, DEV_NO_METER) == 0){
                snprintf(class_type, 32, "%s_%s", dev->dev_child_type, dev->dev_type);
            }
            else
                snprintf(class_type, 32, "%s", dev->dev_type);

            for(int m = 0; m < var->num; m++)
            {
                char **compatible = external_match_by_class_type(var->mqt_north_class[m]->class_type);
                if (compatible == NULL){
                    continue;
                }
                while(*compatible != NULL){
                    if (strcmp(class_type, *compatible) == 0){
                        break;
                    }
                    compatible++;
                }
                if (*compatible != NULL){
                    mqt_north_class_t *mqt_north_class = var->mqt_north_class[m];
                    for(int n = 0; n < mqt_north_class->num; n++){

                        if (strcmp(dev->no, mqt_north_class->mqt_north_dev[n]->no) == 0){

                            mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[n];

                            if (timestamp < mqt_north_dev->last_ts + mqt_north_class->interval)
                            {
                                goto next_dev_lc; // 时间没到
                            }
                            mqt_north_dev->last_ts = timestamp;
                            (*cnt)++;
                            cJSON *_dev = cJSON_CreateObject();
                            cJSON_AddItemToArray(data, _dev);
                            cJSON_AddStringToObject(_dev, "no", dev->no); 
                            cJSON_AddStringToObject(_dev, "deviceType", dev->dev_type); 
                            cJSON *tags = cJSON_CreateObject();
                            cJSON_AddItemToObject(_dev, "tags", tags);
                            char value_str[30];
                            double value;
                            for(int o = 0; o < mqt_north_dev->realdata_num; o++){

                                    mqt_north_tag_t *mqt_north_tag = mqt_north_dev->realdata_tags[o];
                                    if(strcmp(mqt_north_tag->name,"Online") == 0)
                                    {
                                        cJSON_AddNumberToObject(tags, mqt_north_tag->name, dev->online);
                                        continue;
                                    }
                                    if (mqt_north_tag->data_type) // 0 int 1 float
                                    {
                                        snprintf(value_str, sizeof(value_str), "%.2f", dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name));
                                        value = atof(value_str);
                                        cJSON_AddNumberToObject(tags, mqt_north_tag->name, round(value*100)/100);
                                    }
                                    else
                                        cJSON_AddNumberToObject(tags, mqt_north_tag->name, dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name));
                            }
                            break;
                        }
                    }
                    break;
                }
            }
next_dev_lc:
        ;	//>>检查下一个设备
        }
	}
#endif
    string = cJSON_PrintUnformatted(root);
	
end:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    return string;
}

char *_report_alarm_print(mqt_north_var_t *var, int *cnt, char* function_id, int mi)
{  
    char *string = NULL;
    char class_type[32] = {0}; 
    proto_forward_t *dev_var = get_proto_forward_var();

    time_t timestamp = time(NULL);
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        goto end;
    }

    cJSON_AddStringToObject(root, "funcId", function_id);
    cJSON_AddStringToObject(root, "stationno", var->cab_id);
    cJSON_AddStringToObject(root, "stationname", var->cab_station_name);
    cJSON_AddNumberToObject(root, "mi", mi); 
    cJSON_AddNumberToObject(root, "time", timestamp);
    cJSON *alarms = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "alarms", alarms);

    for (int i = 0; i < dev_var->channels_size; i++)
    {
        //ems_syslog(LOG_DEBUG, "channel:%s", dev_var->channels[i]->channel);
        for (int j = 0; j < dev_var->channels[i]->devs_size; j++)
        {
            device_t *dev = dev_var->channels[i]->devs[j];
            //template_t *p = dev->use_template;
            //ems_syslog(LOG_DEBUG, "dev: %s->template info:model->%s, adapter->%s", dev->no, p->model, p->adapter);

            if (strcmp(dev->dev_type, DEV_NO_METER) == 0){
                snprintf(class_type, 32, "%s_%s", dev->dev_child_type, dev->dev_type);
            }
            else
                snprintf(class_type, 32, "%s", dev->dev_type);

            for(int m = 0; m < var->num; m++)
            {
                if (strcmp(class_type, var->mqt_north_class[m]->class_type) == 0){
            
                        mqt_north_class_t *mqt_north_class = var->mqt_north_class[m];
                        for(int n = 0; n < mqt_north_class->num; n++){
            
                            if (strcmp(dev->no, mqt_north_class->mqt_north_dev[n]->no) == 0){
            
                                mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[n];
                                for(int o = 0; o < mqt_north_dev->alarm_num; o++){
            
                                        mqt_north_tag_t *mqt_north_tag = mqt_north_dev->alarm_tags[o];
                                        if (mqt_north_tag->data_type){ // 0 int 1 float >> 告警只可能是int 
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name);
                                        }else{
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name);
                                        }

                                        // 当前发生/恢复的告警
                                        if (mqt_north_tag->cur_alarm == 1 && mqt_north_tag->report_flag == 0){
                                            mqt_north_tag->report_flag = 1;
                                            cJSON *tag = cJSON_CreateObject();
                                            cJSON_AddStringToObject(tag, "no", dev->no); 
                                            cJSON_AddStringToObject(tag, "name", mqt_north_tag->name); 
                                            cJSON_AddNumberToObject(tag, "stat", ALARM);
                                            cJSON_AddItemToArray(alarms, tag); 
                                            (*cnt)++;
                                        }
                                        else if (mqt_north_tag->cur_alarm == 0 && mqt_north_tag->report_flag == 1){
                                            mqt_north_tag->report_flag = 0;
                                            cJSON *tag = cJSON_CreateObject();
                                            cJSON_AddStringToObject(tag, "no", dev->no); 
                                            cJSON_AddStringToObject(tag, "name", mqt_north_tag->name); 
                                            cJSON_AddNumberToObject(tag, "stat", NOALARM);
                                            cJSON_AddItemToArray(alarms, tag); 
                                            (*cnt)++;
                                        }else
                                        ;
                                }
                                break;
                            }
                        }
                        break;
                }
            }
        }
    }
#ifdef EN_EMS
    pcs_ctrl_var_t *_var = get_pcs_ctrl_var();
    for (int i = 0; i < _var->lc_list_len; i++)
	{
        lc_it *lc_single = &(_var->lc_list[i]);
        
		slave_ems *slave = lc_single->slave;
		if (slave == NULL) continue;  // lc vlc
        for (int j = 0; j < slave->dev_sum; j++)
        {
            device_t *dev = &(slave->devs[j]);
            if (strcmp(dev->dev_type, DEV_NO_METER) == 0){
                snprintf(class_type, 32, "%s_%s", dev->dev_child_type, dev->dev_type);
            }
            else
                snprintf(class_type, 32, "%s", dev->dev_type);

            for(int m = 0; m < var->num; m++)
            {
                if (strcmp(class_type, var->mqt_north_class[m]->class_type) == 0){
            
                        mqt_north_class_t *mqt_north_class = var->mqt_north_class[m];
                        for(int n = 0; n < mqt_north_class->num; n++){
            
                            if (strcmp(dev->no, mqt_north_class->mqt_north_dev[n]->no) == 0){
            
                                mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[n];
                                for(int o = 0; o < mqt_north_dev->alarm_num; o++){
            
                                        mqt_north_tag_t *mqt_north_tag = mqt_north_dev->alarm_tags[o];
                                        if (mqt_north_tag->data_type){ // 0 int 1 float >> 告警只可能是int 
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name);
                                        }else{
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name);
                                        }

                                        // 当前发生/恢复的告警
                                        if (mqt_north_tag->cur_alarm == 1 && mqt_north_tag->report_flag == 0){
                                            mqt_north_tag->report_flag = 1;
                                            cJSON *tag = cJSON_CreateObject();
                                            cJSON_AddStringToObject(tag, "no", dev->no); 
                                            cJSON_AddStringToObject(tag, "name", mqt_north_tag->name); 
                                            cJSON_AddNumberToObject(tag, "stat", ALARM);
                                            cJSON_AddItemToArray(alarms, tag); 
                                            (*cnt)++;
                                        }
                                        else if (mqt_north_tag->cur_alarm == 0 && mqt_north_tag->report_flag == 1){
                                            mqt_north_tag->report_flag = 0;
                                            cJSON *tag = cJSON_CreateObject();
                                            cJSON_AddStringToObject(tag, "no", dev->no); 
                                            cJSON_AddStringToObject(tag, "name", mqt_north_tag->name); 
                                            cJSON_AddNumberToObject(tag, "stat", NOALARM);
                                            cJSON_AddItemToArray(alarms, tag); 
                                            (*cnt)++;
                                        }else
                                        ;
                                }
                                break;
                            }
                        }
                        break;
                }
            }
        }
	}
#endif

    string = cJSON_PrintUnformatted(root);
	
end:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    return string;
}

char *_report_allalarm_print(mqt_north_channel_t *channel, int *cnt, char* function_id, int mi)
{  
    char *string = NULL;
    char class_type[32] = {0}; 
    mqt_north_var_t *var = channel->var;
    proto_forward_t *dev_var = get_proto_forward_var();

    time_t timestamp = time(NULL);
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        goto end;
    }

    cJSON_AddStringToObject(root, "funcId", function_id);
    cJSON_AddStringToObject(root, "stationno", var->cab_id);
    cJSON_AddStringToObject(root, "stationname", var->cab_station_name);
    cJSON_AddNumberToObject(root, "mi", mi); 
    cJSON_AddNumberToObject(root, "time", timestamp);
    cJSON *alarms = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "alarms", alarms);

    for (int i = 0; i < dev_var->channels_size; i++)
    {
        //ems_syslog(LOG_DEBUG, "channel:%s", dev_var->channels[i]->channel);
        for (int j = 0; j < dev_var->channels[i]->devs_size; j++)
        {
            device_t *dev = dev_var->channels[i]->devs[j];
            //template_t *p = dev->use_template;
            //ems_syslog(LOG_DEBUG, "dev: %s->template info:model->%s, adapter->%s", dev->no, p->model, p->adapter);

            if (strcmp(dev->dev_type, DEV_NO_METER) == 0){
                snprintf(class_type, 32, "%s_%s", dev->dev_child_type, dev->dev_type);
            }
            else
                snprintf(class_type, 32, "%s", dev->dev_type);

            for(int m = 0; m < var->num; m++)
            {
                if (strcmp(class_type, var->mqt_north_class[m]->class_type) == 0){
            
                        mqt_north_class_t *mqt_north_class = var->mqt_north_class[m];
                        for(int n = 0; n < mqt_north_class->num; n++){
            
                            if (strcmp(dev->no, mqt_north_class->mqt_north_dev[n]->no) == 0){
            
                                mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[n];
                                for(int o = 0; o < mqt_north_dev->alarm_num; o++){
            
                                        mqt_north_tag_t *mqt_north_tag = mqt_north_dev->alarm_tags[o];
                                        if (mqt_north_tag->data_type){ // 0 int 1 float >> 告警只可能是int 
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name);
                                        }else{
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name);
                                        }

                                        // 全量告警（当前尚未清除的所有告警信息）
                                        if (mqt_north_tag->cur_alarm == 1){
                                            cJSON *tag = cJSON_CreateObject();
                                            cJSON_AddStringToObject(tag, "no", dev->no); 
                                            cJSON_AddStringToObject(tag, "name", mqt_north_tag->name); 
                                            cJSON_AddNumberToObject(tag, "stat", ALARM);
                                            cJSON_AddItemToArray(alarms, tag); 
                                        }
                                }
                                break;
                            }
                        }
                        break;
                }
            }
        }
    }
#ifdef EN_EMS
    pcs_ctrl_var_t *_var = get_pcs_ctrl_var();
    for (int i = 0; i < _var->lc_list_len; i++)
	{
        lc_it *lc_single = &(_var->lc_list[i]);
        
		slave_ems *slave = lc_single->slave;
		if (slave == NULL) continue;  // lc vlc
        for (int j = 0; j < slave->dev_sum; j++)
        {
            device_t *dev = &(slave->devs[j]);
            if (strcmp(dev->dev_type, DEV_NO_METER) == 0){
                snprintf(class_type, 32, "%s_%s", dev->dev_child_type, dev->dev_type);
            }
            else
                snprintf(class_type, 32, "%s", dev->dev_type);

            for(int m = 0; m < var->num; m++)
            {
                if (strcmp(class_type, var->mqt_north_class[m]->class_type) == 0){
            
                        mqt_north_class_t *mqt_north_class = var->mqt_north_class[m];
                        for(int n = 0; n < mqt_north_class->num; n++){
            
                            if (strcmp(dev->no, mqt_north_class->mqt_north_dev[n]->no) == 0){
            
                                mqt_north_dev_t *mqt_north_dev = mqt_north_class->mqt_north_dev[n];
                                for(int o = 0; o < mqt_north_dev->alarm_num; o++){
            
                                        mqt_north_tag_t *mqt_north_tag = mqt_north_dev->alarm_tags[o];
                                        if (mqt_north_tag->data_type){ // 0 int 1 float >> 告警只可能是int 
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_float(mqt_north_dev->no, mqt_north_tag->name);
                                        }else{
                                            mqt_north_tag->cur_alarm = dev_get_dev_tag_int(mqt_north_dev->no, mqt_north_tag->name);
                                        }

                                        // 全量告警（当前尚未清除的所有告警信息）
                                        if (mqt_north_tag->cur_alarm == 1){
                                            cJSON *tag = cJSON_CreateObject();
                                            cJSON_AddStringToObject(tag, "no", dev->no); 
                                            cJSON_AddStringToObject(tag, "name", mqt_north_tag->name); 
                                            cJSON_AddNumberToObject(tag, "stat", ALARM);
                                            cJSON_AddItemToArray(alarms, tag); 
                                        }
                                }
                                break;
                            }
                        }
                        break;
                }
            }
        }
	}
#endif
    string = cJSON_PrintUnformatted(root);
	
end:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    return string;
}





int login_prase(login_info_t *info, const char *str)
{
    if (!info || !str)
    {
        return -1;
    }
    cJSON *root = cJSON_Parse(str);
    if (!root)
    {
        return -1;
    }
    GET_JSON_VALUE_INT(root, "mi", info->serial_num);
    GET_JSON_VALUE_INT(root, "time", info->timestamp);
    GET_JSON_VALUE_INT(root, "result", info->error_code);
    cJSON_Delete(root);
    return 0;
}


char *_login_print(mqt_north_var_t *var, login_info_t *info, char *gw_sn)
{
    //char version[32] = {0};
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        return NULL;
    }
    cJSON_AddStringToObject(root, "funcId", FUNCTION_LOGIN);
    cJSON_AddStringToObject(root, "stationno", var->cab_id);
    cJSON_AddStringToObject(root, "stationname", var->cab_station_name);
    cJSON_AddStringToObject(root, "vendor", "LNXALL");
    cJSON_AddStringToObject(root, "protocol", var->protocol);
    cJSON_AddNumberToObject(root, "mi", info->serial_num);
    cJSON_AddNumberToObject(root, "time", info->timestamp);
    char *str = (cJSON_PrintUnformatted(root));
    cJSON_Delete(root);
    return str;
}

char *_heartbeat_print(mqt_north_var_t *var, int mi, char *gw_sn)
{
    time_t timestamp = time(NULL);
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        return NULL;
    }
    cJSON_AddStringToObject(root, "funcId", FUNCTION_HeartBeat);
    cJSON_AddStringToObject(root, "stationno", var->cab_id);
    cJSON_AddStringToObject(root, "stationname", var->cab_station_name);
    cJSON_AddStringToObject(root, "vendor", "LNXALL");
    cJSON_AddNumberToObject(root, "mi", mi);
    cJSON_AddNumberToObject(root, "time", timestamp);
    char *str = (cJSON_PrintUnformatted(root));
    cJSON_Delete(root);
    return str;
}

char *_lc_cabno_print(mqt_north_var_t *var,int mi)
{
    pcs_ctrl_var_t *pcs_var = get_pcs_ctrl_var();
    int cur_sum = pcs_var->lc_list_len;
    lc_it *lc_cfg = pcs_var->lc_list;

    time_t timestamp = time(NULL);
    cJSON *root = cJSON_CreateObject();
    if (root == NULL)
    {
        return NULL;
    }
    cJSON_AddStringToObject(root, "funcId", "CabInfo");
    cJSON_AddStringToObject(root, "protocol", var->protocol);
    cJSON_AddNumberToObject(root, "mi", mi);
    cJSON_AddNumberToObject(root, "time", timestamp);
    cJSON *cabs = cJSON_CreateArray();
    cJSON *cab = NULL;
    for(int i = 0;i < cur_sum; i++)
    {
        if(lc_cfg[i].type == eLC_TYPE_EMS)
        {
            cab = cJSON_CreateObject();
            cJSON_AddStringToObject(cab, "name", lc_cfg[i].name);
            cJSON_AddItemToArray(cabs, cab);
        }
    }
    if (cabs != NULL)
    {
        cJSON_AddItemToObject(root, "cabs", cabs);
    }
    char *str = (cJSON_PrintUnformatted(root));
    cJSON_Delete(root);
    return str;
}