
#include <QtCore/QCoreApplication>
#include <iostream>
#include <fstream>
#include <qdebug.h>

#include <QFile>
#include <QtXml/QDomDocument>
#include <QtXml/QDomElement>
#include <QtXml/QDomNode>
#include <QtXml/QDomNodeList>
#include <QtCore/qglobal.h>
#include <list> //C++ STL的list
#include <map>  //C++ STL的map
#include <QStringList>

#include <QDateTime>//zw修改 2023-08-22 存储数据合理性相关属性
#include <QMap>//zw修改 2023-08-22 存储数据合理性相关属性

#include "mms_json_inter.h" //json头文件
#include "../mms/db_interface.h" //json头文件
#include "../mms/rdb_client.h"		//台账更新引用接口

//lnk20241031用于上传和下载文件
#include "../json/cjson.h"
///////////////////////////////////////////////////lnk2024-10-21////////////////////////////////////////////////////////
extern void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr);
extern std::string WEB_INTEGRITY;
extern std::string WEB_COMFLAG;
extern std::string WEB_EVENT;
extern std::string WEB_FILEDOWNLOAD;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using namespace std;

extern int parse_commerror_write(const std::vector<std::string>& codes);
extern int parse_commstatus_write(const std::vector<std::string>& codes);
extern int parse_match_write(const std::vector<std::string>& codes);
extern int parse_dataintegrity_write(const std::vector<std::string>& codes);
extern int parse_rationality_write(const std::vector<std::string>& codes);
extern std::string intToString(int number);

QString JSON_CONFIG_FN = QString("JiangSu_Config.xml");
#define APR_SUCCESS 1
#define APR_EBADPATH 0
#define APR_EBADF 0
const string PhsSTR = "ABCT";
extern int FILE_FLAG;

//lnk20250214
extern int isdelta_flag;
//江苏Kafka发送数据类定义-------------------------------------------------------------/*
class CEventData //SOE事件类
{
public:
	int nDataType;       //告警SOE事件类型
	QString type;        //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
	QString triggerFlag; //告警SOE事件触发指标名称
	int nIndex;          //数据在每条线路LineInfo值数组中的位置        
	QString DO;          //数据对象名
	QString DA;          //数据属性名
	QString strFullName; //数据对象名 $ 数据属性名
};

class CDataValue //数据值类
{
public:
	QString strName;     //数据名
	float fValue;        //数据值         
	bool bIsValue;       //数据是否赋值成功标识
	int nIndex;          //数据在每条线路LineInfo值数组中的位置
	QString type;        //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
	QString DO;          //数据对象名
	QString DA;          //数据属性名
	QString strFullName; //数据对象名 $ 数据属性名
	QString strCoefficient; //数据系数(字符型)
	float fCoefficient;  //数据系数(浮点型)
	QString strOffset;   //起始序号偏移量(字符型)
	int iOffset;         //起始序号偏移量(整型) = 江苏电科院臻迪数据项起始序号 - 装置数据项实际起始序号
	bool bIsAngle;       //角度标志 WW 2018-06-28
	bool bPlt;			 //长时闪变标识：true-长时闪变 false-短时闪变
	QString BaseFlag;    //zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
	QString LimitUp;     //zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
	QString LimitDown;   //zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
	
	

	CDataValue()
	{
		fCoefficient = 1.0f; //数据系数(浮点型)
		iOffset = 0; //起始序号偏移量(整型) 
		bIsAngle = false; //非角度标志
		bPlt = false; //短时闪变标识
	}
};

class CSequence //相别(A、B、C、T)类
{
public:
	QString strSValue; //相别值  例：7：ABC三项，8：T相
	QString strSeq;    //相别  例：A、B、C、T
	QString type;      //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
	list<CDataValue*> DataValueList; //数据值链表
};

class CItem //数据项类
{
public:
	QString strItemName;  //数据项名
	QString strItemValue; //数据项值
	QString type;         //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
	list<CSequence*> SequenceList; //相别链表
};

class CMonitor //监测点类
{
public:
	QString strMonitor;    //监测点名
	QString type;          //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
	list<CItem*> ItemList; //数据项链表
};

class CDataType //数据类型类
{
public:
	int iDataType;               //数据类型值：1-稳态 2-闪变 3-暂态
	QString type;                //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
	int BaseFlag1;     //zw修改 2023-8-25 记录基础数据总个数
	int BaseFlag0;     //zw修改 2023-8-25 记录非基础数据个数
	list<CMonitor*> MonitorList; //监测点链表     
	list<CEventData*> SOEList;   //SOE事件链表   
};

class CTopic //Kafka Producer发送主题类
{
public:
	QString strTopic;              //Kafka Producer发送主题值
	list<CDataType*> DataTypeList; //数据类型链表
};

class XmlConfig //zw修改 2023 - 8 - 14 增加xml解析的配置类 
{
public:
	QString WavePhasicFlag;        //是否分相 0-不分相 1-分相 如果Flag=0 A，B，C配置成一样，如果Flag=1，A，B，C根据实际配置
	QString WavePhasicA;           
	QString WavePhasicB;
	QString WavePhasicC;
	QString UnitOfTimeUnit;        //暂态事件持续事件单位：0 - 毫秒 1 - 秒
	QString ValueOfTimeUnit;       //上送值的时间：UTC-UTC时间 beijing-北京时间
	QString WaveTimeFlag;          //录波文件的时间：UTC-UTC时间 beijing-北京时间
	QString IEDname;               //例：PQMonitor
	QString LDevicePrefix;         //例：PQM
	list<CEventData*> SOEList;   //SOE告警事件链表   
};

class XmlDataBase //zw修改 2023-8-30 增加解析数据库模型表数据类
{
public:
	QString MODEL_ID;//模型编码 guid
	QString TMNL_TYPE;//终端型号
	QString TMNL_FACTORY;//终端厂家
	QString FILE_PATH;//远端模型文件路径  lnk2024-10-28
	QString FILE_NAME;//oss文件存储路径
	QDateTime datetime;//更新时间 时间戳
};

class MP_RATIONALITY //zw修改 2023 - 8 - 22 增加数据不合理性记录类
{
public:
	double fValue;//zw修改 2023-08-22 第一次记录的不合理数值
	QDateTime dtvalue;//zw修改 2023-08-22 第一次记录的不合理数值出现时间
	int over_time;//zw修改 2023-08-22 该记录属性不合理数值出现次数
};

class Mn_Timespan //zw修改 2023-08-29 时间间隔保存类
{
public:
	QList<long long> timespan;//时间戳队列
	int msspan;

	Mn_Timespan()
	{
		msspan = 0;
	}
};

class Xmldata //zw修改 2023-08-30
{
public:
	XmlDataBase xmlbase;//xml数据库数据
	XmlConfig xmlcfg;//新増的xml节点解析数据
	list<CTopic*> topicList; //Kafka发送主题链表
	bool updataflag = true;
};

//-------------------------------------------------------------------------------------*/
//主程序已定义该变量
//extern QMutex kafka_data_list_mutex; //Kafka发送数据锁
//extern QList<kafka_data_t> kafka_data_list;  //kafka发送数据链表
extern int FILE_FLAG;

QMutex kafka_data_list_mutex; //Kafka发送数据锁
QList<Ckafka_data_t> kafka_data_list; //kafka发送数据链表

QMutex oss_data_list_mutex; //oss发送数据锁 zw新增
QList<oss_data_t> oss_data_list; //oss发送数据链表 zw新增
//-------------------------------------------------------------------------------------*/
//////////////////////////////////////WW 2023-08-22 start
QMutex Sql_data_list_mutex; //Sql执行语句锁
QList<QString> Sql_data_list; //Sql执行语句链表
//////////////////////////////////////WW 2023-08-22 end

//QMap<int, QMap<QString, MP_RATIONALITY*> > error_data_list;//zw修改 2023 - 8 - 22 新増数据不合理性记录map
//QMap<int, QMap<QString, QDateTime> > error_datamatch_list;//zw修改 2023-8-28 数据匹配率缺少字段记录map
QMap<QString,Mn_Timespan*> data_timespan_list;//zw修改 2023 - 8 - 29 计算时间间隔
QMap<QString, Xmldata*> xmlinfo_list;//zw修改 保存所有型号对应的xml数据-数据库数据 新增的节点解析数据 kafka发送链表

XmlConfig xmlcfg;//zw修改 2023 - 8 - 14 新増xml节点解析的数据
list<CTopic *> topicList; //Kafka发送主题链表
int inited = false; //JiangSu_Config.xml是否初始化标识

XmlConfig xmlcfg2;//lnk2024 - 8 - 13 新増角型xml节点解析的数据
list<CTopic*> topicList2; //lnk2024-8-14角型Kafka发送主题链表
QMap<QString, Xmldata*> xmlinfo_list2;//lnk2024-8-14 保存角型所有型号对应的xml数据-数据库数据 新增的节点解析数据 kafka发送链表
extern int isdelta_flag;//lnk2024-8-16 角型接线标志

///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
void connectlog_pgsql(char* id,char* datetime,int status);
void errorlog_pgsql(char* id, QString time, QString filename);
void SoeRptSql(char* id, int state,char* rpt);
QString errorlog_num_pgsql(QString monitorId, QString datatime, QString filename, int count);
QString errorlog_dataintegrity_pgsql(QString time, QString datatime,QString monitorId,bool recallflag);
QString errorlog_datamatch_pgsql(QString id, QString time, int BASE_MAT_NUM,int ADV_MAT_NUM,int BASE_ACT_NUM,int ADV_ACT_NUM,QString filename);

#if 0
void connectlog_pgsql(char* id)
{
	QString pgsql;
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_comm_status_tr\"(\"terminal_id\",\"statistical_date\",\"comm_status\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',1) ").arg(id).arg(QDateTime::currentDateTime().toString("yyyyMMdd")));
	pgsql.append(QString("on conflict(\"terminal_id\",\"statistical_date\") do update set "));
	pgsql.append(QString("\"comm_status\"= \"%1\".\"%2meas_pq_comm_status_tr\".\"comm_status\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	//cout << pgsql.toAscii().data() << endl;
}
//zw修改 2023 - 8 - 24 新增异常事件 pgsql组装函数 终端id 发生当日时间 存储文件路径
void errorlog_pgsql(char* id, QString time, QString filename)
{
	QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_comm_error_tr\"(\"terminal_id\",\"statistical_date\",\"comm_status\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',1,'%3') ").arg(id).arg(time).arg(filename));
	pgsql.append(QString("on conflict(\"terminal_id\",\"statistical_date\") do update set "));
	pgsql.append(QString("\"comm_status\"= \"%1\".\"%2meas_pq_comm_error_tr\".\"comm_status\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << pgsql.toAscii().data() << endl;
}
//zw修改 20240115 新增暂降触发报告记录
void SoeRptSql(char* id, int state,char* rpt)
{
	QDateTime savetime = QDateTime::currentDateTime();

	QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_comm_error_tr\"(\"terminal_id\",\"statistical_date\",\"comm_status\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',%3,'%4') ").arg(id).arg(savetime.toString("yyyyMMdd")).arg(state).arg(rpt));
	pgsql.append(QString("on conflict(\"terminal_id\",\"statistical_date\",\"file_name\") do update set "));
	pgsql.append(QString("\"comm_status\"= %1;").arg(state));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
}
#endif

//zw修改 2023 - 8 - 18 新增异常事件 json组装函数 终端id 终端ip 终端端口 日志来源 异常类别
void errorlog_json(char* id,char* ip,int port,int type,char* error_type,char* ERROR_DES,char* ERROR_PARAM)
{
	if (id == NULL || ip == NULL || port == NULL || type == NULL || error_type == NULL) {
		cout << "Function errorlog_json Error!" << endl;
	}
	QString json;//待组装的json日志
	json.append("{");
	json.append(QString("\"TERMINAL_ID\": \"%1\",").arg(id));//装置ID
	json.append(QString("\"COMM_TIME\": \"%1\",").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));//发生时间
	json.append(QString("\"TMNL_IP\": \"%1\",").arg(ip));//终端IP
	json.append(QString("\"TMNL_PORT\": \"%1\",").arg(port));//终端端口号
	json.append(QString("\"COMM_TYPE\": \"%1\",").arg(type));//日志来源
	json.append(QString("\"ERROR_TYPE\": \"%1\",").arg(error_type));//异常类别
	json.append(QString("\"ERROR_DES\": \"%1\",").arg(ERROR_DES));//错误描述
	json.append(QString("\"ERROR_PARAM\": \"%1\"").arg(ERROR_PARAM));//关键参数
	json.append("}");
	cout << json.toAscii().data() << endl;

	QDateTime savetime = QDateTime::currentDateTime();
	QString Qfilename, Qsavename;
	Qfilename.append("comtrade/").append(id).append("/").append(savetime.toString("yyyyMMdd")).append("/").append(savetime.toString("yyyyMMddhhmmss")).append("_COMM.log");
	Qsavename.append("/FeProject/dat/").append(id).append("_").append(savetime.toString("yyyyMMddhhmmss")).append("_COMM.log");
	char file_name[256];
	memset(file_name, 0, 256);
	sprintf(file_name, "%s", Qfilename.toAscii().data());
	char save_name[256];
	memset(save_name, 0, 256);
	sprintf(save_name, "%s", Qsavename.toAscii().data());
	//cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;

	oss_data_t OssData;
	OssData.filename = file_name;
	OssData.savename = save_name;
	OssData.data = json;

	OssData.id =  QString(id);
	OssData.time = savetime.toString("yyyyMMdd");  //时间
	OssData.log_name = "comm";

	oss_data_list_mutex.lock(); //加锁
	oss_data_list.append(OssData); //添加 kafka发送链表
	oss_data_list_mutex.unlock(); //解锁
	//std::ofstream file(save_name); // 创建一个输出文件流对象，打开文件 example.txt
	//if (file.is_open()) { // 判断文件是否成功打开
	//	file << json.toAscii().data() << "\n";
	//	file.close(); // 关闭文件
	//}
	//else {
	//	std::cerr << "Unable to open file\n";
	//}

	//PutOSS(file_name, save_name);
	//std::remove(save_name);

	//errorlog_pgsql(id, savetime.toString("yyyyMMdd"), Qfilename);
}
//zw修改 2023 - 8 - 23 数值合理性判断函数 节点属性 实际值 电压等级 存储map
void errorlog_num(CDataValue* pDataValue, double value, double UL, QMap<QString, MP_RATIONALITY*> *map_list,long long time)
{
	if(pDataValue == NULL)
	{
		cout << "Function errorlog_num Error!" <<endl;
		return;
	}
	//cout << pDataValue->LimitUp.toAscii().data() << pDataValue->LimitDown.toAscii().data() << endl;
	if (pDataValue->LimitUp != "not define" && pDataValue->LimitDown != "not define" && UL != 0)//zw修改 2023-8-23 数据合理性判断
	{
		double limitup = 0, limitdown = 0;
		if (pDataValue->LimitUp.indexOf("*%UN") != -1)
		{
			QString tmp = pDataValue->LimitUp;
			float temp = tmp.replace("*%UN", "").toFloat();
			limitup = temp * UL;
		}
		else if (pDataValue->LimitUp.indexOf("*%U") != -1)
		{
			QString tmp = pDataValue->LimitUp;
			float temp = tmp.replace("*%U", "").toFloat();
			limitup = (temp * UL) / 1.732f;
		}
		else
		{
			limitup = pDataValue->LimitUp.toFloat();
		}
		if (pDataValue->LimitDown.indexOf("*%UN") != -1)
		{
			QString tmp = pDataValue->LimitDown;
			float temp = tmp.replace("*%UN", "").toFloat();
			limitdown = temp * UL;
		}
		else if (pDataValue->LimitDown.indexOf("*%U") != -1)
		{
			QString tmp = pDataValue->LimitDown;
			float temp = tmp.replace("*%U", "").toFloat();
			limitdown = (temp * UL) / 1.732f;
		}
		else
		{
			limitdown = pDataValue->LimitDown.toFloat();
		}
		//cout << limitdown << "||||" << limitup << "||||" << UL << endl;
		if (pDataValue->LimitUp != "0" || pDataValue->LimitDown != "0")
		{
			if (value < limitdown || value >limitup)//合理性判断
			{
				if (!map_list->contains(pDataValue->strFullName))
				{
					MP_RATIONALITY* tmp_data = new MP_RATIONALITY();
					tmp_data->fValue = value;
					tmp_data->over_time = 0;
					tmp_data->dtvalue = QDateTime::fromTime_t(time / 1000);

					map_list->insert(pDataValue->strFullName, tmp_data);
				}
				map_list->value(pDataValue->strFullName)->over_time++;
			}
		}
	}
}
//zw修改 2023 - 8 - 23 数值合理性判断 异常数值转换json和pgsql
QString errorlog_num_json(QString monitorId, QMap<QString, MP_RATIONALITY*> map_list)
{
	int count = 0;
	QString log_json;//待生成的json字符串
	QMap<QString, MP_RATIONALITY*> tmp = map_list;
	for (QMap<QString, MP_RATIONALITY*>::iterator it2 = tmp.begin(); it2 != tmp.end(); ++it2)
	{
		count++;
		QString key2 = it2.key();
		MP_RATIONALITY* value2 = it2.value();

		log_json.append("{");
		log_json.append(QString("\"strFullName\":\"%1\", ").arg(key2));//不合理值全称
		log_json.append(QString("\"value\":\"%1\", ").arg(value2->fValue));//不合理值
		log_json.append(QString("\"datetime\":\"%1\"").arg(value2->dtvalue.toString("yyyy-MM-dd hh:mm:ss")));//不合理值发生时间
		log_json.append("}");
	}

	return log_json;
}

///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
#if 0
//2023 9-18 合理性数据 pgsql语句生成
QString errorlog_num_pgsql(QString monitorId, QString datatime, QString filename, int count)
{
	QString log_pqsql;//待生成的pgsql语句
	log_pqsql.append(QString("insert into \"%1\".\"%2meas_pq_measpoint_rationality_tr\"(\"monitor_id\",\"statistical_date\",\"irrat_num\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	log_pqsql.append(QString("values('%1',date'%2',%3,'%4') ").arg(monitorId).arg(datatime).arg(count).arg(filename));
	log_pqsql.append(QString("on conflict(\"monitor_id\",\"statistical_date\") do nothing;"));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(log_pqsql);
	Sql_data_list_mutex.unlock(); //解锁
	return log_pqsql;
}
//zw修改 2023 - 8 - 24 数值完整性判断 单条pgsql插入语句生成 终端id 插入天数2023-08-15 数据时间2023-08-15 19:15:00
QString errorlog_dataintegrity_pgsql(QString time, QString datatime,QString monitorId,bool recallflag)
{
	int num = 480;
	if (data_timespan_list[monitorId]->msspan != 0) {
		num = 1440 / data_timespan_list[monitorId]->msspan;
	}
	QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_measpoint_intact_tr\"(\"monitor_id\",\"statistical_date\",\"exp_num\",\"act_num\",\"value_time\",\"last_value_time\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',480,1,array[TIMESTAMP'%3'],'%4') ").arg(monitorId).arg(time).arg(datatime).arg(datatime));
	pgsql.append(QString("on conflict(\"monitor_id\",\"statistical_date\") do update set "));
	//pgsql.append(QString("\"value_time\"=(array_cat(EXCLUDED.\"value_time\", \"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\"))[:1440] , \"exp_num\" =  %3 , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%4\".\"%5meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(num).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	if (recallflag == true) {
		if (data_timespan_list[monitorId]->msspan != 0) {
			pgsql.append(QString("\"value_time\"= ARRAY_APPEND(\"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\", '%3') , \"exp_num\" =  %4 , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%5\".\"%6meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(datatime).arg(num).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
		}
		else {
			pgsql.append(QString("\"value_time\"= ARRAY_APPEND(\"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\", '%3') , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%4\".\"%5meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(datatime).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
		}
	}
	else {
		pgsql.append(QString("\"value_time\"= ARRAY_APPEND(\"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\", '%3') , \"exp_num\" =  %4 , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%5\".\"%6meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(datatime).arg(num).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	}
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	return pgsql;
}
#endif

//zw修改 2023-8-24 数值完整性判断 保存时间戳
void errorlog_dataintegrity_timespanlist(QString monitorId,long long time)
{
	if (!data_timespan_list.contains(monitorId))//zw修改 计算时间间隔步骤
	{
		Mn_Timespan* mn_tmp = new Mn_Timespan();
		mn_tmp->timespan.append(time);
		data_timespan_list.insert(monitorId, mn_tmp);
	}
	else
	{
		if (data_timespan_list[monitorId]->timespan.count() <= 8) {
			data_timespan_list[monitorId]->timespan.append(time);
		}
	}
}
//zw修改 2023-8-24 数值完整性判断 计算时间间隔
void errorlog_dataintegrity_timespanlist_2(QString monitorId)
{
	if (data_timespan_list[monitorId]->msspan == 0 && data_timespan_list[monitorId]->timespan.count() >= 8) //尝试计算完整性
	{
		int count[10] = {0,0,0,0,0,0,0,0,0,0};
		int tmp_sp = 0;
		qSort(data_timespan_list[monitorId]->timespan.begin(), data_timespan_list[monitorId]->timespan.end());
		for (int i = 1; i < data_timespan_list[monitorId]->timespan.size(); i++) {
			int tmp_ms = data_timespan_list[monitorId]->timespan[i] - data_timespan_list[monitorId]->timespan[i - 1];
			if (tmp_ms >= 30000 && tmp_ms <= 90000) {
				count[0]++;
			}
			else if (tmp_ms >= 90000 && tmp_ms <= 150000) {
				count[1]++;
			}
			else if (tmp_ms >= 150000 && tmp_ms <= 210000) {
				count[2]++;
			}
			else if (tmp_ms >= 210000 && tmp_ms <= 270000) {
				count[3]++;
			}
			else if (tmp_ms >= 270000 && tmp_ms <= 330000) {
				count[4]++;
			}
			else if (tmp_ms >= 330000 && tmp_ms <= 390000) {
				count[5]++;
			}
			else if (tmp_ms >= 390000 && tmp_ms <= 450000) {
				count[6]++;
			}
			else if (tmp_ms >= 450000 && tmp_ms <= 510000) {
				count[7]++;
			}
			else if (tmp_ms >= 510000 && tmp_ms <= 570000) {
				count[8]++;
			}
			else if (tmp_ms >= 570000 && tmp_ms <= 630000) {
				count[9]++;
			}
		}
		for (int i = 0; i < 10; i++) {
			if (count[i] != 0 && count[i] > tmp_sp) {
				tmp_sp = count[i];
				data_timespan_list[monitorId]->msspan = i+1;
			}
		}

	}
}

//zw修改 2023 - 8 - 28 数据匹配率 map记录 数据全称 存储map
void errorlog_datamatch(QString fullname, QMap<QString, QDateTime> *map_list)
{
	if(!map_list->contains(fullname))
	{
		map_list->insert(fullname, QDateTime::currentDateTime());
	}
}

///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
#if 0
//zw修改 2023 - 8 - 25 数值匹配率判断 单条pgsql插入语句生成 终端id 插入天数2023-08-15 基础应有 完整应有 基础实际 完整实际
QString errorlog_datamatch_pgsql(QString id, QString time, int BASE_MAT_NUM,int ADV_MAT_NUM,int BASE_ACT_NUM,int ADV_ACT_NUM,QString filename)
{
	QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_measpoint_match_tr\"(\"monitor_id\",\"statistical_date\",\"base_mat_num\",\"adv_mat_num\",\"base_act_num\",\"adv_act_num\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',%3,%4,%5,%6,'%7') ").arg(id).arg(time).arg(BASE_MAT_NUM).arg(ADV_MAT_NUM).arg(BASE_ACT_NUM).arg(ADV_ACT_NUM).arg(filename));
	pgsql.append(QString("on conflict(\"monitor_id\",\"statistical_date\") do nothing;"));
	//pgsql.append(QString("\"BASE_ACT_NUM\"= %1 , \"ADV_ACT_NUM\"= %2;").arg(BASE_ACT_NUM).arg(ADV_ACT_NUM));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	return pgsql;
}
#endif


//zw修改 2023-8-29 数值匹配率json格式生成
QString errorlog_datamatch_json(QMap<QString, QDateTime> data_match_map_1, QMap<QString, QDateTime> data_match_map_2,long long time)
{
	QString log_json,fullnamelist;//待生成的json字符串
	if (data_match_map_1.count() != 0) {
		for (QMap<QString, QDateTime>::iterator it2 = data_match_map_1.begin(); it2 != data_match_map_1.end(); ++it2) {

			QString key2 = it2.key();
			QDateTime value2 = it2.value();

			fullnamelist.append("\"");
			fullnamelist.append(key2);//不匹配的值全称
			fullnamelist.append("\",");
		}
	}
	if (data_match_map_2.count() != 0) {
		for (QMap<QString, QDateTime>::iterator it2 = data_match_map_2.begin(); it2 != data_match_map_2.end(); ++it2) {

			QString key2 = it2.key();
			QDateTime value2 = it2.value();

			fullnamelist.append("\"");
			fullnamelist.append(key2);//不匹配的值全称
			fullnamelist.append("\",");
		}
	}
	fullnamelist.chop(1);
	log_json.append(QString("{ \"datetime\": \"%1\",").arg(QDateTime::fromTime_t(time / 1000).toString("yyyy-MM-dd hh:mm:ss")));
	log_json.append(QString(" \"LackDataName\": [%1] ").arg(fullnamelist));
	log_json.append("}");
	return log_json;
}

#if 0
bool ParseXMLConfig2(XmlConfig *cfg, list<CTopic*> *ctopiclist,QString path) //解析JiangSu_Config.xml配置文件
{
	//cfg = new XmlConfig();
	//注：①#7#代表通配符，用于通配数据类型 采用8421码，8-CP95 4-最小值 2-最大值 1-平均值
	//    ②%2,50%代表通配符，用于通配谐波数据，采用范围编码，第一个数字表示谐波起始号，第二个数字谐波结束号
	//    ③SEQ=后面的值采用8421码 8-T 4-C 2-B 1-A
	//注：type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件 11-实时SOE事件	
	QString strPhasic[4] = { "A", "B", "C", "T" }; //数组枚举 相别(A-T)
	int nStart = 1, nEnd = 1; //谐波起、止次数
	QString strValueTemp; //临时存放谐波次数字符串  例：%0,49% 或 %2,50%

	//加载JiangSu_Config.xml配置文件
	//QString xml_dir = QString("D:/")+QString("PQD-9k/config/"); //相对路径读取xml失败，此处改用绝对路径！ zl 2018-11-14 15:43:34
	QDomDocument doc;   //新建QDomDocument类对象，它代表一个XML文档
	if ("not define" == path) {
		QString xml_dir = QString("../") + QString("etc/"); //Linux下调试路径
		QFile file(xml_dir + JSON_CONFIG_FN);
		if (!file.open(QIODevice::ReadOnly | QFile::Text)) //以只读方式打开xml
		{
			std::cout << "can't open not define config file" << std::endl;//lnk20250208
			return 0;
		}
		if (!doc.setContent(&file)) //将文件内容读到doc中
		{
			std::cout << "can't read not define config file" << std::endl;//lnk20250208
			file.close();
			return 0;
		}
		file.close();
		cout << "not define xml" << endl;
	}
	else {
		QString tmppath;
		tmppath.append("/FeProject/dat/").append(path).append(".xml");
		QFile file(tmppath);
		if (!file.open(QIODevice::ReadOnly | QFile::Text)) //以只读方式打开xml
		{
			std::cout << "can't open config file" << tmppath.toStdString() <<std::endl;//lnk20250208
			return 0;
		}
		if (!doc.setContent(&file)) //将文件内容读到doc中
		{
			std::cout << "can't read config file" << tmppath.toStdString() <<std::endl;//lnk20250208
			file.close();
			return 0;
		}
		file.close();
		cout << "define xml" << endl;
	}
	//将xml文件内容读到doc中
	QDomNode firstNode = doc.firstChild(); //根节点"JSConfigTemplate"
	QDomElement docElem = doc.documentElement();  //返回根节点元素
	QDomNode n = docElem.firstChild(); //获得doc的第一个节点，即"Topic"
	while (!n.isNull()) //如果Topic节点不为空 
	{
		if (n.isElement())
		{
			QDomElement e = n.toElement(); //将其转换为元素
			QString strTag = e.tagName(); //Topic节点

			if ("Topic" == strTag)//zw修改 2023 - 8 - 14 增加判断 将topic节点和其他节点的解析分离
			{
				CTopic* topic = new CTopic(); //发送主题类指针
				topic->strTopic = e.attribute("name"); //发送主题名
				ctopiclist->push_back(topic); //添加 Kafka发送主题链表

				//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
				if ("Topic" == strTag && ("HISDATA" == topic->strTopic || "RTDATA" == topic->strTopic)) //①读取Topic，HISDATA、RTDATA主题---------------------------------------------------
				{
					QDomNodeList list = e.childNodes(); //获得元素Topic的所有子节点的列表
					for (int i = 0; i < list.count(); i++) //遍历 DataType列表
					{
						QDomNode node = list.at(i); //node1 <DataType>
						if (node.isElement())
						{
							CDataType* dt = new CDataType(); //数据类型指针
							dt->iDataType = node.toElement().attribute("value").toInt(); //数据类型值(1-实时/历史稳态、2-实时/历史闪变、3-实时/历史暂态、4-补招稳态、5-补招闪变、6-补招暂态)
							dt->type = node.toElement().attribute("type"); //参数等级
							dt->BaseFlag0 = 0;
							dt->BaseFlag1 = 0;
							topic->DataTypeList.push_back(dt); //添加 数据类型链表

							QString strTag2 = node.toElement().tagName(); //DataType节点
							if ("DataType" == strTag2) //②读取数据类型DataType
							{
								QDomNodeList list2 = node.childNodes(); //获得元素DataType的所有子节点的列表  
								for (int i2 = 0; i2 < list2.count(); i2++) //遍历 Monitor列表
								{
									QDomNode node2 = list2.at(i2); //node2 <Monitor>
									if (node2.isElement())
									{
										CMonitor* mt = new CMonitor(); //监测点类型指针
										mt->strMonitor = node2.toElement().attribute("name"); //监测点名称 注：该值需要从Rpt解析中获取监测点号
										mt->type = node2.toElement().attribute("type"); //参数等级
										dt->MonitorList.push_back(mt); //添加 监测点链表

										QString strTag3 = node2.toElement().tagName(); //Monitor节点
										if ("Monitor" == strTag3) //③读取监测点Monitor
										{
											QDomNodeList list3 = node2.childNodes(); //获得元素Monitor的所有子节点的列表
											for (int i3 = 0; i3 < list3.count(); i3++) //遍历 Item列表
											{
												QDomNode node3 = list3.at(i3); //node3 <Item>
												if (node3.isElement())
												{
													CItem* it = new CItem(); //数据项类指针
													it->strItemName = node3.toElement().attribute("name"); //FLAG、TIME、V、I、PQ
													it->type = node3.toElement().attribute("type"); //参数等级
													if ("FLAG" == it->strItemName) //剔除标记(1：不剔除，0：剔除，默认剔除)
														it->strItemValue = node3.toElement().attribute("value"); //数据项值
													mt->ItemList.push_back(it); //添加 数据项链表

													QString strTag4 = node3.toElement().tagName(); //Item节点
													if ("Item" == strTag4) //④读取数据项Item
													{
														QDomNodeList list4 = node3.childNodes(); //获得元素Item的所有子节点的列表  
														for (int i4 = 0; i4 < list4.count(); i4++) //遍历 Sequence列表 
														{
															QDomNode node4 = list4.at(i4); //node4 <Sequence>
															if (node4.isElement())
															{
																QString strPhase = node4.toElement().attribute("value"); //相别
																if ("7" == strPhase) //⑤-①读取ABC三相数据
																{
																	for (int n = 0; n < 3; n++) //遍历 相别(ABC三相)
																	{
																		CSequence* sq = new CSequence(); //ABC三相相别类指针
																		sq->strSValue = node4.toElement().attribute("value"); //相别值(7：ABC三相、8：T相)
																		sq->type = node4.toElement().attribute("type"); //参数等级
																		sq->strSeq = strPhasic[n]; //相别赋值  例：A、B、C
																		it->SequenceList.push_back(sq); //添加 相别链表

																		QString strTag5 = node4.toElement().tagName(); //Sequence节点
																		if ("Sequence" == strTag5) //⑤读取相别Sequence
																		{
																			QDomNodeList list5 = node4.childNodes(); //获得元素Sequence的所有子节点的列表
																			for (int i5 = 0; i5 < list5.count(); i5++) //遍历 ABC三相Value列表
																			{
																				QDomNode node5 = list5.at(i5); //node5 <Value>
																				if (node5.isElement())
																				{
																					QDomElement e_Value = node5.toElement(); //将其转换为元素
																					QString strTag6 = e_Value.tagName(); //相别Sequence下 所有DataValue子节点
																					if ("Value" == strTag6) //⑥读取ABC三相Value
																					{
																						QString strDVName = e_Value.attribute("name"); //数据名
																						QString strDAName = e_Value.attribute("DA"); //数据属性名
																						if (strDAName.indexOf("phs*") >= 0) //DA包含"phs*"
																							strDAName = strDAName.replace("*", sq->strSeq); //将DA相别*替换为具体相别(A、B、C)  例：phsA$cVal$mag$f
																						//⑥-①谐波数据读取(ABC三相)-------------------------------------
																						if (strDVName.indexOf("%") >= 0 && strDAName.indexOf("%-") >= 0) //数据名包含% 且 DA包含%-  例：V_%0,49%_MAX
																						{
																							QStringList strHarm1 = strDVName.split('%');
																							if (strHarm1.count() >= 2) //例：V_ | 0,49 | _MAX
																							{
																								strValueTemp = "%" + strHarm1.at(1) + "%"; //例：%0,49%
																								QStringList strHarm2 = strHarm1.at(1).split(','); //例：0,49
																								if (strHarm2.count() >= 2)
																								{
																									nStart = (strHarm2.at(0)).toInt(); //谐波起始次数  例：0
																									nEnd = (strHarm2.at(1)).toInt();   //谐波结束次数  例：49
																								}
																							}

																							QString substring = strDAName.mid(strDAName.indexOf("[") + 1, strDAName.indexOf("]") - strDAName.indexOf("[") - 1);
																							QStringList strDAList1 = substring.split('-');
																							int strDAoffset = (strDAList1.at(1)).toInt();

																							for (int i = nStart; i <= nEnd; i++) //遍历 ABC三相谐波次数
																							{
																								QString strDVNameTemp = strDVName; //临时 数据名
																								QString strDANameTemp = strDAName; //临时 数据属性名
																								CDataValue* dv1 = new CDataValue(); //ABC三相谐波数据值类指针
																								dv1->type = e_Value.attribute("type"); //参数等级
																								if (e_Value.attributes().contains("Coefficient")) {
																									dv1->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																									dv1->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)
																								}
																								dv1->strOffset = e_Value.attribute("Offset"); //起始序号偏移量(字符型)
																								dv1->iOffset = e_Value.attribute("Offset").toInt(); //起始序号偏移量(整型) = 江苏电科院臻迪数据项起始序号 - 装置数据项实际起始序号
																								dv1->DO = e_Value.attribute("DO"); //数据对象名
																								dv1->strName = strDVNameTemp.replace(strValueTemp, QString::number(i + e_Value.attribute("Offset").toInt())); //将数据名中%0,49%替换为具体数字  例：SI_%0,49%变为SI_1
																								dv1->DA = strDANameTemp.replace(substring, QString::number(i - strDAoffset)); //将DA中%-2替换为具体数字  例：phs*Har[1]$mag$f
																								//cout << dv1->strName.toAscii().data() << "--" << dv1->DA.toAscii().data() << " (" << dv1->iOffset << endl;
																								//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																								if (e_Value.attributes().contains("BaseFlag"))
																								{
																									dv1->BaseFlag = e_Value.attribute("BaseFlag");
																									if (dv1->BaseFlag == "1") {
																										dt->BaseFlag1++;
																									}
																									else {
																										dt->BaseFlag0++;
																									}
																								}
																								else
																								{
																									dt->BaseFlag0++;
																									dv1->BaseFlag = "0";
																								}
																								if (e_Value.attributes().contains("LimitUp"))
																								{
																									dv1->LimitUp = e_Value.attribute("LimitUp");
																								}
																								else
																								{
																									dv1->LimitUp = "not define";
																								}
																								if (e_Value.attributes().contains("LimitDown"))
																								{
																									dv1->LimitDown = e_Value.attribute("LimitDown");
																								}
																								else
																								{
																									dv1->LimitDown = "not define";
																								}
																								if (!dv1->DO.isEmpty() && !dv1->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
																									dv1->strFullName = dv1->DO + "$" + dv1->DA;
																								else
																									dv1->strFullName = "not define";
																								sq->DataValueList.push_back(dv1); //添加 数据链表(ABC三相)
																							} //遍历ABC三相谐波次数 结束
																							//continue; //ABC三相谐波次数遍历完成后，继续读取下一节点
																						}
																						else //⑥-②非谐波数据读取(ABC三相)-------------------------------
																						{
																							CDataValue* dv2 = new CDataValue(); //ABC三相非谐波数据值类指针
																							dv2->strName = e_Value.attribute("name"); //数据名                                    
																							dv2->type = e_Value.attribute("type"); //参数等级
																							if (e_Value.attributes().contains("Coefficient")) {
																								dv2->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																								dv2->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)    
																							}                                                                                     
																							dv2->DO = e_Value.attribute("DO"); //数据对象名
																							dv2->DA = strDAName; //数据属性名

																							//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																							if (e_Value.attributes().contains("BaseFlag"))
																							{
																								dv2->BaseFlag = e_Value.attribute("BaseFlag");
																								if (dv2->BaseFlag == "1") {
																									dt->BaseFlag1++;
																								}
																								else {
																									dt->BaseFlag0++;
																								}
																							}
																							else
																							{
																								dt->BaseFlag0++;
																								dv2->BaseFlag = "0";
																							}
																							if (e_Value.attributes().contains("LimitUp"))
																							{
																								dv2->LimitUp = e_Value.attribute("LimitUp");
																							}
																							else
																							{
																								dv2->LimitUp = "not define";
																							}
																							if (e_Value.attributes().contains("LimitDown"))
																							{
																								dv2->LimitDown = e_Value.attribute("LimitDown");
																							}
																							else
																							{
																								dv2->LimitDown = "not define";
																							}
																							if (!e_Value.attribute("PltFlag").isEmpty() && e_Value.attribute("PltFlag") == "True") //长时闪变标识
																								dv2->bPlt = true; //长时闪变标识
																							else
																								dv2->bPlt = false; //短时闪变 或 其他数据

																							if (!dv2->DO.isEmpty() && !dv2->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
																								dv2->strFullName = dv2->DO + "$" + dv2->DA;
																							else
																								dv2->strFullName = "not define";
																							sq->DataValueList.push_back(dv2); //添加 数据链表(ABC三相)
																						}
																					} //读取ABC三相Value 结束
																				} //判断node5为元素 结束
																			} //遍历ABC三相Value列表 结束
																		} //遍历 ABC三相 结束
																	}
																} //⑤-①读取ABC三相数据 结束

																if ("8" == strPhase) //⑤-②读取T相数据
																{
																	CSequence* sq = new CSequence(); //T相相别类指针
																	sq->strSValue = node4.toElement().attribute("value"); //相别值
																	sq->type = node4.toElement().attribute("type"); //参数等级
																	sq->strSeq = strPhasic[3]; //相别赋值
																	it->SequenceList.push_back(sq); //添加 相别链表(T相)

																	QDomNodeList list5 = node4.childNodes(); //获得元素Sequence的所有子节点的列表
																	for (int i5 = 0; i5 < list5.count(); i5++) //遍历 T相Value列表
																	{
																		QDomNode node5 = list5.at(i5); //node5 <Value>
																		if (node5.isElement())
																		{
																			QDomElement e_Value = node5.toElement(); //将其转换为元素
																			QString strTag6 = e_Value.tagName(); //相别Sequence下 所有DataValue子节点
																			if ("Value" == strTag6) //⑥读取T相Value
																			{
																				//⑥-①谐波数据读取(T相)  注：T相没有谐波数据
																				//⑥-②非谐波数据读取(T相)
																				CDataValue* dv2 = new CDataValue(); //T相非谐波数据值类指针
																				dv2->strName = e_Value.attribute("name"); //数据名                                    
																				dv2->type = e_Value.attribute("type"); //参数等级
																				if (e_Value.attributes().contains("Coefficient")) {
																					dv2->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																					dv2->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)   
																				}                                                                                      
																				dv2->DO = e_Value.attribute("DO"); //数据对象名
																				dv2->DA = e_Value.attribute("DA"); //数据属性名

																				//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																				if (e_Value.attributes().contains("BaseFlag"))
																				{
																					dv2->BaseFlag = e_Value.attribute("BaseFlag");
																					if (dv2->BaseFlag == "1") {
																						dt->BaseFlag1++;
																					}
																					else {
																						dt->BaseFlag0++;
																					}
																				}
																				else
																				{
																					dt->BaseFlag0++;
																					dv2->BaseFlag = "0";
																				}
																				if (e_Value.attributes().contains("LimitUp"))
																				{
																					dv2->LimitUp = e_Value.attribute("LimitUp");
																				}
																				else
																				{
																					dv2->LimitUp = "not define";
																				}
																				if (e_Value.attributes().contains("LimitDown"))
																				{
																					dv2->LimitDown = e_Value.attribute("LimitDown");
																				}
																				else
																				{
																					dv2->LimitDown = "not define";
																				}

																				if (!dv2->DO.isEmpty() && !dv2->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
																					dv2->strFullName = dv2->DO + "$" + dv2->DA;
																				else
																					dv2->strFullName = "not define";
																				sq->DataValueList.push_back(dv2); //添加 数据链表(ABC三相)
																			} //读取T相Value 结束
																		} //判断node5为元素 结束
																	} //遍历T相Value列表 结束
																} //⑤-②读取T相数据 结束
															} //判断node4为元素 结束
														} //遍历Sequence列表 结束
													} //读取数据项Item 结束
												} //判断node3为元素 结束
											} //遍历Item列表 结束
										} //读取Monitor节点 结束
									} //判断node2为元素 结束
								} //遍历Monitor列表 结束				
							} //读取数据类型DataType 结束
						} //判断node为元素 结束
					}	//遍历DataType列表 结束
				} //读取Topic节点HISDATA、RTDATA 结束
				else if ("Topic" == strTag && "RTDATASOE" == topic->strTopic) //SOE事件-------------------------------------------------------
				{
					QDomNodeList list = e.childNodes(); //获得元素Topic的所有子节点的列表
					for (int i = 0; i < list.count(); i++) //遍历 DataType列表
					{
						QDomNode node = list.at(i); //node1 <DataType>
						if (node.isElement())
						{
							CDataType* dt = new CDataType(); //数据类型类指针
							dt->iDataType = node.toElement().attribute("value").toInt(); //数据类型值(1-稳态SOE、2-闪变SOE、3-暂态SOE)
							dt->type = node.toElement().attribute("type"); //参数等级
							topic->DataTypeList.push_back(dt); //添加 数据类型链表

							QString strTag2 = node.toElement().tagName(); //DataType节点
							if ("DataType" == strTag2) //②读取数据类型DataType
							{
								QDomNodeList list2 = node.childNodes(); //获得元素DataType的所有子节点的列表  
								for (int i2 = 0; i2 < list2.count(); i2++) //遍历 SOE列表
								{
									QDomNode node2 = list2.at(i2); //node2 <SOE>
									if (node2.isElement())
									{
										CEventData* ed = new CEventData(); //SOE事件类指针
										ed->triggerFlag = node2.toElement().attribute("TriggerFlag"); //SOE触发标识
										ed->DO = node2.toElement().attribute("DO"); //数据对象名
										ed->DA = node2.toElement().attribute("DA"); //数据属性名
										ed->type = node2.toElement().attribute("type"); //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
										if (!ed->DO.isEmpty() && !ed->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
											ed->strFullName = ed->DO + "$" + ed->DA;
										else
											ed->strFullName = "not define";
										dt->SOEList.push_back(ed); //添加 SOE事件链表
									} //判断node2为元素 结束
								} //遍历SOE列表 结束
							} //读取数据类型DataType节点 结束						
						} //判断node为元素 结束
					}	//遍历DataType列表 结束	
				} //Topic节点RTDATASOE 结束
				else if ("Topic" == strTag && "SOEDATA" == topic->strTopic)
                {
				    QDomNodeList list = e.childNodes(); //获得元素Topic的所有子节点的列表
					for (int i = 0; i < list.count(); i++) //遍历 DataType列表
					{
						QDomNode node = list.at(i); //node1 <DataType>
						if (node.isElement()) 
						{
							CEventData* ed = new CEventData(); //SOE事件类指针
							ed->triggerFlag = node.toElement().attribute("name"); //SOE名称
							ed->DO = node.toElement().attribute("DO"); //数据对象名
							ed->DA = node.toElement().attribute("DA"); //数据属性名
							ed->type = node.toElement().attribute("type"); //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
							if (!ed->DO.isEmpty() && !ed->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
								ed->strFullName = ed->DO + "$" + ed->DA;
							else
								ed->strFullName = "not define";
							//cout << ed->triggerFlag.toAscii().data() << "=====" << ed->strFullName.toAscii().data() << endl;
							cfg->SOEList.push_back(ed);
						}
					}
                }
			}
			if ("ReportMap" == strTag)//zw修改 2023 - 8 - 15 增加判断 将触发报告的解析移至XML 原配置RptLogCfg.ini取消
			{
				//cout << "ReportMap" << endl;
			}
			if ("Topic" != strTag && "ReportMap" != strTag)//zw修改 2023 - 8 - 14 增加判断 新增部分节点解析
			{
				if ("WavePhasic" == strTag)
				{
					cfg->WavePhasicFlag.append(e.attribute("Flag"));
					if (cfg->WavePhasicFlag == "1") {
						cfg->WavePhasicA.append(e.attribute("A"));
						cfg->WavePhasicB.append(e.attribute("B"));
						cfg->WavePhasicC.append(e.attribute("C"));
					}
					
				}
				if ("UnitOfTime" == strTag)
				{
					cfg->UnitOfTimeUnit.append(e.attribute("Unit"));
				}
				if ("ValueOfTime" == strTag)
				{
					cfg->ValueOfTimeUnit.append(e.attribute("Unit"));
				}
				if ("ComtradeFile" == strTag)
				{
					cfg->WaveTimeFlag.append(e.attribute("WaveTimeFlag"));
					//cout << xmlcfg->WaveTimeFlag.toAscii().data() << endl;
				}
				if ("IED" == strTag)
				{
					cfg->IEDname.append(e.attribute("name"));
					//cout << xmlcfg->IEDname.toAscii().data() << endl;
				}
				if ("LDevice" == strTag)
				{
					cfg->LDevicePrefix.append(e.attribute("Prefix"));
					//cout<<xmlcfg->LDevicePrefix.toAscii().data() <<endl;
				}
			}
		} //判断n为元素 结束

		n = n.nextSibling();//获取下一个兄弟节点(HISDATA —> RTDATA —> RTDATASOE)
	} //while (!n.isNull) 结束

	return true;
}
#endif
//lnk2024-8-16 适配角型接线
bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QString path) //解析JiangSu_Config.xml配置文件
{
	//cfg = new XmlConfig();
	//注：①#7#代表通配符，用于通配数据类型 采用8421码，8-CP95 4-最小值 2-最大值 1-平均值
	//    ②%2,50%代表通配符，用于通配谐波数据，采用范围编码，第一个数字表示谐波起始号，第二个数字谐波结束号
	//    ③SEQ=后面的值采用8421码 8-T 4-C 2-B 1-A
	//注：type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件 11-实时SOE事件	
	QString strPhasic[4] = { "A", "B", "C", "T" }; //数组枚举 相别(A-T)
	QString strLine[4] = { "AB", "BC", "CA", "T" }; //lnk2024-8-14数组枚举 角型相别(AB-T)
	int nStart = 1, nEnd = 1; //谐波起、止次数
	QString strValueTemp; //临时存放谐波次数字符串  例：%0,49% 或 %2,50%

	//加载JiangSu_Config.xml配置文件
	//QString xml_dir = QString("D:/")+QString("PQD-9k/config/"); //相对路径读取xml失败，此处改用绝对路径！ zl 2018-11-14 15:43:34
	QDomDocument doc;   //新建QDomDocument类对象，它代表一个XML文档
	if ("not define" == path) {
		QString xml_dir = QString("../") + QString("etc/"); //Linux下调试路径
		QFile file(xml_dir + JSON_CONFIG_FN);
		if (!file.open(QIODevice::ReadOnly | QFile::Text)) //以只读方式打开xml
		{
			return 0;
		}
		if (!doc.setContent(&file)) //将文件内容读到doc中
		{
			file.close();
			return 0;
		}
		file.close();
		cout << "not define xml" << endl;
	}
	else {
		QString tmppath;
		tmppath.append("/FeProject/dat/").append(path).append(".xml");
		QFile file(tmppath);
		if (!file.open(QIODevice::ReadOnly | QFile::Text)) //以只读方式打开xml
		{
			return 0;
		}
		if (!doc.setContent(&file)) //将文件内容读到doc中
		{
			file.close();
			return 0;
		}
		file.close();
		cout << "define xml" << endl;
	}
	//将xml文件内容读到doc中
	QDomNode firstNode = doc.firstChild(); //根节点"JSConfigTemplate"
	QDomElement docElem = doc.documentElement();  //返回根节点元素
	QDomNode n = docElem.firstChild(); //获得doc的第一个节点，即"Topic"
	while (!n.isNull()) //如果Topic节点不为空 
	{
		if (n.isElement())
		{
			QDomElement e = n.toElement(); //将其转换为元素
			QString strTag = e.tagName(); //Topic节点

			if ("Topic" == strTag)//zw修改 2023 - 8 - 14 增加判断 将topic节点和其他节点的解析分离
			{
				CTopic* topic = new CTopic(); //发送主题类指针
				topic->strTopic = e.attribute("name"); //发送主题名
				ctopiclist->push_back(topic); //添加 Kafka发送主题链表

				//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
				if ("Topic" == strTag && ("HISDATA" == topic->strTopic || "RTDATA" == topic->strTopic)) //①读取Topic，HISDATA、RTDATA主题---------------------------------------------------
				{
					QDomNodeList list = e.childNodes(); //获得元素Topic的所有子节点的列表
					for (int i = 0; i < list.count(); i++) //遍历 DataType列表
					{
						QDomNode node = list.at(i); //node1 <DataType>
						if (node.isElement())
						{
							CDataType* dt = new CDataType(); //数据类型指针
							dt->iDataType = node.toElement().attribute("value").toInt(); //数据类型值(1-实时/历史稳态、2-实时/历史闪变、3-实时/历史暂态、4-补招稳态、5-补招闪变、6-补招暂态)
							dt->type = node.toElement().attribute("type"); //参数等级
							dt->BaseFlag0 = 0;
							dt->BaseFlag1 = 0;
							topic->DataTypeList.push_back(dt); //添加 数据类型链表

							QString strTag2 = node.toElement().tagName(); //DataType节点
							if ("DataType" == strTag2) //②读取数据类型DataType
							{
								QDomNodeList list2 = node.childNodes(); //获得元素DataType的所有子节点的列表  
								for (int i2 = 0; i2 < list2.count(); i2++) //遍历 Monitor列表
								{
									QDomNode node2 = list2.at(i2); //node2 <Monitor>
									if (node2.isElement())
									{
										CMonitor* mt = new CMonitor(); //监测点类型指针
										mt->strMonitor = node2.toElement().attribute("name"); //监测点名称 注：该值需要从Rpt解析中获取监测点号
										mt->type = node2.toElement().attribute("type"); //参数等级
										dt->MonitorList.push_back(mt); //添加 监测点链表

										QString strTag3 = node2.toElement().tagName(); //Monitor节点
										if ("Monitor" == strTag3) //③读取监测点Monitor
										{
											QDomNodeList list3 = node2.childNodes(); //获得元素Monitor的所有子节点的列表
											for (int i3 = 0; i3 < list3.count(); i3++) //遍历 Item列表
											{
												QDomNode node3 = list3.at(i3); //node3 <Item>
												if (node3.isElement())
												{
													CItem* it = new CItem(); //数据项类指针
													it->strItemName = node3.toElement().attribute("name"); //FLAG、TIME、V、I、PQ
													it->type = node3.toElement().attribute("type"); //参数等级
													if ("FLAG" == it->strItemName) //剔除标记(1：不剔除，0：剔除，默认剔除)
														it->strItemValue = node3.toElement().attribute("value"); //数据项值
													mt->ItemList.push_back(it); //添加 数据项链表

													QString strTag4 = node3.toElement().tagName(); //Item节点
													if ("Item" == strTag4) //④读取数据项Item
													{
														QDomNodeList list4 = node3.childNodes(); //获得元素Item的所有子节点的列表  
														for (int i4 = 0; i4 < list4.count(); i4++) //遍历 Sequence列表 
														{
															QDomNode node4 = list4.at(i4); //node4 <Sequence>
															if (node4.isElement())
															{
																QString strPhase = node4.toElement().attribute("value"); //相别
																if ((!xml_flag || "V" != it->strItemName) && "7" == strPhase) //⑤-①读取ABC三相数据 //lnk2024-8-14 角型判断
																{
																	for (int n = 0; n < 3; n++) //遍历 相别(ABC三相)
																	{
																		CSequence* sq = new CSequence(); //ABC三相相别类指针
																		sq->strSValue = node4.toElement().attribute("value"); //相别值(7：ABC三相、8：T相)
																		sq->type = node4.toElement().attribute("type"); //参数等级
																		sq->strSeq = strPhasic[n]; //相别赋值  例：A、B、C
																		it->SequenceList.push_back(sq); //添加 相别链表

																		QString strTag5 = node4.toElement().tagName(); //Sequence节点
																		if ("Sequence" == strTag5) //⑤读取相别Sequence
																		{
																			QDomNodeList list5 = node4.childNodes(); //获得元素Sequence的所有子节点的列表
																			for (int i5 = 0; i5 < list5.count(); i5++) //遍历 ABC三相Value列表
																			{
																				QDomNode node5 = list5.at(i5); //node5 <Value>
																				if (node5.isElement())
																				{
																					QDomElement e_Value = node5.toElement(); //将其转换为元素
																					QString strTag6 = e_Value.tagName(); //相别Sequence下 所有DataValue子节点
																					if ("Value" == strTag6) //⑥读取ABC三相Value
																					{
																						QString strDVName = e_Value.attribute("name"); //数据名
																						QString strDAName = e_Value.attribute("DA"); //数据属性名
																						
																						
																						if (strDAName.indexOf("l_phs*") >= 0){ //DA包含"l_phs*"//lnk20250221星形接线也可以接受PPV
																							strDAName = strDAName.replace("l_phs", "phs");
																							strDAName = strDAName.replace("*", strLine[n]);
																							//qDebug() << "strDAName:" << strDAName << endl;//调试用
																						} //将DA相别*替换为具体相别(AB、BC、CA)  例：phsAB$cVal$mag$f

																						else if (strDAName.indexOf("phs*") >= 0) {//DA包含"phs*"
																							strDAName = strDAName.replace("*", sq->strSeq);} //将DA相别*替换为具体相别(A、B、C)  例：phsA$cVal$mag$f
																							
																							//⑥-①谐波数据读取(ABC三相)-------------------------------------
																						if (strDVName.indexOf("%") >= 0 && strDAName.indexOf("%-") >= 0) //数据名包含% 且 DA包含%-  例：V_%0,49%_MAX
																						{
																							QStringList strHarm1 = strDVName.split('%');
																							if (strHarm1.count() >= 2) //例：V_ | 0,49 | _MAX
																							{
																								strValueTemp = "%" + strHarm1.at(1) + "%"; //例：%0,49%
																								QStringList strHarm2 = strHarm1.at(1).split(','); //例：0,49
																								if (strHarm2.count() >= 2)
																								{
																									nStart = (strHarm2.at(0)).toInt(); //谐波起始次数  例：0
																									nEnd = (strHarm2.at(1)).toInt();   //谐波结束次数  例：49
																								}
																							}

																							QString substring = strDAName.mid(strDAName.indexOf("[") + 1, strDAName.indexOf("]") - strDAName.indexOf("[") - 1);
																							QStringList strDAList1 = substring.split('-');
																							int strDAoffset = (strDAList1.at(1)).toInt();

																							for (int i = nStart; i <= nEnd; i++) //遍历 ABC三相谐波次数
																							{
																								QString strDVNameTemp = strDVName; //临时 数据名
																								QString strDANameTemp = strDAName; //临时 数据属性名
																								CDataValue* dv1 = new CDataValue(); //ABC三相谐波数据值类指针
																								dv1->type = e_Value.attribute("type"); //参数等级
																								if (e_Value.attributes().contains("Coefficient")) {
																									dv1->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																									dv1->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)
																								}
																								dv1->strOffset = e_Value.attribute("Offset"); //起始序号偏移量(字符型)
																								dv1->iOffset = e_Value.attribute("Offset").toInt(); //起始序号偏移量(整型) = 江苏电科院臻迪数据项起始序号 - 装置数据项实际起始序号
																								dv1->DO = e_Value.attribute("DO"); //数据对象名
																								dv1->strName = strDVNameTemp.replace(strValueTemp, QString::number(i + e_Value.attribute("Offset").toInt())); //将数据名中%0,49%替换为具体数字  例：SI_%0,49%变为SI_1
																								dv1->DA = strDANameTemp.replace(substring, QString::number(i - strDAoffset)); //将DA中%-2替换为具体数字  例：phs*Har[1]$mag$f
																								//cout << dv1->strName.toAscii().data() << "--" << dv1->DA.toAscii().data() << " (" << dv1->iOffset << endl;
																								//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																								if (e_Value.attributes().contains("BaseFlag"))
																								{
																									dv1->BaseFlag = e_Value.attribute("BaseFlag");
																									if (dv1->BaseFlag == "1") {
																										dt->BaseFlag1++;
																									}
																									else {
																										dt->BaseFlag0++;
																									}
																								}
																								else
																								{
																									dt->BaseFlag0++;
																									dv1->BaseFlag = "0";
																								}
																								if (e_Value.attributes().contains("LimitUp"))
																								{
																									dv1->LimitUp = e_Value.attribute("LimitUp");
																								}
																								else
																								{
																									dv1->LimitUp = "not define";
																								}
																								if (e_Value.attributes().contains("LimitDown"))
																								{
																									dv1->LimitDown = e_Value.attribute("LimitDown");
																								}
																								else
																								{
																									dv1->LimitDown = "not define";
																								}
																								if (!dv1->DO.isEmpty() && !dv1->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
																									dv1->strFullName = dv1->DO + "$" + dv1->DA;
																								else
																									dv1->strFullName = "not define";
																								sq->DataValueList.push_back(dv1); //添加 数据链表(ABC三相)
																							} //遍历ABC三相谐波次数 结束
																							//continue; //ABC三相谐波次数遍历完成后，继续读取下一节点
																						}
																						else //⑥-②非谐波数据读取(ABC三相)-------------------------------
																						{
																							CDataValue* dv2 = new CDataValue(); //ABC三相非谐波数据值类指针
																							dv2->strName = e_Value.attribute("name"); //数据名                                    
																							dv2->type = e_Value.attribute("type"); //参数等级
																							if (e_Value.attributes().contains("Coefficient")) {
																								dv2->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																								dv2->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)    
																							}                                                                                     
																							dv2->DO = e_Value.attribute("DO"); //数据对象名
																							dv2->DA = strDAName; //数据属性名

																							//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																							if (e_Value.attributes().contains("BaseFlag"))
																							{
																								dv2->BaseFlag = e_Value.attribute("BaseFlag");
																								if (dv2->BaseFlag == "1") {
																									dt->BaseFlag1++;
																								}
																								else {
																									dt->BaseFlag0++;
																								}
																							}
																							else
																							{
																								dt->BaseFlag0++;
																								dv2->BaseFlag = "0";
																							}
																							if (e_Value.attributes().contains("LimitUp"))
																							{
																								dv2->LimitUp = e_Value.attribute("LimitUp");
																							}
																							else
																							{
																								dv2->LimitUp = "not define";
																							}
																							if (e_Value.attributes().contains("LimitDown"))
																							{
																								dv2->LimitDown = e_Value.attribute("LimitDown");
																							}
																							else
																							{
																								dv2->LimitDown = "not define";
																							}
																							if (!e_Value.attribute("PltFlag").isEmpty() && e_Value.attribute("PltFlag") == "True") //长时闪变标识
																								dv2->bPlt = true; //长时闪变标识
																							else
																								dv2->bPlt = false; //短时闪变 或 其他数据

																							if (!dv2->DO.isEmpty() && !dv2->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
																								dv2->strFullName = dv2->DO + "$" + dv2->DA;
																							else
																								dv2->strFullName = "not define";
																							sq->DataValueList.push_back(dv2); //添加 数据链表(ABC三相)
																						}
																					} //读取ABC三相Value 结束
																				} //判断node5为元素 结束
																			} //遍历ABC三相Value列表 结束
																		} //遍历 ABC三相 结束
																	}
																} //⑤-①读取ABC三相数据 结束

																if (xml_flag && "V" == it->strItemName && "112" == strPhase) //lnk2024-8-13角型
																{
																	for (int n = 0; n < 3; n++) //遍历 相别(AB、BC、CA三相)
																	{
																		CSequence* sq = new CSequence(); //AB、BC、CA三相别类指针
																		sq->strSValue = node4.toElement().attribute("value"); //相别值(7：ABC三相、112:线AB,BC,CA 8：T相)
																		sq->type = node4.toElement().attribute("type"); //参数等级
																		sq->strSeq = strLine[n]; //相别赋值  例：AB、BC、CA
																		it->SequenceList.push_back(sq); //添加 相别链表

																		QString strTag5 = node4.toElement().tagName(); //Sequence节点
																		if ("Sequence" == strTag5) //⑤读取相别Sequence
																		{
																			QDomNodeList list5 = node4.childNodes(); //获得元素Sequence的所有子节点的列表
																			for (int i5 = 0; i5 < list5.count(); i5++) //遍历 AB、BC、CA三相Value列表
																			{
																				QDomNode node5 = list5.at(i5); //node5 <Value>
																				if (node5.isElement())
																				{
																					QDomElement e_Value = node5.toElement(); //将其转换为元素
																					QString strTag6 = e_Value.tagName(); //相别Sequence下 所有DataValue子节点
																					if ("Value" == strTag6) //⑥读取AB、BC、CA三相Value
																					{
																						QString strDVName = e_Value.attribute("name"); //数据名
																						QString strDAName = e_Value.attribute("DA"); //数据属性名
																						if (strDAName.indexOf("phs*") >= 0) //DA包含"phs*"
																							strDAName = strDAName.replace("*", sq->strSeq); //将DA相别*替换为具体相别(AB、BC、CA)  例：phsAB$cVal$mag$f
																						//⑥-①谐波数据读取(AB、BC、CA三相)-------------------------------------
																						if (strDVName.indexOf("%") >= 0 && strDAName.indexOf("%-") >= 0) //数据名包含% 且 DA包含%-  例：V_%0,49%_MAX
																						{
																							QStringList strHarm1 = strDVName.split('%');
																							if (strHarm1.count() >= 2) //例：%0,49%
																							{
																								strValueTemp = "%" + strHarm1.at(1) + "%"; //例：%0,49%
																								QStringList strHarm2 = strHarm1.at(1).split(','); //例：0,49
																								if (strHarm2.count() >= 2)
																								{
																									nStart = (strHarm2.at(0)).toInt(); //谐波起始次数  例：0
																									nEnd = (strHarm2.at(1)).toInt();    //谐波结束次数  例：49
																								}
																							}

																							QString substring = strDAName.mid(strDAName.indexOf("[") + 1, strDAName.indexOf("]") - strDAName.indexOf("[") - 1);
																							QStringList strDAList1 = substring.split('-');
																							int strDAoffset = (strDAList1.at(1)).toInt();

																							for (int i = nStart; i <= nEnd; i++) //遍历 AB、BC、CA三相谐波次数
																							{
																								QString strDVNameTemp = strDVName; //临时 数据名
																								QString strDANameTemp = strDAName;//临时 数据属性名
																								CDataValue* dv1 = new CDataValue(); //AB、BC、CA三相谐波数据值类指针
																								dv1->type = e_Value.attribute("type"); //参数等级
																								if (e_Value.attributes().contains("Coefficient")) {
																									dv1->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																									dv1->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)
																								}
																								dv1->strOffset = e_Value.attribute("Offset"); //起始序号偏移量(字符型)
																								dv1->iOffset = e_Value.attribute("Offset").toInt(); //起始序号偏移量(整型) = 江苏电科院臻迪数据项起始序号 - 装置数据项实际起始序号
																								dv1->DO = e_Value.attribute("DO"); //数据对象名

																								std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
																								std::cout << dv1->DO.toUtf8().constData() << std::endl;	//lnk 输出ppv
																								std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;

																								dv1->strName = strDVNameTemp.replace(strValueTemp, QString::number(i + e_Value.attribute("Offset").toInt())); //将数据名中%0,49%替换为具体数字  例：SI_%0,49%变为SI_1
																								dv1->DA = strDANameTemp.replace(substring, QString::number(i - strDAoffset)); //将DA中%-2替换为具体数字  例：phs*Har[1]$mag$f
																								//cout << dv1->strName.toAscii().data() << "--" << dv1->DA.toAscii().data() << " (" << dv1->iOffset << endl;
																								//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																								if (e_Value.attributes().contains("BaseFlag"))
																								{
																									dv1->BaseFlag = e_Value.attribute("BaseFlag");
																									if (dv1->BaseFlag == "1") {
																										dt->BaseFlag1++;
																									}
																									else {
																										dt->BaseFlag0++;
																									}
																								}
																								else
																								{
																									dt->BaseFlag0++;
																									dv1->BaseFlag = "0";
																								}
																								if (e_Value.attributes().contains("LimitUp"))
																								{
																									dv1->LimitUp = e_Value.attribute("LimitUp");
																								}
																								else
																								{
																									dv1->LimitUp = "not define";
																								}
																								if (e_Value.attributes().contains("LimitDown"))
																								{
																									dv1->LimitDown = e_Value.attribute("LimitDown");
																								}
																								else
																								{
																									dv1->LimitDown = "not define";
																								}
																								if (!dv1->DO.isEmpty() && !dv1->DA.isEmpty()) //数据对象名和数据属性名均不为空                                
																									dv1->strFullName = dv1->DO + "$" + dv1->DA;
																								else
																									dv1->strFullName = "not define";
																								sq->DataValueList.push_back(dv1); //添加 数据链表(AB、BC、CA三相)
																							} //遍历ABC三相谐波次数 结束
																							//continue; //AB、BC、CA三相谐波次数遍历完成后，继续读取下一节点
																						}
																						else //⑥-②非谐波数据读取(AB、BC、CA三相)-------------------------------
																						{
																							CDataValue* dv2 = new CDataValue(); //ABC三相非谐波数据值类指针
																							dv2->strName = e_Value.attribute("name"); //数据名       
																							dv2->type = e_Value.attribute("type"); //参数等级
																							if (e_Value.attributes().contains("Coefficient")) {
																								dv2->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																								dv2->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型) 
																							}
																							dv2->DO = e_Value.attribute("DO"); //数据对象名
																							dv2->DA = strDAName; //数据属性名

																							//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																							if (e_Value.attributes().contains("BaseFlag"))
																							{
																								dv2->BaseFlag = e_Value.attribute("BaseFlag");
																								if (dv2->BaseFlag == "1") {
																									dt->BaseFlag1++;
																								}
																								else {
																									dt->BaseFlag0++;
																								}
																							}
																							else
																							{
																								dt->BaseFlag0++;
																								dv2->BaseFlag = "0";
																							}
																							if (e_Value.attributes().contains("LimitUp"))
																							{
																								dv2->LimitUp = e_Value.attribute("LimitUp");
																							}
																							else
																							{
																								dv2->LimitUp = "not define";
																							}
																							if (e_Value.attributes().contains("LimitDown"))
																							{
																								dv2->LimitDown = e_Value.attribute("LimitDown");
																							}
																							else
																							{
																								dv2->LimitDown = "not define";
																							}
																							if (!e_Value.attribute("PltFlag").isEmpty() && e_Value.attribute("PltFlag") == "True") //长时闪变标识
																								dv2->bPlt = true; //长时闪变标识
																							else
																								dv2->bPlt = false;//短时闪变 或 其他数据

																							if (!dv2->DO.isEmpty() && !dv2->DA.isEmpty()) //数据对象名和数据属性名均不为空                
																								dv2->strFullName = dv2->DO + "$" + dv2->DA;
																							else
																								dv2->strFullName = "not define";
																							sq->DataValueList.push_back(dv2); //添加 数据链表(AB、BC、CA三相)
																						}
																					} //读取AB、BC、CA三相Value 结束
																				}//判断node5为元素 结束
																			}  //遍历AB、BC、CA三相Value列表 结束
																		} //遍历 AB、BC、CA三相 结束
																	}
																}//⑤-①读取AB、BC、CA三相数据 结束

																if ("8" == strPhase) //⑤-②读取T相数据
																{
																	CSequence* sq = new CSequence(); //T相相别类指针
																	sq->strSValue = node4.toElement().attribute("value"); //相别值
																	sq->type = node4.toElement().attribute("type"); //参数等级
																	sq->strSeq = strPhasic[3]; //相别赋值
																	it->SequenceList.push_back(sq); //添加 相别链表(T相)

																	QDomNodeList list5 = node4.childNodes(); //获得元素Sequence的所有子节点的列表
																	for (int i5 = 0; i5 < list5.count(); i5++) //遍历 T相Value列表
																	{
																		QDomNode node5 = list5.at(i5); //node5 <Value>
																		if (node5.isElement())
																		{
																			QDomElement e_Value = node5.toElement(); //将其转换为元素
																			QString strTag6 = e_Value.tagName(); //相别Sequence下 所有DataValue子节点
																			if ("Value" == strTag6) //⑥读取T相Value
																			{
																				//⑥-①谐波数据读取(T相)  注：T相没有谐波数据
																				//⑥-②非谐波数据读取(T相)
																				CDataValue* dv2 = new CDataValue(); //T相非谐波数据值类指针
																				dv2->strName = e_Value.attribute("name"); //数据名                                    
																				dv2->type = e_Value.attribute("type"); //参数等级
																				if (e_Value.attributes().contains("Coefficient")) {
																					dv2->strCoefficient = e_Value.attribute("Coefficient"); //数据系数(字符型)
																					dv2->fCoefficient = e_Value.attribute("Coefficient").toFloat(); //数据系数(浮点型)   
																				}                                                                                      
																				dv2->DO = e_Value.attribute("DO"); //数据对象名
																				dv2->DA = e_Value.attribute("DA"); //数据属性名

																				//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
																				if (e_Value.attributes().contains("BaseFlag"))
																				{
																					dv2->BaseFlag = e_Value.attribute("BaseFlag");
																					if (dv2->BaseFlag == "1") {
																						dt->BaseFlag1++;
																					}
																					else {
																						dt->BaseFlag0++;
																					}
																				}
																				else
																				{
																					dt->BaseFlag0++;
																					dv2->BaseFlag = "0";
																				}
																				if (e_Value.attributes().contains("LimitUp"))
																				{
																					dv2->LimitUp = e_Value.attribute("LimitUp");
																				}
																				else
																				{
																					dv2->LimitUp = "not define";
																				}
																				if (e_Value.attributes().contains("LimitDown"))
																				{
																					dv2->LimitDown = e_Value.attribute("LimitDown");
																				}
																				else
																				{
																					dv2->LimitDown = "not define";
																				}

																				if (!dv2->DO.isEmpty() && !dv2->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
																					dv2->strFullName = dv2->DO + "$" + dv2->DA;
																				else
																					dv2->strFullName = "not define";
																				sq->DataValueList.push_back(dv2); //添加 数据链表(ABC三相)
																			} //读取T相Value 结束
																		} //判断node5为元素 结束
																	} //遍历T相Value列表 结束
																} //⑤-②读取T相数据 结束
															} //判断node4为元素 结束
														} //遍历Sequence列表 结束
													} //读取数据项Item 结束
												} //判断node3为元素 结束
											} //遍历Item列表 结束
										} //读取Monitor节点 结束
									} //判断node2为元素 结束
								} //遍历Monitor列表 结束				
							} //读取数据类型DataType 结束
						} //判断node为元素 结束
					}	//遍历DataType列表 结束
				} //读取Topic节点HISDATA、RTDATA 结束
				else if ("Topic" == strTag && "RTDATASOE" == topic->strTopic) //SOE事件-------------------------------------------------------
				{
					QDomNodeList list = e.childNodes(); //获得元素Topic的所有子节点的列表
					for (int i = 0; i < list.count(); i++) //遍历 DataType列表
					{
						QDomNode node = list.at(i); //node1 <DataType>
						if (node.isElement())
						{
							CDataType* dt = new CDataType(); //数据类型类指针
							dt->iDataType = node.toElement().attribute("value").toInt(); //数据类型值(1-稳态SOE、2-闪变SOE、3-暂态SOE)
							dt->type = node.toElement().attribute("type"); //参数等级
							topic->DataTypeList.push_back(dt); //添加 数据类型链表

							QString strTag2 = node.toElement().tagName(); //DataType节点
							if ("DataType" == strTag2) //②读取数据类型DataType
							{
								QDomNodeList list2 = node.childNodes(); //获得元素DataType的所有子节点的列表  
								for (int i2 = 0; i2 < list2.count(); i2++) //遍历 SOE列表
								{
									QDomNode node2 = list2.at(i2); //node2 <SOE>
									if (node2.isElement())
									{
										CEventData* ed = new CEventData(); //SOE事件类指针
										ed->triggerFlag = node2.toElement().attribute("TriggerFlag"); //SOE触发标识
										ed->DO = node2.toElement().attribute("DO"); //数据对象名
										ed->DA = node2.toElement().attribute("DA"); //数据属性名
										ed->type = node2.toElement().attribute("type"); //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
										if (!ed->DO.isEmpty() && !ed->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
											ed->strFullName = ed->DO + "$" + ed->DA;
										else
											ed->strFullName = "not define";
										dt->SOEList.push_back(ed); //添加 SOE事件链表
									} //判断node2为元素 结束
								} //遍历SOE列表 结束
							} //读取数据类型DataType节点 结束						
						} //判断node为元素 结束
					}	//遍历DataType列表 结束	
				} //Topic节点RTDATASOE 结束
				else if ("Topic" == strTag && "SOEDATA" == topic->strTopic)
                {
				    QDomNodeList list = e.childNodes(); //获得元素Topic的所有子节点的列表
					for (int i = 0; i < list.count(); i++) //遍历 DataType列表
					{
						QDomNode node = list.at(i); //node1 <DataType>
						if (node.isElement()) 
						{
							CEventData* ed = new CEventData(); //SOE事件类指针
							ed->triggerFlag = node.toElement().attribute("name"); //SOE名称
							ed->DO = node.toElement().attribute("DO"); //数据对象名
							ed->DA = node.toElement().attribute("DA"); //数据属性名
							ed->type = node.toElement().attribute("type"); //参数等级type类型：0-DataType 1-监测点 2-剔除标记 3-发生时刻，毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
							if (!ed->DO.isEmpty() && !ed->DA.isEmpty()) //数据对象名和数据属性名均不为空                                              
								ed->strFullName = ed->DO + "$" + ed->DA;
							else
								ed->strFullName = "not define";
							//cout << ed->triggerFlag.toAscii().data() << "=====" << ed->strFullName.toAscii().data() << endl;
							cfg->SOEList.push_back(ed);
						}
					}
                }
			}
			if ("ReportMap" == strTag)//zw修改 2023 - 8 - 15 增加判断 将触发报告的解析移至XML 原配置RptLogCfg.ini取消
			{
				//cout << "ReportMap" << endl;
			}
			if ("Topic" != strTag && "ReportMap" != strTag)//zw修改 2023 - 8 - 14 增加判断 新增部分节点解析
			{
				if ("WavePhasic" == strTag)
				{
					cfg->WavePhasicFlag.append(e.attribute("Flag"));
					if (cfg->WavePhasicFlag == "1") {
						cfg->WavePhasicA.append(e.attribute("A"));
						cfg->WavePhasicB.append(e.attribute("B"));
						cfg->WavePhasicC.append(e.attribute("C"));
					}
					
				}
				if ("UnitOfTime" == strTag)
				{
					cfg->UnitOfTimeUnit.append(e.attribute("Unit"));
				}
				if ("ValueOfTime" == strTag)
				{
					cfg->ValueOfTimeUnit.append(e.attribute("Unit"));
				}
				if ("ComtradeFile" == strTag)
				{
					cfg->WaveTimeFlag.append(e.attribute("WaveTimeFlag"));
					//cout << xmlcfg->WaveTimeFlag.toAscii().data() << endl;
				}
				if ("IED" == strTag)
				{
					cfg->IEDname.append(e.attribute("name"));
					//cout << xmlcfg->IEDname.toAscii().data() << endl;
				}
				if ("LDevice" == strTag)
				{
					cfg->LDevicePrefix.append(e.attribute("Prefix"));
					//cout<<xmlcfg->LDevicePrefix.toAscii().data() <<endl;
				}
			}
		} //判断n为元素 结束

		n = n.nextSibling();//获取下一个兄弟节点(HISDATA —> RTDATA —> RTDATASOE)
	} //while (!n.isNull) 结束

	return true;
}


/// <summary>
/// czy  2023-11-23 测试json的装置间隔频,打印前台
/// </summary>
/// <param name="flag">1是,2是,3是填入计算的interval</param>
/// <param name="interval">1是,2是,3是填入计算的interval</param>
void print_interval(int flag,int interval) {
	if (flag == 1) {
		cout << "interval!!dont't contain mp_id ,interval=1" << endl;
	}
	else if (flag == 2) {
		cout << "interval!!contain mp_id but interval=0, set interval=1" << endl;

	}
	else 
	{
		cout << "interval!!contain mp_id , find interval=" << interval << endl;

	}
}

/// <summary>
/// czy kafka的json中将线电压转成相电压
/// </summary>
/// <param name="pSequence"></param>
/// <returns></returns>
QString line_to_phasic(QString qstrSeq) {
	if (qstrSeq == "A" || qstrSeq == "AB") {
		return "A";
	}
	else if (qstrSeq == "B" || qstrSeq == "BC") {
		return "B";
	}
	else if (qstrSeq == "C" || qstrSeq == "CA") {
		return "C";
	}
	else {
		return qstrSeq;
	}
}

//20250214添加角型接线处理
int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json生成函数 zw修改 2023-8-11 调整传送json结构 目前仅限历史稳态数据
{
	list<CTopic*> ctopic_list;

#if 0
	if (xmlinfo_list.contains(data->dev_type)) {
		cout << "transfer_json_block_data contain data->dev_type" << endl;
		ctopic_list = xmlinfo_list[data->dev_type]->topicList;
	}
	else {
		cout << "transfer_json_block_data not contain data->dev_type" << endl;
		ctopic_list = topicList;
	}
#endif


	////lnk2024-8-15 区分星型,角型接线
	if (strcmp(v_wiring_type, "1") == 0)	//lnk2024-8-15 星型接线
	{
		cout << "1 report v_wiring_type is" << v_wiring_type << endl;
		if (xmlinfo_list.contains(data->dev_type)) {
			cout << "transfer_json_block_data contain data->dev_type" << endl;
			ctopic_list = xmlinfo_list[data->dev_type]->topicList;
		}
		else {
			cout << "transfer_json_block_data not contain data->dev_type:"  << data->dev_type.toStdString()  << "  !!!!"<< endl;
			ctopic_list = topicList;
		}
	}
	else	//lnk2024-8-15 角型接线
	{
		cout << "2 report v_wiring_type is" << v_wiring_type << endl;
		if (xmlinfo_list2.contains(data->dev_type)) {
			cout << "transfer_json_block_data contain data->dev_type" << endl;
			ctopic_list = xmlinfo_list2[data->dev_type]->topicList;
		}
		else {
			cout << "transfer_json_block_data not contain data->dev_type:"  << data->dev_type.toStdString() << "  !!!!"<< endl;
			ctopic_list = topicList;
		}
	}

	//list<CTopic*>* tmp;
	bool shortjumpflag = false;
	bool longjumpflag = false;
	//zw修改 2023-8-28 新增日志启动判断
	//bool data_match_flag = false, data_integrity_flag = true, data_reason_flag = false;//匹配率 完整性 合理性 日志记录标志
	QMap<QString, MP_RATIONALITY*> data_reason_map;//数据合理性map
	QMap<QString, QDateTime> data_match_map_1;//数据匹配率map 基础数据
	QMap<QString, QDateTime> data_match_map_2;//数据匹配率map 非基础数据
	//zw修改 end
	if (!inited) //初始化 JiangSu_Config.xml
	{
		//ParseXMLConfig(); //调用 ParseXMLConfig() 解析JiangSu_Config.xml配置文件
		inited = true;
	}

	if (NULL == data) //json拼接参数类指针为空
		return 0;

	if (100 == data->func_type) //一、稳态/统计数据 ——> MMS_Client
	{		
		list<CTopic*>::iterator tp = ctopic_list.begin();
		while (tp != ctopic_list.end()) //①遍历 Kafka发送主题链表
		{
			CTopic* pTopic = *tp++;
			if ("HISDATA" == pTopic->strTopic) //Topic等于HISDATA
			{					
				list<CDataType*>::iterator dt = pTopic->DataTypeList.begin(); //②遍历 DataTypeList
				while (dt != pTopic->DataTypeList.end())
				{
					bool isJump = false; //是否跳出(整个数据类型)循环
					CDataType* pDataType = *dt++;

					if (2 == pDataType->iDataType) //②-②历史短闪变数据------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "PST"; //kafka发送主题		
						KafkaData.strText = ""; //kafka发送的json字符串

						long long  time_sec; //时间戳(秒)
						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：历史闪变 "02"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"

						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						int countflag = 0, num = 0;
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("TIME" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻，毫秒
									time_sec = data->time / 1000; //时间戳(秒)
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 F

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									num = num + pSequence->DataValueList.size();
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
										{
											countflag++;
											continue;
										}
											
										if (!data->mms_str_map.contains(pDataValue->strFullName))//确认字典里不含有该key
										{
											isJump = false; //跳出本层循环
											countflag++;
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":%2, ").arg(pDataValue->strName).arg("null")); //拼接
											else
												KafkaData.strText.append(QString("\"%1\":%2 ").arg(pDataValue->strName).arg("null")); //拼接
											continue;
										}

										try
										{
											double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":\"%2\",").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
											else
												KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
										}
										catch (exception& e)
										{
											cout << "历史闪变数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

						cout << countflag << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!send name=\"DATA_TYPE\" value=\"02\" " << num << endl;
						cout << KafkaData.strText.toAscii().data() << endl;
						if (countflag < num) {
							kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
							kafka_data_list_mutex.unlock(); //解锁
							shortjumpflag = true;
						}
					} //②-②历史闪变数据解析结束！--------------------------------

					//20241204长闪变类型应该为3
					if (3 == pDataType->iDataType) //②-②历史长闪变数据------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "PLT"; //kafka发送主题		
						KafkaData.strText = ""; //kafka发送的json字符串

						long long  time_sec; //时间戳(秒)
						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：历史闪变 "02"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"

						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						int countflag = 0,num = 0;
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("TIME" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻，毫秒
									time_sec = data->time / 1000; //时间戳(秒)
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 F

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									num = num + pSequence->DataValueList.size();
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
										{
											countflag++;
											continue;
										}
										if (!data->mms_str_map.contains(pDataValue->strFullName))//确认字典里不含有该key
										{
											isJump = false; //跳出本层循环
											countflag++;
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":%2, ").arg(pDataValue->strName).arg("null")); //拼接
											else
												KafkaData.strText.append(QString("\"%1\":%2 ").arg(pDataValue->strName).arg("null")); //拼接
											continue;
										}

										try
										{
											if (0 == time_sec % 7200) //2小时间隔，长时闪变
											{
												double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
											}
										}
										catch (exception& e)
										{
											cout << "历史闪变数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

						cout<< countflag << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!send name=\"DATA_TYPE\" value=\"04\" " << num << endl;
						cout << KafkaData.strText.toAscii().data() << endl;
						if (countflag < num && 0 == time_sec % 7200) {
							kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
							kafka_data_list_mutex.unlock(); //解锁
							longjumpflag = true;
						}
						if (longjumpflag == true || shortjumpflag == true) {
							return 1;
						}
						//return 1; //结束该函数，停止后续代码执行
					} //②-②历史闪变数据解析结束！--------------------------------

					if (1 == pDataType->iDataType) //②-①历史稳态数据-----------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "HISDATA"; //kafka发送主题		
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10,QChar('0'))); //拼接 json数据类型  例：历史稳态 "01"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"
						
						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						while (mt != pDataType->MonitorList.end())
						{							
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("FLAG" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"FLAG\":%1, ").arg(data->flag)); //拼接 json剔除标记，1不剔除，0剔除，默认剔除
									continue;
								}
								if ("TIME" == pItem->strItemName) //剔除"TIME"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":%1, ").arg(data->time)); //拼接 json发生时刻，毫秒

									if (!data_timespan_list.contains(data->mp_id)) {
										KafkaData.strText.append(QString("\"interval\":%1, ").arg(3)); //拼接 json发生时刻，毫秒
									}
									else if (data_timespan_list[data->mp_id]->msspan == 0)
									{
										KafkaData.strText.append(QString("\"interval\":%1, ").arg(3)); //拼接 json发生时刻，毫秒

									}
									else {
										KafkaData.strText.append(QString("\"interval\":%1, ").arg(data_timespan_list[data->mp_id]->msspan)); //拼接 json发生时刻，毫秒

									}
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 V、I、PQ

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C、T相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
										  continue;
										if (!data->mms_str_map.contains(pDataValue->strFullName))//确认字典里不含有该key
										{
											isJump = false; //跳出本层循环
											//zw修改 2023-8-28 不匹配数据添加
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":%2, ").arg(pDataValue->strName).arg("null")); //拼接
											else
												KafkaData.strText.append(QString("\"%1\":%2 ").arg(pDataValue->strName).arg("null")); //拼接

											if (pDataValue->BaseFlag == "1") {
												//errorlog_datamatch(pDataValue->strFullName, &data_match_map_1);//lnk删除
											}
											else {
												//errorlog_datamatch(pDataValue->strFullName, &data_match_map_2);//lnk删除
											}
											continue;
										}

										try
										{
											if (pDataValue->strFullName.indexOf("$ang$f") != -1) //查找61850属性名中含有相角的定义
											{
												double dAngleTemp = data->mms_str_map.value(pDataValue->strFullName); //角度值(-180度 ~ 180度)
												dAngleTemp = dAngleTemp > 180.0f ? dAngleTemp - 360.0f : dAngleTemp;
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dAngleTemp, 10, 6))); //拼接 json数据值(角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dAngleTemp, 10, 6))); //拼接 json数据值(角度值)
												//zw修改 2023 - 8 - 23 数值合理性判断函数 节点属性 实际值 监测点号 电压等级
												//errorlog_num(pDataValue, dAngleTemp, data->voltage_level, &data_reason_map, data->time);
											}
											else
											{
												double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
												//zw修改 2023 - 8 - 23 数值合理性判断函数 节点属性 实际值 监测点号 电压等级
												//(pDataValue, dTemp, data->voltage_level, &data_reason_map, data->time);
											}
										}
										catch (exception& e)
										{
											cout << "历史稳态数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

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

						//lnk20241122不记录这些
						if(false)//zw修改 2023-8-28 数据完整性 合理性 匹配率 日志记录执行判断逻辑
						{
							cout << "!!!!!!!!!!!!!!!!!!!!!!===============" << data_match_map_1.count() << "--------" << data_match_map_2.count() << endl;
							cout << "!!!!!!!!!!!!!!!!!!!!!!---------------" << data_reason_map.count() << endl;
							if(data_match_map_1.count() + data_match_map_2.count() <= 1200)//完整性记录 默认为true 只要发送了kafka记录就执行
							{
								errorlog_dataintegrity_timespanlist(data->mp_id,data->time);
								errorlog_dataintegrity_timespanlist_2(data->mp_id);
								QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time/1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								QString tmp_chr2 = dataintegrity_time.toString("yyyy-MM-dd hh:mm:ss");
								//不再需要完整性记录lnk202411-6
								//cout << errorlog_dataintegrity_pgsql(tmp_chr1, tmp_chr2, data->mp_id,false).toAscii().data() << endl;
							}
							if(data_reason_map.count() != 0)//合理性记录 只要map存在元素 记录不合理性日志
							{
								QString reasonlog = errorlog_num_json(data->mp_id, data_reason_map);

								QDateTime savetime = QDateTime::fromTime_t(data->time / 1000);
								QString Qfilename, Qsavename;
								Qfilename.append("comtrade/").append(data->mp_id).append("/").append(savetime.toString("yyyyMMdd")).append("/").append(savetime.toString("yyyyMMddhhmmss")).append("_reason.log");
								Qsavename.append("/FeProject/dat/").append(data->mp_id).append("_").append(savetime.toString("yyyyMMddhhmmss")).append("_reason.log");
								char file_name[256];
								memset(file_name, 0, 256);
								sprintf(file_name, "%s", Qfilename.toAscii().data());
								char save_name[256];
								memset(save_name, 0, 256);
								sprintf(save_name, "%s", Qsavename.toAscii().data());
								//cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;
								//cout << reasonlog.toAscii().data() << endl;

								oss_data_t OssData;
								OssData.filename = file_name;
								OssData.savename = save_name;
								OssData.data = reasonlog;

								QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								OssData.id = data->mp_id;
								OssData.time = tmp_chr1;  //时间
								OssData.list_num = data_reason_map.size();
								OssData.log_name = "reason";

								if (data->time % 3600000 == 0) {
									oss_data_list_mutex.lock(); //加锁
									oss_data_list.append(OssData); //添加 kafka发送链表
									oss_data_list_mutex.unlock(); //解锁
								}
								
								//std::ofstream file(save_name); // 创建一个输出文件流对象，打开文件 example.txt
								//if (file.is_open()) { // 判断文件是否成功打开
								//	file << reasonlog.toAscii().data() << "\n";
								//	file.close(); // 关闭文件
								//}
								//else {
								//	cout << "Unable to open file\n" << endl;
								//}

								//PutOSS(file_name, save_name);
								//std::remove(save_name);

								/*QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								QString pgsql;
								pgsql.append(errorlog_num_pgsql(data->mp_id, tmp_chr1, Qfilename, data_reason_map.size()));
								cout << pgsql.toAscii().data() << endl;*/
							}
							if(data_match_map_1.count() != 0 || data_match_map_2.count() != 0)//匹配率记录 只要map存在元素 记录不匹配的数值
							{
								QString matchlog = errorlog_datamatch_json(data_match_map_1, data_match_map_2,data->time);
								//cout << matchlog.toAscii().data() << endl;

								QDateTime savetime = QDateTime::fromTime_t(data->time / 1000);
								QString Qfilename,Qsavename;
								Qfilename.append("comtrade/").append(data->mp_id).append("/").append(savetime.toString("yyyyMMdd")).append("/").append(savetime.toString("yyyyMMddhhmmss")).append("_match.log");
								Qsavename.append("/FeProject/dat/").append(data->mp_id).append("_").append(savetime.toString("yyyyMMddhhmmss")).append("_match.log");
								char file_name[256];
								memset(file_name,0,256);
								sprintf(file_name,"%s",Qfilename.toAscii().data());
								char save_name[256];
								memset(save_name, 0, 256);
								sprintf(save_name,"%s", Qsavename.toAscii().data());
								cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name <<  endl;

								oss_data_t OssData;
								OssData.filename = file_name;
								OssData.savename = save_name;
								OssData.data = matchlog;

								QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								OssData.id = data->mp_id;
								OssData.time= tmp_chr1;  //时间
								//match_log
								OssData.base_mat_num= pDataType->BaseFlag1;
								OssData.adv_mat_num= pDataType->BaseFlag1 + pDataType->BaseFlag0;
								OssData.base_act_num= pDataType->BaseFlag1 - data_match_map_1.count();
								OssData.adv_act_num= pDataType->BaseFlag1 + pDataType->BaseFlag0 - data_match_map_1.count() - data_match_map_2.count();
								OssData.log_name = "match";

								if (data->time % 3600000 == 0) {
									oss_data_list_mutex.lock(); //加锁
									oss_data_list.append(OssData); //添加 kafka发送链表
									oss_data_list_mutex.unlock(); //解锁
								}
								//std::ofstream file(save_name); // 创建一个输出文件流对象，打开文件 example.txt
								//if (file.is_open()) { // 判断文件是否成功打开
								//	file << matchlog.toAscii().data() << "\n";
								//	file.close(); // 关闭文件
								//}
								//else {
								//	cout << "Unable to open file\n" << endl;
								//}

								//PutOSS(file_name, save_name);
								//std::remove(save_name);
								//GetOSS(file_name, savename);
								/*QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");

								QString pqsql;
								pqsql.append(errorlog_datamatch_pgsql(data->mp_id, tmp_chr1, pDataType->BaseFlag1, pDataType->BaseFlag1 + pDataType->BaseFlag0, pDataType->BaseFlag1 - data_match_map_1.count(), pDataType->BaseFlag1 + pDataType->BaseFlag0 - data_match_map_1.count() - data_match_map_2.count(), Qfilename));
								cout << pqsql.toAscii().data() << endl;*/
								
							}
							QMap<QString, QDateTime>().swap(data_match_map_1);
							QMap<QString, QDateTime>().swap(data_match_map_2);
							QMap<QString, MP_RATIONALITY*>().swap(data_reason_map);
						}
						return 1; //结束该函数，停止后续代码执行
					} //②-①历史稳态数据解析结束！--------------------------------
				} //DataTypeList 结束
			} //遍历 HISDATA 结束！
		} //TopicList 结束
	} //一、结束

	if (200 == data->func_type) //二、3秒数据/实时数据 ——> MMS_Assist
	{		
		list<CTopic*>::iterator tp = ctopic_list.begin();
		while (tp != ctopic_list.end()) //①遍历 Kafka发送主题链表
		{			
			CTopic* pTopic = *tp++;
			if ("RTDATA" == pTopic->strTopic) //Topic等于RTDATA------------------------------------------------------------
			{
				list<CDataType*>::iterator dt = pTopic->DataTypeList.begin(); //②遍历 DataTypeList
				while (dt != pTopic->DataTypeList.end())
				{
					bool isJump = false; //是否跳出(整个数据类型)循环
					CDataType* pDataType = *dt++;
					if (1 == pDataType->iDataType) //②-①实时3s数据--------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATA"; //kafka发送主题	
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：实时稳态 "01"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"
						
						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("FLAG" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"FLAG\":\"%1\", ").arg(data->flag)); //拼接 json剔除标记，1不剔除，0剔除，默认剔除
									continue;
								}
								if ("TIME" == pItem->strItemName) //剔除"TIME"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻，毫秒
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 V、I、PQ

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C、T相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
											continue;
										if (!data->mms_str_map.contains(pDataValue->strFullName) && pDataValueBegin->strName == pDataValue->strName)//确认字典里不含有该key
										{
											isJump = true; //跳出本层循环
											break;
										}

										try
										{
											if (pDataValue->strFullName.indexOf("$ang$f") != -1) //查找61850属性名中含有相角的定义
											{
												double dAngleTemp = data->mms_str_map.value(pDataValue->strFullName); //角度值(-180度 ~ 180度)
												dAngleTemp = dAngleTemp > 180.0f ? dAngleTemp - 360.0f : dAngleTemp;
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dAngleTemp, 10, 6))); //拼接 json数据值(角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dAngleTemp, 10, 6))); //拼接 json数据值(角度值)
											}
											else
											{
												double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
											}
										}
										catch (exception& e)
										{
											cout << "实时3s数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-①实时3s数据解析结束！----------------------------------

					if (2 == pDataType->iDataType) //②-②实时闪变数据-----------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATA"; //kafka发送主题	
						KafkaData.strText = ""; //kafka发送的json字符串

						long long  time_sec; //时间戳(秒)
						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：实时闪变 "02"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"

						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("TIME" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻，毫秒
									time_sec = data->time / 1000; //时间戳(秒)
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 F

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
											continue;
										if (!data->mms_str_map.contains(pDataValue->strFullName) && pDataValueBegin->strName == pDataValue->strName)//确认字典里不含有该key
										{
											isJump = true; //跳出本层循环
											break;
										}

										try
										{
											if (!pDataValue->bPlt) //短时闪变
											{
												double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
											}
											else //长时闪变
											{
												if (0 == time_sec % 7200) //2小时间隔，长时闪变
												{
													double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
													if (dv != dvEnd) //非单相最后一个数据值元素
														KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
													else
														KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
												}
											}
										}
										catch (exception& e)
										{
											cout << "实时闪变数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-②实时闪变数据解析结束！--------------------------------
				} //DataTypeList 结束
			} //遍历 RTDATA 结束！

			if ("RTDATASOE" == pTopic->strTopic) //Topic等于RTDATASOE----------------------------------------------------------
			{
				list<CDataType*>::iterator dt = pTopic->DataTypeList.begin(); //②遍历 DataTypeList
				while (dt != pTopic->DataTypeList.end())
				{
					int triggerCount = 0; //SOE触发标识计数
					CDataType* pDataType = *dt++;
					if (1 == pDataType->iDataType) //②-①SOE稳态事件------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATASOE"; //kafka发送主题
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\", ").arg(pDataType->iDataType)); //拼接 json数据类型
						KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻(毫秒)
						KafkaData.strText.append(QString("\"%1\":[").arg(data->mp_id)); //拼接 json监测点号

						list<CEventData*>::iterator ed = pDataType->SOEList.begin(); //③遍历 SOEList
						list<CEventData*>::iterator edEnd = pDataType->SOEList.end(); //SOEList尾元素
						while (ed != pDataType->SOEList.end())
						{
							CEventData* pEventData = *ed++;

							if ("NOT DEFINE" == pEventData->strFullName || "not define" == pEventData->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
								continue;
							if (!data->mms_str_map.contains(pEventData->strFullName))//确认字典里不含有该key
								continue;

							try
							{
								double dTemp = data->mms_str_map.value(pEventData->strFullName);
								if (dTemp >= 0.9) //SOE事件发生
								{
									if (0 == triggerCount) //SOE触发标识计数
									{
										KafkaData.strText.append(QString("\"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
										triggerCount++; //SOE触发标识计数
									}
									else
										KafkaData.strText.append(QString(", \"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
								}
							}
							catch (exception& e)
							{
								cout << "SOE稳态事件拼接json错误，原因: " << e.what() << endl;
								return false;
							}
						} //SOEList 结束
						KafkaData.strText.append("]}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-①SOE稳态事件解析结束！---------------------------------

					if (1 == pDataType->iDataType) //②-②SOE暂态事件------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATASOE"; //kafka发送主题
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\", ").arg(pDataType->iDataType)); //拼接 json数据类型
						KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻(毫秒)
						KafkaData.strText.append(QString("\"%1\":[").arg(data->mp_id)); //拼接 json监测点号

						list<CEventData*>::iterator ed = pDataType->SOEList.begin(); //③遍历 SOEList
						list<CEventData*>::iterator edEnd = pDataType->SOEList.end(); //SOEList尾元素
						while (ed != pDataType->SOEList.end())
						{
							CEventData* pEventData = *ed++;

							if ("NOT DEFINE" == pEventData->strFullName || "not define" == pEventData->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
								continue;
							if (!data->mms_str_map.contains(pEventData->strFullName))//确认字典里不含有该key
								continue;

							try
							{
								double dTemp = data->mms_str_map.value(pEventData->strFullName);
								if (dTemp >= 0.9) //SOE事件发生
								{
									if (0 == triggerCount) //SOE触发标识计数
									{
										KafkaData.strText.append(QString("\"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
										triggerCount++; //SOE触发标识计数
									}
									else
										KafkaData.strText.append(QString(", \"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
								}
							}
							catch (exception& e)
							{
								cout << "SOE暂态事件拼接json错误，原因: " << e.what() << endl;
								return false;
							}
						} //SOEList 结束
						KafkaData.strText.append("]}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-②SOE暂态事件解析结束！---------------------------------

					if (1 == pDataType->iDataType) //②-③SOE状态事件------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATASOE"; //kafka发送主题
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\", ").arg(pDataType->iDataType)); //拼接 json数据类型
						KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻(毫秒)
						KafkaData.strText.append(QString("\"%1\":[").arg(data->mp_id)); //拼接 json监测点号

						list<CEventData*>::iterator ed = pDataType->SOEList.begin(); //③遍历 SOEList
						list<CEventData*>::iterator edEnd = pDataType->SOEList.end(); //SOEList尾元素
						while (ed != pDataType->SOEList.end())
						{
							CEventData* pEventData = *ed++;

							if ("NOT DEFINE" == pEventData->strFullName || "not define" == pEventData->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
								continue;
							if (!data->mms_str_map.contains(pEventData->strFullName))//确认字典里不含有该key
								continue;

							try
							{
								double dTemp = data->mms_str_map.value(pEventData->strFullName);
								if (dTemp >= 0.9) //SOE事件发生
								{
									if (0 == triggerCount) //SOE触发标识计数
									{
										KafkaData.strText.append(QString("\"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
										triggerCount++; //SOE触发标识计数
									}
									else
										KafkaData.strText.append(QString(", \"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
								}
							}
							catch (exception& e)
							{
								cout << "SOE状态事件拼接json错误，原因: " << e.what() << endl;
								return false;
							}
						} //SOEList 结束
						KafkaData.strText.append("]}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-③SOE状态事件解析结束！---------------------------------
				} //DataTypeList 结束
			} //遍历 RTDATASOE 结束！
		} //TopicList 结束
	} //二、结束

	if (400 == data->func_type || 500 == data->func_type || 600 == data->func_type || 700 == data->func_type) //三、补招历史数据 ——> MMS_Recall
	{		
		list<CTopic*>::iterator tp = ctopic_list.begin();
		while (tp != ctopic_list.end()) //①遍历 Kafka发送主题链表
		{			
			CTopic* pTopic = *tp++;
			if ("HISDATA" == pTopic->strTopic) //Topic等于HISDATA----------------------------------------------------------
			{
				list<CDataType*>::iterator dt = pTopic->DataTypeList.begin(); //②遍历 DataTypeList
				while (dt != pTopic->DataTypeList.end())
				{
					bool isJump = false; //是否跳出(整个数据类型)循环
					CDataType* pDataType = *dt++;

					if (2 == pDataType->iDataType) //②-②历史短闪变数据------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "PST"; //kafka发送主题		
						KafkaData.strText = ""; //kafka发送的json字符串

						long long  time_sec; //时间戳(秒)
						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：历史闪变 "02"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"

						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						int countflag = 0, num = 0;
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("TIME" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻，毫秒
									time_sec = data->time / 1000; //时间戳(秒)
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 F

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									num = num + pSequence->DataValueList.size();
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
										{
											countflag++;
											continue;
										}
											
										if (!data->mms_str_map.contains(pDataValue->strFullName))//确认字典里不含有该key
										{
											isJump = false; //跳出本层循环
											countflag++;
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":%2, ").arg(pDataValue->strName).arg("null")); //拼接
											else
												KafkaData.strText.append(QString("\"%1\":%2 ").arg(pDataValue->strName).arg("null")); //拼接
											continue;
										}

										try
										{
											double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":\"%2\",").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
											else
												KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
										}
										catch (exception& e)
										{
											cout << "历史闪变数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

						cout << countflag << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!send name=\"DATA_TYPE\" value=\"02\" " << num << endl;
						cout << KafkaData.strText.toAscii().data() << endl;
						if (countflag < num) {
							kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
							kafka_data_list_mutex.unlock(); //解锁
							shortjumpflag = true;
						}
					} //②-②历史闪变数据解析结束！--------------------------------

					//20241204长闪变类型应该为3
					if (3 == pDataType->iDataType) //②-②历史长闪变数据------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "PLT"; //kafka发送主题		
						KafkaData.strText = ""; //kafka发送的json字符串

						long long  time_sec; //时间戳(秒)
						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：历史闪变 "02"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"

						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						int countflag = 0, num = 0;
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("TIME" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻，毫秒
									time_sec = data->time / 1000; //时间戳(秒)
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 F

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									num = num + pSequence->DataValueList.size();
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
										{
											countflag++;
											continue;
										}
										if (!data->mms_str_map.contains(pDataValue->strFullName))//确认字典里不含有该key
										{
											isJump = false; //跳出本层循环
											countflag++;
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":%2, ").arg(pDataValue->strName).arg("null")); //拼接
											else
												KafkaData.strText.append(QString("\"%1\":%2 ").arg(pDataValue->strName).arg("null")); //拼接
											continue;
										}

										try
										{
											if (0 == time_sec % 7200) //2小时间隔，长时闪变
											{
												double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(角度值)
											}
										}
										catch (exception& e)
										{
											cout << "历史闪变数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

						cout << countflag << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!send name=\"DATA_TYPE\" value=\"04\" " << num << endl;
						cout << KafkaData.strText.toAscii().data() << endl;
						if (countflag < num && 0 == time_sec % 7200) {
							kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
							kafka_data_list_mutex.unlock(); //解锁
							longjumpflag = true;
						}
						if (longjumpflag == true || shortjumpflag == true) {
							return 1;
						}
						//return 1; //结束该函数，停止后续代码执行
					} //②-②历史闪变数据解析结束！--------------------------------

					if (1 == pDataType->iDataType) //②-①历史稳态数据-----------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "HISDATA"; //kafka发送主题		
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\" ").arg(pDataType->iDataType, 2, 10, QChar('0'))); //拼接 json数据类型  例：历史稳态 "01"
						KafkaData.strText.append(QString(", \"Monitor\":\"%1\" ").arg(data->mp_id));//例：监测点 "1100"

						list<CMonitor*>::iterator mt = pDataType->MonitorList.begin(); //③遍历 MonitorList
						while (mt != pDataType->MonitorList.end())
						{
							CMonitor* pMonitor = *mt++;
							KafkaData.strText.append(QString(", \"%1\":{").arg("Value")); //拼接 json监测点

							list<CItem*>::iterator it = pMonitor->ItemList.begin(); //④遍历 ItemList
							list<CItem*>::iterator itEnd = pMonitor->ItemList.end(); //ItemList链表最后一个数据值元素
							while (it != pMonitor->ItemList.end())
							{
								CItem* pItem = *it++;
								if ("FLAG" == pItem->strItemName) //剔除"FLAG"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"FLAG\":%1, ").arg(data->flag)); //拼接 json剔除标记，1不剔除，0剔除，默认剔除
									continue;
								}
								if ("TIME" == pItem->strItemName) //剔除"TIME"，防止sq相别出现错误指针
								{
									KafkaData.strText.append(QString("\"TIME\":%1, ").arg(data->time)); //拼接 json发生时刻，毫秒
									if (!data_timespan_list.contains(data->mp_id)) {
										KafkaData.strText.append(QString("\"interval\":%1, ").arg(3)); //拼接 json发生时刻，毫秒
										
									}
									else if (data_timespan_list[data->mp_id]->msspan == 0)
									{
										KafkaData.strText.append(QString("\"interval\":%1, ").arg(3)); //拼接 json发生时刻，毫秒
									}
									else {
										KafkaData.strText.append(QString("\"interval\":%1, ").arg(data_timespan_list[data->mp_id]->msspan)); //拼接 json发生时刻，毫秒
									}
									continue;
								}
								KafkaData.strText.append(QString("\"%1\":{").arg(pItem->strItemName)); //拼接 json数据项 V、I、PQ

								list<CSequence*>::iterator sq = pItem->SequenceList.begin(); //⑤遍历 SequenceList
								list<CSequence*>::iterator sqEnd = pItem->SequenceList.end(); //SequenceList链表最后一个数据值元素
								while (sq != pItem->SequenceList.end())
								{
									CSequence* pSequence = *sq++;
									//KafkaData.strText.append(QString("{\"SEQ\":\"%1\", ").arg(pSequence->strSeq)); //拼接 json相别 A、B、C、T相
									KafkaData.strText.append(QString("\"%1\":{ ").arg(line_to_phasic(pSequence->strSeq))); //拼接 json相别 A、B、C、T相

									list<CDataValue*>::iterator dv = pSequence->DataValueList.begin(); //⑥遍历 DataValueList
									CDataValue* pDataValueBegin = *dv;
									list<CDataValue*>::iterator dvEnd = pSequence->DataValueList.end(); //DataValueList链表最后一个数据值元素
									while (dv != pSequence->DataValueList.end())
									{
										CDataValue* pDataValue = *dv++;

										if ("NOT DEFINE" == pDataValue->strFullName || "not define" == pDataValue->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
											continue;
										if (!data->mms_str_map.contains(pDataValue->strFullName))//确认字典里不含有该key
										{
											isJump = false; //跳出本层循环
											//zw修改 2023-8-28 不匹配数据添加
											if (dv != dvEnd) //非单相最后一个数据值元素
												KafkaData.strText.append(QString("\"%1\":%2, ").arg(pDataValue->strName).arg("null")); //拼接
											else
												KafkaData.strText.append(QString("\"%1\":%2 ").arg(pDataValue->strName).arg("null")); //拼接

											if (pDataValue->BaseFlag == "1") {
												//errorlog_datamatch(pDataValue->strFullName, &data_match_map_1);//lnk删除
											}
											else {
												//errorlog_datamatch(pDataValue->strFullName, &data_match_map_2);//lnk删除
											}
											continue;
										}

										try
										{
											if (pDataValue->strFullName.indexOf("$ang$f") != -1) //查找61850属性名中含有相角的定义
											{
												double dAngleTemp = data->mms_str_map.value(pDataValue->strFullName); //角度值(-180度 ~ 180度)
												dAngleTemp = dAngleTemp > 180.0f ? dAngleTemp - 360.0f : dAngleTemp;
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dAngleTemp, 10, 6))); //拼接 json数据值(角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dAngleTemp, 10, 6))); //拼接 json数据值(角度值)
												//zw修改 2023 - 8 - 23 数值合理性判断函数 节点属性 实际值 监测点号 电压等级
												//errorlog_num(pDataValue, dAngleTemp, data->voltage_level, &data_reason_map, data->time);
											}
											else
											{
												double dTemp = data->mms_str_map.value(pDataValue->strFullName) * pDataValue->fCoefficient; //接口数据 * 系数
												if (dv != dvEnd) //非单相最后一个数据值元素
													KafkaData.strText.append(QString("\"%1\":\"%2\", ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
												else
													KafkaData.strText.append(QString("\"%1\":\"%2\" ").arg(pDataValue->strName).arg(QString::number(dTemp, 10, 6))); //拼接 json数据值(非角度值)
												//zw修改 2023 - 8 - 23 数值合理性判断函数 节点属性 实际值 监测点号 电压等级
												//errorlog_num(pDataValue, dTemp, data->voltage_level, &data_reason_map, data->time);
											}
										}
										catch (exception& e)
										{
											cout << "历史稳态数据值拼接json错误，原因: " << e.what() << endl;
											return false;
										}
									} //DataValueList 结束

									if (!KafkaData.strText.isEmpty()) {
										if (KafkaData.strText[KafkaData.strText.length() - 1] == ',') {
											KafkaData.strText = KafkaData.strText.remove(KafkaData.strText.size() - 1, 1);
											KafkaData.strText.append(" ");
											cout << "KafkaData.strText = KafkaData.strText.chopped(1) " << endl;
										}
									}
									if (isJump) break; //跳出循环
									if (sq != sqEnd) //非A、B、C、T最后一个相别元素
										KafkaData.strText.append("}, "); //拼接 json相别结尾
									else
										KafkaData.strText.append("}"); //拼接 json相别结尾
								} //SequenceList 结束

								if (isJump) break; //跳出循环
								if (it != itEnd) //非 V、I、PQ最后一个json数据项元素
									KafkaData.strText.append("}, "); //拼接 json数据项结尾
								else
									KafkaData.strText.append("}}"); //拼接 json数据项结尾
							} //ItemList 结束
							if (isJump) break; //跳出循环
						} //MonitorList 结束
						if (isJump) continue; //跳出本数据类型循环
						KafkaData.strText.append("}"); //拼接 json稳态数据结尾

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

						//lnk20241122不记录这些
						if (false)//zw修改 2023-8-28 数据完整性 合理性 匹配率 日志记录执行判断逻辑
						{
							cout << "!!!!!!!!!!!!!!!!!!!!!!===============" << data_match_map_1.count() << "--------" << data_match_map_2.count() << endl;
							cout << "!!!!!!!!!!!!!!!!!!!!!!---------------" << data_reason_map.count() << endl;
							if (data_match_map_1.count() + data_match_map_2.count() <= 1200)//完整性记录 默认为true 只要发送了kafka记录就执行
							{
								errorlog_dataintegrity_timespanlist(data->mp_id, data->time);
								errorlog_dataintegrity_timespanlist_2(data->mp_id);
								QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								QString tmp_chr2 = dataintegrity_time.toString("yyyy-MM-dd hh:mm:ss");
								//不再需要完整性记录lnk202411-6
								//cout << errorlog_dataintegrity_pgsql(tmp_chr1, tmp_chr2, data->mp_id,true).toAscii().data() << endl;
							}
							if (data_reason_map.count() != 0)//合理性记录 只要map存在元素 记录不合理性日志
							{
								QString reasonlog = errorlog_num_json(data->mp_id, data_reason_map);

								QDateTime savetime = QDateTime::fromTime_t(data->time / 1000);
								QString Qfilename, Qsavename;
								Qfilename.append("comtrade/").append(data->mp_id).append("/").append(savetime.toString("yyyyMMdd")).append("/").append(savetime.toString("yyyyMMddhhmmss")).append("_reason.log");
								Qsavename.append("/FeProject/dat/").append(data->mp_id).append("_").append(savetime.toString("yyyyMMddhhmmss")).append("_reason.log");
								char file_name[256];
								memset(file_name, 0, 256);
								sprintf(file_name, "%s", Qfilename.toAscii().data());
								char save_name[256];
								memset(save_name, 0, 256);
								sprintf(save_name, "%s", Qsavename.toAscii().data());
								cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;

								oss_data_t OssData;
								OssData.filename = file_name;
								OssData.savename = save_name;
								OssData.data = reasonlog;


								QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								OssData.id = data->mp_id;
								OssData.time = tmp_chr1;  //时间
								OssData.list_num = data_reason_map.size();
								OssData.log_name = "reason";

								if (data->time % 3600000 == 0) {
									oss_data_list_mutex.lock(); //加锁
									oss_data_list.append(OssData); //添加 kafka发送链表
									oss_data_list_mutex.unlock(); //解锁
								}
								//std::ofstream file(save_name); // 创建一个输出文件流对象，打开文件 example.txt
								//if (file.is_open()) { // 判断文件是否成功打开
								//	file << reasonlog.toAscii().data() << "\n";
								//	file.close(); // 关闭文件
								//}
								//else {
								//	cout << "Unable to open file\n" << endl;
								//}

								//PutOSS(file_name, save_name);
								//std::remove(save_name);

								/*QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								QString pgsql;
								pgsql.append(errorlog_num_pgsql(data->mp_id, tmp_chr1, Qfilename, data_reason_map.size()));
								cout << pgsql.toAscii().data() << endl;*/
							}
							if (data_match_map_1.count() != 0 || data_match_map_2.count() != 0)//匹配率记录 只要map存在元素 记录不匹配的数值
							{
								QString matchlog = errorlog_datamatch_json(data_match_map_1, data_match_map_2, data->time);
								//cout << matchlog.toAscii().data() << endl;

								QDateTime savetime = QDateTime::fromTime_t(data->time / 1000);
								QString Qfilename, Qsavename;
								Qfilename.append("comtrade/").append(data->mp_id).append("/").append(savetime.toString("yyyyMMdd")).append("/").append(savetime.toString("yyyyMMddhhmmss")).append("_match.log");
								Qsavename.append("/FeProject/dat/").append(data->mp_id).append("_").append(savetime.toString("yyyyMMddhhmmss")).append("_match.log");
								char file_name[256];
								memset(file_name, 0, 256);
								sprintf(file_name, "%s", Qfilename.toAscii().data());
								char save_name[256];
								memset(save_name, 0, 256);
								sprintf(save_name, "%s", Qsavename.toAscii().data());
								cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;

								oss_data_t OssData;
								OssData.filename = file_name;
								OssData.savename = save_name;
								OssData.data = matchlog;

								QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								OssData.id = data->mp_id;
								OssData.time = tmp_chr1;  //时间
								//match_log
								OssData.base_mat_num = pDataType->BaseFlag1;
								OssData.adv_mat_num = pDataType->BaseFlag1 + pDataType->BaseFlag0;
								OssData.base_act_num = pDataType->BaseFlag1 - data_match_map_1.count();
								OssData.adv_act_num = pDataType->BaseFlag1 + pDataType->BaseFlag0 - data_match_map_1.count() - data_match_map_2.count();
								OssData.log_name = "match";

								if (data->time % 3600000 == 0) {
									oss_data_list_mutex.lock(); //加锁
									oss_data_list.append(OssData); //添加 kafka发送链表
									oss_data_list_mutex.unlock(); //解锁
								}
								//std::ofstream file(save_name); // 创建一个输出文件流对象，打开文件 example.txt
								//if (file.is_open()) { // 判断文件是否成功打开
								//	file << matchlog.toAscii().data() << "\n";
								//	file.close(); // 关闭文件
								//}
								//else {
								//	cout << "Unable to open file\n" << endl;
								//}

								/*PutOSS(file_name, save_name);
								std::remove(save_name);*/
								//GetOSS(file_name, savename);
								/*QDateTime dataintegrity_time = QDateTime::fromTime_t(data->time / 1000);
								QString tmp_chr1 = dataintegrity_time.toString("yyyy-MM-dd");
								QString pqsql;
								pqsql.append(errorlog_datamatch_pgsql(data->mp_id, tmp_chr1, pDataType->BaseFlag1, pDataType->BaseFlag1 + pDataType->BaseFlag0, pDataType->BaseFlag1 - data_match_map_1.count(), pDataType->BaseFlag1 + pDataType->BaseFlag0 - data_match_map_1.count() - data_match_map_2.count(), Qfilename));
								cout << pqsql.toAscii().data() << endl;*/

							}
							QMap<QString, QDateTime>().swap(data_match_map_1);
							QMap<QString, QDateTime>().swap(data_match_map_2);
							QMap<QString, MP_RATIONALITY*>().swap(data_reason_map);
						}
						return 1; //结束该函数，停止后续代码执行
					} //②-①历史稳态数据解析结束！--------------------------------
				} //DataTypeList 结束
			} //遍历 HISDATA 结束！

			if ("RTDATASOE" == pTopic->strTopic) //Topic等于RTDATASOE----------------------------------------------------------
			{
				list<CDataType*>::iterator dt = pTopic->DataTypeList.begin(); //②遍历 DataTypeList
				while (dt != pTopic->DataTypeList.end())
				{
					int triggerCount = 0; //SOE触发标识计数
					CDataType* pDataType = *dt++;
					if (1 == pDataType->iDataType) //②-①SOE稳态事件------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATASOE"; //kafka发送主题
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\", ").arg(pDataType->iDataType)); //拼接 json数据类型
						KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻(毫秒)
						KafkaData.strText.append(QString("\"%1\":[").arg(data->mp_id)); //拼接 json监测点号

						list<CEventData*>::iterator ed = pDataType->SOEList.begin(); //③遍历 SOEList
						list<CEventData*>::iterator edEnd = pDataType->SOEList.end(); //SOEList尾元素
						while (ed != pDataType->SOEList.end())
						{
							CEventData* pEventData = *ed++;

							if ("NOT DEFINE" == pEventData->strFullName || "not define" == pEventData->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
								continue;
							if (!data->mms_str_map.contains(pEventData->strFullName))//确认字典里不含有该key
								continue;

							try
							{
								double dTemp = data->mms_str_map.value(pEventData->strFullName);
								if (dTemp >= 0.9) //SOE事件发生
								{
									if (0 == triggerCount) //SOE触发标识计数
									{
										KafkaData.strText.append(QString("\"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
										triggerCount++; //SOE触发标识计数
									}
									else
										KafkaData.strText.append(QString(", \"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
								}
							}
							catch (exception& e)
							{
								cout << "SOE稳态事件拼接json错误，原因: " << e.what() << endl;
								return false;
							}
						} //SOEList 结束
						KafkaData.strText.append("]}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-①SOE稳态事件解析结束！---------------------------------

					if (1 == pDataType->iDataType) //②-②SOE暂态事件------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATASOE"; //kafka发送主题
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\", ").arg(pDataType->iDataType)); //拼接 json数据类型
						KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻(毫秒)
						KafkaData.strText.append(QString("\"%1\":[").arg(data->mp_id)); //拼接 json监测点号

						list<CEventData*>::iterator ed = pDataType->SOEList.begin(); //③遍历 SOEList
						list<CEventData*>::iterator edEnd = pDataType->SOEList.end(); //SOEList尾元素
						while (ed != pDataType->SOEList.end())
						{
							CEventData* pEventData = *ed++;

							if ("NOT DEFINE" == pEventData->strFullName || "not define" == pEventData->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
								continue;
							if (!data->mms_str_map.contains(pEventData->strFullName))//确认字典里不含有该key
								continue;

							try
							{
								double dTemp = data->mms_str_map.value(pEventData->strFullName);
								if (dTemp >= 0.9) //SOE事件发生
								{
									if (0 == triggerCount) //SOE触发标识计数
									{
										KafkaData.strText.append(QString("\"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
										triggerCount++; //SOE触发标识计数
									}
									else
										KafkaData.strText.append(QString(", \"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
								}
							}
							catch (exception& e)
							{
								cout << "SOE暂态事件拼接json错误，原因: " << e.what() << endl;
								return false;
							}
						} //SOEList 结束
						KafkaData.strText.append("]}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-②SOE暂态事件解析结束！---------------------------------

					if (1 == pDataType->iDataType) //②-③SOE状态事件------------------------------------------------------------
					{
						Ckafka_data_t KafkaData; //kafka发送数据结构类对象
						KafkaData.monitor_id = data->monitorId; //监测点ID	
						KafkaData.mp_id = data->mp_id;
						KafkaData.strTopic = "RTDATASOE"; //kafka发送主题
						KafkaData.strText = ""; //kafka发送的json字符串

						KafkaData.strText.append("{"); //拼接 json起始
						KafkaData.strText.append(QString("\"DATA_TYPE\":\"%1\", ").arg(pDataType->iDataType)); //拼接 json数据类型
						KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻(毫秒)
						KafkaData.strText.append(QString("\"%1\":[").arg(data->mp_id)); //拼接 json监测点号

						list<CEventData*>::iterator ed = pDataType->SOEList.begin(); //③遍历 SOEList
						list<CEventData*>::iterator edEnd = pDataType->SOEList.end(); //SOEList尾元素
						while (ed != pDataType->SOEList.end())
						{
							CEventData* pEventData = *ed++;

							if ("NOT DEFINE" == pEventData->strFullName || "not define" == pEventData->strFullName) //数据对象名 $ 数据属性名  即：拼接名为空
								continue;
							if (!data->mms_str_map.contains(pEventData->strFullName))//确认字典里不含有该key
								continue;

							try
							{
								double dTemp = data->mms_str_map.value(pEventData->strFullName);
								if (dTemp >= 0.9) //SOE事件发生
								{
									if (0 == triggerCount) //SOE触发标识计数
									{
										KafkaData.strText.append(QString("\"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
										triggerCount++; //SOE触发标识计数
									}
									else
										KafkaData.strText.append(QString(", \"%1\" ").arg(pEventData->triggerFlag)); //拼接 json SOE触发标识
								}
							}
							catch (exception& e)
							{
								cout << "SOE状态事件拼接json错误，原因: " << e.what() << endl;
								return false;
							}
						} //SOEList 结束
						KafkaData.strText.append("]}"); //拼接 json稳态数据结尾

						kafka_data_list_mutex.lock(); //加锁
							kafka_data_list.append(KafkaData); //添加 kafka发送链表
						kafka_data_list_mutex.unlock(); //解锁
						
						return 1; //结束该函数，停止后续代码执行
					} //②-③SOE状态事件解析结束！---------------------------------
				} //DataTypeList 结束
			} //遍历 RTDATASOE 结束！
		} //TopicList 结束
	} //三、结束
	
	return 1;
}



/*//生成json暂态消息 zw修改 2023-8-25 调整json结构
int transfer_json_qvvr_data(unsigned int func_type, int monitor_id, float mag, float dur, long long start_tm, long long end_tm, int dis_kind, char* uuid_cfg,char* uuid_dat,char* mp_id,char* Qvvr_rptname,char* devtype) //生成json暂态消息 ——> MMS_Wave
{	
	XmlConfig c_xmlcfg;
	if (xmlinfo_list.contains(devtype)) {
		c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;
	}
	else {
		c_xmlcfg = xmlcfg;
	}

	//if (0 == monitor_id) //json拼接监测点号为空
	//	return 0;
	if (strlen(mp_id) == 0) {
		return 0;
	}

	Ckafka_data_t KafkaData; //kafka发送数据结构类对象
	KafkaData.monitor_id = monitor_id;
	KafkaData.mp_id = mp_id;

//	if (400 == func_type) //三、补招历史数据 ——> MMS_Recall
//		KafkaData.strTopic = "HISDATA"; //kafka发送主题
//	else
//		KafkaData.strTopic = "RTDATA";

    KafkaData.strTopic = "Event"; //kafka发送主题
	
	KafkaData.strText.append("{"); //拼接 json起始

	if (400 == func_type || 500 == func_type || 600 == func_type || 700 == func_type) //三、补招历史数据 ——> MMS_Recall	
		KafkaData.strText.append("\"DATA_TYPE\":\"04\", "); //拼接 数据类型
	else
		KafkaData.strText.append("\"DATA_TYPE\":\"04\", "); //拼接 数据类型

	KafkaData.strText.append(QString("\"Monitor\":\"%1\", ").arg(mp_id)); //拼接 json监测点

	KafkaData.strText.append(QString("\"Value\":{")); //拼接 json监测点
	KafkaData.strText.append(QString("\"FLAG\":%1,").arg(1)); //拼接 剔除标记
	KafkaData.strText.append(QString("\"TIME\":%1,").arg(start_tm)); //拼接 时间
	KafkaData.strText.append("\"VOLTAGE\":{"); //拼接 数据项  例：VOLTAGE
	KafkaData.strText.append(QString("\"MAG\":%1").arg(mag)); //拼接 残余电压，即：特征幅值
	KafkaData.strText.append(QString(", \"DUR\":%1").arg(dur * 1000)); //拼接 持续时间(毫秒)
	KafkaData.strText.append(QString(", \"STARTTIME\":%1").arg(start_tm )); //拼接 开始时间(毫秒)
	KafkaData.strText.append(QString(", \"ENDTIME\":%1").arg(end_tm)); //拼接 结束时间(毫秒)
	KafkaData.strText.append(QString(", \"DISKIND\":\"%1%2\"").arg("0").arg(dis_kind)); //拼接 暂降类型(1210001-暂升 1210002-暂降 1210004-中断 1210003-其他)
	KafkaData.strText.append(QString(", \"CFG_FILE\":\"%1\"").arg(uuid_cfg)); //拼接 cfg波形文件名称
	KafkaData.strText.append(QString(", \"DAT_FILE\":\"%1\"").arg(uuid_dat)); //拼接 dat波形文件名称
	if (c_xmlcfg.WavePhasicFlag == "1") {
		QString Qvvr_Rptname;
		Qvvr_Rptname.append(Qvvr_rptname);
		if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicA) != -1) {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("A")); //拼接 相别
		}
		else if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicB) != -1) {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("B")); //拼接 相别
		}
		else if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicC) != -1) {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("C")); //拼接 相别
		}
		else {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("unknow")); //拼接 相别
		}
	}
	else {
		KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("unknow")); //拼接 相别
	}

	KafkaData.strText.append("}"); //拼接 json结束
	KafkaData.strText.append("}}"); //拼接 json结束

	printf("transfer json qvvr data: %s==%s \n",KafkaData.strText.toStdString().c_str(), Qvvr_rptname);

	kafka_data_list_mutex.lock(); //加锁
	kafka_data_list.append(KafkaData); //添加 kafka发送链表
	//if (400 != func_type) { //非补招历史数据
	//	KafkaData.strTopic = "Event";
	//	kafka_data_list.append(KafkaData); 
	//}
	kafka_data_list_mutex.unlock(); //解锁
	return 1;
}*/

void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long time,char* devtype,int monitor_id)
{
	XmlConfig c_xmlcfg;
	if (xmlinfo_list.contains(devtype)) {
		c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;
	}
	else {
		c_xmlcfg = xmlcfg;
	}

	QString Full_name;
	Full_name.append(fullname);

	Ckafka_data_t KafkaData; //kafka发送数据结构类对象
	KafkaData.monitor_id = monitor_id;
	KafkaData.mp_id = mp_id;
	KafkaData.strTopic = "Alm"; //kafka发送主题

	KafkaData.strText.append("{"); //拼接 json起始
	KafkaData.strText.append("\"DATA_TYPE\":\"05\", "); //拼接 数据类型
	KafkaData.strText.append(QString("\"Monitor\":\"%1\", ").arg(mp_id)); //拼接 json监测点
	KafkaData.strText.append(QString("\"Value\":{")); //拼接 json监测点
	KafkaData.strText.append(QString("\"FLAG\":%1,").arg(1)); //拼接 剔除标记
	KafkaData.strText.append(QString("\"TIME\":%1,").arg(time)); //拼接 时间
	KafkaData.strText.append(QString("\"SOE\":[")); //拼接 SOE

	list<CEventData*>::iterator ed = c_xmlcfg.SOEList.begin(); //③遍历 SOEList
	while (ed != c_xmlcfg.SOEList.end())
	{
		CEventData* pEventData = *ed++;
		if (pEventData->strFullName.indexOf(Full_name) != -1)
		{
			KafkaData.strText.append(QString("\"%1\"").arg(pEventData->triggerFlag));
			break;
		}
	}

	KafkaData.strText.append(QString("]")); //拼接 SOE结束
	KafkaData.strText.append("}"); //拼接 value结束
	KafkaData.strText.append("}"); //拼接 json结束

	printf("transfer json ggio data: %s==%s \n", KafkaData.strText.toStdString().c_str(), fullname);
	kafka_data_list_mutex.lock(); //加锁
	kafka_data_list.append(KafkaData); //添加 kafka发送链表
	kafka_data_list_mutex.unlock(); //解锁
}

//zw修改 2023-8-31 新增或更新list队列 写入xml数据库信息 模型编码 终端型号 终端厂家 oss存储路径 时间
//lnk修改 2024-10-28 去掉终端厂家，换成远端模型文件路径
//void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* TMNL_FACTORY, char* FILE_NAME, int year, int month, int day, int hour, int minute, int second)
void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char* FILE_NAME, int year, int month, int day, int hour, int minute, int second)
{
	if (MODEL_ID == NULL || TMNL_TYPE == NULL || FILE_PATH == NULL || FILE_NAME == NULL)
	{
		cout << "Function Set_xml_databaseinfo Error!" << endl;
		return;
	}
	cout << "Function Set_xml_databaseinfo Start!" << endl;
	QString id, type, filepath, name;
	id.append(MODEL_ID);
	type.append(TMNL_TYPE);
	filepath.append(FILE_PATH);
	name.append(FILE_NAME);

	//调试用lnk20241125
	cout << "setxmldatabase:" << TMNL_TYPE << endl;

	if (!xmlinfo_list.contains(type))//在终端类型列表中没查到
	{
		Xmldata* config = new Xmldata();	//没找到就插个新的终端类型到列表中
		xmlinfo_list.insert(type, config);

		//调试用lnk20241125
		cout << "xmlinfo_list insert type:" << type.toStdString() << endl;
	}
	else//查到就更新覆盖
	{
		//调试用lnk20241125
		cout << "xmlinfo_list type contain:" << type.toStdString() << endl;

		QDateTime time(QDate(year, month, day), QTime(hour, minute, second));
		if (xmlinfo_list[type]->xmlbase.datetime == time) {		//终端型号更新标志，如果新增的型号错误，导致实际用的映射文件不一样，或者覆盖了原来的映射文件这里可能出问题。数据库在录入型号和映射文件时要注意
			xmlinfo_list[type]->updataflag = false;		//时间值一样说明是没有更新，当前业务中不包含时间值，所以每次都会更新
		}
		else {
			xmlinfo_list[type]->updataflag = true;
		}
		//lnk20250208如果类型存在则不再往下执行
	}

	//lnk20250208这里应该是覆盖而不是追加
	//xmlinfo_list[type]->xmlbase.MODEL_ID.append(id);
	//xmlinfo_list[type]->xmlbase.TMNL_TYPE.append(type);
	//xmlinfo_list[type]->xmlbase.FILE_PATH.append(filepath);
	//xmlinfo_list[type]->xmlbase.FILE_NAME.append(name);
	xmlinfo_list[type]->xmlbase.MODEL_ID = id;
	xmlinfo_list[type]->xmlbase.TMNL_TYPE = type;
	xmlinfo_list[type]->xmlbase.FILE_PATH = filepath;
	xmlinfo_list[type]->xmlbase.FILE_NAME = name;

	QDateTime time(QDate(year, month, day), QTime(hour, minute, second));
	xmlinfo_list[type]->xmlbase.datetime = time;

	cout << "##################################isdelta_flag is " << isdelta_flag << endl;
	/*lnk2024-8-14 根据isdelta_flag 选择xmllist*/
	if (isdelta_flag) {
		cout << "xmllist2 create" << endl;
		if (!xmlinfo_list2.contains(type))
		{
			Xmldata* config2 = new Xmldata();
			xmlinfo_list2.insert(type, config2);
		}
		else
		{
			QDateTime time(QDate(year, month, day), QTime(hour, minute, second));
			if (xmlinfo_list2[type]->xmlbase.datetime == time) {
				xmlinfo_list2[type]->updataflag = false;
			}
			else {
				xmlinfo_list2[type]->updataflag = true;
			}
		}
		xmlinfo_list2[type]->xmlbase.MODEL_ID = id;
		xmlinfo_list2[type]->xmlbase.TMNL_TYPE = type;
		xmlinfo_list2[type]->xmlbase.FILE_PATH = filepath;
		xmlinfo_list2[type]->xmlbase.FILE_NAME = name;
		xmlinfo_list2[type]->xmlbase.datetime = time;
	}
	/*lnk2024-8-14*/

	char file_name[256];
	memset(file_name, 0, 256);
	sprintf(file_name, "%s", FILE_NAME);
	QString Qsavename;
	Qsavename.append("/FeProject/dat/").append(id).append(".xml");		//本地保存路径
	char save_name[256];
	memset(save_name, 0, 256);
	sprintf(save_name, "%s", Qsavename.toAscii().data());
	cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;

	//20241028 lnk 替换为文件下载web接口
	//构造文件下载接口参数
	//接口示例http://192.168.1.125:10215/file/download?filePath=/path/xxx.txt
	// 调用web获取文件内容
    char* fileContent = NULL;

	//测试下载
	//char downpath[128] = {"/home/pq/FeProject/src/pt61850netd_pqfe_lnk/download/123.txt"};
	//char download[128] = {"{\"filename\":\"file_test.txt\"}"};
	//SendJsonAPI_web("http://192.168.1.149:8091/file/download", "", download, &fileContent);

	std::string fullPath = std::string("filePath=") + std::string(FILE_PATH);

	//调试用
	std::cout << "fullpath" << fullPath << std::endl;

	SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", &fileContent);
    if (fileContent != NULL) {
        // 创建并打开文件

		//测试
		//std::ofstream outFile(downpath, std::ios::binary);//二进制的方式打开

        std::ofstream outFile(save_name, std::ios::out);//文本模式打开
        if (outFile.is_open()) {
            // 将文件流写入文件
            outFile.write(fileContent, strlen(fileContent));
            outFile.close();
            std::cout << "File saved successfully!" << std::endl;
        } else {
            std::cerr << "Error: Unable to open file for writing." << std::endl;
        }

        // 释放分配的内存
        free(fileContent);
    } else {
        std::cerr << "Error: Unable to download file." << std::endl;
    }

	/*if (FILE_FLAG == 1) {
		GetOSS(file_name, save_name);
	}
	else if (FILE_FLAG == 2) {
		OBSFile(save_name, file_name, "getObject");
	}
	else if (FILE_FLAG == 3) {
		//OBSFile(save_name, file_name, "getObject");
	}
	else {

	}*/
		//调试用
		if (xmlinfo_list.contains(type)) {
			std::cout << "xmlinfo_list.contains" << type.toStdString() <<std::endl;
		}
		else{
			std::cout << "??????????????????xmlinfo_list not contains" << type.toStdString() <<std::endl;
		}
}
//zw修改 2023-9-4 读取装置类型对应的xml文件
void Set_xml_nodeinfo()
{
	//配置无对应xml文件时的默认解析配置
	if (!inited) //初始化 JiangSu_Config.xml 
	{
		QString path;
		path.append("not define");
		ParseXMLConfig2(0, &xmlcfg, &topicList, path); //调用 ParseXMLConfig() 解析JiangSu_Config.xml配置文件
		if (isdelta_flag) {
			ParseXMLConfig2(1, &xmlcfg2, &topicList2, path);	//lnk2024-8-13角型接线
		}
		inited = true;
	}

	if (xmlinfo_list.size() != 0)
	{
		cout << "!!!!!!!!!! xmlinfo_list.size() != 0 !!!!!!!!!!!" << endl;
		for (QMap<QString, Xmldata*>::iterator it2 = xmlinfo_list.begin(); it2 != xmlinfo_list.end(); ++it2)
		{
			QString key2 = it2.key();
			Xmldata* value2 = it2.value();

			if (value2->updataflag == true) {
				ParseXMLConfig2(0,&(value2->xmlcfg), &(value2->topicList), value2->xmlbase.MODEL_ID);
			}
		}
		//lnk2024-8-14 选择角型接线
		if (isdelta_flag) {
			for (QMap<QString, Xmldata*>::iterator it3 = xmlinfo_list2.begin(); it3 != xmlinfo_list2.end(); ++it3)
			{
				QString key3 = it3.key();
				Xmldata* value3 = it3.value();	//

				if (value3->updataflag == true) {
					ParseXMLConfig2(1, &(value3->xmlcfg), &(value3->topicList), value3->xmlbase.MODEL_ID);
				}
			}
		}
	}
	else {
		cout << "!!!!!!!!!! xmlinfo_list.size() == 0 !!!!!!!!!!!" << endl;
	}

}
//zw修改 2023-9-4 获取xml路径
char* Get_xmlpath(char* devtype)
{
	QString type;
	type.append(devtype);

	//调试用lnk20241125
	std::cout << type.toStdString() << std::endl;

	if (xmlinfo_list.contains(type)) {
		cout << "!!!!!!!!!! xmlinfo_list.contains(devtype) == 1 !!!!!!!!!!!" << endl;
		QByteArray byteArray = xmlinfo_list[devtype]->xmlbase.MODEL_ID.toLocal8Bit();
		char* charArray = new char[byteArray.size()];
		memcpy(charArray, byteArray.data(), byteArray.size());
		charArray[byteArray.size()] = '\0';
		return charArray;
	}
	else {
		cout << "!!!!!!!!!! xmlinfo_list.contains(devtype) == 0 !!!!!!!!!!!" << endl;
		return NULL;
	}
}
//zw修改 2023-9-5 获取IED模型
char* Get_IED(char* devtype)
{
	QString type;
	type.append(devtype);
	if (xmlinfo_list.contains(type)) {
		cout << "!!!!!!!!!! Get_IED xmlinfo_list.contains(devtype) == 1 !!!!!!!!!!!" << endl;
		QString ied;
		ied.append(xmlinfo_list[devtype]->xmlcfg.IEDname);//PQMonitor
		ied.append(xmlinfo_list[devtype]->xmlcfg.LDevicePrefix);
		ied.append("%d");
		QByteArray byteArray = ied.toLocal8Bit();
		char* charArray = new char[byteArray.size()];
		memcpy(charArray, byteArray.data(), byteArray.size());
		charArray[byteArray.size()] = '\0';
		return charArray;
	}
	else {
		cout << "!!!!!!!!!! Get_IED xmlinfo_list.contains(devtype) == 0 !!!!!!!!!!!" << endl;
		//cout << "ttttttttttttttt" << topicList.size() << endl;
		//cout << "ttttttttttttttt" << xmlcfg.IEDname.toAscii().data() << endl;
		QString ied;
		ied.append(xmlcfg.IEDname);
		ied.append(xmlcfg.LDevicePrefix);
		ied.append("%d");
		QByteArray byteArray = ied.toLocal8Bit();
		char* charArray = new char[byteArray.size()];
		memcpy(charArray, byteArray.data(), byteArray.size());
		charArray[byteArray.size()] = '\0';
		return charArray;
	}
}
char* Get_LDevice(char* devtype) 
{
	QString type;
	type.append(devtype);
	if (xmlinfo_list.contains(type)) {//解析列表中包含终端类型
		QString ied;
		ied.append(xmlinfo_list[devtype]->xmlcfg.LDevicePrefix);//使用解析列表的终端前缀
		ied.append("%d");
		QByteArray byteArray = ied.toLocal8Bit();
		char* charArray = new char[byteArray.size()];
		memcpy(charArray, byteArray.data(), byteArray.size());
		charArray[byteArray.size()] = '\0';
		return charArray;
	}
	else {
		//cout << "ttttttttttttttt" << topicList.size() << endl;
		//cout << "ttttttttttttttt" << xmlcfg.IEDname.toAscii().data() << endl;
		QString ied;
		ied.append(xmlcfg.LDevicePrefix);//使用默认解析配置的终端前缀
		ied.append("%d");
		QByteArray byteArray = ied.toLocal8Bit();
		char* charArray = new char[byteArray.size()];
		memcpy(charArray, byteArray.data(), byteArray.size());
		charArray[byteArray.size()] = '\0';
		return charArray;
	}
}



///////////////////////////////////////////////////lnk2024-10-21////////////////////////////////////////////////////////
void handleCommentResponse(const std::string& response) {
    
	// 解析 JSON 响应
    cJSON* json_data = cJSON_Parse(response.c_str());
    if (json_data == NULL) {
        std::cerr << "Error parsing response: " << cJSON_GetErrorPtr() << std::endl;
        return;
    }

    // 提取字段
    cJSON* codeItem = cJSON_GetObjectItem(json_data, "code");
    cJSON* msgItem = cJSON_GetObjectItem(json_data, "msg");
    cJSON* dataItem = cJSON_GetObjectItem(json_data, "data");

    if (codeItem) {
        std::string code = codeItem->valuestring;

		// 输出信息
        std::cout << "Response Code: " << code << std::endl;
		
		std::string msg = (msgItem != NULL) ? msgItem->valuestring : "not found";
		std::cout << "Message: " << msg << std::endl;
        
    } else {
        std::cerr << "Error: Missing expected fields in JSON response." << std::endl;
    }

    // 释放 JSON 对象
    cJSON_Delete(json_data);
}

std::string boolToString(bool value) {
    return value ? "1" : "0";
}

//添加入参、时间和状态lnk202411-4
void connectlog_pgsql(char* id,char* datetime,int status)
{
	/*QString pgsql;
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_comm_status_tr\"(\"terminal_id\",\"statistical_date\",\"comm_status\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',1) ").arg(id).arg(QDateTime::currentDateTime().toString("yyyyMMdd")));
	pgsql.append(QString("on conflict(\"terminal_id\",\"statistical_date\") do update set "));
	pgsql.append(QString("\"comm_status\"= \"%1\".\"%2meas_pq_comm_status_tr\".\"comm_status\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	//cout << pgsql.toAscii().data() << endl;*/
	/*std::vector<std::string> codes;
	codes.push_back("log");
	codes.push_back(std::string(id));
	codes.push_back(QDateTime::currentDateTime().toString("yyyyMMdd").toStdString());							
	parse_commstatus_write(codes);				
	codes.clear();*/

	//采用状态更新的方式
	//创建响应接收
	char* ptr=NULL;

    // 创建 JSON 对象
    cJSON* jsonObject = cJSON_CreateObject();
	if (jsonObject == NULL) {
        std::cerr << "Failed to create JSON object." << std::endl;
        return;
    }

    // 添加字段到 JSON 对象
    cJSON* id_item = cJSON_CreateString(id);
	if (!id_item) {
    	std::cerr << "Failed to create 'id' string." << std::endl;
    	cJSON_Delete(jsonObject);
    	return;
	}
	cJSON_AddItemToObject(jsonObject, "id", id_item);

    cJSON* datetime_item = cJSON_CreateString(datetime);
	if (!datetime_item) {
    	std::cerr << "Failed to create 'Datetime' string." << std::endl;
    	cJSON_Delete(jsonObject);
    	return;
	}
	cJSON_AddItemToObject(jsonObject, "Datetime", datetime_item);

 	char statusStr[12];  // 足够容纳一个整数（包括负号和 '\0'）   
    sprintf(statusStr, "%d", status);// 使用 sprintf 将 int 转换为字符串
	
	cJSON* status_item = cJSON_CreateString(statusStr);
	if (!status_item) {
    	std::cerr << "Failed to create 'status' string." << std::endl;
    	cJSON_Delete(jsonObject);
    	return;
	}
	cJSON_AddItemToObject(jsonObject, "status", status_item);

    // 将对象添加到数组
    //cJSON_AddItemToArray(jsonArray, jsonObject);

    // 将数组转换为字符串
    //char* jsonString = cJSON_PrintUnformatted(jsonArray);
	char* jsonString = cJSON_Print(jsonObject);
	if (jsonString == NULL) {
        std::cerr << "Failed to print JSON object." << std::endl;
        cJSON_Delete(jsonObject);
        return;
    }

	//std::cout << "jsonString:  " << jsonString << std::endl;////减少多余的打印

	//发送数据到远端	
	SendJsonAPI_web(WEB_COMFLAG, "", jsonString,&ptr);

	//处理返回的数据
	// 检查 ptr 是否为 NULL，避免 std::string 初始化失败
	if (ptr != NULL) {
	    //handleCommentResponse(std::string(ptr));//减少多余的打印
	    free(ptr);  // 如果 SendJsonAPI_web 分配了内存，记得释放
	} else {
	    // 处理 ptr 为 NULL 的情况，例如日志记录或错误处理
	    std::cout << "Error: Received NULL response" << std::endl;
	}

    // 转换为 QString
    QString result = QString::fromStdString(jsonString);

    // 释放内存
    cJSON_Delete(jsonObject);
    free(jsonString); // cJSON_PrintUnformatted使用malloc分配内存
	
}

//新增异常事件 pgsql组装函数 终端id 发生当日时间 存储文件路径
void errorlog_pgsql(char* id, QString time, QString filename)
{
	/*QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_comm_error_tr\"(\"terminal_id\",\"statistical_date\",\"comm_status\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',1,'%3') ").arg(id).arg(time).arg(filename));
	pgsql.append(QString("on conflict(\"terminal_id\",\"statistical_date\") do update set "));
	pgsql.append(QString("\"comm_status\"= \"%1\".\"%2meas_pq_comm_error_tr\".\"comm_status\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << pgsql.toAscii().data() << endl;*/
	/*std::vector<std::string> codes;
	codes.push_back("log");
	codes.push_back(std::string(id));
	codes.push_back(time.toStdString());
	codes.push_back(filename.toStdString());							
	parse_commerror_write(codes);				
	codes.clear();*/
}

//新增暂降触发报告记录
void SoeRptSql(char* id, int state,char* rpt)
{
	/*QDateTime savetime = QDateTime::currentDateTime();

	QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_comm_error_tr\"(\"terminal_id\",\"statistical_date\",\"comm_status\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',%3,'%4') ").arg(id).arg(savetime.toString("yyyyMMdd")).arg(state).arg(rpt));
	pgsql.append(QString("on conflict(\"terminal_id\",\"statistical_date\",\"file_name\") do update set "));
	pgsql.append(QString("\"comm_status\"= %1;").arg(state));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁*/
	/*std::vector<std::string> codes;
	codes.push_back("soe");
	codes.push_back(std::string(id));
	codes.push_back(QDateTime::currentDateTime().toString("yyyyMMdd").toStdString());
	codes.push_back(intToString(state));
	codes.push_back(std::string(rpt));							
	parse_commerror_write(codes);				
	codes.clear();*/
}
//lnk 20241210删除不需要的代码
#if 0 
//合理性数据 pgsql语句生成
QString errorlog_num_pgsql(QString monitorId, QString datatime, QString filename, int count)
{
	/*QString log_pqsql;//待生成的pgsql语句
	log_pqsql.append(QString("insert into \"%1\".\"%2meas_pq_measpoint_rationality_tr\"(\"monitor_id\",\"statistical_date\",\"irrat_num\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	log_pqsql.append(QString("values('%1',date'%2',%3,'%4') ").arg(monitorId).arg(datatime).arg(count).arg(filename));
	log_pqsql.append(QString("on conflict(\"monitor_id\",\"statistical_date\") do nothing;"));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(log_pqsql);
	Sql_data_list_mutex.unlock(); //解锁
	return log_pqsql;*/
	/*std::vector<std::string> codes;
	codes.push_back("log");
	codes.push_back(monitorId.toStdString());
	codes.push_back(datatime.toStdString());
	codes.push_back(intToString(count));
	codes.push_back(filename.toStdString());							
	parse_rationality_write(codes);				
	codes.clear();*/
}

//数值完整性判断 单条pgsql插入语句生成 终端id 插入天数
QString errorlog_dataintegrity_pgsql(QString time, QString datatime,QString monitorId,bool recallflag)
{
	/*int num = 480;
	if (data_timespan_list[monitorId]->msspan != 0) {
		num = 1440 / data_timespan_list[monitorId]->msspan;
	}
	QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_measpoint_intact_tr\"(\"monitor_id\",\"statistical_date\",\"exp_num\",\"act_num\",\"value_time\",\"last_value_time\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',480,1,array[TIMESTAMP'%3'],'%4') ").arg(monitorId).arg(time).arg(datatime).arg(datatime));
	pgsql.append(QString("on conflict(\"monitor_id\",\"statistical_date\") do update set "));
	//pgsql.append(QString("\"value_time\"=(array_cat(EXCLUDED.\"value_time\", \"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\"))[:1440] , \"exp_num\" =  %3 , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%4\".\"%5meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(num).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	if (recallflag == true) {
		if (data_timespan_list[monitorId]->msspan != 0) {
			pgsql.append(QString("\"value_time\"= ARRAY_APPEND(\"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\", '%3') , \"exp_num\" =  %4 , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%5\".\"%6meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(datatime).arg(num).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
		}
		else {
			pgsql.append(QString("\"value_time\"= ARRAY_APPEND(\"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\", '%3') , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%4\".\"%5meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(datatime).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
		}
	}
	else {
		pgsql.append(QString("\"value_time\"= ARRAY_APPEND(\"%1\".\"%2meas_pq_measpoint_intact_tr\".\"value_time\", '%3') , \"exp_num\" =  %4 , \"last_value_time\" = EXCLUDED.\"last_value_time\"  ,\"act_num\"= \"%5\".\"%6meas_pq_measpoint_intact_tr\".\"act_num\" + 1;").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX).arg(datatime).arg(num).arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	}
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	return pgsql;*/
	
	//不再需要这么多入参202411-1lnk，只需要id和时间点，不区分补招和稳态，不需要时间间隔
	/*std::vector<std::string> codes;
	codes.push_back("log");
	codes.push_back(time.toStdString());
	codes.push_back(datatime.toStdString());
	codes.push_back(monitorId.toStdString());
	codes.push_back(boolToString(recallflag));
	codes.push_back(intToString(data_timespan_list[monitorId]->msspan));							
	parse_dataintegrity_write(codes);				
	codes.clear();*/
	
	//创建响应接收
	char* ptr=NULL;

	// 创建 cJSON 对象
    cJSON* jsonArray = cJSON_CreateArray();

    // 创建 JSON 对象
    cJSON* jsonObject = cJSON_CreateObject();
    cJSON_AddStringToObject(jsonObject, "id", monitorId.toStdString().c_str());
    cJSON_AddStringToObject(jsonObject, "date", datatime.toStdString().c_str());

    // 将对象添加到数组
    cJSON_AddItemToArray(jsonArray, jsonObject);

    // 将数组转换为字符串
    char* jsonString = cJSON_PrintUnformatted(jsonArray);

	//发送数据到远端	
	SendJsonAPI_web(WEB_INTEGRITY,"", jsonString,&ptr);

	//处理返回的数据
	// 检查 ptr 是否为 NULL，避免 std::string 初始化失败
	if (ptr != NULL) {
	    handleCommentResponse(std::string(ptr));
	    free(ptr);  // 如果 SendJsonAPI_web 分配了内存，记得释放
	} else {
	    // 处理 ptr 为 NULL 的情况，例如日志记录或错误处理
	    std::cout << "Error: Received NULL response" << std::endl;
	}

    // 转换为 QString
    QString result = QString::fromStdString(jsonString);

    // 释放内存
    cJSON_Delete(jsonArray);
    free(jsonString); // cJSON_PrintUnformatted使用malloc分配内存

    return result;	//返回json打印用
}

//数值匹配率判断 单条pgsql插入语句生成 终端id 插入天数 基础应有 完整应有 基础实际 完整实际
QString errorlog_datamatch_pgsql(QString id, QString time, int BASE_MAT_NUM,int ADV_MAT_NUM,int BASE_ACT_NUM,int ADV_ACT_NUM,QString filename)
{
	/*QString pgsql;//待组装的pgsql语句
	pgsql.append(QString("insert into \"%1\".\"%2meas_pq_measpoint_match_tr\"(\"monitor_id\",\"statistical_date\",\"base_mat_num\",\"adv_mat_num\",\"base_act_num\",\"adv_act_num\",\"file_name\") ").arg(POSTGRES_SCHEMA).arg(POSTGRES_TABLEPREFIX));
	pgsql.append(QString("values('%1',date'%2',%3,%4,%5,%6,'%7') ").arg(id).arg(time).arg(BASE_MAT_NUM).arg(ADV_MAT_NUM).arg(BASE_ACT_NUM).arg(ADV_ACT_NUM).arg(filename));
	pgsql.append(QString("on conflict(\"monitor_id\",\"statistical_date\") do nothing;"));
	//pgsql.append(QString("\"BASE_ACT_NUM\"= %1 , \"ADV_ACT_NUM\"= %2;").arg(BASE_ACT_NUM).arg(ADV_ACT_NUM));
	Sql_data_list_mutex.lock(); //加锁
	Sql_data_list.append(pgsql);
	Sql_data_list_mutex.unlock(); //解锁
	return pgsql;*/
	/*std::vector<std::string> codes;
	codes.push_back("log");
	codes.push_back(id.toStdString());
	codes.push_back(time.toStdString());
	codes.push_back(intToString(BASE_MAT_NUM));
	codes.push_back(intToString(ADV_MAT_NUM));
	codes.push_back(intToString(BASE_ACT_NUM));	
	codes.push_back(intToString(ADV_ACT_NUM));	
	codes.push_back(filename.toStdString());							
	parse_match_write(codes);				
	codes.clear();*/
}
#endif
//lnk202411-5 暂态数据不再使用kafka发送，改成http接口
int transfer_json_qvvr_data(unsigned int func_type, int monitor_id, 
float mag, float dur, long long start_tm, long long end_tm, int dis_kind, //伏值，持续时间，开始时间，结束时间，暂态类型
char* uuid_cfg,char* uuid_dat,			//两个录波文件
char* mp_id,char* Qvvr_rptname,char* devtype) //监测点号，暂态报告名，设备类型
{	
	XmlConfig c_xmlcfg;
	if (xmlinfo_list.contains(devtype)) {
		c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;//查找映射
	}
	else {
		c_xmlcfg = xmlcfg;
	}

	if (strlen(mp_id) == 0) {
		std::cout << "mp_id is null" << std::endl;
		return 0;
	}

	// 存储 uuid_cfg 和 uuid_dat 测试用
    //const char wave_paths[] = {"/comtrade/"};

    // 初始化 cJSON 根对象
    cJSON* root = cJSON_CreateObject();
    // 拼接 JSON 数据
	//不需要数据类型，因为是http接口不是数据队列
    cJSON_AddStringToObject(root, "monitorId", mp_id);
    cJSON_AddNumberToObject(root, "amplitude", mag);
    cJSON_AddNumberToObject(root, "duration", dur * 1000);
    cJSON_AddNumberToObject(root, "eventType", dis_kind);
    // 格式化时间戳为日期字符串（假设时间戳为毫秒）
    char start_time_str[25];
    time_t start_sec = start_tm / 1000;
    struct tm* time_info = localtime(&start_sec);
    strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%d %H:%M:%S", time_info);
    // 添加毫秒部分
    snprintf(start_time_str + strlen(start_time_str), sizeof(start_time_str) - strlen(start_time_str), ".%03lld", start_tm % 1000);
    cJSON_AddStringToObject(root, "startTime", start_time_str);
    cJSON_AddStringToObject(root, "wavePathcfg", uuid_cfg);  // 动态设置波形文件路径
	cJSON_AddStringToObject(root, "wavePathdat", uuid_dat);  // 动态设置波形文件路径
	//添加相别部分
	if (c_xmlcfg.WavePhasicFlag == "1") {
		QString Qvvr_Rptname;//转换为qstring格式
		Qvvr_Rptname.append(Qvvr_rptname);
		if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicA) != -1) {		//查找映射配置是否在报告名中出现
			cJSON_AddStringToObject(root, "phase", "A"); //拼接 相别
		}
		else if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicB) != -1) {
			cJSON_AddStringToObject(root, "phase", "B"); //拼接 相别
		}
		else if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicC) != -1) {
			cJSON_AddStringToObject(root, "phase", "C"); //拼接 相别
		}
		else {
			cJSON_AddStringToObject(root, "phase", "unknow"); //拼接 相别
		}
	}
	else {
		cJSON_AddStringToObject(root, "phase", "unknow"); //拼接 相别
	}
    // 将 cJSON 对象转换为字符串
    char* json_string = cJSON_Print(root);
    printf("%s\n", json_string);  // 输出 JSON 字符串
    // 发送到暂态接口
    char* ptr = NULL;
    SendJsonAPI_web(WEB_EVENT, "", json_string, &ptr);
    // 处理返回的数据
    // 检查 ptr 是否为 NULL，避免 std::string 初始化失败
	if (ptr != NULL) {
	    handleCommentResponse(std::string(ptr));
	    free(ptr);  // 如果 SendJsonAPI_web 分配了内存，记得释放
	} else {
	    // 处理 ptr 为 NULL 的情况，例如日志记录或错误处理
	    std::cout << "Error: Received NULL response" << std::endl;
		// 释放内存
    	cJSON_Delete(root);
    	free(json_string);
		return 0;
	}
    // 释放内存
    cJSON_Delete(root);
    free(json_string);

	/*Ckafka_data_t KafkaData; //kafka发送数据结构类对象
	KafkaData.monitor_id = monitor_id;
	KafkaData.mp_id = mp_id;

    KafkaData.strTopic = "Event"; //kafka发送主题
	
	KafkaData.strText.append("{"); //拼接 json起始

	if (400 == func_type || 500 == func_type || 600 == func_type || 700 == func_type) //三、补招历史数据 ——> MMS_Recall	
		KafkaData.strText.append("\"DATA_TYPE\":\"04\", "); //拼接 数据类型
	else
		KafkaData.strText.append("\"DATA_TYPE\":\"04\", "); //拼接 数据类型

	KafkaData.strText.append(QString("\"Monitor\":\"%1\", ").arg(mp_id)); //拼接 json监测点

	KafkaData.strText.append(QString("\"Value\":{")); //拼接 json监测点
	KafkaData.strText.append(QString("\"FLAG\":%1,").arg(1)); //拼接 剔除标记
	KafkaData.strText.append(QString("\"TIME\":%1,").arg(start_tm)); //拼接 时间
	KafkaData.strText.append("\"VOLTAGE\":{"); //拼接 数据项  例：VOLTAGE
	KafkaData.strText.append(QString("\"MAG\":%1").arg(mag)); //拼接 残余电压，即：特征幅值
	KafkaData.strText.append(QString(", \"DUR\":%1").arg(dur * 1000)); //拼接 持续时间(毫秒)
	KafkaData.strText.append(QString(", \"STARTTIME\":%1").arg(start_tm )); //拼接 开始时间(毫秒)
	KafkaData.strText.append(QString(", \"ENDTIME\":%1").arg(end_tm)); //拼接 结束时间(毫秒)
	KafkaData.strText.append(QString(", \"DISKIND\":\"%1%2\"").arg("0").arg(dis_kind)); //拼接 暂降类型(1210001-暂升 1210002-暂降 1210004-中断 1210003-其他)
	KafkaData.strText.append(QString(", \"CFG_FILE\":\"%1\"").arg(uuid_cfg)); //拼接 cfg波形文件名称
	KafkaData.strText.append(QString(", \"DAT_FILE\":\"%1\"").arg(uuid_dat)); //拼接 dat波形文件名称
	if (c_xmlcfg.WavePhasicFlag == "1") {
		QString Qvvr_Rptname;
		Qvvr_Rptname.append(Qvvr_rptname);
		if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicA) != -1) {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("A")); //拼接 相别
		}
		else if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicB) != -1) {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("B")); //拼接 相别
		}
		else if (Qvvr_Rptname.indexOf(c_xmlcfg.WavePhasicC) != -1) {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("C")); //拼接 相别
		}
		else {
			KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("unknow")); //拼接 相别
		}
	}
	else {
		KafkaData.strText.append(QString(", \"PHASIC\":\"%1\"").arg("unknow")); //拼接 相别
	}

	KafkaData.strText.append("}"); //拼接 json结束
	KafkaData.strText.append("}}"); //拼接 json结束

	printf("transfer json qvvr data: %s==%s \n",KafkaData.strText.toStdString().c_str(), Qvvr_rptname);

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

	return 1;
}

void qvvr_test()
{
	char uuid_cfg[] = {"/comtrade/"};
	char uuid_dat[] = {"/comtrade/"};
	char mp_id[] = {"000cf2a27f3f13f330b9e8690641e7f2"};
	char Qvvr_rptname[] = {"unknow"};
	char devtype[] = {"01"};

	transfer_json_qvvr_data(1, 123456789, 220, 180, 1730894400.123, 1730894580, 1210001,uuid_cfg,uuid_dat,mp_id,Qvvr_rptname,devtype);
}
/*
void integrity_test()
{
	QString time  = "2024-11-6";
	QString datatime  = "2024-11-6 13:13:13";
	QString monitorId = "000cf2a27f3f13f330b9e8690641e7f2";

	errorlog_dataintegrity_pgsql(time,datatime,monitorId,1);
}*/

void comflag_test()
{
	char id[] = {"000cf2a27f3f13f330b9e8690641e7f2"};
	char datetime[] = {"2024-11-6 15:15:15"};
	connectlog_pgsql(id,datetime,1);
}

///////////////////////////////////////////////////lnk2024-10-21////////////////////////////////////////////////////////
void clearXmlConfigAndTopicList(Xmldata* data) {
    // 清空 XmlConfig
    data->xmlcfg = XmlConfig();  // 通过重新赋值重置 xmlcfg

    // 清空 topicList
    list<CTopic*>::iterator it;
    for (it = data->topicList.begin(); it != data->topicList.end(); ++it) {
        delete *it;  // 释放内存
    }
    data->topicList.clear();  // 清空链表
}
//4-配置映射文件//////////////////////////////
void Set_xml_nodeinfo_one(char* dev_type)
{
	bool ret = false;

//如果是新增台账不是初始化，不需要再解析一次默认配置
/*
	//配置无对应xml文件时的默认解析配置
	if (!inited) //初始化 JiangSu_Config.xml 
	{
		QString path;
		path.append("not define");
		ParseXMLConfig2(&xmlcfg, &topicList, path); //调用 ParseXMLConfig() 解析JiangSu_Config.xml配置文件
		inited = true;
	}
*/

	if(xmlinfo_list[QString::fromUtf8(dev_type)] != NULL){	//原来已存在这个类型的节点
		if(xmlinfo_list[QString::fromUtf8(dev_type)]->updataflag == true){	//需要更新

			//将这个点的xmlcfg和topicList删除
			clearXmlConfigAndTopicList(xmlinfo_list[QString::fromUtf8(dev_type)]);

			ret = ParseXMLConfig2(0,&(xmlinfo_list[QString::fromUtf8(dev_type)]->xmlcfg), &(xmlinfo_list[QString::fromUtf8(dev_type)]->topicList), xmlinfo_list[QString::fromUtf8(dev_type)]->xmlbase.MODEL_ID);
			if(!ret)
			{
				std::cout << "!!!! this ledger xml config fail!!!!" << std::endl;
			}
		}
		
	}
	else{
		std::cout << "xmlinfo_list not contain this devtype" << std::endl;
	}
	//添加角形
	if(isdelta_flag){
		if(xmlinfo_list2[QString::fromUtf8(dev_type)] != NULL){	//原来已存在这个类型的节点
			if(xmlinfo_list2[QString::fromUtf8(dev_type)]->updataflag == true){	//需要更新
	
				//将这个点的xmlcfg和topicList删除
				clearXmlConfigAndTopicList(xmlinfo_list2[QString::fromUtf8(dev_type)]);
	
				ret = ParseXMLConfig2(1,&(xmlinfo_list2[QString::fromUtf8(dev_type)]->xmlcfg), &(xmlinfo_list2[QString::fromUtf8(dev_type)]->topicList), xmlinfo_list2[QString::fromUtf8(dev_type)]->xmlbase.MODEL_ID);
				if(!ret)
				{
					std::cout << "!!!! this ledger xml config fail!!!!" << std::endl;
				}
			}
			
		}
		else{
			std::cout << "xmlinfo_list2 not contain this devtype" << std::endl;
		}
	}
		
}
	//4-配置映射文件///////////////////////////////////
