/****************************************************************************
** File name    :  HTIEC61850ISOFile.cpp
** Description  :  define ISO iec 61850 dat file parser api
** Create date  :  2019.09.01
** Auther by    :  Liuyx
** Version info :  V1.0.01
** Copyrigth By:  xi'an huatek, Inc Co., Ltd
** Update record:
** DATE         AUTHER   DESC
** -------------------------------------------------------------------------
** 2019.09.01   Liuyx    first build
****************************************************************************/
#include "HTGlobal.h"

static const char *_FILE_ = "HTIEC61850ISOFile.cpp";
/*****************************************************************************
* read_cmtr_cfg_line - 读cmtr配置文件一行，跳过空行.
* @pfd:  输入输出参数，地址；
* @strline：输出参数，内容缓冲区；
* @size：输入参数，缓冲区大小；
* @strlend: 输出参数，读取的line的结束字符指针；
* @counter:  输出参数，读取的字节计数器；
*
* 返回当前pfd指针,读失败返回-1。
*
******************************************************************************/
static int read_cmtr_cfg_line(int pfd, char *strline, int size, char **strlend, int *counter)
{
    int pos = 0;
    int oldnum = 0;
    unsigned char datard = 0;
    int curr_pfd = pfd;
    (*strlend) = NULL;
    if (size <= 0) {
        return -1;
    }
    if ((!strline) || (!counter)) {
        return -1;
    }

    memset(strline, '\0', size);
    while (ht_check_cmtr_ptr(curr_pfd)) {
        oldnum = (*counter);
        datard = '\0';
        //*counter = _read(curr_pfd, (void*)&datard, sizeof(char));
        ht_read_cmtr_data(curr_pfd, &datard, 1, *counter);
        if ((*counter) > oldnum) {
            if ((datard != '\0') && (datard != '\r') && (datard != '\n')) {
                if ((*strlend) < (strline + size)) {
                    (*(strline + pos)) = datard;
                    (*strlend) = strline + pos;
                }
                pos += 1;
                continue;
            }
            else {
                break;
            }
        }
    }
    if (pos == 0) {
        if (ht_check_cmtr_ptr(curr_pfd)) {
            return read_cmtr_cfg_line(curr_pfd, strline, size, strlend, counter);
        }
        else {
            return RET_FAIL;
        }
    }

    return curr_pfd;
}

/******************************************************************************
* read_cmtr_cfg_one_analog - 分析一行模拟量信息.
* @analog:  输出参数，模拟量信息；
* @strline：输入参数，内容缓冲区；
* @size：输入参数，缓冲区大小；
* @strlend: 输入参数，读取的line结束指针；
*
* 返回TRUE成功,失败返回FALSE。
*
******************************************************************************/
static bool read_cmtr_cfg_one_analog(ST_CMTR_CFG_ANALOG *pstAnalog, char *strline, int size, char *strlend)
{
    int dataint = 0;
    double dataflt = 0;
    char* ptrpos = 0;
    char* strlcur = strline;

    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
        return false;
    }
    pstAnalog->index = dataint;

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    memset(pstAnalog->name, '\0', CMTR_STRING_MAX_LENGTH);
    memcpy(pstAnalog->name, strlcur, ptrpos - strlcur);

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    memset(pstAnalog->phase, '\0', CMTR_STRING_MAX_LENGTH);
    memcpy(pstAnalog->phase, strlcur, ptrpos - strlcur);

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    memset(pstAnalog->element, '\0', CMTR_STRING_MAX_LENGTH);
    memcpy(pstAnalog->element, strlcur, ptrpos - strlcur);

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    memset(pstAnalog->unit, '\0', CMTR_STRING_MAX_LENGTH);
    memcpy(pstAnalog->unit, strlcur, ptrpos - strlcur);

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    if (sscanf(strlcur, "%lf%*s", &dataflt) <= 0) {
        return false;
    }
    pstAnalog->factor_a = dataflt;

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    if (sscanf(strlcur, "%lf%*s", &dataflt) <= 0) {
        return false;
    }
    pstAnalog->factor_b = dataflt;

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
        return false;
    }
    pstAnalog->offset_time = dataint;

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
        return false;
    }
    pstAnalog->smp_min = dataint;

    strlcur = ptrpos += 1;
    if (ptrpos > strlend) {
        return false;
    }
    if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
        return false;
    }
    pstAnalog->smp_max = dataint;

    return true;
}

/******************************************************************************
* read_cmtr_cfg_one_digit - 分析一行数字量信息.
* @analog:  输出参数，数字量信息；
* @strline：输入参数，内容缓冲区；
* @size：输入参数，缓冲区大小；
* @strlend: 输入参数，读取的line结束指针；
*
* 返回TRUE成功,失败返回FALSE。
*
******************************************************************************/
static bool read_cmtr_cfg_one_digit(ST_CMTR_CFG_DIGIT *pstDigit, char *strline, int size, char *strlend)
{
    int dataint = 0;
    char* ptrpos = 0;
    char* strlcur = strline;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    if (sscanf(strlcur, "%d%*s", &dataint) <= 0) {
        return false;
    }
    pstDigit->index = dataint;

    strlcur = ptrpos += 1;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return false;
    }
    memset(pstDigit->name, '\0', CMTR_STRING_MAX_LENGTH);
    memcpy(pstDigit->name, strlcur, ptrpos - strlcur);

    strlcur = ptrpos += 1;
    if (ptrpos > strlend) {
        return false;
    }
    if (sscanf(strlcur, "%d", &dataint) <= 0) {
        return false;
    }
    pstDigit->state = dataint;

    return true;
}

/******************************************************************************
* read_cmtr_cfg_info - 读cmtr配置文件.
* @pfd:  输入输出参数，地址
* @cfg：输出参数，cmtr(cfg文件)结构体
* @counter:  输出参数，读取的字节计数器；
*
* 返回当前pfd指针,读失败返回NULL
*
******************************************************************************/
static int read_cmtr_cfg_info(int pfd, ST_CMTR_CFG_INFO *pstCfg, int* counter)
{
    unsigned char returntag = false;

    int strsize = 1024;
    char* strline = NULL;
    char* strlcur = NULL;
    char* strlend = NULL;
    int curr_pfd = pfd;

    char* ptrpos = 0;

    int port1num = 0;
    int port2num = 0;
    char port1chr = '\0';
    char port2chr = '\0';

    int index = 0;
    int dataint = 0;
    f32 dataflt = 0;

    assert(pfd && pstCfg);

    strline = (char*)calloc(strsize, sizeof(char));
    memset(strline, '\0', strsize);

    /* read station name and  kymograph id */
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);

    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    strlcur = strline;
    ptrpos = strchr(strlcur, ',');
    memset(pstCfg->station_name, '\0', CMTR_STRING_MAX_LENGTH);
    memset(pstCfg->kymograph_id, '\0', CMTR_STRING_MAX_LENGTH);
    if (ptrpos) {
        memcpy(pstCfg->station_name, strlcur, ptrpos - strlcur);
        if (ptrpos < strlend) {
            ptrpos += 1;
            memcpy(pstCfg->kymograph_id, ptrpos, strlen(ptrpos));
        }
    }
    else {
        memcpy(pstCfg->station_name, strlcur, strlen(strlcur));
    }

    /* read port count */
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    strlcur = strline;
    ptrpos = strchr(strlcur, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        goto RETURN_FINISH;
    }
    ptrpos += 1;
    if (sscanf(ptrpos, "%d%c%*s", &port1num, &port1chr) <= 0) {
        goto RETURN_FINISH;
    }
    ptrpos = strchr(ptrpos, ',');
    if ((!ptrpos) || (ptrpos >= strlend)) {
        goto RETURN_FINISH;
    }
    ptrpos += 1;
    if (sscanf(ptrpos, "%d%c", &port2num, &port2chr) <= 0) {
        goto RETURN_FINISH;
    }
    if ((port1chr == 'A') || (port1chr == 'a')) {
        pstCfg->analog_count = port1num;
        pstCfg->digit_count = port2num;
    }
    else if ((port1chr == 'D') || (port1chr == 'd')) {
        pstCfg->analog_count = port2num;
        pstCfg->digit_count = port1num;
    }
    else {
        goto RETURN_FINISH;
    }

    /* read analog port info */
    for (index = 0; index < pstCfg->analog_count; index++) {
        curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
        if (!curr_pfd) {
            goto RETURN_FINISH;
        }
        if (!read_cmtr_cfg_one_analog((pstCfg->analogs) + index, strline, strsize, strlend)) {
            goto RETURN_FINISH;
        }
    }
    /* read digit port info */
    for (index = 0; index < pstCfg->digit_count; index++) {
        curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
        if (!curr_pfd) {
            goto RETURN_FINISH;
        }
        if (!read_cmtr_cfg_one_digit((pstCfg->digits) + index, strline, strsize, strlend)) {
            goto RETURN_FINISH;
        }
    }

    /* read Frequency info */
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    if (strline > strlend) {
        goto RETURN_FINISH;
    }
    if (sscanf(strline, "%f", &dataflt) <= 0) {
        goto RETURN_FINISH;
    }
    pstCfg->frequency = dataflt;

    /* read smprate count info */
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    if (strline > strlend) {
        goto RETURN_FINISH;
    }
    if (sscanf(strline, "%d", &dataint) <= 0) {
        goto RETURN_FINISH;
    }
    pstCfg->smprate_count = dataint;

    /* read smprate info */
    for (index = 0; index < pstCfg->smprate_count; index++) {
        curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
        if (!curr_pfd) {
            goto RETURN_FINISH;
        }
        strlcur = strline;
        ptrpos = strchr(strlcur, ',');
        if ((!ptrpos) || (ptrpos >= strlend)) {
            goto RETURN_FINISH;
        }
        if (sscanf(strlcur, "%f%*s", &dataflt) <= 0) {
            goto RETURN_FINISH;
        }
        pstCfg->smprates[index].rate = dataflt;
        strlcur = ptrpos += 1;
        if (ptrpos > strlend) {
            goto RETURN_FINISH;
        }
        if (sscanf(strlcur, "%d", &dataint) <= 0) {
            goto RETURN_FINISH;
        }
        pstCfg->smprates[index].point = dataint;
    }

    /* read time info */
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    memset(pstCfg->begin_time, '\0', CMTR_STRING_MAX_LENGTH);
    if (strlend - strline >= 0) {
        memcpy(pstCfg->begin_time, strline, strlend - strline + 1);
    }
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    memset(pstCfg->end_time, '\0', CMTR_STRING_MAX_LENGTH);
    if (strlend - strline >= 0) {
        memcpy(pstCfg->end_time, strline, strlend - strline + 1);
    }

    /* read dat type info */
    curr_pfd = read_cmtr_cfg_line(curr_pfd, strline, strsize, &strlend, counter);
    if (!curr_pfd) {
        goto RETURN_FINISH;
    }
    strlcur = str2upper(strline); //_my_strupr(strline);
    ptrpos = strstr(strlcur, "BIN");
    memset(pstCfg->file_type, '\0', CMTR_STRING_MAX_LENGTH);
    if (ptrpos > 0) {
        strcpy((char*)pstCfg->file_type, "BINARY");
    }
    else if (strstr(strlcur, "ASC") > 0) {
        strcpy((char*)pstCfg->file_type, "ASCII");
    }
    else {
        goto RETURN_FINISH;
    }

    returntag = true;

RETURN_FINISH:
    if (strline) {
        free(strline);
        strline = NULL;
    }
    return returntag ? curr_pfd : RET_FAIL;
}

/******************************************************************************
* write_cmtr_cfg_info - 写cmtr配置文件.
* @pfd:  输入输出参数，地址
* @cfg：输入参数，cmtr(cfg文件)结构体
* @counter:  输出参数，写入的字节计数器；
*
* 返回当前pfd指针,写失败返回NULL
*
******************************************************************************/
int write_cmtr_cfg_info(int pfd, ST_CMTR_CFG_INFO *pstCfg, int *counter)
{
    unsigned int strlenr = 0;
    unsigned int strmaxl = CMTR_STRING_MAX_LENGTH * 10;
    unsigned char* strline = (unsigned char *)calloc((size_t)(strmaxl), sizeof(char));
    int index = 0;

    int curr_pfd = pfd;

    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%s,%s\n", pstCfg->station_name, pstCfg->kymograph_id);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);

    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%d,%dA,%dD\n", pstCfg->analog_count + pstCfg->digit_count, pstCfg->analog_count, pstCfg->digit_count);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);

    for (index = 0; index < pstCfg->analog_count; index++) {
        memset(strline, '\0', strmaxl);
        strlenr = sprintf((char*)strline, "%d,%s,%s,%s,%s,%lf,%lf,%d,%d,%d\n",
            pstCfg->analogs[index].index,
            pstCfg->analogs[index].name,
            pstCfg->analogs[index].phase,
            pstCfg->analogs[index].element,
            pstCfg->analogs[index].unit,
            pstCfg->analogs[index].factor_a,
            pstCfg->analogs[index].factor_b,
            pstCfg->analogs[index].offset_time,
            pstCfg->analogs[index].smp_min,
            pstCfg->analogs[index].smp_max);
        ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    }

    for (index = 0; index < pstCfg->digit_count; index++) {
        memset(strline, '\0', strmaxl);
        strlenr = sprintf((char*)strline, "%d,%s,%d\n",
            pstCfg->digits[index].index,
            pstCfg->digits[index].name,
            pstCfg->digits[index].state);
        ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    }

    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%f\n", pstCfg->frequency);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);

    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%d\n", pstCfg->smprate_count);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    for (index = 0; index < pstCfg->smprate_count; index++) {
        memset(strline, '\0', strmaxl);
        strlenr = sprintf((char*)strline, "%f,%d\n", pstCfg->smprates[index].rate, pstCfg->smprates[index].point);
        ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    }

    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%s\n", pstCfg->begin_time);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%s\n", pstCfg->end_time);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    strlenr = sprintf((char*)strline, "%s\n", pstCfg->file_type);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    if (strline) {
        free(strline);
        strline = NULL;
    }

    return curr_pfd;
}

/******************************************************************************
* print_cmtr_cfg_info - 打印cmtr文件配置数.
* @cfg:  输入参数，cmtr文件配置数据;
*
******************************************************************************/
void print_cmtr_cfg_info(ST_CMTR_CFG_INFO *pstCfg)
{
    int index = 0;
    if (pstCfg) {
        printf("=====================\n");
        printf("%s,%s\n", pstCfg->station_name, pstCfg->kymograph_id);
        printf("%d,%dA,%dD\n", pstCfg->analog_count + pstCfg->digit_count, pstCfg->analog_count, pstCfg->digit_count);
        for (index = 0; index < pstCfg->analog_count; index++) {
            printf("%d, %s, %s, %s, %s, %.6lf, %.6lf, %d, %d, %d\n",
                pstCfg->analogs[index].index,
                pstCfg->analogs[index].name,
                pstCfg->analogs[index].phase,
                pstCfg->analogs[index].element,
                pstCfg->analogs[index].unit,
                pstCfg->analogs[index].factor_a,
                pstCfg->analogs[index].factor_b,
                pstCfg->analogs[index].offset_time,
                pstCfg->analogs[index].smp_min,
                pstCfg->analogs[index].smp_max);
        }
        for (index = 0; index < pstCfg->digit_count; index++) {
            printf("%d,%s,%d\n",
                pstCfg->digits[index].index,
                pstCfg->digits[index].name,
                pstCfg->digits[index].state);
        }
        printf("%.6f\n", pstCfg->frequency);
        for (index = 0; index < pstCfg->smprate_count; index++) {
            printf("%.4f,%d\n", pstCfg->smprates[index].rate, pstCfg->smprates[index].point);
        }
        printf("%s\n", pstCfg->begin_time);
        printf("%s\n", pstCfg->end_time);
        printf("%s\n", pstCfg->file_type);
        printf("=====================\n");
    }
}

/******************************************************************************
* read_cmtr_dat_smpdot_ascii - 读ascii格式cmtr采样点数据信息.
* @pfd:  输入输出参数，地址
* @read_buf: 输入参数，读缓冲,在外部申请内存，避免在内部频繁申请、释放内存；
* @buf_size: 输入参数，读缓冲区的大小；
* @analog_count: 输入参数，模拟量个数；
* @digit_count: 输入参数，数字量个数；
* @dot:  输出参数，采样点信息；
* @the_smp_mins: 输出参数，统计最小值,为数组，个数至少为analog_count个,值为NULL时忽略统计；
* @the_smp_maxs: 输出参数，统计最大值,为数组，个数至少为analog_count个,值为NULL时忽略统计；
* @counter:  输出参数，读取的字节计数器；
*
* 返回当前pfd指针,读失败返回-1
*
******************************************************************************/
int read_cmtr_dat_smpdot_ascii(int pfd, unsigned char *read_buf, int buf_size,  int analog_count, 
    int digit_count, ST_CMTR_DAT_SMPDOT *pstDot, unsigned short* the_smp_mins, 
    unsigned short* the_smp_maxs, int* counter)
{
    char* ptrpos = 0;
    char* strlend = 0;

    int index = 0;

    int dataint = 0;
    float dataflt = 0;

    int curr_pfd = pfd;

    memset(read_buf, '\0', buf_size);
    curr_pfd = read_cmtr_cfg_line(curr_pfd, (char*)read_buf, buf_size, &strlend, counter);
    if (!curr_pfd) {
        return RET_FAIL;
    }

    ptrpos = (char*)read_buf;
    if ((!ptrpos) || (ptrpos >= strlend)) {
        return RET_FAIL;
    }
    if (sscanf(ptrpos, "%d%*s", &dataint) <= 0) {
        return RET_FAIL;
    }
    pstDot->index = dataint;
    ptrpos = strchr(ptrpos, ',');
    if (!ptrpos) {
        return RET_FAIL;
    }
    ptrpos += 1;
    if ((!ptrpos) || (ptrpos > strlend)) {
        return RET_FAIL;
    }
    if (sscanf(ptrpos, "%d%*s", &dataint) <= 0) {
        return RET_FAIL;
    }
    pstDot->time = dataint;

    /* read analog port info */
    for (index = 0; index < analog_count; index++) 
    {
        ptrpos = strchr(ptrpos, ',');
        if (!ptrpos) {
            return RET_FAIL;
        }
        ptrpos += 1;
        if ((!ptrpos) || (ptrpos > strlend)) {
            return RET_FAIL;
        }
        if (sscanf(ptrpos, "%f%*s", &dataflt) <= 0) {
            return RET_FAIL;
        }
        pstDot->analogs[index] = (int)dataflt;
        if (the_smp_mins) {
            if (the_smp_mins + index) {
                the_smp_mins[index] = (unsigned short)((float)the_smp_mins[index] < dataflt ? the_smp_mins[index]: dataflt); //_my_min(the_smp_mins[index], dataflt);
            }
        }
        if (the_smp_maxs) {
            if (the_smp_maxs + index) {
                the_smp_maxs[index] = (unsigned short)((float)the_smp_maxs[index]> dataflt ? the_smp_maxs[index] : dataflt); // _my_min(the_smp_maxs[index], dataflt);
            }
        }
    }
    /* read digit port info */
    for (index = 0; index < digit_count; index++) {
        ptrpos = strchr(ptrpos, ',');
        if (!ptrpos) {
            return RET_FAIL;
        }
        ptrpos += 1;
        if ((!ptrpos) || (ptrpos > strlend)) {
            return RET_FAIL;
        }
        if (sscanf(ptrpos, "%d%*s", &dataint) <= 0) {
            return RET_FAIL;
        }
        pstDot->digits[index] = dataint;
    }

    return curr_pfd;
}

/******************************************************************************
* read_cmtr_dat_smpdot_binary - 读bin格式cmtr采样点数据信息.
* @pfd:  输入输出参数，地址
* @big_endian_tag: 输入参数，标识文件中数据的字节顺序，为FALSE按照小端读（默认值），True按照大端读；
* @analog_count: 输入参数，模拟量个数；
* @digit_count: 输入参数，数字量个数；
* @dot:  输出参数，采样点信息；
* @the_smp_mins: 输出参数，统计最小值,为数组，个数至少为analog_count个,值为NULL时忽略统计；
* @the_smp_maxs: 输出参数，统计最大值,为数组，个数至少为analog_count个,值为NULL时忽略统计；
* @counter:  输出参数，读取的字节计数器；
*
* 返回当前pfd指针,读失败返回-1
*
******************************************************************************/
int read_cmtr_dat_smpdot_binary(int pfd, unsigned char big_endian_tag,
    int analog_count, int digit_count, ST_CMTR_DAT_SMPDOT *pstDot,
    unsigned int* the_smp_mins, unsigned int* the_smp_maxs, int* counter)
{
    unsigned short data16 = 0x00;
    unsigned int data32 = 0x00;
    int oldnum = 0;

    int index = 0;
    int bitpos = 0;

    int curr_pfd = pfd;

    oldnum = (*counter);
    data32 = 0x00;
    ht_read_cmtr_data(curr_pfd, &data32, 4, *counter);  // format: n(4)+time(4)+A1(2)+A2(2)+...+Ak(2)+S1(2)+S2(2)+Sm(2)
    if ((*counter) <= oldnum) {
        return RET_FAIL;
    }
    //dot->index = big_endian_tag ? _my_btoh32(data32) : _my_ltoh32(data32);
    pstDot->index = big_endian_tag ? ntohi(data32) : data32;

    oldnum = (*counter);
    data32 = 0x00;
    ht_read_cmtr_data(curr_pfd, &data32, 4, *counter);
    if ((*counter) <= oldnum) {
        return RET_FAIL;
    }
    pstDot->time = big_endian_tag ? ntohi(data32) : (data32);

    /* read analog port info */
    for (index = 0; index < analog_count; index++) {
        oldnum = (*counter);
        data16 = 0x00;
        ht_read_cmtr_data(curr_pfd, &data16, 2, *counter);
        if ((*counter) <= oldnum) {
            return RET_FAIL;
        }
        pstDot->analogs[index] = big_endian_tag ? ntohs(data16) : (data16);
        if (the_smp_mins) {
            if (the_smp_mins + index) {
                the_smp_mins[index] = (int)the_smp_mins[index] < pstDot->analogs[index] ? the_smp_mins[index] : pstDot->analogs[index];  // _my_min(the_smp_mins[index], dot->analogs[index]);
            }
        }
        if (the_smp_maxs) {
            if (the_smp_maxs + index) {
                the_smp_maxs[index] = (int)the_smp_maxs[index]> pstDot->analogs[index] ? the_smp_maxs[index] : pstDot->analogs[index]; // _my_min(the_smp_maxs[index], dot->analogs[index]);
            }
        }
    }
    /* read digit port info */
    for (index = 0; index < digit_count; index++) {
        oldnum = (*counter);
        data16 = 0x00;
        ht_read_cmtr_data(curr_pfd, &data16, 2, *counter);
        if ((*counter) <= oldnum) {
            return RET_FAIL;
        }
        data16 = big_endian_tag ? ntohs(data16) : (data16);
        for (bitpos = 0; bitpos < 16; bitpos++) {
            if ((index * 16 + bitpos) < digit_count) {
                pstDot->digits[index * 16 + bitpos] = (data16 & (0x0001 << bitpos));
            }
            else {
                break;
            }
        }
    }

    return curr_pfd;
}


/******************************************************************************
* write_cmtr_dat_smpdot_ascii - 写cmtr采样点数据信息(ascii格式).
* @pfd:  输入输出参数，地址
* @analog_count: 输入参数，模拟量个数；
* @digit_count: 输入参数，数字量个数；
* @dot:  输入参数，采样点信息；
* @counter:  输出参数，写入的字节计数器；
*
* 返回当前pfd指针,写失败返回NULL
*
******************************************************************************/
int write_cmtr_dat_smpdot_ascii(int pfd, int analog_count, int digit_count, ST_CMTR_DAT_SMPDOT *pstDot, int* counter)
{
    unsigned int strlenr = 0;
    unsigned int strmaxl = CMTR_STRING_MAX_LENGTH;
    unsigned char* strline = (unsigned char *)calloc((size_t)(strmaxl), sizeof(char));
    int index = 0;

    int curr_pfd = pfd;

    assert(pfd && pstDot);

    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "%d,%d", pstDot->index, pstDot->time);
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    for (index = 0; index < analog_count; index++) {
        memset(strline, '\0', strmaxl);
        strlenr = sprintf((char*)strline, ",%d", pstDot->analogs[index]);
        ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    }
    for (index = 0; index < digit_count; index++) {
        memset(strline, '\0', strmaxl);
        strlenr = sprintf((char*)strline, ",%d", pstDot->digits[index]);
        ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);
    }
    memset(strline, '\0', strmaxl);
    strlenr = sprintf((char*)strline, "\n");
    ht_write_cmtr_data(curr_pfd, strline, strlenr, *counter);

    if (strline) {
        free((char*)strline);
    }
    strline = NULL;

    return curr_pfd;
}

/******************************************************************************
* print_cmtr_dat_smpdot - 打印cmtr数据文件采样点.
* @cfg:  输入参数，cmtr文件配置数据;
* @analog_count: 输入参数，模拟量个数；
* @digit_count: 输入参数，数字量个数；
* @dot:  输入参数，采样点信息；
*
******************************************************************************/
void print_cmtr_dat_smpdot(int analog_count, int digit_count, ST_CMTR_DAT_SMPDOT *pstDot)
{
    int index = 0;
    if (pstDot) {
        printf("%u,%d", pstDot->index, pstDot->time);
        for (index = 0; index < analog_count; index++) {
            printf(",%d", pstDot->analogs[index]);
        }
        for (index = 0; index < digit_count; index++) {
            printf(",%d", pstDot->digits[index]);
        }
        printf("\n");
    }
}


// 加载61850配置信息
int iLoad61850Config(ST_CMTR_CFG_INFO &stCfg)
{
    int counter1 = 0;
    int fdcfg = 0;
    printf("config_file=%s\n", g_TConfig.getIecConfigFileName());
    fdcfg = ht_cmtr_openrb(g_TConfig.getIecConfigFileName());
    assert(fdcfg);

    read_cmtr_cfg_info(fdcfg, &stCfg, &counter1);
    ht_cmtr_close(fdcfg);

    print_cmtr_cfg_info(&stCfg);
    return counter1;
}

// 创建测试配置文件
int iCreateTest61850Config()
{
    ST_CMTR_CFG_INFO stCfg;
    int counter1 = 0;
    int fdcfg = 0;
    char szTmp[64] = { 0 };

    memset(&stCfg, 0x00, sizeof(ST_CMTR_CFG_INFO));
    printf("cfg_size = %ld\n", sizeof(ST_CMTR_CFG_INFO));

    strcpy((char*)stCfg.station_name, "浙江仙居蓄能抽水发电站");    // 站点名称
    strcpy((char*)stCfg.kymograph_id, "ZJXJ_IEC_61850_TEST001");  // 录波器编号
    strcpy((char*)stCfg.begin_time, "2019-09-25 15:54:30");  // 起始时间
    strcpy((char*)stCfg.end_time, "2019-09-25 15:59:45");  // 结束时间
    strcpy((char*)stCfg.file_type, "BINARY");  // 文件类型
    stCfg.analog_count = 20;   // 模拟量个数
    stCfg.digit_count = 10;    // 数字量个数
    stCfg.frequency = 50.00f;    // 50Hz
    stCfg.smprate_count = 180;        // 采样率个数
    for (int i = 0; i < stCfg.analog_count; i++) {
        stCfg.analogs[i].index = i;
        stCfg.analogs[i].factor_a = getRandByTime();
        stCfg.analogs[i].factor_b = getRandByTime();
        stCfg.analogs[i].offset_time = 0;
        stCfg.analogs[i].smp_min = 1;
        stCfg.analogs[i].smp_max = 30;
        sprintf(szTmp, "模拟量端口名称%02d", i + 1);
        strcpy((char*)stCfg.analogs[i].name, szTmp);
        strcpy((char*)stCfg.analogs[i].unit, "Kv");
        strcpy((char*)stCfg.analogs[i].phase, "A");
    }

    for (int i = 0; i < stCfg.digit_count; i++) {
        stCfg.digits[i].index = i;
        stCfg.digits[i].state = 1;
        sprintf(szTmp, "数字量端口名称%02d", i + 1);
        strcpy((char*)stCfg.digits[i].name, szTmp);
    }

    for (int i = 0; i < stCfg.smprate_count; i++) {
        stCfg.smprates[i].rate = (float)getRandByTime();
        stCfg.smprates[i].point = 123;
    }
    printf("File: %s  \n", g_TConfig.getIecConfigFileName());
    fdcfg = f_open(g_TConfig.getIecConfigFileName(), O_CREAT | O_RDWR, S_IWRITE | S_IREAD);
    printf("File: %s  errno:%d:%s\n", g_TConfig.getIecConfigFileName(), errno, strerror(errno));
    //fdcfg = ht_cmtr_openwb(g_TConfig.getIecConfigFileName());
    assert(!(fdcfg<0));

    write_cmtr_cfg_info(fdcfg, &stCfg, &counter1);
    ht_cmtr_close(fdcfg);

    print_cmtr_cfg_info(&stCfg);
    return counter1;
}

/********************************************************************
* function   : vIec61850Application
* param in   : none
* param out  : None
* return val : None
* Description: iec 61850 protocol parser.
********************************************************************/
void vIec61850FileParser()
{
    int counter1 = 0;
    ST_CMTR_DAT_SMPDOT stDot;
    ST_CMTR_CFG_INFO stCfg;
    int fddat1 = 0;

    memset(&stCfg, 0x00, sizeof(ST_CMTR_CFG_INFO));
    counter1 = iLoad61850Config(stCfg);

    printf("cfg_size = %ld  read_config_byte_size=%d\n", sizeof(ST_CMTR_CFG_INFO), counter1);
    int analog_count = 0;
    int digit_count = 0;
    unsigned int *uithe_smp_mins = 0;
    unsigned int *uithe_smp_maxs = 0;

    //printf("data_file=%s\n", g_TConfig.getIecBinFilePath());
    //fddat1 = ht_cmtr_openrb(g_TConfig.getIecBinFilePath());
    while (ht_check_cmtr_ptr(fddat1)) 
    {
        analog_count = stCfg.analog_count;
        digit_count = stCfg.digit_count;

        if (analog_count > 0) uithe_smp_mins = (unsigned int*)calloc((2 * analog_count), sizeof(int)); //_my_buf_malloc(2 * analog_count);
        if (digit_count > 0) uithe_smp_maxs = (unsigned int*)calloc((2 * digit_count), sizeof(int)); //_my_buf_malloc(2 * digit_count);
        
        fddat1 = read_cmtr_dat_smpdot_binary(fddat1, false, analog_count, digit_count, &stDot, uithe_smp_mins, uithe_smp_maxs, &counter1);
        if (ht_check_cmtr_ptr(fddat1)) 
        {
            print_cmtr_dat_smpdot(analog_count, digit_count, &stDot);
        }

        
    }
    ht_cmtr_close(fddat1);
}

