Files
microser/json/create_json.cpp

3746 lines
164 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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"
#include "../log4cplus/log4.h"//lnk添加log4
///////////////////////////////////////////////////////////////////////lnk20260305数据追踪相关
#include <QHash>
#include <QMutex>
#include <QMutexLocker>
#include <QMapIterator>
#include <QStringList>
// ★MOD: 全局追踪表mp_id -> remaining times
static QMutex g_trace_mutex;
static QHash<QString, int> g_trace_map;
///////////////////////////////////////////////////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;
extern int RECALL_ONLY_FLAG;
//lnk20250115添加台账锁
extern pthread_mutex_t mtx;
bool DEBUGOPEN = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 desc; //soe事件描述
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; //相别值 例7ABC三项8T相
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 ABC配置成一样如果Flag=1ABC根据实际配置
QString WavePhasicA;
QString WavePhasicB;
QString WavePhasicC;
QString TypeOfData; //闪变和统计是否合并 0-分开 1-合并
QString IEDControl; //例LD0 lnk2026-5-13
QString UnitOfTimeUnit; //暂态事件持续事件单位0 - 毫秒 1 - 秒 lnk20260127
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接口//////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////lnk20260305数据追踪
static QString escape_json_string(const QString& s)
{
QString out = s;
out.replace("\\", "\\\\");
out.replace("\"", "\\\"");
out.replace("\r", "\\r");
out.replace("\n", "\\n");
out.replace("\t", "\\t");
return out;
}
// 打开追踪:次数 times比如 5
void process_trace_command(const std::string& id, int times)
{
if (times <= 0) return;
QString qid = QString::fromStdString(id).trimmed();
if (qid.isEmpty()) return;
QMutexLocker lk(&g_trace_mutex);
g_trace_map[qid] = times; // 重新打开就覆盖/重置次数
}
// 查询是否要追踪
static bool trace_is_enabled(const QString& mp_id)
{
QMutexLocker lk(&g_trace_mutex);
auto it = g_trace_map.constFind(mp_id);
return (it != g_trace_map.constEnd() && it.value() > 0);
}
// 命中一次并扣减;扣到 0 自动删
static void trace_hit_and_decrement(const QString& mp_id)
{
QMutexLocker lk(&g_trace_mutex);
auto it = g_trace_map.find(mp_id);
if (it == g_trace_map.end()) return;
int left = it.value();
left -= 1;
if (left <= 0) g_trace_map.erase(it);
else it.value() = left;
}
//追踪61850原始数据
static QString build_mms_multiline_text(const json_block_data* data)
{
QStringList lines;
QMapIterator<QString, double> it(data->mms_str_map);
while (it.hasNext()) {
it.next();
lines << QString("%1 = %2").arg(it.key()).arg(it.value(), 0, 'g', 15);
}
return lines.join("\n");
}
static QString build_trace_json(const json_block_data* data)
{
if (!data) return "{}";
QString mms_text = build_mms_multiline_text(data);
QString json;
json += "{";
json += QString("\"mp_id\":\"%1\",").arg(escape_json_string(data->mp_id));
json += QString("\"func_type\":%1,").arg(data->func_type);
json += QString("\"data_time\":%1,").arg(QString::number((qlonglong)data->time));
json += QString("\"voltage_level\":\"%1\",").arg(QString::number(data->voltage_level, 'f', 6));
json += QString("\"dev_type\":\"%1\",").arg(escape_json_string(data->dev_type));
json += QString("\"mms_text\":\"%1\"").arg(escape_json_string(mms_text));
json += "}";
return json;
}
static void send_trace_if_needed(json_block_data* pdata)
{
const QString mp_id_q = pdata->mp_id;
if (trace_is_enabled(mp_id_q)) {
// 1) 组 json
QString jsonText = build_trace_json(pdata);
// 2) 组 KafkaData
Ckafka_data_t KafkaData;
KafkaData.monitor_id = pdata->monitorId;
KafkaData.mp_id = pdata->mp_id;
KafkaData.strTopic = "DATA_TRACE_TOPIC";
KafkaData.strText = jsonText;
kafka_data_list_mutex.lock();
kafka_data_list.append(KafkaData);
kafka_data_list_mutex.unlock();
// 3) 次数 -1
trace_hit_and_decrement(mp_id_q);
}
}
////////////////////////////////////////////////////////////////////////////////////////////lnk20250710添加频率值存储
struct mp_freq_save {
double G_FREQ;
double FREQ;
double MAX_FREQ;
double MIN_FREQ;
mp_freq_save()
: G_FREQ(0.0), FREQ(0.0), MAX_FREQ(0.0), MIN_FREQ(0.0) {}
};
std::map<std::string,mp_freq_save> mp_freq_save_map;
//lnk20250520 获取映射文件中的一些数据/////////////////////////////////////////////////////////////////
bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg) {
if (!dev_type || !out_cfg)
{
printf("null dev_type");
return false;
}
memset(out_cfg, 0, sizeof(*out_cfg));
QString dev_type_q = QString::fromUtf8(dev_type);
QMap<QString, Xmldata*>::iterator it = xmlinfo_list.find(dev_type_q);
if (it == xmlinfo_list.end() || it.value() == nullptr) {
printf("this dev_type not contain");
return false;
}
const XmlConfig& cfg = it.value()->xmlcfg;
// 将 QString 复制到结构体中的 char[],确保不越界
strncpy(out_cfg->WavePhasicFlag, cfg.WavePhasicFlag.toUtf8().constData(), sizeof(out_cfg->WavePhasicFlag) - 1);
strncpy(out_cfg->WavePhasicA, cfg.WavePhasicA.toUtf8().constData(), sizeof(out_cfg->WavePhasicA) - 1);
strncpy(out_cfg->WavePhasicB, cfg.WavePhasicB.toUtf8().constData(), sizeof(out_cfg->WavePhasicB) - 1);
strncpy(out_cfg->WavePhasicC, cfg.WavePhasicC.toUtf8().constData(), sizeof(out_cfg->WavePhasicC) - 1);
strncpy(out_cfg->UnitOfTimeUnit, cfg.UnitOfTimeUnit.toUtf8().constData(), sizeof(out_cfg->UnitOfTimeUnit) - 1);
strncpy(out_cfg->TypeOfData, cfg.TypeOfData.toUtf8().constData(), sizeof(out_cfg->TypeOfData) - 1); out_cfg->TypeOfData[sizeof(out_cfg->TypeOfData) - 1] = '\0';//lnk20260127
strncpy(out_cfg->ValueOfTimeUnit, cfg.ValueOfTimeUnit.toUtf8().constData(),sizeof(out_cfg->ValueOfTimeUnit) - 1);
strncpy(out_cfg->WaveTimeFlag, cfg.WaveTimeFlag.toUtf8().constData(), sizeof(out_cfg->WaveTimeFlag) - 1);
strncpy(out_cfg->IEDControl, cfg.IEDControl.toUtf8().constData(), sizeof(out_cfg->IEDControl) - 1);//lnk2026-5-13
strncpy(out_cfg->IEDname, cfg.IEDname.toUtf8().constData(), sizeof(out_cfg->IEDname) - 1);
strncpy(out_cfg->LDevicePrefix, cfg.LDevicePrefix.toUtf8().constData(), sizeof(out_cfg->LDevicePrefix) - 1);
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//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)) //①读取TopicHISDATA、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 && "F_S" != it->strItemName && "F_L" != 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"); //相别值(7ABC三相、8T相)
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 || "F_S" == it->strItemName || "F_L" == it->strItemName) && "112" == strPhase) //lnk2024-8-13角型//lnk20250729闪变也要加上角形
{
for (int n = 0; n < 3; n++) //遍历 相别(AB、BC、CA三相)
{
CSequence* sq = new CSequence(); //AB、BC、CA三相别类指针
sq->strSValue = node4.toElement().attribute("value"); //相别值(7ABC三相、112:线AB,BC,CA 8T相)
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;
if(DEBUGOPEN)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;
if(DEBUGOPEN)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->desc = node.toElement().attribute("desc"); //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"));
}
//lnk 20260127
if ("TypeOfData" == strTag)
{
cfg->TypeOfData.append(e.attribute("Unit"));
}
if ("ValueOfTime" == strTag)
{
cfg->ValueOfTimeUnit.append(e.attribute("Unit"));
}
if ("ComtradeFile" == strTag)
{
cfg->WaveTimeFlag.append(e.attribute("WaveTimeFlag"));
}
if ("IEDControl" == strTag)
{
cfg->IEDControl.append(e.attribute("name"));
}
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;
}
}
//调试用
void printCTopicList(const std::list<CTopic*>& ctopic_list) {
int topicIndex = 0;
for (const auto& topic : ctopic_list) {
printf("==== Topic[%d] ====\n", topicIndex++);
printf("Topic name: %s\n", topic->strTopic.toStdString().c_str());
int dtypeIndex = 0;
for (const auto& dtype : topic->DataTypeList) {
printf(" -- DataType[%d] --\n", dtypeIndex++);
printf(" iDataType: %d, type: %s, BaseFlag1: %d, BaseFlag0: %d\n",
dtype->iDataType,
dtype->type.toStdString().c_str(),
dtype->BaseFlag1,
dtype->BaseFlag0);
int monitorIndex = 0;
for (const auto& monitor : dtype->MonitorList) {
printf(" >> Monitor[%d] name: %s, type: %s\n",
monitorIndex++,
monitor->strMonitor.toStdString().c_str(),
monitor->type.toStdString().c_str());
int itemIndex = 0;
for (const auto& item : monitor->ItemList) {
printf(" >> Item[%d] name: %s, value: %s, type: %s\n",
itemIndex++,
item->strItemName.toStdString().c_str(),
item->strItemValue.toStdString().c_str(),
item->type.toStdString().c_str());
int seqIndex = 0;
for (const auto& seq : item->SequenceList) {
printf(" >> Sequence[%d] strSeq: %s, strSValue: %s, type: %s\n",
seqIndex++,
seq->strSeq.toStdString().c_str(),
seq->strSValue.toStdString().c_str(),
seq->type.toStdString().c_str());
int valIndex = 0;
for (const auto& val : seq->DataValueList) {
printf(" >> DataValue[%d] name: %s, value: %f\n",
valIndex++,
val->strName.toStdString().c_str(),
val->fValue);
}
}
}
}
// 如果需要打印 SOEList可加以下
/*
int soeIndex = 0;
for (const auto& soe : dtype->SOEList) {
printf(" >> SOE[%d] ... \n", soeIndex++);
// 打印 SOE 具体字段(如有定义)
}
*/
}
}
}
// ===== DEBUG 打印: mms_str_map (属性名 -> 值) =====
static void print_mms_str_map(const json_block_data* data)
{
if (!data) {
std::cout << "[DBG] json_block_data is NULL\n";
return;
}
std::cout << "\n========== [DBG] json_block_data.mms_str_map ==========\n";
std::cout << "[DBG] monitorId=" << data->monitorId
<< " func_type=" << data->func_type
<< " flag=" << data->flag
<< " time(ms)=" << data->time
<< " voltage_level=" << data->voltage_level
<< "\n";
std::cout << "[DBG] mp_id=" << data->mp_id.toStdString()
<< " dev_type=" << data->dev_type.toStdString()
<< "\n";
std::cout << "[DBG] mms_str_map size=" << data->mms_str_map.size() << "\n";
// Qt4/Qt5 都稳QMapIterator
QMapIterator<QString, double> it(data->mms_str_map);
while (it.hasNext()) {
it.next();
std::cout << " " << it.key().toStdString() << " = " << it.value() << "\n";
}
std::cout << "======================================================\n\n";
}
//20250214添加角型接线处理
int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json生成函数 zw修改 2023-8-11 调整传送json结构 目前仅限历史稳态数据
{
// 刚进函数就打印 mms_str_map
if (DEBUGOPEN) {
print_mms_str_map(data);
}
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;
}
}
if(DEBUGOPEN)printCTopicList(ctopic_list);
//lnk20260127 添加数据类型区分
bool typeofdata = false;
bool data_have_static = data->data_have_statistic;
QString devType = data->dev_type;
QByteArray devTypeBytes = devType.toUtf8();
const char* dev_type_cstr = devTypeBytes.constData();
qDebug() << "[DBG] devType (QString) =" << devType;
qDebug() << "[DBG] devType length =" << devType.length();
qDebug() << "[DBG] devTypeBytes =" << devTypeBytes;
qDebug() << "[DBG] devTypeBytes size =" << devTypeBytes.size();
printf("[DBG] dev_type_cstr = '%s'\n", dev_type_cstr);
XmlConfigC cfg1;
if (get_xml_config_by_dev_type(dev_type_cstr, &cfg1)) {
printf("========== XmlConfigC dump ==========\n");
printf("WavePhasicFlag = '%s'\n", cfg1.WavePhasicFlag);
printf("WavePhasicA = '%s'\n", cfg1.WavePhasicA);
printf("WavePhasicB = '%s'\n", cfg1.WavePhasicB);
printf("WavePhasicC = '%s'\n", cfg1.WavePhasicC);
printf("UnitOfTimeUnit = '%s'\n", cfg1.UnitOfTimeUnit);
printf("TypeOfData = '%s'\n", cfg1.TypeOfData);
printf("ValueOfTimeUnit = '%s'\n", cfg1.ValueOfTimeUnit);
printf("WaveTimeFlag = '%s'\n", cfg1.WaveTimeFlag);
printf("IEDControl = '%s'\n", cfg1.IEDControl);
printf("IEDname = '%s'\n", cfg1.IEDname);
printf("LDevicePrefix = '%s'\n", cfg1.LDevicePrefix);
printf("=====================================\n");
// 如果 TypeOfData == "1",则置 true
if (strcmp(cfg1.TypeOfData, "1") == 0) {
typeofdata = true;
}
} else {
printf("not find this dev_type\n");
}
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=\"03\" " << 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;
}
//lnk20260127
if (typeofdata == false || data_have_static == false) {//不合并则处理完闪变就不处理其他数据,如果有统计数据或者数据类型区分了就继续处理其他数据
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数据值(非角度值)
//lnk20250710添加频率存储
if(dTemp > 0.99){
//printf("pDataValue->strName==========================%s",pDataValue->strName.toStdString().c_str());
if(pDataValue->strName == "G_FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].G_FREQ = dTemp; //保存95值
}
else if(pDataValue->strName == "FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].FREQ = dTemp; //保存平均值
}
else if(pDataValue->strName == "MAX_FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].MAX_FREQ = dTemp; //保存最大值
}
else if(pDataValue->strName == "MIN_FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].MIN_FREQ = dTemp; //保存最小值
}
}
else{
if(pDataValue->strName == "G_FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].G_FREQ; //保存95值
}
else if(pDataValue->strName == "FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].FREQ; //保存平均值
}
else if(pDataValue->strName == "MAX_FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].MAX_FREQ; //保存最大值
}
else if(pDataValue->strName == "MIN_FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].MIN_FREQ; //保存最小值
}
}
//lnk20250710添加频率存储
}
}
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稳态数据结尾
//调试用
if(DEBUGOPEN)cout << KafkaData.strText.toAscii().data() << endl;
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; //接口数据 * 系数
//lnk20250710添加频率存储
if(dTemp > 0.99){
//printf("pDataValue->strName==========================%s",pDataValue->strName.toStdString().c_str());
if(pDataValue->strName == "G_FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].G_FREQ = dTemp; //保存95值
}
else if(pDataValue->strName == "FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].FREQ = dTemp; //保存平均值
}
else if(pDataValue->strName == "MAX_FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].MAX_FREQ = dTemp; //保存最大值
}
else if(pDataValue->strName == "MIN_FREQ") {
mp_freq_save_map[data->mp_id.toStdString()].MIN_FREQ = dTemp; //保存最小值
}
}
else{
if(pDataValue->strName == "G_FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].G_FREQ; //保存95值
}
else if(pDataValue->strName == "FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].FREQ; //保存平均值
}
else if(pDataValue->strName == "MAX_FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].MAX_FREQ; //保存最大值
}
else if(pDataValue->strName == "MIN_FREQ") {
dTemp = mp_freq_save_map[data->mp_id.toStdString()].MIN_FREQ; //保存最小值
}
}
//lnk20250710添加频率存储
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++;
//////////////////////////////////////////////////////////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链表最后一个数据值元素
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稳态数据结尾
//调试用
if(DEBUGOPEN)cout << KafkaData.strText.toAscii().data() << endl;
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 (2 == 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 (3 == 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++;
//////////////////////////////////////////////////////////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
{
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=\"03\" " << 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 (typeofdata == false || data_have_static == false) {//不合并则处理完闪变就不处理其他数据
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稳态数据结尾
//调试用
if(DEBUGOPEN)cout << KafkaData.strText.toAscii().data() << endl;
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;
}
static void format_time_ms(long long ms, char* buf, size_t buf_len)
{
time_t sec = ms / 1000;
int milli = ms % 1000;
struct tm tm_time;
localtime_r(&sec, &tm_time); // 线程安全
snprintf(buf, buf_len,
"%04d-%02d-%02d %02d:%02d:%02d.%03d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
milli);
}
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));
//使用日志接口记录日志
char time_str[64];
format_time_ms(time, time_str, sizeof(time_str));
QByteArray descBa = pEventData->desc.toLocal8Bit();
pthread_mutex_lock(&mtx); std::cout << "ggio hold lock !!!!!!!!!!!" << std::endl;
const char* mp_name_raw = find_mp_name_from_mp_id(mp_id);
pthread_mutex_unlock(&mtx); std::cout << "ggio unlock lock !!!!!!!!!!!" << std::endl;
char mp_name[128];
if (mp_name_raw && mp_name_raw[0] != '\0') {
snprintf(mp_name, sizeof(mp_name), "%s", mp_name_raw);
} else {
snprintf(mp_name, sizeof(mp_name), "unknown");
}
DIY_WARNLOG_CODE(mp_id,2 ,LOG_CODE_GGIO_LPHD,
"监测点:%s(%s),在%s发生事件:%s,事件值:%.2f",
mp_name, mp_id, time_str, descBa.constData(), v);
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);
xmlinfo_list[type]->updataflag = true;//lnk20250820
//调试用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);
xmlinfo_list2[type]->updataflag = true;
}
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);
snprintf(file_name, sizeof(file_name), "%s", FILE_NAME);
file_name[sizeof(file_name) - 1] = '\0';
QString Qsavename;
Qsavename.append("/FeProject/dat/").append(id).append(".xml"); //本地保存路径
char save_name[256];
memset(save_name, 0, 256);
snprintf(save_name, sizeof(save_name), "%s", Qsavename.toAscii().data());
save_name[sizeof(save_name) - 1] = '\0';
cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;
//mq日志
DIY_WARNLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name);
// 调用web获取文件内容
char* fileContent = NULL;
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 && fileContent[0] != '\0') {
// 创建并打开文件
//判断返回的是不是错误json响应
bool isErrorJson = false;
cJSON* root = cJSON_Parse(fileContent);
if (root != NULL) {
cJSON* codeItem = cJSON_GetObjectItem(root, "code");
cJSON* dataItem = cJSON_GetObjectItem(root, "data");
if (codeItem && codeItem->valuestring &&
strcmp(codeItem->valuestring, "A00555") == 0 &&
(dataItem == NULL || (dataItem->type == cJSON_NULL))) {
isErrorJson = true;
std::cerr << "Error: Server returned empty file stream, code=A00555." << std::endl;
DIY_ERRORLOG_CODE("process",0, LOG_CODE_ICD_AND_DOWNLOAD,
"【ERROR】前置下载文件失败服务端返回A00555(文件流为空),文件=%s",
save_name);
}
cJSON_Delete(root);
}
//测试
//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;
//mq日志
DIY_INFOLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【NORMAL】前置下载映射文件%s成功",save_name);
} else {
std::cerr << "Error: Unable to open file for writing." << std::endl;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置写入本地映射文件%s失败",save_name);
}
// 释放分配的内存
free(fileContent);
} else {
std::cerr << "Error: Unable to download file." << std::endl;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH);
}
}
//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); // 从配置文件读取的终端名
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.mp_id = QString::fromLocal8Bit(id);//这里填装置id后续作为key
connect_info.strText = QString::fromStdString(std::string(jsonString));
if((g_node_id == STAT_DATA_BASE_NODE_ID && RECALL_ONLY_FLAG == 0) || (g_node_id == RECALL_HIS_DATA_BASE_NODE_ID && RECALL_ONLY_FLAG == 1)){//稳态或者补招才上传
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 bool writeJsonToFile(const char* filePath, const char* jsonString)
{
FILE* fp = fopen(filePath, "w");
if (!fp) {
//DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】无法将暂态事件写入本地缓存");
std::cerr << "Failed to write in file : " << filePath << std::endl;
return false;
}
fprintf(fp, "%s", jsonString);
fclose(fp);
return true;
}
// 检查 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) {
DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】无法打开本地缓存的暂态事件");
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 && ptr[0] != '\0') {
cJSON* j_r = cJSON_Parse(ptr);
if (j_r == NULL) {
std::cout << "old file send fail" << std::endl;
DIY_WARNLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件失败");
}
else{
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
handleCommentResponse(std::string(ptr));
DIY_WARNLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件成功");
std::cout << "old file send success,remove it" << std::endl;
// 删除文件
remove(fileList[i].fileName.c_str());
cJSON_Delete(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 (NULL == mp_id || 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);
if (json_string == NULL) {
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s暂态事件生成JSON字符串失败",mp_id);
std::cerr << "Failed to print JSON object." << std::endl;
cJSON_Delete(root);
return 0;
}
printf("%s\n", json_string); // 输出 JSON 字符串
// 发送到暂态接口
char* ptr = NULL;
SendJsonAPI_web(WEB_EVENT, "", json_string, &ptr);
// ================ 插入新功能 =========================
// ********** 新增功能开始 **********
if(ptr != NULL && ptr[0] != '\0')
{
cJSON* j_r = cJSON_Parse(ptr);
// 如果发送失败(j_r == NULL),则把当前 json 存入指定目录(/FeProject/dat/qvvr/)
if (j_r == NULL) {
//mq日志
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件",mp_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件
std::string qvvrDir = "/FeProject/dat/qvvr/";
// 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 写入文件
if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
}
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
}
else{
cJSON_Delete(j_r);
//后续处理
}
}
// 无论此次发送成功或失败,都要扫描/FeProject/dat/qvvr/目录下的文件并尝试依次重发
if(1)
{
std::string qvvrDir = "/FeProject/dat/qvvr/";
scanAndResendOfflineFiles(qvvrDir);
}
// ********** 新增功能结束 **********
// 下面继续原逻辑,不动,处理本次发送
if (ptr != NULL && ptr[0] != '\0') {
std::cout << "current qvvr handle response" << std::endl;
handleCommentResponse(std::string(ptr));
free(ptr);
ptr = NULL;
} else {
// 处理 ptr 为 NULL 的情况,例如日志记录或错误处理
std::cout << "Error: Received NULL response" << std::endl;
//mq日志
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件",mp_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件
std::string qvvrDir = "/FeProject/dat/qvvr/";
// 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 写入文件
if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
}
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
// 释放内存
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;
}
}
}