/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    M451
*
* Filename      : uart_dtu.c
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

#include  "includes.h"

#include "drv_dtu.h"
#include "drv_gps.h"

// 运动状态（默认为1，万一加速度计有问题）
volatile uint8_t Motion_Status = 1;

// 初始唤醒次数(快速发送）
#define INITIAL_TRAN_COUNT 6

// 绝对值
#define abs(x) ((x) < 0 ? -(x) : (x))

// GPS上报数据的时间戳，年基数为2010
#define GPS_BASE_YEAR	2010

// Boot-loader地址（在线升级以后重启运行）
#define LDROM_BASE			0x100000ul	// 1M

// GPRS串口接收的循环缓冲
#define DTU_TASKM_DATA_COUNT 200
loopbuff_t DTU_TaskM;
uint8_t DTU_TaskM_Data[sizeof(uint8_t) * (DTU_TASKM_DATA_COUNT + 1)] = {0};

// 最近一条上传数据的采集时间
volatile uint32_t DTU_dataTime = 0;
// 发送成功时间
volatile uint32_t DTU_succTime = 0;

// 这个缓冲区比较大，不放在stack里面
char DTU_gpsData[2][DTU_GPSDATA_SIZE] = {0}; // 扩展内存
char DTU_recvBuff[DTU_RECVBUFF_SIZE] = {0}; // 扩展内存

// 一次请求升级包数据大小
#define UPGRADE_DATA_LEN 1024

// DTU_Task任务和服务器之间的收发缓冲
uint8_t Task_sendBuff[TASK_SENDBUFF_SIZE] = {0}; // 扩展内存

#if UPGRADE_DATA_LEN >= SFLASH_ERASE_SIZE
	#define TASK_RECVBUFF_SIZE	(UPGRADE_DATA_LEN + 32)
#else
	#define TASK_RECVBUFF_SIZE	(SFLASH_ERASE_SIZE)
#endif
uint8_t Task_recvBuff[TASK_RECVBUFF_SIZE] = {0}; // 扩展内存

// 信号量，用于通知执行任务		
SemaphoreHandle_t DTU_semUpgrade = NULL;		

// 用于发送到服务器的数据结构
// 和蓝牙的相应命令一致
#pragma pack(push, 1)

typedef struct
{
	uint16_t	mark;
	unsigned	ver : 7;
	unsigned	trans : 1;
	unsigned	reserved: 8;
	uint16_t	len;
	union
	{
		uint16_t	cmd;
		struct
		{
			uint8_t		err;
			uint8_t		cmd_L;
		};
	};
} bluetooth_recv_t;

typedef bluetooth_recv_t bluetooth_send_t;

typedef struct
{
	unsigned staEPress3 :	2;
	unsigned staETempr1 :	2;
	unsigned staETempr2 :	2;
	unsigned staETempr3 :	2;

	unsigned staDiff :		2;
	unsigned staPress :		2;
	unsigned staEPress1 :	2;
	unsigned staEPress2 :	2;
	
} bluetooth_sensor_t;

typedef struct
{
	unsigned maskStamp :	1;
	unsigned maskEPress1 :	1;
	unsigned maskEPress2 :	1;
	unsigned maskEPress3 :	1;
	unsigned  : 1;
	unsigned maskLowPower : 1;
	unsigned maskAbnormal :	1;
	unsigned maskCharging :	1;
	
	unsigned maskRssi :		1;
	unsigned maskGPS :		1;
	unsigned maskETempr1 :	1;
	unsigned maskETempr2 :	1;
	unsigned maskETempr3 :	1;
	unsigned maskBattery :	1;
	unsigned maskFlow :		1;
	unsigned maskLeak :		1;
} bluetooth_mask_t;

typedef union
{
	struct
	{
		unsigned sec : 6;
		unsigned min : 6;
		unsigned hour_L : 4;
		unsigned hour_H : 1;
		unsigned day : 5;
		unsigned mon : 4;
		unsigned year : 6;
	};
	uint32_t tm;
} bluetooth_timestamp_t;

typedef	union
{
	unsigned long long ll;
	struct
	{
		unsigned long l;
		unsigned long h;
	};
} longlong_mask_t;

typedef struct
{
	union
	{
		struct
		{
			unsigned sateCount : 5;		// gps可见卫星数量
			unsigned posState : 1;		// gps定位状态		（0-GPS未定位，1-GPS已定位）
			unsigned carState : 1;		// 车辆是否启动		（0-车辆未启动，1-车辆已启动）
			unsigned carEvent : 1;		// 车辆启动或停止事件（0-启动状态未改变，1-启动状态已改变）
		};
		uint8_t state;
	};
	bluetooth_timestamp_t 	time;	// 时间戳
	int32_t					latitude;
	int32_t					longitude;
	uint16_t 				speed;
} gps_data_t;

typedef struct	// size = 158
{
	uint32_t	sample_time;	// 采集时间：自启动以来经过的秒数
	data_dtu_t			dtuData;	// size = 36
	data_sample_t		sampleData; // size = 118
} gprs_data_t;

// 升级进度信息（存放在FRAM中，可断点续传）
typedef struct
{
	uint16_t	check;		// 标志，固定为0x55AA
	uint32_t	ver;		// 固件版本
	int32_t		fileSize;	// 固件总字节数
	uint16_t	fileCrc;	// 固件总的crc
	int32_t		offset;		// 本次固件偏移量
	int32_t 	len;		// 本次数据长度
	uint16_t	crc;		// 本记录的crc
} upgrade_info_t;

// 升级包接收记录
typedef struct
{
	uint32_t	ver;		// 固件版本
	int32_t		fileSize;	// 固件总字节数
	uint16_t	fileCrc;	// 固件总的crc
	int32_t		offset;		// 本次固件偏移量
	int32_t 	len;		// 本次数据长度
	uint8_t		data[UPGRADE_DATA_LEN];		// 本次数据
	uint16_t	crc;		// 本次数据的crc
} upgrade_frame_t;

// 升级文件头
typedef struct // size=12
{
	unsigned short check;			// 数据有效标志, 0x55AA表示有效 
	unsigned upgrade_request : 1;	// 升级请求标志，0-无升级，1-有升级
	unsigned upgrade_result : 3;	// 升级失败标志，0-成功，1-失败，其余保留
	unsigned encrypt_flag : 2;		// 加密标志， 0-无加密，其余保留
	unsigned compress_flag : 2;		// 压缩标志， 0-无压缩，1-有压缩，其余保留
	unsigned rerseved1 : 8;			// 保留，必须为0xFF
	
	unsigned long upgrade_length; 	// 升级文件长度
	
	unsigned rerseved2 : 8;			// 保留，必须为0xFF
	unsigned rerseved3 : 8;			// 保留，必须为0xFF
	unsigned short crc;				// 对前面内容的crc校验
} TUpgradeHeader;

#pragma pack(pop)

// 升级包记录
upgrade_info_t upInfo = {0};
// 下载储罐档案记录
upgrade_info_t boxesInfo = {0};
// 储罐档案缓冲区
char boxesBuff[16384 + 1] = {0};

// 计算两个经纬度之间的距离
const double EARTH_RADIUS = 6378.137;
double rad(double d)
{
   return d * PI / 180.0;
}

double GetDistance(int32_t lat1, int32_t lng1, int32_t lat2, int32_t lng2)
{
   double radLat1 = rad(lat1 * 0.000001);
   double radLat2 = rad(lat2 * 0.000001);
   double a = radLat1 - radLat2;
   double b = rad(lng1 * 0.000001) - rad(lng2 * 0.000001);
   double s = 2 * asin(sqrt(pow(sin(a / 2), 2) +
			cos(radLat1) * cos(radLat2) * pow(sin(b / 2), 2)));
   s = s * EARTH_RADIUS;
   return s;
}

// 比较新数据的时间，是否晚于老数据的时间
int32_t GPS_IsLateThan(bluetooth_timestamp_t *pNewTime, bluetooth_timestamp_t *pOldTime)
{
	uint8_t newHour = (pNewTime->hour_H << 4) | pNewTime->hour_L;
	uint8_t oldHour = (pOldTime->hour_H << 4) | pOldTime->hour_L;
	
	if(pNewTime->year > pOldTime->year)
		return TRUE;
	if(pNewTime->year < pOldTime->year)
		return FALSE;
	if(pNewTime->mon > pOldTime->mon)
		return TRUE;
	if(pNewTime->mon < pOldTime->mon)
		return FALSE;
	if(pNewTime->day > pOldTime->day)
		return TRUE;
	if(pNewTime->day < pOldTime->day)
		return FALSE;
	if(newHour > oldHour)
		return TRUE;
	if(newHour < oldHour)
		return FALSE;
	if(pNewTime->min > pOldTime->min)
		return TRUE;
	if(pNewTime->min < pOldTime->min)
		return FALSE;
	
	return pNewTime->sec > pOldTime->sec;
}

// 计算两个时间间隔的秒数
uint32_t GPS_CalcInterval(bluetooth_timestamp_t *pNewTime, bluetooth_timestamp_t *pOldTime)
{
	// 计算从OldYear以来的秒数
	uint32_t newSeconds = Calc_SecondsFromYear(GPS_BASE_YEAR + pOldTime->year, pNewTime->year + GPS_BASE_YEAR, pNewTime->mon, 
		pNewTime->day, (pNewTime->hour_H << 4) | pNewTime->hour_L, pNewTime->min, pNewTime->sec);
	uint32_t oldSeconds = Calc_SecondsFromYear(GPS_BASE_YEAR + pOldTime->year, pOldTime->year + GPS_BASE_YEAR, pOldTime->mon, 
		pOldTime->day, (pOldTime->hour_H << 4) | pOldTime->hour_L, pOldTime->min, pOldTime->sec);
	
	return newSeconds - oldSeconds;
}

// 将采集数据中的传感器状态转换为蓝牙协议中的状态
static uint8_t Bluetooth_ConvertStat(sensor_status_t *pStat)
{
	if(pStat->notConnect)
		return 3;
	if(pStat->overFlow)
		return 1;
	if(pStat->underFlow)
		return 2;
	return 0;
}

// GPS uart
void GPS_IRQHandler(USART_Handle *huart)
{
	uint8_t u8DTU = (uint8_t) huart->Instance->DR;
		
//	printf("%c", u8DTU);
	// 直接处理
	DTU_Task0(u8DTU);	
}

// GSM uart
void GPRS_IRQHandler(USART_Handle *huart)
{
	uint8_t u8DTU = (uint8_t) huart->Instance->DR;
	
	if(DTU_uartPrint)
	{
//		if(u8DTU == '\n')
//			printf("\\n\n");
//		else if(u8DTU == '\r')
//			printf("\\r");
//		else
			printf("%c", u8DTU);
	}
	// 加入缓冲
	LoopBuff_PutItem(&DTU_TaskM, &u8DTU);
}

void DTU_Open()
{
    // 分配扩展内存
//	DTU_gpsData[0] = (char *) SRAM_Alloc(DTU_GPSDATA_SIZE);
//	DTU_gpsData[1] = (char *) SRAM_Alloc(DTU_GPSDATA_SIZE);
//	DTU_recvBuff = (char *) SRAM_Alloc(DTU_RECVBUFF_SIZE);
//	Task_sendBuff = (uint8_t *) SRAM_Alloc(TASK_SENDBUFF_SIZE);
//	Task_recvBuff = (uint8_t *) SRAM_Alloc(TASK_RECVBUFF_SIZE);
	LoopBuff_Create(&DTU_TaskM, sizeof(uint8_t), DTU_TASKM_DATA_COUNT, 0, (uint32_t) DTU_TaskM_Data);

	// 创建信号量
	DTU_semUpgrade = xSemaphoreCreateBinary();
	
	huart1.RxISR = GPRS_IRQHandler;
	huart6.RxISR = GPS_IRQHandler;
  
  SET_BIT(USART1->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
  LL_USART_Enable(USART1);

  /* 打开GPS端口: GPS和Debug共用一个串口，GPS用到输入，DEBUG用到输出 */
  SET_BIT(USART6->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
}

// 任务主体：采集GPS数据
void DTU_Task0(uint8_t c)
{
	static uint16_t RdIdx = 0;
	static uint8_t bufIdx = 0;
	static data_dtu_t sample = {0};
	static int32_t last_latitude, last_longitude;
	static uint8_t gps_flag = 0, motion_count = 0, motionless_count = 0;
	static uint32_t last_time = 0;
	static uint32_t last_gpsTime = 0;
	uint32_t time;

	if(c == '$' || RdIdx >= DTU_GPSDATA_SIZE)
		RdIdx = 0;
	
	if(RdIdx == 0 && c != '$')
		return;

	if(c != '\r' && c != '\n')
		DTU_gpsData[bufIdx][RdIdx++] = c;
	else
	{
		// 收到完整的一行
		DTU_gpsData[bufIdx][RdIdx] = 0;
		RdIdx = 0;
		
		// 解析一行数据
		if(parse_frame(&bufIdx, DTU_gpsData[bufIdx], &sample))
		{
			if(sample.sateCount > 0)
				printf("sateCount:\t%d\n", sample.sateCount);

			if(sample.posState)
			{
				time = Calc_SecondsFromYear(INITIAL_YEAR, sample.sysTime.year + 2000, sample.sysTime.month, 
						sample.sysTime.day, sample.sysTime.hour, sample.sysTime.minute, sample.sysTime.second);

				// 修正时间基准（可显示绝对时间）
				if(RTC_offsetSeconds == 0 && time >= DTU_gpsTime)
				{
					RTC_offsetSeconds = time - DTU_gpsTime;
					// 关联铁电和SFlash的一致性
					CheckFramSFlashValid(DTU_gpsTime);
				}
				// 修正时间基准（可显示绝对时间）
				if(time >= DTU_gpsTime) // 每次成功定位都修正时间
					RTC_offsetSeconds = time - DTU_gpsTime;
				
				if(sample.sateCount >= 4)
				{
					if(time >= last_time + dcBuff.configData.intervalGPS)
					{
						last_time = time;
					
						// 没有硬件加速度计，用软件方式判断
						if(sample.speed <= 3)
						{
							motion_count = 0;
							if(Motion_Status == 1 && ++motionless_count >= 3)
							{
								Motion_Status = 0;
								printf("\nSoft Motion status = 0\n");
							}
						}
						else
						{
							motionless_count = 0;
							if(Motion_Status == 0 && ++motion_count >= 3)
							{
								Motion_Status = 1;
								printf("\nSoft Motion status = 1\n");
							}
						}
					
						printf("Latitude:\t%10.6f\n", sample.latitude * 0.000001);
						printf("Longitude:\t%10.6f\n", sample.longitude * 0.000001);
						printf("Speed:\t\t%d km/h\n", sample.speed);
						printf("GPS time:\t%d-%02d-%02d %02d:%02d:%02d\n", 
							sample.sysTime.year + 2000, sample.sysTime.month, sample.sysTime.day,
							sample.sysTime.hour, sample.sysTime.minute, sample.sysTime.second);

						// 计算和上次定位之间的距离，或者判断运动状态
						if(gps_flag == 1 && (
							!Motion_Status
//						 		|| (sample.speed < 5 && GetDistance(last_latitude, last_longitude, sample.latitude, sample.longitude) < 10)
						))
						{
							printf("\nCalibrate to last position\n");
							sample.latitude = last_latitude;
							sample.longitude = last_longitude;
						}
						else
						{
							gps_flag = 1;
							last_latitude = sample.latitude;
							last_longitude = sample.longitude;
						}

						// 写入全局缓冲
						dcBuff.dtuData.posState = sample.posState;
						dcBuff.dtuData.sateCount = sample.sateCount;
						dcBuff.dtuData.latitude = sample.latitude;
						dcBuff.dtuData.longitude = sample.longitude;
						dcBuff.dtuData.speed = sample.speed;
						dcBuff.dtuData.sysTime = sample.sysTime;
						
						// 每30秒保存一次定位信息，重启有效
						if(time >= last_gpsTime + 30)
						{
							last_gpsTime = time;

							Ext_GPS.sysTime = dcBuff.dtuData.sysTime;
							Ext_GPS.longitude = dcBuff.dtuData.longitude;
							Ext_GPS.latitude = dcBuff.dtuData.latitude;
							Ext_GPS.speed = dcBuff.dtuData.speed;
							Ext_GPS.sateCount = dcBuff.dtuData.sateCount;
							Ext_GPS.posState = dcBuff.dtuData.posState;							
							FRAM_SaveInfo(FRAM_GPS_INFO_BASE, (uint8_t *) &Ext_GPS, sizeof(ext_gps_t));
						}
					}
				}
			}
			// 清除数据
			memset(&sample, 0, sizeof(sample));
		}
	}
}

uint8_t pack_gprs_tran_data(ext_data_t *pGprs, uint8_t is4G)
{
	uint16_t i, j;
	bluetooth_sensor_t *pSensor;
	bluetooth_mask_t   *pMask;
	uint16_t crc;

	rf_app_data_t *pData = (rf_app_data_t *) pGprs->payload;
	static data_sample_t sample;
	
	// TODO: 将精简数据转换成上传数据
	cacl_gprs_tran_data(pGprs, &sample);

	// 打包上报数据（按modbus从机响应的格式）
	memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
	i = 0;
	
	// PSN
	memmove(Task_sendBuff + i, pGprs->oriPSN, 6);
	i += 6;
	// 功能码
	Task_sendBuff[i++] = 0x10;
	// 数据长度：先预设为0，最后再修改，位置为Task_sendBuff[7]
	Task_sendBuff[i++] = 0;
	
	// 当前差压值
	*(uint16_t *) (Task_sendBuff + i) = htons(sample.diff);
	i +=2 ;
	// 容积百分比
	*(uint16_t *) (Task_sendBuff + i) = htons(sample.volumePct);
	i += 2;
	// 当前容积
	*(uint32_t *) (Task_sendBuff + i) = htonl(sample.volume);
	i += 4;
	// 重量
	*(uint32_t *) (Task_sendBuff + i) = htonl(sample.weight);
	i += 4;
	if(pData->Sensor.measure_type == 0) 		// 差压
	{
		// 高度：mmWC
		*(uint16_t *) (Task_sendBuff + i) = htons((uint16_t) (sample.diff * 101.9716213));
	}
	else if(pData->Sensor.measure_type == 2)	// 电容
	{
		// 高度：mm
		*(uint16_t *) (Task_sendBuff + i) = htons((uint16_t) (sample.height));
	}
	i += 2;
	// 压力
	*(uint16_t *) (Task_sendBuff + i) = htons(pData->press);
	i += 2;
	// 温度-调试信息
	*(int16_t *) (Task_sendBuff + i) = htons(is4G ? 3 : 1); // 1-标识为LoRa转发,2-标志为北斗上传，3-标志为4G转发
	i += 2;
	// 液源
	if(pData->Sensor.L_source <= SOURCE_POPO)
		Task_sendBuff[i] = pData->Sensor.L_source;
	i++;
	// 储罐类型
	if(pData->Sensor.bottle_type == BOTTLE_TYPE_STAND)
		Task_sendBuff[i] = 0;
	else if(pData->Sensor.bottle_type == BOTTLE_TYPE_LYING)
		Task_sendBuff[i] = 1;
	else if(pData->Sensor.bottle_type == BOTTLE_TYPE_SPHERICAL)
		Task_sendBuff[i] = 2;
	i++;
	// 故障码
	pSensor = (bluetooth_sensor_t *) (Task_sendBuff + i);
	
	pSensor->staDiff = pData->Sensor.staDiff;
	pSensor->staPress = pData->Sensor.staPress;
	pSensor->staEPress1 = 3;
	pSensor->staEPress2 = 3;
	pSensor->staEPress3 = 3;
	pSensor->staETempr1 = pData->Sensor.staETempr1;
	pSensor->staETempr2 = 3;
	pSensor->staETempr3 = 3;
	i += 2;
	// 传感器状态
	pMask = (bluetooth_mask_t *) (Task_sendBuff + i);
	memset(pMask, 0xFF, 2);
	pMask->maskFlow = 0;
	pMask->maskLowPower = pData->Sensor.bat_low;
	pMask->maskAbnormal = 0;
	pMask->maskCharging = pData->Sensor.charging;
	i += 2;
	
	// 版本号
	Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor;
	// rssi
	Task_sendBuff[i++] = 0;
	if(pMask->maskGPS)
	{
		 // 经度
		*(int32_t *) (Task_sendBuff + i) = htonl(pData->longitude);
		i += 4;
		// 纬度
		*(int32_t *) (Task_sendBuff + i) = htonl(pData->latitude);
		i += 4;
	}
	// 扩展温度
	if(pMask->maskETempr1)
	{
		*(uint16_t *) (Task_sendBuff + i) = htons(pData->tempr);
		i += 2;
	}
	if(pMask->maskETempr2)
	{
		i += 2;
	}
	if(pMask->maskETempr3)
	{
		i += 2;
	}
	
	// 电池信息
	if(pMask->maskBattery)
	{
		// 电量百分比
		*(uint16_t *) (Task_sendBuff + i) = htons(pData->batPct);
		i += 2;
		// 电池内部温度
		i += 2;
		// 电池当前电压
		*(int16_t *) (Task_sendBuff + i) = htons(pData->voltage);
		i += 2;
		// 电池容量
		i += 2;
		// 电池当前容量
		i += 2;
		// 充电电流，电流的符号表示充放电状态
		*(int16_t *) (Task_sendBuff + i) = htons(pData->batCurrent);
		i += 2;
		// 光照强度
		i += 2;
	}
	
	// 流量计
	if(pMask->maskFlow)
	{
		// 天信MODBUS /A1 通信协议 (BCD码）
		// 标况体积总量
		i += 6;
		// 标况流量
		i += 4;
		// 工况流量
		i += 4;
		// 温度
		i += 4;
		// 压力
		i += 4;
	}
	
	// 泄露报警
	if(pMask->maskLeak)
	{
		// 类型
		Task_sendBuff[i++] = LEAK_TYPE_SWITCH | LEAK_TYPE_CURRENT | LEAK_TYPE_MODBUS;
		// 状态、报警浓度
		Task_sendBuff[i++] = 0x80;
	}
	
	if(pMask->maskStamp)
	{
		if(dcBuff.powerInfo.protocolVer.minor == 107)
		{
			*(uint32_t *) (Task_sendBuff + i) = htonl(pData->relative_time + (RTC_offsetSeconds + rf_get_seconds() - pGprs->recvTime));
		}
		// 时间
		i += 4;
		// 年月日
		i += 4;
	}
	
	// 扩展压力
	if(pMask->maskEPress1)
	{
		i += 2;
	}
	if(pMask->maskEPress2)
	{
		i += 2;
	}
	if(pMask->maskEPress3)
	{
		i += 2;
	}
	
	// 硬件版本
//	Task_sendBuff[i++] = ((pData->hardVer / 10) << 4) + pData->hardVer % 10;
	Task_sendBuff[i++] = pData->hardVer;
	// 软件版本
//	Task_sendBuff[i++] = ((pData->softVer / 10) << 4) + pData->softVer % 10;;
	Task_sendBuff[i++] = pData->softVer;
	
	// 真空传感器
	for(j = 0; j < 2; j++)
	{
		// 状态
		*(uint16_t *) (Task_sendBuff + i) = htons(0);
		i += 2;
		// 使用年限
		i += 2;
		// 真空度
		i += 4;
		// 漏放气速率
		i += 4;
	}
	
	// 气瓶容量
	*(uint32_t *) (Task_sendBuff + i) = htonl(Theoretical_Param.v);
	i += 4;
	// 储罐封头直边长
	*(uint16_t *) (Task_sendBuff + i) = htons(0);
	i += 2;
	// 储罐筒长度
	*(uint32_t *) (Task_sendBuff + i) = htonl(pData->L);
	i += 4;
	// 储罐直径
	*(uint32_t *) (Task_sendBuff + i) = htonl(pData->d);
	i += 4;
	// 自动发送频率
	i += 2;
	// 自动发送短信频率
	i += 2;
	
	// 修改数据长度
	Task_sendBuff[7] = i - 8;
	
	// 校验码
	crc = MODBUS_RTU_CRC16((uint8_t *) Task_sendBuff, i);
	*(uint16_t *)(Task_sendBuff + i) = htons(crc);
	i += 2;
	// 结束符
	Task_sendBuff[i++] = 0x0d;
	Task_sendBuff[i++] = 0x0a;
	
	return i;
}

uint8_t pack_modbus_tran_data(ext_data_t *pGprs)
{
	uint16_t i, j;
	bluetooth_sensor_t *pSensor;
	bluetooth_mask_t   *pMask;
	uint16_t crc;

	rf_app_data_t *pData = (rf_app_data_t *) pGprs->payload;
	static data_sample_t sample;
	
	// TODO: 将精简数据转换成上传数据
	cacl_gprs_tran_data(pGprs, &sample);

	// 打包上报数据（按modbus从机响应的格式）
	memset(Modbus_sendBuff, 0, TASK_SENDBUFF_SIZE);
	i = 0;
	
	// PSN
	memmove(Modbus_sendBuff + i, pGprs->oriPSN, 6);
	i += 6;
	// 功能码
	Modbus_sendBuff[i++] = 0x10;
	// 数据长度：先预设为0，最后再修改，位置为Modbus_sendBuff[7]
	Modbus_sendBuff[i++] = 0;
	
	// 当前差压值
	*(uint16_t *) (Modbus_sendBuff + i) = htons(sample.diff);
	i +=2 ;
	// 容积百分比
	*(uint16_t *) (Modbus_sendBuff + i) = htons(sample.volumePct / 100);
	i += 2;
	// 当前容积
	*(uint32_t *) (Modbus_sendBuff + i) = htonl(sample.volume);
	i += 4;
	// 重量
	*(uint32_t *) (Modbus_sendBuff + i) = htonl(sample.weight);
	i += 4;
	if(pData->Sensor.measure_type == 0) 		// 差压
	{
		// 高度：mmWC
		*(uint16_t *) (Modbus_sendBuff + i) = htons((uint16_t) (sample.diff * 101.9716213));
	}
	else if(pData->Sensor.measure_type == 2)	// 电容
	{
		// 高度：mm
		*(uint16_t *) (Modbus_sendBuff + i) = htons((uint16_t) (sample.height));
	}
	i += 2;
	// 压力
	*(uint16_t *) (Modbus_sendBuff + i) = htons(pData->press);
	i += 2;
	// 温度-调试信息
	*(int16_t *) (Modbus_sendBuff + i) = 1; // 1-标识为LoRa转发,2-标志为北斗上传，3-标志为4G转发
	i += 2;
	// 液源
	if(pData->Sensor.L_source <= SOURCE_POPO)
		Modbus_sendBuff[i] = pData->Sensor.L_source;
	i++;
	// 储罐类型
	if(pData->Sensor.bottle_type == BOTTLE_TYPE_STAND)
		Modbus_sendBuff[i] = 0;
	else if(pData->Sensor.bottle_type == BOTTLE_TYPE_LYING)
		Modbus_sendBuff[i] = 1;
	else if(pData->Sensor.bottle_type == BOTTLE_TYPE_SPHERICAL)
		Modbus_sendBuff[i] = 2;
	i++;
	// 故障码
	pSensor = (bluetooth_sensor_t *) (Modbus_sendBuff + i);
	
	pSensor->staDiff = pData->Sensor.staDiff;
	pSensor->staPress = pData->Sensor.staPress;
	pSensor->staEPress1 = 3;
	pSensor->staEPress2 = 3;
	pSensor->staEPress3 = 3;
	pSensor->staETempr1 = pData->Sensor.staETempr1;
	pSensor->staETempr2 = 3;
	pSensor->staETempr3 = 3;
	i += 2;
	// 传感器状态
	pMask = (bluetooth_mask_t *) (Modbus_sendBuff + i);
	memset(pMask, 0xFF, 2);
	pMask->maskFlow = 0;
	pMask->maskLowPower = pData->Sensor.bat_low;
	pMask->maskAbnormal = 0;
	pMask->maskCharging = pData->Sensor.charging;
	i += 2;
	
	// 版本号
	Modbus_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor;
	// rssi
	Modbus_sendBuff[i++] = 0;
	if(pMask->maskGPS)
	{
		 // 经度
		*(int32_t *) (Modbus_sendBuff + i) = htonl(pData->longitude);
		i += 4;
		// 纬度
		*(int32_t *) (Modbus_sendBuff + i) = htonl(pData->latitude);
		i += 4;
	}
	// 扩展温度
	if(pMask->maskETempr1)
	{
		*(uint16_t *) (Modbus_sendBuff + i) = htons(pData->tempr);
		i += 2;
	}
	if(pMask->maskETempr2)
	{
		i += 2;
	}
	if(pMask->maskETempr3)
	{
		i += 2;
	}
	
	// 电池信息
	if(pMask->maskBattery)
	{
		// 电量百分比
		*(uint16_t *) (Modbus_sendBuff + i) = htons(pData->batPct);
		i += 2;
		// 电池内部温度
		i += 2;
		// 电池当前电压
		*(int16_t *) (Modbus_sendBuff + i) = htons(pData->voltage);
		i += 2;
		// 电池容量
		i += 2;
		// 电池当前容量
		i += 2;
		// 充电电流，电流的符号表示充放电状态
		*(int16_t *) (Modbus_sendBuff + i) = htons(pData->batCurrent);
		i += 2;
		// 光照强度
		i += 2;
	}
	
	// 流量计
	if(pMask->maskFlow)
	{
		// 天信MODBUS /A1 通信协议 (BCD码）
		// 标况体积总量
		i += 6;
		// 标况流量
		i += 4;
		// 工况流量
		i += 4;
		// 温度
		i += 4;
		// 压力
		i += 4;
	}
	
	// 泄露报警
	if(pMask->maskLeak)
	{
		// 类型
		Modbus_sendBuff[i++] = LEAK_TYPE_SWITCH | LEAK_TYPE_CURRENT | LEAK_TYPE_MODBUS;
		// 状态、报警浓度
		Modbus_sendBuff[i++] = 0x80;
	}
	
	if(pMask->maskStamp)
	{
		if(dcBuff.powerInfo.protocolVer.minor == 107)
		{
			*(uint32_t *) (Modbus_sendBuff + i) = htonl(pData->relative_time + (RTC_offsetSeconds + rf_get_seconds() - pGprs->recvTime));
		}
		// 时间
		i += 4;
		// 年月日
		i += 4;
	}
	
	// 扩展压力
	if(pMask->maskEPress1)
	{
		i += 2;
	}
	if(pMask->maskEPress2)
	{
		i += 2;
	}
	if(pMask->maskEPress3)
	{
		i += 2;
	}
	
	// 硬件版本
//	Modbus_sendBuff[i++] = ((pData->hardVer / 10) << 4) + pData->hardVer % 10;
	Modbus_sendBuff[i++] = pData->hardVer;
	// 软件版本
//	Modbus_sendBuff[i++] = ((pData->softVer / 10) << 4) + pData->softVer % 10;;
	Modbus_sendBuff[i++] = pData->softVer;
	
	// 真空传感器
	for(j = 0; j < 2; j++)
	{
		// 状态
		*(uint16_t *) (Modbus_sendBuff + i) = htons(0);
		i += 2;
		// 使用年限
		i += 2;
		// 真空度
		i += 4;
		// 漏放气速率
		i += 4;
	}
	
	// 气瓶容量
	*(uint32_t *) (Modbus_sendBuff + i) = htonl(Theoretical_Param.v);
	i += 4;
	// 储罐封头直边长
	*(uint16_t *) (Modbus_sendBuff + i) = htons(0);
	i += 2;
	// 储罐筒长度
	*(uint32_t *) (Modbus_sendBuff + i) = htonl(pData->L);
	i += 4;
	// 储罐直径
	*(uint32_t *) (Modbus_sendBuff + i) = htonl(pData->d);
	i += 4;
	// 自动发送频率
	i += 2;
	// 自动发送短信频率
	i += 2;
	
	// 修改数据长度
	Modbus_sendBuff[7] = i - 8;
	
	// 校验码
	crc = MODBUS_RTU_CRC16((uint8_t *) Modbus_sendBuff, i);
	*(uint16_t *)(Modbus_sendBuff + i) = htons(crc);
	i += 2;
	// 结束符
	Modbus_sendBuff[i++] = 0x0d;
	Modbus_sendBuff[i++] = 0x0a;
	
	return i;
}

////////////////////////////////////////////////////////////////////////////////////////
// 填写双向通讯的固定字段
uint16_t fill_biDir_fixFields(uint16_t cmd, uint16_t len)
{
	bluetooth_send_t *pSend = (bluetooth_send_t *) Task_sendBuff;
	uint16_t crc;

	pSend->mark = CONFIG_MARK_LS;
	pSend->ver = htons(dcBuff.powerInfo.protocolVer.major);
	pSend->trans = 0;
	pSend->len = htons(len - sizeof(bluetooth_send_t) + 2);
	pSend->cmd = htons(cmd);
	crc = MODBUS_RTU_CRC16((uint8_t *) Task_sendBuff, len);
	Int2ByteS(Task_sendBuff, len, htons(crc));
	
	return len + 2;
}

uint16_t pack_ldms_info_data(uint32_t dataTime, uint32_t totalSeconds)
{
	uint16_t i = 0;
	S_RTC_TIME_DATA_T sRTC;
	bluetooth_timestamp_t t;
	
	memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
	
	// 头信息（最后再填内容）
	i += sizeof(bluetooth_send_t);
	// PSN
	memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
	i += 6;
	Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.major;
	Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor;
	Task_sendBuff[i++] = dcBuff.powerInfo.softVer.major;
	Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor;
	// 软件日期：yyyymmdd
	Int2ByteL(Task_sendBuff, i, htonl((2000 + dcBuff.powerInfo.softDate.year) * 10000 + dcBuff.powerInfo.softDate.month * 100 + dcBuff.powerInfo.softDate.day));
	i += 4;
	// Report format
	Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.major;
	Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor;
	// Config format
	Task_sendBuff[i++] = dcBuff.configBottle.header.ver.major;
	Task_sendBuff[i++] = dcBuff.configBottle.header.ver.minor;

	// 运行时间：分钟
	Int2ByteL(Task_sendBuff, i, htonl(totalSeconds / 60));
	i += 4;
	Int2ByteS(Task_sendBuff, i, htons(SYS_RSTSTS));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.dtuData.batCurrent));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.dtuData.batVoltage / 10));
	i += 2;
	Task_sendBuff[i++] = dcBuff.dtuData.batPct;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.dtuData.batCapa));
	i += 4;
	Task_sendBuff[i] = 0;
	i++;
	if(dcBuff.dtuData.posState)
		Int2ByteL(Task_sendBuff, i, htonl(dcBuff.dtuData.latitude));
	i += 4;
	if(dcBuff.dtuData.posState)
		Int2ByteL(Task_sendBuff, i, htonl(dcBuff.dtuData.longitude));
	i += 4;

	// 定位时间
	if(dcBuff.dtuData.posState && dcBuff.dtuData.sysTime.year)
	{
		t.year = dcBuff.dtuData.sysTime.year + 2000 - 2010;
		t.mon = dcBuff.dtuData.sysTime.month;
		t.day = dcBuff.dtuData.sysTime.day;
		t.hour_H = dcBuff.dtuData.sysTime.hour >> 4;
		t.hour_L = dcBuff.dtuData.sysTime.hour & 0x0F;
		t.min = dcBuff.dtuData.sysTime.minute;
		t.sec = dcBuff.dtuData.sysTime.second;
		Int2ByteL(Task_sendBuff, i, htonl(t.tm));
	}
	i += 4;
	// 卫星数量
	Task_sendBuff[i++] = dcBuff.dtuData.sateCount;
	// 数据时间
	Wakeup_CalcUTCTime(dataTime + RTC_offsetSeconds, &sRTC);
	t.year = sRTC.u32Year - 2010;
	t.mon = sRTC.u32Month;
	t.day = sRTC.u32Day;
	t.hour_H = sRTC.u32Hour >> 4;
	t.hour_L = sRTC.u32Hour & 0x0F;
	t.min = sRTC.u32Minute;
	t.sec = sRTC.u32Second;
	Int2ByteL(Task_sendBuff, i, htonl(t.tm));
	i += 4;
	// 信号强度
	Task_sendBuff[i++] = dcBuff.dtuData.rssi;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.powerInfo.gprsSuccCount));
	i += 4;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.powerInfo.gprsSendCount - dcBuff.powerInfo.gprsSuccCount));
	i += 4;
	if(dcBuff.powerInfo.gprsSendCount > 0)
		Task_sendBuff[i] = dcBuff.powerInfo.gprsSuccCount * 100 / dcBuff.powerInfo.gprsSendCount;
	i++;
	memmove(Task_sendBuff + i, dcBuff.powerInfo.gprsFailCode, strlen(dcBuff.powerInfo.gprsFailCode));
	i += 6;
	memmove(Task_sendBuff + i, dcBuff.powerInfo.simNumber, strlen(dcBuff.powerInfo.simNumber));
	i += 24;
//	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.powerInfo.bdNumber));
	i += 4;
	
	// 储罐类型
	Task_sendBuff[i++] = dcBuff.configBottle.type;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.diameter));
	i += 4;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.len));
	i += 4;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.lenExtra));
	i += 4;
	Int2ByteL(Task_sendBuff, i, htonl(Theoretical_Param.v));
	i += 4;
	Task_sendBuff[i++] = dcBuff.configBottle.chargePct;
	Task_sendBuff[i++] = dcBuff.configBottle.source;
//	Int2ByteS(Task_sendBuff, i, htons(Config_GetDensity(dcBuff.configBottle.source) * 1000));
	i += 2;
	Task_sendBuff[i++] = dcBuff.configBottle.dispMode;
//	if(dcBuff.configDisplay.L_Unit == UNIT_KPA)
//		Task_sendBuff[i] = 0;
//	else if(dcBuff.configDisplay.L_Unit == UNIT_KG)
//		Task_sendBuff[i] = 1;
//	else if(dcBuff.configDisplay.L_Unit == UNIT_L)
//		Task_sendBuff[i] = 2;
//	else if(dcBuff.configDisplay.L_Unit == UNIT_MMH2O)
//		Task_sendBuff[i] = 4;
//	else
//		Task_sendBuff[i] = 3;
	i++;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.serverVer));
	i += 2;
	memmove(Task_sendBuff + i, dcBuff.configData.server, strlen(dcBuff.configData.server));
	i += 26;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.port));
	i += 2;
	memmove(Task_sendBuff + i, dcBuff.configData.gpsServer, strlen(dcBuff.configData.gpsServer));
	i += 26;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.gpsPort));
	i += 2;
	memmove(Task_sendBuff + i, dcBuff.configData.upgServer, strlen(dcBuff.configData.upgServer));
	i += 26;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.upgPort));
	i += 2;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configData.intervalTrans));
	i += 4;
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configData.intervalSample));
	i += 4;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.intervalGPSTrans));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.intervalGPS));
	i += 2;
	Task_sendBuff[i++] = dcBuff.configData.timeLag;
	strcpy((char *) Task_sendBuff + i, DTU_DecideAPN());
	i += 20;
//	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configDisplay.bdCommander));
	i += 4;
	
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPress));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPressH));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.fullPct));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.priPct));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.orderPct));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.emptyPct));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnVolt));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnVoltH));
	i += 2;
	//Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.planMount));
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.offlineSeconds));
	i += 4;
	//Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.predictMount));
	i += 4;
	//Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.floorLevel));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTempr)); // span
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTemprH)); // spanPeriod
	i += 2;

	// 测量方式
//	Task_sendBuff[i] = dcBuff.configDisplay.op_USE_CAPACITY_SENSOR ? 2 : dcBuff.configBottle.measureType;
	i++;
//	Task_sendBuff[i] = 0;
	i++;
//	Task_sendBuff[i] = dcBuff.configDisplay.op_USE_PT100_SENSOR ? 0 : 1;
	i++;

	// 差压传感器参数
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.lowRange));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.highRange));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.zeroValue));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.fullValue));
	i += 2;
	// 电容传感器参数
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.baseC));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.refC));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.c1ADC));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.c2ADC));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(CAP_K_C1));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(CAP_K_C2));
	i += 2;
	// 称重传感器参数
//	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.lowRange));
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adDPress));
	i += 4;
//	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.highRange));
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adPress));
	i += 4;
//	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.zeroValue));
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adExtTempr[0]));
	i += 4;
//	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.fullValue));
	Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adExtTempr[1]));
	i += 4;
	// 压力传感器参数
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.lowRange));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.highRange));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.zeroValue));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.fullValue));
	i += 2;
	// 扩展压力传感器1参数
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].lowRange));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].highRange));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].zeroValue));
	i += 2;
	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].fullValue));
	i += 2;
	// 扩展温度传感器1参数
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].calibrateT));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].calibrateR));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].zeroValue));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].fullValue));
	i += 2;
	// 扩展温度传感器2参数
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].calibrateT));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].calibrateR));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].zeroValue));
	i += 2;
//	Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].fullValue));
	i += 2;
	
	// 填写固定字段
	return fill_biDir_fixFields(0xD035, i);
}

#define D036_PARAM_SIZE (240)
uint8_t parse_param_D036_data(uint8_t *param, uint8_t *reset)
{
	longlong_mask_t mask;
	uint16_t i = 0, shift = 0;
	
	// 参数有效标志位（用一个无符号长整数表示, 共63项可选配置（bit 0~62）, 最高位（bit 63）代表复位命令）
	// 网络字节序： 12 34 56 78 90 ab cd ef
	// h = 0x78563412, l = 0xefcdab90 （网络字节序）
	// h = 0x12345678, l = 0x90abcdef （本机字节序)
	// mask = 0x1234567890abcdef
	mask.h = ntohl(Byte2IntL(param, i));
	i += 4;
	mask.l = ntohl(Byte2IntL(param, i));
	i += 4;
	
	printf("\nmask = %016llX\n", mask.ll);
	
	// 储罐类型
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.type = param[i];
	i++;
	// 直径
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.diameter = ntohl(Byte2IntL(param, i));
	i += 4;
	// 长度
	if(mask.ll & (1ull << (shift++)))
	{
		dcBuff.configBottle.len = ntohl(Byte2IntL(param, i));
		dcBuff.configBottle.lenExtra = 0;
	}
	i += 4;
	// 充装比
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.chargePct = param[i];
	i++;
	// 介质
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.source = param[i];
	i++;
	// 密度
	if(mask.ll & (1ull << (shift++)))
		;//Config_SetDensity(dcBuff.configBottle.source, ntohs(Byte2IntS(param, i)) / 1000.0);
	i += 2;
	// 显示模式
	if(mask.ll & (1ull << (shift++)))
	{
		dcBuff.configBottle.dispMode = param[i];

		dcBuff.configBottle.options &= ~0x0003ul;
		if(dcBuff.configBottle.dispMode == DISP_MODE_ALL)
			dcBuff.configBottle.options |= 0x0003ul;
		else if(dcBuff.configBottle.dispMode == DISP_MODE_L)
			dcBuff.configBottle.options |= 0x0001ul;
		else if(dcBuff.configBottle.dispMode == DISP_MODE_KG)
			dcBuff.configBottle.options |= 0x0002ul;
	}
	i++;
	// 显示单位
	if(mask.ll & (1ull << (shift++)))
	{
		if(param[i] == 0)
			dcBuff.configDisplay.L_Unit = UNIT_KPA;
		else if(param[i] == 1)
			dcBuff.configDisplay.L_Unit = UNIT_KG;
		else if(param[i] == 2)
			dcBuff.configDisplay.L_Unit = UNIT_L;
		else if(param[i] == 4)
			dcBuff.configDisplay.L_Unit = UNIT_MMH2O;
		else
			dcBuff.configDisplay.L_Unit = UNIT_PCT;
	}
	i++;

	// 服务器版本
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.serverVer = ntohs(Byte2IntS(param, i));
	i += 2;
	// 远传服务器
	if(mask.ll & (1ull << (shift++)))
		strcpy(dcBuff.configData.server, (char *) param + i);
	i += 26;
	// 远传端口
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.port = ntohs(Byte2IntS(param, i));
	i += 2;
	// 远传服务器
	if(mask.ll & (1ull << (shift++)))
		strcpy(dcBuff.configData.gpsServer, (char *) param + i);
	i += 26;
	// 远传端口
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.gpsPort = ntohs(Byte2IntS(param, i));
	i += 2;
	// 远传服务器
	if(mask.ll & (1ull << (shift++)))
		strcpy(dcBuff.configData.upgServer, (char *) param + i);
	i += 26;
	// 远传端口
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.upgPort = ntohs(Byte2IntS(param, i));
	i += 2;
	// 发送频率
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.intervalTrans = ntohl(Byte2IntL(param, i));
	i += 4;
	// 采集频率
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.intervalSample = ntohl(Byte2IntL(param, i));
	i += 4;
	// 发送频率
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.intervalGPSTrans = ntohs(Byte2IntS(param, i));
	i += 2;
	// 采集频率
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.intervalGPS = ntohs(Byte2IntS(param, i));
	i += 2;
	// 时差
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configData.timeLag = param[i];
	i++;
	// APN
	if(mask.ll & (1ull << (shift++)))
		strcpy(dcBuff.configDisplay.APN, (char *) param + i);
	i += 20;
	// 北斗指挥机卡号
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configDisplay.bdCommander = ntohl(Byte2IntL(param, i));
	i += 4;

	// 压力报警点低: KPa
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.warnPress = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力报警点高: KPa
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.warnPressH = ntohs(Byte2IntS(param, i));
	i += 2;
	// 满液位报警点: 0.01%
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.fullPct = ntohs(Byte2IntS(param, i));
	i += 2;
	// 关键液位报警点: 0.01%
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.priPct = ntohs(Byte2IntS(param, i));
	i += 2;
	// 订货液位报警点: 0.01%
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.orderPct = ntohs(Byte2IntS(param, i));
	i += 2;
	// 空液位报警点: 0.01%
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.emptyPct = ntohs(Byte2IntS(param, i));
	i += 2;
	// 电压报警低点: mV
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.warnVolt = ntohs(Byte2IntS(param, i));
	i += 2;
	// 电压报警高点: mV
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.warnVoltH = ntohs(Byte2IntS(param, i));
	i += 2;
	// 每日计划用量: L
	if(mask.ll & (1ull << (shift++)))
	{
		//dcBuff.configBottle.planMount = ntohl(Byte2IntL(param, i));
		dcBuff.configBottle.offlineSeconds = ntohl(Byte2IntL(param, i));
	}
	i += 4;
	// 每日预测用量: L
	if(mask.ll & (1ull << (shift++)))
		; // dcBuff.configBottle.predictMount = ntohl(Byte2IntL(param, i));
	i += 4;
	// TTS-空液位报警点: 0.01%
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configBottle.floorLevel = ntohs(Byte2IntS(param, i));
	i += 2;
	// TTS-变化量报警点: 0.01%
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.warnTempr = ntohs(Byte2IntS(param, i));		// span
	i += 2;
	// TTS-变化量检测时间: 秒
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configBottle.warnTemprH = ntohs(Byte2IntS(param, i));	// spanPeriod
	i += 2;
	
	// 差压传感器量程: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorDPress.lowRange = ntohs(Byte2IntS(param, i));
	i += 2;
	// 差压传感器量程: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorDPress.highRange = ntohs(Byte2IntS(param, i));
	i += 2;
	// 差压传感器标定: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorDPress.zeroValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 差压传感器标定: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorDPress.fullValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 电容传感器量程: 底电容
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorCap.baseC = ntohs(Byte2IntS(param, i));
	i += 2;
	// 电容传感器量程: 增长电容
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorCap.refC = ntohs(Byte2IntS(param, i));
	i += 2;
 	// 电容传感器标定: C1ADC
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorCap.c1ADC = ntohs(Byte2IntS(param, i));
	i += 2;
	// 电容传感器标定: C2ADC
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorCap.c2ADC = ntohs(Byte2IntS(param, i));
	i += 2;
	// 称重传感器量程: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorWeight.lowRange = ntohl(Byte2IntL(param, i));
	i += 4;
	// 称重传感器量程: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorWeight.highRange = ntohl(Byte2IntL(param, i));
	i += 4;
	// 称重传感器标定: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorWeight.zeroValue = ntohl(Byte2IntL(param, i));
	i += 4;
	// 称重传感器标定: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorWeight.fullValue = ntohl(Byte2IntL(param, i));
	i += 4;
	// 压力传感器1量程: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorPress.lowRange = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器1量程: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorPress.highRange = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器1标定: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorPress.zeroValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器1标定: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorPress.fullValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器2量程: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorEPress[0].lowRange = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器2量程: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorEPress[0].highRange = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器2标定: 低
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorEPress[0].zeroValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 压力传感器2标定: 高
	if(mask.ll & (1ull << (shift++)))
		dcBuff.configSensor.sensorEPress[0].fullValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器1量程: 低
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[0].calibrateT = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器1量程: 高
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[0].calibrateR = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器1标定: 低
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[0].zeroValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器1标定: 高
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[0].fullValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器2量程: 低
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[1].calibrateT = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器2量程: 高
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[1].calibrateR = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器2标定: 低
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[1].zeroValue = ntohs(Byte2IntS(param, i));
	i += 2;
	// 温度传感器2标定: 高
	if(mask.ll & (1ull << (shift++)))
		; //dcBuff.configSensor.sensorPTempr[1].fullValue = ntohs(Byte2IntS(param, i));
	i += 2;
	
	*reset = ((mask.ll & (1ull << shift)) != 0);
	
	return ((mask.ll & ~(1ull << shift)) != 0);
}

#define D038_CONFIG_SIZE (74)
uint8_t parse_config_D038_data(uint8_t *param)
{
	uint16_t i = 0;
	
	// 服务器版本
	dcBuff.configBottle.serverVer = ntohs(Byte2IntS(param, i));
	i += 2;
	// 远传服务器
	strcpy(dcBuff.configData.server, (char *) param + i);
	i += 26;
	// 远传端口
	dcBuff.configData.port = ntohs(Byte2IntS(param, i));
	i += 2;
	// 远传服务器
	strcpy(dcBuff.configData.gpsServer, (char *) param + i);
	i += 26;
	// 远传端口
	dcBuff.configData.gpsPort = ntohs(Byte2IntS(param, i));
	i += 2;
	// 发送频率
	dcBuff.configData.intervalTrans = ntohl(Byte2IntL(param, i));
	i += 4;
	// 采集频率
	dcBuff.configData.intervalSample = ntohl(Byte2IntL(param, i));
	i += 4;

	// 硬件版本
//	dcBuff.configDisplay.op_HARDWARE_VER_MAJOR = param[i];
	i++;
	// 只显示毫米水柱
//	dcBuff.configDisplay.op_DISP_MMWC_ONLY = param[i];
	i++;
	// 罐箱版本
//	dcBuff.configDisplay.op_BOX_VER = param[i];
	i++;
	// 基站定位
//	dcBuff.configDisplay.op_CELL_LOCATION = param[i];
	i++;
	// 发送轨迹
//	dcBuff.configDisplay.op_SEND_GPS_DATA = param[i];
	i++;
	// 通信方式
//	dcBuff.configDisplay.op_SERVER_PROTOCOL = param[i];
	i++;
	// URL索引
//	dcBuff.configDisplay.op_SERVER_INDEX = param[i];
	i++;
	// 单向通信
//	dcBuff.configDisplay.op_UNIDIR_COMM = param[i];
	i++;
	
	return 1;
}

// 从服务器获取时间
void DTU_setOffsetSecondsFromServer()
{
	bluetooth_send_t *pRecv = (bluetooth_send_t *) Task_recvBuff;
	S_RTC_TIME_DATA_T sRTC;
	uint32_t totalSeconds1, totalSeconds2;
	int16_t zz;
	uint16_t i, recvLen;

	// 从服务器获取当前时间
	printf("\nGet time from server ...\n");
	// 连接升级服务器
	if(DTU_Connect(0, dcBuff.configData.upgServer, dcBuff.configData.upgPort))
	{
		memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
		
		i = sizeof(bluetooth_send_t);								
		// 填写固定字段
		i = fill_biDir_fixFields(0xD03B, i);

		// 发送i个字节到服务器，至少接收10个字节
		recvLen = sizeof(bluetooth_recv_t) + 2;
		if(DTU_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
		{
			if(recvLen >= sizeof(bluetooth_recv_t) + 2
				&& MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0)
			{
				if(recvLen >= sizeof(bluetooth_recv_t) + 11
					&& pRecv->cmd == ntohs(0x003B)
					&& MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + 11) == 0)
				{
					// 获取当前时间
					RTC_GetDateAndTime(&sRTC);
					totalSeconds1 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
							sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
					
					// UTC日期
					i = sizeof(bluetooth_recv_t);

					// 年
					sRTC.u32Year = ntohs(Byte2IntS(Task_recvBuff, i));
					i += 2;
					// 月
					sRTC.u32Month = Task_recvBuff[i++];
					// 日
					sRTC.u32Day = Task_recvBuff[i++];
					// 时
					sRTC.u32Hour = Task_recvBuff[i++];
					// 分
					sRTC.u32Minute = Task_recvBuff[i++];
					// 秒
					sRTC.u32Second = Task_recvBuff[i++];
					// 时差（按1/4小时, 带符号）
					recvLen = ntohs(Byte2IntS(Task_recvBuff, i));
					memmove(&zz, &recvLen, 2);
					
					printf("\n%04d-%02d-%02d %02d:%02d:%02d %d\n", sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, 
							sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second, zz);
					
					totalSeconds2 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
							sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

					// 将UTC时间转换为GMT时间（时差为0）
					totalSeconds2 -= zz * 900;
					// 将GMT时间转换为UTC时间（按配置的时差）
					totalSeconds2 += dcBuff.configData.timeLag * 3600;

					if(RTC_offsetSeconds == 0)
					{
						RTC_offsetSeconds = totalSeconds2 - totalSeconds1;
						// 关联铁电和SFlash的一致性
						CheckFramSFlashValid(totalSeconds1);
					}
				}
			}
		}
		// 关闭和服务器的连接
		DTU_Close(0);
	}
}
////////////////////////////////////////////////////////////////////////////////////////
// 任务主体：发送运行数据和GPS数据，读取网络信号强度等
void DTU_Task(void *p_arg)
{
	bluetooth_send_t *pSend = (bluetooth_send_t *) Task_sendBuff;
	bluetooth_send_t *pRecv = (bluetooth_send_t *) Task_recvBuff;
	uint16_t i, j, k;
	uint32_t totalSeconds;
    S_RTC_TIME_DATA_T sRTC;
	uint8_t try_count;
	uint16_t recvLen;
	uint8_t upgrade;
	uint8_t ackUpgrade;
	uint8_t downloadParam;
	uint8_t ackParam;
	uint8_t downloadOptions;
	uint8_t ackOptions;
	uint8_t downloadBoxes;
	uint8_t ackBoxes;
	uint8_t downloadConfig;
	uint8_t ackConfig;
	uint8_t reset = 0;
	TUpgradeHeader upHeader;
	upgrade_frame_t *pFrame;
	int32_t nextPtr;
	uint8_t write_count;

	uint32_t rssiTick = 0;
	uint8_t tranLocked = 0;

	// 清除数据
	memset(&dcBuff.dtuData, 0, sizeof(dcBuff.dtuData));
	
	// 从铁电读取最近一次GPS定位信息，并检查是否合法
	if(FRAM_LoadInfo(FRAM_GPS_INFO_BASE, (uint8_t *) &Ext_GPS, sizeof(ext_gps_t)))
	{
		dcBuff.dtuData.sysTime = Ext_GPS.sysTime;
		dcBuff.dtuData.longitude = Ext_GPS.longitude;
		dcBuff.dtuData.latitude = Ext_GPS.latitude;
		dcBuff.dtuData.speed = Ext_GPS.speed;
		dcBuff.dtuData.sateCount = Ext_GPS.sateCount;
		dcBuff.dtuData.posState = Ext_GPS.posState;
	}
	
	// 触发固件升级任务：开机执行一次
	xSemaphoreGive(DTU_semUpgrade);

	while(1)
	{
		// 获取当前时间
		RTC_GetDateAndTime(&sRTC);
		// 计算自上次gps定位以来的时间
		totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
				sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
		// 刚开始运行的时候，回退到刚启动的时间（忽略系统初始化时间）
		if(totalSeconds < 10)
			totalSeconds = 0;
		
		// 每30秒刷新一下4G信号
		if(IsTickOut(rssiTick))
		{
			rssiTick = GetDelayTick(30000);
			
			DTU_PowerOn();
			// 采集信号强度和注册信息
			Sim808_ReadGPRS();
			
			// GPRS拨号和GPS定位同时进行，以节省时间
			if(dcBuff.dtuData.networked)
				Sim808_GPRSDial();
		}
							
		// 连接成功，对发送加锁
		if(!dcBuff.dtuData.connected && Sim808_Connect(0, dcBuff.configData.server, dcBuff.configData.port) && !tranLocked)
		{
			xSemaphoreTake(RF_TranLock, portMAX_DELAY);
			tranLocked = 1;
		}

		if(!dcBuff.dtuData.connected && tranLocked)
		{
			// 4G连接失败，释放锁让网口有机会发送
			xSemaphoreGive(RF_TranLock);
			tranLocked = 0;
		}
		
		// 掉电有效，如果未获取到UTC时间，不转发
		if(RTC_offsetSeconds > 0 && dcBuff.dtuData.connected && LoopBuff_GetCount(&RF_TranM) > 0)
		{
			nextPtr = RF_TranM.info.rdPtr;
			for(k = 0; k < LoopBuff_GetCount(&RF_TranM); k++)
			{
				dcBuff.powerInfo.gprsSendCount++;

				if(!SFlash_LoadInfo(LoopBuff_GetDataPos(&RF_TranM, nextPtr), (uint8_t *) &Ext_Data_Rec1, sizeof(ext_data_t)))
				{
					nextPtr = LoopBuff_GetNextPtr(&RF_TranM, nextPtr);
					continue; // 不发送，算失败1次
				}
				
				nextPtr = LoopBuff_GetNextPtr(&RF_TranM, nextPtr);
								
				// 打包上报数据（按modbus从机响应的格式）
				i = pack_gprs_tran_data(&Ext_Data_Rec1, 1);

				recvLen = 2;
				if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
				{
					if(tranLocked)
					{
						// 4G发送失败，释放锁让网口有机会发送
						xSemaphoreGive(RF_TranLock);
						tranLocked = 0;
					}

					// 关闭和服务器的连接
					DTU_Close(0);

					break;
				}
			
				// 成功发送数据的时间: 取当前时间
				DTU_dataTime = totalSeconds;
				
				dcBuff.powerInfo.gprsSuccCount++;
			}

			// 移除已成功发送的数据
			if(k > 0)
			{
				LoopBuff_RemoveItems(&RF_TranM, k);
				// 保存到铁电
				FRAM_SaveInfo(RF_TranM.info_base, (uint8_t *) &RF_TranM.info, sizeof(RF_TranM.info));
			}
		}
		
		// 是否连接维护平台：每隔12小时一次（普莱克斯、林德的每次连接）
		if(xSemaphoreTake(DTU_semUpgrade, 0) == pdTRUE)
		{
			// 关闭和服务器的连接
			DTU_Close(0);

			// 是否升级或下载参数：维护平台
			upgrade = 0;
			ackUpgrade = 0;
			downloadParam = 0;
			ackParam = 0;
			downloadOptions = 0;
			ackOptions = 0;
			downloadBoxes = 0;
			ackBoxes = 0;
			downloadConfig = 0;
			ackConfig = 0;
			reset = 0;
			k = 1;	// 发送1条诊断信息

			try_count = 2;
			while((try_count--) && (k || upgrade || ackUpgrade || downloadParam || ackParam || downloadOptions || ackOptions || downloadBoxes || ackBoxes || downloadConfig || ackConfig))
			{
				// 连接升级服务器
				if(Sim808_Connect(0, dcBuff.configData.upgServer, dcBuff.configData.upgPort))
				{
					if(k)
					{
						// 发送诊断信息，至少接收12个字节
						i = pack_ldms_info_data(DTU_dataTime, totalSeconds);
						recvLen = sizeof(bluetooth_recv_t) + 2 + 2;
						if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
						if(recvLen >= sizeof(bluetooth_recv_t) + 2 + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0
							&& pRecv->cmd == ntohs(0x0035))
						{
							upgrade = Task_recvBuff[sizeof(bluetooth_recv_t)];
							downloadParam = Task_recvBuff[sizeof(bluetooth_recv_t) + 1];
							if(recvLen >= sizeof(bluetooth_recv_t) + 3 + 2)
								downloadConfig = Task_recvBuff[sizeof(bluetooth_recv_t) + 2];
							if(recvLen >= sizeof(bluetooth_recv_t) + 4 + 2)
								downloadOptions = Task_recvBuff[sizeof(bluetooth_recv_t) + 3];
							if(recvLen >= sizeof(bluetooth_recv_t) + 5 + 2)
								downloadBoxes = Task_recvBuff[sizeof(bluetooth_recv_t) + 4];
							k--;	// 发送成功
						}
					}

					// 下载参数
					if(downloadParam)
					{
						printf("\nDownload parameters ...\n");

						memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
									
						i = sizeof(bluetooth_send_t);
						
						// PSN
						memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
						i += 6;
						
						// 填写固定字段
						i = fill_biDir_fixFields(0xD036, i);
				
						// 发送i个字节到服务器，至少接收10个字节
						recvLen = sizeof(bluetooth_recv_t) + 2;
						if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							if(recvLen >= sizeof(bluetooth_recv_t) + 2
								&& MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0)
							{
								downloadParam = 0;
								
								if(recvLen >= sizeof(bluetooth_recv_t) + D036_PARAM_SIZE + 2
									&& pRecv->cmd == ntohs(0x0036)
									&& MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + D036_PARAM_SIZE + 2) == 0)
								{
									// 保存参数
									if(parse_param_D036_data(Task_recvBuff + sizeof(bluetooth_recv_t), &reset))
									{
										// 保存参数
										Config_SaveConfig();
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_BOTTLE_CONFIG, &display_modifi);
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_SENSOR_CONFIG, &display_modifi);
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DATA_CONFIG, &display_modifi);
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DISPLAY_CONFIG, &display_modifi);
									}
									ackParam = 1;
								}
							}
						}
						else
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
					}
					
					// 确认参数
					if(ackParam)
					{
						printf("\nConfirm download parameters ...\n");

						// 发送确认
						memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
									
						i = sizeof(bluetooth_send_t);
						
						// PSN
						memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
						i += 6;
						// 参数时间戳
						Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.ts));
						i += 4;
						
						// 填写固定字段
						i = fill_biDir_fixFields(0xD022, i);
				
						// 发送i个字节到服务器，至少接收10个字节
						// 如果失败，下次再发送
						recvLen = sizeof(bluetooth_recv_t) + 2;
						if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
						ackParam = 0;
					}

					// 下载配置选项
					if(downloadOptions)
					{
					}
					
					// 确认配置选项
					if(ackOptions)
					{
					}
					
					// 下载罐箱档案
					if(downloadBoxes)
					{
						printf("\nDownload boxes ...\n");

						if(boxesInfo.fileSize == 0)
						{
							// 从头开始下载
							memset(&boxesInfo, 0, sizeof(boxesInfo));
						}

						// 下载数据
						while(boxesInfo.fileSize == 0 || boxesInfo.offset < boxesInfo.fileSize)
						{
							memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
										
							i = sizeof(bluetooth_send_t);
							
							// PSN
							memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
							i += 6;
							// 当前版本号
							i += 4;
							// 文件偏移量
							Int2ByteL(Task_sendBuff, i, htonl(boxesInfo.offset));
							i += 4;
							// 请求数据长度
							Int2ByteL(Task_sendBuff, i, htonl(UPGRADE_DATA_LEN));
							i += 4;
							
							// 填写固定字段
							i = fill_biDir_fixFields(0xD0E2, i);
					
							// 发送i个字节到服务器，至少接收10个字节
							// 如果失败，下次再下载
							recvLen = sizeof(bluetooth_recv_t) + 2;
							if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
								break;
							
							if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0)
							{
								if(pRecv->cmd == ntohs(0x00E2))
								{
									pFrame = (upgrade_frame_t *) (Task_recvBuff + sizeof(bluetooth_recv_t));
									if(MODBUS_RTU_CRC16(pFrame->data, ntohl(pFrame->len) + 2) == 0)
									{
										// 内容下载成功，允许继续下载
										try_count = 2;

										// 如果储罐档案有变化
										if(boxesInfo.fileSize > 0 && (boxesInfo.fileSize != ntohl(pFrame->fileSize) || boxesInfo.fileCrc != pFrame->fileCrc
											|| boxesInfo.offset > ntohl(pFrame->fileSize)))
										{
											// 从头开始升级
											memset(&boxesInfo, 0, sizeof(boxesInfo));
											continue;
										}
										// 保存下载信息
										// 如果只是网络通信失败，会断点续传
										boxesInfo.fileSize = ntohl(pFrame->fileSize);
										boxesInfo.offset = ntohl(pFrame->offset);
										boxesInfo.len = ntohl(pFrame->len);
										boxesInfo.fileCrc = pFrame->fileCrc;
										printf("\nfileSize = %d, offset = %d, len = %d\n", 
											boxesInfo.fileSize, boxesInfo.offset, boxesInfo.len);

										// 要留1个字节用于添加结束符
										if(boxesInfo.offset + boxesInfo.len < sizeof(boxesBuff))
										{
											memmove(boxesBuff + boxesInfo.offset, pFrame->data, boxesInfo.len);
											boxesInfo.offset += boxesInfo.len;
										}
										else
										{
											// 取消本次下载
											boxesInfo.fileSize = 0;
											downloadBoxes = 0;
											break;
										}
									}
								}
								else // 命令返回错误
								{
									// 取消本次下载
									boxesInfo.fileSize = 0;
									downloadBoxes = 0;
									break;
								}
							}
						}
						
						if(boxesInfo.fileSize > 0 && boxesInfo.offset == boxesInfo.fileSize)
						{
							if(do_crc_16(0, (uint8_t *) boxesBuff, boxesInfo.fileSize) == boxesInfo.fileCrc)
							{
								// 校验通过
								printf("\nBoxes confirm passed\n");								
								downloadBoxes = 0;

								// 发送确认
								ackBoxes = 1;
							}
							else
							{
								// 校验未通过
								printf("\n****** Boxes confirm failed\n");
								// 从头开始
								boxesInfo.fileSize = 0;
							}
						}
						else
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 继续
							continue;
						}
					}
					
					// 确认罐箱档案
					if(ackBoxes)
					{
						printf("\nConfirm boxes ...\n");

						// 发送确认
						memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
									
						i = sizeof(bluetooth_send_t);
						
						// PSN
						memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
						i += 6;
						// 当前版本号
						Int2ByteL(Task_sendBuff, i, htonl(boxesInfo.ver));
						i += 4;
						// 档案的CRC16
						Int2ByteS(Task_sendBuff, i, boxesInfo.fileCrc);
						i += 2;
						
						// 填写固定字段
						i = fill_biDir_fixFields(0xD0E3, i);
				
						// 发送i个字节到服务器，至少接收10个字节
						// 如果失败，下次再发送
						recvLen = sizeof(bluetooth_recv_t) + 2;
						if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
						if(recvLen == sizeof(bluetooth_recv_t) + 2 && pRecv->cmd == ntohs(0x00E3))
						{
							ackBoxes = 0;

							// 更新储罐档案
							boxesBuff[boxesInfo.fileSize] = 0;
							Ext_Update_Boxes(boxesBuff);
							
							// 下次再升级从头开始
							boxesInfo.fileSize = 0;							
						}
					}
					
					// 下载配置
					if(downloadConfig)
					{
						printf("\nDownload configuration ...\n");

						memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
									
						i = sizeof(bluetooth_send_t);
						
						// PSN
						memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
						i += 6;
						
						// 填写固定字段
						i = fill_biDir_fixFields(0xD038, i);
				
						// 发送i个字节到服务器，至少接收10个字节
						recvLen = sizeof(bluetooth_recv_t) + 2;
						if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							if(recvLen >= sizeof(bluetooth_recv_t) + 2
								&& MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0)
							{
								downloadConfig = 0;
								
								if(recvLen >= sizeof(bluetooth_recv_t) + D038_CONFIG_SIZE + 2
									&& pRecv->cmd == ntohs(0x0038)
									&& MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + D038_CONFIG_SIZE + 2) == 0)
								{
									// 保存参数
									if(parse_config_D038_data(Task_recvBuff + sizeof(bluetooth_recv_t)))
									{
										// 保存参数
										Config_SaveConfig();
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_BOTTLE_CONFIG, &display_modifi);
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_SENSOR_CONFIG, &display_modifi);
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DATA_CONFIG, &display_modifi);
//												Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DISPLAY_CONFIG, &display_modifi);
									}
									ackConfig = 1;
								}
							}
						}
						else
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
					}
					
					// 确认配置
					if(ackConfig)
					{
						printf("\nConfirm download configuration ...\n");

						// 发送确认
						memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
									
						i = sizeof(bluetooth_send_t);
						
						// PSN
						memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
						i += 6;
						
						// 填写固定字段
						i = fill_biDir_fixFields(0xD039, i);
				
						// 发送i个字节到服务器，至少接收10个字节
						// 如果失败，下次再发送
						recvLen = sizeof(bluetooth_recv_t) + 2;
						if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
						ackConfig = 0;
						// 配置改变，需要复位
						reset = 1;
					}

					// 升级
					if(upgrade)
					{
						printf("\nUpgrade software ...\n");

						// 从FRAM读取初始进度
						FRAM_LoadInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));

						if(upInfo.fileSize == 0)
						{
							// 从头开始升级
							memset(&upInfo, 0, sizeof(upInfo));
							// 保存到铁电
							for(write_count = 0; write_count < 2; write_count++)
							{
								FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));
								if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)))
									break;
								printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo));
								delay_ms(200);
							}
						}

						// 下载数据
						while(upInfo.fileSize == 0 || upInfo.offset < upInfo.fileSize)
						{
							memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
										
							i = sizeof(bluetooth_send_t);
							
							// PSN
							memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
							i += 6;
							// 当前固件号
							Int2ByteL(Task_sendBuff, i, htonl(upInfo.ver));
							i += 4;
							// 文件偏移量
							Int2ByteL(Task_sendBuff, i, htonl(upInfo.offset));
							i += 4;
							// 请求数据长度
							Int2ByteL(Task_sendBuff, i, htonl(UPGRADE_DATA_LEN));
							i += 4;
							
							// 填写固定字段
							i = fill_biDir_fixFields(0xD0E0, i);
					
							// 发送i个字节到服务器，至少接收10个字节
							// 如果失败，下次再升级
							recvLen = sizeof(bluetooth_recv_t) + 2;
							if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
								break;
							
							if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0)
							{
								if(pRecv->cmd == ntohs(0x00E0))
								{
									pFrame = (upgrade_frame_t *) (Task_recvBuff + sizeof(bluetooth_recv_t));
									if(MODBUS_RTU_CRC16(pFrame->data, ntohl(pFrame->len) + 2) == 0)
									{
										// 升级内容下载成功，允许继续升级
										try_count = 2;

										// 如果升级包有变化
										if(upInfo.fileSize > 0 && (upInfo.fileSize != ntohl(pFrame->fileSize) || upInfo.fileCrc != pFrame->fileCrc
											|| upInfo.offset > ntohl(pFrame->fileSize) || upInfo.ver != ntohl(pFrame->ver)))
										{
											// 从头开始升级
											memset(&upInfo, 0, sizeof(upInfo));
											// 保存到铁电
											for(write_count = 0; write_count < 2; write_count++)
											{
												FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));
												if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)))
													break;
												printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo));
												delay_ms(200);
											}
											continue;
										}
										// 保存下载信息
										// 如果只是网络通信失败，会断点续传
										upInfo.ver = ntohl(pFrame->ver);
										upInfo.fileSize = ntohl(pFrame->fileSize);
										upInfo.offset = ntohl(pFrame->offset);
										upInfo.len = ntohl(pFrame->len);
										upInfo.fileCrc = pFrame->fileCrc;
										printf("\nfileSize = %d, offset = %d, len = %d\n", 
											upInfo.fileSize, upInfo.offset, upInfo.len);
							
										// 如果是第一个包，先将升级请求改为0，以免意外重启导致boot-loader解压
										// 待全部下载完以后，再改为1
										if(upInfo.offset == 0)
											((TUpgradeHeader *) pFrame->data)->upgrade_request = 0;
#if UPGRADE_DATA_LEN >= SFLASH_ERASE_SIZE
										// 直接写入flash
										for(write_count = 0; write_count < 2; write_count++)
										{
											SFlash_BufferWrite(SFLASH_UPGRADE_BASE + upInfo.offset, pFrame->data, upInfo.len);
											if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE + upInfo.offset, pFrame->data, upInfo.len))
												break;
											printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE + upInfo.offset, upInfo.len);
											delay_ms(200);
										}
										upInfo.offset += upInfo.len;
#else												
										// 为了减少flash的多次擦写，又节约收发缓冲
										// 先把数据拷到flash页缓冲
										for(write_count = 0; write_count < 2; write_count++)
										{
											FRAM_BufferWrite(FRAM_UPGRADE_DATA_BASE + upInfo.offset % SFLASH_ERASE_SIZE, pFrame->data, upInfo.len);
											if(FRAM_BufferVerify(FRAM_UPGRADE_DATA_BASE + upInfo.offset % SFLASH_ERASE_SIZE, pFrame->data, upInfo.len))
												break;
											printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_DATA_BASE + upInfo.offset % SFLASH_ERASE_SIZE, upInfo.len);
											delay_ms(200);
										}
										upInfo.offset += upInfo.len;
										
										// 够一页了，或者下载完了就从铁电写入flash
										if(upInfo.offset % SFLASH_ERASE_SIZE == 0)
										{
											FRAM_BufferRead(FRAM_UPGRADE_DATA_BASE, Task_recvBuff, SFLASH_ERASE_SIZE);
											for(write_count = 0; write_count < 2; write_count++)
											{
												SFlash_BufferWrite(SFLASH_UPGRADE_BASE + (upInfo.offset - SFLASH_ERASE_SIZE), Task_recvBuff, SFLASH_ERASE_SIZE);
												if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE + (upInfo.offset - SFLASH_ERASE_SIZE), Task_recvBuff, SFLASH_ERASE_SIZE))
													break;
												printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE + (upInfo.offset - SFLASH_ERASE_SIZE), SFLASH_ERASE_SIZE);
												delay_ms(200);
											}

										}
										else if(upInfo.offset == upInfo.fileSize)
										{
											FRAM_BufferRead(FRAM_UPGRADE_DATA_BASE, Task_recvBuff, upInfo.offset % SFLASH_ERASE_SIZE);
											for(write_count = 0; write_count < 2; write_count++)
											{
												SFlash_BufferWrite(SFLASH_UPGRADE_BASE + (upInfo.offset - upInfo.offset % SFLASH_ERASE_SIZE), Task_recvBuff, upInfo.offset % SFLASH_ERASE_SIZE);
												if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE + (upInfo.offset - upInfo.offset % SFLASH_ERASE_SIZE), Task_recvBuff, upInfo.offset % SFLASH_ERASE_SIZE))
													break;
												printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE + (upInfo.offset - upInfo.offset % SFLASH_ERASE_SIZE), upInfo.offset % SFLASH_ERASE_SIZE);
												delay_ms(200);
											}
										}
#endif
										for(write_count = 0; write_count < 2; write_count++)
										{
											// 保存到铁电
											FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));
											if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)))
												break;
											printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo));
											delay_ms(200);
										}
									}
								}
								else // 命令返回错误
								{
									// 取消本次升级
									upInfo.fileSize = 0;
									// 保存到铁电
									for(write_count = 0; write_count < 2; write_count++)
									{
										FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));
										if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)))
											break;
										printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo));
										delay_ms(200);
									}
									
									upgrade = 0;
									break;
								}
							}
						}
						
						if(upInfo.fileSize > 0 && upInfo.offset == upInfo.fileSize)
						{
							SFlash_BufferRead(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader));
							// 将升级请求改为1
							upHeader.upgrade_request = 1;
							if(upHeader.check == 0x55AA
								&& do_crc_16(0, (uint8_t *) &upHeader, sizeof(upHeader)) == 0
								&& do_sflash_crc(SFLASH_UPGRADE_BASE + sizeof(upHeader), upHeader.upgrade_length) == 0)
							{
								// 校验通过
								printf("\nUpgrade package confirm passed\n");
								// 发送确认
								ackUpgrade = 1;
							}
							else
							{
								// 校验未通过
								printf("\n****** Upgrade package confirm failed\n");
								// 从头开始
								upInfo.fileSize = 0;
								// 保存到铁电
								for(write_count = 0; write_count < 2; write_count++)
								{
									FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));
									if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)))
										break;
									printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo));
									delay_ms(200);
								}
							}
						}
						else
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 继续
							continue;
						}
					}
				
					// 确认升级成功
					if(ackUpgrade)
					{
						printf("\nConfirm upgrade software ...\n");


						// 发送确认
						memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE);
									
						i = sizeof(bluetooth_send_t);
						
						// PSN
						memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6);
						i += 6;
						// 当前固件号
						Int2ByteL(Task_sendBuff, i, htonl(upInfo.ver));
						i += 4;
						// 固件的CRC16
						Int2ByteS(Task_sendBuff, i, upInfo.fileCrc);
						i += 2;
						
						// 填写固定字段
						i = fill_biDir_fixFields(0xD0E1, i);
				
						// 发送i个字节到服务器，至少接收10个字节
						// 如果失败，下次再发送
						recvLen = sizeof(bluetooth_recv_t) + 2;
						if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE))
						{
							// 关闭和服务器的连接
							DTU_Close(0);
							// 重连
							continue;
						}
						if(recvLen == sizeof(bluetooth_recv_t) + 2 && pRecv->cmd == ntohs(0x00E1))
						{
							// 将升级请求改为1
							SFlash_BufferRead(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader));
							upHeader.upgrade_request = 1;
							for(write_count = 0; write_count < 2; write_count++)
							{
								SFlash_BufferWrite(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader));
								if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader)))
									break;
								printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE, sizeof(upHeader));
								delay_ms(200);
							}
							
							// 下次再升级从头开始
							upInfo.fileSize = 0;
							// 保存到铁电
							for(write_count = 0; write_count < 2; write_count++)
							{
								FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo));
								if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)))
									break;
								printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo));
								delay_ms(200);
							}
							// 关闭和服务器的连接
							DTU_Close(0);

							// 关闭DTU电源
							VCC_GSM_OFF();
							delay_ms(200);
							
							// 将LDROM映射到地址0x0
//									FMC_Open();
//									FMC_SetVectorPageAddr(LDROM_BASE);
//									FMC_Close();
							// 复位以后执行Bootloader，将升级包解压
							//WDT_Close(); // 先关看门狗，免得bootloader复位
							NVIC_SystemReset();
						}
					}
					
					// 关闭和服务器的连接
					DTU_Close(0);

					// 确认参数以后才执行复位命令（避免反复复位）
					if(reset && !ackParam)
					{
						VCC_GSM_OFF();
						delay_ms(200);
						NVIC_SystemReset();
					}
				}
			}
			
			// 刚处理完，清除等待的信号。等下一个周期再执行（如果有报警必须立即上传）
			xSemaphoreTake(DTU_semUpgrade, 0);
		}
	}
}
