add function:upload and download device file ,modify interface function fix memleak
This commit is contained in:
@@ -322,6 +322,11 @@ std::string Topic_Reply_Topic = "";
|
||||
std::string Topic_Reply_Tag = "";
|
||||
std::string Topic_Reply_Key = "";
|
||||
|
||||
//lnk20260310添加文件管理的topic和tag
|
||||
std::string G_MQCONSUMER_TOPIC_FILE = "";//consumer topie
|
||||
std::string G_MQCONSUMER_TAG_FILE = "";//consumer tag
|
||||
std::string G_MQCONSUMER_KEY_FILE = "";//consumer key
|
||||
|
||||
int G_TEST_FLAG = 0;
|
||||
int G_TEST_NUM = 0;
|
||||
int G_TEST_TYPE = 0;
|
||||
@@ -709,6 +714,16 @@ void init_config() {
|
||||
G_CONNECT_TAG = strdup(ba.data());
|
||||
ba = settings.value("RocketMq/CONNECTKey", "").toString().toLatin1();
|
||||
G_CONNECT_KEY = strdup(ba.data());
|
||||
|
||||
//lnk20260310添加文件管理的topic和tag
|
||||
ba = settings.value("RocketMq/ConsumerTopicFile", "").toString().toLatin1();
|
||||
G_MQCONSUMER_TOPIC_FILE = strdup(ba.data());
|
||||
ba = settings.value("RocketMq/ConsumerTagFile", "").toString().toLatin1();
|
||||
G_MQCONSUMER_TAG_FILE = strdup(ba.data());
|
||||
ba = settings.value("RocketMq/ConsumerKeyFile", "").toString().toLatin1();
|
||||
G_MQCONSUMER_KEY_FILE = strdup(ba.data());
|
||||
|
||||
|
||||
//MQ测试
|
||||
G_TEST_FLAG = settings.value("RocketMq/Testflag", 0).toInt();
|
||||
G_TEST_NUM = settings.value("RocketMq/Testnum", 0).toInt();
|
||||
@@ -3198,8 +3213,21 @@ size_t req_reply_http(void* contents, size_t size, size_t nmemb, void* userp) {
|
||||
}
|
||||
|
||||
void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr) {
|
||||
//【修改点1】先校验 ptr 本身,避免空指针解引用
|
||||
if (ptr == NULL) {
|
||||
printf("SendJsonAPI_web error: ptr is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//【修改点2】如果上层传进来的 *ptr 非空,先释放并置空,避免旧内存残留
|
||||
if (*ptr != NULL) {
|
||||
free(*ptr);
|
||||
*ptr = NULL;
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode res;
|
||||
long http_code = 0; //【修改点3】增加 HTTP 状态码
|
||||
|
||||
// 初始化 *ptr 并分配空字符串
|
||||
*ptr = (char*)malloc(1);
|
||||
@@ -3211,8 +3239,8 @@ void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::str
|
||||
|
||||
if (curl) {
|
||||
char url[256];
|
||||
snprintf(url, sizeof(url), "%s?%s", strUrl.c_str(), code);
|
||||
//printf(">>>json %s\n", url);//减少不必要的打印
|
||||
//【修改点5】避免 code 为 NULL 时 snprintf 异常
|
||||
snprintf(url, sizeof(url), "%s?%s", strUrl.c_str(), (code != NULL ? code : ""));
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply_http);
|
||||
@@ -3220,6 +3248,9 @@ void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::str
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
||||
|
||||
//【修改点6】建议禁用 signal,防止多线程里超时信号影响别的线程
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
||||
|
||||
if (!json.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
|
||||
@@ -3231,9 +3262,31 @@ void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::str
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
//【修改点7】先取 HTTP 状态码
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
printf("web failed res code: %s\n", curl_easy_strerror(res));
|
||||
} else {
|
||||
}
|
||||
//【修改点9】即使 curl 成功,HTTP 非 200 也按失败处理
|
||||
/*else if (http_code != 200) {
|
||||
printf("web http failed, http_code: %ld\n", http_code);
|
||||
|
||||
if (*ptr != NULL) {
|
||||
free(*ptr);
|
||||
*ptr = NULL;
|
||||
}
|
||||
}*/
|
||||
//【修改点10】即使 HTTP 200,但返回内容为空串,也按失败处理
|
||||
else if (*ptr == NULL || (*ptr)[0] == '\0') {
|
||||
printf("web response is empty\n");
|
||||
|
||||
if (*ptr != NULL) {
|
||||
free(*ptr);
|
||||
*ptr = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf(">>> web return str: %s \n", *ptr);
|
||||
}
|
||||
|
||||
@@ -3241,70 +3294,14 @@ void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::str
|
||||
curl_easy_cleanup(curl);
|
||||
} else {
|
||||
printf(">>> web curl init failed\n");
|
||||
|
||||
//【修改点11】curl 初始化失败时,也要释放之前分配的空串并置 NULL
|
||||
if (*ptr != NULL) {
|
||||
free(*ptr);
|
||||
*ptr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr) {
|
||||
// curl 初始化
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode res;
|
||||
|
||||
if (curl) {
|
||||
char url[100];
|
||||
sprintf(url, "%s?%s", strUrl.c_str(), code);
|
||||
printf(">>>json %s\n", url);
|
||||
|
||||
// 设置 URL
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
|
||||
// 设置数据接收和写入函数
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply_web);
|
||||
|
||||
// 数据接收
|
||||
std::string resPost0;
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&resPost0);
|
||||
|
||||
// 设置超时时间
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
||||
|
||||
if(json != ""){
|
||||
// 设置 HTTP 方法为 POST
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
|
||||
// 设置 JSON 格式的 body 数据
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
|
||||
}
|
||||
|
||||
// 设置请求头
|
||||
struct curl_slist* headers = NULL;
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
// 执行请求
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
// 检查请求是否成功
|
||||
if (res != CURLE_OK) {
|
||||
printf("web failed res code: %s\n", curl_easy_strerror(res));
|
||||
} else {
|
||||
printf(">>> web return str: %s \n", resPost0.c_str());
|
||||
|
||||
// 分配内存并复制返回结果
|
||||
*ptr = (char*)malloc(resPost0.size() + 1); // 分配足够的内存空间
|
||||
if (*ptr != NULL) {
|
||||
strcpy(*ptr, resPost0.c_str());
|
||||
} else {
|
||||
printf("Memory allocation failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// 清理请求头
|
||||
curl_slist_free_all(headers);
|
||||
} else {
|
||||
printf(">>> web curl init failed");
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}*/
|
||||
|
||||
// 打印 terminal_dev_map 中所有内容的函数
|
||||
void printTerminalDevMap(const QMap<QString, terminal_dev*>& terminal_dev_map) {
|
||||
@@ -3796,90 +3793,23 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
|
||||
cJSON* root = NULL;
|
||||
|
||||
// 发送 API 请求
|
||||
/*SendJsonAPI_web(WEB_DEVICE, "",parm.c_str(), &ptr);
|
||||
|
||||
if (ptr == NULL) {
|
||||
std::cerr << "Error: Received NULL response from SendJsonAPI_web." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 调试用
|
||||
printf("ptr:%s\n", ptr);
|
||||
|
||||
cJSON* root = cJSON_Parse(ptr); //json格式序列化
|
||||
|
||||
int retry = 0;
|
||||
|
||||
if (root == NULL) {
|
||||
printf("web error %s\n", cJSON_GetErrorPtr());
|
||||
|
||||
//重发多次
|
||||
while(root == NULL){
|
||||
// 在重试前释放之前的 ptr 以避免内存泄漏
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
//测试用url参数
|
||||
//SendJsonAPI_web("http://192.168.1.149:8091/powerQuality/getProperties", parm.c_str(), "",&ptr);
|
||||
SendJsonAPI_web(WEB_DEVICE, "",parm.c_str(), &ptr);
|
||||
|
||||
if(ptr == NULL){
|
||||
std::cerr << "Error: Received NULL response from SendJsonAPI_web in retry" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
root = cJSON_Parse(ptr);
|
||||
retry++;
|
||||
if(retry > 3){
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果重试后仍然失败,确保退出前释放任何已分配的内存
|
||||
if (root == NULL) {
|
||||
printf("web error after 3 retry\n");
|
||||
//return 1; // 根据需要返回适当的错误码
|
||||
//三次重试过后尝试读取本地台账文件
|
||||
char* ledger = NULL;
|
||||
read_latest_ledger_file(&ledger);
|
||||
if (ledger != NULL) {
|
||||
root = cJSON_Parse(ledger);
|
||||
free(ledger);
|
||||
}
|
||||
|
||||
//记录上送日志
|
||||
|
||||
//读取台账文件也失败则启用定时器5分钟等待下一次读取台账和文件,不要退出死掉
|
||||
if (root == NULL) {
|
||||
printf("read local ledger failed, wait 5 min to retry...\n");
|
||||
apr_sleep(apr_time_from_sec(300)); // 睡眠 5 分钟
|
||||
|
||||
// 重新请求
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
SendJsonAPI_web(WEB_DEVICE, "", parm.c_str(), &ptr);
|
||||
if (ptr != NULL) {
|
||||
root = cJSON_Parse(ptr);
|
||||
if (root == NULL) {
|
||||
printf("still failed after sleep retry\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
printf("no response after sleep retry\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
//记录上送日志
|
||||
}
|
||||
}*/
|
||||
while (1) {
|
||||
|
||||
//防止泄露lnk20260312
|
||||
if (root != NULL) {
|
||||
cJSON_Delete(root);
|
||||
root = NULL;
|
||||
}
|
||||
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
// 请求接口
|
||||
SendJsonAPI_web(WEB_DEVICE, "", parm.c_str(), &ptr);
|
||||
|
||||
if (ptr != NULL) {
|
||||
if (ptr != NULL && ptr[0] != '\0') {
|
||||
|
||||
// 调试用
|
||||
printf("ptr:%s\n", ptr);
|
||||
@@ -3909,7 +3839,7 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
}
|
||||
|
||||
// 解析失败,尝试重试
|
||||
printf("web error %s\n", cJSON_GetErrorPtr());
|
||||
//printf("web error %s\n", cJSON_GetErrorPtr());
|
||||
retry++;
|
||||
|
||||
if (retry > 3) {
|
||||
@@ -3922,6 +3852,11 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
}
|
||||
|
||||
// 读取本地台账文件
|
||||
if (root != NULL) {
|
||||
cJSON_Delete(root);
|
||||
root = NULL;
|
||||
}
|
||||
|
||||
char* ledger = NULL;
|
||||
read_latest_ledger_file(&ledger);
|
||||
if (ledger != NULL) {
|
||||
@@ -3959,6 +3894,9 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
retry = 0; // 重置 retry 重新开始循环
|
||||
continue;
|
||||
}
|
||||
|
||||
//每次重试等2秒
|
||||
apr_sleep(apr_time_from_sec(2));
|
||||
}
|
||||
|
||||
// 获取 "code" 和 "msg"
|
||||
@@ -4011,64 +3949,79 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
cJSON* id = cJSON_GetObjectItem(item, "id"); // terminal_id
|
||||
if (id && id->type == cJSON_String) strncpy(dev->terminal_id, id->valuestring, sizeof(dev->terminal_id) - 1);
|
||||
else strncpy(dev->terminal_id, "N/A", sizeof(dev->terminal_id) - 1);
|
||||
dev->terminal_id[sizeof(dev->terminal_id) - 1] = '\0';
|
||||
|
||||
cJSON* ip = cJSON_GetObjectItem(item, "ip"); // addr_str
|
||||
if (ip && ip->type == cJSON_String) strncpy(dev->addr_str, ip->valuestring, sizeof(dev->addr_str) - 1);
|
||||
else strncpy(dev->addr_str, "N/A", sizeof(dev->addr_str) - 1);
|
||||
dev->addr_str[sizeof(dev->addr_str) - 1] = '\0';
|
||||
|
||||
cJSON* terminalCode = cJSON_GetObjectItem(item, "name"); // terminal_code
|
||||
if (terminalCode && terminalCode->type == cJSON_String) strncpy(dev->terminal_code, terminalCode->valuestring, sizeof(dev->terminal_code) - 1);
|
||||
else strncpy(dev->terminal_code, "N/A", sizeof(dev->terminal_code) - 1);
|
||||
dev->terminal_code[sizeof(dev->terminal_code) - 1] = '\0';
|
||||
|
||||
cJSON* orgName = cJSON_GetObjectItem(item, "org_name"); // org_name
|
||||
if (orgName && orgName->type == cJSON_String) strncpy(dev->org_name, orgName->valuestring, sizeof(dev->org_name) - 1);
|
||||
else strncpy(dev->org_name, "N/A", sizeof(dev->org_name) - 1);
|
||||
dev->org_name[sizeof(dev->org_name) - 1] = '\0';
|
||||
|
||||
cJSON* maintName = cJSON_GetObjectItem(item, "maint_name"); // maint_name
|
||||
if (maintName && maintName->type == cJSON_String) strncpy(dev->maint_name, maintName->valuestring, sizeof(dev->maint_name) - 1);
|
||||
else strncpy(dev->maint_name, "N/A", sizeof(dev->maint_name) - 1);
|
||||
dev->maint_name[sizeof(dev->maint_name) - 1] = '\0';
|
||||
|
||||
cJSON* stationName = cJSON_GetObjectItem(item, "stationName"); // station_name
|
||||
if (stationName && stationName->type == cJSON_String) strncpy(dev->station_name, stationName->valuestring, sizeof(dev->station_name) - 1);
|
||||
else strncpy(dev->station_name, "N/A", sizeof(dev->station_name) - 1);
|
||||
dev->station_name[sizeof(dev->station_name) - 1] = '\0';
|
||||
|
||||
cJSON* manufacturer = cJSON_GetObjectItem(item, "manufacturer"); // tmnl_factory
|
||||
if (manufacturer && manufacturer->type == cJSON_String) strncpy(dev->tmnl_factory, manufacturer->valuestring, sizeof(dev->tmnl_factory) - 1);
|
||||
else strncpy(dev->tmnl_factory, "N/A", sizeof(dev->tmnl_factory) - 1);
|
||||
dev->tmnl_factory[sizeof(dev->tmnl_factory) - 1] = '\0';
|
||||
|
||||
cJSON* status = cJSON_GetObjectItem(item, "status"); // tmnl_status
|
||||
if (status && status->type == cJSON_String) strncpy(dev->tmnl_status, status->valuestring, sizeof(dev->tmnl_status) - 1);
|
||||
else strncpy(dev->tmnl_status, "N/A", sizeof(dev->tmnl_status) - 1);
|
||||
dev->tmnl_status[sizeof(dev->tmnl_status) - 1] = '\0';
|
||||
|
||||
cJSON* devType = cJSON_GetObjectItem(item, "devType"); // dev_type
|
||||
if (devType && devType->type == cJSON_String) strncpy(dev->dev_type, devType->valuestring, sizeof(dev->dev_type) - 1);
|
||||
else strncpy(dev->dev_type, "N/A", sizeof(dev->dev_type) - 1);
|
||||
dev->dev_type[sizeof(dev->dev_type) - 1] = '\0';
|
||||
|
||||
cJSON* devKey = cJSON_GetObjectItem(item, "devKey"); // dev_key
|
||||
if (devKey && devKey->type == cJSON_String) strncpy(dev->dev_key, devKey->valuestring, sizeof(dev->dev_key) - 1);
|
||||
else strncpy(dev->dev_key, "N/A", sizeof(dev->dev_key) - 1);
|
||||
dev->dev_key[sizeof(dev->dev_key) - 1] = '\0';
|
||||
|
||||
cJSON* series = cJSON_GetObjectItem(item, "series"); // dev_series
|
||||
if (series && series->type == cJSON_String) strncpy(dev->dev_series, series->valuestring, sizeof(dev->dev_series) - 1);
|
||||
else strncpy(dev->dev_series, "N/A", sizeof(dev->dev_series) - 1);
|
||||
dev->dev_series[sizeof(dev->dev_series) - 1] = '\0';
|
||||
|
||||
//lnk20250210台账进程号
|
||||
cJSON* processNo = cJSON_GetObjectItem(item, "processNo"); // processNo转为字符串
|
||||
if (processNo && processNo->type == cJSON_Number) snprintf(dev->processNo, sizeof(dev->processNo), "%d", processNo->valueint);
|
||||
else strncpy(dev->processNo, "N/A", sizeof(dev->processNo) - 1);
|
||||
dev->processNo[sizeof(dev->processNo) - 1] = '\0';
|
||||
|
||||
//20250513进程数量
|
||||
cJSON* maxProcessNum = cJSON_GetObjectItem(item, "maxProcessNum"); // maxProcessNum转为字符串
|
||||
if (maxProcessNum && maxProcessNum->type == cJSON_Number) snprintf(dev->maxProcessNum, sizeof(dev->maxProcessNum), "%d", maxProcessNum->valueint);
|
||||
else strncpy(dev->maxProcessNum, "N/A", sizeof(dev->maxProcessNum) - 1);
|
||||
dev->maxProcessNum[sizeof(dev->maxProcessNum) - 1] = '\0';
|
||||
|
||||
cJSON* port = cJSON_GetObjectItem(item, "port"); // port
|
||||
if (port && port->type == cJSON_String) strncpy(dev->port, port->valuestring, sizeof(dev->port) - 1);
|
||||
else strncpy(dev->port, "N/A", sizeof(dev->port) - 1);
|
||||
dev->port[sizeof(dev->port) - 1] = '\0';
|
||||
|
||||
cJSON* updateTime = cJSON_GetObjectItem(item, "updateTime"); // timestamp
|
||||
if (updateTime && updateTime->type == cJSON_String) strncpy(dev->timestamp, updateTime->valuestring, sizeof(dev->timestamp) - 1);
|
||||
else strncpy(dev->timestamp, "N/A", sizeof(dev->timestamp) - 1);
|
||||
dev->timestamp[sizeof(dev->timestamp) - 1] = '\0';
|
||||
|
||||
cJSON* logLevel = cJSON_GetObjectItem(item, "log_level"); // log_level
|
||||
int tmp_level = -1;
|
||||
@@ -4100,29 +4053,35 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
cJSON* monitor_id = cJSON_GetObjectItem(monitorItem, "id"); // monitor_id
|
||||
if (monitor_id && monitor_id->type == cJSON_String) strncpy(dev->line[j].monitor_id, monitor_id->valuestring, sizeof(dev->line[j].monitor_id) - 1);
|
||||
else strncpy(dev->line[j].monitor_id, "N/A", sizeof(dev->line[j].monitor_id) - 1);
|
||||
dev->line[j].monitor_id[sizeof(dev->line[j].monitor_id) - 1] = '\0';
|
||||
|
||||
cJSON* monitor_name = cJSON_GetObjectItem(monitorItem, "name"); // monitor_name
|
||||
if (monitor_name && monitor_name->type == cJSON_String) strncpy(dev->line[j].monitor_name, monitor_name->valuestring, sizeof(dev->line[j].monitor_name) - 1);
|
||||
else strncpy(dev->line[j].monitor_name, "N/A", sizeof(dev->line[j].monitor_name) - 1);
|
||||
dev->line[j].monitor_name[sizeof(dev->line[j].monitor_name) - 1] = '\0';
|
||||
|
||||
cJSON* lineNo = cJSON_GetObjectItem(monitorItem, "lineNo"); // logical_device_seq
|
||||
if (lineNo && lineNo->type == cJSON_String) strncpy(dev->line[j].logical_device_seq, lineNo->valuestring, sizeof(dev->line[j].logical_device_seq) - 1);
|
||||
else strncpy(dev->line[j].logical_device_seq, "N/A", sizeof(dev->line[j].logical_device_seq) - 1);
|
||||
dev->line[j].logical_device_seq[sizeof(dev->line[j].logical_device_seq) - 1] = '\0';
|
||||
|
||||
cJSON* voltageLevel = cJSON_GetObjectItem(monitorItem, "voltageLevel"); // voltage_level
|
||||
if (voltageLevel && voltageLevel->type == cJSON_String) strncpy(dev->line[j].voltage_level, voltageLevel->valuestring, sizeof(dev->line[j].voltage_level) - 1);
|
||||
else strncpy(dev->line[j].voltage_level, "N/A", sizeof(dev->line[j].voltage_level) - 1);
|
||||
dev->line[j].voltage_level[sizeof(dev->line[j].voltage_level) - 1] = '\0';
|
||||
|
||||
cJSON* ptType = cJSON_GetObjectItem(monitorItem, "ptType"); // terminal_connect
|
||||
if (ptType && ptType->type == cJSON_String) strncpy(dev->line[j].terminal_connect, ptType->valuestring, sizeof(dev->line[j].terminal_connect) - 1);
|
||||
else strncpy(dev->line[j].terminal_connect, "N/A", sizeof(dev->line[j].terminal_connect) - 1);
|
||||
dev->line[j].terminal_connect[sizeof(dev->line[j].terminal_connect) - 1] = '\0';
|
||||
|
||||
// 添加监测点状态
|
||||
cJSON* monitorstatus = cJSON_GetObjectItem(monitorItem, "status"); // status
|
||||
if (monitorstatus && monitorstatus->type == cJSON_String) strncpy(dev->line[j].status, monitorstatus->valuestring, sizeof(dev->line[j].status) - 1);
|
||||
else strncpy(dev->line[j].status, "N/A", sizeof(dev->line[j].status) - 1);
|
||||
dev->line[j].status[sizeof(dev->line[j].status) - 1] = '\0';
|
||||
|
||||
cJSON* logLevel_m = cJSON_GetObjectItem(item, "log_level"); // log_level
|
||||
cJSON* logLevel_m = cJSON_GetObjectItem(monitorItem, "log_level"); // log_level
|
||||
int tmp_level = -1;
|
||||
if (logLevel_m && logLevel_m->type == cJSON_Number) {
|
||||
tmp_level = logLevel_m->valueint;
|
||||
@@ -4134,7 +4093,7 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
if (tmp_level >= 0 && tmp_level <= 3) {
|
||||
dev->line[j].log_level = tmp_level;
|
||||
} else {
|
||||
dev->line[j].log_level = 1; // 默认 WARN
|
||||
dev->line[j].log_level = dev->log_level; // 默认 WARN
|
||||
}
|
||||
printf("line[%d].log_level: %d\n", j, dev->line[j].log_level);
|
||||
|
||||
@@ -4145,6 +4104,9 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
// 准备键
|
||||
QString key = QString(dev->terminal_id);//用id而不是code区分:有的code存在乱码
|
||||
|
||||
//lnk20260312防止内存泄漏
|
||||
bool inserted = false;
|
||||
|
||||
// 检查是否存在重复键
|
||||
if (terminal_dev_map->contains(key)) {
|
||||
std::cerr << "Duplicate terminal_code found: " << key.toStdString() << std::endl;
|
||||
@@ -4159,23 +4121,31 @@ int terminal_ledger_web(QMap<QString, terminal_dev*>* terminal_dev_map,
|
||||
if(atoi(dev->processNo) == g_front_seg_index || g_front_seg_index == 0){//lnk20250210匹配进程号
|
||||
//调试用
|
||||
std::cout<< "process num match" << std::endl;
|
||||
terminal_dev_map->insert(key, dev);}//后续修改为只有进程号匹配上index才录入当前进程
|
||||
terminal_dev_map->insert(key, dev);
|
||||
inserted = true;
|
||||
}//后续修改为只有进程号匹配上index才录入当前进程
|
||||
} else {
|
||||
// 插入新的 terminal_dev 对象
|
||||
if(atoi(dev->processNo) == g_front_seg_index || g_front_seg_index == 0){//lnk20250210匹配进程号
|
||||
//调试用
|
||||
std::cout<< "process num match" << std::endl;
|
||||
terminal_dev_map->insert(key, dev);}//后续修改为只有进程号匹配上index才录入当前进程
|
||||
terminal_dev_map->insert(key, dev);
|
||||
inserted = true;
|
||||
}//后续修改为只有进程号匹配上index才录入当前进程
|
||||
//调试用
|
||||
//std::cout << "i = " << i << std::endl;
|
||||
//std::cout << "terminal_dev_map.size:" << terminal_dev_map->size() << std::endl;
|
||||
}//如果出现重复项,日志要有体现方便排查
|
||||
|
||||
|
||||
if (!inserted) {
|
||||
delete dev;
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//读取台账有效,保存或更新到台账文件20250513lnk
|
||||
if(g_node_id == STAT_DATA_BASE_NODE_ID && g_front_seg_index == 1){
|
||||
if(g_node_id == STAT_DATA_BASE_NODE_ID && g_front_seg_index == 1 && ptr != NULL && ptr[0] != '\0'){
|
||||
save_ledger_json(ptr);
|
||||
//普通日志,更新本地台账
|
||||
}
|
||||
@@ -4621,14 +4591,17 @@ int parse_model_web(QMap<QString, icd_model*>* icd_model_map,const std::vector<s
|
||||
|
||||
char* ptr=NULL;
|
||||
|
||||
//测试用url参数
|
||||
//SendJsonAPI_web("http://192.168.1.149:8091/powerQuality/getProperties", parm.c_str(), "",&ptr);
|
||||
SendJsonAPI_web(WEB_ICD,"",parm.c_str(),&ptr);
|
||||
|
||||
// 检查 ptr 是否为 NULL,避免 std::string 初始化失败
|
||||
if (ptr == NULL) {
|
||||
// 处理 ptr 为 NULL 的情况,例如日志记录或错误处理
|
||||
std::cout << "Error: Received NULL response"<< std::endl;
|
||||
if (ptr == NULL || ptr[0] == '\0') {
|
||||
std::cout << "Error: Received NULL or empty response" << std::endl;
|
||||
|
||||
//【修改点2】ptr 非空时要释放,避免泄漏
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4649,17 +4622,23 @@ int parse_model_web(QMap<QString, icd_model*>* icd_model_map,const std::vector<s
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
//测试用url参数
|
||||
//SendJsonAPI_web("http://192.168.1.149:8091/powerQuality/getProperties", parm.c_str(), "",&ptr);
|
||||
|
||||
sleep(2);
|
||||
|
||||
SendJsonAPI_web(WEB_ICD,"",parm.c_str(),&ptr);
|
||||
if(ptr == NULL){
|
||||
if(ptr == NULL || ptr[0] == '\0'){
|
||||
retry++;if(retry>3)break;
|
||||
continue;
|
||||
}
|
||||
root = cJSON_Parse(ptr);
|
||||
retry++;if(retry>3)break;
|
||||
retry++;
|
||||
if(retry>3)break;
|
||||
}
|
||||
if (root == NULL) {
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
printf("web error %s\n", cJSON_GetErrorPtr());
|
||||
return 1;
|
||||
}
|
||||
@@ -4669,8 +4648,8 @@ int parse_model_web(QMap<QString, icd_model*>* icd_model_map,const std::vector<s
|
||||
cJSON* msgItem = cJSON_GetObjectItem(root, "msg");
|
||||
|
||||
// 使用 std::string 获取值
|
||||
std::string code = (codeItem != NULL) ? codeItem->valuestring : "not found";
|
||||
std::string msg = (msgItem != NULL) ? msgItem->valuestring : "not found";
|
||||
std::string code = (codeItem != NULL && codeItem->valuestring != NULL) ? codeItem->valuestring : "not found";
|
||||
std::string msg = (msgItem != NULL && msgItem->valuestring != NULL) ? msgItem->valuestring : "not found";
|
||||
|
||||
// 打印结果
|
||||
std::cout << "code: " << code << std::endl;
|
||||
@@ -4680,30 +4659,72 @@ int parse_model_web(QMap<QString, icd_model*>* icd_model_map,const std::vector<s
|
||||
if (data && data->type == cJSON_Array) {
|
||||
cJSON* item;
|
||||
cJSON_ArrayForEach(item, data) {
|
||||
icd_model* model = new icd_model;
|
||||
icd_model* model = new icd_model();
|
||||
|
||||
cJSON* id = cJSON_GetObjectItem(item, "id");//model_id
|
||||
if (id && id->type == cJSON_String) strncpy(model->model_id, id->valuestring, sizeof(model->model_id) - 1);
|
||||
|
||||
if (id && id->type == cJSON_String) {
|
||||
strncpy(model->model_id, id->valuestring, sizeof(model->model_id) - 1);
|
||||
model->model_id[sizeof(model->model_id) - 1] = '\0';
|
||||
}
|
||||
|
||||
cJSON* fileName = cJSON_GetObjectItem(item, "fileName");//file_name
|
||||
if (fileName && fileName->type == cJSON_String) strncpy(model->file_name, fileName->valuestring, sizeof(model->file_name) - 1);
|
||||
if (fileName && fileName->type == cJSON_String) {
|
||||
strncpy(model->file_name, fileName->valuestring, sizeof(model->file_name) - 1);
|
||||
model->file_name[sizeof(model->file_name) - 1] = '\0';
|
||||
}
|
||||
|
||||
cJSON* filePath = cJSON_GetObjectItem(item, "filePath");//新增
|
||||
if (filePath && filePath->type == cJSON_String) strncpy(model->file_path, filePath->valuestring, sizeof(model->file_path) - 1);
|
||||
if (filePath && filePath->type == cJSON_String) {
|
||||
strncpy(model->file_path, filePath->valuestring, sizeof(model->file_path) - 1);
|
||||
model->file_path[sizeof(model->file_path) - 1] = '\0';
|
||||
}
|
||||
|
||||
cJSON* devType = cJSON_GetObjectItem(item, "devType");//tmnl_type
|
||||
if (devType && devType->type == cJSON_String) strncpy(model->tmnl_type, devType->valuestring, sizeof(model->tmnl_type) - 1);
|
||||
if (devType && devType->type == cJSON_String) {
|
||||
strncpy(model->tmnl_type, devType->valuestring, sizeof(model->tmnl_type) - 1);
|
||||
model->tmnl_type[sizeof(model->tmnl_type) - 1] = '\0';
|
||||
}
|
||||
|
||||
cJSON* updateTime = cJSON_GetObjectItem(item, "updateTime");//timestamp
|
||||
if (updateTime && updateTime->type == cJSON_String) strncpy(model->timestamp, updateTime->valuestring, sizeof(model->timestamp) - 1);
|
||||
if (updateTime && updateTime->type == cJSON_String) {
|
||||
strncpy(model->timestamp, updateTime->valuestring, sizeof(model->timestamp) - 1);
|
||||
model->timestamp[sizeof(model->timestamp) - 1] = '\0';
|
||||
}
|
||||
|
||||
// 添加到 QMap
|
||||
icd_model_map->insert(model->model_id, model);
|
||||
if (model->model_id[0] != '\0') {
|
||||
icd_model_map->insert(model->model_id, model);
|
||||
} else {
|
||||
delete model;
|
||||
model = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
std::cout << "Error: 'data' is not an array or is missing" << std::endl;
|
||||
cJSON_Delete(root);
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cJSON_GetArraySize(data) == 0) {
|
||||
std::cout << "Error: 'data' array is empty" << std::endl;
|
||||
cJSON_Delete(root);
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
cJSON_Delete(root);
|
||||
free(ptr); // 如果 SendJsonAPI_web 分配了内存,记得释放
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
return 0; // 确保函数有返回值
|
||||
}
|
||||
@@ -4776,7 +4797,7 @@ int parse_model_cfg_web()
|
||||
char tmnl_type[64];
|
||||
char file_name[128];
|
||||
char file_path[128];
|
||||
otl_datetime timestamp;
|
||||
otl_datetime timestamp = {};
|
||||
|
||||
// 遍历终端台账容器
|
||||
QMap<QString, icd_model*>::iterator it;
|
||||
@@ -4791,6 +4812,12 @@ int parse_model_cfg_web()
|
||||
strncpy(file_path, value->file_path, sizeof(file_path) - 1);
|
||||
strncpy(file_name, value->file_name, sizeof(file_name) - 1);
|
||||
|
||||
//lnk20260311
|
||||
model_id[sizeof(model_id) - 1] = '\0';
|
||||
tmnl_type[sizeof(tmnl_type) - 1] = '\0';
|
||||
file_path[sizeof(file_path) - 1] = '\0';
|
||||
file_name[sizeof(file_name) - 1] = '\0';
|
||||
|
||||
std::cout << "model_id" << model_id << std::endl;
|
||||
std::cout << "tmnl_type" << tmnl_type << std::endl;
|
||||
std::cout << "filepath" << file_path << std::endl;
|
||||
@@ -5445,6 +5472,84 @@ void SOEFileWeb_test()
|
||||
SOEFileWeb(localpath,cloudpath,wavepath);
|
||||
std::cout << "wavepath:" << wavepath << std::endl;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////lnk20260310
|
||||
static size_t write_file_callback(void* ptr, size_t size, size_t nmemb, void* stream)
|
||||
{
|
||||
FILE* fp = (FILE*)stream;
|
||||
return fwrite(ptr, size, nmemb, fp);
|
||||
}
|
||||
/*
|
||||
* 从 WEB_FILEDOWNLOAD 下载 path 对应的文件到 localpath
|
||||
* 成功返回 0,失败返回 -1
|
||||
*/
|
||||
int DownloadFileWeb(const std::string& strUrl,
|
||||
const char* remotePath,
|
||||
const char* localpath)
|
||||
{
|
||||
if (remotePath == NULL || localpath == NULL)
|
||||
return -1;
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
std::cerr << "curl init failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* fp = fopen(localpath, "wb");
|
||||
if (fp == NULL)
|
||||
{
|
||||
std::cerr << "open local file failed: " << localpath << std::endl;
|
||||
curl_easy_cleanup(curl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* encodedPath = curl_easy_escape(curl, remotePath, 0);
|
||||
if (encodedPath == NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
curl_easy_cleanup(curl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string fullUrl = strUrl;
|
||||
if (fullUrl.find('?') == std::string::npos)
|
||||
fullUrl += "?path=";
|
||||
else
|
||||
fullUrl += "&path=";
|
||||
fullUrl += encodedPath;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
long http_code = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
curl_free(encodedPath);
|
||||
fclose(fp);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res != CURLE_OK)
|
||||
{
|
||||
std::cerr << "DownloadFileWeb failed: " << curl_easy_strerror(res) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (http_code != 200)
|
||||
{
|
||||
std::cerr << "DownloadFileWeb http code: " << http_code << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*/////////////////////////////////////////////////////////lnk10-24根据web接口修改/////////////////////////////////////////////////////////////*/
|
||||
/*封装C可调用的台账更新函数 */////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -2931,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
|
||||
{
|
||||
@@ -2952,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响应
|
||||
@@ -3459,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】前置重发暂态事件成功");
|
||||
|
||||
@@ -3478,7 +3475,7 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
|
||||
// 删除文件
|
||||
remove(fileList[i].fileName.c_str());
|
||||
|
||||
free(j_r);
|
||||
cJSON_Delete(j_r);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3524,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;
|
||||
}
|
||||
@@ -3567,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 字符串
|
||||
|
||||
// 发送到暂态接口
|
||||
@@ -3575,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/)
|
||||
@@ -3604,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);
|
||||
//后续处理
|
||||
}
|
||||
}
|
||||
@@ -3623,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;
|
||||
@@ -3652,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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1316,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;
|
||||
}
|
||||
@@ -1327,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;
|
||||
}
|
||||
@@ -1338,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;
|
||||
}
|
||||
@@ -1349,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;
|
||||
}
|
||||
@@ -1359,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;
|
||||
}
|
||||
@@ -1369,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;
|
||||
}
|
||||
@@ -1379,6 +1438,7 @@ 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;
|
||||
}
|
||||
@@ -1389,6 +1449,7 @@ int parse_log(const std::string& json_str) {
|
||||
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;
|
||||
}
|
||||
@@ -1397,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;
|
||||
}
|
||||
@@ -1439,6 +1502,7 @@ int parse_log(const std::string& json_str) {
|
||||
}
|
||||
|
||||
// 释放 JSON 对象
|
||||
cJSON_Delete(messageBody);
|
||||
cJSON_Delete(root);
|
||||
return 0;
|
||||
}
|
||||
@@ -1479,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;
|
||||
}
|
||||
@@ -1490,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;
|
||||
}
|
||||
@@ -1501,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;
|
||||
}
|
||||
@@ -1511,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;
|
||||
}
|
||||
@@ -1773,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;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -2048,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()
|
||||
{
|
||||
@@ -2060,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));
|
||||
}
|
||||
|
||||
|
||||
@@ -171,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
|
||||
|
||||
@@ -1551,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))
|
||||
|
||||
@@ -1546,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 */
|
||||
|
||||
@@ -532,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
|
||||
|
||||
@@ -51,11 +51,13 @@ kill_process_by_name() {
|
||||
if [ -n "$PID" ]; then
|
||||
echo "Found process '$PROCESS_NAME' with PID: $PID"
|
||||
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'."
|
||||
kill -15 $PID
|
||||
sleep 3
|
||||
|
||||
PID2=$(ps -ef | grep "$PROCESS_NAME" | grep -v "grep" | awk '{print $2}')
|
||||
if [ -n "$PID2" ]; then
|
||||
echo "Process still exists, force kill: $PID2"
|
||||
kill -9 $PID2
|
||||
fi
|
||||
else
|
||||
echo "Process '$PROCESS_NAME' not found."
|
||||
@@ -86,7 +88,7 @@ handle_reset() {
|
||||
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_soe_comtrade"
|
||||
|
||||
#关闭进程后等待一段时间,防止端口占用
|
||||
#sleep 5
|
||||
sleep 1
|
||||
|
||||
# 清空 runtime.cf 中的所有进程配置
|
||||
sed -i '/cfg_stat_data/d' /home/pq/FeProject/etc/runtime.cf
|
||||
@@ -119,6 +121,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
|
||||
|
||||
Reference in New Issue
Block a user