8 Commits
0731 ... DB_1.0

Author SHA1 Message Date
lnk
79676aa90d fix 7-8 recall and better log 2025-09-04 16:26:00 +08:00
lnk
2e4a599200 remove unneed comment 2025-08-25 16:39:43 +08:00
lnk
320cf6d9ba add reply in recall and +5 sec in recall and fix utc time in recall 2025-08-25 11:25:03 +08:00
lnk
e2ee8546c7 fix ledger update 2025-08-20 20:32:17 +08:00
lnk
78f95f2c96 log add rpt control and log control 2025-08-19 20:56:35 +08:00
lnk
2134a43e31 log4 add code and fix comtrade file pair 2025-08-19 16:36:45 +08:00
lnk
9d02a4b031 fix regist log too much 2025-08-12 10:59:15 +08:00
lnk
3b5b14f9ae fix error in recall when hours more than 300 2025-08-01 16:31:57 +08:00
13 changed files with 662 additions and 144 deletions

View File

@@ -555,7 +555,7 @@ void rocketmq_producer_send(const char* strbody, const char* topic)
catch (const std::exception& e) { catch (const std::exception& e) {
std::cerr << "Failed to send message: " << e.what() << std::endl; std::cerr << "Failed to send message: " << e.what() << std::endl;
// 处理发送失败的情况,例如记录日志或重试 // 处理发送失败的情况,例如记录日志或重试
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 mq发送失败,请检查mq配置", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_MQ,"【ERROR】前置的%s%d号进程 mq发送失败,请检查mq配置", get_front_msg_from_subdir(), g_front_seg_index);
} }
} }
#endif #endif

View File

@@ -1462,7 +1462,7 @@ int parse_rpt_log_ini()
//添加判断有的监测点没有cpuno为2直接申请了LD_info[1]没申请LD_info[0] //添加判断有的监测点没有cpuno为2直接申请了LD_info[1]没申请LD_info[0]
if(ied_usr->LD_info[cpuno].LD_name == NULL){ if(ied_usr->LD_info[cpuno].LD_name == NULL){
printf("this ld_info didn't palloc space ,maybe this ledger has problem!"); printf("this ld_info didn't palloc space ,maybe this ledger has problem!");
DIY_ERRORLOG("process","【ERROR】终端%s的监测点序号为%d的监测点没有在写入台账时申请空间,所以无法初始化报告,台账可能存在缺失,跳过这个监测点的报告初始化操作",ied_usr->terminal_id,cpuno + 1); DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1);
continue;//跳过防止崩溃 continue;//跳过防止崩溃
} }
@@ -1804,13 +1804,13 @@ int parse_ledger_update_xml(trigger_update_xml_t* trigger_update_xml)
//加载一个文件的内容到数据结构 //加载一个文件的内容到数据结构
if (!load_ledger_update_from_xml(trigger_update_xml, filename)) { if (!load_ledger_update_from_xml(trigger_update_xml, filename)) {
std::cout << "read /etc/ledgerupdate/" << filename << " success..." << std::endl; std::cout << "read /etc/ledgerupdate/" << filename << " success..." << std::endl;
DIY_WARNLOG("process","【WARN】前置的%s%d号进程 读取台账更新文件成功,开始更新台账", get_front_msg_from_subdir(), g_front_seg_index); DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER_UPDATE,"【WARN】前置的%s%d号进程 读取台账更新文件成功,开始更新台账", get_front_msg_from_subdir(), g_front_seg_index);
} }
//处理过的文件删除掉 //处理过的文件删除掉
if (std::remove(filename.c_str()) != 0) { if (std::remove(filename.c_str()) != 0) {
std::cerr << "Failed to remove file: " << filename << " Error: " << strerror(errno) << std::endl; std::cerr << "Failed to remove file: " << filename << " Error: " << strerror(errno) << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 删除已读取的台账更新文件失败!请检查台账更新文件是否残留在/FeProject/etc/ledgerupdate", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER_UPDATE,"【ERROR】前置的%s%d号进程 删除已读取的台账更新文件失败!请检查台账更新文件是否残留在/FeProject/etc/ledgerupdate", get_front_msg_from_subdir(), g_front_seg_index);
return APR_EGENERAL; return APR_EGENERAL;
} }
else{ else{
@@ -1995,7 +1995,7 @@ int parse_3s_xml(trigger_3s_xml_t* trigger_3s_xml)
printf("/etc/trigger3s/*.xml success...\n"); printf("/etc/trigger3s/*.xml success...\n");
DIY_WARNLOG("process","【WARN】前置读取实时数据触发文件成功,即将注册实时数据报告"); DIY_INFOLOG("process","【WARN】前置读取实时数据触发文件成功,即将注册实时数据报告");
return APR_SUCCESS; return APR_SUCCESS;
} }
@@ -2150,6 +2150,7 @@ int parse_file_names_by_fltnum(int fltnum, char* domname, char** filenames, int
p = strtok(NULL, "_"); //PQM1 p = strtok(NULL, "_"); //PQM1
p = strtok(NULL, "_"); //000001 p = strtok(NULL, "_"); //000001
int nFltNum = atoi(p); //将字符转换成整型 int nFltNum = atoi(p); //将字符转换成整型
printf(">>>>>>>>>>>>>>>>>>get nFltNum from file list is %d", nFltNum);
if (nFltNum == fltnum) { if (nFltNum == fltnum) {
@@ -2183,11 +2184,76 @@ int parse_file_names_by_fltnum(int fltnum, char* domname, char** filenames, int
//WW2023-11-01 end //WW2023-11-01 end
//补招部分//////////////////////////////////////////////////////////////////////////////// //补招部分////////////////////////////////////////////////////////////////////////////////
////////////////////////////20250801
/* 最小块,每次至少扩容这么多;也可以调大一点 */
#define RECALL_CHUNK 64
/* 初始化 */
void recall_xml_init(recall_xml_t *rx) // ★
{
rx->work_cnt = rx->work_cap = 0;
rx->new_cnt = rx->new_cap = 0;
rx->work_recalls = rx->new_recalls = nullptr;
}
/* 若需要,扩容 `*arr` 直到能放下 needed 条记录 */
static int ensure_cap(recall_t **arr, int *cap, int need)
{
if (need <= *cap) return 0;
int new_cap = (*cap) ? (*cap) : 16;
while (new_cap < need) new_cap <<= 1;
/* C++ 里要显式转换 */
void *mem = realloc(*arr, new_cap * sizeof(recall_t));
if (!mem) return -1;
*arr = static_cast<recall_t *>(mem); // ★ 显式 static_cast
*cap = new_cap;
return 0;
}
/* push 到 work / new 数组 */
static int push_work(recall_xml_t *rx, const recall_t *rec)
{
if (ensure_cap(&rx->work_recalls, &rx->work_cap, rx->work_cnt + 1))
return -1;
rx->work_recalls[rx->work_cnt++] = *rec;
return 0;
}
static int push_new(recall_xml_t *rx, const recall_t *rec)
{
if (ensure_cap(&rx->new_recalls, &rx->new_cap, rx->new_cnt + 1))
return -1;
rx->new_recalls[rx->new_cnt++] = *rec;
return 0;
}
/* 释放内存(栈退出前或不用时调用) */
void recall_xml_free(recall_xml_t *rx) // ★
{
for (int i = 0; i < rx->work_cnt; ++i)
free(rx->work_recalls[i].line_id);
for (int i = 0; i < rx->new_cnt; ++i)
free(rx->new_recalls[i].line_id);
free(rx->work_recalls);
free(rx->new_recalls);
recall_xml_init(rx); /* 复位为全 0防止悬挂指针 */
}
////////////////////////////20250801
void parse_recall(recall_xml_t* recall_xml, QString parentTag, QDomElement& recall_e, char* id) void parse_recall(recall_xml_t* recall_xml, QString parentTag, QDomElement& recall_e, char* id)
{ {
recall_t recall; //recall_t recall;//lnk20250801
recall.line_id = id; //recall.line_id = id;
recall_t recall = {0};
recall.line_id = strdup(id); /* malloc 字符串 */
QDateTime start_dt = QDateTime::fromString(recall_e.attribute("StartTime"), "yyyy-MM-dd hh:mm:ss"); QDateTime start_dt = QDateTime::fromString(recall_e.attribute("StartTime"), "yyyy-MM-dd hh:mm:ss");
recall.start_time = start_dt.toMSecsSinceEpoch() / 1000; recall.start_time = start_dt.toMSecsSinceEpoch() / 1000;
@@ -2201,10 +2267,12 @@ void parse_recall(recall_xml_t* recall_xml, QString parentTag, QDomElement& reca
<< " " << recall.start_time << " " << recall.end_time; << " " << recall.start_time << " " << recall.end_time;
if (parentTag == "Work") { if (parentTag == "Work") {
recall_xml->work_recalls[recall_xml->work_recall_num++] = recall; //recall_xml->work_recalls[recall_xml->work_recall_num++] = recall;
push_work(recall_xml, &recall);
} }
else if (parentTag == "New") { else if (parentTag == "New") {
recall_xml->new_recalls[recall_xml->new_recall_num++] = recall; //recall_xml->new_recalls[recall_xml->new_recall_num++] = recall;
push_new(recall_xml, &recall);
} }
} }
@@ -2240,7 +2308,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id)
QDir dir(cfg_dir); QDir dir(cfg_dir);
if (!dir.exists()) { if (!dir.exists()) {
qDebug() << "folder does not exist!"; qDebug() << "folder does not exist!";
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 无法解析补招文件,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法解析补招文件,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index);
return false; return false;
} }
//指定文件后缀名,可指定多种类型 //指定文件后缀名,可指定多种类型
@@ -2256,7 +2324,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id)
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
{ {
qDebug() << "file.open error"; qDebug() << "file.open error";
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 无法打开补招文件%s", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法打开补招文件%s", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str());
continue; //以只读方式打开 continue; //以只读方式打开
} }
bool ret = doc.setContent(&file); bool ret = doc.setContent(&file);
@@ -2264,7 +2332,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id)
if (!ret) if (!ret)
{ {
qDebug() << "doc.setContent error"; qDebug() << "doc.setContent error";
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 无法解析补招文件%s,补招内容无效", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法解析补招文件%s,补招内容无效", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str());
continue; continue;
} }
//将文件内容读到doc中 //将文件内容读到doc中
@@ -2295,7 +2363,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id)
return APR_SUCCESS; return APR_SUCCESS;
} }
void process_recall_config(recall_xml_t* recall_xml) /*void process_recall_config(recall_xml_t* recall_xml)
{ {
int i, j; int i, j;
recall_t* recall; recall_t* recall;
@@ -2328,13 +2396,18 @@ void process_recall_config(recall_xml_t* recall_xml)
if (LD_info->autorecallflag != 0 || LD_info->autorecallcount == 0) { // if (LD_info->autorecallflag != 0 || LD_info->autorecallcount == 0) { //
if (LD_info->autorecallcount != 0) { if (LD_info->autorecallcount != 0) {
for (int j = 0; j < LD_info->autorecallcount; j++) { for (int j = 0; j < LD_info->autorecallcount; j++) {
delete LD_info->autorecall[j]; delete[] LD_info->autorecall[j];//避免重复释放lnk20250801
} }
delete LD_info->autorecall; delete LD_info->autorecall;
LD_info->autorecallcount = 0; LD_info->autorecallcount = 0;
} }
LD_info->autorecallcount = recall_num; LD_info->autorecallcount = recall_num;
LD_info->autorecall = new autorecall_t * [recall_num]; LD_info->autorecall = new autorecall_t * [recall_num];
for (int k = 0; k < recall_num; ++k) {
LD_info->autorecall[k] = nullptr; //避免野指针lnk20250801
}
for (int j = 0; j < recall_num; j++) { for (int j = 0; j < recall_num; j++) {
printf("\n %d ===== %d\n", recall[j].start_time, recall[j].end_time); printf("\n %d ===== %d\n", recall[j].start_time, recall[j].end_time);
LD_info->autorecall[j] = new autorecall_t[1]; LD_info->autorecall[j] = new autorecall_t[1];
@@ -2352,10 +2425,104 @@ void process_recall_config(recall_xml_t* recall_xml)
} }
} }
//调试
printf("== autorecall count = %d ==\n", LD_info->autorecallcount);
for (int j = 0; j < LD_info->autorecallcount; ++j) {
if (LD_info->autorecall[j] == nullptr) {
printf("autorecall[%d] = nullptr !!!\n", j);
} else {
printf("autorecall[%d] = %p | start = %d, end = %d\n",
j, LD_info->autorecall[j],
LD_info->autorecall[j]->start, LD_info->autorecall[j]->end);
}
} }
}
}
}*/
void process_recall_config(recall_xml_t *rx)
{
if (rx->new_cnt) {
/* 预留空间 */
if (ensure_cap(&rx->work_recalls, &rx->work_cap,
rx->work_cnt + rx->new_cnt))
return; /* 内存不足,直接返回 */
memcpy(&rx->work_recalls[rx->work_cnt],
rx->new_recalls,
rx->new_cnt * sizeof(recall_t));
rx->work_cnt += rx->new_cnt;
rx->new_cnt = 0;
}
/* work 列表为空,直接结束 */
if (rx->work_cnt == 0)
return;
recall_t *recall = rx->work_recalls;
int recall_num = rx->work_cnt;
LD_info_t *LD_info = find_LD_info_only_from_mp_id(recall[0].line_id);
printf("\n recall[0].line_id == %s \n", recall[0].line_id);
printf("\n recall[0].start_time == %lld \n", recall[0].start_time);
if (!LD_info || LD_info->read_flag == 0) {
printf("\n Find LD_info == null \n");
return;
}
printf("\n Find LD_info != null \n");
/* 若正在补招中则跳过;否则装载新补招队列 */
if (LD_info->autorecallflag != 0 || LD_info->autorecallcount == 0) {
/* 先释放旧队列 */
if (LD_info->autorecallcount != 0) {
for (int j = 0; j < LD_info->autorecallcount; ++j)
delete[] LD_info->autorecall[j]; /* 原逻辑 */
delete LD_info->autorecall;
LD_info->autorecallcount = 0;
}
/* 重新分配新队列,大小 = recall_num */
LD_info->autorecallcount = recall_num;
LD_info->autorecall = new autorecall_t*[recall_num];
for (int k = 0; k < recall_num; ++k)
LD_info->autorecall[k] = nullptr;
for (int j = 0; j < recall_num; ++j) {
LD_info->autorecall[j] = new autorecall_t[1];
LD_info->autorecall[j]->start = recall[j].start_time;
LD_info->autorecall[j]->end = recall[j].end_time;
LD_info->autorecall[j]->need_steady = recall[j].need_steady;
LD_info->autorecall[j]->need_voltage = recall[j].need_voltage;
printf("\n %lld ===== %lld\n",
recall[j].start_time, recall[j].end_time);
}
LD_info->autorecallflag = 0; /* 重置“正在补招”标志 */
}
/* 调试输出 */
if(DEBUGOPEN){
printf("== autorecall count = %d ==\n", LD_info->autorecallcount);
for (int j = 0; j < LD_info->autorecallcount; ++j) {
if (!LD_info->autorecall[j])
printf("autorecall[%d] = nullptr !!!\n", j);
else
printf("autorecall[%d] = %p | start = %lld, end = %lld\n",
j, LD_info->autorecall[j],
LD_info->autorecall[j]->start,
LD_info->autorecall[j]->end);
}
}
}
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
void WebSocketThread::run() void WebSocketThread::run()
@@ -2743,7 +2910,7 @@ void DeletcRecallXml() {
QDir dir(cfg_dir); QDir dir(cfg_dir);
if (!dir.exists()) { if (!dir.exists()) {
qDebug() << "folder does not exist!"; qDebug() << "folder does not exist!";
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 删除旧的补招文件失败,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 删除旧的补招文件失败,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index);
return; return;
} }
QStringList filter(file_name); QStringList filter(file_name);
@@ -2808,7 +2975,7 @@ void CreateRecallXml()
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
printf("补招查询完成,打开%s失败,无法写入线路补招配置!\n", qstrRecallPath.toAscii().data()); printf("补招查询完成,打开%s失败,无法写入线路补招配置!\n", qstrRecallPath.toAscii().data());
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 无法将补招文件写入补招文件路径/FeProject/etc/recall/", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法将补招文件写入补招文件路径/FeProject/etc/recall/", get_front_msg_from_subdir(), g_front_seg_index);
QMap<QString, QList<CJournalRecall> >().swap(ID_CJournalRecall_Map); QMap<QString, QList<CJournalRecall> >().swap(ID_CJournalRecall_Map);
return; return;
@@ -3536,14 +3703,14 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
// 参数验证 // 参数验证
if (num <= 0) { if (num <= 0) {
std::cerr << "Error: 'num' must be greater than 0." << std::endl; std::cerr << "Error: 'num' must be greater than 0." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的多进程最大进程号为:%d,应该为大于0的整数",num); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的多进程最大进程号为:%d,应该为大于0的整数",num);
return 1; // 返回适当的错误码 return 1; // 返回适当的错误码
} }
index = index - 1; index = index - 1;
if (index < 0 || index >= num) { if (index < 0 || index >= num) {
std::cerr << "Error: 'index' must be in the range [0, num]." << std::endl; std::cerr << "Error: 'index' must be in the range [0, num]." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置当前进程的进程号为:%d,应该为0到最大进程号范围内的整数",index); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置当前进程的进程号为:%d,应该为0到最大进程号范围内的整数",index);
return 1; // 返回适当的错误码 return 1; // 返回适当的错误码
} }
} }
@@ -3551,7 +3718,7 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
// 获取参数 // 获取参数
if (codes.empty()) { if (codes.empty()) {
std::cerr << "Error: 'codes' vector is empty." << std::endl; std::cerr << "Error: 'codes' vector is empty." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程调用web台账接口的入参为空",get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口的入参为空",get_front_msg_from_subdir(), g_front_seg_index);
return 1; return 1;
} }
@@ -3671,7 +3838,7 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
} }
} }
std::cerr << "data 无效或为空数组,重试" << std::endl; std::cerr << "data 无效或为空数组,重试" << std::endl;
DIY_ERRORLOG("process","【ERROR】前置从web接口中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置从web接口中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str());
} }
} }
@@ -3713,7 +3880,7 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
break; // 本地台账解析成功且数组非空 break; // 本地台账解析成功且数组非空
} }
} }
DIY_ERRORLOG("process","【ERROR】前置从本地台账中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置从本地台账中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str());
} }
free(ledger); // root==null释放内容 free(ledger); // root==null释放内容
@@ -3981,13 +4148,13 @@ int parse_device_cfg_web()
//判断是否相等 //判断是否相等
if(max_process_num != max_index){ if(max_process_num != max_index){
if(max_process_num > 0 && max_process_num < 10){ if(max_process_num > 0 && max_process_num < 10){
DIY_WARNLOG("process","【WARN】前置比对台账获取的进程数:%d和本地配置的进程数:%d,不匹配,按照台账进程数重置前置的进程数量",max_process_num,max_index); DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER,"【WARN】前置比对台账获取的进程数:%d和本地配置的进程数:%d,不匹配,按照台账进程数重置前置的进程数量",max_process_num,max_index);
// 调用执行脚本函数 // 调用执行脚本函数
close_listening_socket(); close_listening_socket();
execute_bash("reset", max_process_num, "all"); execute_bash("reset", max_process_num, "all");
} }
else{ else{
DIY_ERRORLOG("process","【ERROR】前置从台账获取的进程数:%d不符合范围1~9,按照本地配置进程数启动进程",max_process_num); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置从台账获取的进程数:%d不符合范围1~9,按照本地配置进程数启动进程",max_process_num);
} }
} }
} }
@@ -4011,7 +4178,7 @@ int parse_device_cfg_web()
//添加提示 //添加提示
std::cout << "!!!!!!!!!!single process can not add any ledger unless reboot!!!!!!!"<< std::endl; std::cout << "!!!!!!!!!!single process can not add any ledger unless reboot!!!!!!!"<< std::endl;
DIY_WARNLOG("process","【WARN】前置的%s%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账",get_front_msg_from_subdir(), g_front_seg_index,IED_COUNT); DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER,"【WARN】前置的%s%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账",get_front_msg_from_subdir(), g_front_seg_index,IED_COUNT);
} }
else{ else{
g_node->clients = (ied_t**)apr_pcalloc(g_cfg_pool, IED_COUNT * sizeof(ied_t*));//g_node->clients 这块大内存空间存储了 count_cfg 个 ied_t* 类型的指针(即一个指针数组)这是(指向内存块的指针)的指针数组 g_node->clients = (ied_t**)apr_pcalloc(g_cfg_pool, IED_COUNT * sizeof(ied_t*));//g_node->clients 这块大内存空间存储了 count_cfg 个 ied_t* 类型的指针(即一个指针数组)这是(指向内存块的指针)的指针数组
@@ -4292,7 +4459,7 @@ int parse_device_cfg_web()
isdelta_flag = 1; //存在一个监测点为角型接线则这个前置就要启动第二个配置列表 isdelta_flag = 1; //存在一个监测点为角型接线则这个前置就要启动第二个配置列表
cout << "monitor_id" << monitor_id << "v_wiring_type:" << line_info.v_wiring_type << "is delta wiring:" << isdelta_flag << endl; cout << "monitor_id" << monitor_id << "v_wiring_type:" << line_info.v_wiring_type << "is delta wiring:" << isdelta_flag << endl;
DIY_WARNLOG("process","【WARN】前置连接的监测点 %s 是角形接线,对应终端为%s 终端类型是%s",line_info.mp_id,ied_usr->terminal_id,ied_usr->dev_type); DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER,"【WARN】前置连接的监测点 %s 是角形接线,对应终端为%s 终端类型是%s",line_info.mp_id,ied_usr->terminal_id,ied_usr->dev_type);
} }
strcpy(line_info.monitor_status, monitor_status); strcpy(line_info.monitor_status, monitor_status);
@@ -4523,7 +4690,7 @@ int parse_model_cfg_web()
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
if(parse_model_web(&icd_model_map,codes)){ if(parse_model_web(&icd_model_map,codes)){
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置", get_front_msg_from_subdir(), g_front_seg_index);
return APR_SUCCESS; //可以使用默认的映射文件所以返回正常 return APR_SUCCESS; //可以使用默认的映射文件所以返回正常
} }
@@ -5007,7 +5174,7 @@ void handleUploadResponse(const std::string& response, char* wavepath) {
cJSON* json_data = cJSON_Parse(response.c_str()); cJSON* json_data = cJSON_Parse(response.c_str());
if (json_data == nullptr) { if (json_data == nullptr) {
std::cerr << "Error parsing response: " << cJSON_GetErrorPtr() << std::endl; std::cerr << "Error parsing response: " << cJSON_GetErrorPtr() << std::endl;
DIY_ERRORLOG("process","【ERROR】前置上传暂态录波文件失败,web返回的消息不是json格式"); DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传暂态录波文件失败,web返回的消息错误,无法解析");
return; return;
} }
@@ -5057,7 +5224,7 @@ void handleUploadResponse(const std::string& response, char* wavepath) {
} }
} else { } else {
std::cerr << "Error: Missing expected fields in JSON response." << std::endl; std::cerr << "Error: Missing expected fields in JSON response." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置上传暂态录波文件失败,web返回的消息没有远端文件名"); DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传暂态录波文件失败,web返回的消息没有远端文件名");
} }
// 释放 JSON 对象 // 释放 JSON 对象
@@ -5174,7 +5341,7 @@ void SendFileWeb(const std::string& strUrl, const char* localpath, const char* c
CURLcode res = curl_easy_perform(curl); CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) { if (res != CURLE_OK) {
std::cerr << "http web failed: " << curl_easy_strerror(res) << std::endl; std::cerr << "http web failed: " << curl_easy_strerror(res) << std::endl;
DIY_ERRORLOG("process","【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath); DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath);
} else { } else {
std::cout << "http web success, response: " << resPost0 << std::endl; std::cout << "http web success, response: " << resPost0 << std::endl;
handleUploadResponse(resPost0, wavepath); // 处理响应 handleUploadResponse(resPost0, wavepath); // 处理响应
@@ -5260,10 +5427,12 @@ int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_i
if (update[i].addr_str != NULL) { if (update[i].addr_str != NULL) {
ied->channel[0].addr = ntohl(inet_addr(update[i].addr_str)); // DEV_IP ied->channel[0].addr = ntohl(inet_addr(update[i].addr_str)); // DEV_IP
strncpy(ied->channel[0].addr_str, update[i].addr_str, LONGNAME - 1); // DEV_IP strncpy(ied->channel[0].addr_str, update[i].addr_str, LONGNAME - 1); // DEV_IP
ied->channel[0].addr_str[LONGNAME-1] = '\0';
printf("ied_usr->addr_str: %s\n", ied->channel[0].addr_str); printf("ied_usr->addr_str: %s\n", ied->channel[0].addr_str);
} else { } else {
ied->channel[0].addr = ntohl(inet_addr("0.0.0.0")); // DEV_IP ied->channel[0].addr = ntohl(inet_addr("0.0.0.0")); // DEV_IP
strncpy(ied->channel[0].addr_str, update[i].addr_str, LONGNAME - 1); // DEV_IP strncpy(ied->channel[0].addr_str, "0.0.0.0", LONGNAME - 1); // DEV_IP
ied->channel[0].addr_str[LONGNAME-1] = '\0';
printf("ied_usr->addr_str: %s\n", ied->channel[0].addr_str); printf("ied_usr->addr_str: %s\n", ied->channel[0].addr_str);
} }
if (update[i].port != NULL) { if (update[i].port != NULL) {
@@ -5691,7 +5860,7 @@ int parse_rpt_log_ini_one(ied_t* ied)
//添加判断有的监测点没有cpuno为2直接申请了LD_info[2-1]没申请LD_info[0] //添加判断有的监测点没有cpuno为2直接申请了LD_info[2-1]没申请LD_info[0]
if(ied_usr->LD_info[cpuno].LD_name == NULL){ if(ied_usr->LD_info[cpuno].LD_name == NULL){
printf("this ld_info didn't palloc space ,maybe this ledger has problem!"); printf("this ld_info didn't palloc space ,maybe this ledger has problem!");
DIY_ERRORLOG("process","【ERROR】终端%s的监测点序号为%d的监测点没有在写入台账时申请空间,所以无法初始化报告,台账可能存在缺失,跳过这个监测点的报告初始化操作",ied_usr->terminal_id,cpuno + 1); DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1);
continue;//跳过防止崩溃 continue;//跳过防止崩溃
} }
@@ -5881,7 +6050,7 @@ void clearLDInfo(LD_info_t *ld_info) {
for (int i = 0; i < ld_info->autorecallcount; ++i) { for (int i = 0; i < ld_info->autorecallcount; ++i) {
if (ld_info->autorecall[i] != nullptr) { if (ld_info->autorecall[i] != nullptr) {
memset(ld_info->autorecall[i], 0, sizeof(autorecall_t)); memset(ld_info->autorecall[i], 0, sizeof(autorecall_t));
delete ld_info->autorecall[i]; //删除数组元素空间,如果有正在补招的内容,则已经申请空间,需要释放 delete[] ld_info->autorecall[i]; //删除数组元素空间,如果有正在补招的内容,则已经申请空间,需要释放lnk20250801
} }
} }
delete ld_info->autorecall; //删除数组空间 delete ld_info->autorecall; //删除数组空间
@@ -5928,6 +6097,9 @@ void clearLDInfo(LD_info_t *ld_info) {
ld_info->rptPstRecvFlag = 0; ld_info->rptPstRecvFlag = 0;
ld_info->rptPstRecvCheckFlag = 0; ld_info->rptPstRecvCheckFlag = 0;
ld_info->registcount = 0;
ld_info->has_logged_regist = 0;
ld_info->read_flag = 0;//监测点无效 ld_info->read_flag = 0;//监测点无效
ld_info->rptcount = 0; ld_info->rptcount = 0;
@@ -5982,6 +6154,9 @@ void clearIedUsr(ied_usr_t *ied_usr) {
ied_usr->time = 0; //台账更新时间 ied_usr->time = 0; //台账更新时间
ied_usr->update_flag = 0; //台账更新标志暂不使用 ied_usr->update_flag = 0; //台账更新标志暂不使用
ied_usr->lastconnectstat = 0;
ied_usr->has_logged_disconnect = 0;
// 清空指针部分,但不清理非空指针 // 清空指针部分,但不清理非空指针
if (ied_usr->LD_info != nullptr) { if (ied_usr->LD_info != nullptr) {
@@ -6021,7 +6196,7 @@ void clear_channel_and_cpuinfo(byte_t chncount, channel_t *channel, byte_t cpuco
memset(channel[i].addr_str, 0, LONGNAME); memset(channel[i].addr_str, 0, LONGNAME);
channel[i].addr = 0; channel[i].addr = 0;
channel[i].port = 0; channel[i].port = 0;
channel[i].status = 0; channel[i].status = CHANNEL_DISCONNECTED;
channel[i].last_ticks = 0; channel[i].last_ticks = 0;
channel[i].last_send_ticks = 0; channel[i].last_send_ticks = 0;
channel[i].ied_id = 0; channel[i].ied_id = 0;
@@ -6751,6 +6926,34 @@ void send_reply_to_kafka(const std::string& guid, const std::string& step, const
kafka_data_list_mutex.unlock(); kafka_data_list_mutex.unlock();
} }
void send_reply_to_kafka_recall(const std::string& guid, const std::string& step, const std::string& result,const std::string& lineIndex,const std::string& recallStartDate,const std::string& recallEndDate){
// 构造 JSON 字符串
std::ostringstream oss;
oss << "{"
<< "\"guid\":\"" << guid << "\","
<< "\"step\":\"" << step << "\","
<< "\"result\":\"" << result << "\","
<< "\"lineIndex\":\"" << lineIndex << "\","
<< "\"recallStartDate\":\"" << recallStartDate << "\","
<< "\"recallEndDate\":\"" << recallEndDate << "\","
<< "\"processNo\":\"" << g_front_seg_index << "\","
<< "\"frontType\":\"" << get_front_type_from_subdir() << "\","
<< "\"nodeId\":\"" << FRONT_INST << "\""
<< "}";
std::string jsonString = oss.str();
// 封装 Kafka 消息
Ckafka_data_t connect_info;
connect_info.strTopic = QString::fromStdString(Topic_Reply_Topic);
connect_info.strText = QString::fromStdString(jsonString);
// 加入发送队列(带互斥锁保护)
kafka_data_list_mutex.lock();
kafka_data_list.append(connect_info);
kafka_data_list_mutex.unlock();
}
void send_heartbeat_to_kafka(const std::string& status) { void send_heartbeat_to_kafka(const std::string& status) {
// 构造 JSON 字符串 // 构造 JSON 字符串
std::ostringstream oss; std::ostringstream oss;

View File

@@ -127,6 +127,9 @@ bool DebugSwitch::match(const std::string& logger_name, int level, int logtype)
std::map<std::string, TypedLogger> logger_map; std::map<std::string, TypedLogger> logger_map;
DebugSwitch g_debug_switch; DebugSwitch g_debug_switch;
// ★新增:定义 TLS 变量,默认 0
LOG_TLS int g_log_code_tls = 0;
class SendAppender : public Appender { class SendAppender : public Appender {
protected: protected:
void append(const spi::InternalLoggingEvent& event) { void append(const spi::InternalLoggingEvent& event) {
@@ -143,6 +146,9 @@ protected:
else else
level_str = "terminal"; level_str = "terminal";
// ★读取 TLS 中的 code在打日志的线程里由宏设定
int code = g_log_code_tls; // 若未显式传入,则为 0
if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) { if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) {
std::ostringstream oss; std::ostringstream oss;
oss << "{\"processNo\":\"" << intToString(g_front_seg_index) oss << "{\"processNo\":\"" << intToString(g_front_seg_index)
@@ -152,6 +158,8 @@ protected:
<< "\",\"grade\":\"" << get_level_str(level) << "\",\"grade\":\"" << get_level_str(level)
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data") << "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data")
<< "\",\"frontType\":\"" << get_front_type_from_subdir() << "\",\"frontType\":\"" << get_front_type_from_subdir()
// ★新增:输出 code 字段(整型)
<< "\",\"code\":\"" << code
<< "\",\"log\":\"" << escape_json(msg) << "\"}"; << "\",\"log\":\"" << escape_json(msg) << "\"}";
std::string jsonString = oss.str(); std::string jsonString = oss.str();
@@ -332,7 +340,7 @@ void init_loggers_bydevid(const char* dev_id)
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM); logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA); logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
DIY_WARNLOG(device_key_d.c_str(),"WARN】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); DIY_INFOLOG(device_key_d.c_str(),"NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
} }
// 初始化监测点 // 初始化监测点
@@ -361,7 +369,7 @@ void init_loggers_bydevid(const char* dev_id)
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM); logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA); logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
DIY_WARNLOG(mon_key_d.str().c_str(),"WARN】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); DIY_INFOLOG(mon_key_d.str().c_str(),"NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
} }
} }
@@ -410,7 +418,7 @@ void init_loggers() {
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM); logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA); logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
DIY_WARNLOG(device_key_d.c_str(),"WARN】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); DIY_INFOLOG(device_key_d.c_str(),"NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
// 初始化监测点 // 初始化监测点
// 监测点 logger 名称格式monitor.<mp_id>.COM / .DATA // 监测点 logger 名称格式monitor.<mp_id>.COM / .DATA
@@ -435,7 +443,7 @@ void init_loggers() {
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM); logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA); logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
DIY_WARNLOG(mon_key_d.str().c_str(),"WARN】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); DIY_INFOLOG(mon_key_d.str().c_str(),"NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
} }
@@ -527,6 +535,10 @@ extern "C" {
send_reply_to_kafka(std::string(guid), std::string(step), std::string(result)); send_reply_to_kafka(std::string(guid), std::string(step), std::string(result));
} }
void send_reply_to_kafka_recall_c(const char* guid, const char* step, const char* result,const char* lineIndex,const char* recallStartDate,const char* recallEndDate) {
send_reply_to_kafka_recall(std::string(guid), std::string(step), std::string(result),std::string(lineIndex), std::string(recallStartDate), std::string(recallEndDate));
}
//标准化日志接口 //标准化日志接口
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...) { void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...) {
// 写入时间 // 写入时间

View File

@@ -620,9 +620,9 @@ bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QSt
dv1->iOffset = e_Value.attribute("Offset").toInt(); //起始序号偏移量(整型) = 江苏电科院臻迪数据项起始序号 - 装置数据项实际起始序号 dv1->iOffset = e_Value.attribute("Offset").toInt(); //起始序号偏移量(整型) = 江苏电科院臻迪数据项起始序号 - 装置数据项实际起始序号
dv1->DO = e_Value.attribute("DO"); //数据对象名 dv1->DO = e_Value.attribute("DO"); //数据对象名
std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl; //std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
std::cout << dv1->DO.toUtf8().constData() << std::endl; //lnk 输出ppv if(DEBUGOPEN)std::cout << dv1->DO.toUtf8().constData() << std::endl; //lnk 输出ppv
std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl; //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->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 dv1->DA = strDANameTemp.replace(substring, QString::number(i - strDAoffset)); //将DA中%-2替换为具体数字 例phs*Har[1]$mag$f
@@ -679,9 +679,9 @@ bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QSt
dv2->DO = e_Value.attribute("DO"); //数据对象名 dv2->DO = e_Value.attribute("DO"); //数据对象名
dv2->DA = strDAName; //数据属性名 dv2->DA = strDAName; //数据属性名
std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl; //std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
std::cout << dv2->DO.toUtf8().constData() << std::endl; //lnk 输出ppv if(DEBUGOPEN)std::cout << dv2->DO.toUtf8().constData() << std::endl; //lnk 输出ppv
std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl; //std::cout << "!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!!!!!ppv!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
//zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown //zw修改 2023 - 8 - 14 为历史数据部分 Value节点新增指标-BaseFlag LimitUp LimitDown
if (e_Value.attributes().contains("BaseFlag")) if (e_Value.attributes().contains("BaseFlag"))
@@ -1710,6 +1710,13 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
while (it != pMonitor->ItemList.end()) while (it != pMonitor->ItemList.end())
{ {
CItem* pItem = *it++; 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相别出现错误指针 if ("TIME" == pItem->strItemName) //剔除"FLAG"防止sq相别出现错误指针
{ {
KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻毫秒 KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻毫秒
@@ -2011,6 +2018,13 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
while (it != pMonitor->ItemList.end()) while (it != pMonitor->ItemList.end())
{ {
CItem* pItem = *it++; 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相别出现错误指针 if ("TIME" == pItem->strItemName) //剔除"FLAG"防止sq相别出现错误指针
{ {
KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻毫秒 KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻毫秒
@@ -2128,6 +2142,13 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
while (it != pMonitor->ItemList.end()) while (it != pMonitor->ItemList.end())
{ {
CItem* pItem = *it++; 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相别出现错误指针 if ("TIME" == pItem->strItemName) //剔除"FLAG"防止sq相别出现错误指针
{ {
KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻毫秒 KafkaData.strText.append(QString("\"TIME\":\"%1\", ").arg(data->time)); //拼接 json发生时刻毫秒
@@ -2612,6 +2633,7 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
Xmldata* config = new Xmldata(); //没找到就插个新的终端类型到列表中 Xmldata* config = new Xmldata(); //没找到就插个新的终端类型到列表中
xmlinfo_list.insert(type, config); xmlinfo_list.insert(type, config);
xmlinfo_list[type]->updataflag = true;//lnk20250820
//调试用lnk20241125 //调试用lnk20241125
cout << "xmlinfo_list insert type:" << type.toStdString() << endl; cout << "xmlinfo_list insert type:" << type.toStdString() << endl;
} }
@@ -2681,7 +2703,7 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl; cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;
//mq日志 //mq日志
DIY_WARNLOG("process","【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name); DIY_WARNLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name);
//20241028 lnk 替换为文件下载web接口 //20241028 lnk 替换为文件下载web接口
//构造文件下载接口参数 //构造文件下载接口参数
@@ -2703,6 +2725,24 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
if (fileContent != NULL) { if (fileContent != NULL) {
// 创建并打开文件 // 创建并打开文件
//判断返回的是不是错误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", LOG_CODE_ICD_AND_DOWNLOAD,
"【ERROR】前置下载文件失败服务端返回A00555(文件流为空),文件=%s",
save_name);
}
cJSON_Delete(root);
}
//测试 //测试
//std::ofstream outFile(downpath, std::ios::binary);//二进制的方式打开 //std::ofstream outFile(downpath, std::ios::binary);//二进制的方式打开
@@ -2713,17 +2753,17 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
outFile.close(); outFile.close();
std::cout << "File saved successfully!" << std::endl; std::cout << "File saved successfully!" << std::endl;
//mq日志 //mq日志
DIY_WARNLOG("process","WARN】前置下载映射文件%s成功",save_name); DIY_INFOLOG("process","NORMAL】前置下载映射文件%s成功",save_name);
} else { } else {
std::cerr << "Error: Unable to open file for writing." << std::endl; std::cerr << "Error: Unable to open file for writing." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置写入本地映射文件%s失败",save_name); DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置写入本地映射文件%s失败",save_name);
} }
// 释放分配的内存 // 释放分配的内存
free(fileContent); free(fileContent);
} else { } else {
std::cerr << "Error: Unable to download file." << std::endl; std::cerr << "Error: Unable to download file." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH); DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH);
} }
} }
@@ -3050,16 +3090,17 @@ static void getDirectoryFilesInfo(const std::string &dirPath, std::vector<FileIn
} }
// 将 JSON 字符串写入指定文件 // 将 JSON 字符串写入指定文件
static void writeJsonToFile(const char* filePath, const char* jsonString) static bool writeJsonToFile(const char* filePath, const char* jsonString)
{ {
FILE* fp = fopen(filePath, "w"); FILE* fp = fopen(filePath, "w");
if (!fp) { if (!fp) {
DIY_ERRORLOG("process","【ERROR】无法将暂态事件写入本地缓存"); //DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】无法将暂态事件写入本地缓存");
std::cerr << "Failed to write in file : " << filePath << std::endl; std::cerr << "Failed to write in file : " << filePath << std::endl;
return; return false;
} }
fprintf(fp, "%s", jsonString); fprintf(fp, "%s", jsonString);
fclose(fp); fclose(fp);
return true;
} }
// 检查 qvvr 目录下文件总大小,若超过 10M 则删除最老的一个文件 // 检查 qvvr 目录下文件总大小,若超过 10M 则删除最老的一个文件
@@ -3140,7 +3181,7 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
// 读取文件内容(即之前存的 JSON) // 读取文件内容(即之前存的 JSON)
FILE* fp = fopen(fileList[i].fileName.c_str(), "r"); FILE* fp = fopen(fileList[i].fileName.c_str(), "r");
if (!fp) { if (!fp) {
DIY_ERRORLOG("process","【ERROR】无法打开本地缓存的暂态事件"); DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】无法打开本地缓存的暂态事件");
std::cerr << " fail to open exsist file " << fileList[i].fileName << std::endl; std::cerr << " fail to open exsist file " << fileList[i].fileName << std::endl;
continue; continue;
} }
@@ -3168,12 +3209,12 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断 // 表示有响应,则可视为成功;根据项目需要可加更精细的判断
handleCommentResponse(std::string(ptr)); handleCommentResponse(std::string(ptr));
DIY_WARNLOG("process","【WARN】前置重发暂态事件失败"); DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件失败");
} }
else{ else{
DIY_WARNLOG("process","【WARN】前置重发暂态事件成功"); DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件成功");
std::cout << "old file send success,remove it" << std::endl; std::cout << "old file send success,remove it" << std::endl;
// 删除文件 // 删除文件
@@ -3283,7 +3324,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
if (j_r == NULL) { if (j_r == NULL) {
//mq日志 //mq日志
DIY_ERRORLOG(full_key_m_d,"【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件",mp_id); DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件",mp_id);
std::cout << "qvvr send fail ,store in local" << std::endl; std::cout << "qvvr send fail ,store in local" << std::endl;
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件 // 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件
@@ -3304,7 +3345,9 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
fileName += ".txt"; fileName += ".txt";
// 把 json_string 写入文件 // 把 json_string 写入文件
writeJsonToFile(fileName.c_str(), json_string); if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id);
}
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024); checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
} }
@@ -3331,7 +3374,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
std::cout << "Error: Received NULL response" << std::endl; std::cout << "Error: Received NULL response" << std::endl;
//mq日志 //mq日志
DIY_ERRORLOG(full_key_m_d,"【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件",mp_id); DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件",mp_id);
std::cout << "qvvr send fail ,store in local" << std::endl; std::cout << "qvvr send fail ,store in local" << std::endl;
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件 // 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件
@@ -3350,7 +3393,9 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
fileName += buf; fileName += buf;
fileName += ".txt"; fileName += ".txt";
// 把 json_string 写入文件 // 把 json_string 写入文件
writeJsonToFile(fileName.c_str(), json_string); if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id);
}
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024); checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
@@ -3403,7 +3448,7 @@ void Set_xml_nodeinfo_one(char* dev_type)
bool ret = false; bool ret = false;
if(xmlinfo_list[QString::fromUtf8(dev_type)] != NULL){ //原来已存在这个类型的节点 if(xmlinfo_list[QString::fromUtf8(dev_type)] != NULL){ //原来已存在这个类型的节点
if(xmlinfo_list[QString::fromUtf8(dev_type)]->updataflag == true){ //需要更新 //if(xmlinfo_list[QString::fromUtf8(dev_type)]->updataflag == true){ //需要更新
//将这个点的xmlcfg和topicList删除 //将这个点的xmlcfg和topicList删除
clearXmlConfigAndTopicList(xmlinfo_list[QString::fromUtf8(dev_type)]); clearXmlConfigAndTopicList(xmlinfo_list[QString::fromUtf8(dev_type)]);
@@ -3413,7 +3458,7 @@ void Set_xml_nodeinfo_one(char* dev_type)
{ {
std::cout << "!!!! this ledger xml config fail!!!!" << std::endl; std::cout << "!!!! this ledger xml config fail!!!!" << std::endl;
} }
} //}
} }
else{ else{
@@ -3422,7 +3467,7 @@ void Set_xml_nodeinfo_one(char* dev_type)
//添加角形 //添加角形
if(isdelta_flag){ if(isdelta_flag){
if(xmlinfo_list2[QString::fromUtf8(dev_type)] != NULL){ //原来已存在这个类型的节点 if(xmlinfo_list2[QString::fromUtf8(dev_type)] != NULL){ //原来已存在这个类型的节点
if(xmlinfo_list2[QString::fromUtf8(dev_type)]->updataflag == true){ //需要更新 //if(xmlinfo_list2[QString::fromUtf8(dev_type)]->updataflag == true){ //需要更新
//将这个点的xmlcfg和topicList删除 //将这个点的xmlcfg和topicList删除
clearXmlConfigAndTopicList(xmlinfo_list2[QString::fromUtf8(dev_type)]); clearXmlConfigAndTopicList(xmlinfo_list2[QString::fromUtf8(dev_type)]);
@@ -3432,7 +3477,7 @@ void Set_xml_nodeinfo_one(char* dev_type)
{ {
std::cout << "!!!! this ledger xml config fail!!!!" << std::endl; std::cout << "!!!! this ledger xml config fail!!!!" << std::endl;
} }
} //}
} }
else{ else{

View File

@@ -93,7 +93,6 @@ mqconsumerThread mqconsumerThrd;//mq消费者线程lnk20241213
OnTimerThread onTimerThrd;//定时线程 OnTimerThread onTimerThrd;//定时线程
extern int g_iSqlListSize; //Sql执行语句链表允许最大元素个数 注Sql链表中元素超过此个数多出元素需移除
extern int FILE_FLAG; extern int FILE_FLAG;
extern int SEND_FLAG; extern int SEND_FLAG;
extern char* BROKER_LIST; extern char* BROKER_LIST;
@@ -999,7 +998,7 @@ int parse_set(const std::string& json_str) {
} }
execute_bash(fun, processNum, frontType); execute_bash(fun, processNum, frontType);
DIY_WARNLOG("process","【WARN】前置的%s%d号进程执行指令:%s,reset表示重启所有进程,add表示添加进程",get_front_msg_from_subdir(), g_front_seg_index,fun.c_str()); DIY_WARNLOG_CODE("process",LOG_CODE_PROCESS_CONTROL,"【WARN】前置的%s%d号进程执行指令:%s,reset表示重启所有进程,add表示添加进程",get_front_msg_from_subdir(), g_front_seg_index,fun.c_str());
//脚本在3秒后执行 //脚本在3秒后执行
//回复消息 //回复消息
@@ -1021,7 +1020,7 @@ int parse_set(const std::string& json_str) {
send_reply_to_kafka(guid,"1","收到删除进程指令,这个进程将会重启 "); send_reply_to_kafka(guid,"1","收到删除进程指令,这个进程将会重启 ");
//上送日志 //上送日志
DIY_WARNLOG("process","【WARN】前置的%s%d号进程执行指令:%s,即将重启",get_front_msg_from_subdir(), g_front_seg_index,fun.c_str()); DIY_WARNLOG_CODE("process",LOG_CODE_PROCESS_CONTROL,"【WARN】前置的%s%d号进程执行指令:%s,即将重启",get_front_msg_from_subdir(), g_front_seg_index,fun.c_str());
apr_sleep(apr_time_from_sec(10)); apr_sleep(apr_time_from_sec(10));
::_exit(-1039); //进程退出 ::_exit(-1039); //进程退出
@@ -1797,7 +1796,7 @@ int myMessageCallbackrtdata(CPushConsumer* consumer, CMessageExt* msg)
if (!parseJsonMessageRT(body, devid, line, realData, soeData, limit)) { if (!parseJsonMessageRT(body, devid, line, realData, soeData, limit)) {
std::cerr << "Failed to parse the JSON message." << std::endl; std::cerr << "Failed to parse the JSON message." << std::endl;
//记录日志 //记录日志
DIY_ERRORLOG("process","【ERROR】前置消费topic:%s_%s的实时触发消息失败,消息的json格式不正确",FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_RT.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_RT_DATA,"【ERROR】前置消费topic:%s_%s的实时触发消息失败,消息的json格式不正确",FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_RT.c_str());
return E_RECONSUME_LATER; return E_RECONSUME_LATER;
} }
@@ -1815,7 +1814,7 @@ int myMessageCallbackrtdata(CPushConsumer* consumer, CMessageExt* msg)
} }
// 创建 XML 文件 // 创建 XML 文件
if (!createXmlFile(dev_index, mp_index, realData, soeData, limit,"new")) { if (!createXmlFile(dev_index, mp_index, realData, soeData, limit,"new")) {
DIY_ERRORLOG("process","【ERROR】前置无法创建实时数据触发文件"); DIY_ERRORLOG_CODE("process",LOG_CODE_RT_DATA,"【ERROR】前置无法创建实时数据触发文件");
std::cerr << "Failed to create the XML file." << std::endl; std::cerr << "Failed to create the XML file." << std::endl;
return E_RECONSUME_LATER; return E_RECONSUME_LATER;
} }
@@ -1856,7 +1855,7 @@ int myMessageCallbackupdate(CPushConsumer* consumer, CMessageExt* msg)
//处理台账更新消息 //处理台账更新消息
std::string updatefilepath = "/home/pq/FeProject/etc/ledgerupdate"; std::string updatefilepath = "/home/pq/FeProject/etc/ledgerupdate";
if(parse_control(body,updatefilepath)){ if(parse_control(body,updatefilepath)){
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程处理topic:%s_%s的台账更新消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_UD.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER_UPDATE,"【ERROR】前置的%s%d号进程处理topic:%s_%s的台账更新消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_UD.c_str());
} }
} }
@@ -1892,7 +1891,7 @@ int myMessageCallbackset(CPushConsumer* consumer, CMessageExt* msg)
//处理进程更新消息 //处理进程更新消息
if(parse_set(body)){ if(parse_set(body)){
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程处理topic:%s_%s的进程控制消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_SET.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_PROCESS_CONTROL,"【ERROR】前置的%s%d号进程处理topic:%s_%s的进程控制消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_SET.c_str());
} }
} }
@@ -1928,7 +1927,7 @@ int myMessageCallbacklog(CPushConsumer* consumer, CMessageExt* msg)
//处理进程更新消息 //处理进程更新消息
if(parse_log(body)){ if(parse_log(body)){
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程处理topic:%s_%s的日志上送消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_LOG.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_LOG_REQUEST,"【ERROR】前置的%s%d号进程处理topic:%s_%s的日志上送消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_LOG.c_str());
} }
} }
@@ -1977,7 +1976,7 @@ int myMessageCallbackrecall(CPushConsumer* consumer, CMessageExt* msg)
} }
else{ else{
std::cerr << "recall data is NULL." << std::endl; std::cerr << "recall data is NULL." << std::endl;
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程处理topic:%s_%s的补招触发消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_RC.c_str()); DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程处理topic:%s_%s的补招触发消息失败,消息的json结构不正确",get_front_msg_from_subdir(), g_front_seg_index,FRONT_INST.c_str(),G_MQCONSUMER_TOPIC_RC.c_str());
} }
} }

View File

@@ -3,6 +3,8 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <log4cplus/mdc.h> // ★新增:需要 MDCGuard
#include <string> #include <string>
#include <map> #include <map>
@@ -52,6 +54,7 @@ extern std::map<std::string, TypedLogger> logger_map;
extern DebugSwitch g_debug_switch; extern DebugSwitch g_debug_switch;
extern void send_reply_to_kafka(const std::string& guid, const std::string& step, const std::string& result); extern void send_reply_to_kafka(const std::string& guid, const std::string& step, const std::string& result);
extern void send_reply_to_kafka_recall(const std::string& guid, const std::string& step, const std::string& result,const std::string& lineIndex,const std::string& recallStartDate,const std::string& recallEndDate);
std::string get_front_type_from_subdir(); std::string get_front_type_from_subdir();
@@ -86,9 +89,25 @@ void log_warn(const char* key, const char* msg);
void log_error(const char* key, const char* msg); void log_error(const char* key, const char* msg);
void send_reply_to_kafka_c(const char* guid, const char* step, const char* result); void send_reply_to_kafka_c(const char* guid, const char* step, const char* result);
void send_reply_to_kafka_recall(const char* guid, const char* step, const char* result,const char* lineIndex,const char* recallStartDate,const char* recallEndDate);
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...); void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
//宏定义 // ====================== ★新增:线程局部变量透传 code ======================
// 说明:使用编译器的 TLS__thread保存当前日志的 code 值。
// 在每次打日志前写入打完后恢复Appender 读取该值写入 JSON。
#if defined(__GNUC__)
#define LOG_TLS __thread
#else
// 若编译器不支持 __thread可替换为 C++11 thread_local但你的工程多为 C++98/C 混编,优先 __thread
#define LOG_TLS __thread
#endif
extern LOG_TLS int g_log_code_tls; // 声明为 TLS 变量,定义见 log4.cpp
// ====================== ★新增结束 ======================
// ====================== 日志宏区域 ======================
// 原始不带 code 的实现(兼容/复用)
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \ #define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \ do { \
char buf[256]; \ char buf[256]; \
@@ -96,11 +115,52 @@ void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
LEVEL_FUNC(KEY, buf); \ LEVEL_FUNC(KEY, buf); \
} while (0) } while (0)
#define DIY_ERRORLOG(KEY, ...) DIY_LOG(log_error, KEY, __VA_ARGS__) // ★新增:带 code 的实现C/C++ 通用,使用 TLS 保存/恢复)
#define DIY_WARNLOG(KEY, ...) DIY_LOG(log_warn, KEY, __VA_ARGS__) #define DIY_LOG_CODE(LEVEL_FUNC, KEY, CODE_INT, ...) \
#define DIY_INFOLOG(KEY, ...) DIY_LOG(log_info, KEY, __VA_ARGS__) do { \
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG(log_debug, KEY, __VA_ARGS__) int __old_code__ = g_log_code_tls; /* 备份旧值 */ \
g_log_code_tls = (int)(CODE_INT); /* 设置本次日志 code */ \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); /* 输出日志 */ \
g_log_code_tls = __old_code__; /* 恢复旧值 */ \
} while (0)
// ★修改:默认宏改为 code=0兼容原有用法
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...);
#define DIY_ERRORLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, CODE_INT, __VA_ARGS__) // ★新增
// ====================== 日志宏区域 ======================
typedef enum LogCode {
LOG_CODE_OTHER = 99, /* 其他类型 */
LOG_CODE_LEDGER = 100, /* 台账类型 */
LOG_CODE_RPTINIT = 101, /* 报告初始化 */
LOG_CODE_ICD_AND_DOWNLOAD = 200, /* ICD 和文件下载类型 */
LOG_CODE_TRANSIENT = 300, /* 暂态发生 */
LOG_CODE_TRANSIENT_COMM = 301, /* 暂态接口 */
LOG_CODE_COMTRADE_FILE = 302, /* 录波文件Comtrade */
LOG_CODE_MQ = 400, /* MQ发送 */
LOG_CODE_RT_DATA = 401, /* 实时数据 */
LOG_CODE_LEDGER_UPDATE = 402, /* 台账更新 */
LOG_CODE_PROCESS_CONTROL = 403, /* 进程控制 */
LOG_CODE_RECALL = 404, /* 补招相关 */
LOG_CODE_LOG_REQUEST = 405, /* 日志请求 */
LOG_CODE_REPORT = 500, /* 报告处理 */
LOG_CODE_COMM = 600, /* 通讯状态 */
LOG_CODE_SPACE_ALARM = 700 /* 空间告警 */
} LogCode;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -232,7 +232,7 @@ int main(int argc, const char **argv)
//char buf[256]; //char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index); //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index);
//log_debug("process", buf); //log_debug("process", buf);
DIY_WARNLOG("process","WARN】前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index); DIY_INFOLOG("process","NORMAL】前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index);
#ifdef _OS_UNIX_ #ifdef _OS_UNIX_
#ifdef QT_NO_DEBUG #ifdef QT_NO_DEBUG
@@ -268,7 +268,7 @@ int main(int argc, const char **argv)
//char buf[256]; //char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index); //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf); //log_error("process", buf);
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv; return rv;
} }
@@ -277,7 +277,7 @@ int main(int argc, const char **argv)
//char buf[256]; //char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index); //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf); //log_error("process", buf);
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv; return rv;
} }
@@ -324,7 +324,7 @@ int main(int argc, const char **argv)
//char buf[256]; //char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的业务线程死锁,退出进程"); //format_log_msg(buf,sizeof(buf),"前置的业务线程死锁,退出进程");
//log_error("process", buf); //log_error("process", buf);
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 业务线程死锁,退出进程", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程 业务线程死锁,退出进程", get_front_msg_from_subdir(), g_front_seg_index);
apr_sleep(apr_time_from_sec(10)); apr_sleep(apr_time_from_sec(10));
exit(-1039); exit(-1039);

View File

@@ -184,7 +184,7 @@ void closeChannel(chnl_usr_t *chnl_usr)
ret = mms_disconnectFromServer(chnl_usr->net_info,&chnl_usr->m_reqCtrl); ret = mms_disconnectFromServer(chnl_usr->net_info,&chnl_usr->m_reqCtrl);
echo_warn("---------end disconnectFromServer!\n"); echo_warn("---------end disconnectFromServer!\n");
DIY_WARNLOG(full_key_t_c,"【WARN】前置与终端%s - ip端口%s:%d 断开连接", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】前置与终端%s - ip端口%s:%d 断开连接", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
if (ret != SD_SUCCESS){ if (ret != SD_SUCCESS){
echo_warn("---------disconnectFromServer success!\n"); echo_warn("---------disconnectFromServer success!\n");
@@ -308,11 +308,6 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
{ {
LD_info = &(ied_usr->LD_info[cpuno]); //遍历监测点 LD_info = &(ied_usr->LD_info[cpuno]); //遍历监测点
if (LD_info->cpuno==0)
continue;
for(rpt_no=0 ; rpt_no<LD_info->rptcount; rpt_no++) { //遍历报告(映射文件中读取的报告控制)
//监测点日志的key,lnk20250526 //监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间 char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间 char full_key_m_d[256]; // 分配足够空间
@@ -320,6 +315,28 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id); snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526 //监测点日志的key,lnk20250526
if (LD_info->cpuno==0){
// 仅在还没达到5次上限时打印
if (!LD_info->has_logged_regist) {
LD_info->registcount++;
if (LD_info->registcount <= 5) {
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【ERROR】监测点:%s - id:%s报告触发失败,监测点逻辑标识号为0,请检查装置对应的台账信息是否正确", LD_info->name,LD_info->mp_id);
}
// 到5次就不再打印并标记
if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s监测点逻辑标识号错误日志已达本次记录上限不再输出请检查装置对应的台账信息是否正确",
LD_info->name, LD_info->mp_id);
}
}
continue;
}
for(rpt_no=0 ; rpt_no<LD_info->rptcount; rpt_no++) { //遍历报告(映射文件中读取的报告控制)
rptinfo = LD_info->rptinfo[rpt_no] ; rptinfo = LD_info->rptinfo[rpt_no] ;
if (judge_rpt_next_should_do(rptinfo)==SHOULD_DO_NOTHING)//检查是否触发 if (judge_rpt_next_should_do(rptinfo)==SHOULD_DO_NOTHING)//检查是否触发
@@ -363,7 +380,22 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
chnl_usr->chnl_id, rptinfo->IntgPd,rptinfo->TrgOpt ); chnl_usr->chnl_id, rptinfo->IntgPd,rptinfo->TrgOpt );
//mq日志 //mq日志
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s注册报告失败,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); // 仅在还没达到5次上限时打印
if (!LD_info->has_logged_regist) {
LD_info->registcount++;
if (LD_info->registcount <= 5) {
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT, "【WARN】监测点:%s - id:%s注册报告失败,报告名:%s",
LD_info->name, LD_info->mp_id, rpt_inst_name);
}
// 到5次就不再打印并标记
if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告失败日志已达本次注册上限不再输出请检查装置icd和映射文件是否匹配或者装置存在过多连接",
LD_info->name, LD_info->mp_id);
}
}
} }
else else
@@ -381,7 +413,9 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
rptinfo->IntgPd,rptinfo->TrgOpt,rptinfo->OptFlds[0],rptinfo->OptFlds[1] ); rptinfo->IntgPd,rptinfo->TrgOpt,rptinfo->OptFlds[0],rptinfo->OptFlds[1] );
//mq日志 //mq日志
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s注册报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); LD_info->has_logged_regist = FALSE;
LD_info->registcount = 0;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
// add here to GI not the same time // add here to GI not the same time
GIoffset = 0.5 * g_pt61850app->giTime; GIoffset = 0.5 * g_pt61850app->giTime;
@@ -409,7 +443,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
APR_EGENERAL, LD_info->ied->id,LD_info->cpuno,LD_info->LD_name,rpt_inst_name,chnl_usr->ip_str,chnl_usr->chnl_id); APR_EGENERAL, LD_info->ied->id,LD_info->cpuno,LD_info->LD_name,rpt_inst_name,chnl_usr->ip_str,chnl_usr->chnl_id);
//mq日志 //mq日志
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s注销报告失败,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注销报告失败,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
} }
else { else {
@@ -448,6 +482,15 @@ void ChannelCheckWaveFiles(chnl_usr_t *chnl_usr)
} }
} }
//lnk20250821时间转换秒转本地时间
static void sec_to_timestr(long long sec, char *out, size_t out_sz)
{
time_t t = (time_t)sec;
struct tm tmv;
localtime_r(&t, &tmv); // 本地时间
strftime(out, out_sz, "%Y-%m-%d %H:%M:%S", &tmv);
}
void ChannelCheckIECLogs(chnl_usr_t *chnl_usr) void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
{ {
ST_RET ret; ST_RET ret;
@@ -466,12 +509,6 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
for(cpuno=0 ; cpuno<ied->cpucount; cpuno++) { for(cpuno=0 ; cpuno<ied->cpucount; cpuno++) {
LD_info = &(ied_usr->LD_info[cpuno]); LD_info = &(ied_usr->LD_info[cpuno]);
if (LD_info->logcount<=0)
continue;
loginfo = LD_info->loginfo[0] ;
apr_sleep(apr_time_from_sec(1) / 10);
//监测点日志的key,lnk20250526 //监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间 char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间 char full_key_m_d[256]; // 分配足够空间
@@ -479,6 +516,31 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id); snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526 //监测点日志的key,lnk20250526
//日志控制块缺失
if (LD_info->logcount<=0){
// 仅在还没达到5次上限时打印
if (!LD_info->has_logged_regist) {
LD_info->registcount++;
if (LD_info->registcount <= 5) {
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败,监测点缺少日志控制块,请检查装置对应的装置类型是否有配对的icd模型", LD_info->name,LD_info->mp_id);
}
// 到5次就不再打印并标记
if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s缺少日志控制块日志已达本次记录上限不再输出请检查装置对应的装置类型是否有配对的icd模型",
LD_info->name, LD_info->mp_id);
}
}
continue;
}
loginfo = LD_info->loginfo[0] ;
apr_sleep(apr_time_from_sec(1) / 10);
Check_Recall_Config(LD_info->mp_id);//尝试获取xml结构 Check_Recall_Config(LD_info->mp_id);//尝试获取xml结构
//补招数量不为0且不是正在补招 //补招数量不为0且不是正在补招
@@ -498,28 +560,41 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
if(strcmp(cfg1.ValueOfTimeUnit, "utc") == 0){//装置时间是utc还是北京 if(strcmp(cfg1.ValueOfTimeUnit, "utc") == 0){//装置时间是utc还是北京
utc_or_beijing = 28800;//秒 utc_or_beijing = 28800;//秒
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为utc时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type); DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为utc时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type);
} }
else{ else{
utc_or_beijing = 0; utc_or_beijing = 0;
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为beijing时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type); DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为beijing时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type);
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
//记录本次补招的时间范围
long long min_start_sec = LLONG_MAX;
long long max_end_sec = 0;
/////////////////////////////////////////////////////////////
for (i = 0; i < LD_info->autorecallcount; i++) { for (i = 0; i < LD_info->autorecallcount; i++) {
// ===== [新增] 累计全局最小/最大区间(直接用原始 start/end=====
if (LD_info->autorecall[i]->start < min_start_sec) {
min_start_sec = LD_info->autorecall[i]->start;
}
if (LD_info->autorecall[i]->end > max_end_sec) {
max_end_sec = LD_info->autorecall[i]->end;
}
// ===== [新增结束] =====
LD_info->autorecallflag = 1;//正在补招 LD_info->autorecallflag = 1;//正在补招
//当前不区分稳态和暂态lnk20241030如果做区分修改Check_Recall_Config从xml文件获取数据后赋值给了LD_info //当前不区分稳态和暂态lnk20241030如果做区分修改Check_Recall_Config从xml文件获取数据后赋值给了LD_info
loginfo->need_steady = LD_info->autorecall[i]->need_steady; loginfo->need_voltage = LD_info->autorecall[i]->need_voltage; loginfo->need_steady = LD_info->autorecall[i]->need_steady; loginfo->need_voltage = LD_info->autorecall[i]->need_voltage;
loginfo->start_time = apr_time_from_sec(LD_info->autorecall[i]->start - 5);//保证时间开头 loginfo->start_time = apr_time_from_sec(LD_info->autorecall[i]->start - 5);//保证时间开头
loginfo->end_time = apr_time_from_sec(LD_info->autorecall[i]->end - 5);//不保证时间结尾,可以+5保证时间结尾 loginfo->end_time = apr_time_from_sec(LD_info->autorecall[i]->end - 5);//不保证时间结尾
/////////////////////////////////////////////////////根据配置文件控制下发补招时间为北京时间还是utc时间,上送的数据61850库会转换成北京时间 /////////////////////////////////////////////////////根据配置文件控制下发补招时间为北京时间还是utc时间,上送的数据61850库会转换成北京时间
loginfo->start_time = loginfo->start_time - utc_or_beijing;//下发utc时间需要减去8小时-秒 loginfo->start_time = loginfo->start_time - utc_or_beijing * APR_USEC_PER_SEC;//下发utc时间需要减去8小时-秒
loginfo->end_time = loginfo->end_time - utc_or_beijing; loginfo->end_time = loginfo->end_time - utc_or_beijing * APR_USEC_PER_SEC;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
if (loginfo->need_steady == 0 && loginfo->need_voltage == 0) if (loginfo->need_steady == 0 && loginfo->need_voltage == 0)
@@ -542,7 +617,7 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
LD_info->ied->id, LD_info->cpuno, LD_info->LD_name, loginfo->logName, chnl_usr->ip_str, chnl_usr->chnl_id); LD_info->ied->id, LD_info->cpuno, LD_info->LD_name, loginfo->logName, chnl_usr->ip_str, chnl_usr->chnl_id);
//mq日志 //mq日志
DIY_ERRORLOG(full_key_m_c,"【ERROR】监测点:%s - id:%s补招数据失败 - 失败时间点:%lld 至 %lld", LD_info->name,LD_info->mp_id,loginfo->start_time,loginfo->end_time); DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败 - 失败时间点:%lld 至 %lld", LD_info->name,LD_info->mp_id,loginfo->start_time,loginfo->end_time);
failed_count++; failed_count++;
} }
@@ -565,7 +640,37 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
//不管是否成功这个补招文件必须删除可能出现一直失败循环读取文件和循环补招导致程序崩溃202050724lnk //不管是否成功这个补招文件必须删除可能出现一直失败循环读取文件和循环补招导致程序崩溃202050724lnk
//if (failed_count==0) {//成功 //if (failed_count==0) {//成功
Delete_recall_Xml(LD_info->mp_id); Delete_recall_Xml(LD_info->mp_id);
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s结束补招数据", LD_info->name,LD_info->mp_id);
// ===== [新增] 组装上送的补招开始/结束时间字符串(本地时区,直接“秒转字符串”)=====
char recallStartDate[32] = {0};
char recallEndDate[32] = {0};
if (min_start_sec == LLONG_MAX) {
// 理论上不会进来:有 autorecallcount != 0。兜底写成当前时间
time_t nowt = time(NULL);
sec_to_timestr((long long)nowt, recallStartDate, sizeof(recallStartDate));
sec_to_timestr((long long)nowt, recallEndDate, sizeof(recallEndDate));
} else {
sec_to_timestr(min_start_sec, recallStartDate, sizeof(recallStartDate));
sec_to_timestr(max_end_sec, recallEndDate, sizeof(recallEndDate));
}
//拼接result
const char *ld_name_safe = (LD_info->name && LD_info->name[0])
? LD_info->name : "-";
char result_buf[256];
snprintf(result_buf, sizeof(result_buf),
"监测点:%s 补招时间最小值和最大值:%s ~ %s 本次补招执行结束",
ld_name_safe, recallStartDate, recallEndDate);
// guid 固定 "12345"step 固定 "2"
//send_reply_to_kafka_c("12345", "2", result_buf);
send_reply_to_kafka_recall_c("12345", "2", result_buf,LD_info->mp_id,recallStartDate,recallEndDate);
// ===== [新增结束] =====
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s结束补招数据", LD_info->name,LD_info->mp_id);
//} //}
} }
@@ -696,7 +801,7 @@ void process_3s_config(trigger_3s_xml_t *trigger_3s_xml)
create_3s_xml(trigger_3s_xml); //写入文件的work块 create_3s_xml(trigger_3s_xml); //写入文件的work块
} }
void del_process_recall_config(recall_xml_t* recall_xml) /*void del_process_recall_config(recall_xml_t* recall_xml)
{ {
int i,j; int i,j;
recall_t *recall; recall_t *recall;
@@ -733,7 +838,7 @@ void del_process_recall_config(recall_xml_t* recall_xml)
} }
} }*/
void check_3s_config() void check_3s_config()
{ {
@@ -1370,13 +1475,13 @@ void check_disk_quota()
//printf("Current user disk free size: %dMB ,total size: %dMB \n",freeSizeMB,totalSizeMB); //printf("Current user disk free size: %dMB ,total size: %dMB \n",freeSizeMB,totalSizeMB);
if (freeSizeMB<g_min_free_size){ if (freeSizeMB<g_min_free_size){
echo_warn2("Current user disk free size: %dMB < %dMB, please check!\n",freeSizeMB,g_min_free_size); echo_warn2("Current user disk free size: %dMB < %dMB, please check!\n",freeSizeMB,g_min_free_size);
DIY_WARNLOG("process","【WARN】前置磁盘检测 当前磁盘的可用空间为%dMB,小于最小可用空间%dMB,请检查磁盘",freeSizeMB,g_min_free_size); DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测 当前磁盘的可用空间为%dMB,小于最小可用空间%dMB,请检查磁盘",freeSizeMB,g_min_free_size);
} }
if ((freeSizeMB/(totalSizeMB/100+1) )<10){ if ((freeSizeMB/(totalSizeMB/100+1) )<10){
echo_warn2("Current user disk free size percent < 10%%, free size: %dMB ,total size: %dMB ,please check!\n", echo_warn2("Current user disk free size percent < 10%%, free size: %dMB ,total size: %dMB ,please check!\n",
freeSizeMB,totalSizeMB); freeSizeMB,totalSizeMB);
DIY_WARNLOG("process","【WARN】前置磁盘检测 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘",freeSizeMB,totalSizeMB); DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘",freeSizeMB,totalSizeMB);
} }
} }
@@ -1402,9 +1507,14 @@ void Check_Recall_Config(char *id) //检查补招配置文件Recall.xml
if (g_node_id == HIS_DATA_BASE_NODE_ID || g_node_id == NEW_HIS_DATA_BASE_NODE_ID || g_node_id == RECALL_HIS_DATA_BASE_NODE_ID || (g_node_id == RECALL_ALL_DATA_BASE_NODE_ID)) { if (g_node_id == HIS_DATA_BASE_NODE_ID || g_node_id == NEW_HIS_DATA_BASE_NODE_ID || g_node_id == RECALL_HIS_DATA_BASE_NODE_ID || (g_node_id == RECALL_ALL_DATA_BASE_NODE_ID)) {
recall_xml_t recall_xml; recall_xml_t recall_xml;
memset((char*)&recall_xml, 0, sizeof(recall_xml_t)); //memset((char*)&recall_xml, 0, sizeof(recall_xml_t));
recall_xml_init(&recall_xml);
parse_recall_xml(&recall_xml,id); //解析补招文件,目录下所有属于这个监测点的文件都读取 parse_recall_xml(&recall_xml,id); //解析补招文件,目录下所有属于这个监测点的文件都读取
process_recall_config(&recall_xml); //解析的补招数据赋值到全局变量 process_recall_config(&recall_xml); //解析的补招数据赋值到全局变量
recall_xml_free(&recall_xml);
} }
} }
@@ -1522,7 +1632,7 @@ void CheckNextNotConnectedChannel()
//mq日志 //mq日志
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = true; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = true;
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = false; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = false;
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip端口:%s:%d连接成功", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d连接成功", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
mvl_free_req_ctrl(chnl_usr->m_reqCtrl); mvl_free_req_ctrl(chnl_usr->m_reqCtrl);
chnl_usr->m_reqCtrl = NULL; chnl_usr->m_reqCtrl = NULL;
@@ -1569,11 +1679,11 @@ void CheckNextNotConnectedChannel()
if(true == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat){ if(true == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = false; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = false;
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip/端口:%s:%d - 识别码/秘钥:%s/%s,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_series,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_key,secsSince); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip/端口:%s:%d,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,secsSince);
} }
else if(false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat && false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect){ else if(false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat && false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip/端口:%s:%d - 识别码/秘钥:%s/%s,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_series,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_key,secsSince); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip/端口:%s:%d,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,secsSince);
} }
mvl_free_req_ctrl(chnl_usr->m_reqCtrl); mvl_free_req_ctrl(chnl_usr->m_reqCtrl);
@@ -1581,6 +1691,14 @@ void CheckNextNotConnectedChannel()
chnl_usr->net_info->rem_vmd = NULL; chnl_usr->net_info->rem_vmd = NULL;
chnl_usr->m_state = CHANNEL_DISCONNECTED; chnl_usr->m_state = CHANNEL_DISCONNECTED;
chnl_usr->m_ClosedMsTime = sGetMsTime(); chnl_usr->m_ClosedMsTime = sGetMsTime();
//断联成功
apr_time_t t_now = apr_time_now();
connectlog_pgsql(ied_usr->terminal_id,convertMsToDateTimeString(t_now),0);
//更新状态
chnl_usr->chnl->ied->status = STATUS_OVERTIME;
chnl_usr->chnl->status = STATUS_OVERTIME;
} }
} }
else else
@@ -1596,11 +1714,11 @@ void CheckNextNotConnectedChannel()
if(true == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat){ if(true == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = false; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = false;
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
} }
else if(false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat && false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect){ else if(false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat && false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true; ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
} }
@@ -1615,6 +1733,14 @@ void CheckNextNotConnectedChannel()
chnl_usr->m_state = CHANNEL_DISCONNECTED; chnl_usr->m_state = CHANNEL_DISCONNECTED;
chnl_usr->m_ClosedMsTime = sGetMsTime(); chnl_usr->m_ClosedMsTime = sGetMsTime();
//断联
apr_time_t t_now = apr_time_now();
connectlog_pgsql(ied_usr->terminal_id,convertMsToDateTimeString(t_now),0);
//更新状态
chnl_usr->chnl->ied->status = STATUS_OVERTIME;
chnl_usr->chnl->status = STATUS_OVERTIME;
} }
} }
} }
@@ -1682,9 +1808,12 @@ void CheckNextNotConnectedChannel()
ied_usr_t* ied_usr = (ied_usr_t*)chnl_usr->chnl->ied->usr_ext; ied_usr_t* ied_usr = (ied_usr_t*)chnl_usr->chnl->ied->usr_ext;
apr_time_t t_now = apr_time_now(); apr_time_t t_now = apr_time_now();
connectlog_pgsql(ied_usr->terminal_id,convertMsToDateTimeString(t_now),0); connectlog_pgsql(ied_usr->terminal_id,convertMsToDateTimeString(t_now),0);
//更新状态
chnl_usr->chnl->ied->status = STATUS_BREAKOFF;
chnl_usr->chnl->status = STATUS_BREAKOFF;
//mq日志 //mq日志
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip端口:%s:%d 断连完成,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d 断连完成,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
} }
else else
@@ -1709,9 +1838,12 @@ void CheckNextNotConnectedChannel()
ied_usr_t* ied_usr = (ied_usr_t*)chnl_usr->chnl->ied->usr_ext; ied_usr_t* ied_usr = (ied_usr_t*)chnl_usr->chnl->ied->usr_ext;
apr_time_t t_now = apr_time_now(); apr_time_t t_now = apr_time_now();
connectlog_pgsql(ied_usr->terminal_id,convertMsToDateTimeString(t_now),0); connectlog_pgsql(ied_usr->terminal_id,convertMsToDateTimeString(t_now),0);
//更新状态
chnl_usr->chnl->ied->status = STATUS_BREAKOFF;
chnl_usr->chnl->status = STATUS_BREAKOFF;
//mq日志 //mq日志
DIY_WARNLOG(full_key_t_c,"【WARN】终端%s - ip端口:%s:%d 断连未完成,但是已经超时180秒,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port); DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d 断连未完成,但是已经超时180秒,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
} }
} }
@@ -1826,6 +1958,29 @@ apr_status_t prepare_call_cn_wavelist(LD_info_t *LD_info, int FltNum)
return APR_SUCCESS; return APR_SUCCESS;
} }
//判断暂态记录非空lnk20250818
int ld_has_qvvr_nonempty(const LD_info_t* info)
{
if (!info) return 0;
/* 规则1索引计数 > 0 直接认为非空 */
if (info->qvvr_idx > 0) return 1;
/* 规则2扫描数组任意一项出现被使用/有时间/有名称/有数值 即认为非空 */
int i;
for (i = 0; i < QVVR_NUM; ++i) {
const QVVR_t* it = &info->qvvr[i];
if (it->used_status != 0 && it->QVVR_time != 0 && it->QVVR_PerTime != 0)
{
return 1;
}
}
/* 都没有则为空 */
return 0;
}
apr_status_t call_cn_wavelist(LD_info_t *LD_info ) apr_status_t call_cn_wavelist(LD_info_t *LD_info )
{ {
int ret ; int ret ;
@@ -1887,7 +2042,10 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
//WW 2023-11-01 end //WW 2023-11-01 end
if (ret2 !=APR_SUCCESS){ if (ret2 !=APR_SUCCESS){
//mq日志 //mq日志
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s匹配录波文件失败", LD_info->name,LD_info->mp_id); //DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【WARN】监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]);
//lnk20250819装置没有对应的文件时清除录波号段
printf("监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]);
LD_info->FltNum[i] = -1;
return ret2; return ret2;
} }
@@ -2120,20 +2278,36 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
} }
else else if(ld_has_qvvr_nonempty(LD_info))//防止手动录波日志还一直上送
{ {
DIY_ERRORLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s匹配录波文件失败请检查装置的暂态时间是秒还是毫秒并修改映射文件", LD_info->name,LD_info->mp_id); //获取时间类型lnk20250520
XmlConfigC cfg;
if (get_xml_config_by_dev_type(ied_usr->dev_type, &cfg)) {
} else {
printf("读取失败,未找到 dev_type\n");
}
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是秒", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
else{
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是毫秒", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
} }
} }
} }
else{
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 下载录波文件%s和%s失败录波号段%d", LD_info->name,LD_info->mp_id,filenames[cfg_idx],filenames[dat_idx],LD_info->FltNum[i]);
}
} }
else { else {
if (ied && chnl_usr){ if (ied && chnl_usr){
echo_warn2("mms_mvla_fdir Failed: IED [%d] %s \n", ied->id , chnl_usr->ip_str) ; echo_warn2("mms_mvla_fdir Failed: IED [%d] %s \n", ied->id , chnl_usr->ip_str) ;
//mq日志 //mq日志
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s召唤录波文件失败", LD_info->name,LD_info->mp_id); DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【WARN】监测点:%s - id:%s召唤录波文件列表失败,放弃这个号段", LD_info->name,LD_info->mp_id);
LD_info->FltNum[i] = -1;
} }
return APR_EAGAIN; return APR_EAGAIN;

View File

@@ -56,6 +56,8 @@ SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
extern pt61850app_t* g_pt61850app; extern pt61850app_t* g_pt61850app;
extern bool DEBUGOPEN;
/************************************************************************/ /************************************************************************/
/* Static function prototypes. */ /* Static function prototypes. */
/************************************************************************/ /************************************************************************/
@@ -126,7 +128,7 @@ static ST_RET process_jou_entry(loginfo_t *loginfo,apr_time_t t,
double start, end; double start, end;
static double last_check_recall_config_time = 0.0; static double last_check_recall_config_time = 0.0;
printf("\nbrf for"); if(DEBUGOPEN)printf("\nbrf for");
for (j = 0; j < jou_entry->ef.data.num_of_var; j++) { for (j = 0; j < jou_entry->ef.data.num_of_var; j++) {
printf("\nfor %d", jou_entry->ef.data.num_of_var); printf("\nfor %d", jou_entry->ef.data.num_of_var);
@@ -146,7 +148,7 @@ static ST_RET process_jou_entry(loginfo_t *loginfo,apr_time_t t,
do_name++; do_name++;
} }
printf("\nbrf if"); if(DEBUGOPEN)printf("\nbrf if");
if (sel_mvl_type_ctrl_flag(do_name) == -1) if (sel_mvl_type_ctrl_flag(do_name) == -1)
{ {
var_type_id = mms_var_type_id_create(clientNetInfo, DOM_SPEC, var_type_id = mms_var_type_id_create(clientNetInfo, DOM_SPEC,
@@ -157,15 +159,15 @@ static ST_RET process_jou_entry(loginfo_t *loginfo,apr_time_t t,
add_mvl_type_ctrl(doname, var_type_id); add_mvl_type_ctrl(doname, var_type_id);
} }
printf("\nbrf var_type_id"); if(DEBUGOPEN)printf("\nbrf var_type_id");
var_type_id = sel_mvl_type_ctrl_flag(do_name); var_type_id = sel_mvl_type_ctrl_flag(do_name);
printf("\nafter var_type_id"); if(DEBUGOPEN)printf("\nafter var_type_id");
if (var_type_id < 0) { if (var_type_id < 0) {
continue; continue;
} }
log_var_jou_data(var_type_id,&(jou_entry->ef.data.list_of_var[j].value_spec),&mms_dec_data, do_name); log_var_jou_data(var_type_id,&(jou_entry->ef.data.list_of_var[j].value_spec),&mms_dec_data, do_name);
printf("\nafter log_var_jou_data"); if(DEBUGOPEN)printf("\nafter log_var_jou_data");
if (timeflag) { if (timeflag) {
int readtime = 0; int readtime = 0;
int readquailty = 0; int readquailty = 0;
@@ -443,7 +445,7 @@ static ST_RET process_jou_entry(loginfo_t *loginfo,apr_time_t t,
} }
} }
printf("\naft for"); if(DEBUGOPEN)printf("\naft for");
if ( log_data_type == QVVR_DATA ) { if ( log_data_type == QVVR_DATA ) {
processQVVR_end(loginfo->LD_info); processQVVR_end(loginfo->LD_info);
} }

View File

@@ -1162,7 +1162,7 @@ ST_VOID u_iec_rpt_ind_data_by_devtype(MVL_VAR_ASSOC** info_va,
echo_err3("Ignore this report due to line_id invalid , Report From %s %s %s !!!", echo_err3("Ignore this report due to line_id invalid , Report From %s %s %s !!!",
APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID); APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID);
//mq日志 //mq日志
DIY_ERRORLOG(full_key_m_d,"【ERROR】前置不处理这个监测点:%s - id:%s的报告,报告名称:%s,原因是监测点的序号非法", LD_info->name,LD_info->mp_id,rcb_info->RptID); DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_REPORT,"【ERROR】前置不处理这个监测点:%s - id:%s的报告,报告名称:%s,原因是监测点的序号非法", LD_info->name,LD_info->mp_id,rcb_info->RptID);
} }
printf("[END Process] Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n", printf("[END Process] Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n",

View File

@@ -194,7 +194,7 @@ apr_status_t init_rdb()
//char buf[256]; //char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index); //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf); //log_error("process", buf);
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv; return rv;
} }
@@ -209,7 +209,7 @@ apr_status_t init_rdb()
//char buf[256]; //char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index); //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf); //log_error("process", buf);
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv; return rv;
} }
@@ -220,7 +220,7 @@ apr_status_t init_rdb()
if (rv != APR_SUCCESS) { if (rv != APR_SUCCESS) {
echo_errg("Failed to parse report log define ini file! \n"); echo_errg("Failed to parse report log define ini file! \n");
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv; return rv;
} }
@@ -228,7 +228,7 @@ apr_status_t init_rdb()
if (app_get_private_config(g_my_conf_fname) != APR_SUCCESS) { if (app_get_private_config(g_my_conf_fname) != APR_SUCCESS) {
echo_errg("Failed when processing private configuration\n"); echo_errg("Failed when processing private configuration\n");
DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程读取mms配置失败", get_front_msg_from_subdir(), g_front_seg_index); DIY_ERRORLOG_CODE("process",LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程读取mms配置失败", get_front_msg_from_subdir(), g_front_seg_index);
return APR_EGENERAL; return APR_EGENERAL;
} }

View File

@@ -144,13 +144,19 @@ struct recall_t{
int need_voltage; int need_voltage;
}; };
typedef struct recall_xml_t recall_xml_t; typedef struct recall_xml_t recall_xml_t;
struct recall_xml_t{ /*struct recall_xml_t{
int work_recall_num; int work_recall_num;
int new_recall_num; int new_recall_num;
recall_t work_recalls[MAX_RECALL_NUM]; recall_t work_recalls[MAX_RECALL_NUM];
recall_t new_recalls[MAX_RECALL_NUM]; recall_t new_recalls[MAX_RECALL_NUM];
};*/
/* 动态数组 + 容量字段 lnk20250801*/
struct recall_xml_t{
int work_cnt, work_cap;
int new_cnt , new_cap;
recall_t *work_recalls;
recall_t *new_recalls;
}; };
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
struct element_usr_t{ struct element_usr_t{
char* FCD_ref; char* FCD_ref;
@@ -263,6 +269,10 @@ struct LD_info_t{
int rptPstRecvFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,rptRecvFlag=有效报告序号相加 int rptPstRecvFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,rptRecvFlag=有效报告序号相加
int rptPstRecvCheckFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,每次收到报告相加与rptRecvFlag一起判断是否收完 int rptPstRecvCheckFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,每次收到报告相加与rptRecvFlag一起判断是否收完
//报告 //报告
int registcount;//lnk20250812
bool has_logged_regist;//lnk20250812
//不使用 //不使用
int iUnitOfTime;//CZY 2023-08-17 WW 2022年12月7日15:43:34 装置上送事件持续时间单位切换(0-ms; 1-s) int iUnitOfTime;//CZY 2023-08-17 WW 2022年12月7日15:43:34 装置上送事件持续时间单位切换(0-ms; 1-s)
int iStatOfTime;//CZY 2023-08-17 WW 2022年12月7日15:48:33 统计数据时间 0-北京时间 1-UTC时间 int iStatOfTime;//CZY 2023-08-17 WW 2022年12月7日15:48:33 统计数据时间 0-北京时间 1-UTC时间
@@ -494,6 +504,9 @@ int delete_recall_xml(char* id);
int parse_recall_xml(recall_xml_t* recall_xml,char *id); int parse_recall_xml(recall_xml_t* recall_xml,char *id);
void process_recall_config(recall_xml_t* recall_xml); void process_recall_config(recall_xml_t* recall_xml);
void recall_xml_free(recall_xml_t *rx);//lnk20250801
void recall_xml_init(recall_xml_t *rx);
int init_rptctrl_by_count(LD_info_t* LD_info,int rptcount); int init_rptctrl_by_count(LD_info_t* LD_info,int rptcount);
int fill_rptctrl_by_cfg(LD_info_t* LD_info,int rptno,char *buf); int fill_rptctrl_by_cfg(LD_info_t* LD_info,int rptno,char *buf);
int init_logctrl_by_count(LD_info_t* LD_info,int logcount); int init_logctrl_by_count(LD_info_t* LD_info,int logcount);

View File

@@ -488,7 +488,7 @@ void processQVVR_start(LD_info_t* LD_info)
LD_info->qvvr[LD_info->qvvr_idx].used_status = QVVR_DATA_RECEIVED;//这个点标记为收到暂态数据 LD_info->qvvr[LD_info->qvvr_idx].used_status = QVVR_DATA_RECEIVED;//这个点标记为收到暂态数据
LD_info->qvvr[LD_info->qvvr_idx].QVVR_type = 0; //类型未定 LD_info->qvvr[LD_info->qvvr_idx].QVVR_type = 0; //类型未定
LD_info->qvvr[LD_info->qvvr_idx].timestamp = apr_time_sec(apr_time_now());//记录当前时间为暂态时间 LD_info->qvvr[LD_info->qvvr_idx].timestamp = apr_time_sec(apr_time_now());//记录当前时间
printf("\n~~~~~~~~~~~~~~~~~ processQVVR_start: line_id=%d \n",LD_info->line_id); printf("\n~~~~~~~~~~~~~~~~~ processQVVR_start: line_id=%d \n",LD_info->line_id);
} }
@@ -562,11 +562,11 @@ void processQVVR_end(LD_info_t* LD_info)
long long utc_or_beijing; long long utc_or_beijing;
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0 if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
s_or_ms = 0.001; s_or_ms = 0.001;
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type); //DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
} }
else{ else{
s_or_ms = 1.0; s_or_ms = 1.0;
DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是毫秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type); //DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是毫秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
} }
if(strcmp(cfg.ValueOfTimeUnit, "utc") == 0){//上送的是utc还是北京 if(strcmp(cfg.ValueOfTimeUnit, "utc") == 0){//上送的是utc还是北京
@@ -578,11 +578,8 @@ void processQVVR_end(LD_info_t* LD_info)
for (i=0;i<QVVR_NUM;i++) { //暂降/暂升/中断等进入处理,遍历所有波动位置 for (i=0;i<QVVR_NUM;i++) { //暂降/暂升/中断等进入处理,遍历所有波动位置
if (i==LD_info->qvvr_idx) //跳过监测点当前波动位置,第一次记录波形后,第一次的第个事件会让0号点为QVVR_DATA_RECEIVED if (i==LD_info->qvvr_idx) //跳过监测点当前波动位置,不会和自己做匹配。第一次记录波形后,第一次的第个事件会让0号点为QVVR_DATA_RECEIVED
//第二次记录波形,第二次的第一个事件qvvr_idx=11号中为QVVR_DATA_RECEIVEDQVVR_start=1跳过记录 //第二次qvvr_idx=11号中为QVVR_DATA_RECEIVEDQVVR_start=0会和0点做匹配
//第二次的第二个事件qvvr_idx=1QVVR_start=0记录到0中0为QVVR_DATA_PAIRED
//第二次的第三个事件qvvr_idx=22号中为QVVR_DATA_RECEIVEDQVVR_start=1跳过记录
//第二次录波匹配文件时应该匹配到1号的qvvrtime但是1没有QVVR_DATA_PAIRED所以对不上需要修改逻辑
{ {
printf("skip this index\n"); printf("skip this index\n");
continue; continue;
@@ -638,7 +635,11 @@ void processQVVR_end(LD_info_t* LD_info)
//匹配后再发qvvr起始时间要填暂态触发的时间就是第一次事件上送时只有时间没有值的那个时间 //匹配后再发qvvr起始时间要填暂态触发的时间就是第一次事件上送时只有时间没有值的那个时间
//mq日志 //mq日志
DIY_WARNLOG(full_key_m_d,"【WARN】监测点%s - id:%s 发生暂态事件",LD_info->name,LD_info->mp_id); DIY_WARNLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT,"【WARN】监测点%s - id:%s 发生暂态事件,暂态时间:%lld暂态持续时间%f暂态幅值%f暂态类型%d",LD_info->name,LD_info->mp_id,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_time,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_Amg,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_type);
ret = transfer_json_qvvr_data(g_node_id, //这个参数没有使用 ret = transfer_json_qvvr_data(g_node_id, //这个参数没有使用
LD_info->line_id, //监测点序号 LD_info->line_id, //监测点序号
@@ -665,6 +666,15 @@ void processQVVR_end(LD_info_t* LD_info)
LD_info->qvvr[LD_info->qvvr_idx].used_status = QVVR_DATA_NOT_USED; //全都没有匹配上直接释放这个点,下次事件可以直接在这个点上使用 LD_info->qvvr[LD_info->qvvr_idx].used_status = QVVR_DATA_NOT_USED; //全都没有匹配上直接释放这个点,下次事件可以直接在这个点上使用
printf("\nERROR:~~~~~~~~~~~~~ processQVVR qvvr returned to 0,but found no data to pair!, line_id=%d,QVVR_type=%d \n", printf("\nERROR:~~~~~~~~~~~~~ processQVVR qvvr returned to 0,but found no data to pair!, line_id=%d,QVVR_type=%d \n",
LD_info->line_id, LD_info->qvvr[LD_info->qvvr_idx].QVVR_type); LD_info->line_id, LD_info->qvvr[LD_info->qvvr_idx].QVVR_type);
//mq日志
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s记录了一个暂态事件但是没有匹配到事件的发生时间装置型号:%s 配置的暂态持续时间单位是秒",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
else{
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s记录了一个暂态事件但是没有匹配到事件的发生时间装置型号:%s 配置的暂态持续时间单位是毫秒",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
} }
printf("\n~~~~~~~~~~~~~~~~~ processQVVR_end: line_id=%d \n",LD_info->line_id); printf("\n~~~~~~~~~~~~~~~~~ processQVVR_end: line_id=%d \n",LD_info->line_id);