
#include "ota.h"
#include "../network_mgr/sx1268/peripherals/radio/radio.h"
#include "../storage/AT24C128Opt.h"
#include "../toolkit/CH455G.h"
#include "../network_mgr/sx1268/lora.h"
#if 0
typedef struct _ota_retransmit_resp {//重传响应, 同ota_continues_info_t
} ota_retransmit_resp_t;
#endif

uint8_t ota_continuous_end_flag = 0;
uint8_t updata_state = 0;
uint16_t updata_state_save = 0;
uint8_t cad_ch_activitydetected = 0;
timeout_t ota_retransmit_delay;
timeout_t ota_total_timer;
uint8_t  ota_total_timer_start = 0;

device_fixed_info_t device_fixed_info;

ota_pkg_info_t	ota_info;
updata_state_t updata_state_info;

#define OTA_START_INFO_LEN			sizeof(ota_start_info_t)
#define OTA_CONTINUES_INFO_LEN			sizeof(ota_continues_info_t)
#define OTA_RETRNSMIT_INFO_LEN			sizeof(ota_retransmit_req_t)
#define OTA_UPDATE_PAYLAOA_LEN			128


typedef void (*timeout_cb)(void *p_tmr, void *p_arg);
extern void lora_gw_ota_timeout(void *p_tmr, void *p_arg);

extern void collect_msg_frame_fill(gateway_collect_com_t *p_msg,uint8_t msg_type,uint16_t len);
extern void net_msg_frame_fill(gateway_collect_com_t *p_msg, uint8_t msg_type, uint16_t len);


void lora_timer_one_shot(system_network_t *p_sys_net, uint8_t timeout, timeout_cb cb)
{
	OS_ERR      err;
	
	OSTmrCreate(&ota_info.ota_tmr, "ota_timer", timeout, timeout, OS_OPT_TMR_ONE_SHOT, cb, p_sys_net, &err);
	OSTmrStart(&ota_info.ota_tmr, &err);
}

void lora_gw_ota_start(system_network_t *p_sys_net)
{

    uint16_t crc = 0;//, p_crc = 0,len = 0;
    gateway_collect_com_t msg;
    ota_start_info_t *p_ota = (ota_start_info_t *)msg.taxinfo.info;

    p_ota->des_device_type = ota_info.des_device_type;
    p_ota->des_device_id = ota_info.des_device_id;
    p_ota->rcv_device_id = ota_info.rcv_device_id;
    p_ota->rcv_device_type = ota_info.rcv_device_type;
    p_ota->update_version = ota_info.update_version;
    p_ota->update_version = ota_info.update_version;
    p_ota->total_bytes = ota_info.total_bytes;
    p_ota->time = UPDATE_EACH_TIME;

    collect_msg_frame_fill(&msg, net_msg_type_update_start, OTA_START_INFO_LEN+2);

    //len = GATE_COLL_HEAD_LEN + OTA_START_INFO_LEN;
    crc = _crc16_get((uint8_t *)&msg,msg.len + GATE_COLL_HEAD_LEN -2 );

    msg.taxinfo.info[msg.len -2] = crc&0xff;
    msg.taxinfo.info[msg.len - 1] = (crc>>8)&0xff;

    data_dump("send start updata", (uint8_t *)&msg, msg.len + 12);
    p_sys_net->downlink_send((char *)&msg, GATE_COLL_HEAD_LEN + msg.len);
    p_sys_net->workstate = DEV_WORK_STATE_UPDATING;
}

void lora_gw_ota_continues(system_network_t *p_sys_net,uint32_t address)
{
    gateway_collect_com_t msg;
    ota_continues_info_t *p_ota = (ota_continues_info_t *)msg.taxinfo.info;
    OS_ERR  err;
    uint32_t timer = 0;
    uint16_t crc = 0;

    char buff[256] = {0};
    uint16_t i=0;
    printf("lora_gw_ota_continues\r\n");
    p_ota->total_pkgs = ota_info.total_pkgs;
    p_ota->sub_pkg_len = OTA_UPDATE_PAYLAOA_LEN;
    p_ota->des_device_type = ota_info.des_device_type;
    p_ota->des_device_id = ota_info.des_device_id;
    p_ota->rcv_device_id = ota_info.rcv_device_id;
    p_ota->rcv_device_type = ota_info.rcv_device_type;

    timer = RadioTimeOnAir2(MODEM_LORA,140);
    timer = (timer>UPDATE_EACH_TIME) ? timer : UPDATE_EACH_TIME;
    printf("timer = %d\r\n", timer);
    printf("lora_update total_pkgs = %d\r\n",ota_info.total_pkgs);
    while(ota_info.sub_pkg_id <= ota_info.total_pkgs) {
        printf("lora_gw_ota_continues %d\r\n", ota_info.sub_pkg_id);
        p_ota->sub_pkg_id = ota_info.sub_pkg_id++;
        Flash_BufferRead(address + (p_ota->sub_pkg_id - 1)*OTA_UPDATE_PAYLAOA_LEN,
                                                        ((uint8_t *)p_ota) + OTA_CONTINUES_INFO_LEN, OTA_UPDATE_PAYLAOA_LEN);

        collect_msg_frame_fill(&msg, net_msg_type_update_continues, OTA_CONTINUES_INFO_LEN + OTA_UPDATE_PAYLAOA_LEN+2);

        crc = _crc16_get((uint8_t *)&msg,msg.len-2+GATE_COLL_HEAD_LEN);
        msg.taxinfo.info[msg.len-2] = crc&0xff;
        msg.taxinfo.info[msg.len-1] = (crc>>8)&0xff;
       // memcpy(buff,(char*)&msg,msg.len + GATE_COLL_HEAD_LEN);

        memcpy(buff,(char*)&(msg.taxinfo.info[OTA_CONTINUES_INFO_LEN]),128);
        for(i=0;i< msg.len +GATE_COLL_HEAD_LEN;i++){
            printf("%02x ",buff[i]);
        }
        printf("\r\n");
        p_sys_net->downlink_send((char *)&msg, GATE_COLL_HEAD_LEN + msg.len);
        set_led_update_status(ota_info.total_pkgs - ota_info.sub_pkg_id);
        OSTimeDlyHMSM(0, 0, 0, timer, OS_OPT_TIME_DLY, &err);
    }
    p_sys_net->workstate = DEV_WORK_STATE_UPDATE_RETRANSMIT;
    lora_timer_one_shot(p_sys_net, 60, lora_gw_ota_timeout);
}

void lora_gw_ota_retransmit_resp(system_network_t *p_sys_net, ota_retransmit_req_t *p_req,uint32_t address)
{
    char buff[256] = {0};
    uint16_t i=0;
    uint16_t crc = 0;
    gateway_collect_com_t msg;
    ota_continues_info_t *p_ota = (ota_continues_info_t *)msg.taxinfo.info;

    p_ota->total_pkgs = ota_info.total_pkgs;
    p_ota->sub_pkg_id = p_req->repeat_sub_pkg_id;
    p_ota->sub_pkg_len = OTA_UPDATE_PAYLAOA_LEN;
    p_ota->des_device_type =ota_info.des_device_type;
    p_ota->des_device_id = ota_info.des_device_id;
    p_ota->rcv_device_id = ota_info.rcv_device_id;
    p_ota->rcv_device_type = ota_info.rcv_device_type;
    Flash_BufferRead(address + (p_req->repeat_sub_pkg_id - 1)*OTA_UPDATE_PAYLAOA_LEN,
                                                    ((uint8_t *)p_ota) + OTA_CONTINUES_INFO_LEN, OTA_UPDATE_PAYLAOA_LEN);

    collect_msg_frame_fill(&msg, net_msg_type_update_retransmit_rsp, OTA_CONTINUES_INFO_LEN + OTA_UPDATE_PAYLAOA_LEN + 2);

    crc = _crc16_get((uint8_t *)&msg,msg.len-2+GATE_COLL_HEAD_LEN);
    msg.taxinfo.info[msg.len-2] = crc&0xff;
    msg.taxinfo.info[msg.len-1] = (crc>>8)&0xff;
    memcpy(buff,(char*)&msg,msg.len + GATE_COLL_HEAD_LEN);

   // memcpy(buff,(char*)&(msg.taxinfo.info[OTA_CONTINUES_INFO_LEN]),128);
    for(i=0;i< msg.len +GATE_COLL_HEAD_LEN;i++){
        printf("%02x ",buff[i]);
    }
    printf("\r\n");
    p_sys_net->downlink_send((char *)&msg, GATE_COLL_HEAD_LEN + msg.len);
   // p_sys_net->downlink_send((char *)&msg, GATE_COLL_HEAD_LEN + OTA_CONTINUES_INFO_LEN + OTA_UPDATE_PAYLAOA_LEN);
}


void lora_gw_ota_timeout(void *p_tmr, void *p_arg)
{
//	OS_ERR      err;
	system_network_t *p_sys_net = (system_network_t *)p_arg;

	switch(p_sys_net->workstate) {
		case DEV_WORK_STATE_NORMAL:
			break;
		case DEV_WORK_STATE_UPDATING:			
			break;
		case DEV_WORK_STATE_UPDATE_RETRANSMIT:
			p_sys_net->workstate = DEV_WORK_STATE_NORMAL;
			break;
		case DEV_WORK_STATE_ONLOOKER:
			p_sys_net->workstate = DEV_WORK_STATE_NORMAL;
			break;
		default:
			break;
	}	
}

int lora_gw_ota_info_Init(update_msg_format *p_update, uint32_t total_len, uint32_t total_crc)
{
	memset(&ota_info, 0, sizeof(ota_pkg_info_t));
	ota_info.des_device_type = p_update->des_device_type;
	ota_info.des_device_id= p_update->des_device_id;
        ota_info.rcv_device_id = p_update->rcv_device_id;
        ota_info.rcv_device_type = p_update->rcv_device_type;
        //ota_info.update_type = p_update->update_type;
	ota_info.update_version = p_update->update_version;
	ota_info.total_bytes = total_len;
	ota_info.total_crc = total_crc;
	ota_info.total_pkgs = total_len/OTA_UPDATE_PAYLAOA_LEN;
	ota_info.lastRightPkgNum = 1;

	if(total_len%OTA_UPDATE_PAYLAOA_LEN) {
		ota_info.total_pkgs += 1;
	}

	ota_info.sub_pkg_id = 1;

	return 0;
}

int lora_node_ota_info_Init(ota_start_info_t *p_ota)
{
        memset(&ota_info, 0, sizeof(ota_pkg_info_t));
        ota_info.rcv_device_type = p_ota->rcv_device_type;
        ota_info.rcv_device_id = p_ota->rcv_device_id;
        ota_info.des_device_type = p_ota->des_device_type;
        ota_info.des_device_id = p_ota->des_device_id;

        ota_info.update_version = p_ota->update_version;
        ota_info.total_bytes = p_ota->total_bytes;

        ota_info.total_pkgs = p_ota->total_bytes/OTA_UPDATE_PAYLAOA_LEN;
        ota_info.lossPkgIndex = 0;
        ota_info.lastRightPkgNum = 1;
        if(p_ota->total_bytes%OTA_UPDATE_PAYLAOA_LEN) {
                ota_info.total_pkgs += 1;
        }
        ota_info.lossPkgCounter = 0;
        ota_info.sub_pkg_id = 1;

        ota_info.Send_interval = p_ota->time;

        return 0;
}
void lora_gw_ota_proc(system_network_t *p_sys_net, gateway_collect_com_t *p_msg)
{
    ota_retransmit_req_t *p_req = NULL;

    uint32_t address = OTA_UPDATE_APP3_FLASH_START_ADDR;
    //if(p_sys_net->dev_type != DEV_TYPE_GATEWAY) {
    //	return;
    //}
    p_req = (ota_retransmit_req_t *)p_msg->taxinfo.info;

    if((p_req->rcv_devict_type&0x0200) == 0x0200) address = OTA_UPDATE_APP3_FLASH_START_ADDR;
    else if(p_req->rcv_devict_type == 0x0101)address = OTA_UPDATE_APP1_FLASH_START_ADDR;

    printf("retransmit add = 0x%08x\r\n",address);

    switch(p_msg->type) {
    case net_msg_type_update_retransmit_req:

        set_led_update_status(p_req->repeat_sub_pkg_id);
        lora_gw_ota_retransmit_resp(p_sys_net, p_req,address);
        break;
    case net_msg_type_update_status:
        break;
    default:
        break;
    }
}

//旁观者定时器
void ota_timer_onlooker_one_shot(uint16_t timeout, timeout_cb cb)
{
        OS_ERR      err;

        OSTmrCreate(&ota_info.ota_onlooker_tmr, "ota_timer_onlooker", timeout, timeout, OS_OPT_TMR_ONE_SHOT, cb, NULL, &err);
        OSTmrStart(&ota_info.ota_onlooker_tmr, &err);
        //升级指示灯
        //ota_start_led_init(); gch
        //Led_Single_State_Set(UPDATA_ONLOOKER_LED,LED_ON); gch
        //Data_last4bit_led(0xff,1); gch
        set_led_update_status(0);

}

void ota_timeout_onlooker(void *p_tmr, void *p_arg)
{
        OS_ERR      err;

//        if(device_info.alrd == DEVICE_ALRD)//已初始化
//        {
                device_fixed_info.Work_State = DEV_WORK_STATE_NORMAL;
//        }
//        else
//        {
//                device_fixed_info.Work_State = DEV_WORK_STATE_UNINIT;
//                //未初始化时，将设备sn置为0xffffffff；设备类型是默认的
//                device_info.device_id = 0xffffffff;
//                device_info.device_type = (SOFTWARE_VERSION_APP&0xffff0000)>>16;
//        }

        OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err);
        OSTmrStop(&ota_info.ota_retransmit_tmr, OS_OPT_TMR_NONE, NULL, &err);

        ota_total_timer_start = 0;//关闭升级总定时器
        printf("onlooker timeout \n");
        g_runData.bUpdate = 0;
        g_updateProg.rec0x16 = 0x00;
        //升级指示灯
     //   LED_OFF_ALL();
//	Data_lastNbit_led(SOFTWARE_VERSION_APP,2,1);//APP版本后2位常亮
}
/* 重传定时器 */
void ota_timer_retransmit_one_shot(uint16_t timeout, timeout_cb cb)
{
        OS_ERR      err;

        OSTmrCreate(&ota_info.ota_retransmit_tmr, "ota_timer_retransmit", timeout, timeout, OS_OPT_TMR_ONE_SHOT, cb, NULL, &err);
        OSTmrStart(&ota_info.ota_retransmit_tmr, &err);
}
void ota_timeout_retransmit(void *p_tmr, void *p_arg)
{
        device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
        ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //′ò?a??1????¨ê±?÷

        updata_state = RETRANSMIT_TIMEOUT;
        updata_state_save = set_updata_state(updata_state);
        BKP_WriteBackupRegister(BKP_DR3, updata_state_save);

        printf("retransmit timeout \n");
}

//连续接收定时器
void ota_timer_continuous_one_shot(uint16_t timeout, timeout_cb cb)
{
        OS_ERR      err;

        OSTmrCreate(&ota_info.ota_continuous_tmr, "ota_timer_continuous", timeout, timeout, OS_OPT_TMR_ONE_SHOT, cb, NULL, &err);
        OSTmrStart(&ota_info.ota_continuous_tmr, &err);
}



void ota_timeout_continuous(void *p_tmr, void *p_arg)
{
        uint16_t i;
        switch(device_fixed_info.Work_State)
        {
                case DEV_WORK_STATE_OTA_BEGIN:
                        device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                        ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                        updata_state = PACKET_LOSS_MORE;
                        updata_state_save = set_updata_state(updata_state);
                        BKP_WriteBackupRegister(BKP_DR3, updata_state_save);
                break;
                case DEV_WORK_STATE_OTA_CONTINUOUS:
                        //更新收包相关状态
                        for(i = ota_info.lastRightPkgNum;i < ota_info.total_pkgs+1;i++) {
                                ota_info.lossPkgCounter++;
                                ota_info.lossPkgId[ota_info.lossPkgIndex++] = i;//+1因为子包编号从0开始，
                                //丢包太多了，超过了MAX_LOSS_PKG_COUNT，结束本次升级。
                                if(ota_info.lossPkgCounter == MAX_LOSS_PKG_COUNT) {//降为旁观者, 放弃本次升级
                                        device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                                        ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                                        updata_state = PACKET_LOSS_MORE;
                                        updata_state_save = set_updata_state(updata_state);
                                        BKP_WriteBackupRegister(BKP_DR3, updata_state_save);
                                        return;
                                }
                        }

                        if(ota_info.lossPkgCounter == 0) //没有丢包
                        {
                                ota_continuous_end_flag = OTA_CONTINUOUS_DIRECT;
                                device_fixed_info.Work_State = DEV_WORK_STATE_OTA_UPGRADE_RCV_END;
                                printf("check begin\n");
                        }
                        else //有丢包
                        {
                                //进入连续接收完成任务处理函数
                                ota_continuous_end_flag = OTA_CONTINUOUS_DIRECT;
                                device_fixed_info.Work_State = DEV_WORK_STATE_OTA_RETRANSMIT;
                                ota_timer_retransmit_one_shot(RETRANSMIT_TIMEOUT_TIME,ota_timeout_retransmit);  //打开重传定时器
                                printf("retransmit begin\n");
                        }

                break;
                default:
                        break;
        }

        printf("continuous timeout \n");
}


//总定时器
void ota_timer_total_one_shot(uint16_t timeout, timeout_cb cb)
{
        OS_ERR      err;

        OSTmrCreate(&ota_info.ota_total_tmr, "ota_timer_total", timeout, timeout, OS_OPT_TMR_ONE_SHOT, cb, NULL, &err);
        OSTmrStart(&ota_info.ota_total_tmr, &err);
}

void ota_timeout_total(void *p_tmr, void *p_arg)
{
        OS_ERR      err;
       // if(device_info.alrd == DEVICE_ALRD)//已初始化
       // {
        //        device_fixed_info.Work_State = DEV_WORK_STATE_NORMAL;
       // }
       // else
        {
                device_fixed_info.Work_State = DEV_WORK_STATE_UNINIT;
                //未初始化时，将设备sn置为0xffffffff；设备类型是默认的
               // device_info.device_id = 0xffffffff; gch
               // device_info.device_type = (SOFTWARE_VERSION_APP&0xffff0000)>>16; gch
        }
        device_fixed_info.Work_State = DEV_WORK_STATE_NORMAL;

        OSTmrStop(&ota_info.ota_onlooker_tmr, OS_OPT_TMR_NONE, NULL, &err);
        OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err);
        OSTmrStop(&ota_info.ota_retransmit_tmr, OS_OPT_TMR_NONE, NULL, &err);

        updata_state = UPDATA_TOTAL_TIMEOUT;
        updata_state_save = set_updata_state(updata_state);
        BKP_WriteBackupRegister(BKP_DR3, updata_state_save);

        g_runData.bUpdate = 0;
        printf("total timeout \n");

        //升级指示灯
  //      LED_OFF_ALL();
//	Data_lastNbit_led(SOFTWARE_VERSION_APP,2,1);//APP版本后2位常亮
}



//升级重传函数
void ota_retransmit_req(uint16_t repeat_sub_pkg_id)
{
        char *p_msg = NULL;
        gateway_collect_com_t msg;
        ota_retransmit_req_t *p_ota = (ota_retransmit_req_t *)msg.taxinfo.info;

        p_ota->rcv_devict_type = ota_info.rcv_device_type;
        p_ota->rcv_device_id = ota_info.rcv_device_id;
        p_ota->repeat_sub_pkg_id = repeat_sub_pkg_id;

        net_msg_frame_fill(&msg, net_msg_type_update_retransmit_req, OTA_RETRNSMIT_INFO_LEN);

        p_msg = (char *)lora_queue_mem_calloc_must();
        if(p_msg) {
                memcpy(p_msg, (char *)&msg, FRAME_HEADER_LEN + OTA_RETRNSMIT_INFO_LEN+2);
                lora_queue_insert((char *)p_msg, FRAME_HEADER_LEN + OTA_RETRNSMIT_INFO_LEN+2);
        }
        else
        {
                lora_queue_mem_free(p_msg);
        }
}

uint16_t OTA_Continuous_Timeout = 0;

//网关下发的升级命令分析
void gateway_lora_ota_proc(gateway_collect_com_t *p_msg)
{
    OS_ERR      err;
    uint32_t i;
    uint32_t remain_pkg = 0;
    ota_start_info_t *p_start = NULL;
    ota_continues_info_t *p_cont = NULL;

    g_runData.bUpdate = 1;

    if(device_fixed_info.Work_State == DEV_WORK_STATE_ONLOOKER)//旁观者模式
    {
        printf("p_msg->type:%x\n",p_msg->type);
        OSTmrStop(&ota_info.ota_onlooker_tmr, OS_OPT_TMR_NONE, NULL, &err);
        ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
    }
    else //非旁观者模式
    {
        switch(p_msg->type)
        {
        case net_msg_type_update_start:  //开始升级指令
            g_runData.bUpdate = 1;

            p_start = (ota_start_info_t *)p_msg->taxinfo.info;
            printf("p_msg->type:%x, work_state=%d\n",p_msg->type,device_fixed_info.Work_State);
            /* 校验当前设备是否为接收对象 */
            if(device_type_and_id_cmp(p_start->rcv_device_type, p_start->rcv_device_id))
            {
                OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭连续接收定时器
                if(device_fixed_info.Work_State == DEV_WORK_STATE_NORMAL || device_fixed_info.Work_State == DEV_WORK_STATE_UNINIT)
                {
                    Flash_RangeErase(OTA_UPDATE_APP3_FLASH_START_ADDR, OTA_UPDATE_APP3_FLASH_SIZE); //擦除app3

                    //打开升级总定时器
                    ota_total_timer_start = 1;
                    ota_total_timer.counter = TickCounter;
                    ota_total_timer.timeout = OTA_TOTAL_TIMEOUT_TIME_TICK;
                    printf("open total timer\n");

                    //收到升级指令
                    updata_state = START_UPDATA;
                    updata_state_save = set_updata_state(updata_state);
                    BKP_WriteBackupRegister(BKP_DR3, updata_state_save);

                    //升级指示灯
                   // ota_start_led_init(); gch
                   // Led_Single_State_Set(UPDATA_SLAVE_LED,LED_ON); gch
                }
                //本设备为接收对象
                device_fixed_info.Work_State = DEV_WORK_STATE_OTA_BEGIN;
                lora_node_ota_info_Init(p_start);

                OTA_Continuous_Timeout = (ota_info.total_pkgs * ota_info.Send_interval)/1000 + CONTINUOUS_TIMEOUT_DELAY_TIME;//连续接收定时时间
                if(OTA_Continuous_Timeout > CONTINUOUS_TIMEOUT_TIME_MUX)//发送时间太长
                {
                    printf("continuous time to long\n");
                    printf("ota continuous time:%d\n",OTA_Continuous_Timeout);

                    device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                    ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                    return;
                }

                ota_timer_continuous_one_shot(OTA_Continuous_Timeout,ota_timeout_continuous);//打开连续接收定时器
                printf("ota_totle_byte:%d, ota_totle_pkg:%d\n",ota_info.total_bytes,ota_info.total_pkgs);
                printf("send interval:%d, continuous time:%d\n",ota_info.Send_interval,OTA_Continuous_Timeout);

            }
            else
            {
                device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
            }
            break;
        case net_msg_type_update_continues: //连续发包指令
            g_runData.bUpdate = 1;
            p_cont = (ota_continues_info_t *)p_msg->taxinfo.info;

            if(device_fixed_info.Work_State == DEV_WORK_STATE_OTA_BEGIN || device_fixed_info.Work_State == DEV_WORK_STATE_OTA_CONTINUOUS)
            {
                if(device_type_and_id_cmp(p_cont->rcv_device_type, p_cont->rcv_device_id)) //是当前设备
                {
                    if(p_cont->sub_pkg_len > OTA_UPDATE_PAYLAOA_LEN)//收到的包长度大于128，收到的数据错误
                        return;
                    if(device_fixed_info.Work_State == DEV_WORK_STATE_OTA_BEGIN)
                    {
                        device_fixed_info.Work_State = DEV_WORK_STATE_OTA_CONTINUOUS;
                    }

                    if(p_cont->total_pkgs == ota_info.total_pkgs)
                    {
                        OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭连续接收定时器

                        printf("update continues: type = 0x%x, id = 0x%x, {%d/%d/%d}\r\n",
                        p_cont->rcv_device_type, p_cont->rcv_device_id,
                        p_cont->total_pkgs, p_cont->sub_pkg_id,ota_info.lossPkgCounter);

                        //接受本包并写入flash的对应位置
                        Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + (p_cont->sub_pkg_id - 1)*OTA_UPDATE_PAYLAOA_LEN,
                                        (uint32_t *)(&(p_msg->taxinfo.info[OTA_CONTINUES_INFO_LEN])), p_cont->sub_pkg_len);

                        //更新收包相关状态
                        for(i = ota_info.lastRightPkgNum;i < p_cont->sub_pkg_id;i++) {
                            ota_info.lossPkgCounter++;
                            ota_info.lossPkgId[ota_info.lossPkgIndex++] = i;//+1因为子包编号从0开始，
                            //丢包太多了，超过了MAX_LOSS_PKG_COUNT，结束本次升级。
                            if(ota_info.lossPkgCounter == MAX_LOSS_PKG_COUNT) {//降为旁观者, 放弃本次升级
                                device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                                ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                                updata_state = PACKET_LOSS_MORE;
                                updata_state_save = set_updata_state(updata_state);
                                BKP_WriteBackupRegister(BKP_DR3, updata_state_save);
                                return;
                            }
                        }
                        ota_info.lastRightPkgNum = p_cont->sub_pkg_id + 1;

                        if(p_cont->sub_pkg_id == ota_info.total_pkgs)//当前是最后一包
                        {
                            if(ota_info.lossPkgCounter == 0) //没有丢包
                            {
                                ota_continuous_end_flag = OTA_CONTINUOUS_DIRECT;
                                device_fixed_info.Work_State = DEV_WORK_STATE_OTA_UPGRADE_RCV_END;
                                printf("check begin\n");
                            }
                            else //有丢包
                            {
                                    //进入连续接收完成任务处理函数
                                ota_retransmit_delay.timeout = OTA_FIRST_DELAYTIME;
                                ota_retransmit_delay.counter = TickCounter;
                                ota_continuous_end_flag = OTA_CONTINUOUS_DELAY;

                                device_fixed_info.Work_State = DEV_WORK_STATE_OTA_RETRANSMIT;
                                ota_timer_retransmit_one_shot(RETRANSMIT_TIMEOUT_TIME,ota_timeout_retransmit);  //打开重传定时器
                                printf("retransmit begin\n");
                            }
                        }
                        else //收到最后一包不再打开连续定时器
                        {
                                //连续接收定时时间
                            OTA_Continuous_Timeout = ((ota_info.total_pkgs-p_cont->sub_pkg_id) * ota_info.Send_interval)/1000 + CONTINUOUS_TIMEOUT_DELAY_TIME;
                            ota_timer_continuous_one_shot(OTA_Continuous_Timeout,ota_timeout_continuous);//打开连续接收定时器
                            printf("send interval:%d, continuous time:%d\n",ota_info.Send_interval,OTA_Continuous_Timeout);
                        }

                        //指示灯显示
                        remain_pkg = ota_info.total_pkgs-p_cont->sub_pkg_id;// gch
                       // Data_last4bit_led(remain_pkg,1); gch
                        set_led_update_status(remain_pkg);

                    }
                }
                else
                {
                    device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                    ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                    OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭连续接收定时器
                }
            }
            else
            {
                device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭连续接收定时器
            }
            break;
        case net_msg_type_update_retransmit_rsp:  //重传发包指令
            g_runData.bUpdate = 1;
            p_cont = (ota_continues_info_t *)p_msg->taxinfo.info;
            if(device_fixed_info.Work_State == DEV_WORK_STATE_OTA_RETRANSMIT)
            {
                OSTmrStop(&ota_info.ota_retransmit_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭重传定时器

                if(device_type_and_id_cmp(p_cont->rcv_device_type, p_cont->rcv_device_id)&&
                (p_cont->total_pkgs == ota_info.total_pkgs))
                {
                    if(p_cont->sub_pkg_len > OTA_UPDATE_PAYLAOA_LEN)//收到的包长度大于128，收到的数据错误
                        return;

                    //判定该包是否为本设备丢的那些包之中的子包
                    for(i = 0;i < ota_info.lossPkgIndex;i++) {
                        if(ota_info.lossPkgId[i] == p_cont->sub_pkg_id) {
                            ota_info.lossPkgCounter--;
                            ota_info.lossPkgId[i] = 0;

                            //接受本包并写入flash的对应位置
                            Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + (p_cont->sub_pkg_id - 1)*OTA_UPDATE_PAYLAOA_LEN,
                            (uint32_t *)(&(p_msg->taxinfo.info[OTA_CONTINUES_INFO_LEN]) ), p_cont->sub_pkg_len);

                            printf("rcv retransmit pkgid:%d\n",p_cont->sub_pkg_id);
                            break;
                        }
                    }
                    if(ota_info.lossPkgCounter == 0) //丢包已收完
                    {
                        ota_continuous_end_flag = OTA_CONTINUOUS_DIRECT;
                        device_fixed_info.Work_State = DEV_WORK_STATE_OTA_UPGRADE_RCV_END;
                    }
                    printf("ota_info.lossPkgCounter = %d, lossPkgId:%d\r\n", ota_info.lossPkgCounter,p_cont->sub_pkg_id);
                    //指示灯显示
                    remain_pkg = ota_info.lossPkgCounter; //gch
                    //Data_last4bit_led(remain_pkg,1); gch
                    set_led_update_status(remain_pkg);
                }
                ota_timer_retransmit_one_shot(RETRANSMIT_TIMEOUT_TIME,ota_timeout_retransmit);  //打开重传定时器
            }
            else
            {
                device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
                ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
                OSTmrStop(&ota_info.ota_continuous_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭连续接收定时器
            }

            break;
        default: break;
        }
    }
}

//连续接收完成任务处理函数
void ota_continuous_end_handle(void)
{
    OS_ERR      err;
    uint32_t crcVl,fixChar,fileVer,filelen;
    uint32_t getcrc;
    uint16_t i;
    switch(device_fixed_info.Work_State)
    {
    case DEV_WORK_STATE_OTA_UPGRADE_RCV_END:

        OSTmrStop(&ota_info.ota_retransmit_tmr, OS_OPT_TMR_NONE, NULL, &err); //关闭重传定时器

        crcVl = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_info.total_bytes-4); //CRC校验
        fixChar = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_info.total_bytes-8); // 固定字符 WBJW
        fileVer = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_info.total_bytes-12); // 固件信息
        filelen =  *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+ota_info.total_bytes-20); // 文件总长度

        printf("read_fixchar:%08x, fixchar:%08x\n",fixChar,0x57424A57);
        if(fixChar != 0x57424A57) //固定字符错误
        {
            device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
            ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
            updata_state = FIXED_CHARACTER_ERROR;
            updata_state_save = set_updata_state(updata_state);
            BKP_WriteBackupRegister(BKP_DR3, updata_state_save);

            printf("fixChar error\r\n");// 升级文件固定字符校验错误
            return;
        }

        printf("read_filever:%08x, device_type:%08x\n",fileVer,0x01013000);
        if((fileVer&0xfffff000) != 0x01013000) //固件信息错误
        {
            device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
            ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
            updata_state = DEVICE_TYPE_ERROR;
            updata_state_save = set_updata_state(updata_state);
            BKP_WriteBackupRegister(BKP_DR3, updata_state_save);
            printf("fileVer error\r\n");// 升级文件固件信息校验错误
            return;
        }

        printf("read_filelen:%08x, total_bytes:%08x\n",filelen,(ota_info.total_bytes-20));
        if(ota_info.total_bytes != (filelen+20))//长度错误
        {
                //
            device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
            ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
            updata_state = UPDATA_PACKAGE_LENGTH_ERROR;
            updata_state_save = set_updata_state(updata_state);
            BKP_WriteBackupRegister(BKP_DR3, updata_state_save);
            printf("filelen error\r\n");// 升级文件长度校验错误
            return;
        }

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);
        CRC_ResetDR();
        CRC_CalcBlockCRC((uint32_t*)OTA_UPDATE_APP3_FLASH_START_ADDR, (ota_info.total_bytes -4)/4);
        getcrc =  CRC_GetCRC();
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,DISABLE);
        printf("read_crc:%x, get_crc:%x\n",crcVl,getcrc);
        if(getcrc!=crcVl) { //校验错误
            printf("update file crc error\r\n");// 升级文件crc校验错误

            device_fixed_info.Work_State = DEV_WORK_STATE_ONLOOKER;
            ota_timer_onlooker_one_shot(ONLOOKER_TIMEOUT_TIME,ota_timeout_onlooker);   //打开旁观者定时器
            updata_state = UPDATA_CRC_ERROR;
            updata_state_save = set_updata_state(updata_state);
            BKP_WriteBackupRegister(BKP_DR3, updata_state_save);

            return;
        }

        printf("收包正确\n");
        updata_state = UPDATA_DATA_SUCCESS;
        updata_state_save = set_updata_state(updata_state);
        BKP_WriteBackupRegister(BKP_DR3, updata_state_save);
        //置升级标志
        updata_state_info.updata_flag = set_updata_state(UPDATA_FLAG);
        BKP_WriteBackupRegister(BKP_DR2, updata_state_info.updata_flag);
        /* 置网关下发的升级状态 */
        BKP_WriteBackupRegister(BKP_DR5, UP_PROG_FROM_GAT); // 升级的来源 0x44 来源来网关下发的

        //存储APP3版本
        //device_version_info.APP3_ver = fileVer;
        //eeprom_write_data(EECFG_APP3_VER0,(uint8_t *)&device_version_info.APP3_ver,4);
        g_firmwareMsg.gatewayMsg.verMsg.gate_appVr3 = fileVer;
        fram_write_gateway_version();
        NVIC_SystemReset();
        break;
    case DEV_WORK_STATE_OTA_RETRANSMIT:
        for(i = 0;i < ota_info.lossPkgIndex;i++) {
            if(ota_info.lossPkgId[i])
            {
                ota_retransmit_req(ota_info.lossPkgId[i]);
                printf("send retransmit pkgid:%d\n",ota_info.lossPkgId[i]);
                break;
            }
        }
        break;
    default:
            break;
    }
}

void ota_process_handle(void)
{
    //连续接收完成延时处理
    if(ota_continuous_end_flag == OTA_CONTINUOUS_DIRECT)
    {
        ota_continuous_end_flag = OTA_CONTINUOUS_CLOSE;
        ota_continuous_end_handle();
    }
    else if(ota_continuous_end_flag == OTA_CONTINUOUS_DELAY)
    {
        if(TickCounter - ota_retransmit_delay.counter >= ota_retransmit_delay.timeout)
        {
            ota_continuous_end_flag = OTA_CONTINUOUS_CLOSE;
            ota_continuous_end_handle();
            //g_runData.bUpdate = 0;
        }
    }

    //升级总定时器计时
    if(ota_total_timer_start)
    {
        if(TickCounter - ota_total_timer.counter >= ota_total_timer.timeout)
        {
            ota_total_timer_start = 0;
            ota_timeout_total(NULL,NULL);
        }
    }
}
