/** * @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 //文件有效时间的取值 #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对象,分成general,phsa,b,c等数个对象 /** ======================浙江渔都变顺控扩展同期功能============================ */ /* 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) /**< 定值区组->编辑定值区点 */ //lnk添加使能标志20250121 #define ENABLE 1 #define UNUSED 0 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 10 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; double QVVR_PerTime; double 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 终端id,例:8afaa9a15707483a0157262f8e78077d 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 char processNo[64];//台账进程号 }; 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; int stringToInt(const char* str, int* result); bool isCharPtrEmpty(const char* str); int parse_ledger_update_xml(trigger_update_xml_t* trigger_update_xml); int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_index,int ied_take); void print_trigger_update_xml(const trigger_update_xml_t* trigger_update); char* parse_model_cfg_web_one(ied_t* ied); void Set_xml_nodeinfo_one(char* dev_type); void create_ledger_log(trigger_update_xml_t* ledger_update_xml); ied_t* find_ied_unused(); int parse_rpt_log_ini_one(ied_t* ied); apr_status_t init_rem_dib_table_one(ied_t *ied); void clearIed(ied_t *ied); void clearIedUsr(ied_usr_t *ied_usr); //////////////////////////////// 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 */