From cf94a99cadc3d4e42b6600f79f1f3309165ff6af Mon Sep 17 00:00:00 2001 From: lnk Date: Thu, 16 Apr 2026 10:56:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97=EF=BC=8C?= =?UTF-8?q?=E8=80=8C=E4=B8=94=E5=8F=B0=E8=B4=A6=E4=BF=AE=E6=94=B9=E6=97=B6?= =?UTF-8?q?=E6=97=A0=E8=AE=BA=E4=BB=80=E4=B9=88=E7=8A=B6=E6=80=81=E9=83=BD?= =?UTF-8?q?=E5=85=88=E5=85=B3=E9=97=AD=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cfg_parse/SimpleProducer.cpp | 38 +++- cfg_parse/cfg_parser.cpp | 62 +++---- cfg_parse/log4.cpp | 38 +++- include/ied.h | 338 +++++++++++++++++------------------ json/create_json.cpp | 44 ++--- json/save2json.cpp | 66 +++---- log4cplus/log4.h | 69 ++++--- mms/main.c | 8 +- mms/mms_process.c | 167 ++++++++--------- mms/mmscli_rpt.c | 13 +- mms/rdb_client.c | 8 +- mms/rdb_ext_utils.c | 17 +- 12 files changed, 451 insertions(+), 417 deletions(-) diff --git a/cfg_parse/SimpleProducer.cpp b/cfg_parse/SimpleProducer.cpp index 591e158..c9f7014 100644 --- a/cfg_parse/SimpleProducer.cpp +++ b/cfg_parse/SimpleProducer.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "../mms/db_interface.h" @@ -371,7 +372,7 @@ void rocketmq_consumer_receive( static int currentQueueId = 0; // 队列选择器回调函数:轮询选择队列 ID -int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) { +/*int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) { if (queueNum == 0) { throw std::runtime_error("No available queues"); } @@ -381,6 +382,24 @@ int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) { currentQueueId = 0; } return queueId; +}*/ +int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) { + static std::atomic currentQueueId(0); + + if (queueNum <= 0) { + std::cout << "[MQ][SELECTOR_FAIL] queueNum=" << queueNum << std::endl; + return -1; + } + + int id = currentQueueId.fetch_add(1, std::memory_order_relaxed); + int queueId = id % queueNum; + + std::cout << "[MQ][SELECTOR] queueNum=" << queueNum + << ", current=" << id + << ", selected=" << queueId + << std::endl; + + return queueId; } // 封装生产者的类 @@ -464,9 +483,20 @@ public: ); if (sendResult == 0) { // 假设返回 0 表示成功 - std::cout << "Message sent successfully.topic:" << topic <LD_info[cpuno].LD_name == NULL){ printf("this ld_info didn't palloc space ,maybe this ledger has problem!"); - DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1); continue;//跳过防止崩溃 } @@ -1878,18 +1878,18 @@ int parse_ledger_update_xml(trigger_update_xml_t* trigger_update_xml) //加载一个文件的内容到数据结构 if (!load_ledger_update_from_xml(trigger_update_xml, filename)) { std::cout << "read /etc/ledgerupdate/" << filename << " success..." << std::endl; - DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER_UPDATE,"【WARN】前置的%s%d号进程 读取台账更新文件成功,开始更新台账", get_front_msg_from_subdir(), g_front_seg_index); + DIY_WARNLOG_CODE("process",0,LOG_CODE_LEDGER_UPDATE,"【WARN】前置的%s%d号进程 读取台账更新文件成功,开始更新台账", get_front_msg_from_subdir(), g_front_seg_index); } //处理过的文件删除掉 if (std::remove(filename.c_str()) != 0) { std::cerr << "Failed to remove file: " << filename << " Error: " << strerror(errno) << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER_UPDATE,"【ERROR】前置的%s%d号进程 删除已读取的台账更新文件失败!请检查台账更新文件是否残留在/FeProject/etc/ledgerupdate", get_front_msg_from_subdir(), g_front_seg_index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER_UPDATE,"【ERROR】前置的%s%d号进程 删除已读取的台账更新文件失败!请检查台账更新文件是否残留在/FeProject/etc/ledgerupdate", get_front_msg_from_subdir(), g_front_seg_index); return APR_EGENERAL; } else{ std::cout << "remove file: " << filename << " success..." << std::endl; - DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程 删除已读取的台账更新文件成功", get_front_msg_from_subdir(), g_front_seg_index); + DIY_INFOLOG_CODE("process",0,LOG_CODE_LEDGER_UPDATE,"【NORMAL】前置的%s%d号进程 删除已读取的台账更新文件成功", get_front_msg_from_subdir(), g_front_seg_index); } } } @@ -2069,7 +2069,7 @@ int parse_3s_xml(trigger_3s_xml_t* trigger_3s_xml) printf("/etc/trigger3s/*.xml success...\n"); - DIY_INFOLOG("process","【WARN】前置读取实时数据触发文件成功,即将注册实时数据报告"); + DIY_INFOLOG_CODE("process",0,LOG_CODE_RT_DATA,"【WARN】前置读取实时数据触发文件成功,即将注册实时数据报告"); return APR_SUCCESS; } @@ -2382,7 +2382,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id) QDir dir(cfg_dir); if (!dir.exists()) { qDebug() << "folder does not exist!"; - DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法解析补招文件,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法解析补招文件,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); return false; } //指定文件后缀名,可指定多种类型 @@ -2398,7 +2398,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id) if (!file.open(QIODevice::ReadOnly)) { qDebug() << "file.open error"; - DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法打开补招文件%s", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str()); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法打开补招文件%s", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str()); continue; //以只读方式打开 } bool ret = doc.setContent(&file); @@ -2406,7 +2406,7 @@ int parse_recall_xml(recall_xml_t* recall_xml, char* id) if (!ret) { qDebug() << "doc.setContent error"; - DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法解析补招文件%s,补招内容无效", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str()); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法解析补招文件%s,补招内容无效", get_front_msg_from_subdir(), g_front_seg_index,qstrRecallPath.toStdString().c_str()); continue; } //将文件内容读到doc中 @@ -2984,7 +2984,7 @@ void DeletcRecallXml() { QDir dir(cfg_dir); if (!dir.exists()) { qDebug() << "folder does not exist!"; - DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 删除旧的补招文件失败,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 删除旧的补招文件失败,补招文件路径/FeProject/etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); return; } QStringList filter(file_name); @@ -2999,7 +2999,7 @@ void DeletcRecallXml() { if (fileInfo.lastModified() < saveDaysAgo) { QFile::remove(fileInfo.absoluteFilePath()); - DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程 删除超过两天的补招文件", get_front_msg_from_subdir(), g_front_seg_index); + DIY_INFOLOG_CODE("process",0,LOG_CODE_RECALL,"【NORMAL】前置的%s%d号进程 删除超过两天的补招文件", get_front_msg_from_subdir(), g_front_seg_index); } } @@ -3016,7 +3016,7 @@ void CreateRecallXml() { printf("insert ID_CJournalRecall_Map!\n"); - DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程 开始写入补招文件", get_front_msg_from_subdir(), g_front_seg_index); + DIY_INFOLOG_CODE("process",0,LOG_CODE_RECALL,"【NORMAL】前置的%s%d号进程 开始写入补招文件", get_front_msg_from_subdir(), g_front_seg_index); QMap > ID_CJournalRecall_Map; @@ -3049,7 +3049,7 @@ void CreateRecallXml() if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { printf("补招查询完成,打开%s失败,无法写入线路补招配置!\n", qstrRecallPath.toAscii().data()); - DIY_ERRORLOG_CODE("process",LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法将补招文件写入补招文件路径/FeProject/etc/recall/", get_front_msg_from_subdir(), g_front_seg_index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RECALL,"【ERROR】前置的%s%d号进程 无法将补招文件写入补招文件路径/FeProject/etc/recall/", get_front_msg_from_subdir(), g_front_seg_index); QMap >().swap(ID_CJournalRecall_Map); return; @@ -3766,14 +3766,14 @@ int terminal_ledger_web(QMap* terminal_dev_map, // 参数验证 if (num <= 0) { std::cerr << "Error: 'num' must be greater than 0." << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的多进程最大进程号为:%d,应该为大于0的整数",num); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置的多进程最大进程号为:%d,应该为大于0的整数",num); return 1; // 返回适当的错误码 } index = index - 1; if (index < 0 || index >= num) { std::cerr << "Error: 'index' must be in the range [0, num]." << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置当前进程的进程号为:%d,应该为0到最大进程号范围内的整数",index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置当前进程的进程号为:%d,应该为0到最大进程号范围内的整数",index); return 1; // 返回适当的错误码 } } @@ -3781,7 +3781,7 @@ int terminal_ledger_web(QMap* terminal_dev_map, // 获取参数 if (codes.empty()) { std::cerr << "Error: 'codes' vector is empty." << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口的入参为空",get_front_msg_from_subdir(), g_front_seg_index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口的入参为空",get_front_msg_from_subdir(), g_front_seg_index); return 1; } @@ -3834,7 +3834,7 @@ int terminal_ledger_web(QMap* terminal_dev_map, } } std::cerr << "data 无效或为空数组,重试" << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置从web接口中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str()); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置从web接口中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str()); } } @@ -3881,7 +3881,7 @@ int terminal_ledger_web(QMap* terminal_dev_map, break; // 本地台账解析成功且数组非空 } } - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置从本地台账中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str()); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置从本地台账中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",parm.c_str()); } free(ledger); // root==null释放内容 @@ -4181,7 +4181,7 @@ int parse_device_cfg_web() std::cout << "input_jstr: " << input_jstr << std::endl; // 输出结果 - DIY_DEBUGLOG("process","【DEBUG】前置的%s%d号进程调用web接口获取台账使用的请求输入为:%s",get_front_msg_from_subdir(), g_front_seg_index,input_jstr); + DIY_DEBUGLOG_CODE("process",0,LOG_CODE_LEDGER,"【DEBUG】前置的%s%d号进程调用web接口获取台账使用的请求输入为:%s",get_front_msg_from_subdir(), g_front_seg_index,input_jstr); codes.push_back(input_jstr); //是否需要筛选状态直接在配置文件控制 @@ -4216,13 +4216,13 @@ int parse_device_cfg_web() //判断是否相等 if(max_process_num != max_index){ if(max_process_num > 0 && max_process_num < 10){ - DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER,"【WARN】前置比对台账获取的进程数:%d和本地配置的进程数:%d,不匹配,按照台账进程数重置前置的进程数量",max_process_num,max_index); + DIY_WARNLOG_CODE("process",0,LOG_CODE_LEDGER,"【WARN】前置比对台账获取的进程数:%d和本地配置的进程数:%d,不匹配,按照台账进程数重置前置的进程数量",max_process_num,max_index); // 调用执行脚本函数 close_listening_socket(); execute_bash("reset", max_process_num, "all"); } else{ - DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置从台账获取的进程数:%d不符合范围1~9,按照本地配置进程数启动进程",max_process_num); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置从台账获取的进程数:%d不符合范围1~9,按照本地配置进程数启动进程",max_process_num); } } } @@ -4231,7 +4231,7 @@ int parse_device_cfg_web() std::cout << "terminal_ledger_num:" << count_cfg << std::endl; - DIY_DEBUGLOG("process","【DEBUG】前置的%s%d号进程调用获取到的台账的数量为:%d",get_front_msg_from_subdir(), g_front_seg_index,count_cfg); + DIY_DEBUGLOG_CODE("process",0,LOG_CODE_LEDGER,"【DEBUG】前置的%s%d号进程调用获取到的台账的数量为:%d",get_front_msg_from_subdir(), g_front_seg_index,count_cfg); //如果当前进程获取的台账为0,按照配置数量申请空间,台账内容为空 g_node->n_clients = count_cfg; @@ -4246,11 +4246,11 @@ int parse_device_cfg_web() //添加提示 std::cout << "!!!!!!!!!!single process can not add any ledger unless reboot!!!!!!!"<< std::endl; - DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER,"【WARN】前置的%s%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账",get_front_msg_from_subdir(), g_front_seg_index,IED_COUNT); + DIY_WARNLOG_CODE("process",0,LOG_CODE_LEDGER,"【WARN】前置的%s%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账",get_front_msg_from_subdir(), g_front_seg_index,IED_COUNT); } else{ g_node->clients = (ied_t**)apr_pcalloc(g_cfg_pool, IED_COUNT * sizeof(ied_t*));//g_node->clients 这块大内存空间存储了 count_cfg 个 ied_t* 类型的指针(即一个指针数组)这是(指向内存块的指针)的指针数组 - DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程根据配置文件中给单个进程配置的台账数量:%d来创建台账空间",get_front_msg_from_subdir(), g_front_seg_index,IED_COUNT); + DIY_INFOLOG_CODE("process",0,LOG_CODE_LEDGER,"【NORMAL】前置的%s%d号进程根据配置文件中给单个进程配置的台账数量:%d来创建台账空间",get_front_msg_from_subdir(), g_front_seg_index,IED_COUNT); } //把ied放入数组 @@ -4512,7 +4512,7 @@ int parse_device_cfg_web() { isdelta_flag = 1; //存在一个监测点为角型接线则这个前置就要启动第二个配置列表 cout << "monitor_id" << monitor_id << "v_wiring_type:" << line_info.v_wiring_type << "is delta wiring:" << isdelta_flag << endl; - DIY_WARNLOG_CODE("process",LOG_CODE_LEDGER,"【WARN】前置连接的监测点 %s 是角形接线,对应终端为%s 终端类型是%s",line_info.mp_id,ied_usr->terminal_id,ied_usr->dev_type); + DIY_WARNLOG_CODE("process",0,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); cout << "monitor_status:" << line_info.monitor_status << endl; @@ -4786,7 +4786,7 @@ int parse_model_cfg_web() ///////////////////////////////////////////////////////////////////////// if(parse_model_web(&icd_model_map,codes)){ - DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置", get_front_msg_from_subdir(), g_front_seg_index); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置", get_front_msg_from_subdir(), g_front_seg_index); return APR_SUCCESS; //可以使用默认的映射文件所以返回正常 } @@ -5053,7 +5053,7 @@ int recall_json_handle(const char* jstr) if(strcmp(ied_usr->LD_info[m].mp_id,monitorId.toStdString().c_str()) == 0){//匹配上了 - DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程处理监测点%s -id:%s 的数据补招",get_front_msg_from_subdir(), g_front_seg_index,ied_usr->LD_info[m].name,ied_usr->LD_info[m].mp_id); + DIY_INFOLOG_CODE("process",0,LOG_CODE_RECALL,"【NORMAL】前置的%s%d号进程处理监测点%s -id:%s 的数据补招",get_front_msg_from_subdir(), g_front_seg_index,ied_usr->LD_info[m].name,ied_usr->LD_info[m].mp_id); mppair = 1; break;//找到就退出监测点循环 } @@ -5276,7 +5276,7 @@ void handleUploadResponse(const std::string& response, char* wavepath) { cJSON* json_data = cJSON_Parse(response.c_str()); if (json_data == nullptr) { std::cerr << "Error parsing response: " << cJSON_GetErrorPtr() << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传文件失败,web返回的消息错误,无法解析"); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传文件失败,web返回的消息错误,无法解析"); return; } @@ -5322,11 +5322,11 @@ void handleUploadResponse(const std::string& response, char* wavepath) { std::cout << "wavepath: " << wavepath << std::endl; - DIY_INFOLOG("process","【NORMAL】前置上传文件成功,远端文件名:%s",wavepath); + DIY_INFOLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【NORMAL】前置上传文件成功,远端文件名:%s",wavepath); } } else { std::cerr << "Error: Missing expected fields in JSON response." << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传文件失败,web返回的消息没有远端文件名"); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传文件失败,web返回的消息没有远端文件名"); } // 释放 JSON 对象 @@ -5443,7 +5443,7 @@ void SendFileWeb(const std::string& strUrl, const char* localpath, const char* c CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "http web failed: " << curl_easy_strerror(res) << std::endl; - DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath); } else { std::cout << "http web success, response: " << resPost0 << std::endl; handleUploadResponse(resPost0, wavepath); // 处理响应 @@ -6064,7 +6064,7 @@ int parse_rpt_log_ini_one(ied_t* ied) //添加判断,有的监测点没有cpuno为2,直接申请了LD_info[2-1],没申请LD_info[0] if(ied_usr->LD_info[cpuno].LD_name == NULL){ printf("this ld_info didn't palloc space ,maybe this ledger has problem!"); - DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1); + DIY_ERRORLOG_CODE("process",0,LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1); continue;//跳过防止崩溃 } diff --git a/cfg_parse/log4.cpp b/cfg_parse/log4.cpp index 90f857c..be0d746 100644 --- a/cfg_parse/log4.cpp +++ b/cfg_parse/log4.cpp @@ -388,9 +388,10 @@ private: struct RateState { uint64_t hit_count; std::chrono::steady_clock::time_point last_emit; + std::chrono::steady_clock::time_point last_reset; bool has_emit; - RateState() : hit_count(0), last_emit(), has_emit(false) {} + RateState() : hit_count(0), last_emit(), last_reset(), has_emit(false) {} }; static std::unordered_map s_rate_map; @@ -398,7 +399,7 @@ private: static std::string make_key(const std::string& logger_name, int level, int code, const std::string& msg) { std::ostringstream oss; - oss << logger_name << "|" << level << "|" << code << "|" << msg; + oss << logger_name << "|" << level << "|" << code ; //<< "|" << msg; return oss.str(); } @@ -410,13 +411,31 @@ private: RateState& st = s_rate_map[key]; const int RESET_SEC = 3600; + + // 🚀 强制时间窗口重置(关键) if (st.has_emit) { - auto idle = duration_cast(now - st.last_emit).count(); - if (idle >= RESET_SEC) st.hit_count = 0; + auto since_reset = duration_cast(now - st.last_reset).count(); + if (since_reset >= RESET_SEC) { + st.hit_count = 0; + st.has_emit = false; + st.last_reset = now; + } + } else { + // 第一次初始化 + st.last_reset = now; } st.hit_count++; - const int period_sec = (st.hit_count > 3) ? 300 : 1; + + // 🚀 前20条:完全放行 + if (st.hit_count <= 20) { + st.last_emit = now; + st.has_emit = true; + return true; + } + + // 🚀 超过20条:1分钟限1条 + const int period_sec = 60; if (!st.has_emit) { st.last_emit = now; @@ -429,6 +448,7 @@ private: st.last_emit = now; return true; } + return false; } }; @@ -554,7 +574,7 @@ void init_loggers_bydevid(const char* dev_id) Logger device_logger = init_logger(device_key, device_dir, dev_id, device_appender); //用终端id作为日志文件名 logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT); - DIY_INFOLOG(device_key.c_str(),"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); + DIY_INFOLOG_CODE(device_key.c_str(),1,LOG_CODE_OTHER,"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); } // 初始化监测点 @@ -579,7 +599,7 @@ void init_loggers_bydevid(const char* dev_id) Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(),monitor_appender);//用监测点号作为日志文件名 logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT); - DIY_INFOLOG(mon_key.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); + DIY_INFOLOG_CODE(mon_key.str().c_str(),2,LOG_CODE_OTHER,"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); } } @@ -628,7 +648,7 @@ void init_loggers() { logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT); - DIY_INFOLOG(device_key.c_str(),"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); + DIY_INFOLOG_CODE(device_key.c_str(),1,LOG_CODE_OTHER,"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); // 初始化监测点 // 监测点 logger 名称格式:monitor. @@ -650,7 +670,7 @@ void init_loggers() { logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT); - DIY_INFOLOG(mon_key.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); + DIY_INFOLOG_CODE(mon_key.str().c_str(),2,LOG_CODE_OTHER,"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); } diff --git a/include/ied.h b/include/ied.h index 10b497b..66a54c7 100644 --- a/include/ied.h +++ b/include/ied.h @@ -1,6 +1,6 @@ /** * @file: $RCSfile: ied.h,v $ - * @brief: $豸ݽṹ + * @brief: $设备数据结构定义 * * @version: $Revision: 1.1 $ * @date: $Date: 2018/11/24 06:54:49 $ @@ -24,35 +24,35 @@ typedef byte_t channel_size_type; #endif -#define PRV_ANA_EXTENSION (1) //ģûչ -#define PRV_DIGIT_EXTENSION (3) //ңûչ -#define PRV_EVENT_EXTENSION (3) //¼ûչ -#define PRV_PULSE_EXTENSION (2) //ңûչ -//-----ģûչ---------------// -#define ANA_EXTENSION_ALARM (0) //澯:澯ȼ;澯ļ +#define PRV_ANA_EXTENSION (1) //模拟量用户扩展属性 总数 +#define PRV_DIGIT_EXTENSION (3) //遥信量用户扩展属性 总数 +#define PRV_EVENT_EXTENSION (3) //事件量用户扩展属性 总数 +#define PRV_PULSE_EXTENSION (2) //遥测量用户扩展属性 总数 +//-----模拟量用户扩展---------------// +#define ANA_EXTENSION_ALARM (0) //告警:告警等级;告警声音文件名 typedef struct analog_t analog_t; struct analog_t { - byte_t type; /**< ѹ//й/޹/Ƶ// */ - float initval; /**< ȱʡֵ */ - float minimum; /**< ȡֵ */ - float maximum; /**< ȡֵ */ - float step; /**< */ + byte_t type; /**< 电压/电流/有功功率/无功功率/频率/功率因素/其它 */ + float initval; /**< 缺省值 */ + float minimum; /**< 取值下限 */ + float maximum; /**< 取值上限 */ + float step; /**< 步长 */ byte_t integral; /**< precision ( n , m ) - n */ byte_t decimal; /**< precision ( n , m ) - m */ - float offset; /**< ʵֵת */ - float factor; /**< ʵֵתϵ */ - float threshold; /**< ֵ */ - float smooth; /**< ƽϵ */ - float lower; /**< 澯ֵ */ - float higher; /**< 澯ֵ */ - float lowest; /**< ޸澯ֵ */ - float highest; /**< ޸澯ֵ */ - float blur; /**< ֵģϵ */ - char dimension[SHORTNAME]; /**< ASCIIʽ(A/V/kV/kvar/kW/MW etc.) */ - void *ext[PRV_ANA_EXTENSION]; /**< չ */ + float offset; /**< 实际值转换基数 */ + float factor; /**< 实际值转换系数 */ + float threshold; /**< 门限值 */ + float smooth; /**< 平滑系数 */ + float lower; /**< 告警下限值 */ + float higher; /**< 告警上限值 */ + float lowest; /**< 下下限告警值 */ + float highest; /**< 上上限告警值 */ + float blur; /**< 阀值模糊系数 */ + char dimension[SHORTNAME]; /**< 量纲ASCII格式(A/V/kV/kvar/kW/MW etc.) */ + void *ext[PRV_ANA_EXTENSION]; /**< 保护管理机扩展 */ }ALIGNPACKED; @@ -66,27 +66,27 @@ struct ana_extention_t{ }; typedef struct digit_t digit_t; -#define DGT_TYP_UNDEF 0x00 /**< δ */ -#define DGT_TYP_SAMPLING 0x01 /**< */ -#define DGT_TYP_EVENT 0x02 /**< ¼ */ -#define DGT_TYP_ALARM 0x03 /**< 澯 */ -#define DGT_TYP_OPERATE 0x04 /**< */ -#define DGT_TYP_SYSTEM 0x05 /**< ϵͳ */ -/** ˽ */ +#define DGT_TYP_UNDEF 0x00 /**< 未定义 */ +#define DGT_TYP_SAMPLING 0x01 /**< 采样 */ +#define DGT_TYP_EVENT 0x02 /**< 事件 */ +#define DGT_TYP_ALARM 0x03 /**< 告警 */ +#define DGT_TYP_OPERATE 0x04 /**< 操作 */ +#define DGT_TYP_SYSTEM 0x05 /**< 系统 */ +/** 数字量私有属性 */ struct digit_t { - byte_t type; /**< /¼/澯//ϵͳ */ + byte_t type; /**< 采样/事件/告警/操作/系统 */ byte_t initval; /**< default zero value(0 or 1) */ byte_t level; /**< level */ byte_t snd_timer; /**< sound play timer (s) */ byte_t rst_timer; /**< auto restore timer (s) */ - uint16_t act_lim; /**< (0 ==> 1)澯 */ - uint16_t rst_lim; /**< (1 ==> 0)澯 */ - uint16_t act_num; /**< (0 ==> 1)(¼) */ - uint16_t rst_num; /**< (1 ==> 0)(¼) */ - //ڶȥ - //char on[SHORTNAME]; /**< 0==>1(ASCIIʽ) */ - //char off[SHORTNAME]; /**< 1==>0(ASCIIʽ) */ - void *ext[PRV_DIGIT_EXTENSION]; /**< չ */ + uint16_t act_lim; /**< (0 ==> 1)动作告警上限 */ + uint16_t rst_lim; /**< (1 ==> 0)动作告警上限 */ + uint16_t act_num; /**< (0 ==> 1)动作上限(不需界面录入) */ + uint16_t rst_num; /**< (1 ==> 0)动作上限(不需界面录入) */ + //第二版去掉 + //char on[SHORTNAME]; /**< 0==>1动作名称(ASCII格式) */ + //char off[SHORTNAME]; /**< 1==>0动作名称(ASCII格式) */ + void *ext[PRV_DIGIT_EXTENSION]; /**< 保护管理机扩展 */ }ALIGNPACKED; @@ -102,12 +102,12 @@ struct digit_t { typedef struct state_describe_extention_t state_describe_extention_t; struct state_describe_extention_t{ - char *state_describe[4]; /**< ״̬0123 */ + char *state_describe[4]; /**< 状态0,1,2,3的描述 */ }; typedef struct sound_file_name_extention_t sound_file_name_extention_t; struct sound_file_name_extention_t{ - char *sound_file_name[3]; /**< ϱ¹ʱ */ + char *sound_file_name[3]; /**< 开报警声、合报警声、事故报警声 */ }; typedef struct epfi_addt_extension_t epfi_addt_extension_t; @@ -120,48 +120,48 @@ struct epfi_addt_extension_t { typedef struct pulse_t pulse_t; /** Integrated totals private attr */ -#define PLS_TYP_UNDEF 0x00 /**< δ */ -#define PLS_TYP_PLUS_POWER_HV 0x01 /**< й */ -#define PLS_TYP_PLUS_POWER_NO 0x02 /**< ޹ */ -#define PLS_TYP_NEGATIVE_POWER_HV 0x03 /**< й */ -#define PLS_TYP_NEGATIVE_POWER_NO 0x04 /**< ޹ */ +#define PLS_TYP_UNDEF 0x00 /**< 未定义 */ +#define PLS_TYP_PLUS_POWER_HV 0x01 /**< 正向有功 */ +#define PLS_TYP_PLUS_POWER_NO 0x02 /**< 正向无功 */ +#define PLS_TYP_NEGATIVE_POWER_HV 0x03 /**< 反向有功 */ +#define PLS_TYP_NEGATIVE_POWER_NO 0x04 /**< 反向无功 */ struct pulse_t { - byte_t type; /**< й/޹/й/޹ */ - uint32_t save_flag; /**< 洢 */ + byte_t type; /**< 正向有功/正向无功/反向有功/反向无功 */ + uint32_t save_flag; /**< 存储标记 */ uint32_t initval; /**< default value */ uint32_t minimum; /**< minimum value */ uint32_t maximum; /**< maximum value */ - uint32_t step; /**< */ - //changed by zhancg 2017-04-05 ϵ -// uint32_t offset; /**< ʵֵת */ -// uint32_t factor; /**< ʵֵתϵ */ -// uint32_t threshold; /**< ֵ */ -// uint32_t smooth; /**< ƽϵ */ - float offset; /**< ʵֵת */ - float factor; /**< ʵֵתϵ */ - float threshold; /**< ֵ */ - float smooth; /**< ƽϵ */ - char dimension[SHORTNAME]; /**< ASCIIʽ(kvar/kW/MW etc.) */ + uint32_t step; /**< 步长 */ + //changed by zhancg 2017-04-05 配系数 +// uint32_t offset; /**< 实际值转换基数 */ +// uint32_t factor; /**< 实际值转换系数 */ +// uint32_t threshold; /**< 门限值 */ +// uint32_t smooth; /**< 平滑系数 */ + float offset; /**< 实际值转换基数 */ + float factor; /**< 实际值转换系数 */ + float threshold; /**< 门限值 */ + float smooth; /**< 平滑系数 */ + char dimension[SHORTNAME]; /**< 量纲ASCII格式(kvar/kW/MW etc.) */ void *ext[PRV_PULSE_EXTENSION]; }ALIGNPACKED; typedef struct pluse_stage_limits_extention_t pluse_stage_limits_extention_t; struct pluse_stage_limits_extention_t{ - uint32_t limits[3]; /**< ֵ,յֵ,µֵ */ + uint32_t limits[3]; /**< 峰电度限值,日电度限值,月电度限值 */ }; typedef struct pluse_stage_const_extention_t pluse_stage_const_extention_t; struct pluse_stage_const_extention_t{ - char* stage[8]; /**< ʱ1,ʱ2,ʱ3,ʱ4,ʱ1,ʱ2,ʱ3,ʱ4 */ + char* stage[8]; /**< 峰时段1,峰时段2,峰时段3,峰时段4,谷时段1,谷时段2,谷时段3,谷时段4 */ }; // typedef struct command_t command_t; -/** Ϣṹ */ +/** 命令消息结构 */ struct command_t { ticks_t ticks; /**< Ticks when command generated */ - apr_time_t tmlimit; /**< ִɵʱ */ - byte_t state; /**< ACTIVEFINISH or TIMEOUT */ + apr_time_t tmlimit; /**< 命令执行完成的限制时间 */ + byte_t state; /**< ACTIVE、FINISH or TIMEOUT */ byte_t channel; /**< command channel no */ - byte_t flag; /**< GeneralSystem or Special */ + byte_t flag; /**< General、System or Special */ byte_t typ; /**< Command TYPE(IEC60870-5-101) */ uint32_t ied; /**< Controlled IED id */ uint32_t group; /**< Controlled group id */ @@ -173,65 +173,65 @@ struct command_t { /** status_t code definiens */ -#define STATUS_NORMAL 0 /**< */ -#define STATUS_NOINIT 1 /**< δʼ */ -#define STATUS_OVERTIME 2 /**< ͨųʱ */ -#define STATUS_BREAKOFF 3 /**< ͨж */ -#define STATUS_BLOCKED 4 /**< */ -#define STATUS_TESTING 5 /**< */ -#define STATUS_NOTDEF 6 /**< δã״̬û) */ +#define STATUS_NORMAL 0 /**< 正常 */ +#define STATUS_NOINIT 1 /**< 未初始化 */ +#define STATUS_OVERTIME 2 /**< 通信超时 */ +#define STATUS_BREAKOFF 3 /**< 通信中断 */ +#define STATUS_BLOCKED 4 /**< 封锁 */ +#define STATUS_TESTING 5 /**< 测试 */ +#define STATUS_NOTDEF 6 /**< 未配置(本运行状态没有配置) */ -typedef uint16_t status_t; /**< 豸ͨŽڵ״̬ */ +typedef uint16_t status_t; /**< 设备或通信节点的运行状态 */ typedef struct alias_t alias_t; -/** Ԫصıṹ */ -struct alias_t { /**< Ԫصıṹ */ - uint32_t id; /**< Ϣַ */ - uint32_t parent; /**< ָIED */ - uint32_t group; /**< ָIEDڵ */ - uint32_t dot; /**< ָIEDڵ */ - value_t* value; /**< ʱʵʱ */ +/** 数据元素的别名结构 */ +struct alias_t { /**< 数据元素的别名结构 */ + uint32_t id; /**< 别名信息地址 */ + uint32_t parent; /**< 所指代的IED */ + uint32_t group; /**< 所指代的IED内的组号 */ + uint32_t dot; /**< 所指代的IED内的序号 */ + value_t* value; /**< 运行时刻实时数据 */ }; typedef struct ied_t ied_t; typedef struct group_t group_t; typedef struct element_t element_t; -/** ϢԪصĽṹ */ +/** 数据信息元素的结构 */ struct element_t { uint32_t id; /**< Identification, Information Address */ uint32_t flags; /**< flags define */ byte_t type; /**< IEC60870-5-101 TYP.(IEC60870DEF.h) */ byte_t code; /**< Data code type.(BIN/ASCII/BCD/etc.) */ - uint32_t parent; /**< 豸 */ - uint32_t group; /**< */ - uint32_t dot; /**< */ - uint16_t size; /**< ݿ(ֽΪλ) */ - char name[LONGNAME]; /**< */ + uint32_t parent; /**< 隶属设备 */ + uint32_t group; /**< 数据组号 */ + uint32_t dot; /**< 数据序号 */ + uint16_t size; /**< 数据宽度(以字节为单位) */ + char name[LONGNAME]; /**< 数据名称 */ - char *aliasname; /**< ݵƶӦӢ ++EPFI++ */ + char *aliasname; /**< 数据点别名,如用于中文名称对应的英文名称 ++EPFI++ */ - void *owner; /**< ˽Խṹ(analog_t/digit_t/..../etc.) */ - void *script; /**< ļʽ */ + void *owner; /**< 私有属性结构(analog_t/digit_t/..../etc.) */ + void *script; /**< 关联的计算表达式 */ /** Runtime generate */ - value_t value; /**< ʱʵʱݻ */ - ticks_t last; /**< 仯ʱ */ - uint32_t state; /**< ״̬ */ - byte_t funtype; /**< ̳ͣʾݹ */ - uint16_t index; /**< Ԫ */ - uint16_t n_alias_add_1; /**< ݱĴСԤ1̬ã */ - uint16_t n_alias; /**< ݱԪظ */ - alias_t* alias; /**< ݱ */ - uint16_t alias_pos; /**< ݱǰλ */ - uint32_t offset; /**< 豸ݻڵƫ */ - group_t *grp; /**< */ - ied_t *ied; /**< 豸 */ + value_t value; /**< 运行时刻实时数据缓冲区 */ + ticks_t last; /**< 最后变化时间 */ + uint32_t state; /**< 数据状态 */ + byte_t funtype; /**< 继承自所属组的类型,表示数据功能类型 */ + uint16_t index; /**< 数据元素索引 */ + uint16_t n_alias_add_1; /**< 分配的数据别名缓冲区的大小(预留1,动态定订购用) */ + uint16_t n_alias; /**< 数据别名数组元素个数 */ + alias_t* alias; /**< 数据别名索引数组 */ + uint16_t alias_pos; /**< 数据别名当前位置 */ + uint32_t offset; /**< 数据在设备数据缓冲区内的偏移索引 */ + group_t *grp; /**< 所属数据组句柄 */ + ied_t *ied; /**< 所属设备句柄 */ /* Extend property */ - void *sys_ext; /**< ݵϵͳչ,ɻʵ */ - void *app_ext; /**< ݵӦչ,Ӧÿʵ */ - void *usr_ext; /**< ݵûչ,Ӧóʵ */ + void *sys_ext; /**< 数据点的系统扩展属性,由基本库实现 */ + void *app_ext; /**< 数据点的应用扩展属性,由应用库实现 */ + void *usr_ext; /**< 数据点的用户扩展属性,由应用程序实现 */ }; /** group_t->type definiens */ @@ -245,36 +245,36 @@ struct element_t { #define GRP_ALARM 7 /**< Alarm type */ #define GRP_SETTING 8 /**< Fixed value type */ #define GRP_STATUS 9 /**< State of device */ -#define GRP_VDI 10 /**< ѹ type */ +#define GRP_VDI 10 /**< 软压板 type */ #define GRP_STEPPOS 11 /**< Step position type */ #define GRP_COMBO 12 /**< combo/compute type */ -#define GRP_SIMANA 13 /**< ģ */ -#define GRP_SETAREA 14 /**< ֵ */ -#define GRP_ACCANA 15 /**< ¼ģ */ -#define GRP_ACCDGT 16 /**< ¼ */ +#define GRP_SIMANA 13 /**< 模拟量 */ +#define GRP_SETAREA 14 /**< 定值区 */ +#define GRP_ACCANA 15 /**< 录波模拟量 */ +#define GRP_ACCDGT 16 /**< 录波开关量 */ #define GRP_SETPOINT 18 /**< Set point type for 101,104 protocol used only */ -#define GRP_STEPCONTROL 19 /**< λõ */ +#define GRP_STEPCONTROL 19 /**< 步位置调节组 */ -/** ṹ */ +/** 数据组结构 */ struct group_t { uint32_t id; /**< Identification, Commond Address of Set */ uint32_t flags; /**< Flags definiens */ byte_t type; /**< Analogue/Digit/Control/Event/etc. */ - char name[LONGNAME]; /**< */ - uint16_t maxelems; /**< elementsĿ */ - element_t *elements; /**< Ԫض */ + char name[LONGNAME]; /**< 数据组的名称 */ + uint16_t maxelems; /**< 允许包含elements的最大数目 */ + element_t *elements; /**< 数据元素定义数组 */ // runtime generate - uint16_t count; /**< ʵʰԪĿ */ - uint16_t index; /**< IED->groups± */ - value_t value; /**< 黺˳elementsʵʱֵ */ - ied_t *ied; /**< 豸 */ - apr_hash_t *htdots; /**< Ԫضϣ */ + uint16_t count; /**< 实际包含的数据元素数目 */ + uint16_t index; /**< 数据组索引IED->groups的数组下标 */ + value_t value; /**< 数据组缓冲区,顺序存放elements的实时值 */ + ied_t *ied; /**< 所属设备句柄 */ + apr_hash_t *htdots; /**< 数据元素定义哈希表 */ /* Extend property */ - void *sys_ext; /**< ϵͳչ,ɻʵ */ - void *app_ext; /**< Ӧչ,Ӧÿʵ */ - void *usr_ext; /**< ûչ,Ӧóʵ */ + void *sys_ext; /**< 数据组的系统扩展属性,由基本库实现 */ + void *app_ext; /**< 数据组的应用扩展属性,由应用库实现 */ + void *usr_ext; /**< 数据组的用户扩展属性,由应用程序实现 */ }; //