11 Commits

Author SHA1 Message Date
lnk
1b2dd863e9 x86 and arm use same code 2026-04-07 10:18:44 +08:00
lnk
c78bc592a8 同步arm修改 2026-04-03 16:03:25 +08:00
lnk
6f7ee762ec fix process control script 2026-03-23 16:11:17 +08:00
lnk
0acc58bbe1 add function:upload and download device file ,modify interface function fix memleak 2026-03-12 15:28:17 +08:00
lnk
d1ed49412c 现在可以只开日志并保留台账更新和进程控制 2026-03-09 19:55:36 +08:00
lnk
748f8481bc modify log4 function and add data trace function 2026-03-06 16:27:58 +08:00
lnk
d5916f5559 fix D001 2026-03-04 19:15:32 +08:00
lnk
50dd5c8a3e add log in ggio 2026-02-04 09:21:54 +08:00
lnk
1bc32ae38c add debug print 2026-02-02 10:39:27 +08:00
lnk
fe8ba6fad9 fix recall 2026-01-28 13:43:24 +08:00
lnk
a2aa627b1e fix phpst and phplt in statistic data 2026-01-27 16:58:15 +08:00
19 changed files with 2528 additions and 862 deletions

View File

@@ -58,8 +58,6 @@ extern std::string FRONT_INST;
extern "C" { extern "C" {
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -561,7 +559,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_CODE("process",LOG_CODE_MQ,"前置的%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
@@ -655,7 +653,7 @@ void producer_send(const char* strbody)
/////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////
extern "C" { extern "C" {
//extern std::string G_MQCONSUMER_TOPIC_RT;
void rocketmq_test_rt() void rocketmq_test_rt()
{ {
Ckafka_data_t data; Ckafka_data_t data;
@@ -669,7 +667,7 @@ void rocketmq_test_rt()
data.mp_id = 123123; data.mp_id = 123123;
my_rocketmq_send(data); my_rocketmq_send(data);
} }
//extern std::string G_MQCONSUMER_TOPIC_UD;
void rocketmq_test_ud()//用来测试台账更新 void rocketmq_test_ud()//用来测试台账更新
{ {
Ckafka_data_t data; Ckafka_data_t data;
@@ -712,7 +710,7 @@ void rocketmq_test_only()//用来测试进程控制脚本
my_rocketmq_send(data); my_rocketmq_send(data);
} }
//extern std::string G_MQCONSUMER_TOPIC_RC;
void rocketmq_test_rc() void rocketmq_test_rc()
{ {
Ckafka_data_t data; Ckafka_data_t data;
@@ -727,7 +725,7 @@ void rocketmq_test_rc()
my_rocketmq_send(data); my_rocketmq_send(data);
} }
//extern std::string G_MQCONSUMER_TOPIC_LOG;
void rocketmq_test_log() void rocketmq_test_log()
{ {
Ckafka_data_t data; Ckafka_data_t data;

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
#include "../log4cplus/fileappender.h" #include "../log4cplus/fileappender.h"
#include "../log4cplus/layout.h" #include "../log4cplus/layout.h"
#include "../log4cplus/ndc.h" #include "../log4cplus/ndc.h"
#include "../log4cplus/log4.h" //#include "../log4cplus/log4.h"
#include "../log4cplus/spi/loggingevent.h" #include "../log4cplus/spi/loggingevent.h"
#include <iostream> #include <iostream>
#include <map> #include <map>
@@ -18,21 +18,47 @@
//目录创建 //目录创建
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
//kafka结构定义
#include "../json/mms_json_inter.h" #include "../json/mms_json_inter.h"
#include "../mms/rdb_client.h" #include "../mms/rdb_client.h"
#include "../include/node.h"//lnk20241223 #include "../include/node.h"//lnk20241223
#include "../log4cplus/log4.h"//后移防止min/max定义冲突
///////////////////////////////////////////////lnk20260303添加日志上送控制
#include <unordered_map>
#include <chrono>
#include <mutex>
#include <atomic>
#include <memory>
struct LogLevelCache { //记录日志等级的缓存减少频繁访问全局map的开销
std::unordered_map<std::string, int> term_min; // terminal_id -> min level
std::unordered_map<std::string, int> mp_min; // mp_id -> min level
};
// append线程只读不加锁
static std::shared_ptr<LogLevelCache> g_level_cache_sp;
///////////////////////////////////////////////
//用来控制日志上送的结构
struct LOGEntry {
std::string id;
std::string level; // terminal / measurepoint
int code; //code
int min_grade;
int countdown;
};
//日志上送map管理
std::map<std::string, LOGEntry> g_log_entries;
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
/////////////////////////////////////////////外部定义
extern unsigned int g_node_id; extern unsigned int g_node_id;
extern int g_front_seg_index; extern int g_front_seg_index;
extern std::string FRONT_INST; extern std::string FRONT_INST;
extern char subdir[128]; extern char subdir[128];
extern node_t* g_node; extern node_t* g_node;
//mq //mq
extern QMutex kafka_data_list_mutex; //Kafka发送数据锁 extern QMutex kafka_data_list_mutex; //Kafka发送数据锁
extern QList<Ckafka_data_t> kafka_data_list; //kafka发送数据链表 extern QList<Ckafka_data_t> kafka_data_list; //kafka发送数据链表
@@ -42,12 +68,153 @@ extern std::string intToString(int number);
//日志主题 //日志主题
extern std::string G_LOG_TOPIC; extern std::string G_LOG_TOPIC;
/////////////////////////////////////////////////////////
//log4命名空间 //log4命名空间
using namespace log4cplus; using namespace log4cplus;
using namespace log4cplus::helpers; using namespace log4cplus::helpers;
///////////////////////////////////////////////////////////////
static std::string extract_logger_id(const std::string& logger_name);
////////////////////////////////////////////////////////辅助函数 ////////////////////////////////////////////////////////辅助函数
///////////////////////////////////////////////////////lnk20260303添加日志上送控制
//用于在台账中查询日志上送控制项的日志等级字符串转换为整数
static int int_to_loglevel(int v, int default_level = WARN_LOG_LEVEL)
{
switch (v) {
case 0: return ERROR_LOG_LEVEL;
case 1: return WARN_LOG_LEVEL;
case 2: return INFO_LOG_LEVEL;
case 3: return DEBUG_LOG_LEVEL;
default: return default_level;
}
}
// 构建日志等级缓存,减少 append 线程访问全局 map 的开销
static LogLevelCache* build_cache_unlocked()
{
LogLevelCache* nc = new LogLevelCache;
// 没 node / 没 clients返回空 cache查不到会兜底 WARN
if (!g_node || g_node->n_clients <= 0 || !g_node->clients) {
return nc;
}
// 你 LD_info 是固定 10 个就用 10如果不是改成实际长度
const int MAX_LD = 10;
for (int iedno = 0; iedno < g_node->n_clients; ++iedno) {
ied_t* ied = g_node->clients[iedno];
if (!ied || !ied->usr_ext) continue;
ied_usr_t* ied_usr = (ied_usr_t*)ied->usr_ext;
// terminal_id 必须有效
const char* tid = ied_usr->terminal_id;
if (!tid || tid[0] == '\0') continue;
const std::string terminal_id(tid);
// 装置级阈值0~3 -> log4cplus level默认 WARN
const int term_lv = int_to_loglevel(ied_usr->log_level, WARN_LOG_LEVEL);
nc->term_min[terminal_id] = term_lv;
// 监测点阈值:若非法/缺失,兜底用装置级 term_lv
for (int i = 0; i < MAX_LD; ++i) {
const char* mp = ied_usr->LD_info[i].mp_id;
if (!mp || mp[0] == '\0') continue;
const std::string mp_id(mp);
// mp 的 log_level 优先;非法则用 term_lv
const int mp_lv = int_to_loglevel(ied_usr->LD_info[i].log_level, term_lv);
nc->mp_min[mp_id] = mp_lv;
}
}
return nc;
}
//用于更新日志等级缓存的函数,获取最新的日志上送控制项并更新到缓存中,调用时需持锁
void refresh_log_level_cache_locked()
{
std::shared_ptr<LogLevelCache> nc(build_cache_unlocked());
std::atomic_store(&g_level_cache_sp, nc);
}
const int LOGTYPE_DEFAULT = LOG_CODE_OTHER; // 默认日志类型,表示不区分具体类型的日志上送控制
static const int LOGTYPE_WILDCARD = 999; // 用于匹配任意日志类型的特殊值
static const char* ID_WILDCARD = "all"; // 用于匹配任意 ID 的特殊值
static std::string build_debug_key(const std::string& id,
const std::string& level, // terminal/measurepoint/process
int code) // 日志类型
{
std::ostringstream oss;
oss << id << "|" << level << "|" << code;
return oss.str();
}
static bool find_entry_allow(const std::string& key, int level_val)
{
std::map<std::string, LOGEntry>::iterator it = g_log_entries.find(key);
if (it == g_log_entries.end() || it->second.countdown <= 0) return false;
return level_val >= it->second.min_grade;
}
static bool allow_low_level_send(const std::string& id,
const std::string& level_str,
int code,
int level_val)
{
pthread_mutex_lock(&g_log_mutex);
// 1) 精确
if (find_entry_allow(build_debug_key(id, level_str, code), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
// 2) logtype 通配
if (find_entry_allow(build_debug_key(id, level_str, LOGTYPE_WILDCARD), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
// 3) id 通配
if (find_entry_allow(build_debug_key(ID_WILDCARD, level_str, code), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
// 4) 双通配
if (find_entry_allow(build_debug_key(ID_WILDCARD, level_str, LOGTYPE_WILDCARD), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
pthread_mutex_unlock(&g_log_mutex);
return false;
}
static int get_min_send_level_cached(const std::string& level_str, const std::string& logger_name)
{
const int DEFAULT_LEVEL = WARN_LOG_LEVEL;
if (level_str == "process") return DEFAULT_LEVEL;
const std::string id = extract_logger_id(logger_name); //terminal.<id> / monitor.<mp>
if (id.empty()) return DEFAULT_LEVEL;
std::shared_ptr<LogLevelCache> c = std::atomic_load(&g_level_cache_sp);
if (!c) return DEFAULT_LEVEL;
if (level_str == "terminal") {
auto it = c->term_min.find(id);
return (it != c->term_min.end()) ? it->second : DEFAULT_LEVEL;
}
if (level_str == "measurepoint") {
auto it = c->mp_min.find(id);
return (it != c->mp_min.end()) ? it->second : DEFAULT_LEVEL;
}
return DEFAULT_LEVEL;
}
///////////////////////////////////////////////////////lnk20260303添加日志上送控制
std::string get_front_type_from_subdir() { std::string get_front_type_from_subdir() {
if (std::strstr(subdir, "cfg_3s_data") != NULL) if (std::strstr(subdir, "cfg_3s_data") != NULL)
return "realTime"; return "realTime";
@@ -79,12 +246,11 @@ bool create_directory_recursive(const std::string& path) {
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
std::string extract_logger_id(const std::string& logger_name) { std::string extract_logger_id(const std::string& logger_name) {
size_t first = logger_name.find('.'); if (logger_name == "process") return "process";
size_t last = logger_name.rfind('.'); size_t pos = logger_name.find('.');
if (first != std::string::npos && last != std::string::npos && first + 1 < last) { if (pos == std::string::npos) return "";
return logger_name.substr(first + 1, last - first - 1); // 去掉开头"terminal."和结尾".COM" // 取第一个 '.' 后面的全部terminal.<id> / monitor.<mp>
} return logger_name.substr(pos + 1);
return "";
} }
std::string get_level_str(int level) { std::string get_level_str(int level) {
@@ -98,7 +264,7 @@ std::string get_level_str(int level) {
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
TypedLogger::TypedLogger() {} TypedLogger::TypedLogger() {}
TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), logtype(t) {} TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), code(t) {}
DebugSwitch::DebugSwitch() : debug_open(false), min_level(WARN_LOG_LEVEL) {} DebugSwitch::DebugSwitch() : debug_open(false), min_level(WARN_LOG_LEVEL) {}
void DebugSwitch::open() { debug_open = true; } void DebugSwitch::open() { debug_open = true; }
@@ -132,47 +298,66 @@ 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) override {
std::string logger_name = event.getLoggerName(); std::string logger_name = event.getLoggerName();
int level = event.getLogLevel(); int level = event.getLogLevel();
std::string msg = event.getMessage(); std::string msg = event.getMessage();
int logtype = (logger_name.find(".COM") != std::string::npos) ? LOGTYPE_COM : LOGTYPE_DATA;
std::string level_str; std::string level_str;
if (logger_name.find("process") == 0) if (logger_name.find("process") == 0)
level_str = "process"; level_str = "process";
else if (logger_name.find("monitor") != std::string::npos) else if (logger_name.find("monitor") != std::string::npos)
level_str = "measurepoint"; level_str = "measurepoint";
else else if (logger_name.find("terminal") != std::string::npos)
level_str = "terminal"; level_str = "terminal";
else
level_str = "process";
// ★读取 TLS 中的 code(在打日志的线程里由宏设定) int code = g_log_code_tls; // TLS code
int code = g_log_code_tls; // 若未显式传入,则为 0 int safe_logtype = code; // ★关键:用 code 当 logtype 维度
bool allow_send = false;
int min_send_level = get_min_send_level_cached(level_str, logger_name);
// ① 高于台账阈值:直接上送
if (level >= min_send_level) {
allow_send = true;
} else {
// ② 低等级:默认不上送,除非命令打开
std::string ctrl_id;
if (level_str == "process") ctrl_id = "process";
else ctrl_id = extract_logger_id(logger_name);
if (!ctrl_id.empty()) {
allow_send = allow_low_level_send(ctrl_id, level_str, safe_logtype, level);
}
}
if (!allow_send) return;
// ③ 限频:同一条日志
const std::string rkey = make_key(logger_name, level, code, msg);
if (!should_emit(rkey)) return;
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)
<< "\",\"nodeId\":\"" << FRONT_INST << "\",\"nodeId\":\"" << FRONT_INST
<< "\",\"businessId\":\"" << extract_logger_id(logger_name) << "\",\"businessId\":\"" << extract_logger_id(logger_name)
<< "\",\"level\":\"" << level_str << "\",\"level\":\"" << level_str
<< "\",\"grade\":\"" << get_level_str(level) << "\",\"grade\":\"" << get_level_str(level)
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data") << "\",\"logtype\":\"" << safe_logtype
<< "\",\"frontType\":\"" << get_front_type_from_subdir() << "\",\"frontType\":\"" << get_front_type_from_subdir()
// ★新增:输出 code 字段(整型) << "\",\"code\":" << code
<< "\",\"code\":\"" << code << ",\"log\":\"" << escape_json(msg) << "\"}";
<< "\",\"log\":\"" << escape_json(msg) << "\"}";
std::string jsonString = oss.str();
Ckafka_data_t connect_info; Ckafka_data_t connect_info;
connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC); connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC);
connect_info.strText = QString::fromStdString(jsonString); connect_info.strText = QString::fromStdString(oss.str());
kafka_data_list_mutex.lock(); kafka_data_list_mutex.lock();
kafka_data_list.append(connect_info); kafka_data_list.append(connect_info);
kafka_data_list_mutex.unlock(); kafka_data_list_mutex.unlock();
} }
}
std::string escape_json(const std::string& input) { std::string escape_json(const std::string& input) {
std::ostringstream ss; std::ostringstream ss;
@@ -198,25 +383,58 @@ public:
virtual ~SendAppender() { virtual ~SendAppender() {
destructorImpl(); // 重要!释放 log4cplus 基类资源 destructorImpl(); // 重要!释放 log4cplus 基类资源
} }
//////////////////////////////////////////////////////////////////20260303添加日志上送控制 - 频率限制实现
private:
struct RateState {
uint64_t hit_count;
std::chrono::steady_clock::time_point last_emit;
bool has_emit;
RateState() : hit_count(0), last_emit(), has_emit(false) {}
};
static std::unordered_map<std::string, RateState> s_rate_map;
static std::mutex s_rate_mutex;
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;
return oss.str();
}
static bool should_emit(const std::string& key) {
using namespace std::chrono;
const auto now = steady_clock::now();
std::lock_guard<std::mutex> lk(s_rate_mutex);
RateState& st = s_rate_map[key];
const int RESET_SEC = 3600;
if (st.has_emit) {
auto idle = duration_cast<seconds>(now - st.last_emit).count();
if (idle >= RESET_SEC) st.hit_count = 0;
}
st.hit_count++;
const int period_sec = (st.hit_count > 3) ? 300 : 1;
if (!st.has_emit) {
st.last_emit = now;
st.has_emit = true;
return true;
}
const auto elapsed = duration_cast<seconds>(now - st.last_emit).count();
if (elapsed >= period_sec) {
st.last_emit = now;
return true;
}
return false;
}
}; };
//////////////////////////////////////////////////////////////////20260303添加日志上送控制 - 频率限制实现
//用来控制日志上送的结构 std::unordered_map<std::string, SendAppender::RateState> SendAppender::s_rate_map;
struct LOGEntry { std::mutex SendAppender::s_rate_mutex;
std::string id;
std::string level; // terminal / measurepoint
int logtype; // com / data
int min_grade;
int countdown;
};
//日志上送map管理
std::map<std::string, LOGEntry> g_log_entries;
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
// 生成唯一 key
std::string build_debug_key(const std::string& id, const std::string& level, int logtype) {
return id + "|" + level + "|" + (logtype == 1 ? "COM" : "DATA");
}
// 外部线程中调用每秒更新所有倒计时0 则删除 // 外部线程中调用每秒更新所有倒计时0 则删除
void update_log_entries_countdown() { void update_log_entries_countdown() {
@@ -236,25 +454,25 @@ void update_log_entries_countdown() {
pthread_mutex_unlock(&g_log_mutex); pthread_mutex_unlock(&g_log_mutex);
} }
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str) { void process_log_command(const std::string& id,
if (level != "terminal" && level != "measurepoint") return; const std::string& level,
const std::string& grade,
int code)
{
if (level != "terminal" && level != "measurepoint" && level != "process") return;
int type = (logtype_str == "com") ? LOGTYPE_COM : LOGTYPE_DATA;
int grade_level = (grade == "DEBUG") ? DEBUG_LOG_LEVEL : INFO_LOG_LEVEL; int grade_level = (grade == "DEBUG") ? DEBUG_LOG_LEVEL : INFO_LOG_LEVEL;
std::string key = build_debug_key(id, level, type); std::string key = build_debug_key(id, level, code);
pthread_mutex_lock(&g_log_mutex); pthread_mutex_lock(&g_log_mutex);
LOGEntry& entry = g_log_entries[key];
LOGEntry& entry = g_log_entries[key]; // 会自动 insert 或取已有
entry.id = id; entry.id = id;
entry.level = level; entry.level = level;
entry.logtype = type; entry.code = code;
entry.min_grade = grade_level; entry.min_grade = grade_level;
entry.countdown = 60; // 重置倒计时 entry.countdown = 60;
pthread_mutex_unlock(&g_log_mutex); pthread_mutex_unlock(&g_log_mutex);
} }
Logger init_logger(const std::string& full_name, const std::string& file_dir, const std::string& base_file, SharedAppenderPtr fileAppender) { Logger init_logger(const std::string& full_name, const std::string& file_dir, const std::string& base_file, SharedAppenderPtr fileAppender) {
@@ -286,7 +504,7 @@ log4cplus::Logger init_logger(const std::string& full_name,
//进程的日志 //进程的日志
void init_logger_process() { void init_logger_process() {
std::string base_dir = std::string("/FeProject/") + subdir + "/processNo" + intToString(g_front_seg_index) + "/log"; std::string base_dir = std::string("/FeProject/") + subdir + "/processNo" + intToString(g_front_seg_index) + "/log";
logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DATA); logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DEFAULT);
std::cout << "process log init ok" << std::endl; std::cout << "process log init ok" << std::endl;
} }
@@ -321,12 +539,10 @@ void init_loggers_bydevid(const char* dev_id)
std::string device_dir = base_dir + "/" + ip_str; std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + dev_id + ".COM"; std::string device_key = std::string("terminal.") + dev_id;
std::string device_key_d = std::string("terminal.") + dev_id + ".DATA";
// 添加判断:终端日志 logger 是否已存在 // 添加判断:终端日志 logger 是否已存在
if (logger_map.find(device_key_c) == logger_map.end() && if (logger_map.find(device_key) == logger_map.end()) {
logger_map.find(device_key_d) == logger_map.end()) {
// 所有终端日志com 和 data写到同一个 device 日志文件中 // 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + dev_id + ".log"; std::string file_path_t = device_dir + "/" + dev_id + ".log";
@@ -335,27 +551,23 @@ void init_loggers_bydevid(const char* dev_id)
SharedAppenderPtr device_appender = SharedAppenderPtr(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2)); SharedAppenderPtr device_appender = SharedAppenderPtr(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); device_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, dev_id, device_appender); //用终端id作为日志文件名 Logger device_logger = init_logger(device_key, device_dir, dev_id, device_appender); //用终端id作为日志文件名
Logger device_logger_d = init_logger(device_key_d, device_dir, dev_id, device_appender); //用终端id作为日志文件名 logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT);
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
DIY_INFOLOG(device_key_d.c_str(),"终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); DIY_INFOLOG(device_key.c_str(),"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
} }
// 初始化监测点 // 初始化监测点
// 监测点 logger 名称格式monitor.<mp_id>.COM / .DATA // 监测点 logger 名称格式monitor.<mp_id>
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
if (strlen(ied_usr->LD_info[i].mp_id) > 0){ if (strlen(ied_usr->LD_info[i].mp_id) > 0){
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name; std::ostringstream mon_key, mon_path, mon_name;
mon_key_c << "monitor." << ied_usr->LD_info[i].mp_id << ".COM"; mon_key << "monitor." << ied_usr->LD_info[i].mp_id;
mon_key_d << "monitor." << ied_usr->LD_info[i].mp_id << ".DATA";
mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录 mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录
mon_name << ied_usr->LD_info[i].mp_id; mon_name << ied_usr->LD_info[i].mp_id;
// 添加判断:监测点 logger 是否已存在 // 添加判断:监测点 logger 是否已存在
if (logger_map.find(mon_key_c.str()) == logger_map.end() && if (logger_map.find(mon_key.str()) == logger_map.end()) {
logger_map.find(mon_key_d.str()) == logger_map.end()) {
// 所有监测点日志com 和 data写到同一个 monitor 日志文件中 // 所有监测点日志com 和 data写到同一个 monitor 日志文件中
std::string file_path_m = mon_path.str() + "/" + mon_name.str() + ".log"; std::string file_path_m = mon_path.str() + "/" + mon_name.str() + ".log";
@@ -364,12 +576,10 @@ void init_loggers_bydevid(const char* dev_id)
SharedAppenderPtr monitor_appender = SharedAppenderPtr(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2)); SharedAppenderPtr monitor_appender = SharedAppenderPtr(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); monitor_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(),monitor_appender);//用监测点号作为日志文件名 Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(),monitor_appender);//用监测点号作为日志文件名
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(),monitor_appender); logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
DIY_INFOLOG(mon_key_d.str().c_str(),"监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); DIY_INFOLOG(mon_key.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
} }
} }
@@ -377,6 +587,9 @@ void init_loggers_bydevid(const char* dev_id)
break; // 只匹配一个 terminal_id break; // 只匹配一个 terminal_id
} }
//lnk20260303添加日志上送控制 - 初始化时构建日志等级缓存
refresh_log_level_cache_locked();
} }
void init_loggers() { void init_loggers() {
@@ -402,8 +615,7 @@ void init_loggers() {
std::string device_dir = base_dir + "/" + ip_str; std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + ied_usr->terminal_id + ".COM"; std::string device_key = std::string("terminal.") + ied_usr->terminal_id;
std::string device_key_d = std::string("terminal.") + ied_usr->terminal_id + ".DATA";
// 所有终端日志com 和 data写到同一个 device 日志文件中 // 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + ied_usr->terminal_id + ".log"; std::string file_path_t = device_dir + "/" + ied_usr->terminal_id + ".log";
@@ -412,21 +624,18 @@ void init_loggers() {
SharedAppenderPtr device_appender = SharedAppenderPtr(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2)); SharedAppenderPtr device_appender = SharedAppenderPtr(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); device_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, ied_usr->terminal_id, device_appender); //用终端id作为日志文件名 Logger device_logger = init_logger(device_key, device_dir, ied_usr->terminal_id, device_appender); //用终端id作为日志文件名
Logger device_logger_d = init_logger(device_key_d, device_dir, ied_usr->terminal_id, device_appender); //用终端id作为日志文件名
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM); logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
DIY_INFOLOG(device_key_d.c_str(),"终端id:%s终端级日志初始化完毕", ied_usr->terminal_id); DIY_INFOLOG(device_key.c_str(),"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
// 初始化监测点 // 初始化监测点
// 监测点 logger 名称格式monitor.<mp_id>.COM / .DATA // 监测点 logger 名称格式monitor.<mp_id>
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
if (strlen(ied_usr->LD_info[i].mp_id) > 0){ if (strlen(ied_usr->LD_info[i].mp_id) > 0){
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name; std::ostringstream mon_key, mon_path, mon_name;
mon_key_c << "monitor." << ied_usr->LD_info[i].mp_id << ".COM"; mon_key << "monitor." << ied_usr->LD_info[i].mp_id;
mon_key_d << "monitor." << ied_usr->LD_info[i].mp_id << ".DATA";
mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录 mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录
mon_name << ied_usr->LD_info[i].mp_id; mon_name << ied_usr->LD_info[i].mp_id;
@@ -437,19 +646,19 @@ void init_loggers() {
SharedAppenderPtr monitor_appender = SharedAppenderPtr(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2)); SharedAppenderPtr monitor_appender = SharedAppenderPtr(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); monitor_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender); Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM); logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
DIY_INFOLOG(mon_key_d.str().c_str(),"监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id); DIY_INFOLOG(mon_key.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
} }
} }
} }
//lnk20260303添加日志上送控制 - 初始化时构建日志等级缓存
refresh_log_level_cache_locked();
} }
void remove_loggers_by_terminal_id(const char* terminal_id_cstr) { void remove_loggers_by_terminal_id(const char* terminal_id_cstr) {
@@ -465,37 +674,24 @@ void remove_loggers_by_terminal_id(const char* terminal_id_cstr) {
if (strcmp(ied_usr->terminal_id, terminal_id.c_str()) != 0) continue; if (strcmp(ied_usr->terminal_id, terminal_id.c_str()) != 0) continue;
// 删除终端日志 logger // 删除终端日志 logger
std::string com_key = "terminal." + terminal_id + ".COM"; std::string terminal_key = "terminal." + terminal_id;;
std::string data_key = "terminal." + terminal_id + ".DATA";
if (logger_map.count(com_key)) { if (logger_map.count(terminal_key)) {
logger_map[com_key].logger.removeAllAppenders(); logger_map[terminal_key].logger.removeAllAppenders();
logger_map.erase(com_key); logger_map.erase(terminal_key);
}
if (logger_map.count(data_key)) {
logger_map[data_key].logger.removeAllAppenders();
logger_map.erase(data_key);
} }
// 删除监测点日志 logger // 删除监测点日志 logger
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
const char* mp_id = ied_usr->LD_info[i].mp_id; const char* mp_id = ied_usr->LD_info[i].mp_id;
if (strlen(mp_id) > 0) { if (strlen(mp_id) > 0) {
std::string mon_prefix = std::string("monitor.") + mp_id; std::string mon_key = std::string("monitor.") + mp_id;
std::string mon_com_key = mon_prefix + ".COM"; if (logger_map.count(mon_key)) {
std::string mon_data_key = mon_prefix + ".DATA"; logger_map[mon_key].logger.removeAllAppenders();
logger_map.erase(mon_key);
if (logger_map.count(mon_com_key)) {
logger_map[mon_com_key].logger.removeAllAppenders();
logger_map.erase(mon_com_key);
} }
if (logger_map.count(mon_data_key)) {
logger_map[mon_data_key].logger.removeAllAppenders();
logger_map.erase(mon_data_key);
}
} }
} }

View File

@@ -174,7 +174,6 @@ void SendWebAPI_Nacos_Ptr(const string strUrl, const char* code, char** ptr)
strcpy(*ptr, resPost0.c_str()); strcpy(*ptr, resPost0.c_str());
} }
else { else {
printf("Memory allocation failed!\n"); printf("Memory allocation failed!\n");
} }
} }

View File

@@ -40,7 +40,7 @@ void get_object_to_file();
void get_object_to_file_new(char* File_Name, char* savepath); void get_object_to_file_new(char* File_Name, char* savepath);
void delete_object(); void delete_object();
void delete_object_new(char* File_Name); void delete_object_new(char* File_Name);
#if 0
void TestOSS() void TestOSS()
{ {
apr_file_t *output = NULL; apr_file_t *output = NULL;
@@ -136,7 +136,7 @@ void DelOSS(char* File_Name)
return; return;
} }
#endif
void coutTest() void coutTest()
{ {
std:: cout << "OSS_ENDPOINT:" << OSS_ENDPOINT << std::endl; std:: cout << "OSS_ENDPOINT:" << OSS_ENDPOINT << std::endl;

View File

@@ -25,6 +25,18 @@
#include "../json/cjson.h" #include "../json/cjson.h"
#include "../log4cplus/log4.h"//lnk添加log4 #include "../log4cplus/log4.h"//lnk添加log4
///////////////////////////////////////////////////////////////////////lnk20260305数据追踪相关
#include <QHash>
#include <QMutex>
#include <QMutexLocker>
#include <QMapIterator>
#include <QStringList>
// ★MOD: 全局追踪表mp_id -> remaining times
static QMutex g_trace_mutex;
static QHash<QString, int> g_trace_map;
///////////////////////////////////////////////////lnk2024-10-21//////////////////////////////////////////////////////// ///////////////////////////////////////////////////lnk2024-10-21////////////////////////////////////////////////////////
extern void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr); extern void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr);
extern std::string WEB_INTEGRITY; extern std::string WEB_INTEGRITY;
@@ -33,6 +45,9 @@ extern std::string WEB_EVENT;
extern std::string WEB_FILEDOWNLOAD; extern std::string WEB_FILEDOWNLOAD;
extern std::string G_CONNECT_TOPIC; extern std::string G_CONNECT_TOPIC;
//lnk20250115添加台账锁
extern pthread_mutex_t mtx;
bool DEBUGOPEN = 0; bool DEBUGOPEN = 0;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -57,6 +72,9 @@ public:
QString type; //参数等级type类型0-DataType 1-监测点 2-剔除标记 3-发生时刻,毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件 QString type; //参数等级type类型0-DataType 1-监测点 2-剔除标记 3-发生时刻,毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
QString triggerFlag; //告警SOE事件触发指标名称 QString triggerFlag; //告警SOE事件触发指标名称
int nIndex; //数据在每条线路LineInfo值数组中的位置 int nIndex; //数据在每条线路LineInfo值数组中的位置
QString desc; //soe事件描述
QString DO; //数据对象名 QString DO; //数据对象名
QString DA; //数据属性名 QString DA; //数据属性名
QString strFullName; //数据对象名 $ 数据属性名 QString strFullName; //数据对象名 $ 数据属性名
@@ -145,7 +163,8 @@ public:
QString WavePhasicA; QString WavePhasicA;
QString WavePhasicB; QString WavePhasicB;
QString WavePhasicC; QString WavePhasicC;
QString UnitOfTimeUnit; //暂态事件持续事件单位0 - 毫秒 1 - 秒 QString TypeOfData; //闪变和统计是否合并 0-分开 1-合并
QString UnitOfTimeUnit; //暂态事件持续事件单位0 - 毫秒 1 - 秒 lnk20260127
QString ValueOfTimeUnit; //上送值的时间UTC-UTC时间 beijing-北京时间 QString ValueOfTimeUnit; //上送值的时间UTC-UTC时间 beijing-北京时间
QString WaveTimeFlag; //录波文件的时间UTC-UTC时间 beijing-北京时间 QString WaveTimeFlag; //录波文件的时间UTC-UTC时间 beijing-北京时间
QString IEDname; //例PQMonitor QString IEDname; //例PQMonitor
@@ -223,7 +242,106 @@ extern int isdelta_flag;//lnk2024-8-16 角型接线标志
void connectlog_pgsql(char* id,char* datetime,int status); void connectlog_pgsql(char* id,char* datetime,int status);
///////////////////////////////////////////////lnk20241021替换web接口////////////////////////////////// ///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////lnk20260305数据追踪
static QString escape_json_string(const QString& s)
{
QString out = s;
out.replace("\\", "\\\\");
out.replace("\"", "\\\"");
out.replace("\r", "\\r");
out.replace("\n", "\\n");
out.replace("\t", "\\t");
return out;
}
// 打开追踪:次数 times比如 5
void process_trace_command(const std::string& id, int times)
{
if (times <= 0) return;
QString qid = QString::fromStdString(id).trimmed();
if (qid.isEmpty()) return;
QMutexLocker lk(&g_trace_mutex);
g_trace_map[qid] = times; // 重新打开就覆盖/重置次数
}
// 查询是否要追踪
static bool trace_is_enabled(const QString& mp_id)
{
QMutexLocker lk(&g_trace_mutex);
auto it = g_trace_map.constFind(mp_id);
return (it != g_trace_map.constEnd() && it.value() > 0);
}
// 命中一次并扣减;扣到 0 自动删
static void trace_hit_and_decrement(const QString& mp_id)
{
QMutexLocker lk(&g_trace_mutex);
auto it = g_trace_map.find(mp_id);
if (it == g_trace_map.end()) return;
int left = it.value();
left -= 1;
if (left <= 0) g_trace_map.erase(it);
else it.value() = left;
}
//追踪61850原始数据
static QString build_mms_multiline_text(const json_block_data* data)
{
QStringList lines;
QMapIterator<QString, double> it(data->mms_str_map);
while (it.hasNext()) {
it.next();
lines << QString("%1 = %2").arg(it.key()).arg(it.value(), 0, 'g', 15);
}
return lines.join("\n");
}
static QString build_trace_json(const json_block_data* data)
{
if (!data) return "{}";
QString mms_text = build_mms_multiline_text(data);
QString json;
json += "{";
json += QString("\"mp_id\":\"%1\",").arg(escape_json_string(data->mp_id));
json += QString("\"func_type\":%1,").arg(data->func_type);
json += QString("\"data_time\":%1,").arg(QString::number((qlonglong)data->time));
json += QString("\"voltage_level\":\"%1\",").arg(QString::number(data->voltage_level, 'f', 6));
json += QString("\"dev_type\":\"%1\",").arg(escape_json_string(data->dev_type));
json += QString("\"mms_text\":\"%1\"").arg(escape_json_string(mms_text));
json += "}";
return json;
}
static void send_trace_if_needed(json_block_data* pdata)
{
const QString mp_id_q = pdata->mp_id;
if (trace_is_enabled(mp_id_q)) {
// 1) 组 json
QString jsonText = build_trace_json(pdata);
// 2) 组 KafkaData
Ckafka_data_t KafkaData;
KafkaData.monitor_id = pdata->monitorId;
KafkaData.mp_id = pdata->mp_id;
KafkaData.strTopic = "DATA_TRACE_TOPIC";
KafkaData.strText = jsonText;
kafka_data_list_mutex.lock();
kafka_data_list.append(KafkaData);
kafka_data_list_mutex.unlock();
// 3) 次数 -1
trace_hit_and_decrement(mp_id_q);
}
}
////////////////////////////////////////////////////////////////////////////////////////////lnk20250710添加频率值存储 ////////////////////////////////////////////////////////////////////////////////////////////lnk20250710添加频率值存储
struct mp_freq_save { struct mp_freq_save {
double G_FREQ; double G_FREQ;
@@ -244,6 +362,8 @@ bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg) {
return false; return false;
} }
memset(out_cfg, 0, sizeof(*out_cfg));
QString dev_type_q = QString::fromUtf8(dev_type); QString dev_type_q = QString::fromUtf8(dev_type);
QMap<QString, Xmldata*>::iterator it = xmlinfo_list.find(dev_type_q); QMap<QString, Xmldata*>::iterator it = xmlinfo_list.find(dev_type_q);
if (it == xmlinfo_list.end() || it.value() == nullptr) { if (it == xmlinfo_list.end() || it.value() == nullptr) {
@@ -259,6 +379,7 @@ bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg) {
strncpy(out_cfg->WavePhasicB, cfg.WavePhasicB.toUtf8().constData(), sizeof(out_cfg->WavePhasicB) - 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->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->UnitOfTimeUnit, cfg.UnitOfTimeUnit.toUtf8().constData(), sizeof(out_cfg->UnitOfTimeUnit) - 1);
strncpy(out_cfg->TypeOfData, cfg.TypeOfData.toUtf8().constData(), sizeof(out_cfg->TypeOfData) - 1); out_cfg->TypeOfData[sizeof(out_cfg->TypeOfData) - 1] = '\0';//lnk20260127
strncpy(out_cfg->ValueOfTimeUnit, cfg.ValueOfTimeUnit.toUtf8().constData(),sizeof(out_cfg->ValueOfTimeUnit) - 1); strncpy(out_cfg->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->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->IEDname, cfg.IEDname.toUtf8().constData(), sizeof(out_cfg->IEDname) - 1);
@@ -865,6 +986,7 @@ bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QSt
{ {
CEventData* ed = new CEventData(); //SOE事件类指针 CEventData* ed = new CEventData(); //SOE事件类指针
ed->triggerFlag = node.toElement().attribute("name"); //SOE名称 ed->triggerFlag = node.toElement().attribute("name"); //SOE名称
ed->desc = node.toElement().attribute("desc"); //SOE描述
ed->DO = node.toElement().attribute("DO"); //数据对象名 ed->DO = node.toElement().attribute("DO"); //数据对象名
ed->DA = node.toElement().attribute("DA"); //数据属性名 ed->DA = node.toElement().attribute("DA"); //数据属性名
ed->type = node.toElement().attribute("type"); //参数等级type类型0-DataType 1-监测点 2-剔除标记 3-发生时刻,毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件 ed->type = node.toElement().attribute("type"); //参数等级type类型0-DataType 1-监测点 2-剔除标记 3-发生时刻,毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
@@ -898,6 +1020,11 @@ bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QSt
{ {
cfg->UnitOfTimeUnit.append(e.attribute("Unit")); cfg->UnitOfTimeUnit.append(e.attribute("Unit"));
} }
//lnk 20260127
if ("TypeOfData" == strTag)
{
cfg->TypeOfData.append(e.attribute("Unit"));
}
if ("ValueOfTime" == strTag) if ("ValueOfTime" == strTag)
{ {
cfg->ValueOfTimeUnit.append(e.attribute("Unit")); cfg->ValueOfTimeUnit.append(e.attribute("Unit"));
@@ -1029,9 +1156,46 @@ void printCTopicList(const std::list<CTopic*>& ctopic_list) {
} }
} }
// ===== DEBUG 打印: mms_str_map (属性名 -> 值) =====
static void print_mms_str_map(const json_block_data* data)
{
if (!data) {
std::cout << "[DBG] json_block_data is NULL\n";
return;
}
std::cout << "\n========== [DBG] json_block_data.mms_str_map ==========\n";
std::cout << "[DBG] monitorId=" << data->monitorId
<< " func_type=" << data->func_type
<< " flag=" << data->flag
<< " time(ms)=" << data->time
<< " voltage_level=" << data->voltage_level
<< "\n";
std::cout << "[DBG] mp_id=" << data->mp_id.toStdString()
<< " dev_type=" << data->dev_type.toStdString()
<< "\n";
std::cout << "[DBG] mms_str_map size=" << data->mms_str_map.size() << "\n";
// Qt4/Qt5 都稳QMapIterator
QMapIterator<QString, double> it(data->mms_str_map);
while (it.hasNext()) {
it.next();
std::cout << " " << it.key().toStdString() << " = " << it.value() << "\n";
}
std::cout << "======================================================\n\n";
}
//20250214添加角型接线处理 //20250214添加角型接线处理
int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json生成函数 zw修改 2023-8-11 调整传送json结构 目前仅限历史稳态数据 int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json生成函数 zw修改 2023-8-11 调整传送json结构 目前仅限历史稳态数据
{ {
// 刚进函数就打印 mms_str_map
if (DEBUGOPEN) {
print_mms_str_map(data);
}
list<CTopic*> ctopic_list; list<CTopic*> ctopic_list;
////lnk2024-8-15 区分星型,角型接线 ////lnk2024-8-15 区分星型,角型接线
@@ -1054,7 +1218,7 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
cout << "transfer_json_block_data contain data->dev_type" << endl; cout << "transfer_json_block_data contain data->dev_type" << endl;
ctopic_list = xmlinfo_list2[data->dev_type]->topicList; ctopic_list = xmlinfo_list2[data->dev_type]->topicList;
if(DEBUGOPEN)printCTopicList(ctopic_list);
} }
else { else {
cout << "transfer_json_block_data not contain data->dev_type:" << data->dev_type.toStdString() << " !!!!"<< endl; cout << "transfer_json_block_data not contain data->dev_type:" << data->dev_type.toStdString() << " !!!!"<< endl;
@@ -1063,6 +1227,43 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
} }
} }
if(DEBUGOPEN)printCTopicList(ctopic_list);
//lnk20260127 添加数据类型区分
bool typeofdata = false;
bool data_have_static = data->data_have_statistic;
QString devType = data->dev_type;
QByteArray devTypeBytes = devType.toUtf8();
const char* dev_type_cstr = devTypeBytes.constData();
qDebug() << "[DBG] devType (QString) =" << devType;
qDebug() << "[DBG] devType length =" << devType.length();
qDebug() << "[DBG] devTypeBytes =" << devTypeBytes;
qDebug() << "[DBG] devTypeBytes size =" << devTypeBytes.size();
printf("[DBG] dev_type_cstr = '%s'\n", dev_type_cstr);
XmlConfigC cfg1;
if (get_xml_config_by_dev_type(dev_type_cstr, &cfg1)) {
printf("========== XmlConfigC dump ==========\n");
printf("WavePhasicFlag = '%s'\n", cfg1.WavePhasicFlag);
printf("WavePhasicA = '%s'\n", cfg1.WavePhasicA);
printf("WavePhasicB = '%s'\n", cfg1.WavePhasicB);
printf("WavePhasicC = '%s'\n", cfg1.WavePhasicC);
printf("UnitOfTimeUnit = '%s'\n", cfg1.UnitOfTimeUnit);
printf("TypeOfData = '%s'\n", cfg1.TypeOfData);
printf("ValueOfTimeUnit = '%s'\n", cfg1.ValueOfTimeUnit);
printf("WaveTimeFlag = '%s'\n", cfg1.WaveTimeFlag);
printf("IEDname = '%s'\n", cfg1.IEDname);
printf("LDevicePrefix = '%s'\n", cfg1.LDevicePrefix);
printf("=====================================\n");
// 如果 TypeOfData == "1",则置 true
if (strcmp(cfg1.TypeOfData, "1") == 0) {
typeofdata = true;
}
} else {
printf("not find this dev_type\n");
}
bool shortjumpflag = false; bool shortjumpflag = false;
bool longjumpflag = false; bool longjumpflag = false;
@@ -1336,11 +1537,16 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
kafka_data_list_mutex.unlock(); //解锁 kafka_data_list_mutex.unlock(); //解锁
longjumpflag = true; longjumpflag = true;
} }
//lnk20260127
if (typeofdata == false || data_have_static == false) {//不合并则处理完闪变就不处理其他数据,如果有统计数据或者数据类型区分了就继续处理其他数据
if (longjumpflag == true || shortjumpflag == true) { if (longjumpflag == true || shortjumpflag == true) {
return 1; return 1;
} }
}
} //②-②历史闪变数据解析结束!-------------------------------- } //②-②历史闪变数据解析结束!--------------------------------
//合并则继续处理其他数据
if (1 == pDataType->iDataType) //②-①历史稳态数据----------------------------------------------------------- if (1 == pDataType->iDataType) //②-①历史稳态数据-----------------------------------------------------------
{ {
Ckafka_data_t KafkaData; //kafka发送数据结构类对象 Ckafka_data_t KafkaData; //kafka发送数据结构类对象
@@ -2240,9 +2446,11 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
kafka_data_list_mutex.unlock(); //解锁 kafka_data_list_mutex.unlock(); //解锁
longjumpflag = true; longjumpflag = true;
} }
if (typeofdata == false || data_have_static == false) {//不合并则处理完闪变就不处理其他数据
if (longjumpflag == true || shortjumpflag == true) { if (longjumpflag == true || shortjumpflag == true) {
return 1; return 1;
} }
}
//return 1; //结束该函数,停止后续代码执行 //return 1; //结束该函数,停止后续代码执行
} //②-②历史闪变数据解析结束!-------------------------------- } //②-②历史闪变数据解析结束!--------------------------------
@@ -2561,8 +2769,35 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
return 1; return 1;
} }
static void format_time_ms(long long ms, char* buf, size_t buf_len)
{
time_t sec = ms / 1000;
int milli = ms % 1000;
struct tm tm_time;
localtime_r(&sec, &tm_time); // 线程安全
snprintf(buf, buf_len,
"%04d-%02d-%02d %02d:%02d:%02d.%03d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
milli);
}
void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long time,char* devtype,int monitor_id) void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long time,char* devtype,int monitor_id)
{ {
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", mp_id);
//监测点日志的key,lnk20250526
XmlConfig c_xmlcfg; XmlConfig c_xmlcfg;
if (xmlinfo_list.contains(devtype)) { if (xmlinfo_list.contains(devtype)) {
c_xmlcfg = xmlinfo_list[devtype]->xmlcfg; c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;
@@ -2594,6 +2829,28 @@ void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long ti
if (pEventData->strFullName.indexOf(Full_name) != -1) if (pEventData->strFullName.indexOf(Full_name) != -1)
{ {
KafkaData.strText.append(QString("\"%1\"").arg(pEventData->triggerFlag)); KafkaData.strText.append(QString("\"%1\"").arg(pEventData->triggerFlag));
//使用日志接口记录日志
char time_str[64];
format_time_ms(time, time_str, sizeof(time_str));
QByteArray descBa = pEventData->desc.toLocal8Bit();
pthread_mutex_lock(&mtx); std::cout << "ggio hold lock !!!!!!!!!!!" << std::endl;
const char* mp_name_raw = find_mp_name_from_mp_id(mp_id);
pthread_mutex_unlock(&mtx); std::cout << "ggio unlock lock !!!!!!!!!!!" << std::endl;
char mp_name[128];
if (mp_name_raw && mp_name_raw[0] != '\0') {
snprintf(mp_name, sizeof(mp_name), "%s", mp_name_raw);
} else {
snprintf(mp_name, sizeof(mp_name), "unknown");
}
DIY_WARNLOG_CODE(full_key_m_d, LOG_CODE_REPORT,
"监测点:%s(%s),在%s发生事件:%s,事件值:%.2f",
mp_name, mp_id, time_str, descBa.constData(), v);
break; break;
} }
} }
@@ -2606,6 +2863,7 @@ void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long ti
kafka_data_list_mutex.lock(); //加锁 kafka_data_list_mutex.lock(); //加锁
kafka_data_list.append(KafkaData); //添加 kafka发送链表 kafka_data_list.append(KafkaData); //添加 kafka发送链表
kafka_data_list_mutex.unlock(); //解锁 kafka_data_list_mutex.unlock(); //解锁
} }
//zw修改 2023-8-31 新增或更新list队列 写入xml数据库信息 模型编码 终端型号 终端厂家 oss存储路径 时间 //zw修改 2023-8-31 新增或更新list队列 写入xml数据库信息 模型编码 终端型号 终端厂家 oss存储路径 时间
@@ -2673,6 +2931,7 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
{ {
Xmldata* config2 = new Xmldata(); Xmldata* config2 = new Xmldata();
xmlinfo_list2.insert(type, config2); xmlinfo_list2.insert(type, config2);
xmlinfo_list2[type]->updataflag = true;
} }
else else
{ {
@@ -2694,35 +2953,30 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
char file_name[256]; char file_name[256];
memset(file_name, 0, 256); memset(file_name, 0, 256);
sprintf(file_name, "%s", FILE_NAME); snprintf(file_name, sizeof(file_name), "%s", FILE_NAME);
file_name[sizeof(file_name) - 1] = '\0';
QString Qsavename; QString Qsavename;
Qsavename.append("/FeProject/dat/").append(id).append(".xml"); //本地保存路径 Qsavename.append("/FeProject/dat/").append(id).append(".xml"); //本地保存路径
char save_name[256]; char save_name[256];
memset(save_name, 0, 256); memset(save_name, 0, 256);
sprintf(save_name, "%s", Qsavename.toAscii().data()); snprintf(save_name, sizeof(save_name), "%s", Qsavename.toAscii().data());
save_name[sizeof(save_name) - 1] = '\0';
cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl; cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;
//mq日志 //mq日志
DIY_WARNLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"前置获取到终端类型%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接口
//构造文件下载接口参数
//接口示例http://192.168.1.125:10215/file/download?filePath=/path/xxx.txt
// 调用web获取文件内容 // 调用web获取文件内容
char* fileContent = NULL; char* fileContent = NULL;
//测试下载
//char downpath[128] = {"/home/pq/FeProject/src/pt61850netd_pqfe_lnk/download/123.txt"};
//char download[128] = {"{\"filename\":\"file_test.txt\"}"};
//SendJsonAPI_web("http://192.168.1.149:8091/file/download", "", download, &fileContent);
std::string fullPath = std::string("filePath=") + std::string(FILE_PATH); std::string fullPath = std::string("filePath=") + std::string(FILE_PATH);
//调试用 //调试用
std::cout << "fullpath" << fullPath << std::endl; std::cout << "fullpath" << fullPath << std::endl;
SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", &fileContent); SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", &fileContent);
if (fileContent != NULL) { if (fileContent != NULL && fileContent[0] != '\0') {
// 创建并打开文件 // 创建并打开文件
//判断返回的是不是错误json响应 //判断返回的是不是错误json响应
@@ -2737,7 +2991,7 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
isErrorJson = true; isErrorJson = true;
std::cerr << "Error: Server returned empty file stream, code=A00555." << std::endl; std::cerr << "Error: Server returned empty file stream, code=A00555." << std::endl;
DIY_ERRORLOG_CODE("process", LOG_CODE_ICD_AND_DOWNLOAD, DIY_ERRORLOG_CODE("process", LOG_CODE_ICD_AND_DOWNLOAD,
"前置下载文件失败服务端返回A00555(文件流为空),文件=%s", "【ERROR】前置下载文件失败服务端返回A00555(文件流为空),文件=%s",
save_name); save_name);
} }
cJSON_Delete(root); cJSON_Delete(root);
@@ -2753,17 +3007,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_INFOLOG("process","前置下载映射文件%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_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"前置写入本地映射文件%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_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH); DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH);
} }
} }
@@ -3094,7 +3348,7 @@ 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_CODE("process",LOG_CODE_TRANSIENT_COMM,"无法将暂态事件写入本地缓存"); //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 false; return false;
} }
@@ -3181,7 +3435,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_CODE("process",LOG_CODE_TRANSIENT_COMM,"无法打开本地缓存的暂态事件"); 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;
} }
@@ -3201,26 +3455,27 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
// 尝试发送 // 尝试发送
char* ptr = NULL; // 接收返回 char* ptr = NULL; // 接收返回
SendJsonAPI_web(WEB_EVENT, "", jsonContent.c_str(), &ptr); SendJsonAPI_web(WEB_EVENT, "", jsonContent.c_str(), &ptr);
if (ptr != NULL) { if (ptr != NULL && ptr[0] != '\0') {
cJSON* j_r = cJSON_Parse(ptr); cJSON* j_r = cJSON_Parse(ptr);
if (j_r == NULL) { if (j_r == NULL) {
std::cout << "old file send fail" << std::endl; std::cout << "old file send fail" << std::endl;
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
handleCommentResponse(std::string(ptr));
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"前置重发暂态事件失败");
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件失败");
} }
else{ else{
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
handleCommentResponse(std::string(ptr));
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"前置重发暂态事件成功"); 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;
// 删除文件 // 删除文件
remove(fileList[i].fileName.c_str()); remove(fileList[i].fileName.c_str());
free(j_r); cJSON_Delete(j_r);
} }
} }
@@ -3266,7 +3521,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
c_xmlcfg = xmlcfg; c_xmlcfg = xmlcfg;
} }
if (strlen(mp_id) == 0) { if (NULL == mp_id || strlen(mp_id) == 0 ) {
std::cout << "mp_id is null" << std::endl; std::cout << "mp_id is null" << std::endl;
return 0; return 0;
} }
@@ -3309,6 +3564,12 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
} }
char* json_string = cJSON_Print(root); char* json_string = cJSON_Print(root);
if (json_string == NULL) {
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s暂态事件生成JSON字符串失败",mp_id);
std::cerr << "Failed to print JSON object." << std::endl;
cJSON_Delete(root);
return 0;
}
printf("%s\n", json_string); // 输出 JSON 字符串 printf("%s\n", json_string); // 输出 JSON 字符串
// 发送到暂态接口 // 发送到暂态接口
@@ -3317,14 +3578,14 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
// ================ 插入新功能 ========================= // ================ 插入新功能 =========================
// ********** 新增功能开始 ********** // ********** 新增功能开始 **********
if(ptr != NULL) if(ptr != NULL && ptr[0] != '\0')
{ {
cJSON* j_r = cJSON_Parse(ptr); cJSON* j_r = cJSON_Parse(ptr);
// 如果发送失败(j_r == NULL),则把当前 json 存入指定目录(/FeProject/dat/qvvr/) // 如果发送失败(j_r == NULL),则把当前 json 存入指定目录(/FeProject/dat/qvvr/)
if (j_r == NULL) { if (j_r == NULL) {
//mq日志 //mq日志
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"暂态接口响应异常,无法上送监测点%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若超过则删除最老的一个文件
@@ -3346,13 +3607,13 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
// 把 json_string 写入文件 // 把 json_string 写入文件
if(!writeJsonToFile(fileName.c_str(), json_string)){ if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id); DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
} }
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024); checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
} }
else{ else{
free(j_r); cJSON_Delete(j_r);
//后续处理 //后续处理
} }
} }
@@ -3365,16 +3626,17 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
// ********** 新增功能结束 ********** // ********** 新增功能结束 **********
// 下面继续原逻辑,不动,处理本次发送 // 下面继续原逻辑,不动,处理本次发送
if (ptr != NULL) { if (ptr != NULL && ptr[0] != '\0') {
std::cout << "current qvvr handle response" << std::endl; std::cout << "current qvvr handle response" << std::endl;
handleCommentResponse(std::string(ptr)); handleCommentResponse(std::string(ptr));
free(ptr); free(ptr);
ptr = NULL;
} else { } else {
// 处理 ptr 为 NULL 的情况,例如日志记录或错误处理 // 处理 ptr 为 NULL 的情况,例如日志记录或错误处理
std::cout << "Error: Received NULL response" << std::endl; std::cout << "Error: Received NULL response" << std::endl;
//mq日志 //mq日志
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"暂态接口无响应,无法上送监测点%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若超过则删除最老的一个文件
@@ -3394,7 +3656,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
fileName += ".txt"; fileName += ".txt";
// 把 json_string 写入文件 // 把 json_string 写入文件
if(!writeJsonToFile(fileName.c_str(), json_string)){ if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id); DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
} }
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024); checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);

View File

@@ -38,7 +38,11 @@ public:
QString mp_id; //char型监测点 QString mp_id; //char型监测点
QString dev_type;//设备类型 QString dev_type;//设备类型
bool data_have_statistic;//是否有统计数据0没有1有
QMap<QString, double> mms_str_map; //数据值(61850数据属性名, 数据值) QMap<QString, double> mms_str_map; //数据值(61850数据属性名, 数据值)
bool data_trace_flag; //数据追踪标记0不追踪1追踪
}; };
class Ckafka_data_t //kafka发送数据结构类 class Ckafka_data_t //kafka发送数据结构类

File diff suppressed because it is too large Load Diff

View File

@@ -670,6 +670,8 @@ struct monitor // 监测点台账
char timestamp[64]; char timestamp[64];
char status[255]; char status[255];
int log_level;//日志级别0ERROR1WARN2NORMAL3DEBUG
}; };
struct terminal // 终端台账 struct terminal // 终端台账
{ {
@@ -692,6 +694,7 @@ struct terminal // 终端台账
char timestamp[64]; char timestamp[64];
monitor line[10]; // 最多 10 个监测点 monitor line[10]; // 最多 10 个监测点
int log_level;//日志级别0ERROR1WARN2NORMAL3DEBUG
}; };
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -24,12 +24,9 @@
#include "appender.h" #include "appender.h"
#define LOGTYPE_COM 1
#define LOGTYPE_DATA 2
struct TypedLogger { struct TypedLogger {
log4cplus::Logger logger; log4cplus::Logger logger;
int logtype; int code;
TypedLogger(); TypedLogger();
TypedLogger(const log4cplus::Logger& l, int t); TypedLogger(const log4cplus::Logger& l, int t);
}; };
@@ -47,7 +44,7 @@ struct DebugSwitch {
void set_level(int level); void set_level(int level);
void enable_type(int type); void enable_type(int type);
void disable_type(int type); void disable_type(int type);
bool match(const std::string& logger_name, int level, int logtype); bool match(const std::string& logger_name, int level, int code);
}; };
extern std::map<std::string, TypedLogger> logger_map; extern std::map<std::string, TypedLogger> logger_map;
@@ -71,11 +68,14 @@ log4cplus::Logger init_logger(const std::string& full_name,
const std::string& base_file, const std::string& base_file,
log4cplus::SharedAppenderPtr fileAppender); log4cplus::SharedAppenderPtr fileAppender);
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str); void process_log_command(const std::string& id, const std::string& level, const std::string& grade, int code);
void update_log_entries_countdown(); void update_log_entries_countdown();
/////////////////////////////////////////////////////////////////////lnk20260306数据追踪
void process_trace_command(const std::string& id, int times);
extern "C" { extern "C" {
#endif #endif
void remove_loggers_by_terminal_id(const char* terminal_id_cstr); void remove_loggers_by_terminal_id(const char* terminal_id_cstr);
@@ -89,7 +89,7 @@ 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 send_reply_to_kafka_recall_c(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 ====================== // ====================== ★新增:线程局部变量透传 code ======================
@@ -133,7 +133,7 @@ extern LOG_TLS int g_log_code_tls; // 声明为 TLS 变量,定义见 log4.cpp
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0 #define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏 // ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "监测点:%s ...", ...); // 用法示例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_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_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_INFOLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, CODE_INT, __VA_ARGS__) // ★新增
@@ -159,7 +159,8 @@ typedef enum LogCode {
LOG_CODE_LOG_REQUEST = 405, /* 日志请求 */ LOG_CODE_LOG_REQUEST = 405, /* 日志请求 */
LOG_CODE_REPORT = 500, /* 报告处理 */ LOG_CODE_REPORT = 500, /* 报告处理 */
LOG_CODE_COMM = 600, /* 通讯状态 */ LOG_CODE_COMM = 600, /* 通讯状态 */
LOG_CODE_SPACE_ALARM = 700 /* 空间告警 */ LOG_CODE_SPACE_ALARM = 700, /* 空间告警 */
LOG_CODE_DEVICE = 800 /* 设备告警 */
} LogCode; } LogCode;
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -45,10 +45,10 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
extern char* OSS_ENDPOINT; //extern char* OSS_ENDPOINT;
extern char* ACCESS_KEY_ID; //extern char* ACCESS_KEY_ID;
extern char* ACCESS_KEY_SECRET; //extern char* ACCESS_KEY_SECRET;
extern char* BUCKET_NAME; //extern char* BUCKET_NAME;
extern char* POSTGRES_SCHEMA; extern char* POSTGRES_SCHEMA;
extern char* POSTGRES_TABLEPREFIX; extern char* POSTGRES_TABLEPREFIX;
@@ -105,16 +105,16 @@ void TestToken();
void TestBodyPost();//WW 测试qt post void TestBodyPost();//WW 测试qt post
void TestSMSPost();//WW 测试qt post void TestSMSPost();//WW 测试qt post
void TestJson(char* szJson); void TestJson(char* szJson);
void TestOSS();//WW 测试 //void TestOSS();//WW 测试
void PutOSS(char* File_Name, char* data); //zw修改 2023-9-7 上送oss文件 //void PutOSS(char* File_Name, char* data); //zw修改 2023-9-7 上送oss文件
void GetOSS(char* File_Name, char* savepath); //zw修改 2023-9-7 获取oss文件 //void GetOSS(char* File_Name, char* savepath); //zw修改 2023-9-7 获取oss文件
void DelOSS(char* File_Name); //void DelOSS(char* File_Name);
void delete_object_new(char* File_Name); void delete_object_new(char* File_Name);
void coutTest();//CZY 2023-09-11 test void coutTest();//CZY 2023-09-11 test
void TestOBS();//WW 20230921 测试华为云服务器 //void TestOBS();//WW 20230921 测试华为云服务器
void OBSFile(char* localpath, char* cloudpath,const char* code); //void OBSFile(char* localpath, char* cloudpath,const char* code);
void OBSFile_del(char* cloudpath, const char* code); //void OBSFile_del(char* cloudpath, const char* code);
void DataHub_Send_Datahub(char* topic, char* data);//datahub通讯 //void DataHub_Send_Datahub(char* topic, char* data);//datahub通讯
void Nacos_GetParam(char* postgres_uid, char* postgres_pwd, char* web_clientid, char* web_clientsecret);//nacos void Nacos_GetParam(char* postgres_uid, char* postgres_pwd, char* web_clientid, char* web_clientsecret);//nacos
void Nacos_GetParam_Ptr(const char* code, char** ptr); void Nacos_GetParam_Ptr(const char* code, char** ptr);
void Read_Nacos_Param_Postgres(char** database_ip, char** database_port, char** postgres_database, char** postgres_username, char** postgres_password, char** postgres_schema, char** postgres_dnsname, char** postgres_tableprefix); void Read_Nacos_Param_Postgres(char** database_ip, char** database_port, char** postgres_database, char** postgres_username, char** postgres_password, char** postgres_schema, char** postgres_dnsname, char** postgres_tableprefix);
@@ -152,6 +152,8 @@ int parse_model_cfg_web();
void SOEFileWeb(char* localpath,char* cloudpath,char* wavepath); void SOEFileWeb(char* localpath,char* cloudpath,char* wavepath);
const char* get_front_msg_from_subdir(); const char* get_front_msg_from_subdir();
char* find_mp_name_from_mp_id(const char* mp_id);
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
typedef struct { typedef struct {
@@ -160,6 +162,7 @@ typedef struct {
char WavePhasicB[64]; char WavePhasicB[64];
char WavePhasicC[64]; char WavePhasicC[64];
char UnitOfTimeUnit[64]; char UnitOfTimeUnit[64];
char TypeOfData[64];
char ValueOfTimeUnit[64]; char ValueOfTimeUnit[64];
char WaveTimeFlag[64]; char WaveTimeFlag[64];
char IEDname[64]; char IEDname[64];
@@ -168,6 +171,21 @@ typedef struct {
bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg); bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg);
//////////////////////////////////////////////////////////////////////////////////////文件控制请求参数
typedef struct file_dir_req_t
{
struct file_dir_req_t *next;
struct file_dir_req_t *prev;
char guid[128];
char frontid[128];
int processNo;
char devid[128];
int type;
char path[256];
time_t create_time;
} file_dir_req_t;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

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_INFOLOG("process","前置的%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_CODE("process",LOG_CODE_LEDGER,"前置的%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_CODE("process",LOG_CODE_OTHER,"前置的%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_CODE("process",LOG_CODE_OTHER,"前置的%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

@@ -34,6 +34,7 @@ extern apr_pool_t* g_init_pool;
extern int g_DevFlag; //日志配置中读取的参数暂无特定使用lnk20250121 extern int g_DevFlag; //日志配置中读取的参数暂无特定使用lnk20250121
extern int IED_COUNT; extern int IED_COUNT;
extern int RECALL_ONLY_FLAG; //lnk20260309添加一个全局变量标志是否只运行补招程序
//lnk20250115end //lnk20250115end
@@ -184,7 +185,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_CODE(full_key_t_c,LOG_CODE_COMM,"前置与终端%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");
@@ -321,13 +322,13 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
LD_info->registcount++; LD_info->registcount++;
if (LD_info->registcount <= 5) { if (LD_info->registcount <= 5) {
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"监测点:%s - id:%s报告触发失败,监测点逻辑标识号为0,请检查装置对应的台账信息是否正确", LD_info->name,LD_info->mp_id); DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【ERROR】监测点:%s - id:%s报告触发失败,监测点逻辑标识号为0,请检查装置对应的台账信息是否正确", LD_info->name,LD_info->mp_id);
} }
// 到5次就不再打印并标记 // 到5次就不再打印并标记
if (LD_info->registcount > 5) { if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true; LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"监测点:%s - id:%s监测点逻辑标识号错误日志已达本次记录上限不再输出请检查装置对应的台账信息是否正确", DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s监测点逻辑标识号错误日志已达本次记录上限不再输出请检查装置对应的台账信息是否正确",
LD_info->name, LD_info->mp_id); LD_info->name, LD_info->mp_id);
} }
} }
@@ -341,7 +342,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
if (judge_rpt_next_should_do(rptinfo)==SHOULD_DO_NOTHING)//检查是否触发 if (judge_rpt_next_should_do(rptinfo)==SHOULD_DO_NOTHING)//检查是否触发
{ {
//DIY_DEBUGLOG(full_key_m_c,"监测点:%s - id:%s不注册报告", LD_info->name,LD_info->mp_id); //DIY_DEBUGLOG(full_key_m_c,"【DEBUG】监测点:%s - id:%s不注册报告", LD_info->name,LD_info->mp_id);
continue; continue;
} }
@@ -357,7 +358,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
printf("start mms_register_iec_rpt................................\n"); printf("start mms_register_iec_rpt................................\n");
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s开始注册报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s开始注册报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
if ( strstr(rptinfo->rptID,"LLN0$BR$brcbFlickerData") ) if ( strstr(rptinfo->rptID,"LLN0$BR$brcbFlickerData") )
rptinfo->IntgPd = 600; //10分钟 rptinfo->IntgPd = 600; //10分钟
@@ -385,14 +386,14 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
LD_info->registcount++; LD_info->registcount++;
if (LD_info->registcount <= 5) { if (LD_info->registcount <= 5) {
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT, "监测点:%s - id:%s注册报告失败,报告名:%s", 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); LD_info->name, LD_info->mp_id, rpt_inst_name);
} }
// 到5次就不再打印并标记 // 到5次就不再打印并标记
if (LD_info->registcount > 5) { if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true; LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"监测点:%s - id:%s注册报告失败日志已达本次注册上限不再输出请检查装置icd和映射文件是否匹配或者装置存在过多连接", DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告失败日志已达本次注册上限不再输出请检查装置icd和映射文件是否匹配或者装置存在过多连接",
LD_info->name, LD_info->mp_id); LD_info->name, LD_info->mp_id);
} }
} }
@@ -415,7 +416,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
//mq日志 //mq日志
LD_info->has_logged_regist = FALSE; LD_info->has_logged_regist = FALSE;
LD_info->registcount = 0; LD_info->registcount = 0;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"监测点:%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);
// 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;
@@ -423,7 +424,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
} }
printf("end mms_register_iec_rpt................................\n"); printf("end mms_register_iec_rpt................................\n");
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s注册报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s注册报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
} }
} }
else { //rpt_registered ==TRUE else { //rpt_registered ==TRUE
@@ -432,7 +433,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
printf("start mms_unregister_iec_rpt................................\n"); printf("start mms_unregister_iec_rpt................................\n");
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s开始注销报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s开始注销报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
ret = mms_unregister_iec_rpt (chnl_usr->net_info, &g_rpt_typeids, ret = mms_unregister_iec_rpt (chnl_usr->net_info, &g_rpt_typeids,
LD_info->LD_name,rpt_inst_name,g_pt61850app->mmsOpTimeout); LD_info->LD_name,rpt_inst_name,g_pt61850app->mmsOpTimeout);
@@ -443,7 +444,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_CODE(full_key_m_c,LOG_CODE_REPORT,"监测点:%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 {
@@ -452,11 +453,11 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
LD_info->ied->id,LD_info->cpuno,LD_info->LD_name,rpt_inst_name,chnl_usr->ip_str,chnl_usr->chnl->port,chnl_usr->chnl_id ); LD_info->ied->id,LD_info->cpuno,LD_info->LD_name,rpt_inst_name,chnl_usr->ip_str,chnl_usr->chnl->port,chnl_usr->chnl_id );
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s注销报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s注销报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
} }
printf("end mms_unregister_iec_rpt................................\n"); printf("end mms_unregister_iec_rpt................................\n");
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s注销报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s注销报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
} }
} }
@@ -523,13 +524,13 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
LD_info->registcount++; LD_info->registcount++;
if (LD_info->registcount <= 5) { if (LD_info->registcount <= 5) {
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"监测点:%s - id:%s补招数据失败,监测点缺少日志控制块,请检查装置对应的装置类型是否有配对的icd模型", LD_info->name,LD_info->mp_id); DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败,监测点缺少日志控制块,请检查装置对应的装置类型是否有配对的icd模型", LD_info->name,LD_info->mp_id);
} }
// 到5次就不再打印并标记 // 到5次就不再打印并标记
if (LD_info->registcount > 5) { if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true; LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"监测点:%s - id:%s缺少日志控制块日志已达本次记录上限不再输出请检查装置对应的装置类型是否有配对的icd模型", DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s缺少日志控制块日志已达本次记录上限不再输出请检查装置对应的装置类型是否有配对的icd模型",
LD_info->name, LD_info->mp_id); LD_info->name, LD_info->mp_id);
} }
} }
@@ -560,11 +561,11 @@ 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_CODE(full_key_m_c,LOG_CODE_RECALL,"监测点:%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_CODE(full_key_m_c,LOG_CODE_RECALL,"监测点:%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);
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
@@ -608,7 +609,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_WARNLOG(full_key_m_c,"监测点:%s - id:%s开始补招数据", LD_info->name,LD_info->mp_id); //DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s开始补招数据", LD_info->name,LD_info->mp_id);
ret = mms_jread(loginfo, chnl_usr->net_info, loginfo->LD_info->LD_name, loginfo->logName, ret = mms_jread(loginfo, chnl_usr->net_info, loginfo->LD_info->LD_name, loginfo->logName,
loginfo->start_time, loginfo->end_time, g_pt61850app->mmsOpTimeout, chnl_usr->ip_str); loginfo->start_time, loginfo->end_time, g_pt61850app->mmsOpTimeout, chnl_usr->ip_str);
@@ -617,7 +618,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_CODE(full_key_m_c,LOG_CODE_RECALL,"监测点:%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++;
} }
@@ -670,7 +671,7 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
// ===== [新增结束] ===== // ===== [新增结束] =====
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"监测点:%s - id:%s结束补招数据", LD_info->name,LD_info->mp_id); DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s结束补招数据", LD_info->name,LD_info->mp_id);
//} //}
} }
@@ -1328,6 +1329,7 @@ void print_monitor(const monitor* mon) {
printf("Terminal Connect: %s\n", is_empty(mon->terminal_connect) ? "N/A" : mon->terminal_connect); printf("Terminal Connect: %s\n", is_empty(mon->terminal_connect) ? "N/A" : mon->terminal_connect);
printf("Timestamp: %s\n", is_empty(mon->timestamp) ? "N/A" : mon->timestamp); printf("Timestamp: %s\n", is_empty(mon->timestamp) ? "N/A" : mon->timestamp);
printf("Status: %s\n", is_empty(mon->status) ? "N/A" : mon->status); printf("Status: %s\n", is_empty(mon->status) ? "N/A" : mon->status);
printf("Log Level: %d\n", mon->log_level);
} }
// 打印 terminal 结构体信息 // 打印 terminal 结构体信息
@@ -1346,6 +1348,7 @@ void print_terminal(const terminal* tmnl) {
printf("Address: %s\n", is_empty(tmnl->addr_str) ? "N/A" : tmnl->addr_str); printf("Address: %s\n", is_empty(tmnl->addr_str) ? "N/A" : tmnl->addr_str);
printf("Port: %s\n", is_empty(tmnl->port) ? "N/A" : tmnl->port); printf("Port: %s\n", is_empty(tmnl->port) ? "N/A" : tmnl->port);
printf("Timestamp: %s\n", is_empty(tmnl->timestamp) ? "N/A" : tmnl->timestamp); printf("Timestamp: %s\n", is_empty(tmnl->timestamp) ? "N/A" : tmnl->timestamp);
printf("Log Level: %d\n", tmnl->log_level);
// 打印监测点信息,如果监测点字段为空,则打印 N/A // 打印监测点信息,如果监测点字段为空,则打印 N/A
int i; int i;
@@ -1416,11 +1419,14 @@ void check_ledger_update()//lnk20250113
//调试用 //调试用
print_trigger_update_xml(trigger_ledger_update_xml); print_trigger_update_xml(trigger_ledger_update_xml);
//处理台账更新加台账锁lnk20250114 //处理台账更新添加控制标志
//pthread_mutex_lock(&mtx); printf("ledgerupdate hold lock !!!!!!!!!!!"); if (RECALL_ONLY_FLAG != 1 || (g_node_id != STAT_DATA_BASE_NODE_ID)) {
process_ledger_update(trigger_ledger_update_xml); //台账更新 process_ledger_update(trigger_ledger_update_xml); //台账更新
//pthread_mutex_unlock(&mtx); printf("ledgerupdate free lock !!!!!!!!!!!"); }
else{
printf("only process recall config, skip ledger update\n");
DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】当前配置为仅日志模式,统计数据进程跳过台账更新");
}
} }
// 使用完后释放动态分配的内存 // 使用完后释放动态分配的内存
@@ -1475,13 +1481,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_CODE("process",LOG_CODE_SPACE_ALARM,"前置磁盘检测: 当前磁盘的可用空间为%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_CODE("process",LOG_CODE_SPACE_ALARM,"前置磁盘检测: 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘",freeSizeMB,totalSizeMB); DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测: 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘",freeSizeMB,totalSizeMB);
} }
} }
@@ -1545,6 +1551,9 @@ void CheckAllConnectedChannel()
if(chnl_usr->m_state == CHANNEL_CONNECTED) if(chnl_usr->m_state == CHANNEL_CONNECTED)
{ {
if(g_node_id == THREE_SECS_DATA_BASE_NODE_ID) {
HandleFileDirReqForChannel(chnl_usr);//文件目录请求
}
ChannelCheckIECReports(chnl_usr);//报告 ChannelCheckIECReports(chnl_usr);//报告
if ( (g_node_id == SOE_COMTRADE_BASE_NODE_ID) || (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 == SOE_COMTRADE_BASE_NODE_ID) || (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))
@@ -1632,7 +1641,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_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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;
@@ -1679,11 +1688,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_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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); 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_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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); 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);
@@ -1714,11 +1723,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_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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);
} }
@@ -1758,7 +1767,7 @@ void CheckNextNotConnectedChannel()
if (chnl_usr->chnl->ied->cpucount != NULL && chnl_usr->chnl->ied->cpucount > 0 && ied_usr->dev_flag == ENABLE) {//2023-09-26 czy 如果line count<0 不需要连接//lnk20250121如果终端无效则不连接 if (chnl_usr->chnl->ied->cpucount != NULL && chnl_usr->chnl->ied->cpucount > 0 && ied_usr->dev_flag == ENABLE) {//2023-09-26 czy 如果line count<0 不需要连接//lnk20250121如果终端无效则不连接
//mq日志 //mq日志
//DIY_WARNLOG(full_key_t_c,"重新连接终端%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(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);
ret = mms_connectToServer(ied_usr->dev_key, ied_usr->dev_series, serverARName, &(chnl_usr->net_info), &(chnl_usr->m_reqCtrl)); ret = mms_connectToServer(ied_usr->dev_key, ied_usr->dev_series, serverARName, &(chnl_usr->net_info), &(chnl_usr->m_reqCtrl));
@@ -1770,7 +1779,7 @@ void CheckNextNotConnectedChannel()
chnl_usr->m_StartConnectingTime = sGetMsTime(); chnl_usr->m_StartConnectingTime = sGetMsTime();
//mq日志 //mq日志
//DIY_WARNLOG(full_key_t_c,"正在重新连接终端%s - ip端口:%s:%d - 识别码/秘钥:%s/%s", ((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); //DIY_WARNLOG(full_key_t_c,"【WARN】正在重新连接终端%s - ip端口:%s:%d - 识别码/秘钥:%s/%s", ((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);
} }
@@ -1782,7 +1791,7 @@ void CheckNextNotConnectedChannel()
echo_warn3("FAILED: mms_connectToServer IP %s:%d ,NetInfo= %x \n", chnl_usr->ip_str, chnl_usr->chnl->port, chnl_usr->net_info); echo_warn3("FAILED: mms_connectToServer IP %s:%d ,NetInfo= %x \n", chnl_usr->ip_str, chnl_usr->chnl->port, chnl_usr->net_info);
//mq日志 //mq日志
//DIY_WARNLOG(full_key_t_c,"重新连接终端%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(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);
} }
} }
@@ -1813,7 +1822,7 @@ void CheckNextNotConnectedChannel()
chnl_usr->chnl->status = STATUS_BREAKOFF; chnl_usr->chnl->status = STATUS_BREAKOFF;
//mq日志 //mq日志
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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
@@ -1843,7 +1852,7 @@ void CheckNextNotConnectedChannel()
chnl_usr->chnl->status = STATUS_BREAKOFF; chnl_usr->chnl->status = STATUS_BREAKOFF;
//mq日志 //mq日志
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"终端%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);
} }
} }
@@ -2013,7 +2022,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
printf(">>>>>>>> IED [%d]: %s is calling cn wavefile, !!!!!!!! file_match_str=%s \n",ied->id,ied->name,file_match_str); printf(">>>>>>>> IED [%d]: %s is calling cn wavefile, !!!!!!!! file_match_str=%s \n",ied->id,ied->name,file_match_str);
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s开始召唤录波文件", LD_info->name,LD_info->mp_id); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s开始召唤录波文件", LD_info->name,LD_info->mp_id);
ret = SD_FAILURE; ret = SD_FAILURE;
filenum = 0; filenum = 0;
@@ -2035,14 +2044,14 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
int ret2,ret3; int ret2,ret3;
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s获取录波文件列表成功,开始匹配录波文件", LD_info->name,LD_info->mp_id); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s获取录波文件列表成功,开始匹配录波文件", LD_info->name,LD_info->mp_id);
//WW 2023-11-01将录波段号由字符串匹配修改为int的fltnum匹配 //WW 2023-11-01将录波段号由字符串匹配修改为int的fltnum匹配
ret2 = parse_file_names_by_fltnum(LD_info->FltNum[i], ldstr, filenames, filenum, &cfg_idx, &dat_idx, file_base_name, file_yyyymm); ret2 = parse_file_names_by_fltnum(LD_info->FltNum[i], ldstr, filenames, filenum, &cfg_idx, &dat_idx, file_base_name, file_yyyymm);
//WW 2023-11-01 end //WW 2023-11-01 end
if (ret2 !=APR_SUCCESS){ if (ret2 !=APR_SUCCESS){
//mq日志 //mq日志
//DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]); //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装置没有对应的文件时清除录波号段 //lnk20250819装置没有对应的文件时清除录波号段
printf("监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]); printf("监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]);
LD_info->FltNum[i] = -1; LD_info->FltNum[i] = -1;
@@ -2058,7 +2067,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
if (ret2==SD_SUCCESS && ret3==SD_SUCCESS ) { //两个文件都写好了 if (ret2==SD_SUCCESS && ret3==SD_SUCCESS ) { //两个文件都写好了
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s从终端获取录波文件成功", LD_info->name,LD_info->mp_id); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s从终端获取录波文件成功", LD_info->name,LD_info->mp_id);
QVVR_t *qvvr; //暂态事件 QVVR_t *qvvr; //暂态事件
long long start_tm,trig_tm,end_tm; long long start_tm,trig_tm,end_tm;
@@ -2066,7 +2075,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
ret2 = extract_timestamp_from_cfg_file(filenames[cfg_idx],&start_tm,&trig_tm);//提取文件的开始时间和触发时间 ret2 = extract_timestamp_from_cfg_file(filenames[cfg_idx],&start_tm,&trig_tm);//提取文件的开始时间和触发时间
printf(">>>>>>>> extract_timestamp_from_cfg_file end \n"); printf(">>>>>>>> extract_timestamp_from_cfg_file end \n");
if (ret2 ==APR_SUCCESS) { if (ret2 ==APR_SUCCESS) {
DIY_INFOLOG(full_key_m_c,"监测点:%s - id:%s提取录波文件时间成功", LD_info->name,LD_info->mp_id); DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s提取录波文件时间成功", LD_info->name,LD_info->mp_id);
//to find the paired qvvr by the time of trig_tm //to find the paired qvvr by the time of trig_tm
printf(">>>>>>>> extract_timestamp_from_cfg_file success \n"); printf(">>>>>>>> extract_timestamp_from_cfg_file success \n");
qvvr = find_qvvr_by_trig_tm(LD_info,trig_tm); //根据文件的触发时间查找检测点记录的匹配上的暂态事件 qvvr = find_qvvr_by_trig_tm(LD_info,trig_tm); //根据文件的触发时间查找检测点记录的匹配上的暂态事件
@@ -2094,10 +2103,10 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
//PutOSS(oss_file_fullname_cfg, loc_file_fullname_cfg);//使用buffer推送文件 //PutOSS(oss_file_fullname_cfg, loc_file_fullname_cfg);//使用buffer推送文件
} }
else if (FILE_FLAG == 2) { else if (FILE_FLAG == 2) {
OBSFile(loc_file_fullname_cfg, oss_file_fullname_cfg, "putObject");//这里并没有上传文件流 //OBSFile(loc_file_fullname_cfg, oss_file_fullname_cfg, "putObject");//这里并没有上传文件流
} }
else if(FILE_FLAG==3){ else if(FILE_FLAG==3){
WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_cfg, uuid_cfg, filename_cfg);//通过form-data上传文件 //WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_cfg, uuid_cfg, filename_cfg);//通过form-data上传文件
} }
//LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取 //LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取
else if (FILE_FLAG == 4) { else if (FILE_FLAG == 4) {
@@ -2132,10 +2141,10 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
//PutOSS(oss_file_fullname_dat, loc_file_fullname_dat);//使用buffer推送文件 //PutOSS(oss_file_fullname_dat, loc_file_fullname_dat);//使用buffer推送文件
} }
else if (FILE_FLAG == 2) { else if (FILE_FLAG == 2) {
OBSFile(loc_file_fullname_dat, oss_file_fullname_dat, "putObject");//这里并没有上传文件流 //OBSFile(loc_file_fullname_dat, oss_file_fullname_dat, "putObject");//这里并没有上传文件流
} }
else if(FILE_FLAG==3){ else if(FILE_FLAG==3){
WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_dat, uuid_dat, filename_dat);//通过form-data上传文件 //WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_dat, uuid_dat, filename_dat);//通过form-data上传文件
} }
//LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取 //LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取
else if (FILE_FLAG == 4) { else if (FILE_FLAG == 4) {
@@ -2287,10 +2296,10 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
printf("读取失败,未找到 dev_type\n"); printf("读取失败,未找到 dev_type\n");
} }
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0 if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是秒", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm); 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{ else{
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是毫秒", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm); 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);
} }
} }
@@ -2298,7 +2307,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
} }
else{ else{
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"监测点:%s - id:%s 下载录波文件%s和%s失败录波号段%d", LD_info->name,LD_info->mp_id,filenames[cfg_idx],filenames[dat_idx],LD_info->FltNum[i]); 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]);
} }
} }
@@ -2306,7 +2315,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
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_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"监测点:%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; LD_info->FltNum[i] = -1;
} }

View File

@@ -862,7 +862,7 @@ ST_VOID u_iec_rpt_ind_data_by_devtype(MVL_VAR_ASSOC** info_va,
//监测点日志的key,lnk20250526 //监测点日志的key,lnk20250526
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_d,"前置收到监测点:%s - id:%s的报告,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count); DIY_INFOLOG(full_key_m_d,"【NORMAL】前置收到监测点:%s - id:%s的报告,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
//apr_time_t previousTime = apr_time_now();// //apr_time_t previousTime = apr_time_now();//
//apr_time_exp_t localTime; //apr_time_exp_t localTime;
@@ -1162,14 +1162,14 @@ 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_CODE(full_key_m_d,LOG_CODE_REPORT,"前置不处理这个监测点:%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",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count); chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count);
//mq日志 //mq日志
DIY_INFOLOG(full_key_m_d,"前置处理监测点:%s - id:%s的报告结束,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count); DIY_INFOLOG(full_key_m_d,"【NORMAL】前置处理监测点:%s - id:%s的报告结束,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
//apr_time_t previousTimeend = apr_time_now();// //apr_time_t previousTimeend = apr_time_now();//
//apr_time_exp_t localTimeend; //apr_time_exp_t localTimeend;
@@ -1532,7 +1532,7 @@ ST_VOID u_iec_rpt_ind_data(MVL_VAR_ASSOC** info_va,
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_data(LD_info, FULL_FCDA_Name, v); processRDRE_data(LD_info, FULL_FCDA_Name, v);
} }
else if (strstr(FULL_FCDA_Name, "GGIO")) else if (strstr(FULL_FCDA_Name, "GGIO") || strstr(FULL_FCDA_Name, "LPHD"))
{ {
ied_t* ied = LD_info->ied; ied_t* ied = LD_info->ied;
ied_usr_t* ied_usr = GET_IEDEXT_ADDR(ied); ied_usr_t* ied_usr = GET_IEDEXT_ADDR(ied);

View File

@@ -1457,6 +1457,29 @@ ST_VOID u_mvl_ident_ind (MVL_IND_PEND *indCtrl)
/************************************************************************/ /************************************************************************/
/* getFile */ /* getFile */
/*
先向远端发 fopen打开远程文件
拿到这个远程文件会话句柄 frsmid
循环发 fread一块一块把远程文件内容读回来并写入本地文件
最后发 fclose关闭远程文件
clientNetInfo客户端和 MMS 服务器之间的网络连接信息
loc_file本地保存的文件路径
rem_file远端设备上的文件路径
iTimeout每次请求等待响应的超时时间
返回值:
SD_SUCCESS下载成功
其他:失败错误码
*/
/************************************************************************/ /************************************************************************/
ST_RET mms_getFile (MVL_NET_INFO *clientNetInfo, ST_CHAR *loc_file, ST_RET mms_getFile (MVL_NET_INFO *clientNetInfo, ST_CHAR *loc_file,
ST_CHAR *rem_file, ST_INT iTimeout) ST_CHAR *rem_file, ST_INT iTimeout)
@@ -1523,6 +1546,59 @@ ERR:
} }
} }
//***************************lnk20260309下发文件到装置*********************/
ST_RET mms_putFile(MVL_NET_INFO *clientNetInfo,
ST_CHAR *src_file,
ST_CHAR *dest_file,
ST_INT iTimeout)
{
MVL_REQ_PEND *reqCtrl = NULL;
ST_RET ret = SD_FAILURE;
if (clientNetInfo == NULL)
{
printf("\n mms_putFile failed: clientNetInfo is NULL");
return SD_FAILURE;
}
if (src_file == NULL || src_file[0] == '\0')
{
printf("\n mms_putFile failed: src_file is NULL or empty");
return SD_FAILURE;
}
if (dest_file == NULL || dest_file[0] == '\0')
{
printf("\n mms_putFile failed: dest_file is NULL or empty");
return SD_FAILURE;
}
ret = mvla_obtfile(clientNetInfo, src_file, dest_file, &reqCtrl);
if (ret == SD_SUCCESS)
ret = waitReqDone(reqCtrl, iTimeout);
if (ret != SD_SUCCESS)
{
printf("\n mms_putFile failed, src='%s', dest='%s', ret=0x%X",
src_file, dest_file, ret);
}
else
{
printf("\n mms_putFile OK, src='%s', dest='%s'",
src_file, dest_file);
}
if (reqCtrl != NULL)
{
mvl_free_req_ctrl(reqCtrl);
reqCtrl = NULL;
}
return ret;
}
//************************************************************************/
/* putFile */
/************************************************************************/ /************************************************************************/
/* init_mem */ /* init_mem */

View File

@@ -24,6 +24,7 @@ extern int SOCKET_PORT;
extern int G_TEST_FLAG; extern int G_TEST_FLAG;
extern int g_front_seg_index; extern int g_front_seg_index;
extern int g_front_seg_num; extern int g_front_seg_num;
extern int RECALL_ONLY_FLAG; //lnk20260309添加一个全局变量标志是否只运行补招程序
#include "../rocketmq/SimpleProducer.h" #include "../rocketmq/SimpleProducer.h"
#include "../cfg_parse/custom_printf.h"//lnk20250225 #include "../cfg_parse/custom_printf.h"//lnk20250225
@@ -187,6 +188,8 @@ apr_status_t init_rdb()
init_config(); init_config();
GetServerIndexFromDB(); GetServerIndexFromDB();
//只有补招运行时,统计不读取台账和模型
if (RECALL_ONLY_FLAG != 1 || (g_node_id != STAT_DATA_BASE_NODE_ID)) {
rv = parse_device_cfg_web(); rv = parse_device_cfg_web();
if (rv != APR_SUCCESS) { if (rv != APR_SUCCESS) {
echo_errg("Parsed device config xml file with error,try to run! \n"); echo_errg("Parsed device config xml file with error,try to run! \n");
@@ -194,7 +197,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_CODE("process",LOG_CODE_LEDGER,"前置的%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 +212,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_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"前置的%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,15 +223,16 @@ 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_CODE("process",LOG_CODE_RPTINIT,"前置的%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;
} }
}
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_CODE("process",LOG_CODE_OTHER,"前置的%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

@@ -255,6 +255,9 @@ struct LD_info_t{
rptinfo_t **rptinfo; /**< rptinfo_t* 数组 */ rptinfo_t **rptinfo; /**< rptinfo_t* 数组 */
int read_flag ; //CZY 2023-02-28 判断是否将监测点是否有效 int read_flag ; //CZY 2023-02-28 判断是否将监测点是否有效
//测点日志等级
int log_level; //0 ERROR 1 WARN 2 NORMAL 3 DEBUG
char mp_id[256];//CZY 2023-08-20 监测点编码8afaa char mp_id[256];//CZY 2023-08-20 监测点编码8afaa
char terminal_code[256];//CZY 2023-08-20 终端编码 char terminal_code[256];//CZY 2023-08-20 终端编码
//int ld_ins;//CZY 2023-08-20 逻辑设备实例号1 //int ld_ins;//CZY 2023-08-20 逻辑设备实例号1
@@ -273,8 +276,8 @@ struct LD_info_t{
int registcount;//lnk20250812 int registcount;//lnk20250812
bool has_logged_regist;//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时间
int iJournalTime;//CZY 2023-08-17 WW 2022年12月7日15:52:32 补招日志时间(0-UTC时间(日志、录波文件均为UTC时间); 1-北京时间(日志北京时间、录波文件UTC时间 注:仅四川地区+8小时读取补招日志)) int iJournalTime;//CZY 2023-08-17 WW 2022年12月7日15:52:32 补招日志时间(0-UTC时间(日志、录波文件均为UTC时间); 1-北京时间(日志北京时间、录波文件UTC时间 注:仅四川地区+8小时读取补招日志))
//不使用 //不使用
@@ -327,6 +330,8 @@ struct ied_usr_t{
void *cookie; void *cookie;
double last_call_wavelist_time ; //上次召录波列表时间 double last_call_wavelist_time ; //上次召录波列表时间
int log_level; //0 ERROR 1 WARN 2 NORMAL 3 DEBUG
char terminal_id[256];//CZY 2023-08-20 终端id8afaa9a15707483a0157262f8e78077d char terminal_id[256];//CZY 2023-08-20 终端id8afaa9a15707483a0157262f8e78077d
char org_name[256];//CZY 2023-08-20 所属单位,例:南京供公司 char org_name[256];//CZY 2023-08-20 所属单位,例:南京供公司
char maint_name[256];//CZY 2023-08-20 运维单位,例:南京供公司 char maint_name[256];//CZY 2023-08-20 运维单位,例:南京供公司
@@ -527,6 +532,8 @@ int extract_timestamp_from_cfg_file(char *comtrade_fn,long long *start_tm,long l
int parse_file_names_by_fltnum(int fltnum, char* domname, char** filenames, int filenum, int* cfg_idx, int* dat_idx, char* file_base_name, char* file_yyyymm); int parse_file_names_by_fltnum(int fltnum, char* domname, char** filenames, int filenum, int* cfg_idx, int* dat_idx, char* file_base_name, char* file_yyyymm);
QVVR_t* find_qvvr_by_trig_tm(LD_info_t* LD_info,long long trig_tm); QVVR_t* find_qvvr_by_trig_tm(LD_info_t* LD_info,long long trig_tm);
void HandleFileDirReqForChannel(chnl_usr_t *chnl_usr);
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -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_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"监测点:%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_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"监测点:%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还是北京
@@ -635,7 +635,7 @@ void processQVVR_end(LD_info_t* LD_info)
//匹配后再发qvvr起始时间要填暂态触发的时间就是第一次事件上送时只有时间没有值的那个时间 //匹配后再发qvvr起始时间要填暂态触发的时间就是第一次事件上送时只有时间没有值的那个时间
//mq日志 //mq日志
DIY_WARNLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT,"监测点%s - id:%s 发生暂态事件,暂态时间:%lld暂态持续时间%f暂态幅值%f暂态类型%d",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_time,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime, 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_Amg,
@@ -669,10 +669,10 @@ void processQVVR_end(LD_info_t* LD_info)
//mq日志 //mq日志
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0 if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"监测点:%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{
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"监测点:%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);
} }
} }

View File

@@ -8,9 +8,216 @@
#前置all的重置或者新增都是由稳态的第一个进程来处理所有进程收到这条消息后先判断自己的进程号是否是1而且是稳态否则不处理所有操作均由这个进程完成 #前置all的重置或者新增都是由稳态的第一个进程来处理所有进程收到这条消息后先判断自己的进程号是否是1而且是稳态否则不处理所有操作均由这个进程完成
if [ -z "$SETSID" ]; then
export SETSID=1
nohup setsid "$0" "$@" >> /tmp/set_process_detach.log 2>&1 < /dev/null &
exit 0
fi
# 关闭从父进程继承来的 socket / pipe / 文件描述符
for fd_path in /proc/$$/fd/*; do
fd_num=$(basename "$fd_path")
case "$fd_num" in
0|1|2) ;;
*) eval "exec ${fd_num}>&-" 2>/dev/null ;;
esac
done
# 设置日志文件路径 # 设置日志文件路径
LOGFILE="$FEP_ENV/dat/log/start_fe.log" LOGFILE="$FEP_ENV/dat/log/start_fe.log"
INI_FILE="/FeProject/etc/config/mykafka.ini"
LOCK_FILE="/tmp/set_process.lock"
if [ -f "$LOCK_FILE" ]; then
old_pid=$(cat "$LOCK_FILE")
if ps -p "$old_pid" > /dev/null 2>&1; then
echo "Already running: $old_pid"
exit 1
else
echo "Stale lock found, removing"
rm -f "$LOCK_FILE"
fi
fi
echo $$ > "$LOCK_FILE"
trap "rm -f $LOCK_FILE" EXIT
get_ini_value() {
local key="$1"
local line
line=$(grep -E "^[[:space:]]*${key}=" "$INI_FILE" | tail -n 1)
[ -z "$line" ] && return 1
# 去掉 key=
line="${line#*=}"
# 去掉首尾空格
line=$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
[ -n "$line" ] || return 1
echo "$line"
return 0
}
log() {
echo "$@" | tee -a "$LOGFILE"
}
check_local_port_released() {
local PORT="$1"
for retry in $(seq 1 3); do
for i in $(seq 1 20); do
if ! ss -lntp 2>/dev/null | grep -q ":${PORT}[[:space:]]"; then
log "[OK] Local port $PORT released"
return 0
fi
log "[WAIT] Local port $PORT still in use... ($i/20)"
sleep 1
done
log "[RETRY] Local port $PORT not released, retry $retry/3"
sleep 1
done
log "[FAIL] Local port $PORT still in use after retries:"
ss -lntp 2>/dev/null | grep ":${PORT}[[:space:]]" | tee -a "$LOGFILE"
return 1
}
check_remote_conn_released() {
local REMOTE_IP="$1"
local REMOTE_PORT="$2"
for retry in $(seq 1 3); do
for i in $(seq 1 20); do
if ! ss -ntp 2>/dev/null \
| grep "${REMOTE_IP}:${REMOTE_PORT}" \
| grep -E 'pt61850netd_pqfe|fe_watchdog|fe_main' >/dev/null; then
log "[OK] Remote ${REMOTE_IP}:${REMOTE_PORT} released"
return 0
fi
log "[WAIT] Remote ${REMOTE_IP}:${REMOTE_PORT} still exists... ($i/20)"
ss -ntp 2>/dev/null \
| grep "${REMOTE_IP}:${REMOTE_PORT}" \
| grep -E 'pt61850netd_pqfe|fe_watchdog|fe_main' \
| tee -a "$LOGFILE"
sleep 1
done
log "[RETRY] Remote ${REMOTE_IP}:${REMOTE_PORT} not released, retry $retry/3"
sleep 1
done
log "[FAIL] Remote ${REMOTE_IP}:${REMOTE_PORT} still exists:"
ss -ntp 2>/dev/null \
| grep "${REMOTE_IP}:${REMOTE_PORT}" \
| grep -E 'pt61850netd_pqfe|fe_watchdog|fe_main' \
| tee -a "$LOGFILE"
return 1
}
check_value_released() {
local key="$1"
local value="$2"
[ -z "$value" ] && return 0
# 纯端口
if echo "$value" | grep -Eq '^[0-9]+$'; then
[ "$value" = "0" ] && { log "[SKIP] $key disabled"; return 0; }
log "[CHECK] $key local port: $value"
check_local_port_released "$value"
return $?
fi
# URL
if echo "$value" | grep -Eq '^[a-zA-Z]+://'; then
local hostport ip port
hostport=$(echo "$value" | sed -n 's#^[a-zA-Z]\+://\([^/]*\).*#\1#p')
ip="${hostport%%:*}"
port="${hostport##*:}"
if [ -n "$ip" ] && [ -n "$port" ] && [ "$ip" != "$port" ]; then
log "[CHECK] $key remote: $ip:$port"
check_remote_conn_released "$ip" "$port"
return $?
fi
log "[SKIP] $key invalid URL: $value"
return 0
fi
# ip:port
if echo "$value" | grep -Eq '^[^:]+:[0-9]+$'; then
local ip="${value%%:*}"
local port="${value##*:}"
log "[CHECK] $key remote: $ip:$port"
check_remote_conn_released "$ip" "$port"
return $?
fi
log "[SKIP] $key unsupported value: $value"
return 0
}
check_key_released() {
local key="$1"
local value
value=$(get_ini_value "$key") || {
log "[SKIP] $key not found"
return 0
}
log "==== Checking $key = $value ===="
check_value_released "$key" "$value"
return $?
}
check_all_resources_released() {
local ret=0
log "=============================="
log " Start checking resources..."
log "=============================="
# 本地端口
check_key_released "TestPort" || ret=1
check_key_released "HttpPort" || ret=1
check_key_released "SocketPort" || ret=1
# MQ
check_key_released "Ipport" || ret=1
check_key_released "ConsumerIpport" || ret=1
# Web
check_key_released "WebDevice" || ret=1
check_key_released "WebIcd" || ret=1
check_key_released "WebIntegrity" || ret=1
check_key_released "WebComflag" || ret=1
check_key_released "WebEvent" || ret=1
check_key_released "WebFileupload" || ret=1
check_key_released "WebFiledownload" || ret=1
if [ $ret -eq 0 ]; then
log "✅ ALL resources released"
else
log "❌ Some resources NOT released"
fi
return $ret
}
# 输出当前时间并打印进程停止信息 # 输出当前时间并打印进程停止信息
echo "" ; echo "" echo "" ; echo ""
echo "****** `date "+%F %R:%S"` start setting Processes after 3 sec ******" echo "****** `date "+%F %R:%S"` start setting Processes after 3 sec ******"
@@ -20,7 +227,7 @@ echo "****** `date "+%F %R:%S"` start setting Processes after 3 sec ******" >>"$
# 函数检查并处理日志文件大小 # 函数检查并处理日志文件大小
check_log_file() { check_log_file() {
if [ -n "$1" ]; then if [ -n "$1" ] && [ -f "$1" ]; then
FILE_SIZE=0 FILE_SIZE=0
FILE_SIZE=$(du "$1" | awk '{print $1}') FILE_SIZE=$(du "$1" | awk '{print $1}')
@@ -45,23 +252,46 @@ check_log_file $LOGFILE
# 定义查找并杀死进程的函数 # 定义查找并杀死进程的函数
kill_process_by_name() { kill_process_by_name() {
PROCESS_NAME=$1 local PROCESS_NAME="$1"
PID=$(ps -ef | grep "$PROCESS_NAME" | grep -v "grep" | awk '{print $2}') local PIDS
if [ -n "$PID" ]; then PIDS=$(ps -ef | grep "$PROCESS_NAME" | grep -v grep | awk '{print $2}')
echo "Found process '$PROCESS_NAME' with PID: $PID"
if [ -n "$PIDS" ]; then
echo "Found process '$PROCESS_NAME' with PID(s): $PIDS"
echo "Killing process..." echo "Killing process..."
kill -9 $PID
if [ $? -eq 0 ]; then for pid in $PIDS; do
echo "Process '$PROCESS_NAME' killed successfully." kill -15 "$pid" 2>/dev/null
else done
echo "Failed to kill the process '$PROCESS_NAME'."
sleep 3
for pid in $PIDS; do
if ps -p "$pid" >/dev/null 2>&1; then
echo "Process still exists, force kill: $pid"
kill -9 "$pid" 2>/dev/null
fi fi
done
else else
echo "Process '$PROCESS_NAME' not found." echo "Process '$PROCESS_NAME' not found."
fi fi
} }
wait_all_exit() {
for i in $(seq 1 30); do
COUNT=$(ps -ef | grep -E 'pt61850netd_pqfe|fe_watchdog' | grep -v grep | wc -l)
if [ "$COUNT" -eq 0 ]; then
echo "All FE processes exited"
return 0
fi
echo "Waiting FE processes exit... ($COUNT still running)"
sleep 1
done
echo "Timeout waiting FE processes exit"
return 1
}
# 功能块开始 # 功能块开始
handle_reset() { handle_reset() {
# 功能reset # 功能reset
@@ -71,22 +301,28 @@ handle_reset() {
if [ "$2" == "all" ]; then if [ "$2" == "all" ]; then
# 关闭旧的看门狗进程 # 关闭旧的看门狗进程
kill_process_by_name "/FeProject/bin/fe_watchdog" #kill_process_by_name "/FeProject/bin/fe_watchdog"
# 关闭旧的 stat 进程 # 关闭旧的 stat 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_stat_data" #kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_stat_data"
# 关闭旧的 recall 进程 # 关闭旧的 recall 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_recallhis_data" #kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_recallhis_data"
# 关闭旧的 3s 进程 # 关闭旧的 3s 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_3s_data" #kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_3s_data"
# 关闭旧的 comtrade 进程 # 关闭旧的 comtrade 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_soe_comtrade" #kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_soe_comtrade"
/home/pq/FeProject/boot/stop_fe.sh
wait_all_exit || exit 1
check_all_resources_released || exit 1
#关闭进程后等待一段时间,防止端口占用 #关闭进程后等待一段时间,防止端口占用
#sleep 5 sleep 5
# 清空 runtime.cf 中的所有进程配置 # 清空 runtime.cf 中的所有进程配置
sed -i '/cfg_stat_data/d' /home/pq/FeProject/etc/runtime.cf sed -i '/cfg_stat_data/d' /home/pq/FeProject/etc/runtime.cf
@@ -120,6 +356,9 @@ handle_reset() {
fi fi
# 修改后等一下
sleep 1
# 确保文件已被写入并刷新 # 确保文件已被写入并刷新
sync sync
@@ -230,14 +469,13 @@ handle_add() {
} }
# 获取当前脚本的进程ID # 获取当前脚本的进程ID
CURRENT_PID=$$ #CURRENT_PID=$$
# 检查是否有其他的set_process.sh脚本正在运行排除当前脚本 # 检查是否有其他的set_process.sh脚本正在运行排除当前脚本
if pgrep -f "set_process.sh" | grep -v "^$CURRENT_PID$" > /dev/null; then #if pgrep -f "set_process.sh" | grep -v "^$CURRENT_PID$" > /dev/null; then
echo "set_process.sh is already running. Exiting..." # echo "set_process.sh is already running. Exiting..."
echo "set_process.sh is already running. Exiting..." >>"$LOGFILE" # echo "set_process.sh is already running. Exiting..." >>"$LOGFILE"
exit 1 # exit 1
fi #fi
#脚本应该等待3秒钟 #脚本应该等待3秒钟
sleep 3 sleep 3