#include "downlink.h"
#include "uplink.h"
#include "device.h"
#include "gateway.h"
#include "../network_mgr/net_proc.h"
#include "../tax/tax.h"
#include "../../User/includes.h"
#include "../storage/AT24c128.h"
#include "../gateway_collect/gateway_collect.h"
#include "../dev_mgr/taxctrl/tax_ctrl.h"
#include "../globalDef.h"
#include "../storage/AT24C128Opt.h"
#include "../network_mgr/net_ctrl.h"
#include "nettimer.h"
#include "../network_mgr/sx1268/lora.h"
#include "me3616.h"
#include "../encode/encodeOpt.h"
#include "../toolkit/CH455G.h"
extern ME3616  air;

downlink_config_t downlink_config;
void downlink_init(void)
{
    int ret;
    int i,j;
//    uint32_t flag = 0;
    uint8_t taxCount = 0;
    memset(&downlink_config.collect_conf,0,sizeof(downlink_config.collect_conf));
    memset(&rcv_data_temp,0,sizeof(rcv_data_temp));

    sprintf(g_upLinkTopic,"%s%04x/%010u",(char*)MQTT_UPLINK_TOPIC,GATEWAY_DEVICE_TYPE, g_firmwareMsg.gatewayMsg.hardwareMsg.gateway_sn);
    sprintf(g_logupLinkTopic,"%s%04x/%010u",(char*)MQTT_LOGUPLINK_TOPIC,GATEWAY_DEVICE_TYPE, g_firmwareMsg.gatewayMsg.hardwareMsg.gateway_sn);


    fram_read_config_msg();
    printf("config_flag:%d,gateway_id:%010u,collect_num:%d\n",downlink_config.config_flag,downlink_config.gateway_id,downlink_config.collect_num);
    if(downlink_config.config_flag == CONFIG_WRITE)
    {
        fram_read_collect_msg();
        if((g_encoderDa.bhaveEncoder == 1) && (g_encodeOpt.benable==1)){
            fram_read_encoder_configMsg();
            fram_read_encoder_msg();
        }
        ret = gateway_collect_init();
        encoder_printf();
        if(ret)
        {
            downlink_config.config_flag = 0;
        }
        if(downlink_config.collect_num == 0xFF) downlink_config.collect_num = 0;
        for(i=0;i<downlink_config.collect_num;i++){ // 初始化采集器的SN号
            g_firmwareMsg.collMsg[i].device_sn = downlink_config.collect_conf[i].collect_no;
            downlink_config.collect_conf[i].coll_send_num = 0;
            downlink_config.collect_conf[i].collect_status = 0;
            g_readCmd83.checknum[i][0] = 0;
            g_readCmd83.checknum[i][1] = 0;

            for(j=0;j<2;j++){
                if(downlink_config.collect_conf[i].tax_conf[j].status) taxCount++;
            }

            set_led_status(i,1);
            printf("coll_%02d = %010u\r\n",i,downlink_config.collect_conf[i].collect_no);
        }
        init_gun_status();
        g_runData.firstReadNum = downlink_config.collect_num*taxCount*4;

        g_ledStatus.collNum =  g_ledStatus.led16.status;
        g_runData.bfirstSend0x56 = 1;
        g_runData.timeSendStatus = 3;
        g_runData.bUpdate = 0;
        g_readCmd83.nodeCur = 0;
        g_readCmd83.portCur = 0;
        g_readCmd83.stauts[0]  = 0;
        g_readCmd83.stauts[1] = 0;
        g_readCmd56.nodeCur = 0;
        g_runData.collerr = 0;
        init_queue(&g_cmdInfo83);
        init_comm_queue();
    }
}
static void downlink_config_init(uint8_t step,uint8_t flag,uint8_t configNo)
{
    int i=0,j=0;

    if(step == CONFIG_STEP_01) {
        downlink_config.config_flag = CONFIG_WRITE;
        g_runData.bReadData = 0;
        g_runData.bfirstSend0x56 = 0;
        g_runData.bfirstRead0x83 = 0;
        g_runData.bRead0x58 = 0;
        g_runData.read1053Num = 0;
        g_runData.ballowRead58 = 0;
        g_runData.bsendUpdateStatus = 0;
        g_readCmd58.nodeCur = 0;
        g_readCmd58.stauts[0] = 0;
        g_runData.collstatus = 0x0000;
        g_readCmd83.stauts[0] = 0;
        g_readCmd83.stauts[1] = 0;
        g_readCmd83.nodeCur = 0;
        g_readCmd83.portCur = 0;
        for(i=0;i<16;i++){
            for(j=0;j<2;j++) g_readCmd83.checknum[i][j] = 0;
            g_runData.collrunMsg[i].checkNum = 0;
        }
        g_firmwareMsg.gatewayMsg.configmsg.time_interval = 0;
        g_firmwareMsg.gatewayMsg.configmsg.configNo = configNo;
        g_firmwareMsg.gatewayMsg.configmsg.coll_num = downlink_config.collect_num;
        g_firmwareMsg.gatewayMsg.configmsg.bInitMsg.bInit.bConfig_qei = g_encoderDa.bhaveEncoder;
        fram_init_collect_msg();
        fram_write_config_msg(flag);
        fram_write_collect_msg();
        gateway_collect_init();
        downlink_config.config_flag = flag&0x0F;
        g_runData.timeSendStatus = 3;
        g_runData.bUpdate = 0;
//        g_runData.bfirstReadTax = 0;

        init_queue(&g_cmdInfo83);
        init_comm_queue();
        init_gun_status();
        g_runData.bfirstSend0x56 = 1;
    }
//    downlink_config.config_xsp = (flag>>4)&0x0F;
}
#if(0)
int downlink_gateway_para(uint8_t *data, uint16_t len)
{
    int ret=-1;
    int i,j,k;
    downlinkSysCmd0x1011 *p_msg = NULL;
    uint16_t flag = 0x01;
    
//    uint8_t flag1 = 0;
 //   uint8_t *tempdata;
 //   tempdata = data+5;
	
    p_msg = (downlinkSysCmd0x1011 *)data;


    return 0;

    if(p_msg->configNo == g_firmwareMsg.gatewayMsg.configmsg.configNo) {
        printf("\r\n the same config, not init\r\n");
        return 0;
    }

    printf("\r\n 0x1011 recv config = %d, eppromconfig = %d\r\n",p_msg->configNo,g_firmwareMsg.gatewayMsg.configmsg.configNo);

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


    downlink_config.gateway_id = p_msg->gateway_id;
    downlink_config.collect_num = p_msg->collect_num;
    g_firmwareMsg.gatewayMsg.configmsg.coll_num = p_msg->collect_num;
    if(p_msg->collect_num > COLLECT_MAX_NUM) //采集器个数大于最大值，数据错误，直接返回
        return ret;

    for(i=0;i<p_msg->collect_num;i++){
        downlink_config.collect_conf[i].collect_no = p_msg->cfigMsg[i].collectSn;
        g_firmwareMsg.collMsg[i].device_sn = p_msg->cfigMsg[i].collectSn;
        downlink_config.collect_conf[i].collect_status = 0;
        downlink_config.collect_conf[i].tax_num = 2;
        for(j=0;j<2;j++){
            downlink_config.collect_conf[i].tax_conf[j].tax_id = j+1;
            downlink_config.collect_conf[i].tax_conf[j].gun_num = 0;
            downlink_config.collect_conf[i].tax_conf[j].encryption = p_msg->cfigMsg[i].comEncrypt[j];
            for(k=0;k<8;k++){
                downlink_config.collect_conf[i].tax_conf[j].gunid[k] = k+1;
            }
        }
    }

    downlink_config.config_flag = CONFIG_WRITE;
    g_runData.bfirstSend0x56 = 1;
    g_runData.bfirstRead0x83 = 0;
    g_runData.bRead0x58 = 0;
    g_runData.bsendUpdateStatus = 0;
    g_readCmd58.nodeCur = 0;
    g_readCmd58.stauts[0] = 0;
    g_runData.bReadData = 0;
    g_runData.collstatus = 0x0000;
    g_readCmd83.stauts[0] = 0;
    g_readCmd83.stauts[1] = 0;
    g_readCmd83.nodeCur = 0;
    g_readCmd83.portCur = 0;
    for(i=0;i<16;i++){
        for(j=0;j<2;j++) g_readCmd83.checknum[i][j] = 0;
        g_runData.collrunMsg[i].checkNum = 0;
    }
    g_firmwareMsg.gatewayMsg.configmsg.time_interval = 2;
    g_firmwareMsg.gatewayMsg.configmsg.configNo = p_msg->configNo;
    fram_init_collect_msg();
    fram_write_config_msg(flag);
    fram_write_collect_msg();

    downlink_config.config_flag = flag;

    g_runData.timeSendStatus = 3;
    g_runData.bUpdate = 0;
    init_queue(&g_cmdInfo83);
    NVIC_SystemReset();//复位
    return 0;
}
#endif
/*--------------------------------------------------------------
 *  刷新税控序列号0x1012
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1012(uint8_t *data,uint16_t size)
{
    uint8_t index = 0;
    uint8_t num = 0;
    downlinkSysCmd0x1012 *p_msg = NULL;

    p_msg = (downlinkSysCmd0x1012*)data;

    if(p_msg->gateway_sn != downlink_config.gateway_id){ // 不是发给本网关的消息

        return ;
    }

    num = downlink_config.collect_num;
    index = read_collect_index(p_msg->coll_sn); //根据采集器的SN号，查找采集器的编号
    if(index >= downlink_config.collect_num) return;
    g_runData.bfirstRead0x83 = 1;
    g_readCmd83.nodeCur = index;
    g_readCmd83.portCur = p_msg->tax_no-1;
   // downlink_config.collect_conf[index].tax_conf[p_msg->tax_no-1].alrd_sn = 0;
    nodeConf.taxconf[index].port[p_msg->tax_no-1].alrd_sn = 0;
    g_readCmd83.stauts[0] = (uint16_t)(pow(2,num)-1);
    g_readCmd83.stauts[1] = g_readCmd83.stauts[0];
    g_readCmd83.stauts[0] = (g_readCmd83.stauts[0] & (~(0x01<<index)));
    g_readCmd83.stauts[1] = (g_readCmd83.stauts[1] & (~(0x01<<index)));


}

/*--------------------------------------------------------------
 *  设备重新启动 0x1021
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1021(uint8_t *data,uint16_t size)
{

    downlinkSysCmd0x1021 *p_msg = NULL;

    p_msg = (downlinkSysCmd0x1021*)data;

    switch(p_msg->targetType){
    case 0x0101: // 网关
        if(p_msg->sn != downlink_config.gateway_id) break;
        NVIC_SystemReset();//复位//设备重新启动
        break;
    case 0x0201: case 0x0202:// 采集器
        gateway_collect_set_cmd0x59(0,p_msg->sn);
        g_runData.bfirstSend0x56 = 1;
        break;
    case 0x0301: // 液位仪采集器

        break;
    case 0x0401: // 显示器

        break;
    case 0x0601: // 加密模块
        gateway_collect_set_cmd0x5D(0,p_msg->sn,0x0601,0x01);
        g_runData.bfirstSend0x56 = 1;
        break;
    }
}
/*--------------------------------------------------------------
 *  时间轮询
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1013(uint8_t *data)
{
    downlinkSysCmd0x1013 *p_msg = NULL;

     p_msg = (downlinkSysCmd0x1013*)data;

     if((p_msg->gateway_sn == downlink_config.gateway_id) || ( p_msg->gateway_sn==0xFFFFFFFF) ){
            timeout_setValue(&g_timeOut,p_msg->time_interval*1000);
            g_firmwareMsg.gatewayMsg.configmsg.time_interval = p_msg->time_interval;
            fram_write_config_msg(2);
            g_runData.bInstallFinish = 0xA5;
     }


}

/*--------------------------------------------------------------
 *  lora 信道参数切换
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1016(uint8_t *data, uint16_t size)
{
    downlinkSysCmd0x1016 *p_msg = NULL;
    uint32_t sn = 0 ;
    uint8_t i = 0;

    g_loraCollMsg.collNum = data[4];
    data[4] = 0;
    sn = *((uint32_t*)data);

    if(sn != downlink_config.gateway_id) return;

    for(i=0;i<g_loraCollMsg.collNum;i++){
        g_loraCollMsg.info[i].coll_sn = *((uint32_t*)(data+5+i*4));
        g_loraCollMsg.info[i].loraindex = 5;
    }

    p_msg = (downlinkSysCmd0x1016*)(data + i*4+5);
    g_runData.nextlorIndex = p_msg->loraIndex;
    g_runData.bchangelora = 1;
    g_loraCollMsg.step = 1;
}

/*--------------------------------------------------------------
 *  lora 信道参数读取
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1017(uint8_t *data, uint16_t size)
{
    uint8_t sendBuff[160];
    uint8_t sendLen = 0;

    downlinkSysCmd0x1017 *p_msg = NULL;


     p_msg = (downlinkSysCmd0x1017*)data;

     if(p_msg->gateway_sn != downlink_config.gateway_id) return;

     uplink_update_systemcmd_0x2017(sendBuff,&sendLen,0xFFFFFFFF,1,g_runData.curloraIndex);
     tax_net_send(sendBuff,sendLen,FIRST_TYPE_STATUS,COLL_UP_SYS_CMD2017);


}
/*--------------------------------------------------------------
 *  手动读取税控序列号 0x1018
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1018(uint8_t *data, uint16_t size)
{  
    uint8_t num = 0, i=0;
    downlinkSysCmd0x1018 *p_msg = NULL;

     p_msg = (downlinkSysCmd0x1018*)data;

     printf("rcv 1018 cmd  pa = %d\r\n",p_msg->prara);
     printf("msgSN = %010u , id = %010u\r\n",p_msg->gateway_sn,downlink_config.gateway_id);
     if(p_msg->gateway_sn != downlink_config.gateway_id) return;
     printf("sn right\r\n");
     if(p_msg->prara==1){

         g_readCmd83.nodeCur = 0;
         g_readCmd83.portCur = 0;
         num = downlink_config.collect_num;
         for(i = 0; i<num; i++) {
           // downlink_config.collect_conf[i].tax_conf[0].alrd_sn = 0;
           // downlink_config.collect_conf[i].tax_conf[1].alrd_sn = 0;
             nodeConf.taxconf[i].port[0].alrd_sn = 0;
             nodeConf.taxconf[i].port[1].alrd_sn = 0;
         }
         g_readCmd83.stauts[0] = 0;
         g_readCmd83.stauts[1] = 0;
         g_runData.bfirstRead0x83 = 1;
     }
     else {
         printf("param = 2\r\n");
         en_queue_cmd83(&g_cmdInfo83,p_msg->coll_sn,p_msg->prara,p_msg->taxNo,1);
         g_cmdInfo83.bread83 = 1;
     }
}
/*--------------------------------------------------------------
 *  解析网络下发的 系统类（0x01)的 0x1002指令 连接器版本同步
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1002(uint8_t *data,uint16_t size)
{
    uint32_t sn = 0;

    sn = *((uint32_t*)data);

    if(sn != downlink_config.gateway_id) return;

    gateway_send_update_collect_up_collect(&sys_net,data+4,size-4-2); // data+4因为 前面4个字节为SN，后面的数据可以直接传
}
/*--------------------------------------------------------------
 *  解析网络下发的 系统类（0x01)的 0x1003指令 切换mqtt服务器
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1003(uint8_t *data,uint16_t size)
{
    uint8_t len = 0;
    downlinkSysCmd0x1003 *msg = NULL;

    msg = (downlinkSysCmd0x1003*)data;

    if(msg->gateway_sn != downlink_config.gateway_id) return;
   // if(msg->targettype != GATEWAY_DEVICE_TYPE) return;

    memset(&(g_mqttRunDa.mqttMsg),0,sizeof(MqttIdPort));

    memcpy(g_mqttRunDa.mqttMsg.ip,msg->str,msg->iplen);
    len = msg->iplen;
    memcpy(g_mqttRunDa.mqttMsg.port,msg->str+len,msg->portlen);
    len += msg->portlen;
    memcpy(g_mqttRunDa.mqttMsg.admin,msg->str+len,msg->userlen);
    len += msg->userlen;
    memcpy(g_mqttRunDa.mqttMsg.password,msg->str+len,msg->pwdlen);

    g_mqttRunDa.mqttIdlen = msg->iplen;
    g_mqttRunDa.mqttPortlen = msg->portlen;
    g_mqttRunDa.mqttUserlen = msg->userlen;
    g_mqttRunDa.mqttPwdlen = msg->pwdlen;

    close_tcp_mqtt();
    g_mqttRunDa.bChangeMqtt = 1;
    air.State.MQTT_State= 0;
    g_data4G.flag = 0;
    timeout_stop(&g_usmTimeOut);
    //g_mqttRunDa.bChangeSuc = 0;
    g_mqttRunDa.connectNum = 0;
    g_runData.cregStatus = 0;


}

/*--------------------------------------------------------------
 *  1019 配置的第一步
 *  确定采集器的个数以及SN ，（即确定采集器的路由表）
 * -------------------------------------------------------------*/
int init_collect_table(void *data,uint8_t step)
{
    int ret=-1;
    int i,j,k;
    downlink0x1019_01 *p_msg = NULL;
    uint16_t flag = 0x01;


    p_msg = (downlink0x1019_01 *)data;


   // printf("\r\n 0x1011 recv config = %d, eppromconfig = %d\r\n",p_msg->configNo,g_firmwareMsg.gatewayMsg.configmsg.configNo);
    g_runData.bReadData = 0;
    downlink_config.collect_num = p_msg->collect_num;
    g_firmwareMsg.gatewayMsg.configmsg.coll_num = p_msg->collect_num;
    g_encoderDa.bhaveEncoder = p_msg->bencoder;
    if(p_msg->collect_num > COLLECT_MAX_NUM) //采集器个数大于最大值，数据错误，直接返回
        return ret;

    for(i=0;i<p_msg->collect_num;i++){
        downlink_config.collect_conf[i].collect_no = p_msg->cfigMsg[i].collectSn;
        g_firmwareMsg.collMsg[i].device_sn = p_msg->cfigMsg[i].collectSn;
        downlink_config.collect_conf[i].collect_status = 0;
        downlink_config.collect_conf[i].tax_num = 2;
        for(j=0;j<2;j++){
            downlink_config.collect_conf[i].tax_conf[j].tax_id = j+1;
            downlink_config.collect_conf[i].tax_conf[j].gun_num = 0;
            downlink_config.collect_conf[i].tax_conf[j].encryption = p_msg->cfigMsg[i].comEncrypt[j];
            for(k=0;k<8;k++){
                downlink_config.collect_conf[i].tax_conf[j].gunid[k] = k+1;
            }
        }
    }

    downlink_config_init(1,flag,step);
  //  g_xspDa.xspcfig.configStep = step;
		
		return 0;
}

/* 更新编码器的表 */
static void update_encoder_table_step_04(uint8_t *index,uint8_t *data,uint8_t step)
{
    volatile uint8_t i=0,j=0;
//    int ret = -1;
//    uint8_t priceid = 0;
    downlink0x1019_04 *p_msg = NULL;

    p_msg = (downlink0x1019_04*)data;
    printf("groutno = %d",p_msg->groupNo);
    if(step == CONFIG_STEP_04){ //
        for(i=0;i<p_msg->groupNo;i++){
            g_encodeOpt.tableDa[*index].da.dcollId = p_msg->da[i].daColl;
            g_encodeOpt.tableDa[*index].da.dportId = p_msg->da[i].daPort;
            g_encodeOpt.tableDa[*index].da.dgunId  = p_msg->da[i].daGun;
            g_encodeOpt.tableDa[*index].da.bcollId = p_msg->da[i].busColl;
            g_encodeOpt.tableDa[*index].da.bportId = p_msg->da[i].busPort;
            g_encodeOpt.tableDa[*index].da.bgunId  = p_msg->da[i].busGun;
            (*index)++;
            printf("dcoll = %d, dprot = %d, dgun = %d, bcoll = %d, bprot = %d, bgun = %d\r\n",\
                   g_encodeOpt.tableDa[i].da.dcollId,g_encodeOpt.tableDa[i].da.dportId,g_encodeOpt.tableDa[i].da.dgunId,\
                   g_encodeOpt.tableDa[i].da.bcollId,g_encodeOpt.tableDa[i].da.bportId,g_encodeOpt.tableDa[i].da.bgunId);
        }
    }
   /* else if(step == CONFIG_STEP_03){ // 第三步，更新显示屏表
        for(i=0;i<p_msg->groupNo;i++){
            if(*index == 0){
                g_xspDa.xspDa[*index].configDa.xspmsg.xsp_sn = p_msg->_xspMsg[i].xsp_sn;
                g_xspDa.xspDa[*index].configDa.xspmsg.cbusId = p_msg->_xspMsg[i].cbusId;
                g_xspDa.xspDa[*index].configDa.xspmsg.cdaId = p_msg->_xspMsg[i].cdaId;
                g_xspDa.xspDa[*index].configDa.xspmsg.portid = p_msg->_xspMsg[i].portid;
                priceid = p_msg->_xspMsg[i].priceid;
                g_xspDa.xspDa[*index].configDa.xspmsg.gunid[priceid] = p_msg->_xspMsg[i].gunid;
               // g_xspDa.xspDa[*index].configDa.xspmsg.gunPri[0].priceid = p_msg->_xspMsg[i].priceid;
                g_xspDa.xspDa[*index].configDa.priceNum = 1;
                (*index)++;
            }
            else {
                ret = check_xsp_table_repeat_sn(*index,p_msg->_xspMsg[i].xsp_sn);
                if(ret == -1){ // 显示屏的SN没有重复的
                    g_xspDa.xspDa[*index].configDa.xspmsg.xsp_sn = p_msg->_xspMsg[i].xsp_sn;
                    g_xspDa.xspDa[*index].configDa.xspmsg.cbusId = p_msg->_xspMsg[i].cbusId;
                    g_xspDa.xspDa[*index].configDa.xspmsg.cdaId = p_msg->_xspMsg[i].cdaId;
                    g_xspDa.xspDa[*index].configDa.xspmsg.portid = p_msg->_xspMsg[i].portid;
                    priceid = p_msg->_xspMsg[i].priceid;
                    g_xspDa.xspDa[*index].configDa.xspmsg.gunid[priceid] = p_msg->_xspMsg[i].gunid;
                    g_xspDa.xspDa[*index].configDa.priceNum = 1;
                    (*index)++;
                }
                else { // 显示屏的SN有重复的，处理单价屏
                    j = g_xspDa.xspDa[ret].configDa.priceNum;
                    priceid = p_msg->_xspMsg[i].priceid;
                    g_xspDa.xspDa[ret].configDa.xspmsg.gunid[priceid] = p_msg->_xspMsg[i].gunid;
                    g_xspDa.xspDa[*index].configDa.priceNum++;
                }
            }
        }
    }*/
}
void init_encoder_table_step_04(uint8_t *data,uint8_t step)
{
    static uint8_t groupId = 0;
    downlink0x1019_04 *p_msg = NULL;
    uint8_t sendbuff[256] = {0},sendlen = 0;

    p_msg = (downlink0x1019_04 *)data;

    if(p_msg->frame_no==0xFF){ /* 表示单帧 */
        if(step == CONFIG_STEP_04){ // 单帧第一步时要清零
            memset(&g_encodeOpt,0,sizeof(encodeMsg));
        }

        groupId = 0;
        update_encoder_table_step_04(&groupId,data,step);
        g_encodeOpt.encodenum = groupId; // 编码器的个数

    }
    else if((p_msg->frame_no&0x80) == 0x80) {/* 为多帧且为第一帧 */
        memset(&g_encodeOpt,0,sizeof(encodeMsg));
        groupId = 0;
        update_encoder_table_step_04(&groupId,data,step);
    }
    else if((p_msg->frame_no&0x0F) != 0x01) { /* 多帧的后续帧 */
        update_encoder_table_step_04(&groupId,data,step);
    }
    else { /* 多帧的最后一帧 */
        update_encoder_table_step_04(&groupId,data,step);
        g_encodeOpt.encodenum = groupId; // 显示屏的个数
    }
    if((p_msg->frame_no==0xFF) || (p_msg->frame_no&0x01) == 0x01){ //单帧或是最后一帧
        if(step == CONFIG_STEP_04) {
            gateway_collect_init();
            fram_write_encoder_configMsg();
            fram_write_encoder_msg();

            if(g_encodeOpt.encodenum!=0) {
                g_firmwareMsg.gatewayMsg.configmsg.bInitMsg.bInit.benable_qei = 1;
                g_encodeOpt.benable = 1;
                fram_write_config_msg(0);

                encoder_printf();
                uplink_tax_statusmcmd_0x2002(sendbuff,&sendlen,DEVICE_GATEWAY,0); //网关的状态信息上报
                tax_net_send(sendbuff,sendlen,FIRST_TYPE_STATUS,COLL_UP_STATUS_CMD2002);

            }

            //downlink_config.config_xsp = (0x11>>4)&0x0F;
            /*gateway_collect_init();
            fram_write_xsp_configMsg();
            fram_write_xsp_msg();
            fram_write_config_msg(0x11);*/
        }
    }

}

void downlink_analyze_system_cmd0x1019(uint8_t *data,uint16_t size)
{
    volatile uint8_t i=0,j=0,k=0,flag=0x11;
//    uint32_t collsn[64];
//    static uint8_t groupId = 0;
    downlinkSyscmd0x1019 *p_msg = NULL;

    p_msg = (downlinkSyscmd0x1019*)data;

    printf("sn = %010u, step = %d\r\n",p_msg->gateway_sn,p_msg->step);
    if(p_msg->gateway_sn != downlink_config.gateway_id){ // 不是发给本网关的消息

        return ;
    }

    if(p_msg->step == CONFIG_STEP_01){
        memset(&downlink_config,0,sizeof(downlink_config));
        g_encodeOpt.encodenum = 0;
        g_encoderDa.bhaveEncoder = p_msg->da.step1.bencoder;
        downlink_config.bInstallFinish = INSTALL_5A;// 安装第一步
        downlink_config.gateway_id = g_firmwareMsg.gatewayMsg.hardwareMsg.gateway_sn;
        printf("\r\n config step 01\r\n");
        init_collect_table((void*)(&p_msg->da.step1),p_msg->step);

        g_firmwareMsg.gatewayMsg.configmsg.bInitMsg.bInit.benable_qei = 0;
        g_encodeOpt.benable = 0;
        fram_write_config_msg(0);
    }
    else if(p_msg->step == CONFIG_STEP_04){ // 配置第四步  编码器路由表初始化
        init_encoder_table_step_04((void*)(&p_msg->da.step4),p_msg->step);
        printf("\r\n confige step 4  encodernum = %d\r\n",g_encodeOpt.encodenum);
    } 
    else if(p_msg->step == CONFIG_STEP_05) { // 配置第五步， 配置编码器使能
        printf("\r\n confige step %d, value = %d\r\n",p_msg->step,p_msg->da.step5.enableTime);
        if(p_msg->da.step5.enableTime == 0xFF){ // 永久使用编码器
            encoder_timer_stop();
            g_encoderDa.bhaveEncoder = 0x01;
            g_firmwareMsg.gatewayMsg.configmsg.bInitMsg.bInit.bConfig_qei = g_encoderDa.bhaveEncoder;
            fram_write_config_msg(0);
        }
        else if(p_msg->da.step5.enableTime == 0x00 ){ // 不使用编码器
            g_encoderDa.bhaveEncoder = 0x00;
            g_firmwareMsg.gatewayMsg.configmsg.bInitMsg.bInit.bConfig_qei = g_encoderDa.bhaveEncoder;
            fram_write_config_msg(0);
        }
        else { // 定时使用编码器,时间为分钟
            g_encoderDa.bhaveEncoder = 0x01;
            encoder_timer_start(p_msg->da.step5.enableTime);
        }
    }
    else if(p_msg->step == CONFIG_STEP_09) { // 配置最后下 即配置完成
        printf("\r\n config step 09\r\n");
        downlink_config.bInstallFinish = 0;//
    }
}

/*--------------------------------------------------------------
 *  配置报税口的枪的个数0x1020
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1020(uint8_t *data,uint16_t size)
{
    uint8_t i = 0;
    downlinkSysCmd0x1020 *p_msg = NULL;

   // return;

    p_msg = (downlinkSysCmd0x1020*)data;

    if(p_msg->gateway_sn != downlink_config.gateway_id){ // 不是发给本网关的消息

        return ;
    }

    for(i=0;i<downlink_config.collect_num;i++){
        if(p_msg->coll_sn==downlink_config.collect_conf[i].collect_no) break;
    }
    if(p_msg->taxNo01 > 0) {
        downlink_config.collect_conf[i].tax_conf[0].gun_num = p_msg->gunNum01;
    }
    if(p_msg->taxNo02 > 0) {
        downlink_config.collect_conf[i].tax_conf[1].gun_num = p_msg->gunNum02;
    }
    fram_write_collect_msg();
    init_gun_status();
}
/*--------------------------------------------------------------
 *  编码器路由表是否启用
 * -------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1022(uint8_t *data)
{
    downlinkSysCmd0x1022 *p_msg = NULL;
    uint8_t sendbuff[256] = {0},sendlen = 0;

     p_msg = (downlinkSysCmd0x1022*)data;
    printf("1022 recve\r\n");
     if((p_msg->gateway_sn == downlink_config.gateway_id) || ( p_msg->gateway_sn==0xFFFFFFFF) ){
            g_firmwareMsg.gatewayMsg.configmsg.bInitMsg.bInit.benable_qei = p_msg->benable;
            g_encodeOpt.benable = p_msg->benable;
            fram_write_config_msg(0);
            printf("msg 1022 config sucess\r\n");

            uplink_tax_statusmcmd_0x2002(sendbuff,&sendlen,DEVICE_GATEWAY,0); //网关的状态信息上报
            tax_net_send(sendbuff,sendlen,FIRST_TYPE_STATUS,COLL_UP_STATUS_CMD2002);
     }
}
/*--------------------------------------------------------------
 *  采集器设备设置 0x1023
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1023(uint8_t *data,uint16_t size)
{

    downlinkSysCmd0x1023 *p_msg = NULL;

    p_msg = (downlinkSysCmd0x1023*)data;

    if(p_msg->gateway_sn != downlink_config.gateway_id) return;
    switch(p_msg->targetType){
    case 0x0101: // 网关
        if(p_msg->sn != downlink_config.gateway_id) break;
        break;
    case 0x0201: case 0x0202:// 采集器
        if(p_msg->cmd == 0x02 )gateway_collect_set_cmd0x5D(0,p_msg->sn,p_msg->targetType,p_msg->cmd);
        g_runData.bfirstSend0x56 = 1;
        break;
    case 0x0301: // 液位仪采集器

        break;
    case 0x0401: // 显示器

        break;
    case 0x0601: // 加密模块
        break;
    }
}
/*--------------------------------------------------------------
 *  读取报税口数据 0x1034
 * --------------------------------------------------------------*/
extern uint64_t g_checkDa[16][2][8];
void downlink_analyze_system_cmd0x1034(uint8_t *data,uint16_t size)
{
    downlinkSysCmd0x1034 *msg = (downlinkSysCmd0x1034*)data;
    uint8_t index,i,j,k;
    printf("rcv msg 01--1034, type=%x\r\n",msg->read_type);
    if(msg->read_type == 0xFF){
        g_runData.bReadMingWenData=5;
        for(i=0;i<downlink_config.collect_num;i++){
            for(j=0;j<2;j++){
                for(k=0;k<8;k++){
                    g_checkDa[i][j][k] = 0;
                }
            }
        }
    }
    else if(msg->read_type == 0x00){
        index = read_collect_index(msg->coll_sn);
        if(index == 0xFF) return;
        nodeConf.taxconf[index].port[msg->taxNo-1].gun[msg->gunNo-1].tsmw_flag = 0;
    }

}
/*--------------------------------------------------------------
 *  系统类(0x01) 密文是否实时读取
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1051(uint8_t *data,uint16_t size)
{
    int ret = 0;
    uint8_t sendbuff[256] = {0}, sendlen = 0;
    downlinkSysCmd0x1051 *pmsg = NULL;

    pmsg = (downlinkSysCmd0x1051*)data;
    if(pmsg->gateway_sn != downlink_config.gateway_id) return;

    ret = read_collect_index(pmsg->coll_sn);
    if(ret == -1) return;
    printf("rcv cmd 1051\r\n");
    downlink_config.collect_conf[ret].tax_conf[pmsg->taxNo-1].encryption = pmsg->benable; // 拓盛密文，但不用50分钟读取一次
    //printf("1051, coll_sn = %010u,tax = %d\r\n",pmsg->coll_sn,pmsg->taxNo)
    fram_write_collect_msg(); // 存储
    uplink_update_systemcmd_0x2051(sendbuff,&sendlen,pmsg->coll_sn,pmsg->taxNo,pmsg->benable); //网关的状态信息上报
    tax_net_send(sendbuff,sendlen,FIRST_TYPE_SYST,GATE_UP_SYS_CMD2051);

    return;
}
/*--------------------------------------------------------------
 *  系统类(0x01) 透传指令（0x1052)
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1052(uint8_t *data,uint16_t size)
{
    int ret = 0;

    downlinkSysCmd0x1052 *pmsg = NULL;

    pmsg = (downlinkSysCmd0x1052*)(data+12);

    if(pmsg->gateway_sn != downlink_config.gateway_id) return;

    ret = read_collect_index(pmsg->coll_sn);
    if(ret == -1) return;
    printf("rcv cmd 1052\r\n");

    g_runData.bNetCmd = 1;
    save_comme_queue(0x01, 0x1052,data,size);

    return;
}

/*--------------------------------------------------------------
 *  系统类(0x01) （0x1053)
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd0x1053(uint8_t *data,uint16_t size)
{
    int ret = 0;

    downlinkSysCmd0x1053 *pmsg = NULL;

    pmsg = (downlinkSysCmd0x1053*)(data+12);

    if(pmsg->firstLevelSn != downlink_config.gateway_id) return;



    printf("rcv cmd 1053\r\n");

    if(pmsg->targetDevType != DEVICE_GATEWAY){
        g_runData.bNetCmd = 1;
        save_comme_queue(0x01, 0x1053,data,size);
    }

    return;
}
/*--------------------------------------------------------------
 *  解析网络下发的 系统类（0x01）的数据
 * --------------------------------------------------------------*/
void downlink_analyze_system_cmd(uint16_t type, uint8_t *data, uint16_t size)
{
    switch(type){
    case COLL_DN_SYS_CMD1011: //系统类 采集路由信息初始化下行
//        downlink_gateway_para(data,size);
        break;
    case COLL_DN_SYS_CMD1012: // 系统类，刷新税控序列号
        downlink_analyze_system_cmd0x1012(data,size);
        break;
    case COLL_DN_SYS_CMD1021: // 系统类，系统重新启动
        downlink_analyze_system_cmd0x1021(data,size);
        break;
    case GATEWAY_DN_SYS_CMD1013: // 系统类，时间轮询间隔
        downlink_analyze_system_cmd0x1013(data);
         break;
    case COLL_DN_SYS_CMD1001: // 升级
        printf(" recive update cmd\r\n");
        gateway_update_proc(data,size);
        break;
    case COLL_DN_SYS_CMD1002: // 连接器版本同步
        downlink_analyze_system_cmd0x1002(data,size);
        break;
    case GATEWAY_DN_SYS_CMD1003: //配置mqtt服务器
        downlink_analyze_system_cmd0x1003(data,size);
        break;
    case COLL_DN_SYS_CMD1016: //lora参数切换
        downlink_analyze_system_cmd0x1016(data,size);
        break;
    case COLL_DN_SYS_CMD1017: // lora参数读取
        downlink_analyze_system_cmd0x1017(data,size);
        break;
    case GATEWAY_DN_SYS_CMD1018: // 手动刷新税控序列号
        downlink_analyze_system_cmd0x1018(data,size);
        break;
    case COLL_DN_SYS_CMD1019: // 系统类，带显示屏或不带显示屏的路由信息初始化下行
        downlink_analyze_system_cmd0x1019(data,size);
        break;
    case COLL_DN_SYS_CMD1020: // 系统类，配置报税口枪的个数
        downlink_analyze_system_cmd0x1020(data,size);
        break;
    case GATEWAY_DN_SYS_CMD1022: // 系统类， 是否启用编码器路由表
        downlink_analyze_system_cmd0x1022(data);
        break;
    case COLL_DN_SYS_CMD1023: // 系统类 采集器设备设置
        downlink_analyze_system_cmd0x1023(data,size);
        break;
    case COLL_DN_SYS_CMD1034: // 系统类，读取报税口数据
        downlink_analyze_system_cmd0x1034(data,size);
        break;
    case GATEWAY_DN_SYS_CMD1051: // 系统类 拓盛密文实时读取
            downlink_analyze_system_cmd0x1051(data,size);
            break;
    case GATEWAY_DN_SYS_CMD1052:// 系统类， 透传指令
        downlink_analyze_system_cmd0x1052(data,size);
        break;
    case GATEWAY_DN_SYS_CMD1053:// 系统类，
        downlink_analyze_system_cmd0x1053(data,size);
        break;
    }
}
/*----------------------------------------------------------------------
 *  解析网络下发的  状态类的信息   固件信息下行指令 0x1001
 * ---------------------------------------------------------------------*/
void downlink_analyze_status_cmd0x1001(uint16_t type, uint8_t *data,uint16_t size)
{
    uint8_t index = 0;
    uint8_t sendBuff[160];
    uint8_t sendLen = 0;

    downlinkStatusCmd0x1001 *pMsg = NULL;

    pMsg = (downlinkStatusCmd0x1001*)data;

    if(pMsg->gateway_sn!=downlink_config.gateway_id) return;
    memset(sendBuff,0,sizeof(sendBuff));
    switch(pMsg->targetType){
    case 0x0101: // 网关
        uplink_tax_statusmcmd_0x2001(sendBuff,&sendLen,pMsg->targetType,0);
        tax_net_send(sendBuff,sendLen,FIRST_TYPE_STATUS,COLL_UP_STATUS_CMD2001);
        break;
    case 0x0201: case 0x0202:// 采集器
        index = read_collect_index(pMsg->sn); //根据采集器的SN号，查找采集器的编号
        g_readCmd58.nodeCur = index;
        g_runData.bRead0x58 = 1;
        g_readCmd58.stauts[0] =( g_readCmd58.stauts[0] &( ~(0x01<<index)));
        g_runData.bServerRead58 = 1;
        break;
    case 0x0301: // 液位仪采集器

        break;
    case 0x0401: // 显示器

        break;
    }
}

/*--------------------------------------------------------------
 *  解析网络下发的状态类（0x02）的数据
 * --------------------------------------------------------------*/
void downlink_analyze_status_cmd(uint16_t type,uint8_t *data, uint16_t size)
{
    switch(type){
    case COLL_DN_STATUS_CMD1001: // 固件信息下行
        downlink_analyze_status_cmd0x1001(type,data,size);
        break;
    }
}

/*--------------------------------------------------------------
 *  异常类数据下行 0x1001
 * --------------------------------------------------------------*/
void downlink_analyze_log_cmd0x1001(uint8_t *data,uint16_t size)
{
    uint8_t sendBuff[256] = {0};
    uint8_t sendLen = 0,i=0,num = 0;
    downlinkLogCmd0x1001 *msg = NULL;

    msg = (downlinkLogCmd0x1001*)data;

    if(msg->gateway_sn!=downlink_config.gateway_id) return;

    num = downlink_config.collect_num;

    i = 0;
    do{
        if(num<=6){
            uplink_tax_log_da(sendBuff,&sendLen,LOG_BASIC_MSG,i,0,0,0,0,num);
            //tax_net_send(sendBuff,sendLen,FIRST_TYPE_LOG,GATEWAY_UP_LOG_CMD2001);
            tax_net_send_log(sendBuff,sendLen);
            i += num;
        }
        else{
            uplink_tax_log_da(sendBuff,&sendLen,LOG_BASIC_MSG,i,0,0,0,0,6);
            //tax_net_send(sendBuff,sendLen,FIRST_TYPE_LOG,GATEWAY_UP_LOG_CMD2001);
            tax_net_send_log(sendBuff,sendLen);
            i += 6;
            num = num-6;
        }
        if(i>=downlink_config.collect_num) break;
    }while(i<downlink_config.collect_num);



    g_logCfigDa.bEnable = msg->bEnable;
    if(msg->bEnable == 1){ // 开启
        g_logCfigDa.settimer = msg->timer*1000; // 单位为秒，要换为毫秒计算
        timeout_setValue(&g_logCfigDa.time,msg->timer*1000);
        timeout_start(&g_logCfigDa.time);
        g_runData.bsendgatewayfirmMsg = 1;
        g_runData.bRead0x58 = 1;
        g_readCmd58.nodeCur = 0;
        g_readCmd58.stauts[0] = 0;
    }
    else { // 关闭
        timeout_stop(&g_logCfigDa.time);
        timeout_stop(&g_logCfigDa.time2);
    }
}
/*--------------------------------------------------------------
 *  异常类数据下行 0x1002 原始数据上传
 *
 * --------------------------------------------------------------*/
void downlink_analyze_log_cmd0x1002(uint8_t *data,uint16_t size)
{
    uint8_t sendBuff[256] = {0};
    uint8_t sendLen = 0,i=0,num = 0;
    downlinkLogCmd0x1002 *msg = NULL;

    msg = (downlinkLogCmd0x1002*)data;

    if(msg->gateway_sn!=downlink_config.gateway_id) return;
    printf ("----1002\r\n");
    num = downlink_config.collect_num;

    i = 0;
    do{
        if(num<=6){
            uplink_tax_log_da(sendBuff,&sendLen,LOG_BASIC_MSG,i,0,0,0,0,num);
            tax_net_send_log(sendBuff,sendLen);
            i += num;
        }
        else{
            uplink_tax_log_da(sendBuff,&sendLen,LOG_BASIC_MSG,i,0,0,0,0,6);
            tax_net_send_log(sendBuff,sendLen);
            i += 6;
            num = num-6;
        }
        if(i>=downlink_config.collect_num) break;
    }while(i<downlink_config.collect_num);


    g_logCfigDa.bEnable = msg->bEnable;

   // g_logCfigDa.status = msg->opentype;
    if(msg->bEnable == 1){ // 开启
        if(msg->opentype==0x01) g_logCfigDa.status = 0x80; // 不指定任何
        else if(msg->opentype == 0x02) g_logCfigDa.status = 0x81;//指定采集器
        else if(msg->opentype == 0x03) g_logCfigDa.status = 0x83; // 指定报税口
        else if(msg->opentype == 0x04) g_logCfigDa.status = 0x87; // 指定到枪
        g_logCfigDa.settimer2 = msg->timer*1000; // 单位为秒，要换为毫秒计算
        g_logCfigDa.collIndex = read_collect_index(msg->collSN);
        g_logCfigDa.taxInddex = msg->taxno;
        g_logCfigDa.gunIndex = msg->gunno;
        timeout_setValue(&g_logCfigDa.time2,msg->timer*1000);
        timeout_start(&g_logCfigDa.time2);
        g_runData.bsendgatewayfirmMsg = 1;
        g_runData.bRead0x58 = 1;
        g_readCmd58.nodeCur = 0;
        g_readCmd58.stauts[0] = 0;
    }
    else { // 关闭
        timeout_stop(&g_logCfigDa.time2);
        timeout_stop(&g_logCfigDa.time);
    }
}

/*--------------------------------------------------------------
 *  解析网络下发的异常类（0x10）的数据
 * --------------------------------------------------------------*/
void downlink_analyze_log_cmd(uint16_t type,uint8_t *data, uint16_t size)
{
    switch(type){
    case GATEWAY_DN_LOG_CMD1001: // 异常类下行
        downlink_analyze_log_cmd0x1001(data,size);
        break;
    case GATEWAY_DN_LOG_CMD1002:
        downlink_analyze_log_cmd0x1002(data,size);
        break;
    }
}


extern uint16_t crc16_get(uint8_t *data, uint8_t size);
int downlink_gateway_analyze(uint8_t *data, uint16_t len)
{
    int ret = 1;
    uint16_t crc,fcrc;
    uint8_t msg_type = 0;
    sverMsgHeader *p_msg = (sverMsgHeader *)data;

    if(p_msg->len > 256)
        return ret;

    crc = _crc16_get(data,p_msg->len+FRAME_HEADER_LEN-2);// len-2);
    fcrc = p_msg->info[p_msg->len-1];
    fcrc = (fcrc<<8)|p_msg->info[p_msg->len-2];
    if(p_msg->frame_header != 0xfefe){printf("rcv net data head error\r\n"); return 0;}
    if(crc != fcrc) {printf("rcv net data crc error\r\n"); return 0;}

    msg_type = p_msg->msgtypeFirst;
    printf("msg_type:%d, cmd=%0x\n",msg_type,p_msg->msgtypeSecd);
    switch(msg_type)
    {
        case FIRST_TYPE_SYST: //0x01
            //downlink_analyze_system_cmd(p_msg->msgtypeSecd,(uint8_t*)p_msg->info,p_msg->len);
            if((p_msg->msgtypeSecd == 0x1052) || (p_msg->msgtypeSecd== 0x1053))
                downlink_analyze_system_cmd(p_msg->msgtypeSecd,data,len);
            else
                downlink_analyze_system_cmd(p_msg->msgtypeSecd,(uint8_t*)p_msg->info,p_msg->len);
            break;
        case FIRST_TYPE_STATUS: // 0x02
            downlink_analyze_status_cmd(p_msg->msgtypeSecd,(uint8_t*)p_msg->info,p_msg->len);
            break;
        case FIRST_TYPE_DATA: // 0x03
            break;
        case FIRST_TYPE_LOG: // 0x10
            downlink_analyze_log_cmd(p_msg->msgtypeSecd,(uint8_t*)p_msg->info,p_msg->len);
            break;
        default:
            break;
    }
    return 0;
}
