Compare commits
9 Commits
DB_1.0
...
6f7ee762ec
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f7ee762ec | |||
| 0acc58bbe1 | |||
| d1ed49412c | |||
| 748f8481bc | |||
| d5916f5559 | |||
| 50dd5c8a3e | |||
| 1bc32ae38c | |||
| fe8ba6fad9 | |||
| a2aa627b1e |
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
#include "../log4cplus/fileappender.h"
|
||||
#include "../log4cplus/layout.h"
|
||||
#include "../log4cplus/ndc.h"
|
||||
#include "../log4cplus/log4.h"
|
||||
//#include "../log4cplus/log4.h"
|
||||
#include "../log4cplus/spi/loggingevent.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
@@ -18,21 +18,47 @@
|
||||
//目录创建
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
//kafka结构定义
|
||||
#include "../json/mms_json_inter.h"
|
||||
|
||||
|
||||
#include "../mms/rdb_client.h"
|
||||
#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 int g_front_seg_index;
|
||||
extern std::string FRONT_INST;
|
||||
extern char subdir[128];
|
||||
extern node_t* g_node;
|
||||
|
||||
|
||||
//mq
|
||||
extern QMutex kafka_data_list_mutex; //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;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//log4命名空间
|
||||
using namespace log4cplus;
|
||||
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() {
|
||||
if (std::strstr(subdir, "cfg_3s_data") != NULL)
|
||||
return "realTime";
|
||||
@@ -79,12 +246,11 @@ bool create_directory_recursive(const std::string& path) {
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
std::string extract_logger_id(const std::string& logger_name) {
|
||||
size_t first = logger_name.find('.');
|
||||
size_t last = logger_name.rfind('.');
|
||||
if (first != std::string::npos && last != std::string::npos && first + 1 < last) {
|
||||
return logger_name.substr(first + 1, last - first - 1); // 去掉开头"terminal."和结尾".COM"
|
||||
}
|
||||
return "";
|
||||
if (logger_name == "process") return "process";
|
||||
size_t pos = logger_name.find('.');
|
||||
if (pos == std::string::npos) return "";
|
||||
// 取第一个 '.' 后面的全部:terminal.<id> / monitor.<mp>
|
||||
return logger_name.substr(pos + 1);
|
||||
}
|
||||
|
||||
std::string get_level_str(int level) {
|
||||
@@ -98,7 +264,7 @@ std::string get_level_str(int level) {
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
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) {}
|
||||
void DebugSwitch::open() { debug_open = true; }
|
||||
@@ -132,46 +298,65 @@ LOG_TLS int g_log_code_tls = 0;
|
||||
|
||||
class SendAppender : public Appender {
|
||||
protected:
|
||||
void append(const spi::InternalLoggingEvent& event) {
|
||||
void append(const spi::InternalLoggingEvent& event) override {
|
||||
std::string logger_name = event.getLoggerName();
|
||||
int level = event.getLogLevel();
|
||||
std::string msg = event.getMessage();
|
||||
|
||||
int logtype = (logger_name.find(".COM") != std::string::npos) ? LOGTYPE_COM : LOGTYPE_DATA;
|
||||
std::string level_str;
|
||||
if (logger_name.find("process") == 0)
|
||||
level_str = "process";
|
||||
else if (logger_name.find("monitor") != std::string::npos)
|
||||
level_str = "measurepoint";
|
||||
else
|
||||
else if (logger_name.find("terminal") != std::string::npos)
|
||||
level_str = "terminal";
|
||||
else
|
||||
level_str = "process";
|
||||
|
||||
// ★读取 TLS 中的 code(在打日志的线程里由宏设定)
|
||||
int code = g_log_code_tls; // 若未显式传入,则为 0
|
||||
int code = g_log_code_tls; // TLS code
|
||||
int safe_logtype = code; // ★关键:用 code 当 logtype 维度
|
||||
|
||||
if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) {
|
||||
std::ostringstream oss;
|
||||
oss << "{\"processNo\":\"" << intToString(g_front_seg_index)
|
||||
<< "\",\"nodeId\":\"" << FRONT_INST
|
||||
<< "\",\"businessId\":\"" << extract_logger_id(logger_name)
|
||||
<< "\",\"level\":\"" << level_str
|
||||
<< "\",\"grade\":\"" << get_level_str(level)
|
||||
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data")
|
||||
<< "\",\"frontType\":\"" << get_front_type_from_subdir()
|
||||
// ★新增:输出 code 字段(整型)
|
||||
<< "\",\"code\":\"" << code
|
||||
<< "\",\"log\":\"" << escape_json(msg) << "\"}";
|
||||
bool allow_send = false;
|
||||
int min_send_level = get_min_send_level_cached(level_str, logger_name);
|
||||
|
||||
std::string jsonString = oss.str();
|
||||
// ① 高于台账阈值:直接上送
|
||||
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);
|
||||
|
||||
Ckafka_data_t connect_info;
|
||||
connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC);
|
||||
connect_info.strText = QString::fromStdString(jsonString);
|
||||
|
||||
kafka_data_list_mutex.lock();
|
||||
kafka_data_list.append(connect_info);
|
||||
kafka_data_list_mutex.unlock();
|
||||
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;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "{\"processNo\":\"" << intToString(g_front_seg_index)
|
||||
<< "\",\"nodeId\":\"" << FRONT_INST
|
||||
<< "\",\"businessId\":\"" << extract_logger_id(logger_name)
|
||||
<< "\",\"level\":\"" << level_str
|
||||
<< "\",\"grade\":\"" << get_level_str(level)
|
||||
<< "\",\"logtype\":\"" << safe_logtype
|
||||
<< "\",\"frontType\":\"" << get_front_type_from_subdir()
|
||||
<< "\",\"code\":" << code
|
||||
<< ",\"log\":\"" << escape_json(msg) << "\"}";
|
||||
|
||||
Ckafka_data_t connect_info;
|
||||
connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC);
|
||||
connect_info.strText = QString::fromStdString(oss.str());
|
||||
|
||||
kafka_data_list_mutex.lock();
|
||||
kafka_data_list.append(connect_info);
|
||||
kafka_data_list_mutex.unlock();
|
||||
}
|
||||
|
||||
std::string escape_json(const std::string& input) {
|
||||
@@ -198,25 +383,58 @@ public:
|
||||
virtual ~SendAppender() {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
//用来控制日志上送的结构
|
||||
struct LOGEntry {
|
||||
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");
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////20260303添加日志上送控制 - 频率限制实现
|
||||
std::unordered_map<std::string, SendAppender::RateState> SendAppender::s_rate_map;
|
||||
std::mutex SendAppender::s_rate_mutex;
|
||||
|
||||
// 外部线程中调用:每秒更新所有倒计时,0 则删除
|
||||
void update_log_entries_countdown() {
|
||||
@@ -236,25 +454,25 @@ void update_log_entries_countdown() {
|
||||
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) {
|
||||
if (level != "terminal" && level != "measurepoint") return;
|
||||
void process_log_command(const std::string& id,
|
||||
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;
|
||||
|
||||
std::string key = build_debug_key(id, level, type);
|
||||
std::string key = build_debug_key(id, level, code);
|
||||
|
||||
pthread_mutex_lock(&g_log_mutex);
|
||||
|
||||
LOGEntry& entry = g_log_entries[key]; // 会自动 insert 或取已有
|
||||
LOGEntry& entry = g_log_entries[key];
|
||||
entry.id = id;
|
||||
entry.level = level;
|
||||
entry.logtype = type;
|
||||
entry.code = code;
|
||||
entry.min_grade = grade_level;
|
||||
entry.countdown = 60; // 重置倒计时
|
||||
|
||||
entry.countdown = 60;
|
||||
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) {
|
||||
@@ -286,7 +504,7 @@ log4cplus::Logger init_logger(const std::string& full_name,
|
||||
//进程的日志
|
||||
void init_logger_process() {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -321,12 +539,10 @@ void init_loggers_bydevid(const char* dev_id)
|
||||
|
||||
std::string device_dir = base_dir + "/" + ip_str;
|
||||
|
||||
std::string device_key_c = std::string("terminal.") + dev_id + ".COM";
|
||||
std::string device_key_d = std::string("terminal.") + dev_id + ".DATA";
|
||||
std::string device_key = std::string("terminal.") + dev_id;
|
||||
|
||||
// 添加判断:终端日志 logger 是否已存在
|
||||
if (logger_map.find(device_key_c) == logger_map.end() &&
|
||||
logger_map.find(device_key_d) == logger_map.end()) {
|
||||
if (logger_map.find(device_key) == logger_map.end()) {
|
||||
|
||||
// 所有终端日志(com 和 data)写到同一个 device 日志文件中
|
||||
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));
|
||||
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_d = init_logger(device_key_d, device_dir, dev_id, device_appender); //用终端id作为日志文件名
|
||||
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
|
||||
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
|
||||
Logger device_logger = init_logger(device_key, device_dir, dev_id, device_appender); //用终端id作为日志文件名
|
||||
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT);
|
||||
|
||||
DIY_INFOLOG(device_key_d.c_str(),"【NORMAL】终端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) {
|
||||
if (strlen(ied_usr->LD_info[i].mp_id) > 0){
|
||||
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
|
||||
mon_key_c << "monitor." << ied_usr->LD_info[i].mp_id << ".COM";
|
||||
mon_key_d << "monitor." << ied_usr->LD_info[i].mp_id << ".DATA";
|
||||
std::ostringstream mon_key, mon_path, mon_name;
|
||||
mon_key << "monitor." << ied_usr->LD_info[i].mp_id;
|
||||
mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录
|
||||
mon_name << ied_usr->LD_info[i].mp_id;
|
||||
|
||||
// 添加判断:监测点 logger 是否已存在
|
||||
if (logger_map.find(mon_key_c.str()) == logger_map.end() &&
|
||||
logger_map.find(mon_key_d.str()) == logger_map.end()) {
|
||||
if (logger_map.find(mon_key.str()) == logger_map.end()) {
|
||||
|
||||
// 所有监测点日志(com 和 data)写到同一个 monitor 日志文件中
|
||||
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));
|
||||
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_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_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
|
||||
Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(),monitor_appender);//用监测点号作为日志文件名
|
||||
logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT);
|
||||
|
||||
DIY_INFOLOG(mon_key_d.str().c_str(),"【NORMAL】监测点:%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
|
||||
}
|
||||
|
||||
//lnk20260303添加日志上送控制 - 初始化时构建日志等级缓存
|
||||
refresh_log_level_cache_locked();
|
||||
}
|
||||
|
||||
void init_loggers() {
|
||||
@@ -402,8 +615,7 @@ void init_loggers() {
|
||||
|
||||
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_d = std::string("terminal.") + ied_usr->terminal_id + ".DATA";
|
||||
std::string device_key = std::string("terminal.") + ied_usr->terminal_id;
|
||||
|
||||
// 所有终端日志(com 和 data)写到同一个 device 日志文件中
|
||||
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));
|
||||
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_d = init_logger(device_key_d, 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_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
|
||||
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
|
||||
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT);
|
||||
|
||||
DIY_INFOLOG(device_key_d.c_str(),"【NORMAL】终端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) {
|
||||
if (strlen(ied_usr->LD_info[i].mp_id) > 0){
|
||||
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
|
||||
mon_key_c << "monitor." << ied_usr->LD_info[i].mp_id << ".COM";
|
||||
mon_key_d << "monitor." << ied_usr->LD_info[i].mp_id << ".DATA";
|
||||
std::ostringstream mon_key, mon_path, mon_name;
|
||||
mon_key << "monitor." << ied_usr->LD_info[i].mp_id;
|
||||
|
||||
mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录
|
||||
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));
|
||||
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_d = init_logger(mon_key_d.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_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
|
||||
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
|
||||
logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT);
|
||||
|
||||
DIY_INFOLOG(mon_key_d.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
|
||||
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) {
|
||||
@@ -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;
|
||||
|
||||
// 删除终端日志 logger
|
||||
std::string com_key = "terminal." + terminal_id + ".COM";
|
||||
std::string data_key = "terminal." + terminal_id + ".DATA";
|
||||
std::string terminal_key = "terminal." + terminal_id;;
|
||||
|
||||
if (logger_map.count(com_key)) {
|
||||
logger_map[com_key].logger.removeAllAppenders();
|
||||
logger_map.erase(com_key);
|
||||
}
|
||||
|
||||
if (logger_map.count(data_key)) {
|
||||
logger_map[data_key].logger.removeAllAppenders();
|
||||
logger_map.erase(data_key);
|
||||
if (logger_map.count(terminal_key)) {
|
||||
logger_map[terminal_key].logger.removeAllAppenders();
|
||||
logger_map.erase(terminal_key);
|
||||
}
|
||||
|
||||
// 删除监测点日志 logger
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
const char* mp_id = ied_usr->LD_info[i].mp_id;
|
||||
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";
|
||||
std::string mon_data_key = mon_prefix + ".DATA";
|
||||
|
||||
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_key)) {
|
||||
logger_map[mon_key].logger.removeAllAppenders();
|
||||
logger_map.erase(mon_key);
|
||||
}
|
||||
|
||||
if (logger_map.count(mon_data_key)) {
|
||||
logger_map[mon_data_key].logger.removeAllAppenders();
|
||||
logger_map.erase(mon_data_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,18 @@
|
||||
#include "../json/cjson.h"
|
||||
|
||||
#include "../log4cplus/log4.h"//lnk添加log4
|
||||
|
||||
///////////////////////////////////////////////////////////////////////lnk20260305数据追踪相关
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QMapIterator>
|
||||
#include <QStringList>
|
||||
|
||||
// ★MOD: 全局追踪表:mp_id -> remaining times
|
||||
static QMutex g_trace_mutex;
|
||||
static QHash<QString, int> g_trace_map;
|
||||
|
||||
///////////////////////////////////////////////////lnk2024-10-21////////////////////////////////////////////////////////
|
||||
extern void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr);
|
||||
extern std::string WEB_INTEGRITY;
|
||||
@@ -33,6 +45,9 @@ extern std::string WEB_EVENT;
|
||||
extern std::string WEB_FILEDOWNLOAD;
|
||||
extern std::string G_CONNECT_TOPIC;
|
||||
|
||||
//lnk20250115添加台账锁
|
||||
extern pthread_mutex_t mtx;
|
||||
|
||||
bool DEBUGOPEN = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -56,7 +71,10 @@ public:
|
||||
int nDataType; //告警SOE事件类型
|
||||
QString type; //参数等级type类型:0-DataType 1-监测点 2-剔除标记 3-发生时刻,毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
|
||||
QString triggerFlag; //告警SOE事件触发指标名称
|
||||
int nIndex; //数据在每条线路LineInfo值数组中的位置
|
||||
int nIndex; //数据在每条线路LineInfo值数组中的位置
|
||||
|
||||
QString desc; //soe事件描述
|
||||
|
||||
QString DO; //数据对象名
|
||||
QString DA; //数据属性名
|
||||
QString strFullName; //数据对象名 $ 数据属性名
|
||||
@@ -145,7 +163,8 @@ public:
|
||||
QString WavePhasicA;
|
||||
QString WavePhasicB;
|
||||
QString WavePhasicC;
|
||||
QString UnitOfTimeUnit; //暂态事件持续事件单位:0 - 毫秒 1 - 秒
|
||||
QString TypeOfData; //闪变和统计是否合并 0-分开 1-合并
|
||||
QString UnitOfTimeUnit; //暂态事件持续事件单位:0 - 毫秒 1 - 秒 lnk20260127
|
||||
QString ValueOfTimeUnit; //上送值的时间:UTC-UTC时间 beijing-北京时间
|
||||
QString WaveTimeFlag; //录波文件的时间:UTC-UTC时间 beijing-北京时间
|
||||
QString IEDname; //例:PQMonitor
|
||||
@@ -223,7 +242,106 @@ extern int isdelta_flag;//lnk2024-8-16 角型接线标志
|
||||
void connectlog_pgsql(char* id,char* datetime,int status);
|
||||
///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////lnk20260305数据追踪
|
||||
static QString escape_json_string(const QString& s)
|
||||
{
|
||||
QString out = s;
|
||||
out.replace("\\", "\\\\");
|
||||
out.replace("\"", "\\\"");
|
||||
out.replace("\r", "\\r");
|
||||
out.replace("\n", "\\n");
|
||||
out.replace("\t", "\\t");
|
||||
return out;
|
||||
}
|
||||
|
||||
// 打开追踪:次数 times(比如 5)
|
||||
void process_trace_command(const std::string& id, int times)
|
||||
{
|
||||
if (times <= 0) return;
|
||||
QString qid = QString::fromStdString(id).trimmed();
|
||||
if (qid.isEmpty()) return;
|
||||
|
||||
QMutexLocker lk(&g_trace_mutex);
|
||||
g_trace_map[qid] = times; // 重新打开就覆盖/重置次数
|
||||
}
|
||||
|
||||
// 查询是否要追踪
|
||||
static bool trace_is_enabled(const QString& mp_id)
|
||||
{
|
||||
QMutexLocker lk(&g_trace_mutex);
|
||||
auto it = g_trace_map.constFind(mp_id);
|
||||
return (it != g_trace_map.constEnd() && it.value() > 0);
|
||||
}
|
||||
|
||||
// 命中一次并扣减;扣到 0 自动删
|
||||
static void trace_hit_and_decrement(const QString& mp_id)
|
||||
{
|
||||
QMutexLocker lk(&g_trace_mutex);
|
||||
auto it = g_trace_map.find(mp_id);
|
||||
if (it == g_trace_map.end()) return;
|
||||
|
||||
int left = it.value();
|
||||
left -= 1;
|
||||
if (left <= 0) g_trace_map.erase(it);
|
||||
else it.value() = left;
|
||||
}
|
||||
|
||||
//追踪61850原始数据
|
||||
static QString build_mms_multiline_text(const json_block_data* data)
|
||||
{
|
||||
QStringList lines;
|
||||
|
||||
QMapIterator<QString, double> it(data->mms_str_map);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
lines << QString("%1 = %2").arg(it.key()).arg(it.value(), 0, 'g', 15);
|
||||
}
|
||||
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
static QString build_trace_json(const json_block_data* data)
|
||||
{
|
||||
if (!data) return "{}";
|
||||
|
||||
QString mms_text = build_mms_multiline_text(data);
|
||||
|
||||
QString json;
|
||||
json += "{";
|
||||
json += QString("\"mp_id\":\"%1\",").arg(escape_json_string(data->mp_id));
|
||||
json += QString("\"func_type\":%1,").arg(data->func_type);
|
||||
json += QString("\"data_time\":%1,").arg(QString::number((qlonglong)data->time));
|
||||
json += QString("\"voltage_level\":\"%1\",").arg(QString::number(data->voltage_level, 'f', 6));
|
||||
json += QString("\"dev_type\":\"%1\",").arg(escape_json_string(data->dev_type));
|
||||
json += QString("\"mms_text\":\"%1\"").arg(escape_json_string(mms_text));
|
||||
json += "}";
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
static void send_trace_if_needed(json_block_data* pdata)
|
||||
{
|
||||
const QString mp_id_q = pdata->mp_id;
|
||||
if (trace_is_enabled(mp_id_q)) {
|
||||
|
||||
// 1) 组 json
|
||||
QString jsonText = build_trace_json(pdata);
|
||||
|
||||
// 2) 组 KafkaData
|
||||
Ckafka_data_t KafkaData;
|
||||
KafkaData.monitor_id = pdata->monitorId;
|
||||
KafkaData.mp_id = pdata->mp_id;
|
||||
KafkaData.strTopic = "DATA_TRACE_TOPIC";
|
||||
KafkaData.strText = jsonText;
|
||||
|
||||
kafka_data_list_mutex.lock();
|
||||
kafka_data_list.append(KafkaData);
|
||||
kafka_data_list_mutex.unlock();
|
||||
|
||||
// 3) 次数 -1
|
||||
trace_hit_and_decrement(mp_id_q);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////lnk20250710添加频率值存储
|
||||
struct mp_freq_save {
|
||||
double G_FREQ;
|
||||
@@ -244,6 +362,8 @@ bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(out_cfg, 0, sizeof(*out_cfg));
|
||||
|
||||
QString dev_type_q = QString::fromUtf8(dev_type);
|
||||
QMap<QString, Xmldata*>::iterator it = xmlinfo_list.find(dev_type_q);
|
||||
if (it == xmlinfo_list.end() || it.value() == nullptr) {
|
||||
@@ -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->WavePhasicC, cfg.WavePhasicC.toUtf8().constData(), sizeof(out_cfg->WavePhasicC) - 1);
|
||||
strncpy(out_cfg->UnitOfTimeUnit, cfg.UnitOfTimeUnit.toUtf8().constData(), sizeof(out_cfg->UnitOfTimeUnit) - 1);
|
||||
strncpy(out_cfg->TypeOfData, cfg.TypeOfData.toUtf8().constData(), sizeof(out_cfg->TypeOfData) - 1); out_cfg->TypeOfData[sizeof(out_cfg->TypeOfData) - 1] = '\0';//lnk20260127
|
||||
strncpy(out_cfg->ValueOfTimeUnit, cfg.ValueOfTimeUnit.toUtf8().constData(),sizeof(out_cfg->ValueOfTimeUnit) - 1);
|
||||
strncpy(out_cfg->WaveTimeFlag, cfg.WaveTimeFlag.toUtf8().constData(), sizeof(out_cfg->WaveTimeFlag) - 1);
|
||||
strncpy(out_cfg->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事件类指针
|
||||
ed->triggerFlag = node.toElement().attribute("name"); //SOE名称
|
||||
ed->desc = node.toElement().attribute("desc"); //SOE描述
|
||||
ed->DO = node.toElement().attribute("DO"); //数据对象名
|
||||
ed->DA = node.toElement().attribute("DA"); //数据属性名
|
||||
ed->type = node.toElement().attribute("type"); //参数等级type类型:0-DataType 1-监测点 2-剔除标记 3-发生时刻,毫秒 4-数据链表 5-相位 6-值索引 9-实时SOE事件
|
||||
@@ -898,6 +1020,11 @@ bool ParseXMLConfig2(int xml_flag, XmlConfig *cfg, list<CTopic*> *ctopiclist,QSt
|
||||
{
|
||||
cfg->UnitOfTimeUnit.append(e.attribute("Unit"));
|
||||
}
|
||||
//lnk 20260127
|
||||
if ("TypeOfData" == strTag)
|
||||
{
|
||||
cfg->TypeOfData.append(e.attribute("Unit"));
|
||||
}
|
||||
if ("ValueOfTime" == strTag)
|
||||
{
|
||||
cfg->ValueOfTimeUnit.append(e.attribute("Unit"));
|
||||
@@ -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添加角型接线处理
|
||||
int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json生成函数 zw修改 2023-8-11 调整传送json结构 目前仅限历史稳态数据
|
||||
{
|
||||
// 刚进函数就打印 mms_str_map
|
||||
if (DEBUGOPEN) {
|
||||
print_mms_str_map(data);
|
||||
}
|
||||
|
||||
list<CTopic*> ctopic_list;
|
||||
|
||||
////lnk2024-8-15 区分星型,角型接线
|
||||
@@ -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;
|
||||
ctopic_list = xmlinfo_list2[data->dev_type]->topicList;
|
||||
|
||||
if(DEBUGOPEN)printCTopicList(ctopic_list);
|
||||
|
||||
}
|
||||
else {
|
||||
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 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(); //解锁
|
||||
longjumpflag = true;
|
||||
}
|
||||
if (longjumpflag == true || shortjumpflag == true) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//lnk20260127
|
||||
if (typeofdata == false || data_have_static == false) {//不合并则处理完闪变就不处理其他数据,如果有统计数据或者数据类型区分了就继续处理其他数据
|
||||
if (longjumpflag == true || shortjumpflag == true) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} //②-②历史闪变数据解析结束!--------------------------------
|
||||
|
||||
//合并则继续处理其他数据
|
||||
if (1 == pDataType->iDataType) //②-①历史稳态数据-----------------------------------------------------------
|
||||
{
|
||||
Ckafka_data_t KafkaData; //kafka发送数据结构类对象
|
||||
@@ -2240,8 +2446,10 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
|
||||
kafka_data_list_mutex.unlock(); //解锁
|
||||
longjumpflag = true;
|
||||
}
|
||||
if (longjumpflag == true || shortjumpflag == true) {
|
||||
return 1;
|
||||
if (typeofdata == false || data_have_static == false) {//不合并则处理完闪变就不处理其他数据
|
||||
if (longjumpflag == true || shortjumpflag == true) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
//return 1; //结束该函数,停止后续代码执行
|
||||
} //②-②历史闪变数据解析结束!--------------------------------
|
||||
@@ -2561,8 +2769,35 @@ int transfer_json_block_data(char v_wiring_type[], json_block_data *data) //json
|
||||
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)
|
||||
{
|
||||
|
||||
//监测点日志的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;
|
||||
if (xmlinfo_list.contains(devtype)) {
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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.append(KafkaData); //添加 kafka发送链表
|
||||
kafka_data_list_mutex.unlock(); //解锁
|
||||
|
||||
}
|
||||
|
||||
//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();
|
||||
xmlinfo_list2.insert(type, config2);
|
||||
xmlinfo_list2[type]->updataflag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2694,35 +2953,30 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
|
||||
|
||||
char file_name[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;
|
||||
Qsavename.append("/FeProject/dat/").append(id).append(".xml"); //本地保存路径
|
||||
char save_name[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;
|
||||
|
||||
//mq日志
|
||||
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获取文件内容
|
||||
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::cout << "fullpath" << fullPath << std::endl;
|
||||
|
||||
SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", &fileContent);
|
||||
if (fileContent != NULL) {
|
||||
if (fileContent != NULL && fileContent[0] != '\0') {
|
||||
// 创建并打开文件
|
||||
|
||||
//判断返回的是不是错误json响应
|
||||
@@ -3201,18 +3455,19 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
|
||||
// 尝试发送
|
||||
char* ptr = NULL; // 接收返回
|
||||
SendJsonAPI_web(WEB_EVENT, "", jsonContent.c_str(), &ptr);
|
||||
if (ptr != NULL) {
|
||||
if (ptr != NULL && ptr[0] != '\0') {
|
||||
|
||||
cJSON* j_r = cJSON_Parse(ptr);
|
||||
if (j_r == NULL) {
|
||||
std::cout << "old file send fail" << std::endl;
|
||||
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
|
||||
handleCommentResponse(std::string(ptr));
|
||||
|
||||
|
||||
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件失败");
|
||||
|
||||
}
|
||||
else{
|
||||
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
|
||||
handleCommentResponse(std::string(ptr));
|
||||
|
||||
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件成功");
|
||||
|
||||
@@ -3220,7 +3475,7 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
|
||||
// 删除文件
|
||||
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;
|
||||
}
|
||||
|
||||
if (strlen(mp_id) == 0) {
|
||||
if (NULL == mp_id || strlen(mp_id) == 0 ) {
|
||||
std::cout << "mp_id is null" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -3309,6 +3564,12 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
|
||||
}
|
||||
|
||||
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 字符串
|
||||
|
||||
// 发送到暂态接口
|
||||
@@ -3317,7 +3578,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
|
||||
|
||||
// ================ 插入新功能 =========================
|
||||
// ********** 新增功能开始 **********
|
||||
if(ptr != NULL)
|
||||
if(ptr != NULL && ptr[0] != '\0')
|
||||
{
|
||||
cJSON* j_r = cJSON_Parse(ptr);
|
||||
// 如果发送失败(j_r == NULL),则把当前 json 存入指定目录(/FeProject/dat/qvvr/)
|
||||
@@ -3346,13 +3607,13 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
|
||||
|
||||
// 把 json_string 写入文件
|
||||
if(!writeJsonToFile(fileName.c_str(), json_string)){
|
||||
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id);
|
||||
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
|
||||
}
|
||||
|
||||
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
|
||||
}
|
||||
else{
|
||||
free(j_r);
|
||||
cJSON_Delete(j_r);
|
||||
//后续处理
|
||||
}
|
||||
}
|
||||
@@ -3365,10 +3626,11 @@ 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;
|
||||
handleCommentResponse(std::string(ptr));
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
} else {
|
||||
// 处理 ptr 为 NULL 的情况,例如日志记录或错误处理
|
||||
std::cout << "Error: Received NULL response" << std::endl;
|
||||
@@ -3394,7 +3656,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
|
||||
fileName += ".txt";
|
||||
// 把 json_string 写入文件
|
||||
if(!writeJsonToFile(fileName.c_str(), json_string)){
|
||||
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id);
|
||||
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点:%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
|
||||
}
|
||||
|
||||
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
|
||||
|
||||
@@ -38,7 +38,11 @@ public:
|
||||
QString mp_id; //char型监测点
|
||||
QString dev_type;//设备类型
|
||||
|
||||
bool data_have_statistic;//是否有统计数据,0没有,1有
|
||||
|
||||
QMap<QString, double> mms_str_map; //数据值(61850数据属性名, 数据值)
|
||||
|
||||
bool data_trace_flag; //数据追踪标记,0不追踪,1追踪
|
||||
};
|
||||
|
||||
class Ckafka_data_t //kafka发送数据结构类
|
||||
|
||||
@@ -46,6 +46,18 @@ int StringToInt(const std::string& str);
|
||||
extern pthread_mutex_t mtx;//lnk20250115
|
||||
|
||||
|
||||
|
||||
extern void SendFileWeb(const std::string& strUrl,
|
||||
const char* localpath,
|
||||
const char* cloudpath,
|
||||
char* wavepath);
|
||||
|
||||
extern int DownloadFileWeb(const std::string& strUrl,
|
||||
const char* remotePath,
|
||||
const char* localpath);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -64,6 +76,13 @@ extern "C" {
|
||||
extern node_t* g_node; //lnk20241223
|
||||
extern LD_info_t* find_LD_info_only_from_mp_id(char* mp_id);//lnk20241223
|
||||
extern void print_terminal(const terminal* tmnl);
|
||||
|
||||
extern ST_RET mms_mvla_obtfile(MVL_NET_INFO *net_info,
|
||||
ST_CHAR *srcfilename,
|
||||
ST_CHAR *destfilename,
|
||||
int iTimeout);
|
||||
|
||||
extern pt61850app_t *g_pt61850app;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -121,13 +140,21 @@ extern std::string G_MQCONSUMER_KEY_RC;//key
|
||||
extern std::string G_MQCONSUMER_TOPIC_SET;//topie_recall
|
||||
extern std::string G_MQCONSUMER_TAG_SET;//tag
|
||||
extern std::string G_MQCONSUMER_KEY_SET;//key
|
||||
|
||||
extern std::string G_MQCONSUMER_TOPIC_LOG;//topie_log
|
||||
extern std::string G_MQCONSUMER_TAG_LOG;//tag
|
||||
extern std::string G_MQCONSUMER_KEY_LOG;//key
|
||||
extern std::string G_LOG_TOPIC;//topie
|
||||
extern std::string G_LOG_TAG;//tag
|
||||
extern std::string G_LOG_KEY;//key
|
||||
extern std::string G_MQCONSUMER_TOPIC_FILE;//topie_file
|
||||
extern std::string G_MQCONSUMER_TAG_FILE;//tag
|
||||
extern std::string G_MQCONSUMER_KEY_FILE;//key
|
||||
extern std::string Topic_Reply_Topic;
|
||||
extern std::string Topic_Reply_Tag;
|
||||
extern std::string Topic_Reply_Key;
|
||||
|
||||
extern std::string WEB_FILEUPLOAD;
|
||||
extern std::string WEB_FILEDOWNLOAD;
|
||||
|
||||
bool showinshellflag =false;
|
||||
|
||||
@@ -143,6 +170,10 @@ static QMap<QString, json_block_data*> json_data_map;//CZY 2023-08-17 ww 2023年
|
||||
static QMap<QString, json_block_data*> json_flicker_data_map;//CZY 2023-09-11 展Map,用于保存各条线路的闪变数据
|
||||
static QMap<QString, json_block_data*> json_pst_data_map;//CZY 2023-09-11 展Map,用于保存各条线路的闪变数据
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////lnk20260310文件控制
|
||||
pthread_mutex_t g_file_req_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
std::list<file_dir_req_t*> g_file_dir_req_list;
|
||||
|
||||
bool is_blank(const std::string& str)
|
||||
{
|
||||
for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
|
||||
@@ -581,7 +612,8 @@ std::string extractDataJson(const char* inputJson) {
|
||||
// 提取 "guid" 部分
|
||||
cJSON* guidstr = cJSON_GetObjectItem(messageBody, "guid");
|
||||
if (guidstr == NULL || guidstr->type != cJSON_String) {
|
||||
std::cerr << "'guid' is missing or is not an array" << std::endl;
|
||||
std::cerr << "'guid' is missing or is not an string" << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return "";
|
||||
}
|
||||
@@ -593,12 +625,19 @@ std::string extractDataJson(const char* inputJson) {
|
||||
cJSON* data = cJSON_GetObjectItem(messageBody, "data");
|
||||
if (data == NULL || data->type != cJSON_Array) {
|
||||
std::cerr << "'data' is missing or is not an array" << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return "";
|
||||
}
|
||||
|
||||
// 创建新的 JSON 数组对象,只包含 "data" 部分
|
||||
cJSON* newJson = cJSON_CreateArray(); // 创建一个新的数组
|
||||
if (newJson == NULL) {
|
||||
std::cerr << "Failed to create new JSON array" << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return "";
|
||||
}
|
||||
|
||||
// 将 "data" 数组中的元素逐个添加到新数组中
|
||||
cJSON* dataItem = NULL;
|
||||
@@ -610,6 +649,7 @@ std::string extractDataJson(const char* inputJson) {
|
||||
char* newJsonString = cJSON_Print(newJson);
|
||||
if (newJsonString == NULL) {
|
||||
std::cerr << "Error printing new JSON" << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
cJSON_Delete(newJson);
|
||||
return "";
|
||||
@@ -620,6 +660,7 @@ std::string extractDataJson(const char* inputJson) {
|
||||
|
||||
// 清理内存
|
||||
free(newJsonString);
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
cJSON_Delete(newJson);
|
||||
|
||||
@@ -684,10 +725,12 @@ bool parseJsonMessageRT(const std::string& body, std::string& devSeries, std::st
|
||||
|
||||
} else {
|
||||
std::cerr << "Missing expected fields in JSON message." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root); // 清理 JSON 对象
|
||||
return true;
|
||||
}
|
||||
@@ -917,6 +960,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* guidstr = cJSON_GetObjectItem(messageBody, "guid");
|
||||
if (guidstr == nullptr) {
|
||||
std::cout << "Missing 'guid' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -928,6 +972,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* code = cJSON_GetObjectItem(messageBody, "code");
|
||||
if (code == nullptr) {
|
||||
std::cout << "Missing 'code' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -938,6 +983,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* processNo = cJSON_GetObjectItem(messageBody, "processNo");
|
||||
if (processNo == nullptr) {
|
||||
std::cout << "Missing 'processNo' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -948,6 +994,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* funtion = cJSON_GetObjectItem(messageBody, "fun");
|
||||
if (funtion == nullptr) {
|
||||
std::cout << "Missing 'fun' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -957,6 +1004,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* front = cJSON_GetObjectItem(messageBody, "frontType");
|
||||
if (front == nullptr) {
|
||||
std::cout << "Missing 'frontType' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -965,6 +1013,7 @@ int parse_set(const std::string& json_str) {
|
||||
|
||||
if (index_value != g_front_seg_index && g_front_seg_index != 0) {
|
||||
std::cout << "msg index:"<< index_value <<"doesnt match self index:" << g_front_seg_index << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
@@ -979,6 +1028,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* num = cJSON_GetObjectItem(messageBody, "processNum");
|
||||
if (num == nullptr) {
|
||||
std::cout << "Missing 'processNum' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1037,6 +1087,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* onlyip = cJSON_GetObjectItem(messageBody, "ip");
|
||||
if (onlyip == nullptr) {
|
||||
std::cout << "Missing 'ip' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1046,6 +1097,7 @@ int parse_set(const std::string& json_str) {
|
||||
cJSON* index_item = cJSON_GetObjectItem(messageBody, "proindex");
|
||||
if (index_item == nullptr) {
|
||||
std::cout << "Missing 'proindex' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1078,6 +1130,7 @@ int parse_set(const std::string& json_str) {
|
||||
}
|
||||
|
||||
// 释放 JSON 对象
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
@@ -1167,9 +1220,13 @@ std::string prepare_update(const std::string& code_str, const terminal& json_dat
|
||||
add_indent(xmlStream, indentLevel);
|
||||
xmlStream << "<processNo>" << json_data.processNo << "</processNo>" << std::endl;
|
||||
|
||||
//lnk20250305
|
||||
add_indent(xmlStream, indentLevel);
|
||||
xmlStream << "<devKey>" << json_data.dev_key << "</devKey>" << std::endl;
|
||||
|
||||
add_indent(xmlStream, indentLevel);
|
||||
xmlStream << "<loglevel>" << json_data.log_level << "</loglevel>" << std::endl;
|
||||
|
||||
// monitorData 部分
|
||||
for (int i = 0; json_data.line[i].monitor_id[0] != '\0'; i++) {
|
||||
const monitor& monitor = json_data.line[i];
|
||||
@@ -1202,6 +1259,9 @@ std::string prepare_update(const std::string& code_str, const terminal& json_dat
|
||||
add_indent(xmlStream, indentLevel);
|
||||
xmlStream << "<status>" << monitor.status << "</status>" << std::endl;
|
||||
|
||||
add_indent(xmlStream, indentLevel);
|
||||
xmlStream << "<loglevel>" << monitor.log_level << "</loglevel>" << std::endl;
|
||||
|
||||
indentLevel--;
|
||||
add_indent(xmlStream, indentLevel);
|
||||
xmlStream << "</monitorData>" << std::endl;
|
||||
@@ -1309,6 +1369,7 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* guidstr = cJSON_GetObjectItem(messageBody, "guid");
|
||||
if (guidstr == nullptr) {
|
||||
std::cout << "Missing 'guid' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1320,6 +1381,7 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* code = cJSON_GetObjectItem(messageBody, "code");
|
||||
if (code == nullptr) {
|
||||
std::cout << "Missing 'code' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1331,6 +1393,7 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* process = cJSON_GetObjectItem(messageBody, "processNo");
|
||||
if (process == nullptr) {
|
||||
std::cout << "Missing 'processNo' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1342,6 +1405,7 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* idstr = cJSON_GetObjectItem(messageBody, "id");
|
||||
if (idstr == nullptr) {
|
||||
std::cout << "Missing 'id' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1352,6 +1416,7 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* levelstr = cJSON_GetObjectItem(messageBody, "level");
|
||||
if (levelstr == nullptr) {
|
||||
std::cout << "Missing 'level' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1362,6 +1427,7 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* gradestr = cJSON_GetObjectItem(messageBody, "grade");
|
||||
if (gradestr == nullptr) {
|
||||
std::cout << "Missing 'grade' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1372,16 +1438,18 @@ int parse_log(const std::string& json_str) {
|
||||
cJSON* logtypestr = cJSON_GetObjectItem(messageBody, "logtype");
|
||||
if (logtypestr == nullptr) {
|
||||
std::cout << "Missing 'logtype' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string logtype = logtypestr->valuestring;
|
||||
int logtype = logtypestr->valueint;
|
||||
|
||||
// 获取 frontType 字段
|
||||
cJSON* frontTypestr = cJSON_GetObjectItem(messageBody, "frontType");
|
||||
if (frontTypestr == nullptr) {
|
||||
std::cout << "Missing 'frontType' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1390,12 +1458,14 @@ int parse_log(const std::string& json_str) {
|
||||
|
||||
if (processNo != g_front_seg_index) {
|
||||
std::cout << "msg index:"<< processNo <<"doesnt match self index:" << g_front_seg_index << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (frontType != subdir) {
|
||||
std::cout << "msg frontType:"<< frontType <<"doesnt match self frontType:" << subdir << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
@@ -1413,13 +1483,16 @@ int parse_log(const std::string& json_str) {
|
||||
//校验数据
|
||||
if((level == "terminal" || level == "measurepoint") &&
|
||||
(grade == "NORMAL" || grade == "DEBUG") &&
|
||||
(logtype == "com" || logtype == "data") &&
|
||||
(!id.empty() && !is_blank(id))){
|
||||
|
||||
//开启开关
|
||||
//开启日志临时开关
|
||||
process_log_command(id, level, grade, logtype);
|
||||
|
||||
}
|
||||
else if((level == "measurepoint") && (grade == "TRACE") && (!id.empty() && !is_blank(id))){ //数据追踪
|
||||
//打开监测点数据追踪开关
|
||||
process_trace_command(id,5); //5表示追踪次数
|
||||
}
|
||||
else{
|
||||
std::cout << "type doesnt match" <<std::endl;
|
||||
//记录warm
|
||||
@@ -1429,6 +1502,7 @@ int parse_log(const std::string& json_str) {
|
||||
}
|
||||
|
||||
// 释放 JSON 对象
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
@@ -1469,6 +1543,7 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
cJSON* code = cJSON_GetObjectItem(messageBody, "code");
|
||||
if (code == nullptr) {
|
||||
std::cout << "Missing 'code' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1480,6 +1555,7 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
cJSON* process = cJSON_GetObjectItem(messageBody, "processNo");
|
||||
if (process == nullptr) {
|
||||
std::cout << "Missing 'processNo' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1491,6 +1567,7 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
cJSON* guidstr = cJSON_GetObjectItem(messageBody, "guid");
|
||||
if (guidstr == nullptr) {
|
||||
std::cout << "Missing 'guid' in JSON." << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 1;
|
||||
}
|
||||
@@ -1501,6 +1578,7 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
//进程号为0的进程处理所有台账更新消息
|
||||
if (process_No != g_front_seg_index && g_front_seg_index !=0) {
|
||||
std::cout << "msg index:"<< process_No <<"doesnt match self index:" << g_front_seg_index << std::endl;
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
@@ -1611,6 +1689,25 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
else
|
||||
std::strncpy(json_data.timestamp, "N/A", sizeof(json_data.timestamp) - 1);
|
||||
|
||||
|
||||
//添加loglevel字段
|
||||
cJSON* loglevel = cJSON_GetObjectItem(item, "loglevel"); // log_level
|
||||
int tmp_level = -1;
|
||||
// 先读取 loglevel
|
||||
if (loglevel && loglevel->type == cJSON_Number) {
|
||||
tmp_level = loglevel->valueint;
|
||||
}
|
||||
else if (loglevel && loglevel->type == cJSON_String) {
|
||||
tmp_level = atoi(loglevel->valuestring);
|
||||
}
|
||||
// 判断是否合法 (0~3)
|
||||
if (tmp_level >= 0 && tmp_level <= 3) {
|
||||
json_data.log_level = tmp_level;
|
||||
} else {
|
||||
json_data.log_level = 1; // 默认日志级别
|
||||
}
|
||||
printf("terminal log_level: %d\n", json_data.log_level);
|
||||
|
||||
// monitorData 解析,填充到 line 数组中
|
||||
cJSON* monitorData = cJSON_GetObjectItem(item, "monitorData");
|
||||
if (monitorData != nullptr && monitorData->type == cJSON_Array) {
|
||||
@@ -1626,6 +1723,27 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
else
|
||||
std::strncpy(monitor_data.monitor_id, "N/A", sizeof(monitor_data.monitor_id) - 1);
|
||||
|
||||
//添加loglevel字段
|
||||
cJSON* loglevel = cJSON_GetObjectItem(monitor_item, "loglevel"); // log_level
|
||||
int tmp_level = -1;
|
||||
// 先尝试读取 loglevel
|
||||
if (loglevel && loglevel->type == cJSON_Number) {
|
||||
tmp_level = loglevel->valueint;
|
||||
}
|
||||
else if (loglevel && loglevel->type == cJSON_String) {
|
||||
tmp_level = atoi(loglevel->valuestring);
|
||||
}
|
||||
// 判断是否合法 (0~3)
|
||||
if (tmp_level >= 0 && tmp_level <= 3) {
|
||||
monitor_data.log_level = tmp_level;
|
||||
}
|
||||
else if (json_data.log_level >= 0 && json_data.log_level <= 3) { // 继承 terminal loglevel
|
||||
monitor_data.log_level = json_data.log_level;
|
||||
}
|
||||
else {
|
||||
monitor_data.log_level = 1; // 默认 warn
|
||||
}
|
||||
|
||||
cJSON* monitor_name = cJSON_GetObjectItem(monitor_item, "name"); // monitor_name
|
||||
if (monitor_name && monitor_name->type == cJSON_String)
|
||||
std::strncpy(monitor_data.monitor_name, monitor_name->valuestring, sizeof(monitor_data.monitor_name) - 1);
|
||||
@@ -1723,10 +1841,492 @@ int parse_control(const std::string& json_str, const std::string& output_dir) {
|
||||
}
|
||||
|
||||
// 释放 JSON 对象
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//处理文件请求
|
||||
static int ParseFileDirReq(const char *body, file_dir_req_t *req)
|
||||
{
|
||||
if (body == NULL || req == NULL)
|
||||
return -1;
|
||||
|
||||
cJSON *root = cJSON_Parse(body);
|
||||
if (root == NULL)
|
||||
return -1;
|
||||
|
||||
cJSON *guid = cJSON_GetObjectItem(root, "guid");
|
||||
cJSON *frontid = cJSON_GetObjectItem(root, "frontid");
|
||||
cJSON *processNo = cJSON_GetObjectItem(root, "ProcessNo");
|
||||
cJSON *devid = cJSON_GetObjectItem(root, "devid");
|
||||
cJSON *type = cJSON_GetObjectItem(root, "type");
|
||||
cJSON *path = cJSON_GetObjectItem(root, "Path");
|
||||
|
||||
if (!guid || guid->type != cJSON_String ||
|
||||
!frontid || frontid->type != cJSON_String ||
|
||||
!processNo || processNo->type != cJSON_Number ||
|
||||
!devid || devid->type != cJSON_String ||
|
||||
!type || type->type != cJSON_Number ||
|
||||
!path || path->type != cJSON_String)
|
||||
{
|
||||
cJSON_Delete(root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(req, 0, sizeof(file_dir_req_t));
|
||||
snprintf(req->guid, sizeof(req->guid), "%s", guid->valuestring);
|
||||
snprintf(req->frontid, sizeof(req->frontid), "%s", frontid->valuestring);
|
||||
req->processNo = processNo->valueint;
|
||||
snprintf(req->devid, sizeof(req->devid), "%s", devid->valuestring);
|
||||
req->type = type->valueint;
|
||||
snprintf(req->path, sizeof(req->path), "%s", path->valuestring);
|
||||
req->create_time = time(NULL);
|
||||
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PushFileDirReq(const file_dir_req_t *req)
|
||||
{
|
||||
if (req == NULL)
|
||||
return;
|
||||
|
||||
file_dir_req_t *node = new file_dir_req_t;
|
||||
*node = *req;
|
||||
|
||||
pthread_mutex_lock(&g_file_req_mutex);
|
||||
|
||||
g_file_dir_req_list.push_back(node);
|
||||
pthread_mutex_unlock(&g_file_req_mutex);
|
||||
}
|
||||
|
||||
static file_dir_req_t* PopMatchedFileDirReq(const char *terminal_id)
|
||||
{
|
||||
if (terminal_id == NULL || terminal_id[0] == 0)
|
||||
return NULL;
|
||||
|
||||
file_dir_req_t *match = NULL;
|
||||
|
||||
pthread_mutex_lock(&g_file_req_mutex);
|
||||
|
||||
for (std::list<file_dir_req_t*>::iterator it = g_file_dir_req_list.begin();
|
||||
it != g_file_dir_req_list.end();
|
||||
++it)
|
||||
{
|
||||
file_dir_req_t *node = *it;
|
||||
if (node != NULL && strcmp(node->devid, terminal_id) == 0)
|
||||
{
|
||||
match = node;
|
||||
g_file_dir_req_list.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_file_req_mutex);
|
||||
return match;
|
||||
}
|
||||
|
||||
static std::string BuildFileDirRespJsonEx(const file_dir_req_t *req,
|
||||
char **names,
|
||||
const char **itemTypes,
|
||||
int *itemSizes,
|
||||
int itemNum,
|
||||
int result)
|
||||
{
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON *dirInfo = cJSON_CreateArray();
|
||||
|
||||
cJSON_AddStringToObject(root, "guid", req ? req->guid : "");
|
||||
cJSON_AddStringToObject(root, "frontid", req ? req->frontid : "");
|
||||
cJSON_AddNumberToObject(root, "processNo", req ? req->processNo : 0);
|
||||
cJSON_AddStringToObject(root, "devid", req ? req->devid : "");
|
||||
cJSON_AddNumberToObject(root, "type", req ? req->type : 0);
|
||||
|
||||
for (int i = 0; i < itemNum; ++i)
|
||||
{
|
||||
cJSON *item = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(item, "name", (names && names[i]) ? names[i] : "");
|
||||
cJSON_AddStringToObject(item, "type", (itemTypes && itemTypes[i]) ? itemTypes[i] : "file");
|
||||
cJSON_AddNumberToObject(item, "size", (itemSizes ? itemSizes[i] : 1));
|
||||
cJSON_AddItemToArray(dirInfo, item);
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(root, "dirInfo", dirInfo);
|
||||
cJSON_AddNumberToObject(root, "result", result);
|
||||
|
||||
char *json = cJSON_PrintUnformatted(root);
|
||||
std::string jsonStr = json ? json : "";
|
||||
|
||||
if (json) free(json);
|
||||
cJSON_Delete(root);
|
||||
return jsonStr;
|
||||
}
|
||||
|
||||
static std::string BuildFileDirRespJson(const file_dir_req_t *req,
|
||||
char **filenames,
|
||||
int filenum,
|
||||
int result)
|
||||
{
|
||||
if (filenum <= 0)
|
||||
return BuildFileDirRespJsonEx(req, NULL, NULL, NULL, 0, result);
|
||||
|
||||
const char **types = new const char*[filenum];
|
||||
int *sizes = new int[filenum];
|
||||
|
||||
for (int i = 0; i < filenum; ++i)
|
||||
{
|
||||
types[i] = "dir";
|
||||
sizes[i] = 1;
|
||||
}
|
||||
|
||||
std::string jsonStr = BuildFileDirRespJsonEx(req, filenames, types, sizes, filenum, result);
|
||||
|
||||
delete [] types;
|
||||
delete [] sizes;
|
||||
return jsonStr;
|
||||
}
|
||||
|
||||
static std::string BuildSingleFileRespJson(const file_dir_req_t *req,
|
||||
const char *name,
|
||||
const char *itemType,
|
||||
int size,
|
||||
int result)
|
||||
{
|
||||
char *names[1];
|
||||
const char *types[1];
|
||||
int sizes[1];
|
||||
|
||||
if (name == NULL || result != 0)
|
||||
{
|
||||
return BuildFileDirRespJsonEx(req, NULL, NULL, NULL, 0, result);
|
||||
}
|
||||
|
||||
names[0] = (char *)name;
|
||||
types[0] = (itemType ? itemType : "file");
|
||||
sizes[0] = size;
|
||||
|
||||
return BuildFileDirRespJsonEx(req, names, types, sizes, 1, result);
|
||||
}
|
||||
|
||||
////////////////////////下载
|
||||
static const char* GetFileNameOnly(const char* fullpath)
|
||||
{
|
||||
if (fullpath == NULL)
|
||||
return "";
|
||||
|
||||
const char* p1 = strrchr(fullpath, '/');
|
||||
const char* p2 = strrchr(fullpath, '\\');
|
||||
const char* p = p1 > p2 ? p1 : p2;
|
||||
|
||||
return (p ? p + 1 : fullpath);
|
||||
}
|
||||
|
||||
static int MakeDirRecursive(const char* dirPath)
|
||||
{
|
||||
if (dirPath == NULL || dirPath[0] == '\0')
|
||||
return -1;
|
||||
|
||||
char tmp[512] = {0};
|
||||
snprintf(tmp, sizeof(tmp), "%s", dirPath);
|
||||
|
||||
int len = strlen(tmp);
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
/* 去掉末尾 '/' */
|
||||
if (tmp[len - 1] == '/')
|
||||
tmp[len - 1] = '\0';
|
||||
|
||||
for (char* p = tmp + 1; *p; ++p)
|
||||
{
|
||||
if (*p == '/')
|
||||
{
|
||||
*p = '\0';
|
||||
if (access(tmp, F_OK) != 0)
|
||||
{
|
||||
if (mkdir(tmp, 0777) != 0 && errno != EEXIST)
|
||||
{
|
||||
printf("mkdir failed: %s, err=%s\n", tmp, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (access(tmp, F_OK) != 0)
|
||||
{
|
||||
if (mkdir(tmp, 0777) != 0 && errno != EEXIST)
|
||||
{
|
||||
printf("mkdir failed: %s, err=%s\n", tmp, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SafePathName(const char* src, char* dst, size_t dstSize)
|
||||
{
|
||||
if (dst == NULL || dstSize == 0)
|
||||
return;
|
||||
|
||||
dst[0] = '\0';
|
||||
|
||||
if (src == NULL)
|
||||
return;
|
||||
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; src[i] != '\0' && j + 1 < dstSize; ++i)
|
||||
{
|
||||
char c = src[i];
|
||||
if ((c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
c == '.' || c == '_' || c == '-')
|
||||
{
|
||||
dst[j++] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[j++] = '_';
|
||||
}
|
||||
}
|
||||
dst[j] = '\0';
|
||||
}
|
||||
|
||||
static int BuildTempLocalPath(char* outPath,
|
||||
size_t outSize,
|
||||
chnl_usr_t* chnl_usr,
|
||||
const char* remotePath)
|
||||
{
|
||||
if (outPath == NULL || outSize == 0 || chnl_usr == NULL)
|
||||
return -1;
|
||||
|
||||
const char* fileName = GetFileNameOnly(remotePath);
|
||||
if (fileName == NULL || fileName[0] == '\0')
|
||||
fileName = "tmp_file.dat";
|
||||
|
||||
const char* ipStr = chnl_usr->ip_str;
|
||||
if (ipStr == NULL || ipStr[0] == '\0')
|
||||
ipStr = "unknown_ip";
|
||||
|
||||
char safeIp[128] = {0};
|
||||
SafePathName(ipStr, safeIp, sizeof(safeIp));
|
||||
|
||||
char dirPath[512] = {0};
|
||||
snprintf(dirPath, sizeof(dirPath), "/tmp/%s", safeIp);
|
||||
|
||||
/* 目录不存在则创建 */
|
||||
if (MakeDirRecursive(dirPath) != 0)
|
||||
{
|
||||
printf("BuildTempLocalPath mkdir failed: %s\n", dirPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(outPath, outSize, "%s/%s", dirPath, fileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HandleTypeDownloadAndUpload(chnl_usr_t* chnl_usr,
|
||||
file_dir_req_t* req,
|
||||
std::string& jsonString)
|
||||
{
|
||||
if (chnl_usr == NULL || req == NULL || chnl_usr->net_info == NULL)
|
||||
return -1;
|
||||
|
||||
char localpath[512] = {0};
|
||||
if (BuildTempLocalPath(localpath, sizeof(localpath), chnl_usr, req->path) != 0)
|
||||
{
|
||||
DIY_ERRORLOG_CODE("process", LOG_CODE_TRANSIENT_COMM,
|
||||
"【ERROR】构造本地临时路径失败 devid=%s path=%s",
|
||||
req->devid, req->path);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req, NULL, "file", 1, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ST_RET ret = mms_getFile(chnl_usr->net_info,
|
||||
(ST_CHAR*)localpath,
|
||||
(ST_CHAR*)req->path,
|
||||
3 * g_pt61850app->mmsOpTimeout);
|
||||
|
||||
if (ret != SD_SUCCESS)
|
||||
{
|
||||
DIY_ERRORLOG_CODE("process", LOG_CODE_TRANSIENT_COMM,
|
||||
"【ERROR】装置文件下载失败 devid=%s, rem=%s, ret=0x%X",
|
||||
req->devid, req->path, ret);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req, NULL, "file", 1, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DIY_INFOLOG("process",
|
||||
"【NORMAL】装置文件下载成功 devid=%s, rem=%s, local=%s",
|
||||
req->devid, req->path, localpath);
|
||||
|
||||
char wavepath[512] = {0};
|
||||
SendFileWeb(WEB_FILEUPLOAD, localpath, req->path, wavepath);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req,
|
||||
(wavepath[0] != 0 ? wavepath : req->path),
|
||||
"file",
|
||||
1,
|
||||
0);
|
||||
remove(localpath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////传输
|
||||
static int HandleTypeTransferToDevice(chnl_usr_t* chnl_usr,
|
||||
file_dir_req_t* req,
|
||||
std::string& jsonString)
|
||||
{
|
||||
if (chnl_usr == NULL || req == NULL || chnl_usr->net_info == NULL)
|
||||
return -1;
|
||||
|
||||
char localpath[512] = {0};
|
||||
if (BuildTempLocalPath(localpath, sizeof(localpath), chnl_usr, req->path) != 0)
|
||||
{
|
||||
DIY_ERRORLOG_CODE("process", LOG_CODE_TRANSIENT_COMM,
|
||||
"【ERROR】构造本地临时路径失败 devid=%s path=%s",
|
||||
req->devid, req->path);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req, NULL, "file", 1, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dlRet = DownloadFileWeb(WEB_FILEDOWNLOAD, req->path, localpath);
|
||||
if (dlRet != 0)
|
||||
{
|
||||
DIY_ERRORLOG_CODE("process", LOG_CODE_TRANSIENT_COMM,
|
||||
"【ERROR】Web 文件下载失败 devid=%s, path=%s",
|
||||
req->devid, req->path);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req, NULL, "file", 1, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DIY_INFOLOG("process",
|
||||
"【NORMAL】Web 文件下载成功 devid=%s, webpath=%s, local=%s",
|
||||
req->devid, req->path, localpath);
|
||||
|
||||
char destfilename[512] = {0};
|
||||
const char* fileName = GetFileNameOnly(req->path);
|
||||
snprintf(destfilename, sizeof(destfilename), "/etc/%s",
|
||||
(fileName && fileName[0]) ? fileName : "tmp_file.dat");
|
||||
|
||||
ST_RET ret = mms_mvla_obtfile(chnl_usr->net_info,
|
||||
(ST_CHAR*)localpath,
|
||||
(ST_CHAR*)destfilename,
|
||||
3 * g_pt61850app->mmsOpTimeout);
|
||||
|
||||
if (ret != SD_SUCCESS)
|
||||
{
|
||||
DIY_ERRORLOG_CODE("process", LOG_CODE_TRANSIENT_COMM,
|
||||
"【ERROR】文件传送到装置失败 devid=%s, src=%s, dest=%s, ret=0x%X",
|
||||
req->devid, localpath, destfilename, ret);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req, NULL, "file", 1, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DIY_INFOLOG("process",
|
||||
"【NORMAL】文件传送到装置成功 devid=%s, src=%s, dest=%s",
|
||||
req->devid, localpath, destfilename);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req,
|
||||
destfilename,
|
||||
"file",
|
||||
1,
|
||||
0);
|
||||
|
||||
remove(localpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HandleFileDirReqForChannel(chnl_usr_t *chnl_usr)
|
||||
{
|
||||
if (chnl_usr == NULL || chnl_usr->chnl == NULL || chnl_usr->chnl->ied == NULL)
|
||||
return;
|
||||
|
||||
ied_t *ied = chnl_usr->chnl->ied;
|
||||
ied_usr_t *ied_usr = GET_IEDEXT_ADDR(ied);
|
||||
if (ied_usr == NULL)
|
||||
return;
|
||||
|
||||
if (ied_usr->terminal_id[0] == 0)
|
||||
return;
|
||||
|
||||
file_dir_req_t *req = PopMatchedFileDirReq(ied_usr->terminal_id);
|
||||
if (req == NULL)
|
||||
return; // 当前连接没有文件请求
|
||||
|
||||
DIY_INFOLOG("process",
|
||||
"【NORMAL】处理文件请求 terminal_id=%s type=%d path=%s",
|
||||
req->devid, req->type, req->path);
|
||||
|
||||
std::string jsonString;
|
||||
int handleRet = -1;
|
||||
|
||||
if (req->type == 0)
|
||||
{
|
||||
/* 目录查询 */
|
||||
char **filenames = NULL;
|
||||
int filenum = 0;
|
||||
|
||||
ST_RET ret = mms_mvla_fdir(chnl_usr->net_info,
|
||||
(ST_CHAR*)req->path,
|
||||
3 * g_pt61850app->mmsOpTimeout,
|
||||
&filenames,
|
||||
&filenum,
|
||||
g_pt61850app->tmp_pool);
|
||||
|
||||
jsonString = BuildFileDirRespJson(req,
|
||||
filenames,
|
||||
filenum,
|
||||
(ret == SD_SUCCESS) ? 0 : ret);
|
||||
|
||||
DIY_INFOLOG("process",
|
||||
"【NORMAL】目录请求处理完成 terminal_id=%s ret=0x%X filenum=%d",
|
||||
req->devid, ret, filenum);
|
||||
|
||||
handleRet = (ret == SD_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
else if (req->type == 1)
|
||||
{
|
||||
/* 装置下载到本地,再上传 Web */
|
||||
handleRet = HandleTypeDownloadAndUpload(chnl_usr, req, jsonString);
|
||||
}
|
||||
else if (req->type == 2)
|
||||
{
|
||||
/* Web 下载到本地,再传送到装置 /etc */
|
||||
handleRet = HandleTypeTransferToDevice(chnl_usr, req, jsonString);
|
||||
}
|
||||
else
|
||||
{
|
||||
DIY_WARNLOG("process",
|
||||
"【WARN】未知文件请求类型 type=%d devid=%s path=%s",
|
||||
req->type, req->devid, req->path);
|
||||
|
||||
jsonString = BuildSingleFileRespJson(req, NULL, "file", 1, 1);//1是失败
|
||||
handleRet = -1;
|
||||
}
|
||||
|
||||
/* 统一回 Kafka */
|
||||
Ckafka_data_t dir_info;
|
||||
dir_info.strTopic = QString::fromStdString(Topic_Reply_Topic);
|
||||
dir_info.strText = QString::fromStdString(jsonString);
|
||||
|
||||
kafka_data_list_mutex.lock();
|
||||
kafka_data_list.append(dir_info);
|
||||
kafka_data_list_mutex.unlock();
|
||||
|
||||
delete req;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1759,6 +2359,19 @@ int find_mp_index_from_mp_id(std::string line)
|
||||
|
||||
}
|
||||
|
||||
char* find_mp_name_from_mp_id(const char* mp_id)
|
||||
{
|
||||
LD_info_t* LD_info = NULL;
|
||||
LD_info = find_LD_info_only_from_mp_id((char*)mp_id);
|
||||
if(LD_info == NULL){
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
return LD_info->name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int myMessageCallbackrtdata(CPushConsumer* consumer, CMessageExt* msg)
|
||||
{
|
||||
if(INITFLAG != 1)return 1;//防止崩溃
|
||||
@@ -1985,6 +2598,44 @@ int myMessageCallbackrecall(CPushConsumer* consumer, CMessageExt* msg)
|
||||
return E_CONSUME_SUCCESS;
|
||||
}
|
||||
|
||||
int myMessageCallbackfile(CPushConsumer* consumer, CMessageExt* msg)
|
||||
{
|
||||
if (INITFLAG != 1) return 1;
|
||||
|
||||
if (msg == NULL) {
|
||||
std::cerr << "Received null message." << std::endl;
|
||||
return E_RECONSUME_LATER;
|
||||
}
|
||||
|
||||
const char* body = GetMessageBody(msg);
|
||||
const char* key = GetMessageKeys(msg);
|
||||
|
||||
if (body == NULL) {
|
||||
std::cerr << "Message body is NULL." << std::endl;
|
||||
return E_RECONSUME_LATER;
|
||||
}
|
||||
|
||||
DIY_INFOLOG("process","【NORMAL】前置消费topic:%s_%s的文件控制消息",
|
||||
FRONT_INST.c_str(), G_MQCONSUMER_TOPIC_FILE.c_str());
|
||||
|
||||
std::cout << "file Callback received message: " << body << std::endl;
|
||||
std::cout << "Message Key: " << (key ? key : "N/A") << std::endl;
|
||||
|
||||
file_dir_req_t req;
|
||||
if (ParseFileDirReq(body, &req) != 0)
|
||||
{
|
||||
DIY_WARNLOG("process", "【WARN】文件控制消息解析失败: %s", body);
|
||||
return E_CONSUME_SUCCESS;
|
||||
}
|
||||
|
||||
PushFileDirReq(&req);
|
||||
|
||||
DIY_INFOLOG("process",
|
||||
"【NORMAL】文件目录请求已入队 guid=%s devid=%s path=%s",
|
||||
req.guid, req.devid, req.path);
|
||||
|
||||
return E_CONSUME_SUCCESS;
|
||||
}
|
||||
|
||||
void mqconsumerThread::run()
|
||||
{
|
||||
@@ -1997,6 +2648,9 @@ void mqconsumerThread::run()
|
||||
std::vector<Subscription> subscriptions;
|
||||
// 初始化消费者1 //lnk20241230只有实时进程会订阅实时topic,不订阅实时topic的进程无法触发实时数据
|
||||
if(g_node_id == THREE_SECS_DATA_BASE_NODE_ID){
|
||||
|
||||
//lnk20260310添加文件管理
|
||||
subscriptions.push_back(Subscription(std::string(FRONT_INST) + "_" + G_MQCONSUMER_TOPIC_FILE, G_MQCONSUMER_TAG_FILE, myMessageCallbackfile));
|
||||
subscriptions.push_back(Subscription(std::string(FRONT_INST) + "_" + G_MQCONSUMER_TOPIC_RT, G_MQCONSUMER_TAG_RT, myMessageCallbackrtdata));
|
||||
}
|
||||
|
||||
@@ -2348,8 +3002,11 @@ int json_block_create_data(char monid_char[], char* mms_str, double v, int flick
|
||||
if (pdata != NULL)
|
||||
{
|
||||
pdata->mms_str_map.insert(QString::fromAscii(mms_str), v);
|
||||
if (strstr(mms_str, "MMXU2$MX$PhV"))
|
||||
if (strstr(mms_str, "MMXU2$MX$PhV")){
|
||||
pdata->data_have_statistic = 1;
|
||||
printf("---------- json_block_create_data: mp_id= %s ,mms_str=%s value=%fkV----------\n", monid_char, mms_str, v);
|
||||
}
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -670,6 +670,8 @@ struct monitor // 监测点台账
|
||||
char timestamp[64];
|
||||
char status[255];
|
||||
|
||||
int log_level;//日志级别,0:ERROR,1:WARN,2:NORMAL,3:DEBUG
|
||||
|
||||
};
|
||||
struct terminal // 终端台账
|
||||
{
|
||||
@@ -692,6 +694,7 @@ struct terminal // 终端台账
|
||||
char timestamp[64];
|
||||
monitor line[10]; // 最多 10 个监测点
|
||||
|
||||
int log_level;//日志级别,0:ERROR,1:WARN,2:NORMAL,3:DEBUG
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -24,12 +24,9 @@
|
||||
|
||||
#include "appender.h"
|
||||
|
||||
#define LOGTYPE_COM 1
|
||||
#define LOGTYPE_DATA 2
|
||||
|
||||
struct TypedLogger {
|
||||
log4cplus::Logger logger;
|
||||
int logtype;
|
||||
int code;
|
||||
TypedLogger();
|
||||
TypedLogger(const log4cplus::Logger& l, int t);
|
||||
};
|
||||
@@ -47,7 +44,7 @@ struct DebugSwitch {
|
||||
void set_level(int level);
|
||||
void enable_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;
|
||||
@@ -71,11 +68,14 @@ log4cplus::Logger init_logger(const std::string& full_name,
|
||||
const std::string& base_file,
|
||||
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();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////lnk20260306数据追踪
|
||||
void process_trace_command(const std::string& id, int times);
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
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 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, ...);
|
||||
|
||||
// ====================== ★新增:线程局部变量透传 code ======================
|
||||
@@ -159,7 +159,8 @@ typedef enum LogCode {
|
||||
LOG_CODE_LOG_REQUEST = 405, /* 日志请求 */
|
||||
LOG_CODE_REPORT = 500, /* 报告处理 */
|
||||
LOG_CODE_COMM = 600, /* 通讯状态 */
|
||||
LOG_CODE_SPACE_ALARM = 700 /* 空间告警 */
|
||||
LOG_CODE_SPACE_ALARM = 700, /* 空间告警 */
|
||||
LOG_CODE_DEVICE = 800 /* 设备告警 */
|
||||
} LogCode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -152,6 +152,8 @@ int parse_model_cfg_web();
|
||||
void SOEFileWeb(char* localpath,char* cloudpath,char* wavepath);
|
||||
const char* get_front_msg_from_subdir();
|
||||
|
||||
char* find_mp_name_from_mp_id(const char* mp_id);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct {
|
||||
@@ -160,6 +162,7 @@ typedef struct {
|
||||
char WavePhasicB[64];
|
||||
char WavePhasicC[64];
|
||||
char UnitOfTimeUnit[64];
|
||||
char TypeOfData[64];
|
||||
char ValueOfTimeUnit[64];
|
||||
char WaveTimeFlag[64];
|
||||
char IEDname[64];
|
||||
@@ -168,6 +171,21 @@ typedef struct {
|
||||
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@ extern apr_pool_t* g_init_pool;
|
||||
extern int g_DevFlag; //日志配置中读取的参数,暂无特定使用lnk20250121
|
||||
|
||||
extern int IED_COUNT;
|
||||
extern int RECALL_ONLY_FLAG; //lnk20260309添加一个全局变量,标志是否只运行补招程序
|
||||
|
||||
//lnk20250115end
|
||||
|
||||
@@ -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("Timestamp: %s\n", is_empty(mon->timestamp) ? "N/A" : mon->timestamp);
|
||||
printf("Status: %s\n", is_empty(mon->status) ? "N/A" : mon->status);
|
||||
printf("Log Level: %d\n", mon->log_level);
|
||||
}
|
||||
|
||||
// 打印 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("Port: %s\n", is_empty(tmnl->port) ? "N/A" : tmnl->port);
|
||||
printf("Timestamp: %s\n", is_empty(tmnl->timestamp) ? "N/A" : tmnl->timestamp);
|
||||
printf("Log Level: %d\n", tmnl->log_level);
|
||||
|
||||
// 打印监测点信息,如果监测点字段为空,则打印 N/A
|
||||
int i;
|
||||
@@ -1416,11 +1419,14 @@ void check_ledger_update()//lnk20250113
|
||||
//调试用
|
||||
print_trigger_update_xml(trigger_ledger_update_xml);
|
||||
|
||||
//处理台账更新加台账锁lnk20250114
|
||||
//pthread_mutex_lock(&mtx); printf("ledgerupdate hold lock !!!!!!!!!!!");
|
||||
process_ledger_update(trigger_ledger_update_xml); //台账更新
|
||||
//pthread_mutex_unlock(&mtx); printf("ledgerupdate free lock !!!!!!!!!!!");
|
||||
|
||||
//处理台账更新添加控制标志
|
||||
if (RECALL_ONLY_FLAG != 1 || (g_node_id != STAT_DATA_BASE_NODE_ID)) {
|
||||
process_ledger_update(trigger_ledger_update_xml); //台账更新
|
||||
}
|
||||
else{
|
||||
printf("only process recall config, skip ledger update\n");
|
||||
DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】当前配置为仅日志模式,统计数据进程跳过台账更新");
|
||||
}
|
||||
}
|
||||
|
||||
// 使用完后释放动态分配的内存
|
||||
@@ -1545,6 +1551,9 @@ void CheckAllConnectedChannel()
|
||||
|
||||
if(chnl_usr->m_state == CHANNEL_CONNECTED)
|
||||
{
|
||||
if(g_node_id == THREE_SECS_DATA_BASE_NODE_ID) {
|
||||
HandleFileDirReqForChannel(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))
|
||||
|
||||
@@ -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
|
||||
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_usr_t* ied_usr = GET_IEDEXT_ADDR(ied);
|
||||
|
||||
@@ -1457,6 +1457,29 @@ ST_VOID u_mvl_ident_ind (MVL_IND_PEND *indCtrl)
|
||||
|
||||
/************************************************************************/
|
||||
/* 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_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 */
|
||||
|
||||
@@ -24,6 +24,7 @@ extern int SOCKET_PORT;
|
||||
extern int G_TEST_FLAG;
|
||||
extern int g_front_seg_index;
|
||||
extern int g_front_seg_num;
|
||||
extern int RECALL_ONLY_FLAG; //lnk20260309添加一个全局变量,标志是否只运行补招程序
|
||||
|
||||
#include "../rocketmq/SimpleProducer.h"
|
||||
#include "../cfg_parse/custom_printf.h"//lnk20250225
|
||||
@@ -187,42 +188,45 @@ apr_status_t init_rdb()
|
||||
init_config();
|
||||
GetServerIndexFromDB();
|
||||
|
||||
rv = parse_device_cfg_web();
|
||||
if (rv != APR_SUCCESS) {
|
||||
echo_errg("Parsed device config xml file with error,try to run! \n");
|
||||
//只有补招运行时,统计不读取台账和模型
|
||||
if (RECALL_ONLY_FLAG != 1 || (g_node_id != STAT_DATA_BASE_NODE_ID)) {
|
||||
rv = parse_device_cfg_web();
|
||||
if (rv != APR_SUCCESS) {
|
||||
echo_errg("Parsed device config xml file with error,try to run! \n");
|
||||
|
||||
//char buf[256];
|
||||
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
//log_error("process", buf);
|
||||
DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
//char buf[256];
|
||||
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
//log_error("process", buf);
|
||||
DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//台账读取过后初始化各级的日志
|
||||
init_loggers();
|
||||
|
||||
rv = parse_model_cfg_web();
|
||||
if (rv != APR_SUCCESS) {//不可能
|
||||
echo_errg("Parsed model with error,try to run! \n");
|
||||
//台账读取过后初始化各级的日志
|
||||
init_loggers();
|
||||
|
||||
//char buf[256];
|
||||
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
//log_error("process", buf);
|
||||
DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
rv = parse_model_cfg_web();
|
||||
if (rv != APR_SUCCESS) {//不可能
|
||||
echo_errg("Parsed model with error,try to run! \n");
|
||||
|
||||
return rv;
|
||||
}
|
||||
//char buf[256];
|
||||
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
//log_error("process", buf);
|
||||
DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
|
||||
Set_xml_nodeinfo();//解析xml模型
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = parse_rpt_log_ini();//报告块初始化
|
||||
if (rv != APR_SUCCESS) {
|
||||
echo_errg("Failed to parse report log define ini file! \n");
|
||||
Set_xml_nodeinfo();//解析xml模型
|
||||
|
||||
DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
rv = parse_rpt_log_ini();//报告块初始化
|
||||
if (rv != APR_SUCCESS) {
|
||||
echo_errg("Failed to parse report log define ini file! \n");
|
||||
|
||||
return rv;
|
||||
DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (app_get_private_config(g_my_conf_fname) != APR_SUCCESS) {
|
||||
|
||||
@@ -255,6 +255,9 @@ struct LD_info_t{
|
||||
rptinfo_t **rptinfo; /**< rptinfo_t* 数组 */
|
||||
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 terminal_code[256];//CZY 2023-08-20 终端编码
|
||||
//int ld_ins;//CZY 2023-08-20 逻辑设备实例号,例:1
|
||||
@@ -273,8 +276,8 @@ struct LD_info_t{
|
||||
int registcount;//lnk20250812
|
||||
bool has_logged_regist;//lnk20250812
|
||||
|
||||
//不使用
|
||||
int iUnitOfTime;//CZY 2023-08-17 WW 2022年12月7日15:43:34 装置上送事件持续时间单位切换(0-ms; 1-s)
|
||||
//不使用
|
||||
int 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小时读取补招日志))
|
||||
//不使用
|
||||
@@ -327,6 +330,8 @@ struct ied_usr_t{
|
||||
void *cookie;
|
||||
double last_call_wavelist_time ; //上次召录波列表时间
|
||||
|
||||
int log_level; //0 ERROR 1 WARN 2 NORMAL 3 DEBUG
|
||||
|
||||
char terminal_id[256];//CZY 2023-08-20 终端id,例:8afaa9a15707483a0157262f8e78077d
|
||||
char org_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);
|
||||
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
|
||||
|
||||
286
set_process.sh
286
set_process.sh
@@ -8,9 +8,216 @@
|
||||
|
||||
#前置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"
|
||||
|
||||
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 "****** `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() {
|
||||
if [ -n "$1" ]; then
|
||||
if [ -n "$1" ] && [ -f "$1" ]; then
|
||||
FILE_SIZE=0
|
||||
FILE_SIZE=$(du "$1" | awk '{print $1}')
|
||||
|
||||
@@ -45,23 +252,46 @@ check_log_file $LOGFILE
|
||||
|
||||
# 定义查找并杀死进程的函数
|
||||
kill_process_by_name() {
|
||||
PROCESS_NAME=$1
|
||||
PID=$(ps -ef | grep "$PROCESS_NAME" | grep -v "grep" | awk '{print $2}')
|
||||
local PROCESS_NAME="$1"
|
||||
local PIDS
|
||||
|
||||
if [ -n "$PID" ]; then
|
||||
echo "Found process '$PROCESS_NAME' with PID: $PID"
|
||||
PIDS=$(ps -ef | grep "$PROCESS_NAME" | grep -v grep | awk '{print $2}')
|
||||
|
||||
if [ -n "$PIDS" ]; then
|
||||
echo "Found process '$PROCESS_NAME' with PID(s): $PIDS"
|
||||
echo "Killing process..."
|
||||
kill -9 $PID
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Process '$PROCESS_NAME' killed successfully."
|
||||
else
|
||||
echo "Failed to kill the process '$PROCESS_NAME'."
|
||||
fi
|
||||
|
||||
for pid in $PIDS; do
|
||||
kill -15 "$pid" 2>/dev/null
|
||||
done
|
||||
|
||||
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
|
||||
done
|
||||
else
|
||||
echo "Process '$PROCESS_NAME' not found."
|
||||
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() {
|
||||
# 功能:reset
|
||||
@@ -71,22 +301,28 @@ handle_reset() {
|
||||
if [ "$2" == "all" ]; then
|
||||
|
||||
# 关闭旧的看门狗进程
|
||||
kill_process_by_name "/FeProject/bin/fe_watchdog"
|
||||
#kill_process_by_name "/FeProject/bin/fe_watchdog"
|
||||
|
||||
# 关闭旧的 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 进程
|
||||
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 进程
|
||||
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 进程
|
||||
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 中的所有进程配置
|
||||
sed -i '/cfg_stat_data/d' /home/pq/FeProject/etc/runtime.cf
|
||||
@@ -119,6 +355,9 @@ handle_reset() {
|
||||
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_soe_comtrade^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
|
||||
|
||||
fi
|
||||
|
||||
# 修改后等一下
|
||||
sleep 1
|
||||
|
||||
# 确保文件已被写入并刷新
|
||||
sync
|
||||
@@ -230,14 +469,13 @@ handle_add() {
|
||||
}
|
||||
|
||||
# 获取当前脚本的进程ID
|
||||
CURRENT_PID=$$
|
||||
|
||||
#CURRENT_PID=$$
|
||||
# 检查是否有其他的set_process.sh脚本正在运行,排除当前脚本
|
||||
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..." >>"$LOGFILE"
|
||||
exit 1
|
||||
fi
|
||||
#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..." >>"$LOGFILE"
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
#脚本应该等待3秒钟
|
||||
sleep 3
|
||||
|
||||
Reference in New Issue
Block a user