#include "main.h"

IAP_Stuct  IAPStuct;

//[INFO] 串口2本次接收229字节报文数据(*4G模组*)：
//[INFO] 
//+MSUB: "/iot/data/down/a284c67982b089f9",175 byte,{"id":"1471561db17870ef","header":"iot.ota.upgrade.post","body":{"crc16":"1f8c","ver":1,"url":"http://iot.futureny.cn/ota/pull/f46bf3544fe6ca73.bin","md5":"f46bf3544fe6ca73"}}

//[INFO] 收到OTA升级指令
//[INFO] 版本号后的数据为:1,"url":"http://iot.futureny.cn/ota/pull/f46bf3544fe6ca73.bin","md5":"f46bf3544fe6ca73"}}

//[INFO] 新的版本号是1
//[INFO] id后的数据为:1471561db17870ef","header":"iot.ota.upgrade.post","body":{"crc16":"1f8c","ver":1,"url":"http://iot.futureny.cn/ota/pull/f46bf3544fe6ca73.bin","md5":"f46bf3544fe6ca73"}}

//[INFO] ErrFlag= 0

//[INFO] 更新代码测试





uint8_t checkId(uint8_t *data){
	uint8_t i;
	char *TempPointer; // 临时指针
	uint8_t  ErrFlag = 0;
	uint16_t Version = 0;
	uint8_t  Err = 0;
	uint8_t verRepeti = 0;
	
	TempPointer = strstr((char *)data, "\"ver\":");
	TempPointer += 6;
	log_info("版本号后的数据为:%s", TempPointer);
	i = 0;
	while ((TempPointer[i] >= '0') && (TempPointer[i] <= '9')){
		Version = (Version * 10) + (TempPointer[i] - '0');
		i++;
	}
	if (TempPointer[i] != ','){
		log_info("版本号解析错误");
		Err = 1;
	}		
	if (Version == MqttInfoStr.iapVer){
		log_info("版本号重复");
		Err = 1;
		verRepeti = 1;
	}else{ // 无误则存储版本号
		MqttInfoStr.iapVer = Version;
		log_info("新的版本号是%d", MqttInfoStr.iapVer);
		eepromWriteData(0, &MqttInfoStr, MQTT_STRUCT_LEN);//将变化的数据写入eeprom
	}
	TempPointer = strstr((char *)data, "\"id\":\"");
	TempPointer += 6; // 找到id的第一个位置
	log_info("id后的数据为:%s", TempPointer);		
	if(verRepeti == 1){
		log_info("****ERR 版本号重复,发送成功指令 ERR****");
		CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.ota.progress.post\\22,\\22body\\22:{\\22id\\22:\\22%.16s\\22,\\22progress\\22:10}}\"\r\n",MqttInfoStr.ClientID,TempPointer);	
		return Err; // 版本号重复或降级退出程序	
	}
	for(i = 0; i < 16; i++){
		if (((TempPointer[i] >= '0') && (TempPointer[i] <= '9')) || ((TempPointer[i] >= 'a') && (TempPointer[i] <= 'z'))){ // 检查是否是字符
			if (MqttInfoStr.iapid[i] == TempPointer[i]){
				ErrFlag++;
			}
		}
		else{ // 不是字符，直接退出
			ErrFlag = 16;
			log_info("id[%d]不是字符,id=%d", i, TempPointer[i]);
			break;
		}
	}
	if (ErrFlag >= 16){ // 如果所有字都相同，直接退出，认为重复发送了升级数据
		Err = 1;
	}
	ErrFlag = 0;
	if (Err == 0){ // 无误,准备存储id
		for (i = 0; i < 16; i++){ // 存储id值
			MqttInfoStr.iapid[i] = TempPointer[i];
			eepromWriteData(0, &MqttInfoStr, MQTT_STRUCT_LEN);//将变化的数据写入eeprom
		}
	}
	return Err;
}


#if 0
void otaUpData(void){
	uint8_t i;
	char NetMessage[512]; // 定义网络数据
	if (GetUpgradePara() == 1)
	{
		i = 0;
		while ((Connce2TCP()) && (i < 200))
		{
			i++;
		}
		if (i < 200)
		{
			if (GetUpgradeFile() == 0)
			{
				Ping_flag = 0; // 要清除Ping_flag标志
				Connect_flag = 0;
				ConnectPack_flag = 0;
				SubcribePack_flag = 0;
				printf("代码升级失败 准备重连\r\n");

				memset(NetMessage, 0, 512 * sizeof(char));																																									   // 清零消息
				sprintf(NetMessage, "AT+MSUB=\"/iot/data/up/%s\",0,0,0,\"{\\\"header\\\":\\\"iot.ota.result.post\\\",\\\"body\\\":{\\\"id\\\":\\\"%.16s\\\",\\\"success\\\":false}}\"\r\n", DEVICEID, IapFlashStuct.iapid); // 构建回复数据
				TxDataBuf_Deal((u8 *)NetMessage, (strlen(NetMessage)));																																						   // 添加数据，发布给服务器
			}
		}
		else
		{
			printf("连接TCP 81端口超时,程序更新失败，准备等待看门狗复位\r\n");
			for (; i > 0; i--)
			{
				printf("%d", i);
				delay_ms(1000);
			}
		}
	}
	else
	{
		Ping_flag = 0; // 要清除Ping_flag标志
		Connect_flag = 0;
		ConnectPack_flag = 0;
		SubcribePack_flag = 0;
		printf("解析指令失败（可能不是Bin文件） 准备重连\r\n");
		memset(NetMessage, 0, 512 * sizeof(char)); // 清零消息
		
		sprintf(NetMessage, "AT+MSUB=\"/iot/data/up/%s\",0,0,0,\"{\\\"header\\\":\\\"iot.ota.result.post\\\",\\\"body\\\":{\\\"id\\\":\\\"%.16s\\\",\\\"success\\\":false}}\"\r\n", DEVICEID, IapFlashStuct.iapid); // 构建回复数据
		TxDataBuf_Deal((u8 *)NetMessage, (strlen(NetMessage)));																																						   // 添加数据，发布给服务器
	}
}



//获取升级文件
u8 GetUpgradeFile()
{
	char TempStr[80];
	uint8_t count = 0;
	u16 i=0;
	u8 UpdataOkFlag = 0;

	log_info("准备获取更新数据\r\n");                 //串口提示数据
	while((count<30)&&(UpdataOkFlag == 0))
	{
		count ++;
		IapStuct.GetBinFlag = 1;//获取Bin文件标志位置1,提示串口接收中断放大其接收数组
		IOT_RxCounter = 0;

		sprintf(TempStr,"GET /ota/pull/%.20s HTTP/1.1\r\nHost: %s:81\r\n\r\n",IapStuct.iapUrl,ServerIP);
		IOT_printf("%s",TempStr);


		
		printf("发送的网络指令是：%s\r\n",TempStr);
		if(!WaitDownLoad(90000000))
		{
			IapStuct.bit2K_Pointer = 2048 - DMA_GetCurrDataCounter(DMA1_Channel6);
			if(IapStuct.bit2K_Pointer != 0)
			{
				Crc = GetCRC(BIN_RX_BUF[IapStuct.bit2K_Select],IapStuct.bit2K_Pointer,Crc);//校验最后一部分CRC

				for(i=0;i<IapStuct.bit2K_Pointer;i++)
				{
					printf("%.2X ",BIN_RX_BUF[IapStuct.bit2K_Select][i]);
				}
				printf("\r\n");
				iap_write_appbin(IapStuct.BinWriteAdd,(u8 *)BIN_RX_BUF[IapStuct.bit2K_Select],IapStuct.bit2K_Pointer);//写入剩下的代码
			}
			if( IapStuct.binLength <= (Bin2KCount*2048+IapStuct.bit2K_Pointer))			
			{//判断是否接收到足够的数据
				Usart2_RxCounter = 0;
				if(Crc == IapStuct.iapCrc)//CRC校验通过
				{
						if(((*(vu32*)(FLASH_APP2_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
						{	 
							IapFlashStuct.iapCount++;//iap计数值++
							IapFlashStuct.iapFlag = 1;//iap升级成功标志位置1
							STMFLASH_Write(IAP_FLASH_ADDR,(u16*)&IapFlashStuct,((((sizeof(struct IAP_FLASH_Stuct))%2) == 0) ? ((sizeof(struct IAP_FLASH_Stuct))/2) : (((sizeof(struct IAP_FLASH_Stuct))/2)+1)));//写入Flash
							UpdataOkFlag = 1;//标记更新成功
							TIM_Cmd(TIM4,ENABLE);//打开定时器4，开始计算ping包时间
							printf("固件更新完成!\r\n");	
							//printf("请实现跳转到BootLoader，再由BootLoader跳转到第二段程序\r\n");
							printf("开始跳转到BootLoader程序!!\r\n");
							if(((*(vu32*)(FLASH_BASE_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
							{	 
								printf("等待看门狗复位系统!!\r\n");
								for(i=0;i<100;i++)//延时100*800ms 等待看门狗复位
								{
									delay_ms(800);
									printf("%d ",i);
								}
							}
							else 
							{
								printf("非FLASH应用程序,无法执行!\r\n");  
							}	
						}					
						else
						{
							printf("固件校验失败\r\n");
							Usart2_RxCounter = 0;
							IapStuct.HttpHeadcount = 0;
							IapStuct.bit2K_Pointer = 0;
							IapStuct.bit2K_Select = 0;
							IapStuct.HttpFlag = 0;
							Bin2KCount = 0;		
							Crc = 0xFFFF;
							IapStuct.BinWriteAdd = 	FLASH_APP2_ADDR;
							USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断	
							memset(BIN_RX_BUF,0,2048*3);							
						}
					
				}
				else
				{
					printf("CRC校验未通过，服务器上传的CRC是%x,由%d字节的数据计算出的CRC值是%x\r\n",IapStuct.iapCrc,(Bin2KCount*2048+IapStuct.bit2K_Pointer),Crc);
					Usart2_RxCounter = 0;
					IapStuct.HttpHeadcount = 0;
					IapStuct.bit2K_Pointer = 0;
					IapStuct.bit2K_Select = 0;
					IapStuct.HttpFlag = 0;
					Bin2KCount = 0;		
					Crc = 0xFFFF;
					IapStuct.BinWriteAdd = 	FLASH_APP2_ADDR;
					USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断
					memset(BIN_RX_BUF,0,2048*3);
				}
			}
			else
			{
				printf("未接收到完整的程序数据,程序长度应该为%dbytes,实际收到数据长度为%dytes\r\n",IapStuct.binLength,(Bin2KCount*2048+IapStuct.bit2K_Pointer));
				Usart2_RxCounter = 0;
				IapStuct.HttpHeadcount = 0;
				IapStuct.bit2K_Pointer = 0;
				IapStuct.bit2K_Select = 0;
				IapStuct.HttpFlag = 0;
				Bin2KCount = 0;		
				Crc = 0xFFFF;
				IapStuct.BinWriteAdd = 	FLASH_APP2_ADDR;
				USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断
				memset(BIN_RX_BUF,0,2048*3);
			}
		}
		else
		{
			printf("等待网络数据包时间过短\r\n");
		}
	}
	return UpdataOkFlag;
}

#endif

