/*******************************************************************************
版权所有：	珠海欧力配网自动化股份有限公司
文件名称：	others.c
文件版本：	01.00
创建作者:	赵海洋
创建日期：	2021-11-03
功能说明：	主要处理杂项和各项特殊需求功能。
其它说明：
注意事项:
修改记录:
********************************************************************************/

#include "head.h"

Array myRmtSetArray;  // 远端定值

/**
 * @brief _get_array_size
 * @param [in] this
 * @return int
 * @author ZhaoYang
 * @date 2023-06-16
 * @details 获取容器数组大小
 */
int _get_array_size(Array *this)
{
    if (this)
    {
        // return this->size + 1;
        return this->size;
    }
    else
    {
        return -1;
    }
}

/**
 * @brief _constructor
 * @param [in] this
 * @author ZhaoYang
 * @date 2023-06-16
 * @details 构造函数
 */
void _constructor(Array *this)
{
    this->size = 0;
    this->max_size = 10;
    this->Data = (TRMTSETTABLE *)rt_malloc(this->max_size * sizeof(TRMTSETTABLE));
    memset(this->Data, 0, this->max_size * sizeof(TRMTSETTABLE));
}

/**
 * @brief _input
 * @param [in] data
 * @param [in] this
 * @author ZhaoYang
 * @date 2023-06-16
 * @details 数据添加
 */
void _input(TRMTSETTABLE data, Array *this)
{
    int i;
    TRMTSETTABLE *ptr;

    if (this->size >= this->max_size)
    {
        this->max_size += 10;
        ptr = (TRMTSETTABLE *)rt_malloc(this->max_size * sizeof(TRMTSETTABLE));
        for (i = 0; i < this->size; i++)
            ptr[i] = this->Data[i];
        rt_free(this->Data);
        this->Data = ptr;
    }
    this->Data[this->size] = data;
    this->size += 1;
}

/**
 * @brief _print
 * @param [in] this
 * @author ZhaoYang
 * @date 2023-06-16
 * @details 打印数据
 */
void _print(struct array *this)
{
    int i;
    struct array *ptr = this;
    if (ptr == NULL)
        return;

    for (i = 0; i < ptr->size; i++)
    {
        rt_printf("data is 0x%04x %d %d %d %d\n", ptr->Data[i].di, ptr->Data[i].unit,
                  ptr->Data[i].group, ptr->Data[i].offset, ptr->Data[i].index);
    }
    return;
}

/**
 * @brief _return_index_value
 * @param [in] this
 * @param [in] index
 * @return int
 * @author ZhaoYang
 * @date 2023-06-16
 * @details
 */
TRMTSETTABLE *_return_index_value(Array *this, int index)
{
    if (this == NULL)
        return NULL;
    return &(this->Data[index]);
}

/**
 * @brief _denstructor
 * @param [in] this
 * @author ZhaoYang
 * @date 2023-06-16
 * @details 析构对象
 */
void _denstructor(Array *this)
{
    int i = 0;
    if (this == NULL)
        return;
    for (i = 0; i < this->max_size; i++)
        memset(&(this->Data[i]), 0, sizeof(TRMTSETTABLE));
    rt_free(this->Data);
}

/**
 * @brief Init
 * @param [in] this
 * @author ZhaoYang
 * @date 2023-06-16
 * @details
 */
void Init(Array *this)
{
    this->Input = _input;
    this->print = _print;
    this->get_array_size = _get_array_size;
    this->return_index_value = _return_index_value;
    this->Constructor = _constructor;
    this->Destructor = _denstructor;
    this->Constructor(this);
}

/**
 * @brief   打印遥调点表
 * @details none
 * @param   none
 * @return  always 0
 * @author  EWen
 * @date    2025-09-02
 * @remarks none
 */
int printf_myRmtSetArray(void)
{
    int i=0,j=0;
    int tblnum = 0;
    const TRMTSETTABLE *pdata=NULL;
    const char *group[4]={"公共定值","开关定值","装置参数","内部定值"};
    const char *tag_name[13]= {"布尔        ","小整形      ","无符号小整形","短整形      ","无符号短整形","整形        ",\
                               "无符号整形  ","长整形      ","无符号长整形","单精度浮点  ","双精度浮点  ","字符串     ","八位位串    "};
    const uint8_t tag[13] =   {BOOL_R,TINY_R,UTINY_R,SHORT_R,USHORT_R,INT_R, UINT_R,LONG_R,ULONG_R,FLOAT_R,DOUBLE_R,STR_R,STR_E};

    if(myRmtSetArray.size != 0)
    {
        tblnum = myRmtSetArray.size;
        rt_printf("配置的遥调点表。\r\n");
    }
    else
    {
        tblnum = RMT_SET_TABLE_NUMBER;
        rt_printf("默认的遥调点表。\r\n");
    }

    rt_printf("点号\t\t类型\t\t分组\t\t偏移\t\t系数\t\t定值\r\n");

    for(i=0; i<tblnum; i++)
    {
        if(myRmtSetArray.size != 0)
        {
            pdata = &myRmtSetArray.Data[i];
        }
        else
        {
            pdata = &tRmtsettable[i];
        }

        rt_printf("0x%04x(%d)\t",pdata->di,pdata->di);
        for(j = 0; j < 13; j++)
        {
            if(pdata->unit == tag[j]) break;
        }
        rt_printf("%s\t%s\t%d\t\t%.4f\t\t",tag_name[j],group[pdata->group],pdata->offset,pdata->rate);

        if(pdata->group == RMT_GRP_EQSET)
        {
            rt_printf("%s\r\n",tEquipParaTable[pdata->index].szName);
        }
        else if(pdata->group == RMT_GRP_SWSET)
        {
            rt_printf("%s\r\n",tSwSetTable[pdata->index].szName);
        }
        else if(pdata->group == RMT_GRP_PUSET)
        {
            rt_printf("%s\r\n",tPubSetTable[pdata->index].szName); 
        }
        else if(pdata->group == RMT_GRP_CSSET)
        {
            rt_printf("%s\r\n",tCstSetTable[pdata->index].szName); 
        }
        else
        {
            rt_printf("错误分组\r\n");
        }
    }

    return 0;
}

/**
 * @brief rmtSetArray_init
 * @author ZhaoYang
 * @date 2023-06-19
 * @details 远端参数初始化
 */
int rmtSetArray_init(void)
{
    Init(&myRmtSetArray);
    return 0;
}

/**
 * @brief rmtSetArray_exit
 * @author ZhaoYang
 * @date 2023-06-19
 * @details 远端参数退出
 */
int rmtSetArray_exit(void)
{
    myRmtSetArray.Destructor(&myRmtSetArray);
    myRmtSetArray.size = 0;
    return 0;
}

/**
 * @brief Set the remote parse csv object
 * @author ZhaoYang
 * @date 2023-06-13
 * @details 解析远端遥调表
 */
void set_remote_parse_csv(void)
{
	u32 i,file_length;
	u8 *filebuf;
	u8  filestr[128],*pstr,strlenth;
	off_t pos;
	int fp = rt_file_open("/app/data/ppl_tbl.csv", O_RDONLY, 0);
	u8 have_check = 0;
	u8 dot_count = 0;
	int ret=0;

	if (IS_ERR(fp)) {
		rt_printf("ppl_tbl open failed.\n");
		return;
	}

	// 得到文件长度

	file_length = rt_file_getfile_size(fp);
	if(file_length <= 0)
	{
		rt_printf("ppl_tbl file length is 0.\n");
		rt_file_close(fp,0);
		return; 	
	}

	// 分配内存
	filebuf = rt_malloc(file_length);
	if((filebuf) == NULL)
	{
		rt_printf("ppl_tbl file rt_malloc errors.\n");
		rt_file_close(fp,0);
		return; 	
	}

	pos = 0;
	if(rt_file_read(fp,filebuf,file_length,&pos) != file_length)
	{
		rt_printf("ppl_tbl file rt_file_read errors.\n");
		rt_file_close(fp,0);
		rt_free(filebuf);
		return;
	}
	pstr = filestr;
	strlenth=0;   // 纠错处理
	//找到\r\n位置，得到一行长度
	for(i = 0; i < file_length; i++)
	{
		*pstr++=filebuf[i];
		strlenth++;
		if(filebuf[i] == 0x0a||strlenth>=128)
		{
			if(have_check == 0)
			{
				// 新旧版本遥调点表结构不同，新版的增加了一列系数，此处做个简单的检查
				u8 j = 0;
				have_check = 1;
				for(j = 0 ; j < i ; j++)
				{
					if(filebuf[j] == 0x2c)//","
						dot_count++;
				}
				if(dot_count<6)
				{
					ret = -1;
					rt_printf("遥调点表文件为旧版本,不匹配,需要更新!\r\n");
					break;
				}
			}
			pstr-=1;  //  去掉回车(Unix:LF)
			*pstr='\0';
			ret = set_remote_parse_data(filestr);
			if(ret != 0) break;
			pstr=filestr;
			strlenth=0;
		}
	}
	// rt_printf("the array size is :%d.\n",myRmtSetArray.get_array_size(&myRmtSetArray));
	// myRmtSetArray.print(&myRmtSetArray);
	if(ret != 0)
	{
		rmtSetArray_exit();
		rt_err_set(ERR_CODE_RMT,ret);
	}
	rt_file_close(fp,0);	// 关闭文件
	rt_free(filebuf);		// 释放内存
}

int set_remote_parse_data(u8 *buf)
{
	u8 str[256];
	TRMTSETTABLE tmp={0};
	int i,len=0,val=0;
	float fval = 0;

	for ( i = 0; i < 6; i++)
	{
		switch (i)
		{
		case 0:
			len=iec_findchardot(buf,str);
			if(len==0)	return -1;
			val=strtoul(str,NULL,16);
			tmp.di = val;
			break;
		
		default:
			buf+=len+1;
			len=iec_findchardot(buf,str); 
			if(len==0)	return -2;
			if(i != 4)
			{
				val=strtoul(str,NULL,10);
			}
			else
			{
				fval=atof1(str);
			}
			switch (i)
			{
			case 1:
				tmp.unit = val;
				break;
			case 2:
				tmp.group = val;
				break;
			case 3:
				tmp.offset = val;
				break;
			case 4:
				tmp.rate = fval;
			case 5:
				tmp.index = val;
				break;
			
			default:
				break;
			}
			break;
		}
	}

	if(tmp.di < 0x8001 || tmp.group >= RMT_GRP_NUMBER || tmp.unit > 45)
	{
		return -3;
	}

	myRmtSetArray.Input(tmp,&myRmtSetArray);
	return 0;
}

/**
 * @brief   公共定值同步到开关定值
 * @details 此处同步是为了液晶显示一致
 * @param   none
 * @return  none
 * @author  EWen
 * @date    2025-03-26
 * @remarks none
 */
#if 0
void pub_set2sw_set(void)
{
    bool need2update = false;
    int sw = 0,i = 0,pubindex = 0,swindex = 0;
    SET_VALUE *psetbuf = NULL;

    if(!pRunSet->bTT_PUB_SET_TO_SW) return;

    psetbuf = rt_malloc(SET_NUMBER*4);	
    if(!psetbuf)
	{
		rt_printf("\r\npub_set2sw_set,分配定值缓冲区错误!\r\n");
		return;
	}

    if(!ReadSet(0,(void *)psetbuf))  // 读定值
	{
		GetDefSet((float*)psetbuf);
	}

    for(sw = 0; sw < SWITCH_NUM_MAX; sw++)
    {
        for(i = 0; i < 3; i++)
        {
            if(i == 0)
            {
                pubindex = SET_PUB_OVLOAD_TT;
                swindex= SET_OVLOAD_TT;
            }
            else if (i == 1)
            {
                pubindex = SET_PUB_DLGZ_TT;
                swindex= SET_DLGZ_TT;
            }
            else
            {
                pubindex = SET_PUB_DLYX_TT;
                swindex= SET_DLYX_TT;
            }

            if((WORD)psetbuf[pubindex].ff != ((WORD)psetbuf[swindex+sw*SW_SET_NUMBER+PUB_SET_NUMBER].ff) \
            || (DWORD)(psetbuf[pubindex+1].ff*1000) != (DWORD)(psetbuf[swindex+1+sw*SW_SET_NUMBER+PUB_SET_NUMBER].ff*1000) \
            || (DWORD)(psetbuf[pubindex+2].ff*1000) != (DWORD)(psetbuf[swindex+2+sw*SW_SET_NUMBER+PUB_SET_NUMBER].ff*1000))
            {
                need2update = true;
                // 将公共定值同步到对应的开关定值中
                // 实际功能使用的定值已经更新，此处同步是为了液晶显示一致。
                psetbuf[swindex+sw*SW_SET_NUMBER+PUB_SET_NUMBER].ff = psetbuf[pubindex].ff;
                psetbuf[swindex+1+sw*SW_SET_NUMBER+PUB_SET_NUMBER].ff = psetbuf[pubindex+1].ff;
                psetbuf[swindex+2+sw*SW_SET_NUMBER+PUB_SET_NUMBER].ff = psetbuf[pubindex+2].ff;
            }
        }
    }

    if(need2update)
    {
        if(SaveSet(0,(void *)psetbuf))
		{
			soe_record_opt(EV_SET_OK,0);
            rt_printf("电流越限公共定值同步到开关定值 成功! \r\n");
        }
        else
        {
            soe_record_opt(EV_SET_FAIL,0);  
            rt_printf("电流越限公共定值同步到开关定值 失败! \r\n");
        }
    }

    rt_free(psetbuf);
}
#endif