#include "net_proc.h"
#include "../ota/ota.h"
#include "me3616.h"
#include "../storage/AT24C128Opt.h"
#include "../network/nettimer.h"
#include "../command/uart_conf.h"

  extern volatile uint32_t TickCounter;

system_network_t	sys_net;
void collect_msg_frame_fill(gateway_collect_com_t *p_msg,uint8_t msg_type,uint16_t len);
#define hextoascii(x)	\
	if((x) < 10) { 	\
		(x) = (x)|0x30;	\
	} else {	\
		(x) = (x)-10 + 'A';\
	}

void NET_IMEI_ICCID_INFO_GET(char *imei, char *iccid)
{
	ME3616	*uplink = sys_net.net_hdl;

	if(uplink) {
		uplink->imei_iccid_get(imei, iccid);
	}
}

extern ME3616  air;
extern ME3616 * AIR_Init(void);
void * uplink_net_init(char *device_id) 
{
    char sub_topic[64] = {0};
    ME3616	*uplink;

//	snprintf(sub_topic, sizeof(sub_topic), "RCC/%s", device_id);
//    snprintf(sub_topic, sizeof(sub_topic), "%s", device_id);
//uplink = ME3616_Init();
    uplink = AIR_Init();
		
    uplink->PowerOn(1);

		
    if(uplink->GetCCID) {
        uplink->GetCCID();	/*获取CCID*/
    } else {
        printf("uplink->GetCCID = %p\r\n", uplink->GetCCID);
    }
    if(uplink->GetIMEI) {
        uplink->GetIMEI();
    } else {
        printf("uplink->GetIMEI = %p\r\n", uplink->GetIMEI);
    }
    uplink->GetCSQ();	/*等待网络*/
//  NVIC_SystemReset();

    sprintf(sub_topic,"%04x-%010u",GATEWAY_DEVICE_TYPE, g_firmwareMsg.gatewayMsg.hardwareMsg.gateway_sn);

    if(g_firmwareMsg.mqttidport.flag ==1){
        if(g_mqttRunDa.bChangeMqtt == 1){
           // uplink->MQTT.SetNet(MQTT_SERVER_IP1, MQTT_SERVER_PORT);
           // uplink->MQTT.Connect("cpyypt", (char*)sub_topic, "1SvTlvm1VCawSzS");

            uplink->MQTT.SetNet(g_mqttRunDa.mqttMsg.ip, g_mqttRunDa.mqttMsg.port);
            uplink->MQTT.Connect(g_mqttRunDa.mqttMsg.admin, (char*)sub_topic, g_mqttRunDa.mqttMsg.password);
            printf("\r\n change, mqttIP:  mqttPort\r\n");//,g_mqttRunDa.mqttMsg.ip,g_mqttRunDa.mqttMsg.port);
            printf("\r\n change, admin:  password\r\n");//,g_mqttRunDa.mqttMsg.admin,g_mqttRunDa.mqttMsg.password);
        }
        else {
            uplink->MQTT.SetNet(g_firmwareMsg.mqttidport.ip, g_firmwareMsg.mqttidport.port);
            uplink->MQTT.Connect(g_firmwareMsg.mqttidport.admin, (char*)sub_topic, g_firmwareMsg.mqttidport.password);
            printf("\r\n Have Init, mqttIP:  mqttPort \r\n");//,g_firmwareMsg.mqttidport.ip,g_firmwareMsg.mqttidport.port);
            printf("\r\n Have Init, admin: password \r\n");//,g_firmwareMsg.mqttidport.admin,g_firmwareMsg.mqttidport.password);
        }
    }
    else
    {
        uplink->MQTT.SetNet(MQTT_SERVER_IP, MQTT_SERVER_PORT);
        uplink->MQTT.Connect("admin", (char*)sub_topic, "houjianwei");
        printf("\r\n NO Init, mqttIP:  mqttPort\r\n");//,MQTT_SERVER_IP,MQTT_SERVER_PORT);
        printf("\r\n No Init, admin: , password\r\n");//,"admin","houjianwei");

    }



    memset(sub_topic,0,sizeof(sub_topic));
    sprintf(sub_topic,"%s%04x/%s",(char*)MQTT_DNLINK_TOPIC_CASE,GATEWAY_DEVICE_TYPE, (char*)"broadcast");
    uplink->MQTT.Sub((char*)sub_topic);

    memset(sub_topic,0,sizeof(sub_topic));
    sprintf(sub_topic,"%s%04x/%010u",(char*)MQTT_DNLINK_TOPIC,GATEWAY_DEVICE_TYPE, g_firmwareMsg.gatewayMsg.hardwareMsg.gateway_sn);
    uplink->MQTT.Sub(sub_topic); // 订阅上行主题

    memcpy(g_firmwareMsg.gatewayMsg.Iccid1,air.State.iccid,20);
    memcpy(g_firmwareMsg.gatewayMsg.Imei,air.State.imei,15);
    return uplink;
}
extern void AIR_CLOSE_TCP();

void close_tcp_mqtt(void)
{
    AIR_CLOSE_TCP();
}

void uplink_net_send(char *buffer, uint32_t len) 
{
	uint32_t i, str_len = 0;//, high, low;
	inner_msg_format_t *p_net_msg = (inner_msg_format_t *)buffer;
	ME3616	*uplink = sys_net.net_hdl;

	if(uplink) {
		memset(sys_net.str, 0, sizeof(sys_net.str));
		//printf("type = %d, len = %d\r\n", p_net_msg->type, len);
#if 0	
		for(i = 0;i < len;i++) {
			high = (buffer[i]>>4)&0xf;		
			low = buffer[i]&0xf;
			hextoascii(high);
			hextoascii(low);		
			str_len += snprintf(sys_net.str + str_len, sizeof(sys_net.str)-str_len, "%x", high);
			str_len += snprintf(sys_net.str + str_len, sizeof(sys_net.str)-str_len, "%x", low);
		}
		//printf("%s, %d\r\n", sys_net.str, strlen(sys_net.str));
		uplink->MQTT.Pub(TOPIC_GET_BY_MSGTYPE(p_net_msg->type), sys_net.str, strlen(sys_net.str)/2);
#else
		for(i = 0;i < len;i++) {
			str_len += snprintf(sys_net.str + str_len, sizeof(sys_net.str)-str_len, "%02x", buffer[i]);
		}	
		//printf("%s, %d\r\n", sys_net.str, strlen(sys_net.str));
                g_data4G.bconnect4G =  uplink->MQTT.Pub(TOPIC_GET_BY_MSGTYPE(p_net_msg->type), sys_net.str, strlen(sys_net.str)/2);
#endif
	}
}

void collect_station_proto_proc(system_network_t *p_sys_net, inner_msg_format_t *p_msg, uint32_t msg_len) 
{
	gb_node_bind_info_t *p_bind = NULL;
	gb_gateway_bind_info_t *p_gw_bind = NULL;
	gb_node_info_t	*p_node = NULL;
	u8 i;

	switch(p_msg->type) {
		case net_msg_type_update:
			break;
		case net_msg_type_reboot:
			p_bind = (gb_node_bind_info_t *)p_msg->info;
			if(gateway_id_cmp(p_bind->gw_device_id)) {
				if(device_type_and_id_cmp(p_bind->device_type, p_bind->device_id)) {
					NVIC_SystemReset();
				}
			}
			break;
		//绑定请求和心跳上行转发
		case net_msg_type_bind_req:
		case net_msg_type_node_echo:
			p_bind = (gb_node_bind_info_t *)p_msg->info;
			if(device_type_and_id_cmp(p_bind->device_type, p_bind->device_id)) {
				if(sys_net.uplink_send) {
					sys_net.uplink_send((char *)p_msg, FRAME_HEADER_LEN + p_msg->len);
				}
			}
			break;
		//接收网关回响及心跳
		case net_msg_type_bind_rsp:
			p_bind = (gb_node_bind_info_t *)p_msg->info;
			if(device_type_and_id_cmp(p_bind->device_type, p_bind->device_id)) {
				gateway_gw_id_flush(p_bind->gw_device_id);
			}
			break;
		case net_msg_type_gw_echo:
			p_gw_bind = (gb_gateway_bind_info_t *)p_msg->info;
			if(gateway_id_cmp(p_gw_bind->gw_device_id)) {
				for(i = 0;i < GB_SUPPORT_MAX_NODE;i++) {
					p_node = &p_gw_bind->node[i];
					if(device_type_and_id_cmp(p_node->device_type, p_node->device_id)) {
						gateway_gw_id_flush(p_gw_bind->gw_device_id);
						break;
					}
				}				
			}
			break;
		default:
			break;
	}
	//printf("collect_station_proto_proc, msg_type = %d, msg_len = %d\r\n", p_msg->type, msg_len);
	//OSTmrStop(&sys_net.net_tmr, OS_OPT_TMR_NONE, NULL, &err);
}

void oiltank_station_proto_proc(system_network_t *p_sys_net, inner_msg_format_t *p_msg, uint32_t msg_len) 
{
	printf("oiltank_station_proto_proc, msg_type = %d, msg_len = %d\r\n", p_msg->type, msg_len);
}

//设置升级标志
uint16_t set_updata_state(uint16_t data)
{
	uint16_t temp_data,ret_data = 0;
	uint16_t temp_h,temp_l;
	temp_data = data;
	temp_h = ((~temp_data)<<8)&0xff00;
	temp_l = temp_data&0x00ff;
	ret_data = temp_h | temp_l;
	return ret_data;
}

//判断升级标志的本体和掩码
uint8_t updata_state_cmp(uint16_t data)
{
	uint8_t ret = 0;
	uint16_t temp_data;
	uint8_t temp_h,temp_l;
	temp_data = data;
	temp_h = (uint8_t)((temp_data&0xff00)>>8);
	temp_l = (uint8_t)(temp_data&0x00ff);
	if((temp_h^temp_l) == 0xff)
	{
		ret = 1;
	}
	return ret;
}

/*------------------------------------------------------------------------
 *  上报服务器的升级状态
 * -----------------------------------------------------------------------*/
void up_to_send_server_update_status(uint16_t targetType, uint32_t sn, uint16_t taskNo,uint8_t updateStatus)
{
    char buff[128] = {0};
    uint8_t bufflen = 0;

    memset(buff,0,sizeof(buff));
    uplink_update_systemcmd_0x2001((uint8_t*)buff,&bufflen,targetType,sn,taskNo,updateStatus);
    tax_net_send((uint8_t*)buff,bufflen,FIRST_TYPE_SYST,COLL_UP_SYS_CMD2001); //向服务器上传数据的完整数据，并通过mqtt发送

    return;
}

extern uint8_t * AIR_HTTP_READ(uint32_t start_addr, uint32_t data_len);
extern void lora_send(char *tx_data, uint32_t tx_len);
/*--------------------------------------------------------------------
 *  升级
 * http://121.89.239.35:8002/chfs/shared/0101/010103001.bin
 * http://121.89.239.35:8002/chfs/shared/0101/A64010001.bin
 * https://oil-public.oss-cn-zhangjiakou.aliyuncs.com/upgrade/apk/20211126/A64010001.bin
 *
 * https://oil-public.oss-cn-zhangjiakou.aliyuncs.com/upgrade/apk/20211129/01013001.bin
 * https://oil-public.oss-cn-zhangjiakou.aliyuncs.com/upgrade/apk/20211129/01013002.bin
 * https://oil-public.oss-cn-zhangjiakou.aliyuncs.com/upgrade/apk/20211211/01013003.bin
 * -------------------------------------------------------------------*/
void gateway_update_proc(uint8_t *data,uint8_t msg_len)
{
    uint32_t start_addr = 0, total_len = 0, remain_len, read_len, total_crc = 0;
    uint8_t *p_content = NULL, i,updateStatus = UPDATE_DOWNLOADFILE_SUCCESS;
	  uint16_t send_data_dr2 = 0;
    int index = 0,len = 0;
    OS_ERR  err;
    char buff[128] = {0};
    const char ch = '.';
    char *ret = NULL;
    uint32_t version = 0;
    uint16_t dd,nn;
    uint8_t ff;
    uint32_t fileVer,addr,filelen,crcVl,fixChar,getcrc;
    downlinkSysCmd0x1001 *p_msg = NULL;
    update_msg_format p_update;

    sverMsgHeader *pHeadmsg;
    OS_MSG_SIZE msg_len_head;

    g_runData.bUpdate = 1;
    g_updateProg.updateProgFrom = UPDATE_PROG_FROM_NET;



    p_msg = (downlinkSysCmd0x1001*)data;
    updateStatus = UPDATE_RECEIVE_UPDATEFLAG; //文件下载 APP3写入成功
    up_to_send_server_update_status(0x0301,downlink_config.gateway_id,p_msg->taskNo,updateStatus);

    while(sys_net.net_q.MsgQ.NbrEntries!=0){
        OSSemPend(&sys_net.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
        pHeadmsg = (sverMsgHeader *)OSQPend(&sys_net.net_q, 0, OS_OPT_PEND_NON_BLOCKING, &msg_len_head, NULL, &err);	/* blocking. */
        OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
        gw_net_send((char *)pHeadmsg, msg_len_head);
        net_queue_mem_free(pHeadmsg);
    }

     BKP_WriteBackupRegister(BKP_DR4, p_msg->taskNo);
//    memset(p_msg->url, 0, sizeof(p_msg->url));
//    snprintf(p_msg->url, sizeof(p_msg->url),
//            "%s","https://oil-public.oss-cn-zhangjiakou.aliyuncs.com/upgrade/apk/20211213/02013001.bin");
    ret = strrchr(p_msg->url, ch)-8;
    sscanf(ret,"%[^.]",buff);
    sscanf(buff,"%08x",&version);
    dd = (version>>16)&0xFFFF; //类型
    ff = (version>>12)&0x0F; //aap类型
    nn = version&0xFFF; // 版本
    if(dd != p_msg->targetType){
        updateStatus = UPDATE_DEVICETYPEERROR;
        goto UPDATE_END;
    }
    if((p_msg->targetType==0x0301)){// 版本对比
        if(g_firmwareMsg.gatewayMsg.verMsg.gate_appVr== version){
            updateStatus = UPDATE_SAMEVERSION;
            goto UPDATE_END;
        }
    }
//    else if(p_msg->targetType==0x0201){
//        if(p_msg->sn!=0xFFFFFFFF){
//            index = read_collect_index(p_msg->sn);
//            if(index== -1){
//                updateStatus = UPDATE_FAILE_NOCOLLECT;
//                goto UPDATE_END;
//            }
//            if(g_firmwareMsg.collMsg[index].appVr == version){
//                updateStatus = UPDATE_SAMEVERSION;
//                goto UPDATE_END;
//            }
//        }
//    }
    g_runData.updateDeviceTyp = p_msg->targetType;
    //提取url文件到对应的升级区
    //len = strlen(p_msg->url);

    g_runData.bUpdate = 1;

    memcpy(buff,p_msg->url,p_msg->urlLen);
    AIR_HTTP_GET(buff ,p_msg->urlLen, &total_len);
    printf("total_len %d\r\n", total_len);
    if(total_len<=2){
       updateStatus = UPDATE_DOWNLOADFILE_FAILED;// 文件下载失败
       goto UPDATE_END;
    }
    else if(total_len>131072){
        updateStatus = UPdATE_FILE_LEN_ERROR;
        goto UPDATE_END;
    }
    g_ledStatus.ledM = LED_M_QUICK;
    Flash_RangeErase(OTA_UPDATE_APP3_FLASH_START_ADDR, OTA_UPDATE_APP3_FLASH_SIZE); // 擦除APP3区

    while(start_addr < total_len) {//每次读取512字节，写入到flash中
        remain_len = total_len - start_addr;
        read_len = (remain_len > 512)?512:remain_len;
        p_content = AIR_HTTP_READ(start_addr, read_len);
        data_dump("Update Data", p_content, read_len);
        Flash_BufferWrite(OTA_UPDATE_APP3_FLASH_START_ADDR + start_addr, (uint32_t *)p_content, read_len);
        start_addr += read_len;
    }

				
     OSTimeDlyHMSM(0, 0, 0, 200, OS_OPT_TIME_DLY, &err);
    crcVl = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-4); //CRC校验
    fixChar = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-8); // 固定字符 WBJW
    fileVer = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-12); // 固件信息
    filelen =  *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-20); // 文件总长度
    addr = *(uint32_t*)(OTA_UPDATE_APP3_FLASH_START_ADDR+total_len-16); // 文件写入的地址

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);
    CRC_ResetDR();
    CRC_CalcBlockCRC((uint32_t*)OTA_UPDATE_APP3_FLASH_START_ADDR, (total_len -4)/4);
    getcrc =  CRC_GetCRC();
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,DISABLE);
    if(getcrc!=crcVl) {
        updateStatus = UPDATE_CRCERROR;
        printf("update file crc error\r\n");// 升级文件crc校验错误
        goto UPDATE_END;
    }
    if(version!=fileVer){
        updateStatus = UPDATE_URL_FILE_TYPE_ERROR;
        goto UPDATE_END;
    }

    printf("^^^^^^^^update file download success\r\n");

    switch(p_msg->targetType){
    case 0x0101: // 网关

        break;
    case 0x0201: // 采集器
       
        break;
    case 0x0301: // 液位仪采集器
        g_firmwareMsg.gatewayMsg.verMsg.gate_appVr3 = version;
        fram_write_gateway_version(); // 将版本号写入到EEPROM中
        fram_write_update_flag(); // 写入升级标志
        send_data_dr2 = set_updata_state(UPDATE_DOWNLOADFILE_SUCCESS);
        BKP_WriteBackupRegister(BKP_DR3, send_data_dr2); // 写入状态码
        send_data_dr2 = set_updata_state(0x81);
        BKP_WriteBackupRegister(BKP_DR2, send_data_dr2); // 写入标志码
        BKP_WriteBackupRegister(BKP_DR5, UP_PROG_FROM_NET); // 升级的来源 0x22 来源来网络服务下发的
        OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err);
        printf("\r\n gateway update ======================\r\n");
        NVIC_SystemReset();//复位//设备重新启动//写升级标志位，然后复位，进入bootloader程序中
        break;
    case 0x0401: // 显示器

        break;
    }
		
		return;
UPDATE_END:
    up_to_send_server_update_status(0x0301,downlink_config.gateway_id,p_msg->taskNo,updateStatus);

    g_runData.bUpdate = 0;
    g_updateProg.updateProgFrom = UPDATE_PROG_NULL;

}
/*--------------------------------------------------------------------------------
 *  升级重传 或是读取升级状态
 * --------------------------------------------------------------------------------*/
void gateway_update_collect_status(void)
{
   
}
/*---------------------------------------------------------------------------------
 *  网关自己升级，重新启动后，自动上报服务器升级的状态
 * ---------------------------------------------------------------------------------*/
void gateway_reset_send_update_status(void)
{
    uint16_t taskNo = 0;

    if((g_runData.bResetUpdate == 1) && (air.State.MQTT_State==1)){
        taskNo = BKP_ReadBackupRegister(BKP_DR4);
        up_to_send_server_update_status(0x0301,downlink_config.gateway_id,taskNo,g_runData.bsendUpdateStatus);

         g_runData.bResetUpdate = 0;
    }
}
/*-------------------------------------------------------------
 *  排序
 * -------------------------------------------------------------*/
void sort(void)
{
    int i = 0;
    int j = 0;
    int tmp = 0;
    int m = g_updateProg.num;

    for (i = 0; i<m - 1; i++)
    {
        for (j = 0; j < m - i - 1; j++)
        {
            if (g_updateProg.sn[j]>g_updateProg.sn[j + 1])
            {
                tmp = g_updateProg.sn[j + 1];
                g_updateProg.sn[j + 1] = g_updateProg.sn[j];
                g_updateProg.sn[j] = tmp;

                tmp = g_updateProg.appVr[j + 1];
                g_updateProg.appVr[j + 1] = g_updateProg.appVr[j];
                g_updateProg.appVr[j] = tmp;

                tmp = g_updateProg.status[j + 1];
                g_updateProg.status[j + 1] = g_updateProg.status[j];
                g_updateProg.status[j] = tmp;
            }
        }
    }
}

/*--------------------------------------------------------------------------------
 *  升级重传 或是读取升级状态 (网关升级网关时用到)
 * --------------------------------------------------------------------------------*/
void gateway_update_gateway_status(void)
{
    uint8_t flag = 0,i=0;
    uint8_t num = 0;
    OS_ERR  err;
    if(g_runData.bUpdate != 2 ) return;
    if(g_runData.updateDeviceTyp!= 0x0301) return;
    if((TickCounter - g_runData.startUpdateTotalTime)< UPDATE_COLLECT_TOTALTIME){
        if((g_runData.repeatUpdateTime!=0) && ((TickCounter - g_runData.repeatUpdateTime) > UPDATE_REPEAT_TIME)){ // 2s内没有收到重传指令
            g_runData.readUpdateStatusTime = TickCounter; // 开始延时5s
            g_runData.repeatUpdateTime = 0;
        }
        if((g_runData.readUpdateStatusTime!=0) && ((TickCounter-g_runData.readUpdateStatusTime)>UPDATE_READSTATUS_TIME_GATEWAY)){
            flag = 1;
            g_runData.readUpdateStatusTime = 0;
        }
    }
    else { // 升级总时间超时
        flag = 1;
    }
    if(flag == 1){ // 读取采集器的升级状态
        g_runData.bUpdate = 0;
        flag = 0;
        //g_runData.bsendUpdateStatus = 2;
        g_ledStatus.ledM = LED_M_LOW;
        g_ledStatus.led16.status = g_ledStatus.collNum;
        g_runData.bUpdateHost = 0;
        printf("\r\n update finish read update status\r\n");
        sort();
        for(i=0;i<g_updateProg.num;i++){
            printf("sn = %010u, appVr = 0x%08x, status = %d\r\n",g_updateProg.sn[i],g_updateProg.appVr[i],g_updateProg.status[i]);
        }
        g_updateProg.updateProgFrom = UPDATE_PROG_NULL;

    }
}

/* -------------------------------------------------------------
 *  网关升级网关
 * -------------------------------------------------------------*/
void gateway_update_gateway_proc(void)
{
	OS_ERR  err;
	
    uint32_t total_len = 0,total_crc = 0;
    uint8_t i = 0;
    update_msg_format p_update;

    g_updateProg.updateProgFrom = UPDATE_PROG_FROM_GATEWAY;
    g_runData.bUpdate = 1;
    total_len = Flash_DatalenRead(OTA_UPDATE_APP1_FLASH_START_ADDR,OTA_UPDATE_APP3_FLASH_SIZE);
    printf("-----------------total_len = %d",total_len);

    p_update.rcv_device_type = 0x0301;// 设备类型
    p_update.rcv_device_id = 0xFFFFFFFF;
    p_update.des_device_type = 0x0301;// 设备类型
    p_update.des_device_id = 0xFFFFFFFF;
    p_update.update_version = g_firmwareMsg.gatewayMsg.verMsg.gate_appVr; // 升级版本号
    g_runData.updateDeviceTyp = 0x0101;
    g_runData.bUpdateHost = 1;
    g_updateProg.num = 0;
    for(i=0;i<64;i++) {
        g_updateProg.sn[i] = 0x00000000;
        g_updateProg.appVr[i] = 0x00000000;
        g_updateProg.status[i] = 0x00000000;
    }
    lora_gw_ota_info_Init(&p_update, total_len, total_crc);
    for(i = 0;i < 5;i++) {
        lora_gw_ota_start(&sys_net);
        OSTimeDlyHMSM(0, 0, 2, 0, OS_OPT_TIME_DLY, &err);
    }
    OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_DLY, &err);
    lora_gw_ota_continues(&sys_net,OTA_UPDATE_APP1_FLASH_START_ADDR);
    g_runData.bUpdate = 2;
    g_runData.startUpdateTotalTime = TickCounter;
    g_runData.repeatUpdateTime = TickCounter;
    g_runData.readUpdateStatusTime = 0;
    printf("\r\n continue update finish \r\n");
//    g_runData.bUpdate = 0;
}
/*-------------------------------------------------------------------------------
 *  升级成功后，主设备 接收升级的状态
 * --------------------------------------------------------------------------------*/
void gateway_update_status_rcv(gateway_collect_com_t *data, uint32_t len)
{
    uint8_t i = 0;
	OS_ERR      err;
    ota_updatestatus_up_t *msg = (ota_updatestatus_up_t *)data->taxinfo.info;

    if(msg->des_device_type == 0x0201) {
        g_runData.repeatUpdateTime = TickCounter;
        g_runData.readUpdateStatusTime = 0;
        printf("^^^^^^^rcv type = %04x  sn = %08x app = %08x, status = %d\r\n",msg->des_device_type, msg->des_device_id,msg->des_device_appVr,msg->status);
        if(g_updateProg.rec0x16 == 0x01){
            // 上报升级成功指令
            g_updateProg.rec0x16 = 0x00;
            g_runData.bUpdate = 0x00;
            OSTmrStop(&g_updateProg.update_total_time, OS_OPT_TMR_NONE, NULL, &err);
        }
        return;
    }
    else if(msg->des_device_type == 0x0101) {
        printf("^^^^^^^rcv sn = %08x app = %08x, status = %d\r\n",msg->des_device_id,msg->des_device_appVr,msg->status);

        for(i=0;i<g_updateProg.num + 1;i++){
            if(g_updateProg.sn[i] == 0x00000000){
                g_updateProg.sn[i] = msg->des_device_id;
                g_updateProg.appVr[i] = msg->des_device_appVr;
                g_updateProg.status[i] = msg->status;
                g_updateProg.num++;
                break;
            }
            else {
                if(g_updateProg.sn[i] == msg->des_device_id) break;
            }
        }

        g_runData.repeatUpdateTime = TickCounter;
        g_runData.readUpdateStatusTime = 0;
    }


}
/*------------------------------------------------------------------------------------
 *  升级成功后， 从设备 上报自己的升级状态
 * -----------------------------------------------------------------------------------*/
void gateway_update_status_send(system_network_t *p_sys_net)
{
    uint16_t data = 0,crc = 0;
    uint32_t a = 0;
    OS_ERR  err;

    gateway_collect_com_t msg;
    ota_updatestatus_up_t *p_ota = (ota_updatestatus_up_t *)msg.taxinfo.info;

    if(g_runData.bUpdateHost == 1 ) return;
    if(g_runData.bResetUpdate ==0 ) return;
    if(g_updateProg.num >=3){
        g_runData.bResetUpdate = 0;
        return;
    }
    if (!(timeout_isOut(&g_updateProg.upStatusOut)))  return;

    p_ota->rcv_device_type = 0x0101;
    p_ota->rcv_device_id = downlink_config.gateway_id;
    p_ota->des_device_type = 0x0101;
    p_ota->des_device_id = downlink_config.gateway_id;
    p_ota->des_device_bootVr = g_firmwareMsg.gatewayMsg.verMsg.gate_bootloaderVr;
    p_ota->des_device_appVr = g_firmwareMsg.gatewayMsg.verMsg.gate_appVr ;
    p_ota->status = g_runData.bsendUpdateStatus;
    p_ota->reserve = 0x00000000;

    collect_msg_frame_fill(&msg, 0x23, sizeof(ota_updatestatus_up_t)+2);

    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;

    if(g_updateProg.num == 0) {
        srand(TickCounter);
        a = rand() % 233+200;
        printf("   a = %d\r\n",a);
        OSTimeDlyHMSM(0, 0, 0, 300+a, OS_OPT_TIME_DLY, &err);
    }

    data_dump("send update status ", (uint8_t *)&msg, msg.len + 12);
    p_sys_net->downlink_send((char *)&msg, GATE_COLL_HEAD_LEN + msg.len);
    g_updateProg.num++; // 发送的次数
   // p_sys_net->workstate = DEV_WORK_STATE_UPDATING;

}
void update_total_timer(void *p_tmr, void *p_arg)
{
    OS_ERR  err;

   g_updateProg.rec0x16 = 0x00;
   g_runData.bUpdate = 0x00;
   printf("rcv 0x16, update timeout\r\n");

   OSTmrStop(&g_updateProg.update_total_time, OS_OPT_TMR_NONE, NULL, &err);

}
/*------------------------------------------------------------------------------------
 *  连接器版本同步
 * -----------------------------------------------------------------------------------*/
void gateway_send_update_collect_up_collect(system_network_t *p_sys_net,uint8_t *data,uint16_t len)
{
    uint16_t crc = 0;
    uint32_t a = 0;
    OS_ERR  err;

    gateway_collect_com_t msg;
    //ota_lineoffupdate_coll_t *p_ota = (ota_lineoffupdate_coll_t *)msg.taxinfo.info;

    g_updateProg.rec0x16 = 0x01;
    g_runData.bUpdate = 0x01;

    memcpy(msg.taxinfo.info,data,len);


    collect_msg_frame_fill(&msg, 0x16, sizeof(ota_lineoffupdate_coll_t)+2);

    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 update status ", (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;

    OSTmrCreate(&g_updateProg.update_total_time, "updateTotal_tmr", UPDATE_TOTAL_PERIOD, UPDATE_TOTAL_PERIOD, OS_OPT_TMR_PERIODIC, update_total_timer, NULL, &err);
    OSTmrStart(&g_updateProg.update_total_time, &err);
    printf("0x16 update total timer start\r\n");
}

void net_queue_insert(char *p_msg, uint32_t msg_len)
{
	OS_ERR      err;
	
	OSSemPend(&sys_net.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
	OS_QPost(&sys_net.net_q, p_msg, msg_len, OS_OPT_POST_FIFO, 0, &err);
	OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
	//printf("net_queue_insert %p %d\r\n", p_msg, msg_len);
}

void * net_queue_mem_calloc(void)
{
	OS_ERR      err;
	void * p_msg = NULL;

	OSSemPend(&sys_net.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
	if((sys_net.workstate == DEV_WORK_STATE_UPDATING)||
		(sys_net.workstate == DEV_WORK_STATE_ONLOOKER)) {
		OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
		return p_msg;
	}
	p_msg = OSMemGet(&sys_net.net_m, &err);
	OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
	return p_msg;
}

void * net_queue_mem_calloc_must(void)
{
	OS_ERR      err;
	void * p_msg = NULL;

	OSSemPend(&sys_net.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
	p_msg = OSMemGet(&sys_net.net_m, &err);
	OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
	return p_msg;
}

int net_queue_mem_free(void * p_msg)
{
	OS_ERR      err;
	
	OSSemPend(&sys_net.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
	OSMemPut(&sys_net.net_m, p_msg, &err);
	OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
	return err;
}
void collect_msg_frame_fill(gateway_collect_com_t *p_msg,uint8_t msg_type,uint16_t len)
{
    p_msg->frame_header = 0xfefe;
    p_msg->type = msg_type;
    p_msg->proto_ver = 0x01;
    p_msg->seq_no = sys_net.seq_no++;
    p_msg->len = len;
    p_msg->secondType = 0;
	
//    CRC_ResetDR();
//    CRC_CalcBlockCRC((uint32_t*)p_msg, GATE_COLL_HEAD_LEN + len);
//    p_msg->fcs = CRC_GetCRC()&0xffff;

    return ;
}
void net_msg_frame_fill(gateway_collect_com_t *p_msg, uint8_t msg_type, uint16_t len)
{
        static uint32_t msg_no = 0;
        uint16_t crc;
        p_msg->frame_header = 0xfefe;
        p_msg->proto_ver = 0x01;
        p_msg->seq_no = msg_no;
        p_msg->type = msg_type;
        p_msg->secondType = 0x00;
        p_msg->len = len+2;// 后面加两个字节的CRC

        crc = _crc16_get((uint8_t *)p_msg,p_msg->len + GATE_COLL_HEAD_LEN -2 );

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

       // data_dump("send repeat updata", (uint8_t *)p_msg, p_msg->len + 12);

        return ;
}

extern volatile  uint32_t TickCounter;
void net_timer_proc(void *p_tmr, void *p_arg)
{
//	inner_msg_format_t *p_msg = NULL;

//	p_msg = (inner_msg_format_t *)net_queue_mem_calloc();
//	p_msg->frame_header = 0xfefe;
//	p_msg->type = net_msg_type_timer;
//	net_queue_insert((char *)p_msg, sizeof(inner_msg_format_t));
//	
//	printf("net_timer_proc %d!!!\r\n", TickCounter);
}

extern void lora_send(char *tx_data, uint32_t tx_len);
void svc_init(u32 dev_type, u32 dev_id)
{
	OS_ERR err;
//	printf("dev_type:%d\n",dev_type);
	switch(dev_type) {
		case DEV_TYPE_COLLECT_STATION:// 采集器
			sys_net.uplink_send = lora_send;
//			tax_init();
			break;
		case DEV_TYPE_OILTANK_STATION: // 油罐车
			sys_net.uplink_send = lora_send; 
//			oiltank_init();
			break;
		case DEV_TYPE_GATEWAY: // 网关设备
			sys_net.net_hdl = uplink_net_init((char*)g_upLinkTopic);
			sys_net.uplink_send = uplink_net_send; //上传数据的函数指针 4G 
      sys_net.downlink_send = lora_send; // 下发数据的函数指针 lora
			break;
		default:
			printf("dev_type = %d error !!!\r\n", dev_type);
			break;
	}
	device_init(dev_type, dev_id);	
}

//void net_msg_recv(void)
//{
//	int len = 0;
//	char *str;
//	char *msg = NULL;
//	inner_msg_format_t *p_msg = NULL;
//	OS_ERR      err;	
//	
//	memset(sys_net.str, 0, sizeof(sys_net.str));	
//	len = Module_Blocking_Read(sys_net.str, 0);
//	if(len) {
//		str = strstr(sys_net.str, "byte,");
//		p_msg = (inner_msg_format_t *)(str + 5);
//		if(str) {
//			/* 接受消息, 发往net_proc模块统一处理 */
//			msg = (char *)net_queue_mem_calloc();	
//			if(msg) {
//				memcpy(msg, p_msg, p_msg->len + FRAME_HEADER_LEN);		
//				OS_QPost(&sys_net.net_q, msg, p_msg->len + FRAME_HEADER_LEN, OS_OPT_POST_FIFO, 0, &err);
//			}

//			data_dump("NET RECB", (uint8_t *)p_msg, p_msg->len + FRAME_HEADER_LEN);
//		}
//	}	
//}

void svc_proc(uint32_t dev_type, uint32_t dev_id)
{
    OS_ERR      err;

    if((downlink_config.gateway_id==0x00000000) || (downlink_config.gateway_id == 0xFFFFFFFF)) return;
    if(g_ptTest.bTestStart == PT_ON ) return;
    dev_type = DEV_TYPE_GATEWAY;
    svc_init(dev_type, dev_id);

    timeout_setValue(&g_timeOut,3*60000); // 十分钟读取一次60*1000*10
    timeout_start(&g_timeOut);
    timeout_setValue(&g_uart4Time,200);//100ms
    timeout_setValue(&g_uart5Time,200);//100ms
    while(1) {

        if(((g_runData.bUpdate!=0) && (g_updateProg.updateProgFrom==UPDATE_PROG_FROM_GATEWAY)) || (g_runData.bResetUpdate==2)) {
               gateway_update_gateway_status();
               gateway_update_status_send(&sys_net);
               goto END_DELAY;
           }

        oiltank_operation(0);
END_DELAY:
        OSTimeDlyHMSM(0, 0, 0, 5, OS_OPT_TIME_DLY, &err);
    }
}

/*******************************/
void net_queue_proc_test(void)
{
    OS_ERR      err;
    sverMsgHeader *p_msg;
    OS_MSG_SIZE msg_len;
    uint8_t type,type1 = 0;

   
    //printf("net_queue_proc 1111\r\n");
    OSSemPend(&sys_net.sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
    p_msg = (sverMsgHeader *)OSQPend(&sys_net.net_q, 0, OS_OPT_PEND_NON_BLOCKING, &msg_len, NULL, &err);	/* blocking. */
    OSSemPost(&sys_net.sem, OS_OPT_POST_ALL, &err);
    type = (p_msg->msgtypeSecd>>8)&0xFF;
    if(p_msg&&msg_len)
    {
        if(type == TAX_UPLINK_TYPE)
        {
            set_led_status(3,1);
            gw_net_send((char *)p_msg, msg_len);	 //向服务器端发送消息
            printf("\r\n mqtt send tax end type = %d, cmd = %x\r\n",p_msg->msgtypeFirst,p_msg->msgtypeSecd);
            set_led_status(3,0);
        }
        else if(type == DOWNLINK_CONFIG_TYPE)
        {
            set_led_status(2,1);
            downlink_gateway_analyze((uint8_t *)p_msg, msg_len); //接收服务器端的消息
            set_led_status(2,0);

        }
        net_queue_mem_free(p_msg);
    }
}
/*******************************/

void net_proc(void)
{
	OS_ERR      err;

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

        OSSemCreate(&sys_net.sem, "net_sem", 1, &err);
        OSQCreate(&sys_net.net_q, "net_queue", 4, &err);//创建网络消息处理队列
        OSMemCreate(&sys_net.net_m, "net_memory", sys_net.memory, 4, 1024, &err);//创建内存管理池

        printf("net_proc finish !!!\r\n");

	while(sys_net.dev_type == 0) {
		sys_net.dev_type = device_type_get(); //
		OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_DLY, &err);
	}
	sys_net.workstate = 0;

	g_runData.bInitNetProc = 1;
	while(1) {

        if(g_ptTest.bTestStart == PT_ON) {
            OSTimeDlyHMSM(0, 0, 0, 5, OS_OPT_TIME_DLY, &err);
            continue;
        }
        if(sys_net.dev_type == DEV_TYPE_GATEWAY)
        {
                if(sys_net.net_hdl) {
                        net_msg_recv1();
                }
        }

        net_queue_proc_test();
        OSTimeDlyHMSM(0, 0, 0, 5, OS_OPT_TIME_DLY, &err);
	}
}

//void net_msg_recv_test(void)
//{
//	int len = 0;
//	char *str;
//	char *msg = NULL;
//	inner_msg_format_t *p_msg = NULL;
//	OS_ERR      err;	
//	
//	memset(sys_net.str, 0, sizeof(sys_net.str));	
//	len = Module_Blocking_Read(sys_net.str, 0);
//	if(len) {
//		str = strstr(sys_net.str, "byte,");
//		p_msg = (inner_msg_format_t *)(str + 5);
//		if(str) {
//			/* 接受消息, 发往net_proc模块统一处理 */
//			msg = (char *)net_queue_mem_calloc();	
//			if(msg) {
//				memcpy(msg, p_msg, p_msg->len + FRAME_HEADER_LEN);		
//				OS_QPost(&sys_net.net_q, msg, p_msg->len + FRAME_HEADER_LEN, OS_OPT_POST_FIFO, 0, &err);
//			}

//			data_dump("NET RECB", (uint8_t *)p_msg, p_msg->len + FRAME_HEADER_LEN);
//		}
//	}	
//}
