3197 lines
142 KiB
C++
3197 lines
142 KiB
C++
|
||
#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;
|
||
extern std::string G_CONNECT_TOPIC;
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
using namespace std;
|
||
|
||
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 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新增
|
||
//-------------------------------------------------------------------------------------*/
|
||
|
||
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);
|
||
///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
|
||
|
||
//lnk2024-8-16 适配角型接线
|
||
bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QString path) //解析JiangSu_Config.xml配置文件
|
||
{
|
||
//注:①#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]);
|
||
|
||
} //将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
|
||
|
||
//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三相谐波次数 结束
|
||
|
||
}
|
||
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
|
||
|
||
//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三相谐波次数 结束
|
||
|
||
}
|
||
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; //数据属性名
|
||
|
||
std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
|
||
std::cout << dv2->DO.toUtf8().constData() << std::endl; //lnk 输出ppv
|
||
std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
|
||
|
||
//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";
|
||
|
||
cfg->SOEList.push_back(ed);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ("ReportMap" == strTag)//zw修改 2023 - 8 - 15 增加判断 将触发报告的解析移至XML 原配置RptLogCfg.ini取消
|
||
{
|
||
|
||
}
|
||
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"));
|
||
|
||
}
|
||
if ("IED" == strTag)
|
||
{
|
||
cfg->IEDname.append(e.attribute("name"));
|
||
|
||
}
|
||
if ("LDevice" == strTag)
|
||
{
|
||
cfg->LDevicePrefix.append(e.attribute("Prefix"));
|
||
|
||
}
|
||
}
|
||
} //判断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;
|
||
|
||
////lnk2024-8-15 区分星型,角型接线
|
||
if (strcmp(v_wiring_type, "0") == 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 = topicList2;
|
||
}
|
||
}
|
||
|
||
bool shortjumpflag = false;
|
||
bool longjumpflag = false;
|
||
|
||
//zw修改 end
|
||
if (!inited) //初始化 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++;
|
||
//////////////////////////////////////////////////////////lnk20250306为了数据入库,构造数据添加FLAG
|
||
if ("FLAG" == pItem->strItemName) //剔除"FLAG",防止sq相别出现错误指针
|
||
{
|
||
KafkaData.strText.append(QString("\"FLAG\":%1, ").arg(data->flag)); //拼接 json剔除标记,1不剔除,0剔除,默认剔除
|
||
continue;
|
||
}
|
||
//////////////////////////////////////////////////////////
|
||
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("\"%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++;
|
||
//////////////////////////////////////////////////////////lnk20250306为了数据入库,构造数据添加FLAG
|
||
if ("FLAG" == pItem->strItemName) //剔除"FLAG",防止sq相别出现错误指针
|
||
{
|
||
KafkaData.strText.append(QString("\"FLAG\":%1, ").arg(data->flag)); //拼接 json剔除标记,1不剔除,0剔除,默认剔除
|
||
continue;
|
||
}
|
||
//////////////////////////////////////////////////////////
|
||
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;
|
||
}
|
||
} //②-②历史闪变数据解析结束!--------------------------------
|
||
|
||
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("\"%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")); //拼接
|
||
|
||
|
||
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数据值(角度值)
|
||
|
||
}
|
||
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 << "历史稳态数据值拼接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; //结束该函数,停止后续代码执行
|
||
} //②-①历史稳态数据解析结束!--------------------------------
|
||
} //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("\"%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("\"%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")); //拼接
|
||
|
||
|
||
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数据值(角度值)
|
||
|
||
}
|
||
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 << "历史稳态数据值拼接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; //结束该函数,停止后续代码执行
|
||
} //②-①历史稳态数据解析结束!--------------------------------
|
||
} //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;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
}
|
||
//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(devtype) &&
|
||
xmlinfo_list[devtype] != NULL && // 先检查指针是否为空
|
||
!xmlinfo_list[devtype]->xmlbase.MODEL_ID.isNull() && // 确保 QString 不是 NULL
|
||
!xmlinfo_list[devtype]->xmlbase.MODEL_ID.isEmpty() && // 确保字符串不为空
|
||
xmlinfo_list[devtype]->xmlbase.MODEL_ID.trimmed().length() >= 4) { //确保modelid存在lnk20250313
|
||
cout << "!!!!!!!!!! xmlinfo_list.contains(devtype) == 1 !!!!!!!!!!!" << endl;
|
||
QByteArray byteArray = xmlinfo_list[devtype]->xmlbase.MODEL_ID.toLocal8Bit();//易崩溃点,一定要确保modelid存在lnk20250313
|
||
char* charArray = new char[byteArray.size()+1];//分配内存时+1防止内存泄漏lnk20250305
|
||
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) && xmlinfo_list[type] != NULL) {
|
||
cout << "!!!!!!!!!! Get_IED xmlinfo_list.contains(devtype) == 1 !!!!!!!!!!!" << endl;
|
||
|
||
// 确保 xmlcfg 及其成员非空
|
||
if (xmlinfo_list[type]->xmlcfg.IEDname.isNull() || xmlinfo_list[type]->xmlcfg.LDevicePrefix.isNull()) {
|
||
cout << "Error: IEDname or LDevicePrefix is NULL in Get_IED!" << endl;
|
||
return NULL;
|
||
}
|
||
|
||
QString ied;
|
||
ied.append(xmlinfo_list[type]->xmlcfg.IEDname); // PQMonitor
|
||
ied.append(xmlinfo_list[type]->xmlcfg.LDevicePrefix);
|
||
ied.append("%d");
|
||
|
||
QByteArray byteArray = ied.toLocal8Bit();
|
||
|
||
if (byteArray.isEmpty()) {
|
||
cout << "Error: Generated QByteArray is empty!" << endl;
|
||
return NULL;
|
||
}
|
||
|
||
// 分配内存,确保足够大小并安全拷贝
|
||
char* charArray = new char[byteArray.size() + 1];
|
||
if (!charArray) {
|
||
cout << "Error: Memory allocation failed!" << endl;
|
||
return NULL;
|
||
}
|
||
|
||
memcpy(charArray, byteArray.data(), byteArray.size());
|
||
charArray[byteArray.size()] = '\0'; // 确保字符串以 '\0' 结尾
|
||
|
||
return charArray;
|
||
}
|
||
else {
|
||
cout << "!!!!!!!!!! Get_IED xmlinfo_list.contains(devtype) == 0 !!!!!!!!!!!" << endl;
|
||
|
||
QString ied;
|
||
ied.append(xmlcfg.IEDname);
|
||
ied.append(xmlcfg.LDevicePrefix);
|
||
ied.append("%d");
|
||
QByteArray byteArray = ied.toLocal8Bit();
|
||
char* charArray = new char[byteArray.size()+1];//分配内存时+1防止内存泄漏lnk20250305
|
||
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) && xmlinfo_list[type] != NULL) { // 确保类型存在且不为空
|
||
if (xmlinfo_list[type]->xmlcfg.LDevicePrefix.isNull() || xmlinfo_list[type]->xmlcfg.LDevicePrefix.isEmpty()) {
|
||
cout << "Error: LDevicePrefix is NULL or empty in Get_IED!" << endl;
|
||
return NULL;
|
||
}
|
||
|
||
QString ied;
|
||
ied.append(xmlinfo_list[type]->xmlcfg.LDevicePrefix); // 使用解析列表的终端前缀
|
||
ied.append("%d");
|
||
|
||
QByteArray byteArray = ied.toLocal8Bit();
|
||
|
||
if (byteArray.isEmpty()) {
|
||
cout << "Error: Generated QByteArray is empty!" << endl;
|
||
return NULL;
|
||
}
|
||
|
||
// 分配内存,确保足够大小
|
||
char* charArray = new char[byteArray.size() + 1];
|
||
if (!charArray) {
|
||
cout << "Error: Memory allocation failed!" << endl;
|
||
return NULL;
|
||
}
|
||
|
||
memcpy(charArray, byteArray.data(), byteArray.size());
|
||
charArray[byteArray.size()] = '\0'; // 确保字符串以 '\0' 结尾
|
||
|
||
return charArray;
|
||
}
|
||
else {
|
||
|
||
QString ied;
|
||
ied.append(xmlcfg.LDevicePrefix);//使用默认解析配置的终端前缀
|
||
ied.append("%d");
|
||
QByteArray byteArray = ied.toLocal8Bit();
|
||
char* charArray = new char[byteArray.size()+1];//分配内存时+1防止内存泄漏lnk20250305
|
||
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)
|
||
{
|
||
|
||
//创建响应接收
|
||
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, "date", 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);
|
||
|
||
|
||
char* jsonString = cJSON_Print(jsonObject);
|
||
if (jsonString == NULL) {
|
||
std::cerr << "Failed to print JSON object." << std::endl;
|
||
cJSON_Delete(jsonObject);
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
//使用mq
|
||
Ckafka_data_t connect_info;
|
||
connect_info.strTopic = QString::fromStdString(G_CONNECT_TOPIC);
|
||
connect_info.strText = QString::fromStdString(std::string(jsonString));
|
||
|
||
if(g_node_id == STAT_DATA_BASE_NODE_ID){//稳态才上传
|
||
kafka_data_list_mutex.lock(); //加锁
|
||
kafka_data_list.append(connect_info); //添加 kafka发送链表
|
||
kafka_data_list_mutex.unlock(); //解锁
|
||
}
|
||
|
||
// 释放内存
|
||
cJSON_Delete(jsonObject);
|
||
free(jsonString); // cJSON_PrintUnformatted使用malloc分配内存
|
||
|
||
}
|
||
|
||
//lnk202411-5 暂态数据不再使用kafka发送,改成http接口
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////暂态事件放入文件
|
||
// 下面这部分是你要在原函数中“插入的新增功能”所需的辅助函数
|
||
// *****************************************************************************************
|
||
// 获取指定目录下所有文件的信息(文件名、修改时间、大小),以便后续做删除或判断文件总大小
|
||
struct FileInfo {
|
||
std::string fileName;
|
||
time_t modTime; // 上次修改时间
|
||
long long fileSize; // 文件大小
|
||
};
|
||
|
||
// 扫描目录,获取该目录下所有普通文件的信息
|
||
static void getDirectoryFilesInfo(const std::string &dirPath, std::vector<FileInfo> &fileList)
|
||
{
|
||
DIR* dp = opendir(dirPath.c_str());
|
||
if (!dp) {
|
||
std::cerr << "Failed to get info from : " << dirPath << std::endl;
|
||
return; // 打开失败则直接返回
|
||
}
|
||
|
||
struct dirent* entry = NULL;
|
||
while ((entry = readdir(dp)) != NULL) {
|
||
// 跳过 . 和 ..
|
||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||
continue;
|
||
}
|
||
|
||
// 拼出完整路径
|
||
std::string fullPath = dirPath + entry->d_name;
|
||
|
||
// 获取文件信息
|
||
struct stat st;
|
||
if (stat(fullPath.c_str(), &st) == 0) {
|
||
if (S_ISREG(st.st_mode)) {
|
||
FileInfo fi;
|
||
fi.fileName = fullPath; // 包含路径
|
||
fi.modTime = st.st_mtime; // 修改时间
|
||
fi.fileSize = (long long)st.st_size; // 文件大小
|
||
|
||
fileList.push_back(fi);
|
||
}
|
||
}
|
||
}
|
||
closedir(dp);
|
||
}
|
||
|
||
// 将 JSON 字符串写入指定文件
|
||
// 注意此处仅做简单演示,实际项目中可加更多错误处理、日志输出等
|
||
static void writeJsonToFile(const char* filePath, const char* jsonString)
|
||
{
|
||
FILE* fp = fopen(filePath, "w");
|
||
if (!fp) {
|
||
std::cerr << "Failed to write in file : " << filePath << std::endl;
|
||
return;
|
||
}
|
||
fprintf(fp, "%s", jsonString);
|
||
fclose(fp);
|
||
}
|
||
|
||
// 检查 qvvr 目录下文件总大小,若超过 10M 则删除最老的一个文件
|
||
// 注意:该逻辑严格按照你需求“只删一个最老的文件”来实现,而不是循环删到小于10M
|
||
static void checkAndRemoveOldestIfNeeded(const std::string &dirPath, long long maxBytes)
|
||
{
|
||
// 1) 判断目录是否存在,不存在则尝试创建
|
||
{
|
||
struct stat st;
|
||
// 调用 stat() 判断是否存在
|
||
if (stat(dirPath.c_str(), &st) == -1) {
|
||
if (errno == ENOENT) {
|
||
// 目录不存在,尝试创建
|
||
// 注意:mkdir 只会创建最后一级目录,若需要递归创建父目录,请自行扩展
|
||
if (mkdir(dirPath.c_str(), 0777) != 0) {
|
||
// 若 mkdir 失败,可根据实际需求进行日志输出或错误处理
|
||
std::cerr << "Failed to create directory: " << dirPath << std::endl;
|
||
return; // 创建失败则直接返回,避免后续操作报错
|
||
}
|
||
} else {
|
||
// stat() 调用出错,但并非 ENOENT,可根据需求处理
|
||
std::cerr << "stat error: " << strerror(errno) << std::endl;
|
||
return;
|
||
}
|
||
}
|
||
else {
|
||
// 如果能 stat 到 dirPath,需要再判断是否真的是个“目录”而非普通文件
|
||
if (!S_ISDIR(st.st_mode)) {
|
||
// 存在同名的非目录文件,无法作为目录使用
|
||
std::cerr << dirPath << " exists but is not a directory." << std::endl;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// ============== 以下是原有的逻辑 ==============
|
||
// 获取目录下所有文件信息
|
||
std::vector<FileInfo> fileList;
|
||
getDirectoryFilesInfo(dirPath, fileList);
|
||
|
||
// 计算总大小
|
||
long long totalSize = 0;
|
||
for (size_t i = 0; i < fileList.size(); ++i) {
|
||
totalSize += fileList[i].fileSize;
|
||
}
|
||
|
||
// 如果超过阈值,则删除最老的那个
|
||
if (totalSize > maxBytes && !fileList.empty()) {
|
||
// 按修改时间升序排序,最老(修改时间最早)的排在最前面
|
||
std::sort(fileList.begin(), fileList.end(),
|
||
// C++98 的比较写法
|
||
static_cast<bool(*)(const FileInfo&, const FileInfo&)>(
|
||
// 不能使用lambda,用函数指针
|
||
// 比较函数
|
||
(bool (*)(const FileInfo&, const FileInfo&))[] (const FileInfo &a, const FileInfo &b) {
|
||
return a.modTime < b.modTime;
|
||
}
|
||
)
|
||
);
|
||
|
||
// 删掉第一个(最老的文件)
|
||
remove(fileList[0].fileName.c_str());
|
||
}
|
||
}
|
||
|
||
// 扫描目录下的离线文件,依次读取并发送;若发送成功则删除该文件,发送不成功则保留
|
||
static void scanAndResendOfflineFiles(const std::string &dirPath)
|
||
{
|
||
// 获取目录下所有文件信息
|
||
std::vector<FileInfo> fileList;
|
||
|
||
std::cout << "getDirectoryFilesInfo" << std::endl;
|
||
getDirectoryFilesInfo(dirPath, fileList);
|
||
|
||
std::cout << "send every file" << std::endl;
|
||
// 逐个文件尝试重发
|
||
for (size_t i = 0; i < fileList.size(); ++i) {
|
||
// 读取文件内容(即之前存的 JSON)
|
||
FILE* fp = fopen(fileList[i].fileName.c_str(), "r");
|
||
if (!fp) {
|
||
std::cerr << " fail to open exsist file " << fileList[i].fileName << std::endl;
|
||
continue;
|
||
}
|
||
|
||
// 读取到内存
|
||
std::string jsonContent;
|
||
char buf[1024];
|
||
while (!feof(fp)) {
|
||
if (fgets(buf, sizeof(buf), fp)) {
|
||
jsonContent += buf;
|
||
}
|
||
}
|
||
fclose(fp);
|
||
|
||
std::cout << "send jsonContent" << jsonContent << std::endl;
|
||
|
||
// 尝试发送
|
||
char* ptr = NULL; // 接收返回
|
||
SendJsonAPI_web(WEB_EVENT, "", jsonContent.c_str(), &ptr);
|
||
if (ptr != NULL) {
|
||
|
||
cJSON* j_r = cJSON_Parse(ptr);
|
||
if (j_r == NULL) {
|
||
std::cout << "old file send fail" << std::endl;
|
||
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
|
||
handleCommentResponse(std::string(ptr));
|
||
}
|
||
else{
|
||
std::cout << "old file send success,remove it" << std::endl;
|
||
// 删除文件
|
||
remove(fileList[i].fileName.c_str());
|
||
|
||
free(j_r);
|
||
}
|
||
|
||
}
|
||
else {
|
||
// 发送失败,保留文件,以便下次重试
|
||
std::cout << "old file send fail" << std::endl;
|
||
}
|
||
free(ptr);
|
||
}
|
||
}
|
||
// *****************************************************************************************
|
||
|
||
std::string FormatTimeForFilename(const std::string& timeStr) {
|
||
std::string result;
|
||
for (char c : timeStr) {
|
||
if (isdigit(c)) {
|
||
result += c;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
// ======================== 原先的函数 ========================
|
||
int transfer_json_qvvr_data(unsigned int func_type, int monitor_id,
|
||
double mag, double 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;
|
||
}
|
||
|
||
cJSON* root = cJSON_CreateObject();
|
||
cJSON_AddStringToObject(root, "monitorId", mp_id);
|
||
cJSON_AddNumberToObject(root, "amplitude", mag);
|
||
cJSON_AddNumberToObject(root, "duration", dur);
|
||
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);
|
||
cJSON_AddStringToObject(root, "wavePath", uuid_dat);
|
||
|
||
if (c_xmlcfg.WavePhasicFlag == "1") {
|
||
QString Qvvr_Rptname;
|
||
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");
|
||
}
|
||
|
||
char* json_string = cJSON_Print(root);
|
||
printf("%s\n", json_string); // 输出 JSON 字符串
|
||
|
||
// 发送到暂态接口
|
||
char* ptr = NULL;
|
||
SendJsonAPI_web(WEB_EVENT, "", json_string, &ptr);
|
||
|
||
// ================ 插入新功能 =========================
|
||
// ********** 新增功能开始 **********
|
||
if(ptr != NULL)
|
||
{
|
||
cJSON* j_r = cJSON_Parse(ptr);
|
||
// 如果发送失败(j_r == NULL),则把当前 json 存入指定目录(/FeProject/dat/qvvr/)
|
||
if (j_r == NULL) {
|
||
std::cout << "qvvr send fail ,store in local" << std::endl;
|
||
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M,若超过则删除最老的一个文件
|
||
std::string qvvrDir = "/FeProject/dat/qvvr/";
|
||
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
|
||
|
||
// 2) 将此条 json 存为文件,文件名: mp_id-start_time_str-dis_kind.txt
|
||
// 例如: 502-2025-04-02 15:25:30.123-3.txt (仅示例)
|
||
std::string fileName = qvvrDir;
|
||
fileName += mp_id;
|
||
fileName += "-";
|
||
fileName += FormatTimeForFilename(start_time_str);
|
||
fileName += "-";
|
||
|
||
char buf[64];
|
||
sprintf(buf, "%d", dis_kind);
|
||
fileName += buf;
|
||
fileName += ".txt";
|
||
|
||
// 把 json_string 写入文件
|
||
writeJsonToFile(fileName.c_str(), json_string);
|
||
}
|
||
else{
|
||
free(j_r);
|
||
//后续处理
|
||
}
|
||
}
|
||
// 无论此次发送成功或失败,都要扫描/FeProject/dat/qvvr/目录下的文件并尝试依次重发
|
||
if(1)
|
||
{
|
||
std::string qvvrDir = "/FeProject/dat/qvvr/";
|
||
scanAndResendOfflineFiles(qvvrDir);
|
||
}
|
||
// ********** 新增功能结束 **********
|
||
|
||
// 下面继续原逻辑,不动,处理本次发送
|
||
if (ptr != NULL) {
|
||
std::cout << "current qvvr handle response" << std::endl;
|
||
handleCommentResponse(std::string(ptr));
|
||
free(ptr);
|
||
} 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);
|
||
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 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;
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
}
|
||
|