diff --git a/cfg_parse/cfg_parser.cpp b/cfg_parse/cfg_parser.cpp index cedcdd4..c5ad1c0 100644 --- a/cfg_parse/cfg_parser.cpp +++ b/cfg_parse/cfg_parser.cpp @@ -13997,7 +13997,6 @@ void SOEFileWeb_test() /*/////////////////////////////////////////////////////////lnk10-24根据web接口修改/////////////////////////////////////////////////////////////*/ /*封装C可调用的台账更新函数 *///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//3-写入台账内容////////////////////////////// int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_index,int ied_take) { chnl_usr_t* chnl_usr = NULL; @@ -14203,17 +14202,17 @@ int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_i ldname = ied_usr->LD_info[cpuno - 1].LD_name; ///////// //清空已有的补招数组占用空间 - if (ied_usr->LD_info[cpuno - 1]->autorecallcount != 0) { - for (int j = 0; j < ied_usr->LD_info[cpuno - 1]->autorecallcount; j++) { - if(NULL != ied_usr->LD_info[cpuno - 1]->autorecall[j]){ - delete ied_usr->LD_info[cpuno - 1]->autorecall[j]; + if (ied_usr->LD_info[cpuno - 1].autorecallcount != 0) { + for (int j = 0; j < ied_usr->LD_info[cpuno - 1].autorecallcount; j++) { + if(NULL != ied_usr->LD_info[cpuno - 1].autorecall[j]){ + delete ied_usr->LD_info[cpuno - 1].autorecall[j]; } } - if(NULL != ied_usr->LD_info[cpuno - 1]->autorecall){ - delete ied_usr->LD_info[cpuno - 1]->autorecall; + if(NULL != ied_usr->LD_info[cpuno - 1].autorecall){ + delete ied_usr->LD_info[cpuno - 1].autorecall; } - ied_usr->LD_info[cpuno - 1]->autorecallcount = 0; + ied_usr->LD_info[cpuno - 1].autorecallcount = 0; } //////// //记录原有的报告和日志数组 @@ -14223,10 +14222,10 @@ int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_i //避免重复分配内存,如果使用已存在的ied,那么它之前初始化就分配了哈希表,如果在删除台账时没有清除,则需要将原来的清除 if (ied_usr->LD_info[cpuno - 1].ht_fcd != NULL) { - apr_hash_destroy(ied_usr->LD_info[cpuno - 1].ht_fcd); + apr_hash_clear(ied_usr->LD_info[cpuno - 1].ht_fcd); } if (ied_usr->LD_info[cpuno - 1].ht_full_fcda != NULL) { - apr_hash_destroy(ied_usr->LD_info[cpuno - 1].ht_full_fcda); + apr_hash_clear(ied_usr->LD_info[cpuno - 1].ht_full_fcda); } ied_usr->LD_info[cpuno - 1] = line_info;//这个放在后面,因为需要先判断原有的指针 @@ -14251,12 +14250,7 @@ int update_one_terminal_ledger(terminal* update, int i,ied_t* ied,int terminal_i } return 0; } - //3-写入台账内容/////////////////////////////////// - //5-报告块初始化////////////////////////////// - //5-报告块初始化/////////////////////////////////// - //6-init_rem_dib_table////////////////////////////// - //6-init_rem_dib_table/////////////////////////////////// ////////////////////////////////////////////////////////////////////////台账更新记录日志 // 获取当前时间并格式化为 "YYYY-MM-DD HH:MM:SS" std::string get_current_time() { @@ -14273,7 +14267,7 @@ void write_log_entry(std::ofstream &log_file, const std::string &action, const s log_file << terminal_id << "\t" << action << "time:" << current_time << "\n"; } -// 创建台账日志 +// 创建台账更新日志 void create_ledger_log(trigger_update_xml_t* ledger_update_xml) { std::string log_filename = "../etc/" + std::string(LEDGER_UPDATE_FN); std::ofstream log_file(log_filename.c_str(), std::ios::app); // 以追加模式打开文件 @@ -14402,13 +14396,12 @@ int parse_rpt_log_ini_one(ied_t* ied) } for (cpuno = 0; cpuno < ied->cpucount; cpuno++) {//根据ied实际的检测点数遍历 LD_info = &(ied_usr->LD_info[cpuno]); + + //这些可能是已有的内存,经过判断才能从g_init_pool中分配内存,lnk20250122 char str[256]; char* tmp = Get_IED(ied_usr->dev_type); qDebug() << tmp << endl; - - //这些可能是已有的内存lnk20250122 apr_snprintf(str, sizeof(str), tmp, cpuno + 1); - //ied_usr->LD_info[cpuno].LD_name = apr_pstrdup(g_init_pool, str);//lnk20250122 // 仅在没有值时更新 LD_name,避免重复分配内存 @@ -14417,9 +14410,8 @@ int parse_rpt_log_ini_one(ied_t* ied) } else {//已有则替换,在原有空间上覆盖 apr_cpystrn(ied_usr->LD_info[cpuno - 1].LD_name, str, sizeof(ied_usr->LD_info[cpuno - 1].LD_name)); } - //这些可能是已有的内存lnk20250122 - delete[] tmp; + delete[] tmp;//Get_IED中分配了内存,使用后删除 //初始化监测点的报告控制 init_rptctrl_by_count(LD_info, rpt_cfg_strlists[type]->size()); @@ -14466,7 +14458,7 @@ apr_status_t init_rem_dib_table_one(ied_t *ied) pos = ied_usr->dev_idx; for(chnl_no=0 ; chnl_nochncount; chnl_no++) { - chnl_usr = ied->channel[chnl_no].connect; + chnl_usr = (chnl_usr_t*)ied->channel[chnl_no].connect;//初始化时已根据最大数量申请空间 g_pt61850app->chnl_usr[pos] = chnl_usr; ip.s_addr = htonl(ied->channel[chnl_no].addr); strcpy(chnl_usr->ip_str,inet_ntoa(ip)); @@ -14494,6 +14486,7 @@ void clearLogInfo(loginfo_t *loginfo) { loginfo->IntgPd = 0; loginfo->reasonCode = 0; loginfo->TrgOpt = 0; + loginfo->start_time = 0; loginfo->end_time = 0; loginfo->need_steady = 0; @@ -14516,20 +14509,29 @@ void clearRptInfo(rptinfo_t *rptinfo) { } // 清空字符数组和非指针成员 + rptinfo->instanceNeedSuffix = 0; + rptinfo->TrgOpt = 0; + memset(rptinfo->OptFlds, 0, sizeof(rptinfo->OptFlds)); rptinfo->IntgPd = 0; rptinfo->report_PQ_type = 0; + rptinfo->rpt_registered = 0; rptinfo->chnl_id = 0; + rptinfo->m_LastDataTime = 0; rptinfo->m_LastGITime = 0; + rptinfo->m_LastRegisterFailedTime = 0; rptinfo->m_LastUnRegisterFailedTime = 0; + memset(rptinfo->m_EntryID, 0, sizeof(rptinfo->m_EntryID)); rptinfo->m_curRptSuffix = 0; + rptinfo->count = 0; rptinfo->rptNo = 0; rptinfo->flickerflag = 0; + rptinfo->pstflag = 0; // 对指针成员进行清理,但不释放内存 @@ -14540,10 +14542,10 @@ void clearRptInfo(rptinfo_t *rptinfo) { // 由于 LD_info 是指针,它不需要清理,仍指向父级 //rptinfo->LD_info = nullptr; - // 对 RCBC_INFO 结构体指针进行处理,假设不需要清理 + // 对 RCBC_INFO 结构体指针进行处理 if (rptinfo->m_rcb_info != nullptr) { // 如果需要,可以选择清理结构体内部内容,但不释放内存 - rptinfo->m_rcb_info = nullptr;//这里可以清空,因为这个指针指向的区域在连接通道关闭时会被清理: + rptinfo->m_rcb_info = nullptr;//这里可以清空,因为这个指针指向的区域在连接通道关闭时会被清理 } } @@ -14552,41 +14554,41 @@ void clearLDInfo(LD_info_t *ld_info) { std::cout << "ldinfo is null" << std::endl; return; } - // 清空指针成员 - if (ld_info->loginfo != nullptr) { - for (int i = 0; i < ld_info->logcount; ++i) { - if (ld_info->loginfo[i] != nullptr) { - clearLogInfold_info->loginfo[i]); //清空日志控制块 + + //保留原来的ied指向 + + //清空报告 + if (ld_info->rptinfo != nullptr) { + for (int i = 0; i < ld_info->rptcount; ++i) { + if (ld_info->rptinfo[i] != nullptr) { + clearRptInfo(ld_info->rptinfo[i]); //清空报告控制块 } } } + std::cout << "clean RptInfo!!!" << std::endl; + //清空日志 + if (ld_info->loginfo != nullptr) { + for (int i = 0; i < ld_info->logcount; ++i) { + if (ld_info->loginfo[i] != nullptr) { + clearLogInfo(ld_info->loginfo[i]); //清空日志控制块 + } + } + } std::cout << "clean loginfo_t!!!" << std::endl; + //清空补招 if (ld_info->autorecall != nullptr) { for (int i = 0; i < ld_info->autorecallcount; ++i) { if (ld_info->autorecall[i] != nullptr) { memset(ld_info->autorecall[i], 0, sizeof(autorecall_t)); - delete ld_info->autorecall[i]; //删除数组元素空间 + delete ld_info->autorecall[i]; //删除数组元素空间,如果有正在补招的内容,则已经申请空间,需要释放 } } delete ld_info->autorecall; //删除数组空间 } - std::cout << "clean autorecall_t!!!" << std::endl; - if (ld_info->rptinfo != nullptr) { - for (int i = 0; i < ld_info->rptcount; ++i) { - if (ld_info->rptinfo[i] != nullptr) { - memset(ld_info->rptinfo[i], 0, sizeof(rptinfo_t)); - - } - } - - } - - std::cout << "clean rptinfo_t!!!" << std::endl; - if (ld_info->ht_fcd != nullptr) { apr_hash_clear(ld_info->ht_fcd); } @@ -14595,6 +14597,9 @@ void clearLDInfo(LD_info_t *ld_info) { } // 清空其他指针成员 + if (ld_info->name != nullptr) { + memset(ld_info->name, 0, sizeof(char) * 256); + } if (ld_info->LD_name != nullptr) { memset(ld_info->LD_name, 0, sizeof(char) * 256); } @@ -14614,22 +14619,53 @@ void clearLDInfo(LD_info_t *ld_info) { memset(ld_info->terminal_code, 0, sizeof(char) * 256); } - // 清空 LD_info_t 结构体中的非指针部分 + ld_info->cpuno = 0; //清空逻辑序列号 + + ld_info->time = 0; //台账更新时间清0 + ld_info->update_flag = 0; //监测点更新标志,暂不使用 + + ld_info->rptRecvFlag = 0;//重置报告标志 + ld_info->rptRecvCheckFlag = 0; + ld_info->rptPstRecvFlag = 0; + ld_info->rptPstRecvCheckFlag = 0; + + ld_info->read_flag = 0;//监测点无效 + ld_info->rptcount = 0; - ld_info->read_flag = 0; ld_info->logcount = 0; ld_info->autorecallflag = 0; ld_info->autorecallcount = 0; + + //ld_info->group = 0; //不使用 + + //清空实时数据部分 ld_info->line_id = 0; ld_info->real_data = 0; ld_info->soe_data = 0; ld_info->limit = 0; ld_info->count = 0; - ld_info->SubV_Index = 0; - ld_info->Dev_Index = 0; - ld_info->Sub_Index = 0; - ld_info->GD_Index = 0; - ld_info->RDRE_FltNum = 0; + + //ld_info->SubV_Index = 0; //不使用 + //ld_info->Dev_Index = 0; //不使用 + //ld_info->Sub_Index = 0; //不使用 + //ld_info->GD_Index = 0; //不使用 + + //清空暂态结构 + for (int i = 0; i < QVVR_NUM; ++i) { + ld_info->qvvr[i].used_status = 0; + ld_info->qvvr[i].QVVR_start = 0; + ld_info->qvvr[i].QVVR_type = 0; + ld_info->qvvr[i].QVVR_time = 0; + ld_info->qvvr[i].QVVR_PerTime = 0.0f; + ld_info->qvvr[i].QVVR_Amg = 0.0f; + memset(ld_info->qvvr[i].QVVR_Rptname, 0, sizeof(ld_info->qvvr[i].QVVR_Rptname)); // 清空字符数组 + ld_info->qvvr[i].timestamp = 0; + } + ld_info->qvvr_idx = 0; + + memset(ld_info->FltNum, 0, sizeof(ld_info->FltNum)); + + ld_info->RDRE_FltNum = 0; //录波号清零 } @@ -14644,24 +14680,24 @@ void clearIedUsr(ied_usr_t *ied_usr) { //ied_usr->dev_idx = 0;//保留index ied_usr->dev_flag = UNUSED; ied_usr->last_call_wavelist_time = 0; - ied_usr->time = 0; - ied_usr->update_flag = 0;//暂不使用 + ied_usr->time = 0; //台账更新时间 + ied_usr->update_flag = 0; //台账更新标志暂不使用 // 清空指针部分,但不清理非空指针 if (ied_usr->LD_info != nullptr) { // 如果 LD_info 不为空,清理它内部的内容 for (int i = 0; i < MAX_CPUNO; ++i) { - if (ied_usr->LD_info[i] != nullptr) { - clearLDInfo(ied_usr->LD_info[i]); + if (&ied_usr->LD_info[i] != NULL) { + clearLDInfo(&ied_usr->LD_info[i]); } } } - if (ied_usr->cookie != nullptr) { + if (ied_usr->cookie != nullptr) { //不使用 std::cout << "cookie not null" << std::endl; } - // 清空其他非指针部分 + // 清空其他非指针部分,也可以不清0,后续都会覆盖 memset(ied_usr->dev_type, 0, sizeof(ied_usr->dev_type)); memset(ied_usr->dev_key, 0, sizeof(ied_usr->dev_key)); memset(ied_usr->dev_series, 0, sizeof(ied_usr->dev_series)); @@ -14674,45 +14710,88 @@ void clearIedUsr(ied_usr_t *ied_usr) { memset(ied_usr->terminal_code, 0, sizeof(ied_usr->terminal_code)); } +// 清空 channel 和 cpuinfo 的非指针部分 +void clear_channel_and_cpuinfo(byte_t chncount, channel_t *channel, byte_t cpucount, cpuinfo_t *cpuinfo) { + // 清空 channel 数组中的每个元素的非指针字段 + for (byte_t i = 0; i < chncount && (&channel[i] != NULL); ++i) { + channel[i].master = 0; + channel[i].channel_type = 0; + memset(channel[i].addr_str, 0, LONGNAME); + channel[i].addr = 0; + channel[i].port = 0; + channel[i].status = 0; + channel[i].last_ticks = 0; + channel[i].last_send_ticks = 0; + channel[i].ied_id = 0; + + // 清理 channel 里的 chnl_usr_t 部分 + // 关闭连接时已清理,保留指针本身 + } + + // 清空 cpuinfo 数组中的每个元素的非指针字段 + for (byte_t i = 0; i < cpucount && (&cpuinfo[i] != NULL); ++i) { + cpuinfo[i].addr = 0; + cpuinfo[i].status = 0; + cpuinfo[i].templ = 0; + memset(cpuinfo[i].name, 0, LONGNAME); + cpuinfo[i].last_gi = 0; + cpuinfo[i].last_gi_send = 0; + cpuinfo[i].next_gi_send = 0; + cpuinfo[i].last_ticks = 0; + cpuinfo[i].last_send_ticks = 0; + } +} + void clearIed(ied_t *ied) { if (ied == nullptr) { return; } - // 清理 channel 里的 chnl_usr_t 部分 - if (ied->channel != nullptr && ied->channel[0].connect != nullptr) { - chnl_usr_t *chnl_usr = (chnl_usr_t*)ied->channel[0].connect; - memset(chnl_usr, 0, sizeof(chnl_usr_t)); - chnl_usr->chnl_id = 0; - chnl_usr->m_state = CHANNEL_DISCONNECTED; - chnl_usr->m_ClosedMsTime = NEXT_CONNECT_TIME * (-1); - } + // 清空 ied_t 的id + ied->id = 0; + //ied->flags = 0; //未使用 + //ied->type = 0; //未使用 - // 清空 ied_t 结构体的非指针部分 - ied->id = 0; - ied->flags = 0; - ied->type = 0; - ied->chncount = 0; - ied->cpucount = 0; - ied->station = 0; - ied->node = 0; - ied->frequency = 0; - ied->delay = 0; - ied->count = 0; - ied->systoken_st = 0; - ied->index = 0; - ied->status = {0}; // 假设 status_t 可清空 - ied->last_ticks = 0; - ied->last_gi = 0; + //清理channel //清理cpuinfo + clear_channel_and_cpuinfo(ied->chncount,ied->channel,ied->cpucount,ied->cpuinfo); + ied->chncount = 0; //清空通道数 + ied->cpucount = 0; //清空检测点数 + + //名称清理 + memset(ied->name, 0, LONGNAME); + + //ied->station = 0; //未使用 + //ied->node = 0; //未使用 + //ied->frequency = 0; //未使用 + //ied->delay = 0; //未使用 + //ied->count = 0; //未使用 + + //数据组定义部分未使用 + //ied->groups = NULL; + //ied->htgroups = NULL; + + //系统令牌未使用 + //ied->systoken_st = 0; + + //ied->index = 0; //未使用 + ied->status = STATUS_NOINIT; //设备状态设为未初始化 + //ied->last_ticks = 0; //未使用 + //ied->last_gi = 0; //未使用 // 清空指针部分 if (ied->usr_ext != nullptr) { ied_usr_t *ied_usr = (ied_usr_t*)ied->usr_ext; clearIedUsr(ied_usr); } - memset(ied->name, 0, sizeof(ied->name)); - memset(ied->channel, 0, sizeof(ied->channel)); - memset(ied->cpuinfo, 0, sizeof(ied->cpuinfo)); // 假设是指针类型,可以清空 + + if (ied->sys_ext != nullptr) { + //不使用 + } + + if (ied->app_ext != nullptr) { + //不使用 + } + } /*封装C可调用的台账更新函数 *///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/mms/interface.h b/mms/interface.h index 558b234..a4d6cdf 100644 --- a/mms/interface.h +++ b/mms/interface.h @@ -106,7 +106,15 @@ ST_VOID doCommService (); ST_VOID init_log_cfg (ST_VOID); ST_VOID set_rem_dib_table_size (ST_INT size); + +//lnk20250207 +#ifdef __cplusplus +extern "C" { +#endif ST_VOID add_rem_dib_table (ST_INT pos,ST_CHAR *remAr,unsigned short port); +#ifdef __cplusplus +} +#endif ST_RET mms_connectToServer (ST_CHAR * dev_key,ST_CHAR *dev_series, ST_CHAR *serverARName, MVL_NET_INFO **clientNetInfo, MVL_REQ_PEND **reqCtrl); diff --git a/mms/mms_process.c b/mms/mms_process.c index e1f89f2..4e22341 100644 --- a/mms/mms_process.c +++ b/mms/mms_process.c @@ -885,7 +885,7 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) if(ied_unused != NULL){ ied_usr_unused = (ied_usr_t*)ied_unused->usr_ext; ied = ied_unused; //新增的ied指向已有的未使用的ied空间 - terminal_index = ied_usr_unused->dev_idx //记录这个ied的编号,即g_node的下标 + terminal_index = ied_usr_unused->dev_idx; //记录这个ied的编号,即g_node的下标 //打印提示 printf("!!!!!!!!ied index:%d ,origin terminal_id:%s has been taken!!!!!!!!!!\n",ied_usr_unused->dev_idx,ied_usr_unused->terminal_id); @@ -981,7 +981,7 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) //5-报告块初始化/////////////////////////////////// //6-init_rem_dib_table////////////////////////////// - init_rem_dib_table_one(ied) + init_rem_dib_table_one(ied); //6-init_rem_dib_table/////////////////////////////////// } @@ -1003,7 +1003,7 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) //关闭这个终端的所有连接////////////////////////////////////////////////////////////////////// for(chnl_no=0 ; chnl_nochncount; chnl_no++) { chnl_usr = (chnl_usr_t*)ied->channel[chnl_no].connect; - if (chnl_usr->m_state!=CHANNEL_CONNECTED){ + if (chnl_usr->m_state!=CHANNEL_CONNECTED){//跳过未连接的通道 continue; } closeChannel(chnl_usr);//关闭更新台账后,任务会自动连接 @@ -1012,7 +1012,11 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) //更新数据///////////////////////////////////////////////////////////////////////////////// //3-写入台账内容////////////////////////////// ied_usr = ied->usr_ext; - int ret = update_one_terminal_ledger(update,i,ied,ied_usr->dev_idx); + + //写入前先清空已有数据 + clearIedUsr(ied_usr);//不会清空dev_idx + + int ret = update_one_terminal_ledger(update,i,ied,ied_usr->dev_idx,1);//1:更新已有的ied if(ret){ printf("ledger can not be update!!!!!quit process!!!!!\n"); return 0; @@ -1043,11 +1047,11 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) //4-配置映射文件/////////////////////////////////// //5-报告块初始化////////////////////////////// - + parse_rpt_log_ini_one(ied); //5-报告块初始化/////////////////////////////////// //6-init_rem_dib_table////////////////////////////// - + init_rem_dib_table_one(ied); //6-init_rem_dib_table/////////////////////////////////// //更新数据////////////////////////////////////////////////////////////////////// } @@ -1059,7 +1063,7 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) } ///////////////////////////////////////////////////////////////////////////////delete update = ledger_update_xml->delete_updates; //处理删除台账部分 - update_num = ledger_update_xml->delete_update_num; + update_num = ledger_update_xml->delete_update_num; //删除的数量 printf("delete ledger num:%d\n",update_num); for (i=0; im_state!=CHANNEL_CONNECTED){ //跳过没连接的通道,一般一个终端只有一个 continue; } - closeChannel(chnl_usr);//关闭更新台账后,任务会自动连接 + closeChannel(chnl_usr);//关闭更新台账后,如果是删除则不会再连接,关闭连接时这个ied的报告会被清除,报告控制会被注销 } //更新数据////////////////////////////////////////////////////////////////////// //3-删除台账内容////////////////////////////// +//调试用 // 假设要删除 g_node->clients 中的某个 ied,index 为删除的索引 int index_to_remove = 0; ied_t* ied_find = NULL; @@ -1105,8 +1110,10 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) if(ied_to_remove == ied){//通过终端id找到的ied应该也指向g_node对应的内存区 printf("this ied is ied_to_remove\n"); } +//调试用 //清空ied的内容 + clearIed(ied_to_remove); //3-删除台账内容/////////////////////////////////// @@ -1115,11 +1122,11 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml) //4-配置映射文件/////////////////////////////////// //5-报告块////////////////////////////// - //报告块清空 + //关闭连接时这个ied的报告已清空。报告控制块保留,因为报告控制块是根据设备类型设置的,如果删除会影响其他同类型的ied。这个ied对应的控制块在清空内容时已清空 //5-报告块/////////////////////////////////// //6-init_rem_dib_table////////////////////////////// - + //rem_dib_table的内容将会被保留,如果有新的台账使用这个位置,将会直接覆盖 //6-init_rem_dib_table/////////////////////////////////// //更新数据////////////////////////////////////////////////////////////////////// } diff --git a/mms/rdb_client.h b/mms/rdb_client.h index 9189010..3a736ce 100644 --- a/mms/rdb_client.h +++ b/mms/rdb_client.h @@ -478,6 +478,10 @@ 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);