完成pqdif文件匹配和获取

This commit is contained in:
lnk
2026-07-23 15:46:10 +08:00
parent 9f74ada894
commit 57b4e65627

View File

@@ -2058,13 +2058,28 @@ static ST_RET Write_Named_Var(LD_info_t *LD_info,chnl_usr_t *chnl_usr,char* VarN
* 2. 只下载最近一个完整周期内、且测点序号匹配的 .pqd 文件;
* 3. 下载前检查 /FeProject/data/pqdif/ 下是否已有同名文件,避免重复下载。
*/
/* Current rule:
* - read /PQDIF/ periodically per terminal;
* - parse the .pqd file's own yyyyMMdd_HHmm_period-hours tokens;
* - save valid files into /FeProject/data/pqdif/<ip>/;
* - prevent repeated downloads with /FeProject/data/pqdif/.state/<ip>.downloaded.
*/
#define PQDIF_REMOTE_DIR "/PQDIF/"
#define PQDIF_LOCAL_DIR "/FeProject/data/pqdif"
#define PQDIF_TMP_DIR "/FeProject/data/pqdif/.tmp"
#define PQDIF_STATE_DIR "/FeProject/data/pqdif/.state"
#define PQDIF_AUTO_INTERVAL_HOURS 2
#define PQDIF_SCAN_INTERVAL_MS (60 * 1000)
#define PQDIF_MAX_DEVICE_INDEX 4096
#define PQDIF_MAX_FETCH_PER_SCAN 32
typedef struct {
int cpu_digit;
int period_hours;
time_t start_time;
time_t end_time;
} pqdif_file_interval_t;
static const char* pqdif_basename(const char* filename)
{
const char* base = filename;
@@ -2120,6 +2135,147 @@ static int pqdif_use_interval_end_time(const char* dev_type)
return (dev_type != NULL && strcmp(dev_type, "PS_NET_PQDIF") == 0);
}
/* Parse names such as xxx_LD1_20260720_0000_24.pqd.
* The token before yyyyMMdd supplies the CPU digit; the last numeric token is
* the file period in hours, so 1h/2h/24h files share the same matcher.
*/
static int pqdif_is_digit_token(const char* str, int expect_len)
{
int i;
if (str == NULL)
return FALSE;
for (i = 0; str[i] != '\0'; ++i) {
if (!isdigit((unsigned char)str[i]))
return FALSE;
}
return (i == expect_len);
}
static int pqdif_parse_datetime(const char* date_token, const char* time_token, time_t* out_time)
{
struct tm tm_value;
int year;
int month;
int day;
int hour;
int min;
if (!pqdif_is_digit_token(date_token, 8) || !pqdif_is_digit_token(time_token, 4) || out_time == NULL)
return FALSE;
year = (date_token[0] - '0') * 1000 + (date_token[1] - '0') * 100 +
(date_token[2] - '0') * 10 + (date_token[3] - '0');
month = (date_token[4] - '0') * 10 + (date_token[5] - '0');
day = (date_token[6] - '0') * 10 + (date_token[7] - '0');
hour = (time_token[0] - '0') * 10 + (time_token[1] - '0');
min = (time_token[2] - '0') * 10 + (time_token[3] - '0');
if (month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
return FALSE;
memset(&tm_value, 0, sizeof(tm_value));
tm_value.tm_year = year - 1900;
tm_value.tm_mon = month - 1;
tm_value.tm_mday = day;
tm_value.tm_hour = hour;
tm_value.tm_min = min;
tm_value.tm_sec = 0;
tm_value.tm_isdst = -1;
*out_time = mktime(&tm_value);
return (*out_time != (time_t)-1);
}
static int pqdif_parse_file_interval(const char* filename, const char* dev_type, pqdif_file_interval_t* out_info)
{
char name_buf[256];
char* tokens[32];
char* token;
const char* base;
size_t len;
int token_count = 0;
int i;
if (out_info == NULL)
return FALSE;
memset(out_info, 0, sizeof(*out_info));
if (!pqdif_has_pqd_suffix(filename))
return FALSE;
base = pqdif_basename(filename);
len = strlen(base);
if (len <= 4 || len >= sizeof(name_buf))
return FALSE;
snprintf(name_buf, sizeof(name_buf), "%s", base);
name_buf[len - 4] = '\0';
token = strtok(name_buf, "_");
while (token != NULL && token_count < (int)(sizeof(tokens) / sizeof(tokens[0]))) {
tokens[token_count++] = token;
token = strtok(NULL, "_");
}
for (i = 1; i + 2 < token_count; ++i) {
const char* cpu_token = tokens[i - 1];
const char* date_token = tokens[i];
const char* time_token = tokens[i + 1];
const char* period_token = tokens[i + 2];
size_t cpu_len = strlen(cpu_token);
time_t file_time;
int period_hours;
if (!pqdif_is_digit_token(date_token, 8) || !pqdif_is_digit_token(time_token, 4))
continue;
if (cpu_len == 0 || !isdigit((unsigned char)cpu_token[cpu_len - 1]))
continue;
for (len = 0; period_token[len] != '\0'; ++len) {
if (!isdigit((unsigned char)period_token[len]))
break;
}
if (period_token[len] != '\0')
continue;
period_hours = atoi(period_token);
if (period_hours <= 0 || period_hours > 24 * 366)
continue;
if (!pqdif_parse_datetime(date_token, time_token, &file_time))
continue;
out_info->cpu_digit = cpu_token[cpu_len - 1] - '0';
out_info->period_hours = period_hours;
if (pqdif_use_interval_end_time(dev_type)) {
out_info->end_time = file_time;
out_info->start_time = file_time - period_hours * 3600;
}
else {
out_info->start_time = file_time;
out_info->end_time = file_time + period_hours * 3600;
}
return TRUE;
}
return FALSE;
}
static int pqdif_cpu_matches(int file_cpu_digit, int cpu_no)
{
if (cpu_no <= 0)
return FALSE;
return (file_cpu_digit == (cpu_no % 10));
}
static time_t pqdif_align_interval_start(long long sec)
{
time_t hour_floor;
@@ -2139,8 +2295,16 @@ static time_t pqdif_align_interval_start(long long sec)
static int pqdif_match_interval(const char* filename, int cpu_no, time_t interval_start, const char* dev_type)
{
time_t name_time;
char time_match[64];
pqdif_file_interval_t file_info;
if (!pqdif_parse_file_interval(filename, dev_type, &file_info))
return FALSE;
if (!pqdif_cpu_matches(file_info.cpu_digit, cpu_no))
return FALSE;
return (file_info.start_time <= interval_start && interval_start < file_info.end_time);
#if 0
if (!pqdif_has_pqd_suffix(filename))
return FALSE;
@@ -2159,16 +2323,102 @@ static int pqdif_match_interval(const char* filename, int cpu_no, time_t interva
pqdif_make_time_match(cpu_no, name_time, time_match, sizeof(time_match));
return strstr(filename, time_match) != NULL;
#endif
}
static int pqdif_match_recent_interval(const char* filename, int cpu_no, const char* dev_type)
{
time_t now_time;
time_t interval_start;
pqdif_file_interval_t file_info;
now_time = time(NULL);
interval_start = pqdif_align_interval_start((long long)now_time) - PQDIF_AUTO_INTERVAL_HOURS * 3600;
return pqdif_match_interval(filename, cpu_no, interval_start, dev_type);
if (!pqdif_parse_file_interval(filename, dev_type, &file_info))
return FALSE;
if (!pqdif_cpu_matches(file_info.cpu_digit, cpu_no))
return FALSE;
return (file_info.end_time <= now_time);
}
static int pqdif_match_auto_candidate(const char* filename, int cpu_no, const char* dev_type,
time_t now_time, pqdif_file_interval_t* out_info)
{
pqdif_file_interval_t file_info;
if (!pqdif_parse_file_interval(filename, dev_type, &file_info))
return FALSE;
if (!pqdif_cpu_matches(file_info.cpu_digit, cpu_no))
return FALSE;
if (file_info.end_time > now_time)
return FALSE;
if (out_info != NULL)
*out_info = file_info;
return TRUE;
}
static int pqdif_is_latest_auto_file(char **filenames, int filenum, const char* candidate_name,
int cpu_no, const char* dev_type, time_t now_time)
{
pqdif_file_interval_t best_info;
const char *best_name = NULL;
int have_best = FALSE;
int i;
if (!pqdif_match_auto_candidate(candidate_name, cpu_no, dev_type, now_time, NULL))
return FALSE;
memset(&best_info, 0, sizeof(best_info));
for (i = 0; i < filenum; i++) {
const char *base_name;
pqdif_file_interval_t file_info;
if (filenames[i] == NULL)
continue;
base_name = pqdif_basename(filenames[i]);
if (base_name[0] == '\0')
continue;
if (!pqdif_match_auto_candidate(base_name, cpu_no, dev_type, now_time, &file_info))
continue;
if (!have_best ||
file_info.end_time > best_info.end_time ||
(file_info.end_time == best_info.end_time && file_info.start_time > best_info.start_time) ||
(file_info.end_time == best_info.end_time && file_info.start_time == best_info.start_time &&
best_name != NULL && strcmp(base_name, best_name) > 0)) {
have_best = TRUE;
best_info = file_info;
best_name = base_name;
}
}
return (have_best && best_name != NULL && strcmp(candidate_name, best_name) == 0);
}
static int pqdif_match_recall_range(const char* filename, int cpu_no, long long start_sec, long long end_sec,
const char* dev_type, pqdif_file_interval_t* out_info)
{
pqdif_file_interval_t file_info;
if (!pqdif_parse_file_interval(filename, dev_type, &file_info))
return FALSE;
if (!pqdif_cpu_matches(file_info.cpu_digit, cpu_no))
return FALSE;
if ((long long)file_info.end_time <= start_sec || (long long)file_info.start_time >= end_sec)
return FALSE;
if (out_info != NULL)
*out_info = file_info;
return TRUE;
}
static int pqdif_ensure_local_dir()
@@ -2179,24 +2429,228 @@ static int pqdif_ensure_local_dir()
if (mkdir(PQDIF_LOCAL_DIR, 0777) != 0 && errno != EEXIST)
return SD_FAILURE;
if (mkdir(PQDIF_TMP_DIR, 0777) != 0 && errno != EEXIST)
return SD_FAILURE;
if (mkdir(PQDIF_STATE_DIR, 0777) != 0 && errno != EEXIST)
return SD_FAILURE;
#endif
return SD_SUCCESS;
}
static int pqdif_local_file_exists(const char* filename)
static void pqdif_make_ip_dir_name(const char* ip_str, char* out, size_t out_len)
{
char local_file[512];
size_t i;
size_t j = 0;
if (out == NULL || out_len == 0)
return;
if (ip_str == NULL || ip_str[0] == '\0') {
snprintf(out, out_len, "unknown");
return;
}
for (i = 0; ip_str[i] != '\0' && j + 1 < out_len; ++i) {
unsigned char ch = (unsigned char)ip_str[i];
if (isalnum(ch) || ch == '.' || ch == '-' || ch == '_')
out[j++] = (char)ch;
else
out[j++] = '_';
}
out[j] = '\0';
if (out[0] == '\0')
snprintf(out, out_len, "unknown");
}
static void pqdif_build_device_dirs(chnl_usr_t *chnl_usr, char* local_dir, size_t local_dir_len, char* tmp_dir, size_t tmp_dir_len)
{
char ip_dir[128];
pqdif_make_ip_dir_name(chnl_usr ? chnl_usr->ip_str : NULL, ip_dir, sizeof(ip_dir));
if (local_dir != NULL && local_dir_len > 0)
snprintf(local_dir, local_dir_len, "%s/%s", PQDIF_LOCAL_DIR, ip_dir);
if (tmp_dir != NULL && tmp_dir_len > 0)
snprintf(tmp_dir, tmp_dir_len, "%s/%s", PQDIF_TMP_DIR, ip_dir);
}
static int pqdif_ensure_device_dirs(chnl_usr_t *chnl_usr, char* local_dir, size_t local_dir_len, char* tmp_dir, size_t tmp_dir_len)
{
pqdif_build_device_dirs(chnl_usr, local_dir, local_dir_len, tmp_dir, tmp_dir_len);
if (pqdif_ensure_local_dir() != SD_SUCCESS)
return SD_FAILURE;
#ifdef _OS_UNIX_
if (local_dir == NULL || tmp_dir == NULL)
return SD_FAILURE;
if (mkdir(local_dir, 0777) != 0 && errno != EEXIST)
return SD_FAILURE;
if (mkdir(tmp_dir, 0777) != 0 && errno != EEXIST)
return SD_FAILURE;
#endif
return SD_SUCCESS;
}
static int pqdif_copy_file(const char* src_file, const char* dst_file)
{
FILE *src;
FILE *dst;
char buf[8192];
size_t nread;
int ret = SD_SUCCESS;
if (src_file == NULL || dst_file == NULL || src_file[0] == '\0' || dst_file[0] == '\0')
return SD_FAILURE;
src = fopen(src_file, "rb");
if (src == NULL)
return SD_FAILURE;
dst = fopen(dst_file, "wb");
if (dst == NULL) {
fclose(src);
return SD_FAILURE;
}
while ((nread = fread(buf, 1, sizeof(buf), src)) > 0) {
if (fwrite(buf, 1, nread, dst) != nread) {
ret = SD_FAILURE;
break;
}
}
if (ferror(src))
ret = SD_FAILURE;
if (fclose(dst) != 0)
ret = SD_FAILURE;
fclose(src);
if (ret != SD_SUCCESS)
remove(dst_file);
return ret;
}
static long pqdif_get_local_file_size(const char* filename)
{
FILE *fp;
long size;
if (filename == NULL || filename[0] == '\0')
return -1;
fp = fopen(filename, "rb");
if (fp == NULL)
return -1;
if (fseek(fp, 0, SEEK_END) != 0) {
fclose(fp);
return -1;
}
size = ftell(fp);
fclose(fp);
return size;
}
/* Successful downloads are tracked outside the final data directory. The PQDIF
* reader may delete /FeProject/data/pqdif/<ip>/ files after processing, so the
* final directory must not be used as the duplicate-download ledger.
*/
static void pqdif_build_state_file(chnl_usr_t *chnl_usr, char* state_file, size_t state_file_len)
{
char ip_dir[128];
if (state_file == NULL || state_file_len == 0)
return;
pqdif_make_ip_dir_name(chnl_usr ? chnl_usr->ip_str : NULL, ip_dir, sizeof(ip_dir));
snprintf(state_file, state_file_len, "%s/%s.downloaded", PQDIF_STATE_DIR, ip_dir);
}
static void pqdif_strip_line_end(char* line)
{
size_t len;
if (line == NULL)
return;
len = strlen(line);
while (len > 0 && (line[len - 1] == '\r' || line[len - 1] == '\n' ||
line[len - 1] == ' ' || line[len - 1] == '\t')) {
line[len - 1] = '\0';
len--;
}
}
static int pqdif_download_record_exists(chnl_usr_t *chnl_usr, const char* filename)
{
char state_file[512];
char line[512];
FILE *fp;
const char* base = pqdif_basename(filename);
if (base[0] == '\0')
return FALSE;
snprintf(local_file, sizeof(local_file), "%s/%s", PQDIF_LOCAL_DIR, base);
#ifdef _OS_UNIX_
return access(local_file, F_OK) == 0;
#else
pqdif_build_state_file(chnl_usr, state_file, sizeof(state_file));
fp = fopen(state_file, "r");
if (fp == NULL)
return FALSE;
#endif
while (fgets(line, sizeof(line), fp) != NULL) {
pqdif_strip_line_end(line);
if (strcmp(line, base) == 0) {
fclose(fp);
return TRUE;
}
}
fclose(fp);
return FALSE;
}
static int pqdif_record_download_success(chnl_usr_t *chnl_usr, const char* filename)
{
char state_file[512];
FILE *fp;
const char* base = pqdif_basename(filename);
int ret = SD_SUCCESS;
if (base[0] == '\0')
return SD_FAILURE;
if (pqdif_download_record_exists(chnl_usr, base))
return SD_SUCCESS;
if (pqdif_ensure_local_dir() != SD_SUCCESS)
return SD_FAILURE;
pqdif_build_state_file(chnl_usr, state_file, sizeof(state_file));
fp = fopen(state_file, "a");
if (fp == NULL)
return SD_FAILURE;
if (fprintf(fp, "%s\n", base) < 0)
ret = SD_FAILURE;
if (fflush(fp) != 0)
ret = SD_FAILURE;
if (fclose(fp) != 0)
ret = SD_FAILURE;
return ret;
}
static void pqdif_build_remote_filename(const char* dir_filename, char* out, size_t out_len)
@@ -2220,7 +2674,10 @@ static void pqdif_build_remote_filename(const char* dir_filename, char* out, siz
static int pqdif_get_file_from_device(chnl_usr_t *chnl_usr, const char *rem_filename, char *only_filename_ret, size_t only_filename_ret_len)
{
int ret;
char loc_file_fullname[512];
char tmp_file_fullname[512];
char final_file_fullname[512];
char local_dir[512];
char tmp_dir[512];
char rem_file_fullname[512];
const char *only_filename;
@@ -2231,40 +2688,61 @@ static int pqdif_get_file_from_device(chnl_usr_t *chnl_usr, const char *rem_file
if (only_filename[0] == '\0')
return SD_FAILURE;
if (pqdif_ensure_local_dir() != SD_SUCCESS) {
echo_warn1("[PQDIF] create local dir failed: %s\n", PQDIF_LOCAL_DIR);
if (pqdif_ensure_device_dirs(chnl_usr, local_dir, sizeof(local_dir), tmp_dir, sizeof(tmp_dir)) != SD_SUCCESS) {
echo_warn2("[PQDIF] create local dir failed: local=%s tmp=%s\n", local_dir, tmp_dir);
return SD_FAILURE;
}
memset(loc_file_fullname,0,sizeof(loc_file_fullname));
memset(tmp_file_fullname,0,sizeof(tmp_file_fullname));
memset(final_file_fullname,0,sizeof(final_file_fullname));
memset(rem_file_fullname,0,sizeof(rem_file_fullname));
apr_snprintf(loc_file_fullname,sizeof(loc_file_fullname),"%s/%s",PQDIF_LOCAL_DIR,only_filename);
apr_snprintf(tmp_file_fullname,sizeof(tmp_file_fullname),"%s/%s",tmp_dir,only_filename);
apr_snprintf(final_file_fullname,sizeof(final_file_fullname),"%s/%s",local_dir,only_filename);
apr_snprintf(rem_file_fullname,sizeof(rem_file_fullname),"%s",rem_filename);
if (only_filename_ret != NULL && only_filename_ret_len > 0)
apr_snprintf(only_filename_ret,only_filename_ret_len,"%s",only_filename);
printf("[PQDIF] mms_getFile local=%s remote=%s\n", loc_file_fullname, rem_file_fullname);
/* Keep the same safety flow as the C# reader:
* download to a temporary backup path first, remove failed/empty files,
* copy to the final PQDIF directory only after validation, then remove temp.
*/
remove(tmp_file_fullname);
ret = mms_getFile(chnl_usr->net_info,loc_file_fullname,rem_file_fullname,g_pt61850app->mmsOpTimeout);
printf("[PQDIF] mms_getFile tmp=%s final=%s remote=%s\n",
tmp_file_fullname, final_file_fullname, rem_file_fullname);
ret = mms_getFile(chnl_usr->net_info,tmp_file_fullname,rem_file_fullname,g_pt61850app->mmsOpTimeout);
if (ret != SD_SUCCESS) {
echo_warn3("[PQDIF] mms_getFile failed IP=%s local=%s remote=%s\n",
chnl_usr->ip_str, loc_file_fullname, rem_file_fullname);
remove(tmp_file_fullname);
echo_warn3("[PQDIF] mms_getFile failed IP=%s tmp=%s remote=%s\n",
chnl_usr->ip_str, tmp_file_fullname, rem_file_fullname);
return ret;
}
#ifdef _OS_UNIX_
{
struct stat st;
if (stat(loc_file_fullname, &st) != 0 || st.st_size <= 0) {
unlink(loc_file_fullname);
if (pqdif_get_local_file_size(tmp_file_fullname) <= 0) {
remove(tmp_file_fullname);
echo_warn2("[PQDIF] file is empty or invalid: %s from %s\n",
loc_file_fullname, rem_file_fullname);
tmp_file_fullname, rem_file_fullname);
return SD_FAILURE;
}
if (pqdif_copy_file(tmp_file_fullname, final_file_fullname) != SD_SUCCESS) {
remove(tmp_file_fullname);
echo_warn2("[PQDIF] copy validated file failed: %s -> %s\n",
tmp_file_fullname, final_file_fullname);
return SD_FAILURE;
}
#endif
if (pqdif_record_download_success(chnl_usr, only_filename) != SD_SUCCESS) {
remove(tmp_file_fullname);
remove(final_file_fullname);
echo_warn2("[PQDIF] write download record failed, remove copied file: IP=%s file=%s\n",
chnl_usr->ip_str, only_filename);
return SD_FAILURE;
}
remove(tmp_file_fullname);
return SD_SUCCESS;
}
@@ -2281,8 +2759,7 @@ static apr_status_t ChannelRecallPQDIFFiles(chnl_usr_t *chnl_usr, LD_info_t *LD_
int existed = 0;
int missing = 0;
int failed = 0;
time_t interval_start;
time_t interval_step;
int matched = 0;
if (chnl_usr == NULL || chnl_usr->chnl == NULL || chnl_usr->chnl->ied == NULL ||
chnl_usr->chnl->ied->usr_ext == NULL || chnl_usr->net_info == NULL ||
@@ -2329,20 +2806,14 @@ static apr_status_t ChannelRecallPQDIFFiles(chnl_usr_t *chnl_usr, LD_info_t *LD_
return APR_EGENERAL;
}
interval_step = PQDIF_AUTO_INTERVAL_HOURS * 3600;
interval_start = pqdif_align_interval_start(start_sec);
printf("[PQDIF][RECALL] begin mp_id=%s cpuno=%d range=%lld~%lld interval_start=%lld files=%d dev_type=%s\n",
LD_info->mp_id, LD_info->cpuno, start_sec, end_sec, (long long)interval_start,
filenum, ied_usr->dev_type);
while ((long long)interval_start < end_sec) {
int found_this_interval = FALSE;
printf("[PQDIF][RECALL] begin mp_id=%s cpuno=%d range=%lld~%lld files=%d dev_type=%s\n",
LD_info->mp_id, LD_info->cpuno, start_sec, end_sec, filenum, ied_usr->dev_type);
for (file_idx = 0; file_idx < filenum; file_idx++) {
const char *base_name;
char remote_filename[256];
char only_filename_ret[256];
pqdif_file_interval_t file_info;
int ret_get;
if (filenames[file_idx] == NULL)
@@ -2352,15 +2823,17 @@ static apr_status_t ChannelRecallPQDIFFiles(chnl_usr_t *chnl_usr, LD_info_t *LD_
if (base_name[0] == '\0')
continue;
if (!pqdif_match_interval(base_name, LD_info->cpuno, interval_start, ied_usr->dev_type))
if (!pqdif_match_recall_range(base_name, LD_info->cpuno, start_sec, end_sec,
ied_usr->dev_type, &file_info))
continue;
found_this_interval = TRUE;
if (pqdif_local_file_exists(base_name)) {
matched++;
if (pqdif_download_record_exists(chnl_usr, base_name)) {
existed++;
printf("[PQDIF][RECALL] local file exists, skip mp_id=%s interval=%lld file=%s\n",
LD_info->mp_id, (long long)interval_start, base_name);
break;
printf("[PQDIF][RECALL] download record exists, skip mp_id=%s file=%s file_range=%lld~%lld period=%d\n",
LD_info->mp_id, base_name, (long long)file_info.start_time,
(long long)file_info.end_time, file_info.period_hours);
continue;
}
memset(remote_filename,0,sizeof(remote_filename));
@@ -2368,37 +2841,37 @@ static apr_status_t ChannelRecallPQDIFFiles(chnl_usr_t *chnl_usr, LD_info_t *LD_
pqdif_build_remote_filename(filenames[file_idx], remote_filename, sizeof(remote_filename));
if (remote_filename[0] == '\0') {
failed++;
break;
continue;
}
ret_get = pqdif_get_file_from_device(chnl_usr, remote_filename, only_filename_ret, sizeof(only_filename_ret));
if (ret_get == SD_SUCCESS) {
char local_dir[512];
fetched++;
chnl_usr->m_LastPosRespTime = sGetMsTime();
printf("[PQDIF][RECALL] fetch success mp_id=%s interval=%lld remote=%s local=%s/%s\n",
LD_info->mp_id, (long long)interval_start, remote_filename, PQDIF_LOCAL_DIR, only_filename_ret);
pqdif_build_device_dirs(chnl_usr, local_dir, sizeof(local_dir), NULL, 0);
printf("[PQDIF][RECALL] fetch success mp_id=%s file_range=%lld~%lld period=%d remote=%s local=%s/%s\n",
LD_info->mp_id, (long long)file_info.start_time, (long long)file_info.end_time,
file_info.period_hours, remote_filename, local_dir, only_filename_ret);
}
else {
failed++;
echo_warn3("[PQDIF][RECALL] fetch failed mp_id=%s remote=%s IP=%s\n",
LD_info->mp_id, remote_filename, chnl_usr->ip_str);
}
break;
}
if (!found_this_interval) {
if (matched == 0) {
missing++;
printf("[PQDIF][RECALL] no matched file mp_id=%s interval=%lld dev_type=%s\n",
LD_info->mp_id, (long long)interval_start, ied_usr->dev_type);
printf("[PQDIF][RECALL] no matched file mp_id=%s range=%lld~%lld dev_type=%s\n",
LD_info->mp_id, start_sec, end_sec, ied_usr->dev_type);
}
interval_start += interval_step;
}
printf("[PQDIF][RECALL] finish mp_id=%s matched=%d fetched=%d existed=%d missing=%d failed=%d\n",
LD_info->mp_id, matched, fetched, existed, missing, failed);
printf("[PQDIF][RECALL] finish mp_id=%s fetched=%d existed=%d missing=%d failed=%d\n",
LD_info->mp_id, fetched, existed, missing, failed);
if (missing > 0 || failed > 0)
if (matched == 0 || failed > 0)
return APR_EGENERAL;
return APR_SUCCESS;
@@ -2463,6 +2936,7 @@ static apr_status_t ChannelCheckPQDIFFiles(chnl_usr_t *chnl_usr)
int matched = 0;
int scan_idx;
double now_ms;
time_t now_time;
static double s_last_scan_ms[PQDIF_MAX_DEVICE_INDEX] = {0};
if (chnl_usr == NULL || chnl_usr->chnl == NULL || chnl_usr->chnl->ied == NULL ||
@@ -2489,6 +2963,7 @@ static apr_status_t ChannelCheckPQDIFFiles(chnl_usr_t *chnl_usr)
return APR_SUCCESS;
}
s_last_scan_ms[scan_idx] = now_ms;
now_time = time(NULL);
/* 本函数只做 PQDIF 文件获取:
* 1. 从装置固定目录 /PQDIF/ 取文件列表;
@@ -2543,13 +3018,16 @@ static apr_status_t ChannelCheckPQDIFFiles(chnl_usr_t *chnl_usr)
* 这里保持同样的匹配方式,不依赖厂家前缀,也兼容普通设备用
* 周期开始时间命名、振兴类设备用周期结束时间命名的差异。
*/
if (!pqdif_match_recent_interval(base_name, LD_info->cpuno, ied_usr->dev_type))
if (!pqdif_is_latest_auto_file(filenames, filenum, base_name,
LD_info->cpuno, ied_usr->dev_type, now_time))
continue;
matched++;
if (pqdif_local_file_exists(base_name)) {
printf("[PQDIF] local file exists, skip mp_id=%s file=%s\n", LD_info->mp_id, base_name);
continue;
if (pqdif_download_record_exists(chnl_usr, base_name)) {
printf("[PQDIF] latest file already downloaded, skip mp_id=%s file=%s\n",
LD_info->mp_id, base_name);
break;
}
memset(remote_filename,0,sizeof(remote_filename));
@@ -2560,10 +3038,13 @@ static apr_status_t ChannelCheckPQDIFFiles(chnl_usr_t *chnl_usr)
ret_get = pqdif_get_file_from_device(chnl_usr, remote_filename, only_filename_ret, sizeof(only_filename_ret));
if (ret_get == SD_SUCCESS) {
char local_dir[512];
fetched++;
chnl_usr->m_LastPosRespTime = sGetMsTime();
pqdif_build_device_dirs(chnl_usr, local_dir, sizeof(local_dir), NULL, 0);
printf("[PQDIF] fetch success mp_id=%s name=%s remote=%s local=%s/%s\n",
LD_info->mp_id, LD_info->name, remote_filename, PQDIF_LOCAL_DIR, only_filename_ret);
LD_info->mp_id, LD_info->name, remote_filename, local_dir, only_filename_ret);
}
else {
echo_warn3("[PQDIF] fetch failed mp_id=%s remote=%s IP=%s\n",
@@ -2575,6 +3056,7 @@ static apr_status_t ChannelCheckPQDIFFiles(chnl_usr_t *chnl_usr)
PQDIF_MAX_FETCH_PER_SCAN, ied->id, chnl_usr->ip_str);
return APR_SUCCESS;
}
break;
}
}