diff --git a/cfg_parse/cfg_parser.cpp b/cfg_parse/cfg_parser.cpp index 7de6f2a..b6f3f5f 100644 --- a/cfg_parse/cfg_parser.cpp +++ b/cfg_parse/cfg_parser.cpp @@ -185,6 +185,8 @@ int IED_COUNT = 300; //默认300 extern int INITFLAG; +extern uint32_t g_ontime_blocked_times; + //lnk2024-8-14添加角型接线标志,0不存在角形接线,1存在角形接线 int isdelta_flag = 0; @@ -1442,7 +1444,12 @@ int parse_rpt_log_ini() if(tmp == NULL){std::cerr << "front read ied config error!" << std::endl;continue;} qDebug() << tmp << endl; - apr_snprintf(str, sizeof(str), tmp, cpuno + 1); + //apr_snprintf(str, sizeof(str), tmp, cpuno + 1); + + //ied_usr->LD_info[cpuno].LD_name = apr_pstrdup(g_init_pool, str); + + //已经分配过内存,直接复制到里面 + apr_snprintf(ied_usr->LD_info[cpuno].LD_name, sizeof(ied_usr->LD_info[cpuno].LD_name), tmp, cpuno + 1); delete[] tmp; @@ -3453,12 +3460,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("process","【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-1]." << std::endl; + std::cerr << "Error: 'index' must be in the range [0, num]." << std::endl; + DIY_ERRORLOG("process","【ERROR】前置当前进程的进程号为:%d,应该为0到最大进程号范围内的整数",index); return 1; // 返回适当的错误码 } } @@ -3466,6 +3475,7 @@ int terminal_ledger_web(QMap* terminal_dev_map, // 获取参数 if (codes.empty()) { 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); return 1; } @@ -3558,9 +3568,7 @@ int terminal_ledger_web(QMap* terminal_dev_map, }*/ while (1) { // 请求接口 - SendJsonAPI_web(WEB_DEVICE, "", parm.c_str(), &ptr); - - + SendJsonAPI_web(WEB_DEVICE, "", parm.c_str(), &ptr); if (ptr != NULL) { @@ -3826,9 +3834,14 @@ 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); + codes.push_back(input_jstr); //是否需要筛选状态直接在配置文件控制 - terminal_ledger_web(&terminal_dev_map,codes,g_front_seg_index,g_front_seg_num); + if(terminal_ledger_web(&terminal_dev_map,codes,g_front_seg_index,g_front_seg_num)){ + return APR_EBADF; + } + codes.clear(); //调试用 @@ -3855,9 +3868,15 @@ int parse_device_cfg_web() //判断是否相等 if(max_process_num != max_index){ - // 调用执行脚本函数 - close_listening_socket(); - execute_bash("reset", max_process_num, "all"); + if(max_process_num > 0 && max_process_num < 10){ + DIY_WARNLOG("process","【WARN】前置比对台账获取的进程数:%s和本地配置的进程数:%s,不匹配,按照台账进程数重置前置的进程数量",max_process_num,max_index); + // 调用执行脚本函数 + close_listening_socket(); + execute_bash("reset", max_process_num, "all"); + } + else{ + DIY_ERRORLOG("process","【ERROR】前置从台账获取的进程数:%s不符合范围1~9,按照本地配置进程数启动进程",max_process_num); + } } } @@ -3865,6 +3884,8 @@ 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); + //如果当前进程获取的台账为0,按照配置数量申请空间,台账内容为空 g_node->n_clients = count_cfg; @@ -3877,9 +3898,12 @@ int parse_device_cfg_web() g_node->clients = (ied_t**)apr_pcalloc(g_cfg_pool, count_cfg * sizeof(ied_t*)); //添加提示 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); } 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); } //把ied放入数组 @@ -4555,6 +4579,9 @@ void OnTimerThread::run() } counter++; + //清空计数器 + g_ontime_blocked_times =0; + msleep(1000); } printf(">>>OnTimerThread::run() is end!!!\n"); @@ -6466,9 +6493,9 @@ void send_reply_to_kafka(const std::string& guid, const std::string& step, const oss << "{" << "\"guid\":\"" << guid << "\"," << "\"step\":\"" << step << "\"," - << "\"result\":\"" << result << "\"" - << "\"processNo\":\"" << g_front_seg_index << "\"" - << "\"frontType\":\"" << get_front_type_from_subdir() << "\"" + << "\"result\":\"" << result << "\"," + << "\"processNo\":\"" << g_front_seg_index << "\"," + << "\"frontType\":\"" << get_front_type_from_subdir() << "\"," << "\"nodeId\":\"" << FRONT_INST << "\"" << "}"; diff --git a/cfg_parse/log4.cpp b/cfg_parse/log4.cpp index 3bb8d63..5e607a7 100644 --- a/cfg_parse/log4.cpp +++ b/cfg_parse/log4.cpp @@ -28,6 +28,7 @@ extern unsigned int g_node_id; extern int g_front_seg_index; +extern std::string FRONT_INST; extern char subdir[128]; extern node_t* g_node; @@ -77,6 +78,14 @@ bool create_directory_recursive(const std::string& path) { return true; } ////////////////////////////////////////////////////////////////////// +std::string extract_logger_id(const std::string& logger_name) { + size_t pos = logger_name.find('.'); + if (pos != std::string::npos && pos + 1 < logger_name.size()) { + return logger_name.substr(pos + 1); + } + return ""; // 没有找到 '.' 或 '.' 后为空 +} +////////////////////////////////////////////////////////////////////// TypedLogger::TypedLogger() {} TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), logtype(t) {} @@ -126,7 +135,8 @@ protected: if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) { std::ostringstream oss; oss << "{\"processNo\":\"" << intToString(g_front_seg_index) - << "\",\"id\":\"" << logger_name + << "\",\"nodeId\":\"" << FRONT_INST + << "\",\"businessId\":\"" << extract_logger_id(logger_name) << "\",\"level\":\"" << level_str << "\",\"grade\":\"" << level << "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data") @@ -354,8 +364,12 @@ void init_loggers() { logger_map[device_key + ".DATA"] = TypedLogger(device_logger, LOGTYPE_DATA); char buf[256]; - sprintf(buf, "终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); - LOG4CPLUS_DEBUG(logger_map[device_key + ".DATA"].logger, buf); + //sprintf(buf, "终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); + //LOG4CPLUS_DEBUG(logger_map[device_key + ".DATA"].logger, buf); + //format_log_msg(buf,sizeof(buf),"终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); + //log_debug(std::string(device_key + ".DATA").c_str(),buf); + std::string full_key_t = device_key + ".DATA"; + DIY_WARNLOG(full_key_t.c_str(),"终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); // 初始化监测点 // 监测点 logger 名称格式:monitor..COM / .DATA @@ -371,9 +385,14 @@ void init_loggers() { logger_map[mon_key.str() + ".COM"] = TypedLogger(mon_logger, LOGTYPE_COM); logger_map[mon_key.str() + ".DATA"] = TypedLogger(mon_logger, LOGTYPE_DATA); - char buf[256]; - sprintf(buf, "监测点id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].mp_id); - LOG4CPLUS_DEBUG(logger_map[mon_key.str() + ".DATA"].logger, buf); + //char buf[256]; + //sprintf(buf, "监测点id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].mp_id); + //LOG4CPLUS_DEBUG(logger_map[mon_key.str() + ".DATA"].logger, buf); + //format_log_msg(buf,sizeof(buf),"监测点id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].mp_id); + //log_debug(std::string(mon_key.str() + ".DATA").c_str(),buf); + std::string full_key_m = mon_key.str() + ".DATA"; + DIY_WARNLOG(full_key_m.c_str(),"监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); + } } @@ -433,7 +452,11 @@ void remove_loggers_by_terminal_id(const char* terminal_id_cstr) { } } + + +#ifdef __cplusplus extern "C" { +#endif // 公共函数 void log4_log_with_level(const char* key, const char* msg, int level) { @@ -459,8 +482,25 @@ extern "C" { void send_reply_to_kafka_c(const char* guid, const char* step, const char* result) { send_reply_to_kafka(std::string(guid), std::string(step), std::string(result)); } + + //标准化日志接口 + void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...) { + // 写入时间 + time_t now = time(NULL); + struct tm tm_info; + localtime_r(&now, &tm_info); + strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S ", &tm_info); // 时间+空格 + + // 处理可变参数并写入剩余内容 + va_list args; + va_start(args, fmt); + vsnprintf(buf + strlen(buf), buf_size - strlen(buf), fmt, args); + va_end(args); + } +#ifdef __cplusplus } +#endif /* diff --git a/json/create_json.cpp b/json/create_json.cpp index 99590b3..8ee32cf 100644 --- a/json/create_json.cpp +++ b/json/create_json.cpp @@ -218,6 +218,39 @@ extern int isdelta_flag;//lnk2024-8-16 角型接线标志 void connectlog_pgsql(char* id,char* datetime,int status); ///////////////////////////////////////////////lnk20241021替换web接口////////////////////////////////// +//lnk20250520 获取映射文件中的一些数据///////////////////////////////////////////////////////////////// + +bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg) { + if (!dev_type || !out_cfg) + { + printf("null dev_type"); + return false; + } + + QString dev_type_q = QString::fromUtf8(dev_type); + QMap::iterator it = xmlinfo_list.find(dev_type_q); + if (it == xmlinfo_list.end() || it.value() == nullptr) { + printf("this dev_type not contain"); + return false; + } + + const XmlConfig& cfg = it.value()->xmlcfg; + + // 将 QString 复制到结构体中的 char[],确保不越界 + strncpy(out_cfg->WavePhasicFlag, cfg.WavePhasicFlag.toUtf8().constData(), sizeof(out_cfg->WavePhasicFlag) - 1); + strncpy(out_cfg->WavePhasicA, cfg.WavePhasicA.toUtf8().constData(), sizeof(out_cfg->WavePhasicA) - 1); + strncpy(out_cfg->WavePhasicB, cfg.WavePhasicB.toUtf8().constData(), sizeof(out_cfg->WavePhasicB) - 1); + strncpy(out_cfg->WavePhasicC, cfg.WavePhasicC.toUtf8().constData(), sizeof(out_cfg->WavePhasicC) - 1); + strncpy(out_cfg->UnitOfTimeUnit, cfg.UnitOfTimeUnit.toUtf8().constData(), sizeof(out_cfg->UnitOfTimeUnit) - 1); + strncpy(out_cfg->ValueOfTimeUnit, cfg.ValueOfTimeUnit.toUtf8().constData(),sizeof(out_cfg->ValueOfTimeUnit) - 1); + strncpy(out_cfg->WaveTimeFlag, cfg.WaveTimeFlag.toUtf8().constData(), sizeof(out_cfg->WaveTimeFlag) - 1); + strncpy(out_cfg->IEDname, cfg.IEDname.toUtf8().constData(), sizeof(out_cfg->IEDname) - 1); + strncpy(out_cfg->LDevicePrefix, cfg.LDevicePrefix.toUtf8().constData(), sizeof(out_cfg->LDevicePrefix) - 1); + + return true; +} +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //lnk2024-8-16 适配角型接线 bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list *ctopiclist,QString path) //解析JiangSu_Config.xml配置文件 { @@ -2611,8 +2644,8 @@ char* Get_IED(char* devtype) } QString ied; - ied.append(xmlinfo_list[type]->xmlcfg.IEDname); // PQMonitor - ied.append(xmlinfo_list[type]->xmlcfg.LDevicePrefix); + ied.append(xmlinfo_list[type]->xmlcfg.IEDname); // 从配置文件读取的终端名 + ied.append(xmlinfo_list[type]->xmlcfg.LDevicePrefix); //// 从配置文件读取的监测点名 ied.append("%d"); QByteArray byteArray = ied.toLocal8Bit(); diff --git a/json/save2json.cpp b/json/save2json.cpp index 3f5affe..f9c3375 100644 --- a/json/save2json.cpp +++ b/json/save2json.cpp @@ -71,6 +71,8 @@ extern "C" { #define nullptr NULL #endif +extern uint32_t g_mqproducer_blocked_times; + extern int INITFLAG; extern std::string FRONT_INST; @@ -528,6 +530,9 @@ void KafkaSendThread::run() QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz").toAscii().data()); } + //清空计数器 + g_mqproducer_blocked_times =0; + QThread::msleep(10); // 避免 CPU 空转lnk20250326 } diff --git a/log4cplus/log4.h b/log4cplus/log4.h index 634b69c..bf92add 100644 --- a/log4cplus/log4.h +++ b/log4cplus/log4.h @@ -77,8 +77,26 @@ void log_warn(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 format_log_msg(char* buf, size_t buf_size, const char* fmt, ...); + +//宏定义 +#define DIY_LOG(LEVEL_FUNC, KEY, ...) \ + do { \ + char buf[256]; \ + format_log_msg(buf, sizeof(buf), __VA_ARGS__); \ + LEVEL_FUNC(KEY, buf); \ + } while (0) + +#define DIY_ERRORLOG(KEY, ...) DIY_LOG(log_error, KEY, __VA_ARGS__) +#define DIY_WARNLOG(KEY, ...) DIY_LOG(log_warn, KEY, __VA_ARGS__) +#define DIY_INFOLOG(KEY, ...) DIY_LOG(log_info, KEY, __VA_ARGS__) +#define DIY_DEBUGLOG(KEY, ...) DIY_LOG(log_debug, KEY, __VA_ARGS__) + + #ifdef __cplusplus } #endif + + #endif // LOG4_H diff --git a/mms/db_interface.h b/mms/db_interface.h index 853e8d2..d688626 100644 --- a/mms/db_interface.h +++ b/mms/db_interface.h @@ -150,6 +150,19 @@ int parse_model_cfg_web(); void SOEFileWeb(char* localpath,char* cloudpath,char* wavepath); const char* get_front_msg_from_subdir(); ////////////////////////////////////////////////////////////////////////////////////// +typedef struct { + char WavePhasicFlag[64]; + char WavePhasicA[64]; + char WavePhasicB[64]; + char WavePhasicC[64]; + char UnitOfTimeUnit[64]; + char ValueOfTimeUnit[64]; + char WaveTimeFlag[64]; + char IEDname[64]; + char LDevicePrefix[64]; +} XmlConfigC; + +bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg); #ifdef __cplusplus } diff --git a/mms/main.c b/mms/main.c index fda1d67..586870b 100644 --- a/mms/main.c +++ b/mms/main.c @@ -55,6 +55,11 @@ SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; /////////////////////////////////////////////////////// uint32_t g_dead_lock_counter = 0; uint32_t g_thread_blocked_times = 0; + +//给mq生产线程和定时线程都加上死锁计数器 +uint32_t g_mqproducer_blocked_times = 0; +uint32_t g_ontime_blocked_times = 0; + /////////////////////////////////////////////////////////////////////////////// int three_secs_enabled = 0; int auto_register_report_enabled = 0; @@ -225,9 +230,11 @@ int main(int argc, const char **argv) //lnk启动进程日志 init_logger_process(); - char buf[256]; - sprintf(buf, "前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index); - log_debug("process", buf); + + //char buf[256]; + //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index); + //log_debug("process", buf); + DIY_WARNLOG("process","前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index); #ifdef _OS_UNIX_ #ifdef QT_NO_DEBUG @@ -260,11 +267,19 @@ int main(int argc, const char **argv) rv = init_rdb(); if (rv!=APR_SUCCESS){ + //char buf[256]; + //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index); + //log_error("process", buf); + DIY_ERRORLOG("process","前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index); return rv; } rv = run_protocol(); if (rv!=APR_SUCCESS){ + //char buf[256]; + //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index); + //log_error("process", buf); + DIY_ERRORLOG("process","前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index); return rv; } @@ -307,6 +322,12 @@ int main(int argc, const char **argv) //work线程死了3*13分钟,退出进程 if (g_thread_blocked_times>=13) { MVL_LOG_ACSE0 ("MYLOG: g_thread_blocked_times>=3, so exit to restart "); + + //char buf[256]; + //format_log_msg(buf,sizeof(buf),"前置的业务线程死锁,退出进程"); + //log_error("process", buf); + DIY_ERRORLOG("process","前置的%s%d号进程 业务线程死锁,退出进程", get_front_msg_from_subdir(), g_front_seg_index); + apr_sleep(apr_time_from_sec(10)); exit(-1039); } @@ -422,6 +443,8 @@ void doMonitorTaskmain(void) { if( !(stimer++ % 60) ) {//分钟 if (g_dead_lock_counter++ >=3) {//三分钟 g_thread_blocked_times++; + g_mqproducer_blocked_times++; + g_ontime_blocked_times++; g_dead_lock_counter = 0; } MVL_LOG_ACSE1 ("MYLOG: current g_thread_blocked_times = %u ", g_thread_blocked_times); @@ -435,7 +458,7 @@ void doMonitorTaskmain(void) { } //work线程死了3*13分钟,退出进程 - if (g_thread_blocked_times>=13) { + if (g_thread_blocked_times>=13 || g_mqproducer_blocked_times>=13 || g_ontime_blocked_times>=13 ) { MVL_LOG_ACSE0 ("MYLOG: g_thread_blocked_times>=3, so exit to restart "); apr_sleep(apr_time_from_sec(10)); exit(-1039); diff --git a/mms/mms_process.c b/mms/mms_process.c index 524d576..266875b 100644 --- a/mms/mms_process.c +++ b/mms/mms_process.c @@ -659,7 +659,7 @@ void check_3s_config() printf("begin 3s config...\n"); last_check_3s_config_time = now; //记录本次运行时间 - while (APR_SUCCESS==parse_3s_xml(&trigger_3s_xml)){ //处理3秒文件 + while (APR_SUCCESS==parse_3s_xml(&trigger_3s_xml)){ //处理3秒文件,一次处理一个 //处理实时触发加台账锁lnk20250114 //pthread_mutex_lock(&mtx); printf("3s hold lock !!!!!!!!!!!"); process_3s_config(&trigger_3s_xml); //根据文件处理数据 @@ -1799,6 +1799,33 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info ) /*上传.cfg和.dat两个文件*/ /*上传消息*/ + /////////////////////////////////////////////////////lnk20250520 + //根据配置文件控制上传的暂态事件时间为北京时间的ms数 + printf("~~~~~~~this dev type is %s~~~~~~~",ied_usr->dev_type); + XmlConfigC cfg1; + if (get_xml_config_by_dev_type(ied_usr->dev_type, &cfg1)) { + printf("UnitOfTimeUnit = %s\n", cfg1.UnitOfTimeUnit); + printf("ValueOfTimeUnit = %s\n", cfg1.ValueOfTimeUnit); + } else { + printf("读取失败,未找到 dev_type\n"); + } + double s_or_ms; + long long utc_or_beijing; + if(cfg1.UnitOfTimeUnit == "1"){//持续时间上送的是秒1还是毫秒0 + s_or_ms = 0.001; + } + else{ + s_or_ms = 1.0; + } + + if(cfg1.ValueOfTimeUnit == "utc"){//持续时间上送的是秒1还是毫秒0 + utc_or_beijing = 28800000; + } + else{ + utc_or_beijing = 0; + } + ///////////////////////////////////////////////////// + //to send json of this qvvr and rdre end_tm = (long long)(qvvr->QVVR_PerTime*1000) + trig_tm; //结束时间是持续时间加触发时间 if (FILE_FLAG == 3) { @@ -1809,7 +1836,18 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info ) if (cfg_result != NULL && dat_result != NULL) { snprintf(cfg_result, cfg_len, "%s-%s", uuid_cfg, filename_cfg); // 拼接字符串并确保不会溢出目标缓冲区 snprintf(dat_result, dat_len, "%s-%s", uuid_dat, filename_dat); // 拼接字符串并确保不会溢出目标缓冲区 - ret3 = transfer_json_qvvr_data(g_node_id, LD_info->line_id, (double)qvvr->QVVR_Amg, (double)qvvr->QVVR_PerTime, start_tm, end_tm, qvvr->QVVR_type, cfg_result, dat_result, LD_info->mp_id, qvvr->QVVR_Rptname, ied_usr->dev_type); + ret3 = transfer_json_qvvr_data(g_node_id, + LD_info->line_id, + (double)qvvr->QVVR_Amg, + (double)qvvr->QVVR_PerTime/s_or_ms, //lnk20250520上送的暂态持续时间为毫秒 + start_tm + utc_or_beijing, //lnk20250520上送的暂态时间为北京时间 + end_tm + utc_or_beijing, //lnk20250520上送的暂态时间为北京时间 + qvvr->QVVR_type, + cfg_result, + dat_result, + LD_info->mp_id, + qvvr->QVVR_Rptname, + ied_usr->dev_type); } free(cfg_result); // 使用完毕后释放动态分配的内存空间 free(dat_result); // 使用完毕后释放动态分配的内存空间 @@ -1827,11 +1865,16 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info ) snprintf(dat_result, dat_len, wavepath_dat); // 拼接字符串并确保不会溢出目标缓冲区 ret3 = transfer_json_qvvr_data(g_node_id, //这个参数没有使用 LD_info->line_id, //监测点序号 - (double)qvvr->QVVR_Amg, (double)qvvr->QVVR_PerTime, - qvvr->QVVR_time, //这里不使用文件中的开始时间start_tm,因为会影响写库,使用QVVR的时间QVVR_time//lnk20250311 - end_tm, qvvr->QVVR_type, //伏值、持续时间、开始时间、结束时间、暂态类型 - cfg_result, dat_result, //两个文件路径 - LD_info->mp_id, qvvr->QVVR_Rptname, ied_usr->dev_type);//监测点号,文件和监测点暂态事件匹配上的暂态报告名,终端类型 + (double)qvvr->QVVR_Amg, + (double)qvvr->QVVR_PerTime/s_or_ms, //lnk20250520上送的暂态持续时间为毫秒 + qvvr->QVVR_time + utc_or_beijing, //lnk20250520上送的暂态时间为北京时间 //这里不使用文件中的开始时间start_tm,因为会影响写库,使用QVVR的时间QVVR_time//lnk20250311 + end_tm + utc_or_beijing, //lnk20250520上送的暂态时间为北京时间 + qvvr->QVVR_type, //伏值、持续时间、开始时间、结束时间、暂态类型 + cfg_result, + dat_result, //两个文件路径 + LD_info->mp_id, + qvvr->QVVR_Rptname, + ied_usr->dev_type);//监测点号,文件和监测点暂态事件匹配上的暂态报告名,终端类型 } free(cfg_result); // 使用完毕后释放动态分配的内存空间 free(dat_result); // 使用完毕后释放动态分配的内存空间 @@ -1845,7 +1888,18 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info ) if (cfg_result != NULL && dat_result != NULL) { snprintf(cfg_result, cfg_len, "%s-%s", oss_file_fullname_cfg, cfg_only_filename_ret); // 拼接字符串并确保不会溢出目标缓冲区 snprintf(dat_result, dat_len, "%s-%s", oss_file_fullname_dat, dat_only_filename_ret); // 拼接字符串并确保不会溢出目标缓冲区 - ret3 = transfer_json_qvvr_data(g_node_id, LD_info->line_id, (double)qvvr->QVVR_Amg, (double)qvvr->QVVR_PerTime, start_tm, end_tm, qvvr->QVVR_type, cfg_result, dat_result, LD_info->mp_id, qvvr->QVVR_Rptname, ied_usr->dev_type); + ret3 = transfer_json_qvvr_data(g_node_id, + LD_info->line_id, + (double)qvvr->QVVR_Amg, + (double)qvvr->QVVR_PerTime/s_or_ms, //lnk20250520上送的暂态持续时间为毫秒 + start_tm + utc_or_beijing, //lnk20250520上送的暂态时间为北京时间 + end_tm + utc_or_beijing, //lnk20250520上送的暂态时间为北京时间 + qvvr->QVVR_type, + cfg_result, + dat_result, + LD_info->mp_id, + qvvr->QVVR_Rptname, + ied_usr->dev_type); } free(cfg_result); // 使用完毕后释放动态分配的内存空间 free(dat_result); // 使用完毕后释放动态分配的内存空间 diff --git a/mms/rdb_client.c b/mms/rdb_client.c index 70296d2..c86a952 100644 --- a/mms/rdb_client.c +++ b/mms/rdb_client.c @@ -190,6 +190,12 @@ apr_status_t init_rdb() rv = parse_device_cfg_web(); if (rv != APR_SUCCESS) { echo_errg("Parsed device config xml file with error,try to run! \n"); + + //char buf[256]; + //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index); + //log_error("process", buf); + DIY_ERRORLOG("process","前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index); + return rv; } @@ -199,6 +205,12 @@ apr_status_t init_rdb() rv = parse_model_cfg_web(); if (rv != APR_SUCCESS) { echo_errg("Parsed model with error,try to run! \n"); + + //char buf[256]; + //format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index); + //log_error("process", buf); + DIY_ERRORLOG("process","前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index); + return rv; } @@ -207,13 +219,20 @@ apr_status_t init_rdb() rv = parse_rpt_log_ini();//报告块初始化 if (rv != APR_SUCCESS) { echo_errg("Failed to parse report log define ini file! \n"); + + DIY_ERRORLOG("process","前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index); + return rv; } if (app_get_private_config(g_my_conf_fname) != APR_SUCCESS) { echo_errg("Failed when processing private configuration\n"); + + DIY_ERRORLOG("process","前置的%s%d号进程读取mms配置失败", get_front_msg_from_subdir(), g_front_seg_index); + return APR_EGENERAL; } + init_rem_dib_table(); return APR_SUCCESS; } diff --git a/mms/rdb_ext_utils.c b/mms/rdb_ext_utils.c index c895414..459e9bd 100644 --- a/mms/rdb_ext_utils.c +++ b/mms/rdb_ext_utils.c @@ -477,7 +477,7 @@ void processQVVR_start(LD_info_t* LD_info) void processQVVR_time(LD_info_t* LD_info, long long Time) { LD_info->qvvr[LD_info->qvvr_idx].QVVR_time = Time; - printf("\n~~~~~~~~~~~~~~~~~ processQVVR_time: line_id=%d ,Time=%lld \n",LD_info->line_id,Time); + printf("\n~~~~~~~~~~~~~~~~~ processQVVR_time: line_id=%d ,Time=%lld \n",LD_info->line_id,Time);//这里是报告上送的时间 } @@ -525,21 +525,55 @@ void processQVVR_end(LD_info_t* LD_info) if (LD_info->qvvr[LD_info->qvvr_idx].QVVR_start)//波动数据处理时FCDA包含VarStr$stVal,QVVR_start为1,退出处理 return; + //获取时间类型lnk20250520 + printf("~~~~~~~this dev type is %s~~~~~~~",ied_usr->dev_type); + XmlConfigC cfg; + if (get_xml_config_by_dev_type(ied_usr->dev_type, &cfg)) { + printf("UnitOfTimeUnit = %s\n", cfg.UnitOfTimeUnit); + printf("ValueOfTimeUnit = %s\n", cfg.ValueOfTimeUnit); + } else { + printf("读取失败,未找到 dev_type\n"); + } + double s_or_ms; + long long utc_or_beijing; + if(cfg.UnitOfTimeUnit == "1"){//持续时间上送的是秒1还是毫秒0 + s_or_ms = 0.001; + } + else{ + s_or_ms = 1.0; + } + + if(cfg.ValueOfTimeUnit == "utc"){//上送的是utc还是北京 + utc_or_beijing = 28800000; + } + else{ + utc_or_beijing = 0; + } + + for (i=0;iqvvr_idx) //跳过监测点当前波动位置,第一次记录波形后,第一次的第三个事件会让0号点为QVVR_DATA_RECEIVED, //第二次记录波形,第二次的第一个事件qvvr_idx=1,1号中为QVVR_DATA_RECEIVED,QVVR_start=1,跳过记录, //第二次的第二个事件qvvr_idx=1,QVVR_start=0,记录到0中,0为QVVR_DATA_PAIRED //第二次的第三个事件qvvr_idx=2,2号中为QVVR_DATA_RECEIVED,QVVR_start=1,跳过记录 //第二次录波匹配文件时应该匹配到1号的qvvrtime,但是1没有QVVR_DATA_PAIRED所以对不上,需要修改逻辑 + { + printf("skip this index\n"); continue; + } + if (LD_info->qvvr[i].used_status != QVVR_DATA_RECEIVED)//跳过没有收到波动的位置 + { + printf("qvvr %d is not received\n",i); continue; - //添加时间判断lnk20250311 - if (fabs((LD_info->qvvr[LD_info->qvvr_idx].QVVR_time - LD_info->qvvr[i].QVVR_time)/1.0 - - LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime) > 1.0){ + } + + //添加时间判断lnk20250311,当前的时间减去找到的时间应该等于持续时间 + if (fabs((LD_info->qvvr[LD_info->qvvr_idx].QVVR_time - LD_info->qvvr[i].QVVR_time)/1.0 //判断秒还是毫秒 + - LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime/s_or_ms) > 1.0){ printf("~~~~~~~fail in pair qvvr node %f~~~~~~~~~~ \n",fabs((LD_info->qvvr[LD_info->qvvr_idx].QVVR_time - LD_info->qvvr[i].QVVR_time)/1.0 - - LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime)); + - LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime/s_or_ms)); continue; } @@ -548,7 +582,8 @@ void processQVVR_end(LD_info_t* LD_info) //其他某位置的波动也没有定义类型/这个位置的波动类型和当前位置的波动类型一致,暂降事件一次会发三个报告,启动和上值和结束 if ( (LD_info->qvvr[i].QVVR_type==0)||(LD_info->qvvr[i].QVVR_type==LD_info->qvvr[LD_info->qvvr_idx].QVVR_type) ) { - long long end_tm = (long long)(LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime*1000) + LD_info->qvvr[i].QVVR_time;//结束时间是持续时间加最初的触发时间,毫秒 + //long long end_tm = (long long)(LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime*1000) + LD_info->qvvr[i].QVVR_time;//结束时间是持续时间加最初的触发时间,毫秒 + long long end_tm = (long long)(LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime/s_or_ms) + LD_info->qvvr[i].QVVR_time;//结束时间是持续时间加最初的触发时间,毫秒 printf("\n~~~~~~~now qvvr node type before record is %d~~~~~~~~~~ \n",LD_info->qvvr[LD_info->qvvr_idx].QVVR_type); printf("~~~~~~~now qvvr node QVVR_PerTime before record is %f~~~~~~~~~~ \n",LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime); @@ -560,7 +595,7 @@ void processQVVR_end(LD_info_t* LD_info) LD_info->qvvr[i].used_status = QVVR_DATA_PAIRED; //匹配上了 LD_info->qvvr[i].QVVR_type = LD_info->qvvr[LD_info->qvvr_idx].QVVR_type; - LD_info->qvvr[i].QVVR_PerTime = LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime; + LD_info->qvvr[i].QVVR_PerTime = LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime;//存在内存的还是原始读出的数据 LD_info->qvvr[i].QVVR_Amg = LD_info->qvvr[LD_info->qvvr_idx].QVVR_Amg; //记录当前这个点的波动数据到找到的点位置上,确保记录的是最新的相同类型的事件 LD_info->qvvr[LD_info->qvvr_idx].used_status = QVVR_DATA_NOT_USED; //当前这个点位置释放 @@ -578,12 +613,15 @@ void processQVVR_end(LD_info_t* LD_info) ret = transfer_json_qvvr_data(g_node_id, //这个参数没有使用 LD_info->line_id, //监测点序号 (double)LD_info->qvvr[LD_info->qvvr_idx].QVVR_Amg, - (double)LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime, - LD_info->qvvr[i].QVVR_time, - end_tm, + (double)LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime/s_or_ms, //上传转换为ms + LD_info->qvvr[i].QVVR_time + utc_or_beijing, //上传北京时间 + end_tm + utc_or_beijing, //上传北京时间 LD_info->qvvr[LD_info->qvvr_idx].QVVR_type, //伏值、持续时间、开始时间、结束时间、暂态类型 - "", "", //两个文件路径为空 - LD_info->mp_id, LD_info->qvvr[LD_info->qvvr_idx].QVVR_Rptname, ied_usr->dev_type);//监测点号,文件和监测点暂态事件匹配上的暂态报告名,终端类型 + "", + "", //两个文件路径为空 + LD_info->mp_id, + LD_info->qvvr[LD_info->qvvr_idx].QVVR_Rptname, + ied_usr->dev_type);//监测点号,文件和监测点暂态事件匹配上的暂态报告名,终端类型 if(!ret)//失败 { printf("\n~~~~~~~~~~~~~~~~~ QVVR_json_data send error: line_id=%d \n",LD_info->line_id); diff --git a/pt61850netd_pqfe b/pt61850netd_pqfe index 93b6b58..460c2f4 100644 Binary files a/pt61850netd_pqfe and b/pt61850netd_pqfe differ diff --git a/pt61850netd_pqfed b/pt61850netd_pqfed index 2584b1b..b569121 100644 Binary files a/pt61850netd_pqfed and b/pt61850netd_pqfed differ