2026-04-22 10:40:19 +08:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
|
|
#include <cstddef>
|
2026-04-29 13:35:49 +08:00
|
|
|
|
#include <complex>
|
2026-04-22 10:40:19 +08:00
|
|
|
|
#include <map>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
#include "pqdif/include/pqdif_ph.h"
|
|
|
|
|
|
|
|
|
|
|
|
// ============================
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 新版:完整 PQDIF 逻辑结构
|
|
|
|
|
|
// 说明:
|
|
|
|
|
|
// 1) 该结构尽量忠实表达 PQDIF 的“文件 -> 记录 -> 定义/实例 -> 数组值”关系;
|
|
|
|
|
|
// 2) 后续所有映射、归并、按时刻整合都应该基于这些结构做;
|
|
|
|
|
|
// 3) 对暂未显式建模的标签,统一进入 extra_tags,避免丢失信息。
|
2026-04-22 10:40:19 +08:00
|
|
|
|
// ============================
|
2026-04-29 13:35:49 +08:00
|
|
|
|
|
|
|
|
|
|
using PqdifExtraTagMap = std::map<std::string, std::string>;
|
|
|
|
|
|
|
|
|
|
|
|
// GUID 及其可读名称
|
|
|
|
|
|
struct PqdifGuidValue
|
2026-04-22 10:40:19 +08:00
|
|
|
|
{
|
2026-04-29 13:35:49 +08:00
|
|
|
|
GUID value{}; // 原始 GUID 值
|
|
|
|
|
|
std::string symbolic_name; // 通过 PQDIF 信息表解析出的标准名,如 tagPhaseID / ID_QT_VALUELOG 等
|
|
|
|
|
|
};
|
2026-04-22 10:40:19 +08:00
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// PQDIF 原始时间戳
|
|
|
|
|
|
struct PqdifTimestampValue
|
|
|
|
|
|
{
|
|
|
|
|
|
UINT4 day = 0; // 自 1900-01-01 起的天数,PQDIF 原始 day 字段
|
|
|
|
|
|
double second = 0.0; // 当天起算的秒,PQDIF 原始 sec 字段
|
|
|
|
|
|
time_t unix_time = 0; // 转换后的 Unix 时间戳,便于上层使用
|
|
|
|
|
|
std::string text; // 格式化后的本地时间文本,便于调试和日志输出
|
|
|
|
|
|
};
|
2026-04-22 10:40:19 +08:00
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 记录头信息
|
|
|
|
|
|
struct PqdifRecordHeaderInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
long record_index = -1; // 本记录在文件中的顺序索引
|
|
|
|
|
|
long file_position = 0; // 记录头在文件中的偏移
|
|
|
|
|
|
PqdifGuidValue record_type; // 记录类型,如 tagContainer / tagRecDataSource / tagRecObservation
|
|
|
|
|
|
long header_size = 0; // 记录头字节数
|
|
|
|
|
|
long data_size = 0; // 记录体字节数
|
|
|
|
|
|
long next_record_position = 0; // 下一条记录偏移
|
|
|
|
|
|
unsigned int checksum = 0; // 记录校验值
|
2026-04-22 10:40:19 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 通用数组值容器:用于保存 PQDIF 向量/序列的真正数组内容
|
|
|
|
|
|
struct PqdifValueArray
|
|
|
|
|
|
{
|
|
|
|
|
|
int physical_type = -1; // PQDIF 物理类型 ID,例如 REAL8 / UINT4 / TIMESTAMPPQDIF
|
|
|
|
|
|
long count = 0; // 数组点数
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<bool> bool_values; // 布尔数组
|
|
|
|
|
|
std::vector<long long> int_values; // 有符号整数数组
|
|
|
|
|
|
std::vector<unsigned long long> uint_values; // 无符号整数数组
|
|
|
|
|
|
std::vector<double> real_values; // 浮点数组,最常见的统计值/波形值
|
|
|
|
|
|
std::vector<std::complex<double>> complex_values; // 复数数组
|
|
|
|
|
|
std::vector<PqdifTimestampValue> timestamp_values; // 时间戳数组
|
|
|
|
|
|
std::vector<PqdifGuidValue> guid_values; // GUID 数组
|
|
|
|
|
|
std::vector<std::string> text_values; // 字符串数组(CHAR1/CHAR2)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Container / General Record:文件级元数据
|
|
|
|
|
|
struct PqdifContainerRecord
|
|
|
|
|
|
{
|
|
|
|
|
|
PqdifRecordHeaderInfo header; // 记录头
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<unsigned int> version_info; // tagVersionInfo,格式版本号数组
|
|
|
|
|
|
std::string file_name; // tagFileName,原始文件名
|
|
|
|
|
|
PqdifTimestampValue creation_time; // tagCreation,文件创建时间
|
|
|
|
|
|
PqdifTimestampValue last_saved_time; // tagLastSaved,最后保存时间
|
|
|
|
|
|
unsigned int times_saved = 0; // tagTimesSaved,保存次数
|
|
|
|
|
|
|
|
|
|
|
|
std::string language; // tagLanguage,语言
|
|
|
|
|
|
std::string title; // tagTitle,标题
|
|
|
|
|
|
std::string subject; // tagSubject,主题
|
|
|
|
|
|
std::string author; // tagAuthor,作者
|
|
|
|
|
|
std::string keywords; // tagKeywords,关键字
|
|
|
|
|
|
std::string comments; // tagComments,备注
|
|
|
|
|
|
std::string last_saved_by; // tagLastSavedBy,最后保存者
|
|
|
|
|
|
std::string application; // tagApplication,生成软件
|
|
|
|
|
|
|
|
|
|
|
|
PqdifGuidValue compression_style_id; // tagCompressionStyleID,压缩风格
|
|
|
|
|
|
unsigned int compression_algorithm_id = 0; // tagCompressionAlgorithmID,压缩算法
|
|
|
|
|
|
unsigned int compression_checksum = 0; // tagCompressionChecksum,压缩校验值
|
|
|
|
|
|
|
|
|
|
|
|
std::string owner; // tagOwner,所有者
|
|
|
|
|
|
std::string copyright; // tagCopyright,版权
|
|
|
|
|
|
std::string trademarks; // tagTrademarks,商标
|
|
|
|
|
|
std::string notes; // tagNotes,附加说明
|
|
|
|
|
|
|
|
|
|
|
|
std::string address1; // tagAddress1,地址行 1
|
|
|
|
|
|
std::string address2; // tagAddress2,地址行 2
|
|
|
|
|
|
std::string city; // tagCity,城市
|
|
|
|
|
|
std::string state; // tagState,州/省
|
|
|
|
|
|
std::string postal_code; // tagPostalCode,邮编
|
|
|
|
|
|
std::string country; // tagCountry,国家
|
|
|
|
|
|
std::string phone_voice; // tagPhoneVoice,电话
|
|
|
|
|
|
std::string phone_fax; // tagPhoneFAX,传真
|
|
|
|
|
|
std::string email; // tagEmail,邮箱
|
|
|
|
|
|
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Series Definition:序列定义,描述“这一列是什么”
|
|
|
|
|
|
struct PqdifSeriesDefinition
|
|
|
|
|
|
{
|
|
|
|
|
|
int series_def_index = -1; // 序列定义在所属通道定义中的顺序索引
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int quantity_units_id = 0; // tagQuantityUnitsID,单位 ID
|
|
|
|
|
|
PqdifGuidValue quantity_characteristic_id; // tagQuantityCharacteristicID,特征量 ID
|
|
|
|
|
|
PqdifGuidValue value_type_id; // tagValueTypeID,值类型 ID,例如 TIME / AVG / MAX / MIN / VAL
|
|
|
|
|
|
unsigned int storage_method_id = 0; // tagStorageMethodID,序列存储方式
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int significant_digits_id = 0; // tagQuantitySignificantDigitsID,有效位定义
|
|
|
|
|
|
double quantity_resolution = 0.0; // tagQuantityResolutionID / 解析出的分辨率
|
|
|
|
|
|
double nominal_quantity = 0.0; // tagSeriesNominalQuantity,标称值
|
|
|
|
|
|
|
|
|
|
|
|
std::string value_type_name; // tagValueTypeName,值类型显示名
|
|
|
|
|
|
unsigned int hint_greek_prefix_id = 0; // tagHintGreekPrefixID,显示前缀提示
|
|
|
|
|
|
unsigned int hint_preferred_units_id = 0; // tagHintPreferredUnitsID,优选单位提示
|
|
|
|
|
|
unsigned int hint_default_display_id = 0; // tagHintDefaultDisplayID,默认显示方式提示
|
|
|
|
|
|
double prob_interval = 0.0; // tagProbInterval,概率间隔
|
|
|
|
|
|
double prob_percentile = 0.0; // tagProbPercentile,概率百分位
|
|
|
|
|
|
PqdifTimestampValue effective_time; // tagEffective,定义生效时间
|
|
|
|
|
|
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Channel Definition:通道定义,描述“这个通道测什么”
|
|
|
|
|
|
struct PqdifChannelDefinition
|
2026-04-22 10:40:19 +08:00
|
|
|
|
{
|
2026-04-29 13:35:49 +08:00
|
|
|
|
int channel_def_index = -1; // 通道定义在数据源中的顺序索引
|
2026-04-22 10:40:19 +08:00
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
std::string channel_name; // tagChannelName,通道名称
|
|
|
|
|
|
unsigned int phase_id = 0; // tagPhaseID,相别
|
|
|
|
|
|
std::string other_channel_identifier; // tagOtherChannelIdentifier,附加通道标识
|
|
|
|
|
|
std::string group_name; // tagGroupName,组名称
|
|
|
|
|
|
|
|
|
|
|
|
PqdifGuidValue quantity_type_id; // tagQuantityTypeID,量类型(如 VALUELOG / PHASOR)
|
|
|
|
|
|
unsigned int quantity_measured_id = 0; // tagQuantityMeasuredID,被测量对象(如电压/电流/频率)
|
|
|
|
|
|
unsigned int physical_channel = 0; // tagPhysicalChannel,物理通道编号
|
|
|
|
|
|
std::string quantity_name; // tagQuantityName,自定义量名称
|
|
|
|
|
|
int primary_series_index = -1; // tagPrimarySeriesIdx,主序列索引
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<PqdifSeriesDefinition> series_definitions; // 该通道下的全部序列定义
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Data Source Record:数据源定义,描述设备和通道体系
|
|
|
|
|
|
struct PqdifDataSourceRecord
|
|
|
|
|
|
{
|
|
|
|
|
|
PqdifRecordHeaderInfo header; // 记录头
|
|
|
|
|
|
int data_source_index = -1; // 在文件中解析出的数据源顺序索引
|
|
|
|
|
|
long record_index = -1; // 对应文件记录索引,便于关联 Observation
|
|
|
|
|
|
|
|
|
|
|
|
PqdifGuidValue data_source_type_id; // tagDataSourceTypeID,数据源类型
|
|
|
|
|
|
PqdifGuidValue vendor_id; // tagVendorID,厂商 ID
|
|
|
|
|
|
PqdifGuidValue equipment_id; // tagEquipmentID,设备型号 ID
|
|
|
|
|
|
std::string custom_source_info; // tagCustomSourceInfo,扩展来源信息
|
|
|
|
|
|
|
|
|
|
|
|
PqdifGuidValue instrument_type_id; // tagInstrumentTypeID,仪器类型
|
|
|
|
|
|
std::string instrument_model_name; // tagInstrumentModelName,仪器型号名称
|
|
|
|
|
|
std::string instrument_model_number; // tagInstrumentModelNumber,仪器型号编号
|
|
|
|
|
|
std::string serial_number; // tagSerialNumberDS,序列号
|
|
|
|
|
|
std::string version; // tagVersionDS,版本号
|
|
|
|
|
|
std::string name; // tagNameDS,设备名称
|
|
|
|
|
|
std::string owner; // tagOwnerDS,设备归属
|
|
|
|
|
|
std::string location; // tagLocationDS,安装位置
|
|
|
|
|
|
std::string time_zone; // tagTimeZoneDS,时区文本
|
|
|
|
|
|
std::string coordinates; // tagCoordinatesDS,坐标信息
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<PqdifChannelDefinition> channel_definitions; // 数据源下的全部通道定义
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Monitor Settings 中单通道的配置
|
|
|
|
|
|
struct PqdifChannelSetting
|
|
|
|
|
|
{
|
|
|
|
|
|
int channel_setting_index = -1; // 通道设置在监测设置记录中的顺序索引
|
|
|
|
|
|
int channel_def_index = -1; // tagChannelDefnIdx,关联的数据源通道定义索引
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int trigger_type_id = 0; // tagTriggerTypeID,触发类型
|
|
|
|
|
|
double full_scale = 0.0; // tagFullScale,满量程
|
|
|
|
|
|
double noise_floor = 0.0; // tagNoiseFloor,噪声底
|
|
|
|
|
|
PqdifValueArray trigger_shape_param; // tagTriggerShapeParam,触发曲线/参数数组
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int xd_transformer_type_id = 0; // tagXDTransformerTypeID,互感器类型
|
|
|
|
|
|
double xd_system_side_ratio = 0.0; // tagXDSystemSideRatio,一次侧变比
|
|
|
|
|
|
double xd_monitor_side_ratio = 0.0; // tagXDMonitorSideRatio,监测侧变比
|
|
|
|
|
|
PqdifValueArray xd_frequency_response; // tagXDFrequencyResponse,频率响应数组
|
|
|
|
|
|
|
|
|
|
|
|
double cal_time_skew = 0.0; // tagCalTimeSkew,校准时延
|
|
|
|
|
|
double cal_offset = 0.0; // tagCalOffset,校准偏移
|
|
|
|
|
|
double cal_ratio = 0.0; // tagCalRatio,校准比例
|
|
|
|
|
|
bool cal_must_use_arcal = false; // tagCalMustUseARCal,是否必须使用校准曲线
|
|
|
|
|
|
PqdifValueArray cal_applied; // tagCalApplied,校准应用值数组
|
|
|
|
|
|
PqdifValueArray cal_recorded; // tagCalRecorded,校准记录值数组
|
|
|
|
|
|
|
|
|
|
|
|
double trigger_high_high = 0.0; // tagTriggerHighHigh,高高阈值
|
|
|
|
|
|
double trigger_high = 0.0; // tagTriggerHigh,高阈值
|
|
|
|
|
|
double trigger_low = 0.0; // tagTriggerLow,低阈值
|
|
|
|
|
|
double trigger_low_low = 0.0; // tagTriggerLowLow,低低阈值
|
|
|
|
|
|
double trigger_deadband = 0.0; // tagTriggerDeadband,死区
|
|
|
|
|
|
double trigger_rate = 0.0; // tagTriggerRate,触发速率
|
|
|
|
|
|
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Monitor Settings Record:监测装置配置
|
|
|
|
|
|
struct PqdifMonitorSettingsRecord
|
|
|
|
|
|
{
|
|
|
|
|
|
PqdifRecordHeaderInfo header; // 记录头
|
|
|
|
|
|
int settings_index = -1; // 在文件中解析出的监测设置顺序索引
|
|
|
|
|
|
long record_index = -1; // 对应文件记录索引,便于关联 Observation
|
|
|
|
|
|
|
|
|
|
|
|
PqdifTimestampValue effective_time; // tagEffective,配置生效时间
|
|
|
|
|
|
PqdifTimestampValue time_installed; // tagTimeInstalled,安装时间
|
|
|
|
|
|
PqdifTimestampValue time_removed; // tagTimeRemoved,拆除时间
|
|
|
|
|
|
|
|
|
|
|
|
bool use_calibration = false; // tagUseCalibration,是否使用校准
|
|
|
|
|
|
bool use_transducer = false; // tagUseTransducer,是否使用传感器/互感器
|
|
|
|
|
|
double nominal_frequency = 0.0; // tagNominalFrequency,额定频率
|
|
|
|
|
|
unsigned int physical_connection = 0; // tagSettingPhysicalConnection,物理接线方式
|
|
|
|
|
|
double nominal_voltage = 0.0; // tagNominalVoltage,额定电压
|
|
|
|
|
|
bool is_pcc = false; // tagIsPCC,是否为 PCC 点
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<PqdifChannelSetting> channel_settings; // 各通道的监测配置
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Observation 中单个序列实例:保存某一次观测里的一个真实数组
|
|
|
|
|
|
struct PqdifSeriesInstance
|
|
|
|
|
|
{
|
|
|
|
|
|
int series_instance_index = -1; // 序列实例在通道实例中的顺序索引
|
|
|
|
|
|
int series_def_index = -1; // 关联的数据源序列定义索引(通常与定义层顺序一致)
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int quantity_units_id = 0; // tagQuantityUnitsID,本实例对应的单位 ID
|
|
|
|
|
|
PqdifGuidValue quantity_characteristic_id; // tagQuantityCharacteristicID,本实例特征量 ID
|
|
|
|
|
|
PqdifGuidValue value_type_id; // tagValueTypeID,本实例值类型 ID
|
|
|
|
|
|
|
|
|
|
|
|
long series_base_type = -1; // 当前库暴露的底层序列物理类型
|
|
|
|
|
|
double series_base_quantity = 0.0; // tagSeriesBaseQuantity,序列基值
|
|
|
|
|
|
double scale = 1.0; // tagSeriesScale,缩放系数
|
|
|
|
|
|
double offset = 0.0; // tagSeriesOffset,偏移量
|
|
|
|
|
|
double nominal_quantity = 0.0; // 关联定义层解析出的标称量
|
|
|
|
|
|
unsigned int significant_digits_id = 0; // 关联定义层解析出的有效位配置
|
|
|
|
|
|
double quantity_resolution = 0.0; // 关联定义层解析出的分辨率
|
|
|
|
|
|
|
|
|
|
|
|
int share_channel_index = -1; // tagSeriesShareChannelIdx,共享通道索引
|
|
|
|
|
|
int share_series_index = -1; // tagSeriesShareSeriesIdx,共享序列索引
|
|
|
|
|
|
|
|
|
|
|
|
PqdifValueArray values; // tagSeriesValues,真正的数组值
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Observation 中单个通道实例:保存某一次观测里的一个真实通道块
|
|
|
|
|
|
struct PqdifChannelInstance
|
|
|
|
|
|
{
|
|
|
|
|
|
int channel_instance_index = -1; // 通道实例在观测中的顺序索引
|
|
|
|
|
|
int channel_def_index = -1; // 关联的数据源通道定义索引
|
|
|
|
|
|
|
|
|
|
|
|
std::string channel_name; // 从 Observation 读出的通道名
|
|
|
|
|
|
unsigned int phase_id = 0; // 相别
|
|
|
|
|
|
PqdifGuidValue quantity_type_id; // 量类型
|
|
|
|
|
|
unsigned int quantity_measured_id = 0; // 被测量对象
|
|
|
|
|
|
int primary_series_index = -1; // 主序列索引
|
|
|
|
|
|
|
|
|
|
|
|
double charact_duration = 0.0; // tagCharactDuration,特征持续时间
|
|
|
|
|
|
double charact_magnitude = 0.0; // tagCharactMagnitude,特征幅值
|
|
|
|
|
|
double charact_frequency = 0.0; // tagCharactFrequency,特征频率
|
|
|
|
|
|
double channel_frequency = 0.0; // tagChannelFrequency,通道频率
|
|
|
|
|
|
int channel_group_id = 0; // tagChannelGroupID,通道分组
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<PqdifSeriesInstance> series_instances; // 该通道实例下的所有序列实例
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Observation Record:一次真实观测
|
|
|
|
|
|
struct PqdifObservationRecord
|
|
|
|
|
|
{
|
|
|
|
|
|
PqdifRecordHeaderInfo header; // 记录头
|
|
|
|
|
|
int observation_index = -1; // 在文件中解析出的观测顺序索引
|
|
|
|
|
|
long record_index = -1; // 对应文件记录索引
|
|
|
|
|
|
|
|
|
|
|
|
int related_data_source_index = -1; // 该观测关联的数据源顺序索引
|
|
|
|
|
|
long related_data_source_record_index = -1; // 该观测关联的数据源记录索引
|
|
|
|
|
|
int related_settings_index = -1; // 该观测关联的监测设置顺序索引
|
|
|
|
|
|
long related_settings_record_index = -1; // 该观测关联的监测设置记录索引
|
|
|
|
|
|
|
|
|
|
|
|
std::string observation_name; // tagObservationName,观测名称
|
|
|
|
|
|
PqdifTimestampValue time_create; // tagTimeCreate,观测记录创建时间
|
|
|
|
|
|
PqdifTimestampValue time_start; // tagTimeStart,观测起始时间
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int trigger_method_id = 0; // tagTriggerMethodID,触发方式
|
|
|
|
|
|
PqdifTimestampValue time_triggered; // tagTimeTriggered,触发时刻
|
|
|
|
|
|
std::vector<int> channel_trigger_indexes; // tagChannelTriggerIdx,触发通道索引数组
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int observation_serial = 0; // tagObservationSerial,观测序号
|
|
|
|
|
|
unsigned int observation_aggregation_serial = 0; // tagObservationAggregationSerial,聚合序号
|
|
|
|
|
|
PqdifGuidValue disturbance_category_id; // tagDisturbanceCategoryID,扰动分类
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<PqdifChannelInstance> channel_instances; // 本次观测中的所有通道实例
|
|
|
|
|
|
PqdifExtraTagMap extra_tags; // 当前结构未单独建模但已读出的标签
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 文件级完整逻辑对象
|
|
|
|
|
|
struct PqdifLogicalFile
|
|
|
|
|
|
{
|
|
|
|
|
|
std::vector<PqdifRecordHeaderInfo> record_headers; // 文件中所有记录的头信息,保留顺序
|
|
|
|
|
|
std::vector<PqdifContainerRecord> containers; // Container / General 记录,一般只有一个
|
|
|
|
|
|
std::vector<PqdifDataSourceRecord> data_sources; // 全部数据源记录
|
|
|
|
|
|
std::vector<PqdifMonitorSettingsRecord> monitor_settings; // 全部监测设置记录
|
|
|
|
|
|
std::vector<PqdifObservationRecord> observations; // 全部观测记录
|
2026-04-22 10:40:19 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ============================
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 统计识别与同一时间聚合层
|
|
|
|
|
|
// 说明:
|
|
|
|
|
|
// 1) 这一层只服务于“从完整 PQDIF 结构中识别目标统计指标并按时间聚合”;
|
|
|
|
|
|
// 2) 当前阶段先不做 tagPqData_Float 映射;
|
|
|
|
|
|
// 3) 当前阶段只处理“筛选出的统计类 observation”,其他 observation 暂不参与识别。
|
2026-04-22 10:40:19 +08:00
|
|
|
|
// ============================
|
2026-04-29 13:35:49 +08:00
|
|
|
|
|
|
|
|
|
|
// 解析得到的接线方式
|
|
|
|
|
|
// 用于区分星型 / 角型 两套指标规则。
|
|
|
|
|
|
enum class ParsedConnectionKind
|
2026-04-22 10:40:19 +08:00
|
|
|
|
{
|
2026-04-29 13:35:49 +08:00
|
|
|
|
Unknown = 0, // 未知 / 无法确认
|
|
|
|
|
|
Wye, // 星型 / Y
|
|
|
|
|
|
Delta // 角型 / Δ
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 当前支持的业务指标 ID
|
|
|
|
|
|
// 后续如果新增指标,只需要继续往这里加枚举,并在 cpp 里的识别规则补充即可。
|
|
|
|
|
|
enum class StatMetricId
|
|
|
|
|
|
{
|
|
|
|
|
|
Unknown = 0,
|
|
|
|
|
|
|
|
|
|
|
|
// 相电压有效值
|
|
|
|
|
|
UaRms,
|
|
|
|
|
|
UbRms,
|
|
|
|
|
|
UcRms,
|
|
|
|
|
|
|
|
|
|
|
|
// 相电流有效值
|
|
|
|
|
|
IaRms,
|
|
|
|
|
|
IbRms,
|
|
|
|
|
|
IcRms,
|
|
|
|
|
|
|
|
|
|
|
|
// 线电压有效值
|
|
|
|
|
|
UabRms,
|
|
|
|
|
|
UbcRms,
|
|
|
|
|
|
UcaRms,
|
|
|
|
|
|
|
|
|
|
|
|
// 相电压偏差
|
|
|
|
|
|
UaDeviation,
|
|
|
|
|
|
UbDeviation,
|
|
|
|
|
|
UcDeviation,
|
|
|
|
|
|
|
|
|
|
|
|
// 线电压偏差
|
|
|
|
|
|
UabDeviation,
|
|
|
|
|
|
UbcDeviation,
|
|
|
|
|
|
UcaDeviation,
|
|
|
|
|
|
|
|
|
|
|
|
// 频率
|
|
|
|
|
|
Frequency,
|
|
|
|
|
|
|
|
|
|
|
|
// 频率偏差
|
|
|
|
|
|
FrequencyDeviation,
|
|
|
|
|
|
|
|
|
|
|
|
// 电压序分量
|
|
|
|
|
|
UZeroSeq, // 电压零序分量
|
|
|
|
|
|
UNegSeq, // 电压负序分量
|
|
|
|
|
|
UPosSeq, // 电压正序分量
|
|
|
|
|
|
|
|
|
|
|
|
// 电压负序不平衡,通常对应 S2/S1,单位可能为 % 或 pu
|
|
|
|
|
|
UNegSeqUnbalance,
|
|
|
|
|
|
|
|
|
|
|
|
// 电流序分量
|
|
|
|
|
|
IZeroSeq, // 电流零序分量
|
|
|
|
|
|
INegSeq, // 电流负序分量
|
|
|
|
|
|
IPosSeq, // 电流正序分量
|
|
|
|
|
|
|
|
|
|
|
|
// 电流负序不平衡,通常对应 S2/S1,单位可能为 % 或 pu
|
|
|
|
|
|
INegSeqUnbalance,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 功率类:三相/总有功、无功、视在功率
|
|
|
|
|
|
PaPower,
|
|
|
|
|
|
PbPower,
|
|
|
|
|
|
PcPower,
|
|
|
|
|
|
PTotalPower,
|
|
|
|
|
|
QaPower,
|
|
|
|
|
|
QbPower,
|
|
|
|
|
|
QcPower,
|
|
|
|
|
|
QTotalPower,
|
|
|
|
|
|
SaPower,
|
|
|
|
|
|
SbPower,
|
|
|
|
|
|
ScPower,
|
|
|
|
|
|
STotalPower,
|
|
|
|
|
|
|
|
|
|
|
|
// 功率因数类:三相/总功率因数、三相/总基波功率因数
|
|
|
|
|
|
PFa,
|
|
|
|
|
|
PFb,
|
|
|
|
|
|
PFc,
|
|
|
|
|
|
PFTotal,
|
|
|
|
|
|
FundPFa,
|
|
|
|
|
|
FundPFb,
|
|
|
|
|
|
FundPFc,
|
|
|
|
|
|
FundPFTotal,
|
2026-04-22 10:40:19 +08:00
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 电压变动幅值 DVC/dV/V:三相与线电压
|
|
|
|
|
|
UaDvc,
|
|
|
|
|
|
UbDvc,
|
|
|
|
|
|
UcDvc,
|
|
|
|
|
|
UabDvc,
|
|
|
|
|
|
UbcDvc,
|
|
|
|
|
|
UcaDvc,
|
2026-04-22 10:40:19 +08:00
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 闪变:三相和线电压短闪 Pst、长闪 Plt
|
|
|
|
|
|
UaPst,
|
|
|
|
|
|
UbPst,
|
|
|
|
|
|
UcPst,
|
|
|
|
|
|
UabPst,
|
|
|
|
|
|
UbcPst,
|
|
|
|
|
|
UcaPst,
|
|
|
|
|
|
UaPlt,
|
|
|
|
|
|
UbPlt,
|
|
|
|
|
|
UcPlt,
|
|
|
|
|
|
UabPlt,
|
|
|
|
|
|
UbcPlt,
|
|
|
|
|
|
UcaPlt,
|
|
|
|
|
|
|
|
|
|
|
|
// 基波功率:三相/总有功、无功、视在基波功率
|
|
|
|
|
|
PaFundPower,
|
|
|
|
|
|
PbFundPower,
|
|
|
|
|
|
PcFundPower,
|
|
|
|
|
|
PTotalFundPower,
|
|
|
|
|
|
QaFundPower,
|
|
|
|
|
|
QbFundPower,
|
|
|
|
|
|
QcFundPower,
|
|
|
|
|
|
QTotalFundPower,
|
|
|
|
|
|
SaFundPower,
|
|
|
|
|
|
SbFundPower,
|
|
|
|
|
|
ScFundPower,
|
|
|
|
|
|
STotalFundPower,
|
|
|
|
|
|
|
|
|
|
|
|
// 基波有效值与基波相角:三相电压、三相电流、线电压
|
|
|
|
|
|
UaFundRms,
|
|
|
|
|
|
UbFundRms,
|
|
|
|
|
|
UcFundRms,
|
|
|
|
|
|
UaFundAngle,
|
|
|
|
|
|
UbFundAngle,
|
|
|
|
|
|
UcFundAngle,
|
|
|
|
|
|
IaFundRms,
|
|
|
|
|
|
IbFundRms,
|
|
|
|
|
|
IcFundRms,
|
|
|
|
|
|
IaFundAngle,
|
|
|
|
|
|
IbFundAngle,
|
|
|
|
|
|
IcFundAngle,
|
|
|
|
|
|
UabFundRms,
|
|
|
|
|
|
UbcFundRms,
|
|
|
|
|
|
UcaFundRms,
|
|
|
|
|
|
UabFundAngle,
|
|
|
|
|
|
UbcFundAngle,
|
|
|
|
|
|
UcaFundAngle,
|
|
|
|
|
|
|
|
|
|
|
|
// 总谐波畸变率 THD:三相电压、三相电流、线电压
|
|
|
|
|
|
UaThd,
|
|
|
|
|
|
UbThd,
|
|
|
|
|
|
UcThd,
|
|
|
|
|
|
IaThd,
|
|
|
|
|
|
IbThd,
|
|
|
|
|
|
IcThd,
|
|
|
|
|
|
UabThd,
|
|
|
|
|
|
UbcThd,
|
|
|
|
|
|
UcaThd,
|
|
|
|
|
|
|
|
|
|
|
|
// 谐波/间谐波类动态指标范围。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 不再为 2-50 次谐波逐项声明 UaHarm02、UaHarm03 ... UcHarm50,
|
|
|
|
|
|
// 而是用“指标族基址 + 相别 + 次数”的方式动态构造。这样后续新增
|
|
|
|
|
|
// 电流谐波、间谐波、谐波含有率等指标时,不需要继续堆大量 enum 项。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 当前已启用:
|
|
|
|
|
|
// VoltageHarmonicUaBase + order => UaHarmXX, order=2..50
|
|
|
|
|
|
// VoltageHarmonicUbBase + order => UbHarmXX, order=2..50
|
|
|
|
|
|
// VoltageHarmonicUcBase + order => UcHarmXX, order=2..50
|
|
|
|
|
|
// 预留区间:
|
|
|
|
|
|
// CurrentHarmonic* 后续电流谐波
|
|
|
|
|
|
// VoltageInterharmonic* 后续电压间谐波
|
|
|
|
|
|
// CurrentInterharmonic* 后续电流间谐波
|
|
|
|
|
|
// 三相电压谐波 RMS,order=2..50
|
|
|
|
|
|
VoltageHarmonicUaBase = 10000,
|
|
|
|
|
|
VoltageHarmonicUbBase = 10100,
|
|
|
|
|
|
VoltageHarmonicUcBase = 10200,
|
|
|
|
|
|
|
|
|
|
|
|
// AB/BC/CA 线电压谐波 RMS,order=2..50
|
|
|
|
|
|
LineVoltageHarmonicUabBase = 10300,
|
|
|
|
|
|
LineVoltageHarmonicUbcBase = 10400,
|
|
|
|
|
|
LineVoltageHarmonicUcaBase = 10500,
|
|
|
|
|
|
|
|
|
|
|
|
// 三相电流谐波 RMS,order=2..50
|
|
|
|
|
|
CurrentHarmonicIaBase = 11000,
|
|
|
|
|
|
CurrentHarmonicIbBase = 11100,
|
|
|
|
|
|
CurrentHarmonicIcBase = 11200,
|
|
|
|
|
|
|
|
|
|
|
|
// 三相电压谐波相角,order=2..50
|
|
|
|
|
|
VoltageHarmonicAngleUaBase = 12000,
|
|
|
|
|
|
VoltageHarmonicAngleUbBase = 12100,
|
|
|
|
|
|
VoltageHarmonicAngleUcBase = 12200,
|
|
|
|
|
|
|
|
|
|
|
|
// AB/BC/CA 线电压谐波相角,order=2..50
|
|
|
|
|
|
LineVoltageHarmonicAngleUabBase = 12300,
|
|
|
|
|
|
LineVoltageHarmonicAngleUbcBase = 12400,
|
|
|
|
|
|
LineVoltageHarmonicAngleUcaBase = 12500,
|
|
|
|
|
|
|
|
|
|
|
|
// 三相电流谐波相角,order=2..50
|
|
|
|
|
|
CurrentHarmonicAngleIaBase = 13000,
|
|
|
|
|
|
CurrentHarmonicAngleIbBase = 13100,
|
|
|
|
|
|
CurrentHarmonicAngleIcBase = 13200,
|
|
|
|
|
|
|
|
|
|
|
|
// 三相电压间谐波 RMS,slot=0..49 表示 0.5..49.5 次
|
|
|
|
|
|
VoltageInterharmonicUaBase = 14000,
|
|
|
|
|
|
VoltageInterharmonicUbBase = 14100,
|
|
|
|
|
|
VoltageInterharmonicUcBase = 14200,
|
|
|
|
|
|
|
|
|
|
|
|
// AB/BC/CA 线电压间谐波 RMS,slot=0..49 表示 0.5..49.5 次
|
|
|
|
|
|
LineVoltageInterharmonicUabBase = 14300,
|
|
|
|
|
|
LineVoltageInterharmonicUbcBase = 14400,
|
|
|
|
|
|
LineVoltageInterharmonicUcaBase = 14500,
|
|
|
|
|
|
|
|
|
|
|
|
// 三相电流间谐波 RMS,slot=0..49 表示 0.5..49.5 次
|
|
|
|
|
|
CurrentInterharmonicIaBase = 15000,
|
|
|
|
|
|
CurrentInterharmonicIbBase = 15100,
|
|
|
|
|
|
CurrentInterharmonicIcBase = 15200,
|
|
|
|
|
|
|
|
|
|
|
|
// 谐波功率 2-50 次:三相/总 有功、无功、视在功率
|
|
|
|
|
|
HarmonicActivePowerPaBase = 16000,
|
|
|
|
|
|
HarmonicActivePowerPbBase = 16100,
|
|
|
|
|
|
HarmonicActivePowerPcBase = 16200,
|
|
|
|
|
|
HarmonicActivePowerTotalBase = 16300,
|
|
|
|
|
|
HarmonicReactivePowerQaBase = 16400,
|
|
|
|
|
|
HarmonicReactivePowerQbBase = 16500,
|
|
|
|
|
|
HarmonicReactivePowerQcBase = 16600,
|
|
|
|
|
|
HarmonicReactivePowerTotalBase = 16700,
|
|
|
|
|
|
HarmonicApparentPowerSaBase = 16800,
|
|
|
|
|
|
HarmonicApparentPowerSbBase = 16900,
|
|
|
|
|
|
HarmonicApparentPowerScBase = 17000,
|
|
|
|
|
|
HarmonicApparentPowerTotalBase = 17100,
|
|
|
|
|
|
|
|
|
|
|
|
// 谐波含有率 2-50 次:三相电压、三相电流、线电压
|
|
|
|
|
|
VoltageHarmonicRatioUaBase = 18000,
|
|
|
|
|
|
VoltageHarmonicRatioUbBase = 18100,
|
|
|
|
|
|
VoltageHarmonicRatioUcBase = 18200,
|
|
|
|
|
|
CurrentHarmonicRatioIaBase = 18300,
|
|
|
|
|
|
CurrentHarmonicRatioIbBase = 18400,
|
|
|
|
|
|
CurrentHarmonicRatioIcBase = 18500,
|
|
|
|
|
|
LineVoltageHarmonicRatioUabBase = 18600,
|
|
|
|
|
|
LineVoltageHarmonicRatioUbcBase = 18700,
|
|
|
|
|
|
LineVoltageHarmonicRatioUcaBase = 18800,
|
2026-04-22 10:40:19 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 统计值类型:用于把 MIN / MAX / AVG / P95 装进同一时间桶。
|
|
|
|
|
|
enum class StatValueKind
|
|
|
|
|
|
{
|
|
|
|
|
|
Unknown = 0,
|
|
|
|
|
|
Min, // 最小值
|
|
|
|
|
|
Max, // 最大值
|
|
|
|
|
|
Avg, // 平均值
|
|
|
|
|
|
P95 // 95 值 / 百分位 95
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 指标质量状态。
|
|
|
|
|
|
// Normal 表示当前指标可正常使用;其他状态用于把“重复来源/全零/量程异常/缺失”显式暴露出来,
|
|
|
|
|
|
// 防止后续新增指标时继续出现静默覆盖或误识别。
|
|
|
|
|
|
enum class StatMetricQuality
|
|
|
|
|
|
{
|
|
|
|
|
|
Normal = 0,
|
|
|
|
|
|
AllZero,
|
|
|
|
|
|
DuplicateSource,
|
|
|
|
|
|
SuspiciousRange,
|
|
|
|
|
|
Missing
|
|
|
|
|
|
};
|
2026-04-22 10:40:19 +08:00
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 单个“已展开的统计样本点”
|
|
|
|
|
|
// 含义:某个统计 observation 中某个通道/某个序列/某个时间点的一条已还原工程值样本。
|
|
|
|
|
|
struct ExpandedStatPoint
|
|
|
|
|
|
{
|
|
|
|
|
|
time_t timestamp = 0; // 样本对应的绝对时刻
|
|
|
|
|
|
std::string timestamp_text; // 格式化后的时间文本,便于日志和调试
|
|
|
|
|
|
|
|
|
|
|
|
int observation_index = -1; // 来源 observation 索引
|
|
|
|
|
|
int channel_instance_index = -1; // 来源通道实例索引
|
|
|
|
|
|
int channel_def_index = -1; // 来源通道定义索引,便于排查同名/同相通道覆盖
|
|
|
|
|
|
int channel_group_id = 0; // 来源通道分组 ID;部分厂家用它表示谐波次数
|
|
|
|
|
|
int channel_spectrum_order_hint = -1; // 当 group/base/nominal 缺失时,从同类通道实例顺序推导出的谐波次数 2..50
|
|
|
|
|
|
int channel_spectrum_block_offset = -1; // 同类通道实例块内偏移;用于排查厂家把谱线拆成多个通道但名称相同的情况
|
|
|
|
|
|
int channel_spectrum_block_size = 0; // 同类通道实例候选总数;用于日志确认是否是 2-50 次整组数据
|
|
|
|
|
|
int series_instance_index = -1; // 来源序列实例索引
|
|
|
|
|
|
int series_def_index = -1; // 来源序列定义索引,便于核查 MIN/MAX/AVG/P95 的定义来源
|
|
|
|
|
|
int sample_index = -1; // 序列内部样本点下标
|
|
|
|
|
|
|
|
|
|
|
|
std::string observation_name; // 来源 observation 名称
|
|
|
|
|
|
std::string channel_name; // 通道名称(如 V RMS A)
|
|
|
|
|
|
std::string quantity_name; // 量名称(来自定义层)
|
|
|
|
|
|
unsigned int phase_id = 0; // 相别
|
|
|
|
|
|
PqdifGuidValue quantity_type_id; // 量类型(VALUELOG 等)
|
|
|
|
|
|
unsigned int quantity_measured_id = 0; // 被测量对象(Voltage / Current)
|
|
|
|
|
|
unsigned int quantity_units_id = 0; // 单位 ID
|
|
|
|
|
|
PqdifGuidValue quantity_characteristic_id;// 特征量(RMS / FREQUENCY)
|
|
|
|
|
|
PqdifGuidValue value_type_id; // 值类型(MIN / MAX / AVG / P95)
|
|
|
|
|
|
|
|
|
|
|
|
double prob_percentile = 0.0; // 序列定义中的概率百分位(若有)
|
|
|
|
|
|
double series_base_quantity = 0.0; // 序列基值;部分 PQDIF 厂家会用它表达谐波次数
|
|
|
|
|
|
double nominal_quantity = 0.0; // 标称量;部分 PQDIF 厂家会用它表达谐波次数
|
|
|
|
|
|
double value = 0.0; // 工程值(已完成 scale/offset 还原)
|
|
|
|
|
|
|
|
|
|
|
|
ParsedConnectionKind connection_kind = ParsedConnectionKind::Unknown; // 当前文件识别出的接线方式
|
|
|
|
|
|
StatMetricId metric_id = StatMetricId::Unknown; // 该样本点识别出的业务指标
|
|
|
|
|
|
StatValueKind stat_kind = StatValueKind::Unknown; // 该样本点属于 MIN/MAX/AVG/P95 哪一种
|
|
|
|
|
|
|
|
|
|
|
|
bool matched_by_name_fallback = false; // 是否通过名称辅助规则匹配成功
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 某一个业务指标在某个时间点上的统计值集合
|
|
|
|
|
|
struct AggregatedStatValues
|
|
|
|
|
|
{
|
|
|
|
|
|
bool has_min = false; // 是否存在最小值
|
|
|
|
|
|
bool has_max = false; // 是否存在最大值
|
|
|
|
|
|
bool has_avg = false; // 是否存在平均值
|
|
|
|
|
|
bool has_p95 = false; // 是否存在 95 值
|
|
|
|
|
|
|
|
|
|
|
|
double min_value = 0.0; // 最小值
|
|
|
|
|
|
double max_value = 0.0; // 最大值
|
|
|
|
|
|
double avg_value = 0.0; // 平均值
|
|
|
|
|
|
double p95_value = 0.0; // 95 值
|
|
|
|
|
|
|
|
|
|
|
|
StatMetricQuality quality = StatMetricQuality::Normal; // 指标质量状态
|
|
|
|
|
|
std::string quality_reason; // 质量状态说明
|
|
|
|
|
|
|
|
|
|
|
|
int source_observation_index = -1; // 选中的来源 observation 索引
|
|
|
|
|
|
int source_channel_instance_index = -1; // 选中的来源通道实例索引
|
|
|
|
|
|
int source_series_instance_index = -1; // 最近一次写入该桶的来源序列实例索引
|
|
|
|
|
|
std::string source_channel_name; // 选中的来源通道名称
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 同一时刻聚合桶
|
|
|
|
|
|
// 含义:在“已筛选出的统计类 observation”内,某个 timestamp 下所有已识别指标的统计值集合。
|
|
|
|
|
|
struct TimeAggregatedStatBucket
|
|
|
|
|
|
{
|
|
|
|
|
|
time_t timestamp = 0; // 聚合时刻
|
|
|
|
|
|
std::string timestamp_text; // 格式化时间文本
|
|
|
|
|
|
|
|
|
|
|
|
std::map<StatMetricId, AggregatedStatValues> metrics; // 当前时刻下各指标的统计值
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PQDIF 统计桶 Base64 子记录对象
|
|
|
|
|
|
// 对象用途:保存“一个 PQDIF 文件 + 一个时间点 + 一种统计类型”的最终 Base64 组装结果。
|
|
|
|
|
|
// 数据粒度:例如同一个时间点会有 Max、Min、Avg、P95 四条子记录。
|
|
|
|
|
|
// 注意:v20 起它不再直接作为全局队列元素,而是作为
|
|
|
|
|
|
// PqdifStatBase64TimePointPacket.records 的子对象存在。
|
|
|
|
|
|
struct PqdifStatBase64Record
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string pqdif_file_path; // 对象来源:PQDIF 文件全路径,便于后续处理时追溯文件
|
|
|
|
|
|
StatValueKind value_kind = StatValueKind::Unknown; // 对象统计类型:Max / Min / Avg / P95
|
|
|
|
|
|
std::string value_kind_name; // 对象统计类型文本:便于日志/外部队列直接查看
|
|
|
|
|
|
int value_kind_code = 0; // 对象统计类型编码:兼容旧统计队列,1=Max, 2=Min, 3=Avg, 4=P95
|
|
|
|
|
|
time_t timestamp = 0; // 对象时间戳:该 Base64 数据所属的桶时间点
|
|
|
|
|
|
std::string timestamp_text; // 对象时间文本:格式化时间点,便于日志、人眼核查
|
|
|
|
|
|
std::string base64_payload; // 对象数据主体:float 按星型/角型顺序组装后整体转换成的 Base64 字符串
|
|
|
|
|
|
size_t float_count = 0; // 对象校验字段:本条记录实际组装的 float 数量
|
|
|
|
|
|
size_t placeholder_count = 0; // 对象校验字段:本条记录中使用 3.14159f 占位的数量
|
|
|
|
|
|
ParsedConnectionKind connection_kind = ParsedConnectionKind::Unknown; // 对象接线方式:星型/角型/未知
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// PQDIF Base64 时间点包对象
|
|
|
|
|
|
// 对象用途:把同一个 PQDIF 文件、同一个时间点下的 Max/Min/Avg/P95 四类 Base64 子记录合并保存。
|
|
|
|
|
|
// 设计原因:后续处理时可以按时间点一次性拿到四种统计类型,避免散落成单条记录。
|
|
|
|
|
|
struct PqdifStatBase64TimePointPacket
|
|
|
|
|
|
{
|
|
|
|
|
|
time_t timestamp = 0; // 对象时间戳:该时间点包对应的桶时间点
|
|
|
|
|
|
std::string timestamp_text; // 对象时间文本:格式化时间点,便于日志、人眼核查
|
|
|
|
|
|
std::vector<PqdifStatBase64Record> records; // 对象子记录:同一时间点下的 Max/Min/Avg/P95 Base64 记录
|
|
|
|
|
|
|
|
|
|
|
|
size_t record_count = 0; // 对象统计字段:records.size() 的冗余统计,便于日志核查
|
|
|
|
|
|
size_t total_float_count = 0; // 对象统计字段:当前时间点下所有子记录的 float 数量合计
|
|
|
|
|
|
size_t total_placeholder_count = 0;// 对象统计字段:当前时间点下所有子记录的占位数量合计
|
|
|
|
|
|
size_t total_base64_chars = 0; // 对象统计字段:当前时间点下所有子记录 base64 字符数合计
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// PQDIF Base64 文件级批次对象
|
|
|
|
|
|
// 对象用途:保存“一个 PQDIF 文件解析完成后”的全部 Base64 时间点包。
|
|
|
|
|
|
// 数据粒度:全局队列中的一个元素就是一个 PqdifStatBase64FileBatch,文件之间不会混合。
|
|
|
|
|
|
struct PqdifStatBase64FileBatch
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string pqdif_file_path; // 对象来源:PQDIF 文件全路径
|
|
|
|
|
|
std::string source_file; // 对象来源:原始文件路径,通常与 pqdif_file_path 一致或接近
|
|
|
|
|
|
std::string mac; // 对象来源:设备目录名/设备标识
|
|
|
|
|
|
time_t parsed_at = 0; // 对象生成时间戳:解析完成时间
|
|
|
|
|
|
std::string parsed_at_text; // 对象生成时间文本:格式化解析完成时间
|
|
|
|
|
|
ParsedConnectionKind connection_kind = ParsedConnectionKind::Unknown; // 对象接线方式:星型/角型/未知
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<PqdifStatBase64TimePointPacket> time_points; // 对象主体:文件内所有时间点包
|
|
|
|
|
|
|
|
|
|
|
|
size_t time_point_count = 0; // 对象统计字段:time_points.size() 的冗余统计,便于日志核查
|
|
|
|
|
|
size_t total_record_count = 0; // 对象统计字段:文件内全部 Max/Min/Avg/P95 子记录数量
|
|
|
|
|
|
size_t total_float_count = 0; // 对象统计字段:文件内全部 float 数量
|
|
|
|
|
|
size_t total_placeholder_count = 0;// 对象统计字段:文件内全部占位数量
|
|
|
|
|
|
size_t total_base64_chars = 0; // 对象统计字段:文件内全部 base64 字符数
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 一个 PQDIF 文件的暂存对象
|
2026-04-22 10:40:19 +08:00
|
|
|
|
struct ParsedPqdifFile
|
|
|
|
|
|
{
|
2026-04-29 13:35:49 +08:00
|
|
|
|
std::string mac; // 设备目录名
|
|
|
|
|
|
std::string source_file; // 原始文件路径
|
|
|
|
|
|
time_t parsed_at = 0; // 解析完成时间
|
|
|
|
|
|
|
|
|
|
|
|
// 新结构:完整 PQDIF 拆分结果
|
|
|
|
|
|
PqdifLogicalFile logical_file;
|
|
|
|
|
|
|
|
|
|
|
|
// 统计识别与聚合层结果
|
|
|
|
|
|
ParsedConnectionKind connection_kind = ParsedConnectionKind::Unknown; ///< 当前文件识别出的接线方式
|
|
|
|
|
|
int selected_observation_index = -1; ///< 当前阶段被选中的“统计类 observation”索引
|
|
|
|
|
|
std::string selected_observation_name; ///< 当前阶段被选中的“统计类 observation”名称
|
|
|
|
|
|
std::vector<ExpandedStatPoint> expanded_stat_points; ///< 从 PQDIF 展开的全部统计样本点
|
|
|
|
|
|
std::vector<TimeAggregatedStatBucket> aggregated_stat_buckets; ///< 按 timestamp 聚合后的时间桶
|
2026-04-22 10:40:19 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 启动 PQDIF 扫描线程
|
2026-04-22 10:40:19 +08:00
|
|
|
|
void RunPqdifScanLoop();
|
|
|
|
|
|
|
2026-04-29 13:35:49 +08:00
|
|
|
|
// 缓存访问接口
|
2026-04-22 10:40:19 +08:00
|
|
|
|
bool PopOldestParsedPqdifFile(ParsedPqdifFile& out);
|
|
|
|
|
|
bool PeekOldestParsedPqdifFile(ParsedPqdifFile& out);
|
|
|
|
|
|
size_t GetParsedPqdifCacheSize();
|
2026-04-29 13:35:49 +08:00
|
|
|
|
void ClearParsedPqdifCache();
|
|
|
|
|
|
|
|
|
|
|
|
// PQDIF 统计桶 Base64 “生成队列”访问接口
|
|
|
|
|
|
// 对象用途:该队列由解析流程写入,RunPqdifScanLoop() 每轮循环末尾会尝试把其中一个文件批次
|
|
|
|
|
|
// 移动到“待后续处理队列”。如果外部仍需直接读取生成队列,可以继续使用以下旧接口。
|
|
|
|
|
|
// v20 起:队列元素 = 一个 PQDIF 文件批次。
|
|
|
|
|
|
bool PopOldestPqdifStatBase64FileBatch(PqdifStatBase64FileBatch& out);
|
|
|
|
|
|
bool PeekOldestPqdifStatBase64FileBatch(PqdifStatBase64FileBatch& out);
|
|
|
|
|
|
|
|
|
|
|
|
// 兼容旧接口:如旧代码仍按单条 Base64 子记录读取,会从文件批次队列的最早文件/最早时间点中拆出一条。
|
|
|
|
|
|
bool PopOldestPqdifStatBase64Record(PqdifStatBase64Record& out);
|
|
|
|
|
|
bool PeekOldestPqdifStatBase64Record(PqdifStatBase64Record& out);
|
|
|
|
|
|
|
|
|
|
|
|
// 返回当前生成队列文件级批次数量;如需查看内部子记录数量,使用 GetPqdifStatBase64RecordCountInQueue()。
|
|
|
|
|
|
size_t GetPqdifStatBase64QueueSize();
|
|
|
|
|
|
size_t GetPqdifStatBase64RecordCountInQueue();
|
|
|
|
|
|
void ClearPqdifStatBase64Queue();
|
|
|
|
|
|
|
|
|
|
|
|
// PQDIF 统计桶 Base64 “待后续处理队列”访问接口
|
|
|
|
|
|
// 对象用途:RunPqdifScanLoop() 已经从生成队列取出、准备交给后续入库/上传/推送流程的数据会放在这里。
|
|
|
|
|
|
// 推荐后续业务优先调用 PopReadyPqdifStatBase64FileBatch(),一次取出一个完整 PQDIF 文件批次。
|
|
|
|
|
|
bool PopReadyPqdifStatBase64FileBatch(PqdifStatBase64FileBatch& out);
|
|
|
|
|
|
bool PeekReadyPqdifStatBase64FileBatch(PqdifStatBase64FileBatch& out);
|
|
|
|
|
|
size_t GetReadyPqdifStatBase64QueueSize();
|
|
|
|
|
|
size_t GetReadyPqdifStatBase64RecordCountInQueue();
|
|
|
|
|
|
void ClearReadyPqdifStatBase64Queue();
|