#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <pthread.h>

#include "xieneng_can_supervisor.h"
#include "xieneng_can_mqtt.h"
#include "can_inf.h"
#include "bmser_log.h"
#include "bmser_mqtt.h"
#include "bmser_dev.h"
#include "toolkit.h"
#include "cJSON.h"
#include "bmser_utils.h"
#include "bmser_error_code.h"
#include "bmser_can_init.h"
#include "bmser_can_j1939_send.h"
#include "bmser_can_j1939_recv.h"
#include "bmser_can_j1939_syn_data.h"
#include "bmser_project_para.h"

#define BMS_TOTAL_DATE_CFG_DB_ADDR              0x0006
#define BMS_TOTAL_DATE_CFG_DB_COUNT             6
#define ENDIAN_TYPE_CONVERT_16(num)  ((((uint16_t)(num) & 0xff00U) >> 8) | \
                                      (((uint16_t)(num) & 0x00ffU) << 8))
#define UPDATE_TIMEOUT                          10000  /*标识升级状态超时时间，单位：ms*/

static int sync_times = 0;
static bool sync_time = false, recv_year = false, recv_min = false;
static uint16_t date_info[8] = {0}, date_info_bak[8] = {0};
static void xieneng_can_send_get_rtc_request(xieneng_can_var_t *var);

xieneng_can_var_t g_xienengCanInfo = {0};
int g_j1939_send_timer = 0;     // j1939请求定时器
int g_j1939_recv_timer = 0;     // j1939接收定时器
int g_j1939_syn_data_timer = 0; // j1939同步信息交互定时器

uint64_t g_receive_upgradePkgTime = 0;      // 最后一次接收到升级包的时间
static bool g_j1939_req_enable = false, g_j1939_listen_enable = false;    //j1939请求/监听开关量

static void share_dir_make(void)
{
    int i;
    char tmp[100] = {0};
    for (i = 0; i < CAN_OBJ_ID_MAX; i++)
    {
        snprintf(tmp, sizeof(tmp), "%s/%d" ,SHAREMEM_PREFIX, i);
        check_make_dir(tmp);
    }
}

static bool sync_linux_system_time(xieneng_can_var_t *var, unsigned short start_addr, unsigned short reg_cnt, unsigned char* data)
{
    int i = 0;
    char buf[32] = {0};

    if (BMS_TOTAL_DATE_CFG_DB_ADDR == start_addr && 4 == reg_cnt) { //canbus一次只能接收8个字节数据,年月日时分秒六个寄存器数据需要通过两个CAN包接收
        if (sync_times % 2 == 1) {
            memcpy(date_info, data, reg_cnt * 2);
        } else {
            memcpy(date_info_bak, data, reg_cnt * 2);
        }
        recv_year = true;
    } else if (BMS_TOTAL_DATE_CFG_DB_ADDR + 4 == start_addr && (BMS_TOTAL_DATE_CFG_DB_COUNT - 4) == reg_cnt) {
        if (sync_times % 2 == 1) {
            memcpy(&date_info[4], data, reg_cnt * 2);
        } else {
            memcpy(&date_info_bak[4], data, reg_cnt * 2);
        }
        recv_min = true;
    } else {
        return false;
    }

    if (recv_year && recv_min) {
        sync_times++;
        recv_year = recv_min = false;
    }

    if (sync_times > 0 && 0 == sync_times % 2) {
        if (0 == memcmp(date_info, date_info_bak, (BMS_TOTAL_DATE_CFG_DB_COUNT - 1) * 2)) { //比较年月日时分
            for (i = 0; i < BMS_TOTAL_DATE_CFG_DB_COUNT; i++) {
                date_info[i] = ENDIAN_TYPE_CONVERT_16(date_info[i]);
            }
            // dy_syslog(LOG_DEBUG, "recv rtc date = %d,%d,%d,%d,%d,%d.", date_info[0], date_info[1], date_info[2], date_info[3], date_info[4], date_info[5]);
            snprintf(buf, sizeof(buf), "date -s \"%02d:%02d:%02d %4d%02d%02d\"", date_info[3], date_info[4], date_info[5], date_info[0], date_info[1], date_info[2]);
            dy_syslog(LOG_DEBUG, "recv rtc data, date cmd is %s.", buf);
            system(buf);
            sync_times = 0;
            memset(date_info, 0, sizeof(date_info));
            memset(date_info_bak, 0, sizeof(date_info_bak));
            return true;
        } else {//时间出现跳变,再次发送读日期请求
            sync_times = 0;
            memset(date_info, 0, sizeof(date_info));
            memset(date_info_bak, 0, sizeof(date_info_bak));
            xieneng_can_send_get_rtc_request(var);
        }
    }
    return false;
}

MSG_FLOW_INFO_STRU g_msgFlowInfo[MAX_UPDATE_DEV_NUM] = {0};

static uint16_t canRcv_selectMsgFlowInfoId(uint32_t canId)
{
    uint16_t selectInfoId = 0;
    uint32_t combinaId = 0, i =0;

    combinaId = canId >> 6;
    //选择出对应的组包的数据信息对�?
    for(i=0; i<MAX_UPDATE_DEV_NUM; i++)
    {
        if(combinaId == g_msgFlowInfo[i].combinaId)
        {
            selectInfoId = i;
            break;
        }
    }
    //如果没有找到对应的组包信息对象，就找出一个空闲的信息对象应用于新的组�?
    if(i == MAX_UPDATE_DEV_NUM)
    {
        for(i=0; i<MAX_UPDATE_DEV_NUM; i++)
        {
            if(0 == g_msgFlowInfo[i].lastMsgFlowRspTime)
            {
                selectInfoId = i;
                break;
            }
        }
        
    }
    
    return selectInfoId;
}

static int canRcv_msg_flow_rsp(xieneng_can_var_t *var, CanMsg *rxcan)
{
    uint8_t frameId = GET_PACK_ID(rxcan->CanId);
    uint8_t selectInfoId = 0;
    uint32_t combinaId = 0, i =0;
    uint64_t now  = bmser_get_time_stamp_ms();

    combinaId = (rxcan->CanId >> 6);
    selectInfoId = canRcv_selectMsgFlowInfoId(rxcan->CanId);
    
    //首次接收，则更新下时间
    if(g_msgFlowInfo[selectInfoId].lastMsgFlowRspTime == 0)
    {
        g_msgFlowInfo[selectInfoId].lastMsgFlowRspTime = now;
    }
    //RSP消息间隔超过1S，清除内部记录的所有数
    if((now - g_msgFlowInfo[selectInfoId].lastMsgFlowRspTime) > 1000)
    {
        memset(&g_msgFlowInfo[selectInfoId],0,sizeof(MSG_FLOW_INFO_STRU));
    }        

    //更新一下接收时间
    g_msgFlowInfo[selectInfoId].lastMsgFlowRspTime = now;
    g_msgFlowInfo[selectInfoId].combinaId = combinaId;
    if((frameId == 0) && ((UP_CMD_TYPE == rxcan->Data[1]) || UP_CMD_TYPE_V50 == rxcan->Data[1]))
    {
        //事务ID == 0(升级)
        if((rxcan->CanId >> 7) & 0x03 == 0)
        {
            // 接收到的为升级包,记录时间用于判断can是否被升级占用
            g_receive_upgradePkgTime = bmser_get_time_stamp_ms();
        }
        g_msgFlowInfo[selectInfoId].dataLen = rxcan->Data[0];
        //计算有多少包，总字节数要算是数据长度本身的一个字节
        if((g_msgFlowInfo[selectInfoId].dataLen+1) % 8 != 0)
        {
            g_msgFlowInfo[selectInfoId].validPackNum = ((g_msgFlowInfo[selectInfoId].dataLen+1) / CAN_BUF_LEN) + 1;
        }
        else
        {
            g_msgFlowInfo[selectInfoId].validPackNum = ((g_msgFlowInfo[selectInfoId].dataLen+1) / CAN_BUF_LEN);
        }
    }
    //每收到一帧就将对应的帧置为有效，并放入对应的buf位置里去
    if(frameId < (DATA_LEN/8))
    {  
        g_msgFlowInfo[selectInfoId].flag[frameId] = true;
        memcpy(&g_msgFlowInfo[selectInfoId].buf[frameId * CAN_BUF_LEN],rxcan->Data,CAN_BUF_LEN);
    }

    //检查包是否收齐
    if((g_msgFlowInfo[selectInfoId].validPackNum > 0) && (g_msgFlowInfo[selectInfoId].dataLen > 2))
    {
        uint16_t crc = 0;
        for(i=0; i<g_msgFlowInfo[selectInfoId].validPackNum; i++ )
        {
            if(g_msgFlowInfo[selectInfoId].flag[i] != true)
            {
                return 1;
            }   
        }
        //校验CRC,校验从帧标识开始再减去2字节crc
        crc = BmsMsg_Crc16(&g_msgFlowInfo[selectInfoId].buf[1],(g_msgFlowInfo[selectInfoId].dataLen - 2));
        //这里按照上位机的做法实现，大端小端都是判断下，任一通过即可
        if((crc == (g_msgFlowInfo[selectInfoId].buf[g_msgFlowInfo[selectInfoId].dataLen] | (g_msgFlowInfo[selectInfoId].buf[g_msgFlowInfo[selectInfoId].dataLen - 1]<<8))) || \
        (crc == ((g_msgFlowInfo[selectInfoId].buf[g_msgFlowInfo[selectInfoId].dataLen]<<8) | g_msgFlowInfo[selectInfoId].buf[g_msgFlowInfo[selectInfoId].dataLen - 1])) )
        {
            publish_binaryFlow_data(&g_msgFlowInfo[selectInfoId].buf[1], 
                (g_msgFlowInfo[selectInfoId].dataLen), rxcan->CanId);
        }
        //不管发送完成还是组包失败，都清除所有的数据
        memset(&g_msgFlowInfo[selectInfoId],0,sizeof(MSG_FLOW_INFO_STRU));
    }
    return 0;
}

#ifdef WITH_BMSER_PRODUCT_TEST
static int canRcv_msg_product_test(xieneng_can_var_t *var, CanMsg *rxcan)
{
    if (rxcan->CanId == 0x7FF)
    {
        // dy_syslog(LOG_DEBUG, "recv 7ff packet, data[1] = 0x%x.", rxcan->Data[1]);
        if ((rxcan->Data[1] & UP_CMD_TYPE) == UP_CMD_TYPE)
        {
            publish_cmd_binary_data_7ff(var->canObjId, rxcan->Data, rxcan->DLC, CMD_RSP);
        }
        else if ((((rxcan->Data[1] >> 2) & 0x7) == 4) && (((rxcan->Data[1] >> 5) & 0x07) == E_CAN_WRITE))
        {
            publish_cmd_binary_data_7ff(var->canObjId, rxcan->Data, rxcan->DLC, WRITE);
        }
        else if ((((rxcan->Data[1] >> 2) & 0x7) == 4) && (((rxcan->Data[1] >> 5) & 0x07) == E_CAN_READ))
        {
            publish_cmd_binary_data_7ff(var->canObjId, rxcan->Data, rxcan->DLC, READ);
        }
        else if ((((rxcan->Data[1] >> 2) & 0x7) == 2) && (((rxcan->Data[1] >> 5) & 0x07) == E_CAN_WRITE_REPLY))
        {
            publish_cmd_binary_data_7ff(var->canObjId, rxcan->Data, rxcan->DLC, WRITE_RSP2);
        }
        else
        {
            //do nothing
        }
    }
	return 0;
}
#endif

static int canRcv_msg_RWreply(xieneng_can_var_t *var, CanMsg *rxcan)
{
    unsigned short start_addr;
    unsigned char func = 0;
    unsigned char dev_id = 0;
    unsigned char layer = 0;
    unsigned short term_addr = 0;
    int len = 0;//rackId是按照每堆下的簇序号
    unsigned short reg_cnt = 0;
    uint16_t bankId = 0,rackId = 0;
    if (var->upgradeflag == 1)
    {
        return -1;
    }
    start_addr = rxcan->CanId & 0xFFFF;
    func = (rxcan->CanId >> 16) & 0x7;
    dev_id = (rxcan->CanId >> 19) & 0x3F;
    layer = (rxcan->CanId >> 25) & 0x7;

    //动环信息默认存到第62簇共享内存里
    if (TOTAL_LAYER == layer && 62 == dev_id) {
        layer = MASTER_LAYER;
    }

    len = rxcan->DLC;
    reg_cnt = len / 2;
    bmser_dev_calcBankIdAndRackIdByDevId(dev_id,&bankId,&rackId);
    // 当接收到显控的信息时，DB数据按照总控层级处理，放入总控的DB中
    if(layer == BDU_LAYER)
    {
        bankId = 0;
        rackId = 0;
        //BDU的寄存器地址只占低12位
        start_addr = start_addr & 0xFFF;
    }
    if (func == E_CAN_WRITE_REPLY)
    {
        //多线程需要加互斥锁
        pthread_mutex_lock(&var->mutex);
        if (0 == set_cache(var->canObjId, bankId, rackId, start_addr, reg_cnt, rxcan->Data, rxcan->DLC))
        {
            publish_critical_binary_data(var->sn_str, var->canObjId, layer, bankId, rackId, start_addr, reg_cnt, rxcan->Data, rxcan->DLC, WRITE_RSP2);
        }
        else
        {
            dy_syslog(LOG_ERR, "E_CAN_WRITE_REPLY  --> error");
        }
        pthread_mutex_unlock(&var->mutex);
    }
    if (func == E_CAN_READ_REPLY)
    {
        //多线程加互斥锁
        pthread_mutex_lock(&var->mutex);
        if (0 != set_cache(var->canObjId, bankId, rackId, start_addr, reg_cnt,rxcan->Data, rxcan->DLC))
        {
            dy_syslog(LOG_DEBUG, "E_CAN_READ_REPLY  canid:0x%x bankId:0x%x rackId:0x%x start_addr:0x%x --> error",rxcan->CanId,bankId,rackId,start_addr);
        }
        pthread_mutex_unlock(&var->mutex);
    }
    return 0;
}

/**
 * @brief       CAN消息接收处理,支持消息流响应解析,DB读写响应解析
 * @param[in]   void *obj        can属性对象
 * @param[in]   CanMsg *rxcan    can接收数据
 * @param[in]   int canObjId     
 * @return      int
 * @retval      0:正常  !0:错误
 * @par         修改日志:
 * Date                Author     Description           \n
 * 2023-03-08           JHC        创建初始版本          \n
*/
static int can_rcv_frame(void *obj, CanMsg *rxcan, int canObjId)
{

    if (0 != canInf_recvMsg(canObjId, rxcan))
    {
        usleep(100);
        return -1;
    }
    //查询协议版本响应
    if(rxcan->CanId == PROTOCOL_VERSION_CHECK_RES)
    {
        bmser_can_get_canrbus_protocol_ver(rxcan);
    }
    uint8_t extfuncCode = GET_EXTFUNC_ID(rxcan->CanId);
    uint8_t protocolType = CANRBUS_PROTOCOL_TYPE_BMSER;
    //根据功能扩展位区分
    if(0 == extfuncCode)
    {
        xieneng_can_var_t *var = (xieneng_can_var_t *)obj;
        uint8_t funcCode = GET_FUNC_CODE(rxcan->CanId);
        
        if(funcCode == FUNC_CODE_MSG_FLOW_RSP)
        {
            // 消息流响应解析
            canRcv_msg_flow_rsp(var, rxcan);
        }
        else
        {
            #ifdef WITH_BMSER_PRODUCT_TEST
            canRcv_msg_product_test(var, rxcan);
            #endif
            // DB读写响应解析
            canRcv_msg_RWreply(var, rxcan);
        }
    }
    else
    {
        if(g_j1939_listen_enable)
        {
            // j1939协议处理
            protocolType = GET_PROTOCOL_TYPE(rxcan->CanId);
            if(CANRBUS_PROTOCOL_TYPE_J1939 == protocolType)
            {
                J1939RecvMsg_ReceiveCallback(canObjId, rxcan);
            }
        }
        return 0;
    }
}

static int period_service_poll(xieneng_can_var_t *var)
{
    TIMER_CONFIRM(var->period_poll_timer);
    long long now = bmser_get_time_stamp_ms();
    int port_index = 0;
    if (var->upgradeflag == 1)
    {
        return -1;
    }
    for (port_index = 0; port_index < CAN_OBJ_ID_MAX; port_index++)
    {
        if (var->period_tables[port_index].cnt > 0 && var->period_tables[port_index].nodes != NULL)
        {
            int i = 0;
            period_node_t *node = NULL;

            for (i = 0; i < var->period_tables[port_index].cnt; i++)
            {
                node = &var->period_tables[port_index].nodes[i];
                if (node->used == 0)
                    continue;

                if (now > node->last_send + node->period || now < node->last_send)
                {
                    send_data_to_can_bus(port_index, node->term_addr, READ, node->start_addr, node->reg_cnt, NULL, 0);
                    node->last_send = now;
                }
            }
        }
    }

    return 0;
}

static int invalidtion_check_poll(xieneng_can_var_t *var)
{
    TIMER_CONFIRM(var->cache_invalidtion_timer);
    long long now = bmser_get_time_stamp_ms();
    int i = 0, port_index = 0;
    EMS_DEV_REG_DATA_S regData = {0};
    for (i = 0; i < MAX_DEV_NUM; i++)
    {
        uint16_t bankId = 0, rackId = 0;
        long long timeInterval_canrbus = now - var->can_bus_tables[i].last_rcv;
        //必须是检查使用中,而且没有超时过的
        if (var->can_bus_tables[i].in_use == 1 && !var->can_bus_tables[i].is_timeout && var->can_bus_tables[i].last_rcv > 0)
        {
            // 检查是否超时
            if (timeInterval_canrbus >= CACHE_INVALIDTION_TIME)
            {
                bmser_dev_calcBankIdAndRackIdByDevId(i,&bankId,&rackId);
                pthread_mutex_lock(&var->mutex); //多线程加互斥锁
                var->can_bus_tables[i].is_timeout = 1;
                pthread_mutex_unlock(&var->mutex);
                //当对应簇通讯超时后, 清除该簇所有的DB有效位
                
                regData.bankId = bankId;
                regData.rackId = rackId;
                regData.startAddr = 0;
                regData.regCount = 0xFFFF;
                BmserProtocolExt_SetDbValidFlag(&regData, 0);
                
            }
        }
        // j1939无总控，devId从1开始
        int devId = i + 1;
        long long timeInterval_j1939 = now - J1939Get_recvTime(devId);
        // J1939 当对应簇通讯超时后, 清除该簇所有的DB有效位 
        if(timeInterval_j1939 >= CACHE_INVALIDTION_TIME)
        {
            uint16_t bankId, rackId = 0;
            bmser_dev_calcBankIdAndRackIdByDevId(devId,&bankId,&rackId);
            regData.bankId = bankId;
            regData.rackId = rackId;
            regData.startAddr = 0;
            regData.regCount = 0xFFFF;
            BmserProtocolExt_SetDbValidFlag(&regData, 0);
        }
    }
    return 0;
}

static void get_lastUpgradeTime(uint64_t *time)
{
    *time = g_receive_upgradePkgTime;
}

bool judgeSysIsUpdate(void)
{
    uint64_t updateTime = 0,now = 0;
    // 获取最后一次接收到帧标识为D0的时间
    get_lastUpgradeTime(&updateTime);
    now = bmser_get_time_stamp_ms();
    // 距上一次接收到升级消息超过10S，视为升级结束
    return (now - updateTime) <= UPDATE_TIMEOUT;
}

static int xieneng_can_j1939Send_loop()
{
    TIMER_CONFIRM(g_j1939_send_timer);
    J1939SendMsg_Step_Runnable();
    return 0;
}

static int xieneng_can_j1939Recv_loop()
{
    TIMER_CONFIRM(g_j1939_recv_timer);
    J1939RecvMsg_TpSession_Runnable();
    return 0;
}

static int xieneng_can_j1939Syn_loop()
{
    TIMER_CONFIRM(g_j1939_syn_data_timer);
    SynSampleDataMaster_Runnable();
    return 0;
}

static void xieneng_can_loop(xieneng_can_var_t *var)
{
    int ret = -1, maxfd = 0;
    fd_set rset;
    struct timeval timeout;
    while (1) 
    {
        bool isUpdate = judgeSysIsUpdate();
        SELECT_INIT();
        if(!isUpdate)
        {
            SELECT_ADD_FD(var->period_poll_timer);
        }
        SELECT_ADD_FD(var->cache_invalidtion_timer);
        if(g_j1939_req_enable && !isUpdate)
        {
            SELECT_ADD_FD(g_j1939_send_timer);
        }
        if(g_j1939_listen_enable)
        {
            SELECT_ADD_FD(g_j1939_recv_timer);
            if(!isUpdate)
            {
                SELECT_ADD_FD(g_j1939_syn_data_timer);
            }
        }
        timeout.tv_usec = 0;
        timeout.tv_sec = 5;

        ret = select(maxfd + 1, &rset, 0, 0, &timeout);
        if (ret < 0)
        {
            dy_syslog(LOG_INFO, "errno %d\n", errno);

            if (errno == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret > 0)
        {
            //升级时关闭xieneng_can请求业务
            if (var->period_poll_timer > 0 && FD_ISSET(var->period_poll_timer, &rset) && !isUpdate)
            {
                FD_CLR(var->period_poll_timer, &rset);
                period_service_poll(var);
            }
            if (var->cache_invalidtion_timer > 0 && FD_ISSET(var->cache_invalidtion_timer, &rset))
            {
                FD_CLR(var->cache_invalidtion_timer, &rset);
                invalidtion_check_poll(var);
            }
            if(g_j1939_req_enable && !isUpdate)
            {
                if (g_j1939_send_timer > 0 && FD_ISSET(g_j1939_send_timer, &rset))
                {
                    FD_CLR(g_j1939_send_timer, &rset);
                    xieneng_can_j1939Send_loop();
                }
            }
            if(g_j1939_listen_enable)
            {
                if (g_j1939_recv_timer > 0 && FD_ISSET(g_j1939_recv_timer, &rset))
                {
                    FD_CLR(g_j1939_recv_timer, &rset);
                    xieneng_can_j1939Recv_loop();
                }
                if (g_j1939_syn_data_timer > 0 && FD_ISSET(g_j1939_syn_data_timer, &rset) && !isUpdate)
                {
                    FD_CLR(g_j1939_syn_data_timer, &rset);
                    xieneng_can_j1939Syn_loop();
                }
            }
        }
    }
}


void xieneng_can_send_get_rtc_request(xieneng_can_var_t *var)
{
    //程序启动后，先主动发送读rtc时钟请求，为了防止日期发生跳变，发送两次读请求，分别比较两次数据是否一致
    int i = 0, dev_id = 0;
    unsigned char layer = TOTAL_LAYER;
    unsigned short term_addr = ((unsigned int)layer) << 8 | dev_id;
    unsigned short year_addr = BMS_TOTAL_DATE_CFG_DB_ADDR; //总控年寄存器地址
    unsigned short reg_cnt = BMS_TOTAL_DATE_CFG_DB_COUNT; //年月日时分秒
    for (i = 0; i < 2; i++) {
        usleep(1000*50);
        dy_syslog(LOG_DEBUG, "send get rtc can frame request %d.", i + 1);
        send_data_to_can_bus(var->canObjId, term_addr, READ, year_addr, reg_cnt, NULL, 0);
    }
    
    return;
}

void *thread_canRecvProcess(void *arg)
{
    int canObjId = 0;
    if (bmser_can_cfg_file_enable()) {
        if (arg && arg + strlen(CAN_BUS_INTERFACE_NAME)) {
            canObjId = atoi(arg + strlen(CAN_BUS_INTERFACE_NAME));
            dy_syslog(LOG_DEBUG, "canObjId = %d.", canObjId);
        }
    }
    dy_syslog(LOG_DEBUG, "begin recv thread_canRecvProcess %d", canObjId);

    while (true)
    {
        CanMsg rxMsg = {0};
        can_rcv_frame(&g_xienengCanInfo, &rxMsg, canObjId);
    }
    return (void *)0;
}

/**
 * @brief       xieneng_can 初始化
 * @param[in]   xieneng_can_var_t *var
 * @return      int
 * @retval      0:正常  !0:错误
 * @par         修改日志:
 * Date                Author     Description           \n
 * 2023-03-08           JHC        创建初始版本          \n
 * 2023-10-12           QZY        配置的can总线数量为0时，不再创建recv线程   \n
*/
int xieneng_can_init(xieneng_can_var_t *var)
{
    int i = 0, ret = 0;

    bmser_dev_get_board_sn(var->sn_str);

    dy_syslog(LOG_INFO, "board SN:%s", var->sn_str);
    share_dir_make();

    g_j1939_req_enable = bmser_general_cfg_j1939_req_enable();
    g_j1939_listen_enable = bmser_general_cfg_j1939_listen_enable();

    var->period_poll_timer = bmser_timerfd_create();
    if (var->period_poll_timer > 0)
    {
        bmser_timerfd_set(var->period_poll_timer, 1, 10);
    }
    var->cache_invalidtion_timer = bmser_timerfd_create();
    if (var->cache_invalidtion_timer > 0)
    {
        bmser_timerfd_set(var->cache_invalidtion_timer, 1, CACHE_INVALIDTION_TIME);
    }

    if(g_j1939_req_enable)
    {
        g_j1939_send_timer = bmser_timerfd_create();
        if (g_j1939_send_timer > 0)
        {
            bmser_timerfd_set(g_j1939_send_timer, 1, 10);
        }
    }
    if(g_j1939_listen_enable)
    {
        // 同步信息交互作为监听功能的一部分
        g_j1939_syn_data_timer = bmser_timerfd_create();
        if (g_j1939_syn_data_timer > 0)
        {
            bmser_timerfd_set(g_j1939_syn_data_timer, 1, 10);
        }
        g_j1939_recv_timer = bmser_timerfd_create();
        if (g_j1939_recv_timer > 0)
        {
            bmser_timerfd_set(g_j1939_recv_timer, 1, 1);
        }
    }

    ret = xieneng_can_mqtt_client_init(var->sn_str);
    if (0 != ret) {
        dy_syslog(LOG_ERR, "xieneng_can mqtt init fail = %d.", ret);
        return ret;
    }
    //TODO:暂时固定为1,后续可以做成配置文件
    var->canObjId = CAN_OBJ_ID_1;    
    dy_syslog(LOG_DEBUG, "begint to create recv pthread.");
    pthread_t ntid;
    int err;
    if (bmser_can_cfg_file_enable()) {
        BMSER_CAN_BUS_CFG_TABLE_S *cfg_table = bmser_can_get_cfg_tables_mgr();
        for (i = 0; i < cfg_table->num; i++) {
            if (!cfg_table->can_cfg[i].disable) {
                err = pthread_create(&ntid, NULL,(void *)thread_canRecvProcess, cfg_table->can_cfg[i].name);
                if (err != 0) {
                    dy_syslog(LOG_ERR,"pthread create err %d",err);
                }
                //请求下位机canrbus版本
                bmser_can_canrbus_protocol_ver_req(i,cfg_table->rack_num);
            }
        }
    } else {
        dy_syslog(LOG_ERR,"can num is 0, pthread not create!\n");
        return -1;
    }
    xieneng_can_send_get_rtc_request(var);
    return 0;
}

xieneng_can_var_t *get_xieneng_can_var()
{
    return &g_xienengCanInfo;
}

int main(int argc, char *argv[])
{
    CAN_INF_CFG_STRU canCfg;
    int32_t ret = 0;
    BMSER_EMS_DB_CONTROL_INIT_S initPara = {0};
    initPara.mode = POLL_MODE;
    memset(&g_xienengCanInfo, 0, sizeof(g_xienengCanInfo));

    pthread_mutex_init(&g_xienengCanInfo.mutex, NULL);
    ret = BmserProtocolExt_DBInit(&initPara);
    if (0 != ret) {
        return ret;
    }

    ret = bmser_can_init();
    if (0 != ret) {
        dy_syslog(LOG_ERR, "bmser_can_init fail, ret = %d\n", ret);
        return ret;
    }

    ret = xieneng_can_init(&g_xienengCanInfo);
    if (0 != ret)
    {
        dy_syslog(LOG_ERR, "xieneng_can_init fail, ret = %d\n", ret);
        return ret;
    }
    xieneng_can_loop(&g_xienengCanInfo);

    return 0;
}
