/**
 * @file:    $RCSfile: parse_xml.c,v $
 * @brief:   $解析xml 
 *
 * @version: $Revision: 1.5 $
 * @date:    $Date: 2018/12/29 03:18:14 $
 * @author:  $Author: lizhongming $
 * @state:   $State: Exp $
 *
 * @latest:  $Id: parse_xml.c,v 1.5 2018/12/29 03:18:14 lizhongming Exp $
 */
#include <string.h>
#include "rdb_client.h" 
#include "xmltools.h"
#include "../cfg_parse/custom_printf.h"//lnk20250225

int comtrade_remain_file_num = 0;

extern node_t*			g_node ;
extern char 			g_my_conf_fname[256];
extern apr_pool_t*		g_init_pool;
extern apr_pool_t*		g_run_pool;
extern pt61850app_t*	g_pt61850app;
 
apr_status_t app_get_private_config(const char *myfilename)
{

	char			*v = NULL;
	char			*str = NULL;

	assert(myfilename); 

	if (xml_get_elem(myfilename, "//pt61850netd/mmsOpTimeout/",&v) == APR_SUCCESS) {
		if((str = strtok(v,","))) 
			g_pt61850app->mmsOpTimeout = atoi(str);
	}
	else {
		echo_warn("Read xml error. error at mmsOpTimeout.\n");
		return APR_EBADDATE;
	}	

	if (xml_get_elem(myfilename, "//pt61850netd/giTime/",&v) == APR_SUCCESS) {
		if((str = strtok(v,","))) 
			g_pt61850app->giTime = atoi(str);
	}
	else {
		echo_warn("Read xml error. error at giTime.\n");
		return APR_EBADDATE;
	}

	if (xml_get_elem(myfilename, "//pt61850netd/cliAsuffixFrom/",&v) == APR_SUCCESS) {
		if((str = strtok(v,","))) 
			g_pt61850app->rptSuffix[0][0] = atoi(str); 
	}
	else {
		echo_warn("Read xml error. error at cliAsuffixFrom .\n");
		return APR_EBADDATE;
	}
	if (xml_get_elem(myfilename, "//pt61850netd/cliAsuffixTo/",&v) == APR_SUCCESS) {
		if((str = strtok(v,","))) 
			g_pt61850app->rptSuffix[0][1] = atoi(str);  
	}
	else {
		echo_warn("Read xml error. error at cliAsuffixTo .\n");
		return APR_EBADDATE;
	} 
	 

	if (xml_get_elem(myfilename, "//pt61850netd/accPath/",&v) == APR_SUCCESS) {
		if((str = strtok(v,","))) 
			strcpy(g_pt61850app->accPath,str_trim_both(str," \t\'" ) );
	}
	else {
		echo_warn("Read xml error. error at accPath .\n");
		return APR_EBADDATE;
	}    

	if (xml_get_elem(myfilename, "//pt61850netd/comtrade_remain_file_num/",&v) == APR_SUCCESS) { 
		if((str = strtok(v,","))) 
			comtrade_remain_file_num = atoi(str);
	}

	return APR_SUCCESS;
}



//************解析  ReportControl.xml ***************// 
#define REPORTCONTROL_FILE_PATH		CONFIG_FILEPATH  

/*
<!-- 装置ID,CPUID,ReportCtrlNum -->
<ReportControlCount>104,1,2</ReportControlCount>
*/
//lnk20250122start

#define MAX_RPT_COUNT 20

int init_rptctrl_by_count(LD_info_t* LD_info,int rptcount) 
{ 
	int		j,i;   
	LD_info->rptcount = rptcount;

	if(LD_info->rptinfo == NULL){	//如果是空的说明是第一次初始化，需要申请空间，直接给每个监测点申请20个报告位，如果台账删除直接清空内容，如果需要重用直接重新赋值
		LD_info->rptinfo = apr_pcalloc( g_init_pool,MAX_RPT_COUNT*sizeof(rptinfo_t*) ); 
	}
	
	for(j=0; j<rptcount; j++)	{
		if(LD_info->rptinfo[j] == NULL){//如果是空的说明是第一次初始化，需要申请空间，否则沿用原来的空间，直接进行值的初始化
			LD_info->rptinfo[j] = apr_pcalloc( g_init_pool,sizeof(rptinfo_t) );
		}
		LD_info->rptinfo[j]->LD_info = LD_info;
		LD_info->rptinfo[j]->m_LastRegisterFailedTime = sGetMsTime() -10*60*1000;
		LD_info->rptinfo[j]->m_LastUnRegisterFailedTime = sGetMsTime() -10*60*1000;
		LD_info->rptinfo[j]->IntgPd = 60;
		LD_info->rptinfo[j]->m_rcb_info = NULL;
		LD_info->rptinfo[j]->rpt_registered = FALSE;
		LD_info->rptinfo[j]->m_curRptSuffix = -1;
		for(i=0; i<8; i++)
			LD_info->rptinfo[j]->m_EntryID[i] = 0xff;
	}

	return 0;
}
//lnk20250122end

//ReportControl: 装置ID,CPUID,ID,RCBName, intgPd, dchg, qchg, dupd, period ,gi, 实例名是否增加后缀,　 
//  seqNum, timeStamp, reasonCode, dataSet, dataRef, bufOvfl, entryID, configRef, segmentation 
//<ReportControl>104,1,1,brcbDin,60,1,0,0,1,0,yes,1,1,0,1,1,1,1,1,0</ReportControl>
int fill_rptctrl_by_cfg(LD_info_t* LD_info,int rptno,char *buf) 
{
	char	*str = NULL;
	char	*tmp_str = NULL;  
	rptinfo_t	*rptinfo;   

	assert( (rptno+1) <= LD_info->rptcount ) ;
	rptinfo = LD_info->rptinfo[rptno];

	
	if (rptinfo == NULL) {
	    printf("[RPT_INIT][ERROR] rptinfo NULL, rptno=%d\n", rptno);
	    return 1;
	}

	rptinfo->LD_info = LD_info;

	if(!(str = strtok(buf,","))) 
		return 1; 	

	rptinfo->rptNo = rptno;//CZY 2023-08-16 WW 2022-11-14  增加报告编号，用于判断报告是否收完，可以进行数据处理

	tmp_str = apr_pstrdup(g_init_pool,str);
	rptinfo->rptID = str_trim_both(tmp_str," \t\'" );
	if((str = strtok(NULL,","))) rptinfo->IntgPd = atoi(str);  else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&rptinfo->TrgOpt, TRGOPS_BITNUM_DATA_CHANGE);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&rptinfo->TrgOpt, TRGOPS_BITNUM_QUALITY_CHANGE);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&rptinfo->TrgOpt, TRGOPS_BITNUM_DATA_UPDATE);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&rptinfo->TrgOpt, TRGOPS_BITNUM_INTEGRITY);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&rptinfo->TrgOpt, TRGOPS_BITNUM_GENERAL_INTERROGATION);
	}else return 1;
	if(!(str = strtok(NULL,","))) 
		return 1; 		
	tmp_str = apr_pstrdup(g_init_pool,str);
	if (strcmp("yes", str_trim_both(tmp_str," \t\'" ) )==0 )
		rptinfo->instanceNeedSuffix = TRUE;
	else 
		rptinfo->instanceNeedSuffix = FALSE;

	//  seqNum, timeStamp, reasonCode, dataSet, dataRef, bufOvfl, entryID, configRef, segmentation 
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_SQNUM);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_TIMESTAMP);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_REASON);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_DATSETNAME);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_DATAREF);
	}else return 1;
	if((str = strtok(NULL,",")))	{ //only valid in RCB_TYPE_IEC_BRCB
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_BUFOVFL);
	}else return 1;
	if((str = strtok(NULL,",")))	{ //only valid in RCB_TYPE_IEC_BRCB
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_ENTRYID);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_CONFREV);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		//SUBSEQNUM is only set by the server, so don't try to set it.
		if ( atoi(str) ) BSTR_BIT_SET_ON(rptinfo->OptFlds, OPTFLD_BITNUM_SUBSEQNUM);
	}else return 1;
	if((str = strtok(NULL,",")))	{ 
		rptinfo->report_PQ_type = atoi(str);
	}else return 1;

	if ((str = strtok(NULL, ","))) { //CZY 2023-08-16 WW 2022-11-14增加闪变报告标志
		rptinfo->flickerflag = atoi(str);
		if (rptinfo->flickerflag == 0) {
			LD_info->rptRecvFlag += 0x01 << rptno;
			printf(" LD_info->rptRecvFlag=%d \n", LD_info->rptRecvFlag);
		}
		else if(rptinfo->flickerflag == 2)
		{
			LD_info->rptPstRecvFlag += 0x01 << rptno;
			printf(" LD_info->rptPstRecvFlag=%d \n", LD_info->rptPstRecvFlag);
		}
	}
	else return 1;

	return 0;
}

 
//////////////////////////////////////////////////////////
//************解析  LogControl.xml ***************//

/*
<!-- 装置ID,CPUID,LogCtrlNum -->
<LogControlCount>104,1,2</LogControlCount>
*/


#define MAX_LOG_COUNT 20

int init_logctrl_by_count(LD_info_t* LD_info,int logcount) 
{ 
	int j;
	LD_info->logcount = logcount;

	if(LD_info->loginfo == NULL){
		LD_info->loginfo = apr_pcalloc(g_init_pool, MAX_LOG_COUNT * sizeof(loginfo_t*)); //new loginfo_t*[logcount];
	}
	for(j=0; j<logcount; j++)	{
		if(LD_info->loginfo[j] == NULL){
			LD_info->loginfo[j] = apr_pcalloc(g_init_pool, sizeof(loginfo_t));//new loginfo_t[1];
		}
		LD_info->loginfo[j]->LD_info = LD_info;

		LD_info->loginfo[j]->IntgPd = 600;
		//LD_info->loginfo[j]->m_lcb_info = NULL;
	}

	return 0;
}
//lnk20250122end

//<!--LogControl:IEDID,CPUID,ID,LCBName,DatasetName,LogName,reasonCode,intgPd,dchg,qchg,dupd,period -->
// <LogControl>106,2,1,LLN0$LG$lcStatisticData,dsStatisticData,PQM1,0,600000,1,0,0,0</LogControl>
// <LogControl>106,2,2,LLN0$LG$lcFlickerData,dsFlickerData,PQM1,0,600000,1,0,0,0</LogControl>
int fill_logctrl_by_cfg(LD_info_t* LD_info,int logno,char *buf,char* devtype)
{ 
	char	*str = NULL;
	char	*tmp_str = NULL;  
	loginfo_t	*loginfo;   

	assert( (logno+1) <= LD_info->logcount ) ;
	loginfo = LD_info->loginfo[logno];

	if (loginfo == NULL) {
	    printf("[LOG_INIT][ERROR] loginfo NULL, logno=%d\n", logno);
	    return 1;
	}
	
	loginfo->LD_info = LD_info;

	if(!(str = strtok(buf,","))) 
		return 1; 		
	tmp_str = apr_pstrdup(g_init_pool,str);
	loginfo->lcbName = str_trim_both(tmp_str," \t\'" );

	if(!(str = strtok(NULL,","))) 
		return 1; 		
	tmp_str = apr_pstrdup(g_init_pool,str);
	loginfo->datasetName = str_trim_both(tmp_str," \t\'" );

	if(!(str = strtok(NULL,","))) 
		return 1; 		
	apr_snprintf(loginfo->logName,sizeof(loginfo->logName), devtype,LD_info->cpuno);//例如PQM1

	if((str = strtok(NULL,","))) loginfo->reasonCode = atoi(str);  else return 1;
	if((str = strtok(NULL,","))) loginfo->IntgPd = atoi(str);  else return 1;

	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&loginfo->TrgOpt, TRGOPS_BITNUM_DATA_CHANGE);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&loginfo->TrgOpt, TRGOPS_BITNUM_QUALITY_CHANGE);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&loginfo->TrgOpt, TRGOPS_BITNUM_DATA_UPDATE);
	}else return 1;
	if((str = strtok(NULL,",")))	{
		if ( atoi(str) ) BSTR_BIT_SET_ON(&loginfo->TrgOpt, TRGOPS_BITNUM_INTEGRITY);
	}else return 1;  

	loginfo->start_time = apr_time_now();// - apr_time_from_sec(600);//
	loginfo->end_time   = apr_time_now();
	loginfo->need_steady = 0;
	loginfo->need_voltage = 0;

	return 0;
}
 

///////////////////////////////////////////////////////////////////////////////////////////////
