#include "tax.h"
#include "../../User/includes.h"
#include "../gateway_collect/gateway_collect.h"
#include "../network_mgr/net_ctrl.h"
#include "../dev_mgr/taxctrl/tax_ctrl.h"
#include "../network_mgr/net_ctrl.h"
#include "../network/downlink.h"
#include "../network/uplink.h"
#include "../network/nettimer.h"
#include "../network_mgr/sx1268/lora.h"
#include "../encode/encodeOpt.h"
#include "../toolkit/CH455G.h"
#include "../storage/AT24C128Opt.h"
//volatile uint32_t TickCounter = 0;
volatile uint32_t TickSecond = 0;

tNodeConf_t nodeConf;

rcv_data_temp_t rcv_data_temp;

//tTaxConf_t taxConf;

tCounterTimeOut_t timeCmdGap;
tCounterTimeOut_t timeCmdOut;
tCounterTimeOut_t timePortGap;
tCounterTimeOut_t timePerSecond;
tCounterTimeOut_t timeTSMWCmdGap;
tCounterTimeOut_t timeCmdJump;
#if 1
/*-----------------------------------------------------------------------
 * 查找 相同的采集器索引 以及报税口索引
 *  -1: 没有相同的
 * ----------------------------------------------------------------------*/
int8_t check_repeat_coll_prot(uint8_t num,uint8_t dcoll,uint8_t dport, uint8_t bcoll,uint8_t bport,uint8_t bgunid)
{
    uint8_t i =0;
    enMsgDa *msg=NULL;
    for(i=0;i<num;i++){
        msg = &(nodeConf.taxconf[dcoll].port[dport].enMsg[i]);
        if(msg->da.bcollid == bcoll && msg->da.bportid==bport){
            msg->da.gunstatus |= (0x01<<(bgunid-1));
            return i;
        }

    }
    return -1;
}
/*------------------------------------------------------------------------
 *  根据编码器的配置更新读取报税口的时间
 * -----------------------------------------------------------------------*/
void update_nodeConfig_encoder(void)
{
    uint8_t i;//,j,m,temp=0;
    uint8_t portid,collid = 0,bcollid,bportid;
    uint8_t num = 0;
    int8_t ret = 0;
    table_msg *msg = NULL;
    enMsgDa *emsg=NULL;
  //  if(g_encodeOpt.benable !=1) return; // 不使用编码器路由表
    if(g_encodeOpt.encodenum == 0) return;
    if(g_encodeOpt.encodenum>64) g_encodeOpt.encodenum = 64;
    for(i=0;i<g_encodeOpt.encodenum;i++){
        msg = &(g_encodeOpt.tableDa[i]);
        collid = msg->da.dcollId;
        portid = msg->da.dportId-1;
        bcollid = msg->da.bcollId;
        bportid = msg->da.bportId;
        nodeConf.taxconf[collid].port[portid].enNum.num.tabNum++;
        num = nodeConf.taxconf[collid].port[portid].enNum.num.tabNum - 1;
        nodeConf.taxconf[collid].port[portid].enPos[num] = i;
        num = nodeConf.taxconf[collid].port[portid].enNum.num.pEnNum;
        emsg = &(nodeConf.taxconf[collid].port[portid].enMsg[num]);
        if(num ==0){
            emsg->da.bcollid = msg->da.bcollId;
            emsg->da.bportid = msg->da.bportId;
            emsg->da.gunstatus |= (0x01<<(msg->da.bgunId-1));
            nodeConf.taxconf[collid].port[portid].enNum.num.pEnNum++;
        }
        else {
            ret = check_repeat_coll_prot(num,collid,portid,bcollid,bportid,msg->da.bgunId);
            if(ret == -1) {
                emsg->da.bcollid = msg->da.bcollId;
                emsg->da.bportid = msg->da.bportId;
                emsg->da.gunstatus |= (0x01<<(msg->da.bgunId-1));
                nodeConf.taxconf[collid].port[portid].enNum.num.pEnNum++;
            }
        }
    }
}
int gateway_collect_init(void)
{
    int ret = -1;
    int i,j,m;

    memset(&nodeConf,0,sizeof(nodeConf));

    if(downlink_config.collect_num > COLLECT_MAX_NUM)
    {
        return ret;
    }
    for(i = 0; i < downlink_config.collect_num; i++)
    {
        if(downlink_config.collect_conf[i].tax_num > TAX_MAX_NUM)
        {
            return ret;
        }

        for(j = 0; j < downlink_config.collect_conf[i].tax_num; j++)
        {
            if(downlink_config.collect_conf[i].tax_conf[j].gun_num > GUN_MAX_NUM)
            {
                return ret;
            }
            nodeConf.taxconf[i].port[j].enNum.data = 0;
            nodeConf.taxconf[i].port[j].enIndex = 0;
            nodeConf.taxconf[i].port[j].taxType = 0;
            for(m = 0; m < downlink_config.collect_conf[i].tax_conf[j].gun_num; m++)
            {
                nodeConf.taxconf[i].port[j].gun[m].gLpState = TAX_GUN_LP_STATE_IDLE;
            }
        }
    }

    update_nodeConfig_encoder();
    timeCmdGap.counter 		= TickCounter;
    timeCmdGap.timeOut		=	TAX_TIME_TAX_CMD_GAP;
    timeCmdOut.counter		=	TickCounter;
    timeCmdOut.timeOut		=	TAX_TIME_TAX_CMD_OUT;
    timePortGap.counter		=	TickCounter;
    timePortGap.timeOut		=	TAX_TIME_TAX_PORT_GAP;
    timePerSecond.counter	=	TickCounter;
    timePerSecond.timeOut	=	TIME_OUT_PER_SECOND;

    timeTSMWCmdGap.counter = TickCounter;
    timeTSMWCmdGap.timeOut = TAX_TIME_TSMW_CMD_GAP;

    timeCmdJump.counter 		= TickCounter;
    timeCmdJump.timeOut		=	TAX_TIME_TAX_JUMP_GAP;

   // timeout_setValue(&g_timeOut,2000);
    timeout_setValue(&g_taxSendTime,2000);
    timeout_setValue(&g_taxDataTime,500);

    ret = 0;
    return ret;
}

void encoder_printf(void)
{
    uint8_t i=0,j=0,k=0;
    uint8_t num = 0;
    enMsgDa *msg = NULL;
    if( downlink_config.collect_num>16 || downlink_config.collect_num == 0) return;
    for(i=0;i<downlink_config.collect_num;i++){
        printf("collid = %d\r\n",i);
        for(j=0;j<2;j++){
            num = nodeConf.taxconf[i].port[j].enNum.num.pEnNum;
            printf("  port = %d,num = %d\r\n",j,num);
            for(k=0;k<num;k++){
                msg = &(nodeConf.taxconf[i].port[j].enMsg[k]);
                printf("    msg: bcoll = %d, bport=%d, gunstatus = %02x\r\n",msg->da.bcollid,msg->da.bportid,msg->da.gunstatus);
            }
        }
    }
}

int tax_send_cmd(uint8_t cmd, uint8_t node, uint8_t port, uint8_t gun)
{
    uint8_t para[16] = {0};
    uint8_t send_buf[64],send_len,taxType = 0;
    int uart=0,gun_num=0,tax = 0;
    uint32_t seq_num = 0,id = 0;

    seq_num = nodeConf.taxconf[node].port[port].gun[gun].seq_no;
 //   uart = nodeConf.taxconf[node].port[port].uart;
    tax = downlink_config.collect_conf[node].tax_conf[port].tax_id;
    gun_num = downlink_config.collect_conf[node].tax_conf[port].gunid[gun];
    id = downlink_config.collect_conf[node].collect_no;//nodeConf.taxconf[node].device_id;
    // taxType = downlink_config.collect_conf[node].tax_type;
    taxType = nodeConf.taxconf[node].port[port].taxType;
    g_logCfigDa.curportno = tax;
    g_logCfigDa.curgunno = gun_num;
    //	printf("id = %d\n",id);
    //printf("cmd 0x83:")
    switch(cmd)
    {
    case 0x83:
        //printf("uart 83\n");
        para[0] = 0;
        send_len = tax_cmd_set(0x83,para,1,send_buf);
        gateway_collect_cmd_set(send_buf,send_len,node,tax,uart,gun_num,taxType,seq_num,id);
        break;
    case 0x86:
        //printf("uart 86\n");
        para[0] = gun_num-1;		/* gun_num */
        para[1] = 0x01;
        send_len = tax_cmd_set(0x86,para,2,send_buf);
        //gateway_collect_cmd_set(send_buf,send_len,uart,PLAINTEXT,seq_num,id,gun);
        //printf("\r\nsend 0x86 node=%d, tax=%d,gun=%d\r\n ",node,tax,gun);
        gateway_collect_cmd_set(send_buf,send_len,node,tax,uart,gun_num,taxType,seq_num,id);
        break;
    case 0x89:
        //printf("uart 89\n");
        para[0] = gun_num-1;	    //gun_num
        para[1] = 0x00;
        para[2] = 0x01;
        send_len = tax_cmd_set(0x89,para,3,send_buf);
        //printf("\r\nsend 0x89 node=%d, tax=%d,gun=%d\r\n ",node,tax,gun);
       // gateway_collect_cmd_set(send_buf,send_len,uart,PLAINTEXT,seq_num,id,gun);
        gateway_collect_cmd_set(send_buf,send_len,node,tax,uart,gun_num,taxType,seq_num,id);
        break;
    case 0x11: // 读取当次加油 相当于86指令
        para[0] = cmd;
        para[1] = gun_num-1;		/* gun_num */
        para[2] = 0x01;
        send_len = tax_cmd_set_0x8C(0x8C,para,3,send_buf);
        gateway_collect_cmd_set(send_buf,send_len,node,tax,uart,gun_num,taxType,seq_num,id);
        break;
//        break;
    case 0x14: // 读取总累计 相当于89指令
        para[0] = cmd;
        para[1] = gun_num-1;	    //gun_num
        para[2] = 0x00;
        para[3] = 0x01;
        send_len = tax_cmd_set_0x8C(0x8C,para,4,send_buf);
        gateway_collect_cmd_set(send_buf,send_len,node,tax,uart,gun_num,taxType,seq_num,id);
        break;
    case 0x70: // 读取密文的83指令
        para[00] = 0x00;
        send_len = tax_cmd_set(0x70,para,1,send_buf);
        gateway_collect_cmd_set(send_buf,send_len,node,tax,uart,gun_num,taxType,seq_num,id);
        break;
    default:
        break;
    }
    return 0;
}

//设置拓盛密文加油枪全部可读
int tsmw_gun_set_read(void)
{
    int ret = 0;
    int i,j,m;
    for(i = 0; i < downlink_config.collect_num; i++)
    {
        for(j = 0; j < downlink_config.collect_conf[i].tax_num; j++)
        {
            if((nodeConf.taxconf[i].port[j].taxType&CIPHERTEXT)==CIPHERTEXT && downlink_config.collect_conf[i].tax_conf[j].factory == 2)
            {
                for(m = 0; m < downlink_config.collect_conf[i].tax_conf[j].gun_num; m++)
                {
                    nodeConf.taxconf[i].port[j].gun[m].tsmw_flag = 0;
                }
            }
        }
    }
    return ret;
}
/*-------------------------------------------------------------
 *  判断拓盛密文 的是否都读取一遍
 *  返回值 ：
 *  0: 没有
 *  1：都读取一遍了
 * -------------------------------------------------------------*/
#if(0)
int tsms_gun_read_finish(void)
{
//    int ret = 0;
    int i,j,m;
    for(i = 0; i < downlink_config.collect_num; i++)
    {
        for(j = 0; j < downlink_config.collect_conf[i].tax_num; j++)
        {
            if(downlink_config.collect_conf[i].tax_type==CIPHERTEXT && downlink_config.collect_conf[i].tax_conf[j].factory == 2)
            {
                for(m = 0; m < downlink_config.collect_conf[i].tax_conf[j].gun_num; j++)
                {
                   if(nodeConf.taxconf[i].port[j].gun[m].tsmw_flag == 0) return 0;
                }
            }
        }
    }
    return 1;
}
#endif
/*-------------------------------------------------------------------------
 * 网络透传数据
 * ------------------------------------------------------------------------*/
void net_to_read_cmd(void)
{
    uint8_t rcvbuff[64] = {0},type1;
    uint16_t type2,ret = 0;

    if(g_runData.bUpdate != 0) return;

    if(g_runData.bNetCmd !=1) return; // 网络读取数据

    if((timeout_isOut(&g_taxSendTime)==0)) return;
    //if(timeout_isOut(&g_netreadxspTimeout) == 0 ) return;
    ret = read_comm_queue(&type1, &type2,rcvbuff);
    if(ret == 0){
        printf("comm queue size = 0\r\n");
        g_runData.bNetCmd = 0;
        return;
    }
    else if(ret >= 1){
        if(type1 == 0x01 && type2==0x1052){ // 透传指令
            printf("下发网络指令 01-1052\n");
            //data_dump("send000 0x01-0x1052:",rcvbuff,ret);
            gateway_collect_cmd_0x01_0x1052(rcvbuff,ret);
            timeout_start(&g_taxSendTime);
        }
        else if((type1 == 0x01) &&(type2 == 0x1053)){
            printf("下发网络指令 01-1053\n");
            gateway_collect_cmd_0x01_0x1053(rcvbuff,ret);
            timeout_start(&g_taxSendTime);
        }
    }

    return;
}
uint8_t tempBuf[128] = {0};
int tsmw_begin_read = 0;
/*向采集器发送读取采集器数据的指令*/
void tax_process(void)
{
//    int result = 0;
    int nodeCur = 0;
    int portCur = 0;
    int gunCur	= 0;
    int state	= 0;
    int taxType = 0;
    uint8_t ret = 0,readport = 0;//rcvCmd=0,
    uint32_t sn,seqno = 0;
    uint8_t factory = 0,encryption = 0;
    static int taskTime = 0;
//    static int lastnodeCur = -1;
//    static int readCount = 0;
    static uint8_t breadPortTax = 0;
    if(g_runData.bUpdate != 0) return;
		
    if(timeout_isOut(&g_timeOut)==0) return;
    timeout_stop(&g_timeOut);

    if(timeout_isOut(&g_taxDataTime)==0) return;



    g_runData.ballowRead58 = 1;

    if(timeout_isOut(&g_taxSendTime) !=1) return;

    nodeCur = nodeConf.nodeIndex;
    portCur = nodeConf.taxconf[nodeCur].portIndex;
    gunCur = nodeConf.taxconf[nodeCur].port[portCur].gunIndex;
    state = nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState;
    //infotype = downlink_config.collect_conf[nodeCur].tax_type; //明文/密文
    taxType = nodeConf.taxconf[nodeCur].port[portCur].taxType;

    factory = downlink_config.collect_conf[nodeCur].tax_conf[portCur].factory;// gateway_read.collect_read[nodeCur].tax_read[portCur].factory;  /* 1: 英泰赛福 2: 拓盛 */
    encryption = downlink_config.collect_conf[nodeCur].tax_conf[portCur].encryption; // 拓盛密文是否实时读取 1：实时读取
    sn = downlink_config.collect_conf[nodeCur].collect_no;
    seqno = nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].seq_no;
    if(portCur == 0x00) readport = 0x01;
    else if(portCur == 0x01) readport = 0x02;
    //	printf("gun state %d\n",state);

   // printf("coll check bit, node = %d, port = %d,gun = %d, value = %x, value1 = %x\n",nodeCur,portCur,gunCur,g_checkGun[nodeCur].gunSta.status[portCur],g_checkGun[nodeCur].gunSta.status1);
    if(g_runData.collrunMsg[nodeCur].checkNum>=5){ //采集器已经下发了5次数据，都没有收到返回
        downlink_config.collect_conf[nodeCur].collect_status = COLL_STATUS_OFFLINE; // 当前采集器已经离线
        downlink_config.collect_conf[nodeCur].tax_conf[0].status = 0;// 报税口1离线
        downlink_config.collect_conf[nodeCur].tax_conf[1].status = 0; //报税口2离线
     }

    if((downlink_config.collect_conf[nodeCur].collect_status == COLL_STATUS_OFFLINE)){ //采集器离线状态

        g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000; // 采集器离线，要清零
        //if(TickCounter - timeCmdGap.counter > timeCmdGap.timeOut) // 1S读取一次指令
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x56;
            g_logCfigDa.curportno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].tax_id;
            g_logCfigDa.curgunno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].gunid[gunCur];
            gateway_collect_set_cmd0x56(0x56,nodeCur,0x03,sn);
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
            nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
            nodeConf.taxconf[nodeCur].port[portCur].gunIndex = 0;
            nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
            set_led_update_status(g_ledStatus.collNum);
           // set_gun_status(nodeCur,portCur,gunCur);
            printf("\r\n 采集器离线状态 coll = %d\n ",nodeCur);
            timeout_start(&g_taxSendTime);
            ret = get_gun_status();
            if(ret==0){
                timeout_setValue(&g_timeOut,g_firmwareMsg.gatewayMsg.configmsg.time_interval*1000);
                init_gun_status();
                if(g_runData.bRead0x58)g_runData.ballowRead58 = 0;
                if(g_timeOut.timeout != 0)timeout_start(&g_timeOut);
                printf("\r\ncheck all collect finsh_%d_offline\r\n",nodeCur);

            }
        }
        return;
    }

    if(g_encoderDa.bhaveEncoder == ENCONDER_EN){ // 有编码器
         if(timeout_isOut(&g_taxSendTime) && (breadPortTax ==0) )  { //超时
             if(nodeConf.taxconf[nodeCur].port[portCur].gunIndex==0) { // 查询过加油机信息的去读取
                encoder_read_data(nodeCur,portCur,gunCur);
                breadPortTax = 1;
                return;
            }
         }
    }
    switch(state){
    case TAX_GUN_LP_STATE_IDLE:
        if(timeout_isOut(&g_taxSendTime) !=1) break;
        if(taskTime==0){
            timePortGap.counter = TickCounter - timePortGap.timeOut;
            timeCmdJump.counter = TickCounter - timeCmdJump.timeOut;
            timeTSMWCmdGap.counter = TickCounter - timeTSMWCmdGap.timeOut;
        }
        if((TickCounter - timeTSMWCmdGap.counter >= timeTSMWCmdGap.timeOut) || (g_runData.bReadMingWenData==5)) //判断是否到50分钟
        {
            tsmw_gun_set_read();
            timeTSMWCmdGap.counter = TickCounter;
//            lastnodeCur = -1;
            g_runData.bReadMingWenData = 0;
        }
        /*if((downlink_config.collect_conf[nodeCur].tax_conf[portCur].status==0) \
             && downlink_config.collect_conf[nodeCur].tax_conf[portCur].alrd_sn==0) { // 报税口的状态没有连接
            printf("tax com status falile\r\n");
            g_checkGun[nodeCur].gunSta.status[portCur] = 0x00;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_83;//TAX_GUN_LP_STATE_CH;
            break;
        }*/
        if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].alrd_sn==1 \
           || downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num != 0)//if(gateway_read.collect_read[nodeCur].tax_read[portCur].alrd_sn)//已经查询过加油机的信息即已经读取过0x83指令/*nodeConf.taxconf[nodeCur].port[portCur].alrd_sn*/
        {
            if((taxType&0x0F) == 0x00){ // 报税口的类型未知，则需要读取56指令
                nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_56;//TAX_GUN_LP_STATE_CH;
            }
            else if(((taxType&CIPHERTEXT) == CIPHERTEXT) && (factory == 2) &&(encryption != 1)) //拓盛密文50分钟读一次
            {
                //printf("this is tsmw\n");
                if(nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].tsmw_flag == 0 )//该加油枪没有读过数据
                {
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].tsmw_flag = 1;
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_89;
                }
                else//已经读过数据直接跳到下一个枪
                {
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_56;//TAX_GUN_LP_STATE_CH;
                }
            }
            else
            {
          //      if(nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState != TAX_GUN_LP_STATE_83)
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_89;
            }

            break;
        }
        else //没有查询过加油机的信息，先去执行0x83指令去查询加油机的信息
        {
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;
        }
        break;
    case TAX_GUN_LP_STATE_83:
        //定时轮询83指令
        //如果超时或出错，则，清空当前枪状态，且枪索引指向当前端口的下一个枪
        //if(TickCounter - timeCmdGap.counter > timeCmdGap.timeOut) // 1S读取一次指令
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x83;
            printf("send : sn = %010d, coll=%d, port=%d, gun=%d, cmd = 0x%02x, seqNo = %010d, taxType = 0x%02x\n",sn,nodeCur,portCur,gunCur,0x83,seqno,taxType);

            if((taxType & PLAINTEXT) == PLAINTEXT)
            {
                tax_send_cmd(tax_send_cmd_83,nodeCur,portCur,gunCur);
            }
            else if((taxType & CIPHERTEXT) == CIPHERTEXT)
            {
                if((taxType & 0x80) == 0x80)
                    tax_send_cmd(0x70,nodeCur,portCur,1);
                else
                    ytsf_send_cmd(0xA2,0x00,nodeCur,portCur,gunCur);
            }
            g_runData.collrunMsg[nodeCur].checkNum++;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;

            timePortGap.counter= TickCounter;
            timeCmdGap.counter = TickCounter;
            timeCmdOut.counter = TickCounter;
            timeout_start(&g_taxSendTime);

        }
        break;

    case TAX_GUN_LP_STATE_89:
        //定时轮询89指令
        //如果超时或出错，则，清空当前枪状态，且枪索引指向当前端口的下一个枪
        //if(TickCounter - timeCmdGap.counter > timeCmdGap.timeOut) //1S读取一次指令
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x89;
            printf("send : sn = %010d, coll=%d, port=%d, gun=%d, cmd = 0x89, seqNo = %010d, taxType = 0x%02x\n",sn,nodeCur,portCur,gunCur,seqno,taxType);
            memset(&rcv_data_temp,0,sizeof(rcv_data_temp_t));
            if((taxType&PLAINTEXT) == PLAINTEXT)
            {
                tax_send_cmd(tax_send_cmd_89,nodeCur,portCur,gunCur);
            }
            else if((taxType&CIPHERTEXT) == CIPHERTEXT)
            {
                if((taxType&0x80) == 0x80)
                    tax_send_cmd(0x14,nodeCur,portCur,gunCur);
                else
                    ytsf_send_cmd(0xA1,0x14,nodeCur,portCur,gunCur);
            }

            g_runData.collrunMsg[nodeCur].checkNum++;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_86;
            timePortGap.counter= TickCounter;
            timeCmdGap.counter = TickCounter;
            timeCmdOut.counter = TickCounter;
            timeout_start(&g_taxSendTime);

        }

        break;

    case TAX_GUN_LP_STATE_86:
        //定时轮询86指令
        //如果超时或出错，则，清空当前枪状态，且枪索引指向当前端口的下一个枪
        //if(TickCounter - timeCmdGap.counter > timeCmdGap.timeOut)
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x86;
            printf("send : sn = %010d, coll=%d, port=%d, gun=%d, cmd = 0x86, seqNo = %010d, taxType = 0x%02x\n",sn,nodeCur,portCur,gunCur,seqno,taxType);

            if((taxType&PLAINTEXT) == PLAINTEXT)
            {
                tax_send_cmd(tax_send_cmd_86,nodeCur,portCur,gunCur);
            }
            else if((taxType&CIPHERTEXT) == CIPHERTEXT)
            {
                if((taxType&0x80) ==0x80)
                    tax_send_cmd(0x11,nodeCur,portCur,gunCur);
                else
                    ytsf_send_cmd(0xA1,0x11,nodeCur,portCur,gunCur);
            }

            g_runData.collrunMsg[nodeCur].checkNum++;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].seq_no++;
            timeout_start(&g_taxSendTime);

        }

        break;
    case TAX_GUN_LP_STATE_CH:
        if(timeout_isOut(&g_taxSendTime) !=1) break;
        if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num==0) // 存在报税口的枪的个数为0，83没有读取，但这个报税口在线，有数据的情况
            g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000;
        else set_gun_status(nodeCur,portCur,gunCur);
        if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].status==0) { // 当前的报税口的状态没为离线状态
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
            nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
            nodeConf.taxconf[nodeCur].port[portCur].gunIndex = 0;
            g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000;
            nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
            breadPortTax = 0;
        }
        else{
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
            if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num==0) nodeConf.taxconf[nodeCur].port[portCur].gunIndex = 0;
            else nodeConf.taxconf[nodeCur].port[portCur].gunIndex = (gunCur+1)%downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num;
            if(nodeConf.taxconf[nodeCur].port[portCur].gunIndex == 0) //一个报税口的枪轮询完了
            {
                nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
                nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
                breadPortTax = 0;
            }

        }

        if(g_runData.bInstallFinish == 0xA5){ // 安装完成
            if((nodeConf.nodeIndex == 0) && (nodeConf.taxconf[nodeCur].portIndex == 0) \
                 && (nodeConf.taxconf[nodeCur].port[portCur].gunIndex == 0)){
                init_gun_status();
                g_runData.bInstallFinish = 0;
                breadPortTax = 0;
            }
        }
       // nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
        timePortGap.counter= TickCounter;
        timeCmdGap.counter = TickCounter;
        timeCmdOut.counter = TickCounter;
        ret = get_gun_status();
        if(ret==0){
            timeout_setValue(&g_timeOut,g_firmwareMsg.gatewayMsg.configmsg.time_interval*1000);
            init_gun_status();
            if(g_runData.bRead0x58)g_runData.ballowRead58 = 0;
            if(g_timeOut.timeout != 0)timeout_start(&g_timeOut);
            printf("\r\ncheck all collect finsh\r\n");
					  
        }
        break;
     case TAX_GUN_LP_STATE_56:
        //if(TickCounter - timeCmdGap.counter > timeCmdGap.timeOut){// 发送心跳指令
        if(timeout_isOut(&g_taxSendTime)) {
            printf("cmd 0x56: collIndex = %d, tick = %d\r\n",nodeCur,TickCounter);
            g_curSendCmd = 0x56;
            g_logCfigDa.curportno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].tax_id;
            g_logCfigDa.curgunno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].gunid[gunCur];
            gateway_collect_set_cmd0x56(0x56,nodeCur,readport,sn);
            timeCmdGap.counter = TickCounter;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;

            timeout_start(&g_taxSendTime);
        }
        break;
     case TAX_GUN_LP_STATE_UNKNOWN:
        nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
        timePortGap.counter   = TickCounter;
        break;
    default:
        nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
        timePortGap.counter   = TickCounter;
       // timeCmdJump.counter = TickCounter;
        break;
    }

    taskTime++;
}
#if(0)
void tax_process_encoder(void)
{
//    int result = 0;
    int nodeCur = 0;
    int portCur = 0;
    int gunCur	= 0;
    int state	= 0;
    int infotype = 0;
    uint8_t ret = 0, readport = 0;//rcvCmd=0,
    uint32_t sn,seqno = 0;
    uint8_t factory = 0,encryption=0;
    static uint8_t flag = 0;
    static int taskTime = 0;
//    static int lastnodeCur = -1;
//    static int readCount = 0;
    static uint8_t breadPortTax = 0;
    if(g_runData.bUpdate != 0) return;

    if(timeout_isOut(&g_timeOut)==0) return;
    timeout_stop(&g_timeOut);

    if(timeout_isOut(&g_taxDataTime)==0) return;

    g_runData.ballowRead58 = 1;
    nodeCur = nodeConf.nodeIndex;
    portCur = nodeConf.taxconf[nodeCur].portIndex;
    gunCur = nodeConf.taxconf[nodeCur].port[portCur].gunIndex;
    state = nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState;
    infotype = downlink_config.collect_conf[nodeCur].tax_type; //明文/密文
    factory = downlink_config.collect_conf[nodeCur].tax_conf[portCur].factory;// gateway_read.collect_read[nodeCur].tax_read[portCur].factory;  /* 1: 英泰赛福 2: 拓盛 */
    encryption = downlink_config.collect_conf[nodeCur].tax_conf[portCur].encryption; // 拓盛密文是否实时读取 1：实时读取
    sn = downlink_config.collect_conf[nodeCur].collect_no;
    seqno = nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].seq_no;
    if(portCur == 0x00) readport = 0x01;
    else if(portCur == 0x01) readport = 0x02;
    if(g_runData.collrunMsg[nodeCur].checkNum>=5){ //采集器已经下发了5次数据，都没有收到返回
        downlink_config.collect_conf[nodeCur].collect_status = COLL_STATUS_OFFLINE; // 当前采集器已经离线
        downlink_config.collect_conf[nodeCur].tax_conf[0].status = 0;// 报税口1离线
        downlink_config.collect_conf[nodeCur].tax_conf[1].status = 0; //报税口2离线
     }

    if((downlink_config.collect_conf[nodeCur].collect_status == COLL_STATUS_OFFLINE) || (infotype == 0x00)){ //采集器离线状态

        g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000; // 采集器离线，要清零
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x56;
            g_logCfigDa.curportno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].tax_id;
            g_logCfigDa.curgunno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].gunid[gunCur];
            gateway_collect_set_cmd0x56(0x56,nodeCur,0x03,sn);
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
            nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
            nodeConf.taxconf[nodeCur].port[portCur].gunIndex = 0;
            nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
            set_led_update_status(g_ledStatus.collNum);
            if(infotype == 0x00) printf("采集器没有读取到明文密文类型,需要读取56, coll = %d\n",nodeCur);
            else printf("\r\n 采集器离线状态 coll = %d\r\n ",nodeCur);
            timeout_start(&g_taxSendTime);
            ret = get_gun_status();
            if(ret==0){
                timeout_setValue(&g_timeOut,g_firmwareMsg.gatewayMsg.configmsg.time_interval*1000);
                init_gun_status();
                if(g_runData.bRead0x58)g_runData.ballowRead58 = 0;
                if(g_timeOut.timeout != 0)timeout_start(&g_timeOut);
                printf("\r\ncheck all collect finsh_%d_offline\r\n",nodeCur);

            }
        }
        return;
    }

    if(g_encoderDa.bhaveEncoder == ENCONDER_EN){ // 有编码器
        if(nodeConf.taxconf[nodeCur].port[portCur].enNum.num.pEnNum!=0) { // 这个报税口下有编码器
            if( nodeConf.taxconf[nodeCur].port[portCur].bEnFinish == 0) {  // 这个报税口下的编码器没有读取完成
                if(timeout_isOut(&g_taxSendTime))  //超时
                    encoder_enable_read_data(nodeCur,portCur,gunCur);
                return;
           }
           else { // 此报税口的编码器已经读取完成
                if(timeout_isOut(&g_taxSendTime) && (breadPortTax==0)) { // 已经下发的指令接收到返回
                    if(nodeConf.taxconf[nodeCur].port[portCur].portRead==nodeConf.taxconf[nodeCur].port[portCur].enNum.num.pEnNum) { // 报税口读取完成且已经收到返回
                        flag = 1;
                    }
                    else {
                        flag = 0;
                    }
                    breadPortTax = 1; // 可以报税报税口了
                    /*printf("flag = %d, protread = %d, ennum = %d,node=%d,port=%d\r\n",
                           flag,nodeConf.taxconf[nodeCur].port[portCur].portRead,\
                           nodeConf.taxconf[nodeCur].port[portCur].enNum.num.pEnNum,\
                           nodeCur,portCur);*/
                }
                else {
                    if(breadPortTax == 1){
                        flag = 1;
                      //  printf("aaaaaaaaaaaaaa\r\n");
                    }
                    else return;
                }
            }
        }
        else flag = 1; // 此报税口下没有编码器

        if(flag==0){ // 此报税口有正在加油的状态，不可以读取报税口
            nodeConf.taxconf[nodeCur].port[portCur].portRead = 0;
            nodeConf.taxconf[nodeCur].port[portCur].bEnFinish = 0;
            nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
            nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
            g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000;
            breadPortTax = 0;
            ret = get_gun_status();
            if(ret==0){
                timeout_setValue(&g_timeOut,g_firmwareMsg.gatewayMsg.configmsg.time_interval*1000);
                init_gun_status();
                if(g_runData.bRead0x58)g_runData.ballowRead58 = 0;
                if(g_timeOut.timeout != 0)timeout_start(&g_timeOut);
                printf("\r\ncheck all collect finsh_%d_read_encoder\r\n",nodeCur);

            }
            return;
        }
    }
    switch(state){
    case TAX_GUN_LP_STATE_IDLE:
        if(timeout_isOut(&g_taxSendTime) !=1) break;
        if(taskTime==0){
            timePortGap.counter = TickCounter - timePortGap.timeOut;
            timeCmdJump.counter = TickCounter - timeCmdJump.timeOut;
            timeTSMWCmdGap.counter = TickCounter - timeTSMWCmdGap.timeOut;
        }
        if((TickCounter - timeTSMWCmdGap.counter >= timeTSMWCmdGap.timeOut) || (g_runData.bReadMingWenData==5)) //判断是否到50分钟
        {
            tsmw_gun_set_read();
            timeTSMWCmdGap.counter = TickCounter;
//            lastnodeCur = -1;
            g_runData.bReadMingWenData = 0;
        }

        if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].alrd_sn==1 \
           || downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num != 0)//if(gateway_read.collect_read[nodeCur].tax_read[portCur].alrd_sn)//已经查询过加油机的信息即已经读取过0x83指令/*nodeConf.taxconf[nodeCur].port[portCur].alrd_sn*/
        {
            if(((infotype == CIPHERTEXT) || (infotype == CIPHERTEXT01)) && (factory == 2) &&(encryption != 1)) //拓盛密文50分钟读一次
            {
                if(nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].tsmw_flag == 0 )//该加油枪没有读过数据
                {
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].tsmw_flag = 1;
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_89;
                }
                else//已经读过数据直接跳到下一个枪
                {
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_56;//TAX_GUN_LP_STATE_CH;
                }
            }
            else
            {
                    nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_89;
            }

            break;
        }
        else //没有查询过加油机的信息，先去执行0x83指令去查询加油机的信息
        {
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;
        }
        break;
    case TAX_GUN_LP_STATE_83:
        //定时轮询83指令
        //如果超时或出错，则，清空当前枪状态，且枪索引指向当前端口的下一个枪
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x83;
            printf("send : sn = %010d, coll=%d, port=%d, gun=%d, cmd = 0x%02x, seqNo = %010d, time = %010d\r\n",sn,nodeCur,portCur,gunCur,0x83,seqno,TickCounter);

            if(infotype == PLAINTEXT)
            {
                tax_send_cmd(tax_send_cmd_83,nodeCur,portCur,gunCur);
            }
            else if(infotype == CIPHERTEXT)
            {
                ytsf_send_cmd(0xA2,0x00,nodeCur,portCur,gunCur);
            }
            g_runData.collrunMsg[nodeCur].checkNum++;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;

            timePortGap.counter= TickCounter;
            timeCmdGap.counter = TickCounter;
            timeCmdOut.counter = TickCounter;
            timeout_start(&g_taxSendTime);

        }
        break;

    case TAX_GUN_LP_STATE_89:
        //定时轮询89指令
        //如果超时或出错，则，清空当前枪状态，且枪索引指向当前端口的下一个枪
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x89;
            printf("send : sn = %010d, coll=%d, port=%d, gun=%d, cmd = 0x89, seqNo = %010d, time = %010d\r\n",sn,nodeCur,portCur,gunCur,seqno,TickCounter);
            memset(&rcv_data_temp,0,sizeof(rcv_data_temp_t));
            if(infotype == PLAINTEXT)
            {
                tax_send_cmd(tax_send_cmd_89,nodeCur,portCur,gunCur);
            }
            else if(infotype == CIPHERTEXT)
            {
                ytsf_send_cmd(0xA1,0x14,nodeCur,portCur,gunCur);
            }
            else if(infotype == CIPHERTEXT01){
                tax_send_cmd(0x14,nodeCur,portCur,gunCur);
            }
            g_runData.collrunMsg[nodeCur].checkNum++;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_86;
            timePortGap.counter= TickCounter;
            timeCmdGap.counter = TickCounter;
            timeCmdOut.counter = TickCounter;
            timeout_start(&g_taxSendTime);

        }

        break;

    case TAX_GUN_LP_STATE_86:
        //定时轮询86指令
        //如果超时或出错，则，清空当前枪状态，且枪索引指向当前端口的下一个枪
        if(timeout_isOut(&g_taxSendTime))
        {
            timeCmdGap.counter = TickCounter;
            g_curSendCmd = 0x86;
            printf("send : sn = %010d, coll=%d, port=%d, gun=%d, cmd = 0x86, seqNo = %010d, time = %010d\r\n",sn,nodeCur,portCur,gunCur,seqno,TickCounter);

            if(infotype == PLAINTEXT)
            {
                tax_send_cmd(tax_send_cmd_86,nodeCur,portCur,gunCur);
            }
            else if(infotype == CIPHERTEXT)
            {
                ytsf_send_cmd(0xA1,0x11,nodeCur,portCur,gunCur);
            }
            else if(infotype == CIPHERTEXT01){
                tax_send_cmd(0x11,nodeCur,portCur,gunCur);
            }
            g_runData.collrunMsg[nodeCur].checkNum++;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].seq_no++;
            timeout_start(&g_taxSendTime);

        }

        break;
    case TAX_GUN_LP_STATE_CH:
        if(timeout_isOut(&g_taxSendTime) !=1) break;
        if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num==0) // 存在报税口的枪的个数为0，83没有读取，但这个报税口在线，有数据的情况
            g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000;
        else set_gun_status(nodeCur,portCur,gunCur);
        if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].status==0) { // 当前的报税口的状态没为离线状态
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
            nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
            nodeConf.taxconf[nodeCur].port[portCur].gunIndex = 0;
            g_checkGun[nodeCur].gunSta.status[portCur] = 0x0000;
            nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
            nodeConf.taxconf[nodeCur].port[portCur].portRead = 0;
            nodeConf.taxconf[nodeCur].port[portCur].bEnFinish = 0;
            flag = 0;
            breadPortTax = 0;
        }
        else{
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
            if(downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num==0) nodeConf.taxconf[nodeCur].port[portCur].gunIndex = 0;
            else nodeConf.taxconf[nodeCur].port[portCur].gunIndex = (gunCur+1)%downlink_config.collect_conf[nodeCur].tax_conf[portCur].gun_num;
            if(nodeConf.taxconf[nodeCur].port[portCur].gunIndex == 0) //一个报税口的枪轮询完了
            {
                flag = 0;
                nodeConf.taxconf[nodeCur].port[portCur].portRead = 0;
                nodeConf.taxconf[nodeCur].port[portCur].bEnFinish = 0;
                nodeConf.taxconf[nodeCur].portIndex = (portCur+1)%downlink_config.collect_conf[nodeCur].tax_num;
                nodeConf.nodeIndex = (nodeCur+1) % downlink_config.collect_num;
                breadPortTax = 0;
            }

        }

        if(g_runData.bInstallFinish == 0xA5){ // 安装完成
            if((nodeConf.nodeIndex == 0) && (nodeConf.taxconf[nodeCur].portIndex == 0) \
                 && (nodeConf.taxconf[nodeCur].port[portCur].gunIndex == 0)){
                init_gun_status();
                g_runData.bInstallFinish = 0;
                breadPortTax = 0;
            }
        }
        timePortGap.counter= TickCounter;
        timeCmdGap.counter = TickCounter;
        timeCmdOut.counter = TickCounter;

        ret = get_gun_status();
        if(ret==0){
            timeout_setValue(&g_timeOut,g_firmwareMsg.gatewayMsg.configmsg.time_interval*1000);
            init_gun_status();
            if(g_runData.bRead0x58)g_runData.ballowRead58 = 0;
            if(g_timeOut.timeout != 0)timeout_start(&g_timeOut);
            printf("\r\ncheck all collect finsh\r\n");

        }
        break;
     case TAX_GUN_LP_STATE_56:
        if(timeout_isOut(&g_taxSendTime)) {
            printf("cmd 0x56: collIndex = %d, tick = %d\r\n",nodeCur,TickCounter);
            g_curSendCmd = 0x56;
            g_logCfigDa.curportno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].tax_id;
            g_logCfigDa.curgunno = downlink_config.collect_conf[nodeCur].tax_conf[portCur].gunid[gunCur];
            gateway_collect_set_cmd0x56(0x56,nodeCur,readport,sn);
            timeCmdGap.counter = TickCounter;
            nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_CH;

            timeout_start(&g_taxSendTime);
        }
        break;
     case TAX_GUN_LP_STATE_UNKNOWN:
        nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
        timePortGap.counter   = TickCounter;
        break;
    default:
        nodeConf.taxconf[nodeCur].port[portCur].gun[gunCur].gLpState = TAX_GUN_LP_STATE_IDLE;
        timePortGap.counter   = TickCounter;
        break;
    }

    taskTime++;
}
#endif
/* 手动刷新税控序列号 0x1018 指令 执行 */
void tax_manual_0x83_process(void)
{
    uint8_t ret = 0,index = 0;
    uint8_t taxType = 0;
//    uint32_t sn;
    static uint8_t breadQueue = 0, taxNo = 0,taxNum = 2;
    static da83 data;
    if(!timeout_isOut(&g_taxSendTime)) { // 超时

        return;
    }

    if(taxNo >=taxNum){
        breadQueue = 0;
        taxNo = 0;
    }
    if(breadQueue == 0 ) {
        ret = de_queue_cmd83(&g_cmdInfo83,&data);
        if(ret == 0) { // 队列为空
            printf("cmd 83 queue empty\r\n");
            breadQueue = 0;
            taxNo = 0;
            init_queue(&g_cmdInfo83);
            return;
        }
        if(data.para == 3){
            taxNo = data.taxNo -1;
            taxNum = 1;
        }
        else taxNum = 2;
        printf("cmd 83 pull queue\r\n");
        breadQueue = 1;
    }

    index = read_collect_index(data.sn);
    if(index >=16){
        printf("coll_sn = %010ud, no have \r\n",data.sn);
        return;
    }
    //infotype = downlink_config.collect_conf[index].tax_type; //明文/密文
    taxType = nodeConf.taxconf[index].port[taxNo].taxType;
//    sn = data.sn;
    if((taxType&PLAINTEXT) == PLAINTEXT)
    {
        printf("send plaintext cmd 0x83: coll = %d, port = %d\r\n",index, taxNo);
        g_curSendCmd = 0x83;
        tax_send_cmd(tax_send_cmd_83,index,taxNo,1);

    }
    else if((taxType&CIPHERTEXT) == CIPHERTEXT)
    {
        printf("send ciphertext cmd 0x83: coll = %d, port = %d\r\n",index, taxNo);
        g_curSendCmd = 0x83;
        if((taxType&0x80)==0x80){
            tax_send_cmd(0x70,index,taxNo,1);
        }
        else ytsf_send_cmd(0xA2,0x00,index,taxNo,1);


    }
    else { // 不知道的按明文读取
        printf("send default cmd 0x83 coll = %d, port = %d, 没有读取到加密类型，按明文读取\r\n ",index, taxNo);
        g_curSendCmd = 0x83;
        if((taxType&0x80) == 0x80) {
            tax_send_cmd(0x70,index,taxNo,1);
        }
        else
            tax_send_cmd(tax_send_cmd_83,index,taxNo,1);

    }
    timeout_start(&g_taxSendTime);
    taxNo++;

}

void tax_0x83_process(void)
{

    int gunCur	= 1;
    int taxType = 0;
//    uint32_t sn;
    uint8_t alrd_sn;
    uint8_t num = 0;


    ReadCollcmd *cmd = &g_readCmd83;

    num = downlink_config.collect_num;

    if((cmd->stauts[0]== (uint16_t)(pow(2,num)-1)) && (cmd->stauts[1]== (uint16_t)(pow(2,num)-1))){
        g_runData.bfirstRead0x83 = 0;
        printf("cmd 0x83 finish\r\n");
        return;
    }
    //if((TickCounter - timeCmdGap.counter) < timeCmdGap.timeOut)  return;
    if(!timeout_isOut(&g_taxSendTime)) { // 未超时
        return;
    }
    if(downlink_config.collect_conf[cmd->nodeCur].collect_status==0){ //采集器的离线状态
        cmd->stauts[0] |=   (uint16_t)(0x01<<cmd->nodeCur);
        cmd->stauts[1] |=   (uint16_t)(0x01<<cmd->nodeCur);
        cmd->nodeCur++;
        if(cmd->nodeCur>=num) {cmd->nodeCur = 0; }
        cmd->portCur=0;
        timeout_stop(&g_taxSendTime);
        return;
    }
    alrd_sn = nodeConf.taxconf[cmd->nodeCur].port[cmd->portCur].alrd_sn;
    //alrd_sn = downlink_config.collect_conf[cmd->nodeCur].tax_conf[cmd->portCur].alrd_sn;
    if(alrd_sn){
        cmd->checknum[cmd->nodeCur][cmd->portCur] = 0;
        cmd->stauts[cmd->portCur] |=   (uint16_t)(0x01<<cmd->nodeCur);
        cmd->portCur++;
        if(cmd->portCur>=2){// 两个端口已经读取完成
            cmd->nodeCur++;
            if(cmd->nodeCur>=num) {cmd->nodeCur = 0; }
            cmd->portCur = 0;
            return;
        }
        timeout_stop(&g_taxSendTime);
    }
    else {
        if(cmd->checknum[cmd->nodeCur][cmd->portCur]>=3){
            cmd->stauts[cmd->portCur] |=   (0x01<<cmd->nodeCur);
            downlink_config.collect_conf[cmd->nodeCur].tax_conf[cmd->portCur].status = 0;
            // 上报服务器状态
        }
//        infotype = downlink_config.collect_conf[cmd->nodeCur].tax_type; //明文/密文
        taxType = nodeConf.taxconf[cmd->nodeCur].port[cmd->portCur].taxType;
//        sn = downlink_config.collect_conf[cmd->nodeCur].collect_no;
        if((taxType&PLAINTEXT) == PLAINTEXT)
        {
            tax_send_cmd(tax_send_cmd_83,cmd->nodeCur,cmd->portCur,gunCur);
            cmd->checknum[cmd->nodeCur][cmd->portCur]++;
            printf("send plaintext cmd 0x83: coll = %d, port = %d\r\n",cmd->nodeCur, cmd->portCur);

        }
        else if((taxType&CIPHERTEXT) == CIPHERTEXT)
        {
            if((taxType&0x80) == 0x80)
                tax_send_cmd(0x70,cmd->nodeCur,cmd->portCur,1);
            else
                ytsf_send_cmd(0xA2,0x00,cmd->nodeCur,cmd->portCur,gunCur);
            cmd->checknum[cmd->nodeCur][cmd->portCur]++;
            printf("send ciphertext cmd 0x83: coll = %d, port = %d\r\n",cmd->nodeCur, cmd->portCur);
        }
        else { // 没有明文密文时
            if((taxType&0x80) == 0x80) {
                tax_send_cmd(0x70,cmd->nodeCur,cmd->portCur,1);
            }
            else
                tax_send_cmd(tax_send_cmd_83,cmd->nodeCur,cmd->portCur,gunCur);
            cmd->checknum[cmd->nodeCur][cmd->portCur]++;
        }
        cmd->portCur++;
        if(cmd->portCur>=2) {
           cmd-> portCur = 0;
            cmd->nodeCur++;
            if(cmd->nodeCur>=num) {
                cmd->nodeCur = 0;
            }
        }
        timeout_start(&g_taxSendTime);
    }
    timeCmdGap.counter = TickCounter;
}
void tax_send_cmd_0x56_first(void)
{
    static uint8_t index = 0;
    uint32_t sn;
    uint8_t num,i;
    uint8_t send_buff[128];
    uint8_t buff_len  = 0;

    ReadCollcmd *cmd = &g_readCmd56;

   //if((TickCounter - timeCmdGap.counter) < timeCmdGap.timeOut) return; // 1S读取一次指令
    if(!(timeout_isOut(&g_taxSendTime))) { // 时间没有到
        return;
    }
   timeCmdGap.counter = TickCounter;
   memset(send_buff,0,sizeof(send_buff));
   num = downlink_config.collect_num;

   i = cmd->nodeCur;
   if((downlink_config.collect_conf[i].collect_status==0) || (downlink_config.collect_conf[i].tax_type==0) ){
       if(downlink_config.collect_conf[i].coll_send_num<5){
           index = i;
           printf("collect = %02d,%010u,readnum = %d error\r\n",i,downlink_config.collect_conf[i].collect_no,downlink_config.collect_conf[i].coll_send_num);
          // break;
       }
       else {
           g_runData.collstatus |= (((uint16_t)0x01)<<i);
           uplink_tax_statusmcmd_0x2002(send_buff,&buff_len,DEVICE_COLLECT,i);//上传服务器，采集器的离线状态
           tax_net_send(send_buff,buff_len,FIRST_TYPE_STATUS,COLL_UP_STATUS_CMD2002);
       }

   }
   else {
       if(((g_runData.collstatus>>i)&0x01) == 0x00){
           uplink_tax_statusmcmd_0x2002(send_buff,&buff_len,DEVICE_COLLECT,i);//上传服务器，采集器的在线状态
           tax_net_send(send_buff,buff_len,FIRST_TYPE_STATUS,COLL_UP_STATUS_CMD2002);
       }
       g_runData.collstatus |= (((uint16_t)0x01)<<i);
       printf("collect = %02d,%010u, readnum = %d suc\r\n",i,downlink_config.collect_conf[i].collect_no,downlink_config.collect_conf[i].coll_send_num);
   }

   if(g_runData.collstatus == (uint16_t)(pow(2,num)-1) ) {
       g_runData.bfirstSend0x56 = 0;
       g_runData.bfirstRead0x83 = 0;
       g_runData.bRead0x58 = 1;
       printf("collect 0x56 succ\r\n");
       return;
   }
   if((downlink_config.collect_conf[index].collect_status==0) || (downlink_config.collect_conf[i].tax_type==0)) { // 采集器离线状态
       sn = downlink_config.collect_conf[index].collect_no;
       gateway_collect_set_cmd0x56(0x56,index,0x03,sn);
       timeout_start(&g_taxSendTime);
   }
   //else {
       cmd->nodeCur++;
       if(cmd->nodeCur>=downlink_config.collect_num) cmd->nodeCur = 0;
  // }
}

/*---------------------------------------------------------------------
 *  读取固件信息
 *
 * -------------------------------------------------------------------*/
void tax_send_cmd_0x58(void)
{
    uint8_t num;
    uint32_t sn;
    ReadCollcmd *cmd = &g_readCmd58;

    num = downlink_config.collect_num;

    //if(TickCounter - timeCmdGap.counter < 2*timeCmdGap.timeOut) return; // 1S读取一次指令
    //    timeCmdGap.counter = TickCounter;
    if( (!timeout_isOut(&g_taxSendTime)) ) { // 超时了
        return ;
    }
    if(g_runData.bRead0x58){

        if((cmd->stauts[0] == (uint16_t)(pow(2,num)-1))){ // 说明已经读取一遍
            g_runData.bRead0x58 = 0;
            g_runData.bReadData = 1;
            cmd->nodeCur = 0;
            if(g_runData.read1053Num <2)g_runData.bRead1053 = 0x01;
            printf("cmd 0x58 finish \r\n");
            return;
        }
        if(downlink_config.collect_conf[cmd->nodeCur].collect_status==1) {
            sn = downlink_config.collect_conf[cmd->nodeCur].collect_no;
            gateway_collect_set_cmd0x58(0x58,cmd->nodeCur,sn);
            cmd->stauts[0] |=   ((uint16_t)0x01<<cmd->nodeCur);
            printf("cmd 0x58_1 coll = %d \r\n", cmd->nodeCur);
            cmd->nodeCur++;
            timeout_start(&g_taxSendTime);

        }
        else { // 采集器离线状态
            cmd->stauts[0] |=   ((uint16_t)0x01<<cmd->nodeCur);
            printf("cmd 0x58_0 coll = %d \r\n", cmd->nodeCur);
            cmd->nodeCur++;
        }
    }
}
/*------------------------------------------------------------------
 *  读取 1053
 * -------------------------------------------------------------------*/
void tax_send_cmd_0x01_0x1053(void)
{
    uint16_t num,sendlen = 0;
    static uint8_t index = 0;
    uint16_t devType;
    uint32_t devSn;
    uint8_t send_buff[128] = {0};
    num = downlink_config.collect_num;

    if( (!timeout_isOut(&g_taxSendTime)) ) { // 超时了
        return ;
    }

    devType = 0x0202;
    devSn = downlink_config.collect_conf[index].collect_no;
    create_0x01_0x1053(send_buff,&sendlen,devType,devSn,devType,devSn,0x02,0x01,0x00);
    gateway_collect_cmd_0x01_0x1053(send_buff,sendlen);
    timeout_start(&g_taxSendTime);
    index = (index+1)%downlink_config.collect_num;
    if(index == 0){
        g_runData.bRead1053 = 0;
        g_runData.read1053Num++;
    }
    return;

}

/*--------------------------------------------------------------------
 *  切换lora信道 0x5B 指令
 * -------------------------------------------------------------------*/
void tax_send_cmd_0x5B(void)
{
    static uint8_t readIndex = 0;
    static uint8_t readCircle = 0; // 下发的圈数
    uint8_t send_buff[160];
    uint8_t sendlen = 0;
    volatile uint8_t i = 0;
    OS_ERR  err;

    uint32_t sn;
    uint8_t paIndex;
    if((TickCounter - timeCmdGap.counter) < timeCmdGap.timeOut) return; // 1S读取一次指令

    timeCmdGap.counter = TickCounter;

    sn = g_loraCollMsg.info[readIndex].coll_sn;

    paIndex = g_runData.nextlorIndex;
    switch(g_loraCollMsg.step){
    case 1:
        if(g_runData.curloraIndex != readCircle){
            printf("第一步: 切换信道到 %d\r\n",readCircle);
            g_runData.curloraIndex = readCircle;
            lora_init("golden_beans");
            OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err);
        }
        printf("第一步信道：%d,采集器sn: %010u索引：%d\r\n",readCircle,sn,readIndex);
        gateway_collect_set_cmd0x5B(readIndex+1,sn,paIndex,0);
        readIndex++;
        if(readIndex >= g_loraCollMsg.collNum) {
            readIndex = 0;
            readCircle++;
            if(readCircle>=4){
                 g_loraCollMsg.step = 2;
                 readIndex = 0;
                 g_runData.curloraIndex = g_runData.nextlorIndex;
                 OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err);
                 lora_init("golden_beans");
            }
        }
        break;
    case 2:
        printf("第二步：\r\n");
        if(readIndex<g_loraCollMsg.collNum){
            gateway_collect_set_cmd0x56(0x56,readIndex+1,0x03,sn);
            readIndex++;
        }
        else {
            printf("第二步完成\r\n");
            readIndex = 0;
            readCircle = 0;
            OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err);
            g_runData.bchangelora = 0;
            fram_write_lora_index(g_runData.curloraIndex);
            for(i=0;i<g_loraCollMsg.collNum;i++){
                if(g_loraCollMsg.info[i].loraindex>=4){
                    uplink_update_systemcmd_0x2017(send_buff,&sendlen,g_loraCollMsg.info[i].coll_sn,0,g_runData.nextlorIndex);
                    tax_net_send(send_buff,sendlen,FIRST_TYPE_SYST,COLL_UP_SYS_CMD2017);
                    set_led_status(i,0);
                }
            }
            g_loraCollMsg.lora_sendCount = 0;
            g_loraCollMsg.lora_rcvCount = 0;
            for(i=0;i<downlink_config.collect_num;i++){
                g_loraCollMsg.info[i].rcvNum = 0;
                g_loraCollMsg.info[i].sendNum = 0;
                set_led_status(i,1);
            }
        }
        break;
    }
}

//查询采集器编号
uint8_t read_collect_index(uint32_t id)
{
    uint8_t ret = 0xFF;
    uint8_t i;
    if( downlink_config.collect_num == 0 ) return 0xFF;
    for(i = 0; i < downlink_config.collect_num; i++)
    {
        if(id == downlink_config.collect_conf[i].collect_no)
        {
            return i;
        }
    }
    return ret;
}

//查询报税口编号
uint8_t read_tax_index(uint8_t node, uint8_t uart)
{
    uint8_t ret = 0xFF;
    uint8_t i;

    for(i = 0; i < downlink_config.collect_conf[node].tax_num; i++)
    {
        if(uart == downlink_config.collect_conf[node].tax_conf[i].tax_id)
        {
            return i;
        }
    }
    return ret;
}

//查询枪编号
uint8_t read_gun_index(uint8_t node,uint8_t port, uint8_t gun)
{
    uint8_t ret = 0xFF;
    uint8_t i;


    if(downlink_config.collect_conf[node].tax_conf[port].gun_num == 0) return 0;
    for(i = 0; i < downlink_config.collect_conf[node].tax_conf[port].gun_num; i++)
    {
        if(gun == downlink_config.collect_conf[node].tax_conf[port].gunid[i])
        {
            return i;
        }
    }
    return ret;
}


void init_gun_status(void)
{
    int i=0;
    uint8_t gunNum = 0;
    for(i=0;i<downlink_config.collect_num;i++){
        gunNum = downlink_config.collect_conf[i].tax_conf[0].gun_num;
        if(gunNum==0) g_checkGun[i].gunSta.status[0] = 0xFF;
        else g_checkGun[i].gunSta.status[0] = pow(2,gunNum)-1;
        gunNum = downlink_config.collect_conf[i].tax_conf[1].gun_num;
        if(gunNum == 0) g_checkGun[i].gunSta.status[1] = 0xFF;
        else g_checkGun[i].gunSta.status[1] = pow(2,gunNum)-1;
    }
}
void set_gun_status(uint8_t nodecur, uint8_t port, uint8_t gun)
{
    g_checkGun[nodecur].gunSta.status[port] &= (~(1<<gun));
}
/* 返回0 查询完成  返回1 ，没有完成*/
uint8_t get_gun_status(void)
{
    int i = 0;

    for(i=0;i<downlink_config.collect_num;i++){

        if(g_checkGun[i].gunSta.status1 != 0) return 1;
    }

    return 0;
}

/* 编码器的数据读取 */
void encoder_read_data(uint8_t node, uint8_t port, uint8_t gun)
{
    uint8_t sendbuff[8] = {0};
    uint8_t sendlen = 1;
    uint32_t seqno = 0,id=0;
    uint8_t portNo = 0, gunNo = 0;

    seqno++;
    g_runData.collrunMsg[node].checkNum++;
    id = downlink_config.collect_conf[node].collect_no;
    portNo = downlink_config.collect_conf[node].tax_conf[port].tax_id;
    gunNo = downlink_config.collect_conf[node].tax_conf[port].gunid[gun];
    if(downlink_config.bInstallFinish==INSTALL_5A) sendbuff[0] = 0x03;
    else sendbuff[0] = 0x02;
    g_curSendCmd = 0x5C;
    g_logCfigDa.curportno = portNo;
    g_logCfigDa.curgunno = gunNo;

    gateway_collect_set_cmd0x5C(sendbuff,sendlen,node,portNo,gunNo,seqno,id);
    printf("send 0x5C sn = %010u, coll = %d, portNo = %d\r\n",id,node,portNo);
    timeout_start(&g_taxSendTime);
}
/*------------------------------------------------------------------------
 *  使能了编码器的路由表，读取编码器数据
 * ------------------------------------------------------------------------*/
void encoder_enable_read_data(uint8_t node, uint8_t port, uint8_t gun)
{
    uint8_t sendbuff[8] = {0};
    uint8_t sendlen = 1,enIndex = 0;
    uint32_t seqno = 0,id=0;
    uint8_t  gunNo = 0,bcollid,bportid;//portNo = 0,
    enMsgDa *msg = NULL;

    enIndex = nodeConf.taxconf[node].port[port].enIndex;
    msg = &(nodeConf.taxconf[node].port[port].enMsg[enIndex]);
    seqno++;
    g_runData.collrunMsg[node].checkNum++;
    bcollid = msg->da.bcollid;
    bportid = msg->da.bportid;
    id = downlink_config.collect_conf[bcollid].collect_no;
    //portNo = downlink_config.collect_conf[bcollid].tax_conf[bportid].tax_id;

    if(downlink_config.bInstallFinish==INSTALL_5A) sendbuff[0] = 0x03;
    else sendbuff[0] = 0x02;
    g_curSendCmd = 0x5C;
    g_logCfigDa.curportno = bportid;//portNo;
    g_logCfigDa.curgunno = gunNo;

    gateway_collect_set_cmd0x5C(sendbuff,sendlen,bcollid,bportid,gunNo,seqno,id);
    printf("send 0x5C_table sn = %010u, coll = %d, portNo = %d\r\n",id,bcollid,bportid);
    g_encodeOpt.curIndex = nodeConf.taxconf[node].port[port].enIndex;
    nodeConf.taxconf[node].port[port].enIndex = (enIndex+1)%nodeConf.taxconf[node].port[port].enNum.num.pEnNum;
    if(nodeConf.taxconf[node].port[port].enIndex==0) {
        nodeConf.taxconf[node].port[port].bEnFinish = 1;
        printf("encoder_table finish\r\n");
    }
    timeout_start(&g_taxSendTime);
}

#endif




