Files
microser/mms/rdb_client.h
2025-01-16 16:17:01 +08:00

510 lines
16 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file iec103ttylink.h
* @brief IEC61850 与rdb 交互处理 的头文件
*
* @version $Revision: 1.18 $
* @date $Date: 2018/12/29 12:30:29 $
* @author $Author: lizhongming $
* @state $State: Exp $
* @latest $Id: rdb_client.h,v 1.18 2018/12/29 12:30:29 lizhongming Exp $
*/
#ifndef _RDB_CLIENT_H_XSDFSDFSEFS15156SFS
#define _RDB_CLIENT_H_XSDFSDFSEFS15156SFS
#include "interface.h"
#include "ied.h"
#include "node.h"
//lnk20250113添加包含台账定义的头文件
#include "../json/save2json.h"
#include <stdbool.h>
//文件有效时间的取值
#define FROM_FILE_NAME (0)
#define FROM_SYSTEM (1)
//通用文件存放的目录
#define GENERAL_PREFIX "0_0"
#define GENERAL_PATH "0_0\\19700101\\00"
//iec report 数据到达状态
#define VALUE_REACHED (0x01) // 状态或遥测值已收到
#define Q_REACHED (0x02) // 数据质量已收到
#define T_REACHED (0x04) // 时标已收到
#define REASON_REACHED (0x08) // 发送原因已收到
//CHANNELSTATE macro defines
#define CHANNEL_CONNECTING (0x01) //
#define CHANNEL_CONNECTED (0x02) //
#define CHANNEL_DISCONNECTING (0x03) //
#define CHANNEL_DISCONNECTED (0x04) //
#define RELAY_SELECT (0x01) //
#define RELAY_RUN (0x02) //
#define RELAY_CANCEL (0x03) //
#define MIN_INIT_NUM (10) //链路层完全初始化最少次数,作为可以进行召唤录波文件的条件。
#define NEXT_CONNECT_TIME (10000) //一次链接失败后下次链接时间间隔10*1000=10s
#define MAX_SAME_FCDNAME_OBJECTS (500) // for 灿能PQ装置改成64 2016-5-10 //最多一个FCD分成多个对象的个数 ,如一个 ACT对象分成generalphsabc等数个对象
/** ======================浙江渔都变顺控扩展同期功能============================ */
/*
16:按定值方式合闸
17:不检同期合闸
18:检同期合闸
19:检无压合闸
CHECK_BY_SETTING CHECK_U 对应顺控票同期遥控点的第一个遥控点
CHECK_NOTHING CHECK_SYN 对应顺控票同期遥控点的第二个遥控点
*/
#define CHECK_START_QU 16
#define CHECK_BY_SETTING 0
#define CHECK_NOTHING 1
#define CHECK_SYN 2
#define CHECK_U 3
#define DEFAULT_EDIT_FXDAREANO (0x80FE) /**< 默认编辑区定值区号 */
#define FIXED_AREA_GRP_DOT2_EDIT_AREA (2) /**< 定值区组->编辑定值区点 */
extern unsigned int g_node_id;
typedef struct element_usr_t element_usr_t;
typedef struct rptinfo_t rptinfo_t;
typedef struct loginfo_t loginfo_t;
typedef struct LD_info_t LD_info_t;
typedef struct ied_usr_t ied_usr_t;
typedef struct chnl_usr_t chnl_usr_t;
typedef struct autorecall_t autorecall_t;
typedef struct ied_info_t ied_info_t;
//////////////////////////////////////////////////////////
struct autorecall_t {
long long start;
long long end;
int need_steady; //lnk20241030添加补招稳态暂态标志
int need_voltage;
};
//////////////////////////////////////////////////////////
struct ied_info_t{
char time[50][20];
unsigned char name[50][128];
char value[50][20];
};
//lnk20250113添加台账更新结构///////////////////////////////
#define MAX_UPDATEA_NUM 300
typedef struct trigger_update_xml_t trigger_update_xml_t;
struct trigger_update_xml_t{
int work_update_num;
int new_update_num;
int delete_update_num;
int modify_update_num;
terminal work_updates[MAX_UPDATEA_NUM];
terminal new_updates[MAX_UPDATEA_NUM];
terminal delete_updates[MAX_UPDATEA_NUM];
terminal modify_updates[MAX_UPDATEA_NUM];
};
//////////////////////////////////////////////////////////
#define MAX_TRIGGER_NUM 300
typedef struct trigger_t trigger_t;
struct trigger_t{
int dev_idx;
int line_id;
int real_data;
int soe_data;
int limit;
int count;
};
typedef struct trigger_3s_xml_t trigger_3s_xml_t;
struct trigger_3s_xml_t{
int work_trigger_num;
int new_trigger_num;
int delete_trigger_num;
int modify_trigger_num;
trigger_t work_triggers[MAX_TRIGGER_NUM];
trigger_t new_triggers[MAX_TRIGGER_NUM];
trigger_t delete_triggers[MAX_TRIGGER_NUM];
trigger_t modify_triggers[MAX_TRIGGER_NUM];
};
/////////////////////////////////
#define MAX_RECALL_NUM 300
typedef struct recall_t recall_t;
struct recall_t{
char* line_id;
long long start_time; //待召唤日志起始时间
long long end_time; //待召唤日志结束时间
int need_steady;
int need_voltage;
};
typedef struct recall_xml_t recall_xml_t;
struct recall_xml_t{
int work_recall_num;
int new_recall_num;
recall_t work_recalls[MAX_RECALL_NUM];
recall_t new_recalls[MAX_RECALL_NUM];
};
/////////////////////////////////////////////////////////////
struct element_usr_t{
char* FCD_ref;
char* FCDA_ref;
char* Full_FCDA_ref;
double m_v;
char q[14]; //q use 13 bits
systime_t tm;
char reason[7]; // reserve 1 bit, use 5 bits
uint32_t DataStatus;
int m_num_same_FCD_Objects;
// element_t* m_pSameFCDObjects[MAX_SAME_FCDNAME_OBJECTS];
int num_same_FCDA_Objects;
// element_t* pSame_FCDA_Objects[MAX_SAME_FCDNAME_OBJECTS];
byte_t is_phase_soe;
byte_t last_soe_status;
};
struct rptinfo_t{
char* rptID;
byte_t instanceNeedSuffix; //实例名是否增加后缀
byte_t TrgOpt;
byte_t OptFlds [2]; /* 10 bit bitstring but only allow write of 9 bits*/
uint32_t IntgPd; //完整性上送时间(秒)
int report_PQ_type; //报告前置类型统计、实时、soe、事件类型等
LD_info_t* LD_info;
int rpt_registered; //是否注册成功
byte_t chnl_id; //如果未注册,下次试图注册报告的通道号
//如果已注册,则是本次注册报告的通道号
RCB_INFO * m_rcb_info;
double m_LastDataTime; //上次收到数据的时间
double m_LastGITime; //上次GI的时间
double m_LastRegisterFailedTime; //上次注册失败的时间
double m_LastUnRegisterFailedTime; //上次取消注册失败的时间
byte_t m_EntryID[8];
int m_curRptSuffix;
int count; //收到报告数据的次数
int rptNo;//CZY 2023-08-17 WW 2022-11-14增加编号用于匹配数据收集
int flickerflag;//CZY 2023-08-17 WW 2022-11-14增加闪变标志
int pstflag;//CZY 2023-08-17 WW 2022-11-14增加短闪闪变标志
};
struct loginfo_t{
char* lcbName;
char* datasetName;
char logName[32];
uint32_t IntgPd; //完整性上送时间(秒)
byte_t reasonCode;
byte_t TrgOpt;
LD_info_t* LD_info;
//LCB_INFO * m_lcb_info;
apr_time_t start_time; //待召唤日志起始时间
apr_time_t end_time; //待召唤日志结束时间
//double last_checktime;
int need_steady;
int need_voltage;
};
#define QVVR_NUM (256)
#define QVVR_DATA_NOT_USED (0)
#define QVVR_DATA_RECEIVED (1)
#define QVVR_DATA_PAIRED (2)
typedef struct QVVR_t QVVR_t;
struct QVVR_t{
int used_status;
int QVVR_start;
int QVVR_type;
long long QVVR_time;
float QVVR_PerTime;
float QVVR_Amg;
char QVVR_Rptname[128];
uint32_t timestamp;
};
struct LD_info_t{
char name[256];
ied_t *ied;
byte_t cpuno;
char *LD_name;
apr_hash_t *ht_fcd; /**< FCD object hash索引 到 element */
apr_hash_t *ht_full_fcda; /**< 完整FCDA object hash索引 到 element */
int rptcount; /**< report 个数 */
rptinfo_t **rptinfo; /**< rptinfo_t* 数组 */
int read_flag ; //CZY 2023-02-28 判断是否将监测点是否有效
char mp_id[256];//CZY 2023-08-20 监测点编码8afaa
char terminal_code[256];//CZY 2023-08-20 终端编码
//int ld_ins;//CZY 2023-08-20 逻辑设备实例号1
char voltage_level[256];//CZY 2023-08-20 电压等级30
char v_wiring_type[256];//CZY 2023-08-20 监测点电压接线方式01-三相星型02-三相角型
long long time; //CZY 2023-08-20 时间戳(秒) 台账更新时间1691656669
int update_flag;//CZY 2023-08-20 台账更新标志 0:keep 2:delete 4:update 8:add
char monitor_status[64]; //lnk20241031监测点状态
//报告
int rptRecvFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,rptRecvFlag=有效报告序号相加
int rptRecvCheckFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,每次收到报告相加与rptRecvFlag一起判断是否收完
int rptPstRecvFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,rptRecvFlag=有效报告序号相加
int rptPstRecvCheckFlag;//CZY 2023-08-17 WW 2022-11-14判断报告是否收齐,每次收到报告相加与rptRecvFlag一起判断是否收完
//报告
//不使用
int iUnitOfTime;//CZY 2023-08-17 WW 2022年12月7日15:43:34 装置上送事件持续时间单位切换(0-ms; 1-s)
int iStatOfTime;//CZY 2023-08-17 WW 2022年12月7日15:48:33 统计数据时间 0-北京时间 1-UTC时间
int iJournalTime;//CZY 2023-08-17 WW 2022年12月7日15:52:32 补招日志时间(0-UTC时间(日志、录波文件均为UTC时间); 1-北京时间(日志北京时间、录波文件UTC时间 注:仅四川地区+8小时读取补招日志))
//不使用
//日志
int logcount; /**< log 个数 */
loginfo_t **loginfo; /**< loginfo_t* 数组 */
//日志
//补招
int autorecallflag;
int autorecallcount;
autorecall_t **autorecall;
//补招
//不使用
uint32_t group; //add by rzx
//不使用
//实时数据
int line_id;
//实时数据
//录波
int FltNum[256];
//录波
//实时数据
int real_data;
int soe_data;
int limit;
int count;
//实时数据
//不使用
int SubV_Index;
int Dev_Index;
int Sub_Index;
int GD_Index;
//不使用
//process QVVR
QVVR_t qvvr[QVVR_NUM];
int qvvr_idx;
//暂态
//process RDRE
int RDRE_FltNum;
//录波
};
struct ied_usr_t{
LD_info_t *LD_info; /**< LD数组 */
int dev_idx; /**< 设备序号 */
char dev_type[256]; /**< 设备类型 */
char dev_key[256]; /**< 设备秘钥 */
char dev_series[256]; /**< 设备识别码 */
int dev_flag; /**< 设备标志 */
void *cookie;
double last_call_wavelist_time ; //上次召录波列表时间
char terminal_id[256];//CZY 2023-08-20 终端id8afaa9a15707483a0157262f8e78077d
char org_name[256];//CZY 2023-08-20 所属单位,例:南京供公司
char maint_name[256];//CZY 2023-08-20 运维单位,例:南京供公司
char station_name[256];//CZY 2023-08-20 所属变电站220kV五台山变
char tmnl_factory[256];//CZY 2023-08-20 终端厂家,例:南京自动化股份有限公司
long long time; //CZY 2023-08-20 时间戳(秒) 台账更新时间1691656669
char tmnl_status[256];//CZY 2023-08-30 运行状态
char terminal_code[256];//CZY 2023-08-30 终端编码
int update_flag;//CZY 2023-08-20 台账更新标志 0:keep 2:delete 4:update 8:add
};
struct chnl_usr_t{
byte_t chnl_id;
char ip_str[20];
channel_t *chnl; /**< 对应的channel 指针 */
MVL_NET_INFO *net_info;
MVL_REQ_PEND *m_reqCtrl; //MVL_REQ_PEND
int m_state;
double m_StartConnectingTime; //这次开始 connect 的时间
double m_StartDisconnectingTime; //这次开始 disconnect 的时间
double m_ClosedMsTime; //上次通道关闭时间
double m_LastPosRespTime; //上次肯定响应的时间
int m_NegRespTimes; // 累计否定响应次数
};
typedef struct pt61850app_t pt61850app_t;
struct pt61850app_t
{
// rdb_t *rdb;
node_t *node;
// driver_t *driver;
//byte_t IsMaster; //当前的主备状态
////////////////////////////
uint32_t mmsOpTimeout; //mms操作读写变量等的交互超时时间
//uint32_t relayTimeout; //遥控等待遥信返回的超时时间
uint32_t giTime; //总查询时间
int rptSuffix[2][2]; //报告控制块后缀
//char ftp_srv_ip[16];
//char ftpsrv_path[64];
//char ftp_user[32];
//char ftp_password[32];
char accPath[65]; //装置录波文件路径
//char RcdMadeAddStr[65]; //录波动作遥信地址
//uint8_t change_file_name; //保存时,是否修改文件名
uint32_t chnl_counts;
chnl_usr_t **chnl_usr;
apr_pool_t *tmp_pool; // 临时pool
//链路层完全初始化次数,作为可以进行召唤录波文件的条件。即确保所有装置初始化最少一次后才允许开始召唤文件
uint8_t initNum;
//召唤文件类型为0则只召唤对应目录下的录波文件为1则召唤对应目录下的所有文件其余留待扩展
//uint8_t call_file_type;
//数字量入库前是否检查值有效
uint8_t check_dgtVal;//0不判非0判
};
//为无锡西径变调档添加
extern uint8_t set_mx_q;
#ifdef _OS_WIN32_
#pragma pack(push,1)
#endif
#ifdef _OS_WIN32_
#pragma pack(pop)
#endif
#ifdef __cplusplus
extern "C" {
#endif
char* str_trim_both(char* temp,const char* pattern) ;
element_usr_t* GET_DOTEXT_ADDR(element_t *elem);
ied_usr_t* GET_IEDEXT_ADDR(ied_t *ied);
ST_RET mms_jread (loginfo_t *loginfo,MVL_NET_INFO *clientNetInfo, ST_CHAR *dom_name,ST_CHAR *logName, apr_time_t start_time,apr_time_t end_time,ST_INT iTimeout, ST_CHAR* ip) ;
LD_info_t* find_LD_from_cpuId(ied_t* ied,byte_t cpuId);
LD_info_t* find_LD_from_IEDLDName(ied_t* ied, char *IEDLDName);
LD_info_t* find_LD_from_cpuCount_and_LEDRs(ied_t* ied, byte_t cpuCount);
LD_info_t* find_LD_from_IEDLDName_in_report(ied_t* ied, char *IEDLDName);
LD_info_t* find_LD_from_element(element_t* elem);
rptinfo_t* find_rptinfo_from_net_rcb_info(MVL_NET_INFO *net_info,RCB_INFO *rcb_info);
rptinfo_t* find_rptinfo_from_net_rpt_info_name(MVL_NET_INFO *net_info, RCB_INFO *rcb_info);
void get_rpt_inst_name(rptinfo_t *rptinfo, char * rpt_inst_name );
/**
* @brief 初始化rdb库相关内容
* @return 如果创建成功,返回 APR_SUCCESS
*/
apr_status_t init_rdb();
/**
* @brief 启动规约处理相关线程
* @return 如果成功,返回 APR_SUCCESS
*/
apr_status_t run_protocol();
void Set_val_from_61850rpt(element_t* elem,double v);
int Set_q_from_61850rpt(char* q);
apr_status_t init_rem_dib_table();
void CheckNextNotConnectedChannel();
//WW 2023-08-22
int HandleReceiveMessage(int socketClient, char buffer[256]);
int ExecuteWebCommand(LD_info_t *LD_info, int iType);
int SendMessageToWeb(int socketClient, int iErrorCode); //向Web Socket客户端发送消息
//WW 2023-08-22 end
void CheckAllConnectedChannel() ;
void check_3s_config();
void check_recall_config();
void create_recall_xml();
void check_disk_quota();
apr_status_t prepare_call_cn_wavelist(LD_info_t *LD_info, int FltNum );
apr_status_t call_cn_wavelist(LD_info_t *LD_info);
void strip_file_name_tail_to_ms(char *fileName);
//////////for pq //////////////////////////////////////////
ied_t* find_ied_from_dev_idx(int dev_idx);
ied_t* find_ied_from_dev_code(char dev_idx[]);
LD_info_t* find_LD_info_from_line_id(ied_t* ied, int line_id);
LD_info_t* find_LD_info_only_from_line_id(int line_id);
LD_info_t* find_LD_info_from_mp_id(ied_t* ied, char* mp_id);
LD_info_t* find_LD_info_only_from_mp_id(char* mp_id);
////////////////////////////////lnk20250115
int parse_ledger_update_xml(trigger_update_xml_t* trigger_update_xml);
extern const int MAX_CPUNO;
extern int stringToInt(const char* str, int* result);
extern bool isCharPtrEmpty(const char* str);
extern int parse_ledger_update_xml(trigger_update_xml_t* trigger_update_xml);
extern int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_index);
extern void print_trigger_update_xml(const trigger_update_xml_t* trigger_update);
////////////////////////////////
int parse_3s_xml(trigger_3s_xml_t* trigger_3s_xml);
int create_3s_xml(trigger_3s_xml_t* trigger_3s_xml);
int get_real_report_count(LD_info_t *LD_info);
int delete_recall_xml(char* id);
int parse_recall_xml(recall_xml_t* recall_xml,char *id);
void process_recall_config(recall_xml_t* recall_xml);
int remove_recall_xml();
int init_rptctrl_by_count(LD_info_t* LD_info,int rptcount);
int fill_rptctrl_by_cfg(LD_info_t* LD_info,int rptno,char *buf);
int init_logctrl_by_count(LD_info_t* LD_info,int logcount);
int fill_logctrl_by_cfg(LD_info_t* LD_info,int logno,char *buf,char* devtype);
//////////////////////////////////////////////////////////
void processQVVR_start(LD_info_t* LD_info);
void processQVVR_time(LD_info_t* LD_info, long long Time);
void processQVVR_data(LD_info_t* LD_info,char* FULL_FCDA_Name,double v);
void processQVVR_end(LD_info_t* LD_info);
void processRDRE_start(LD_info_t* LD_info);
void processRDRE_data(LD_info_t* LD_info,char* FULL_FCDA_Name,double v);
void processRDRE_end(LD_info_t* LD_info);
int extract_timestamp_from_cfg_file(char *comtrade_fn,long long *start_tm,long long *trig_tm);
int parse_file_names(char *file_match_str,char **filenames,int filenum,int *cfg_idx,int *dat_idx,char *file_base_name,char *file_yyyymm);
int parse_file_names_by_fltnum(int fltnum, char* domname, char** filenames, int filenum, int* cfg_idx, int* dat_idx, char* file_base_name, char* file_yyyymm);
QVVR_t* find_qvvr_by_trig_tm(LD_info_t* LD_info,long long trig_tm);
//////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif /* _RDB_CLIENT_H_XSDFSDFSEFS15156SFS */