/*
*********************************************************************************************************
*                                       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"

// 是否打印DTU串口收到的字符
uint8_t DTU_uartPrint = 0;

// 串口超时定时器
const uint16_t DTU_tmrQPendLong = 120;	// 120s
const uint16_t DTU_tmrQPendShort = 5;	// 5s
const uint16_t DTU_tmrQPendSpec = 40;	// 40s

// DTU上电标志
uint8_t DTU_hasPowered = 0;
uint8_t DTU_imeiRead = 0;
uint8_t DTU_simCard = 0;
uint8_t DTU_simReg = 0;
uint8_t DTU_gprsReg = 0;
uint8_t DTU_isATMode = 0;
uint8_t DTU_gprsAttached = 0;
uint8_t DTU_linkEstablished = 0;
uint8_t DTU_sslConfig = 0;
uint8_t DTU_mqttConfig = 0;
uint8_t DTU_ipFetched = 0;
char DTU_APN[20] = "";
uint8_t DTU_isRMCFormat = 0;
uint8_t DTU_fail_count = 0;
uint8_t DTU_shutdown_count = 0;

// 清空无效数据
static void DTU_ClearQueue()
{
	uint8_t timeOut;
	uint32_t timeOutTick;
	
	do
	{
		timeOut = 1;
		timeOutTick = GetDelayTick(500);
		while(!IsTickOut(timeOutTick))
		{
			if(LoopBuff_GetCount(&DTU_TaskM))
			{
				timeOut = 0;
				break;
			}
		}
		LoopBuff_Clear(&DTU_TaskM);
	} while(!timeOut);
}

// 等待DTU命令的返回，检查期待的结果字符串
uint32_t DTU_ParseResult(char *checkPattern, char *checkErrPattern, char *resultBuff, uint16_t waitSeconds)
{
	uint8_t done = 0, timeOut;
	uint32_t timeOutTick;
	uint8_t u8DTU;
	uint16_t count, idx = 0;
	uint32_t ret = FALSE;
	uint8_t strLen = strlen(checkPattern);
	uint8_t errLen = strlen(checkErrPattern);
	
	memset(DTU_recvBuff, 0, DTU_RECVBUFF_SIZE);
	// 检测返回信息
	do
	{
		timeOut = 1;
		timeOutTick = GetDelayTick(waitSeconds * 1000);
		while(!IsTickOut(timeOutTick))
		{
			if(LoopBuff_GetCount(&DTU_TaskM))
			{
				timeOut = 0;
				break;
			}
		}

		if(!timeOut)
		{
			count = LoopBuff_GetCount(&DTU_TaskM);
			while(count--)
			{
				// 取数据
				memmove(&u8DTU, LoopBuff_GetDataPtr(&DTU_TaskM, DTU_TaskM.info.rdPtr), 1);
				LoopBuff_RemoveItems(&DTU_TaskM, 1);

//			if(u8DTU == '\n')
//				printf("\\n");
//			else if(u8DTU == '\r')
//				printf("\\r");
//			else
//				printf("%c", u8DTU);
				
				// 如果是检测发送的提示符（>），直接返回成功
				if(strcmp(checkPattern, ">") == 0 && u8DTU == '>')
				{
					strcpy(resultBuff, ">");
					ret = TRUE;
					
					done = 1;
					break;
				}
				// 换行符
				if(u8DTU == '\n')
				{
					// 丢掉\n前面的\r
					if(idx > 0 && DTU_recvBuff[idx - 1] == '\r')
						DTU_recvBuff[--idx] = 0;

					// 先检查字符串（电话号码没有特征字符串）
					if((strLen > 0 && strstr(DTU_recvBuff, checkPattern)) || (strLen == 0 && idx > 0))
					{
						DTU_recvBuff[idx] = 0;
						strcpy(resultBuff, DTU_recvBuff);
						ret = TRUE;

						done = 1;
						break;
					}
					// 检查返回错误的字符串
					if(errLen > 0 && strstr(DTU_recvBuff, checkErrPattern))
					{
						DTU_recvBuff[idx] = 0;
						strcpy(resultBuff, DTU_recvBuff);
						ret = FALSE;
						
						done = 1;
						break;
					}
					// 没有所要的字符串，清空
					memset(DTU_recvBuff, 0, DTU_RECVBUFF_SIZE);
					idx = 0;
					continue;
				}
				if(idx < DTU_RECVBUFF_SIZE)
					DTU_recvBuff[idx++] = u8DTU;
			}
		}
	} while(!done && !timeOut);

	return ret;	
}

// 执行命令，等待结果
uint32_t DTU_ExecuteCmd(char *cmd, char *checkPattern, char *checkErrPattern, char *resultBuff, uint16_t waitSeconds)
{
	uint32_t ret = FALSE;
	
	// 检查并及时打开GPS电源
	if(DTU_needCheckGPS)
		DTU_CheckGPS();

	if(DTU_hasPowered)
	{
		// 唤醒
//		UART_Transmit(&huart1, (uint8_t *) "AT\r", 3);
//		delay_ms(5);

		printf("\n=> %s\n", cmd);
		
		// 清空数据
		DTU_ClearQueue();
		// 发送命令, 并附加回车换行符
		UART_Transmit(&huart1, (uint8_t *) cmd, strlen(cmd));
		UART_Transmit(&huart1, (uint8_t *) "\r", 1);
		// 等待结果
		ret = DTU_ParseResult(checkPattern, checkErrPattern, resultBuff, waitSeconds);
	}

	return ret;
}

// 等待服务器端返回（至少len个字节，最多size个字节），直到收完或超时
// 返回值为实际收到的数据长度
uint16_t DTU_WaitResponse(uint8_t ssl, uint16_t len, uint8_t *buff, uint16_t size, uint16_t waitSeconds)
{
	uint8_t timeOut;
	uint32_t timeOutTick;
	uint8_t u8DTU, phase;
	uint16_t i, count, data_count;
	uint16_t preidx, idx;
	char cntbuff[40], prebuff[40], *p, *p1; 
	
	// 等待返回数据
	idx = 0;

	memset(prebuff, 0, sizeof(prebuff));
	preidx = 0;
	phase = 0;
	do
	{
		timeOut = 1;
		timeOutTick = GetDelayTick(idx == 0 ? waitSeconds * 1000 : 1000);
		while(!IsTickOut(timeOutTick))
		{
			if(LoopBuff_GetCount(&DTU_TaskM))
			{
				timeOut = 0;
				break;
			}
		}

		if(!timeOut)
		{
			count = LoopBuff_GetCount(&DTU_TaskM);
			while(count--)
			{
				// 取数据
				memmove(&u8DTU, LoopBuff_GetDataPtr(&DTU_TaskM, DTU_TaskM.info.rdPtr), 1);
				LoopBuff_RemoveItems(&DTU_TaskM, 1);
				
//				if(u8DTU == '\n')
//					printf("\\n");
//				else if(u8DTU == '\r')
//					printf("\\r");
//				else if(isprint(u8DTU))
//					printf("%c", u8DTU);
//				else
//					printf("[%02X]", u8DTU);
				
				if(phase == 0)
				{
					// 接收URC消息错误
					if(preidx >= sizeof(prebuff) - 1)
						return 0;

					prebuff[preidx++] = u8DTU;
					if(u8DTU == '\n')
					{
						if(!ssl)
							p =  strstr(prebuff, "+QIURC: \"recv\",0,");
						else
							p =  strstr(prebuff, "+QSSLURC: \"recv\",1,");
						if(p) // 获取数据长度
						{
							p += (ssl ? 19 : 17);
							p1 = strstr(p, "\r\n");

							// 接收URC消息错误
							if(!p1 || p1 >= p + sizeof(cntbuff))
								return 0;

							memset(cntbuff, 0, sizeof(cntbuff));
							strncpy(cntbuff, p, p1 - p);
							data_count = atoi(cntbuff);
							phase = 1;
						}
						else
						{
							memset(prebuff, 0, sizeof(prebuff));
							preidx = 0;
						}
					}
				}
				else if(idx < size)
				{
					 if(data_count--)
						buff[idx++] = u8DTU;
					 if(data_count == 0)
					 {
						memset(prebuff, 0, sizeof(prebuff));
						preidx = 0;
						phase = 0;
					 }
				}
			}
		}
	} while(idx < size && !timeOut);

	if(!ssl)
	{
		printf("\nresponse from server (%d bytes):\n", idx);
		for(i = 0; i < idx && i < 128; i++)
			printf("%02X ", buff[i]);
		if(idx > 128)
			printf("...");
		printf("\n");
	}
	if(idx < len)
		strcpy(dcBuff.powerInfo.gprsFailCode, "RECV");
	else
	{
		// 不清除错误代码（始终保留最近一次的错误代码）
		// strcpy(dcBuff.powerInfo.gprsFailCode, "");
	}
	return idx;	
}

// 模块DEACT
uint8_t DTU_Shutdown()
{
	uint8_t ret = 0;
	char buff[40];
	
	// 设置标志
	DTU_imeiRead = 0;
	DTU_simCard = 0;
	DTU_simReg = 0;
	DTU_gprsReg = 0;
	DTU_gprsAttached = 0;
	DTU_linkEstablished = 0;
	DTU_sslConfig = 0;
	DTU_mqttConfig = 0;
	DTU_ipFetched = 0;
	DTU_fail_count = 0;
	dcBuff.dtuData.connected = 0;
	DTU_shutdown_count++;
	
	if(DTU_ExecuteCmd("AT+QIDEACT=1", "OK", "ERROR", buff, DTU_tmrQPendSpec))
	{
		strcpy(DTU_APN, "");
		printf("\nDTU shutdown.\n");
		ret = 1;
	}
	else
		printf("\nDTU shutdown failed.\n");
	
	return ret;
}

// 发送数据, 等待服务器返回
uint32_t DTU_SendAndRecv(uint8_t ssl, uint8_t *data, uint16_t len, uint16_t *recvLen, uint8_t *recvBuff, uint16_t recvSize)
{
	char cmd[40], buff[40];
	int8_t try_count = 2;
	uint32_t ret = TRUE;
	uint16_t rlen = *recvLen;
	uint16_t totalLen = 0, rslen;
	S_RTC_TIME_DATA_T sRTC;

	// 唤醒
//	UART_Transmit(&huart1, (uint8_t *) "AT\r", 3);
//	delay_ms(5);
		
	// 清空数据
	DTU_ClearQueue();
	// EC20一次最多只能发送1460字节
	while(totalLen < len)
	{		
		if(len - totalLen > 1460)
			rslen = 1460;
		else
			rslen = len - totalLen;
		// 发送命令, 并附加回车换行符
		if(!ssl)
			sprintf(cmd, "AT+QISEND=0,%d", rslen);
		else
			sprintf(cmd, "AT+QSSLSEND=1,%d", rslen);
		
		do
		{
			ret = FALSE;
			
			UART_Transmit(&huart1, (uint8_t *) cmd, strlen(cmd));
			UART_Transmit(&huart1, (uint8_t *) "\r", 1);
			if(DTU_ParseResult(">", "", buff, DTU_tmrQPendShort))
			{
				delay_ms(10);
				UART_Transmit(&huart1, data + totalLen, rslen);
				ret = DTU_ParseResult("SEND OK", "SEND FAIL", buff, DTU_tmrQPendSpec);
			}
			if(ret)
			{
				totalLen += rslen;
				break;
			}
			delay_ms(200);
		} while(--try_count > 0);
		
		if(!ret)
		{
			strcpy(dcBuff.powerInfo.gprsFailCode, "SEND");
			break;
		}
	}

	if(ret && rlen > 0)
	{
		do
		{
			rslen = DTU_WaitResponse(ssl, rlen, recvBuff, recvSize, DTU_tmrQPendSpec);
			memmove(recvLen, &rslen, 2);
			ret = (rslen >= rlen);
			if(ret)
				break;
			delay_ms(200);
		} while(--try_count > 0);
	}

	if(ret)
	{
		DTU_fail_count = 0;
		DTU_shutdown_count = 0;
		printf("\nSend %d bytes ok\n", len);

		// 记录发送成功的时间
		RTC_GetDateAndTime(&sRTC);
		DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
				sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
		return TRUE;
	}
	
	printf("\nSend failed\n");

	// 如果2次失败，模块关机/关电
	if(++DTU_fail_count >= 2)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	
	return FALSE;
}

// 定时器检查DTU是否休眠，如未休眠则关电
void DTU_CheckSleep()
{
}

void DTU_Sleep()
{
	DTU_PowerOff();
}

// 模块上电，等1秒钟才能发送命令
void DTU_PowerOn()
{
	char buff[40];
    S_RTC_TIME_DATA_T sRTC;
	uint8_t try_count = 2;

	if(!DTU_hasPowered)
	{
		printf("\nDTU power on ...\n");
		
		delay_ms(200);
		VCC_GSM_ON();

		if(GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA)
		{
			// 在这里主动打开GPS
			DTU_EnableGPS();
		}

//		delay_ms(10000);
		DTU_ParseResult("RDY", "", buff, DTU_tmrQPendShort * 3);
		
		// 获取当前时间
		RTC_GetDateAndTime(&sRTC);
		// 重设自上次gps定位以来的时间
		DTU_gpsTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

		// 设置标志
		DTU_hasPowered = 1;
		
		// 关闭命令回显
		while(try_count--)
		{
			if(DTU_ExecuteCmd("ATE0", "OK", "", buff, DTU_tmrQPendShort))
			{
				printf("\nDTU echo off.\n");
				break;
			}
			printf("\nDTU echo off failed.\n");
			delay_ms(2000);
		}

		// 版本
		if(DTU_ExecuteCmd("ATI", "Revision: ", "", buff, DTU_tmrQPendShort))
			printf("\n%s\n", buff);
	}
}

// 模块关电
void DTU_PowerOff()
{
	char buff[40];
	
	// 禁止重启GPS
	DTU_needCheckGPS = 0;

	if(DTU_hasPowered)
	{
		// 关闭GPS
		DTU_DisableGPS();

		if(DTU_ExecuteCmd("AT+QPOWD=1", "POWERED DOWN", "", buff, DTU_tmrQPendShort * 2))
			printf("\nGPRS disconnected.\n");
		else
			printf("\nGPRS disconnect failed.\n");

		// 设置标志
		DTU_hasPowered = 0;
		DTU_imeiRead = 0;
		DTU_simCard = 0;
		DTU_simReg = 0;
		DTU_gprsReg = 0;
		DTU_isATMode = 0;
		DTU_gprsAttached = 0;
		DTU_linkEstablished = 0;
		DTU_sslConfig = 0;
		DTU_mqttConfig = 0;
		DTU_ipFetched = 0;
		strcpy(DTU_APN, "");
		DTU_isRMCFormat = 0;
		DTU_fail_count = 0;
		dcBuff.dtuData.connected = 0;
		DTU_shutdown_count = 0;

		printf("\nDTU power off ...\n");
		VCC_GSM_OFF();
	}
}

// 读取IMEI号码(测试4G模块是否正常）
uint32_t DTU_ReadIMEI()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(DTU_imeiRead)
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+GSN", "", "ERROR", buff, DTU_tmrQPendShort))
		{
			if(strlen(buff) == 15)
			{
				DTU_imeiRead = 1;
				printf("\nThe IMEI is: %s\n", buff);
				return TRUE;
			}
		}
		delay_ms(200);
	}

	printf("\nRead IMEI failed.\n");
	return FALSE;
}

// 检查sim card
uint32_t  DTU_CheckSimCard()
{
	char buff[40];
	uint8_t try_count = 4;
	
	if(DTU_simCard)
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+CPIN?","+CPIN:", "", buff, DTU_tmrQPendShort) && strstr(buff, "+CPIN: READY"))
		{
			DTU_simCard = 1;
			printf("\nSim card ready.\n");
			return TRUE;
		}
		delay_ms(200);
	}

	DTU_simReg = 0;
	DTU_gprsReg = 0;
	DTU_gprsAttached = 0;
	DTU_linkEstablished = 0;
	DTU_sslConfig = 0;
	DTU_mqttConfig = 0;
	DTU_ipFetched = 0;
	printf("\nSim card not ready.\n");
	return FALSE;
}

// 检查GPRS附着情况：最多等40秒
uint32_t  DTU_CheckGprs()
{
	char buff[40];
	uint32_t check_time;
    S_RTC_TIME_DATA_T sRTC;
	
	if(DTU_gprsAttached)
		return TRUE;
	
	// 获取当前时间
	RTC_GetDateAndTime(&sRTC);
	check_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
	
	DTU_ExecuteCmd("AT+CGATT=1", "OK", "ERROR", buff, DTU_tmrQPendLong);
	
	do
	{
		if(DTU_ExecuteCmd("AT+CGATT?", "+CGATT: 1", "+CGATT: 0", buff, DTU_tmrQPendShort))
		{
			DTU_gprsAttached = 1;
			printf("\nGprs attached.\n");
			return TRUE;
		}
		
		delay_ms(1000);
		RTC_GetDateAndTime(&sRTC);
	} while(Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) < check_time + 120);

	DTU_gprsAttached = 0;
	DTU_linkEstablished = 0;
	DTU_sslConfig = 0;
	DTU_mqttConfig = 0;
	DTU_ipFetched = 0;
	printf("\nGprs not attached.\n");
	
	// 如果1次失败，模块关机/关电
	if(++DTU_fail_count >= 1)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	
	return FALSE;
}

// 设置APN
uint32_t DTU_SetAPN(char *APN, char *User, char *Pwd)
{
	char cmd[50], buff[40];
	uint8_t try_count = 2;
	
	if(strcmp(DTU_APN, APN) == 0)
		return TRUE;
	
	while(try_count--)
	{
		sprintf(cmd, "AT+QICSGP=1,1,\"%s\",\"%s\",\"%s\"", APN, User, Pwd);
		if(DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			strcpy(DTU_APN, APN);
			printf("\nSet APN to \"%s\".\n", APN);
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nSet APN failed.\n");

	return FALSE;
}

// 建立无线链路
uint32_t DTU_EstablishLink()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(DTU_linkEstablished)
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+QIACT=1", "OK", "ERROR", buff, DTU_tmrQPendLong))
		{
			DTU_linkEstablished = 1;
			printf("\nGprs link established\n");
			
//			DTU_ExecuteCmd("AT+QIDNSCFG=1", "OK", "ERROR", buff, DTU_tmrQPendShort);
			
			return TRUE;
		}
		delay_ms(200);
	}

	DTU_ipFetched = 0;
	printf("\nGprs link not established.\n");

	// 如果2次失败，模块关机/关电
	if(++DTU_fail_count >= 1)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	
	return FALSE;
}

uint32_t DTU_ConfigSSL()
{
	char cmd[40], buff[40];

	if(DTU_sslConfig)
		return TRUE;
	
	// 检查、上传CA证书
	while(!DTU_ExecuteCmd("AT+QFLST=\"RAM:ca_cert.pem\"", "+QFLST: \"RAM:ca_cert.pem\"", "ERROR", buff, DTU_tmrQPendShort))
	{
		sprintf(cmd, "AT+QFUPL=\"RAM:ca_cert.pem\",%d", strlen(ca_cert));
		if(DTU_ExecuteCmd(cmd, "CONNECT", "ERROR", buff, DTU_tmrQPendShort))
		{
			UART_Transmit(&huart1, (uint8_t *) ca_cert, strlen(ca_cert));
			if(DTU_ParseResult("+QFUPL:", "ERROR", buff, DTU_tmrQPendShort))
			{
				printf("\nca_cert.pem uploaded\n");
				break;
			}
		}
		printf("\nca_cert.pem upload failed\n");
		return FALSE;
	}
	
	// 检查、上传CLIENT证书
	while(!DTU_ExecuteCmd("AT+QFLST=\"RAM:client_cert.pem\"", "+QFLST: \"RAM:client_cert.pem\"", "ERROR", buff, DTU_tmrQPendShort))
	{
		sprintf(cmd, "AT+QFUPL=\"RAM:client_cert.pem\",%d", strlen(client_cert));
		if(DTU_ExecuteCmd(cmd, "CONNECT", "ERROR", buff, DTU_tmrQPendShort))
		{
			UART_Transmit(&huart1, (uint8_t *) client_cert, strlen(client_cert));
			if(DTU_ParseResult("+QFUPL:", "ERROR", buff, DTU_tmrQPendShort))
			{
				printf("\nclient_cert.pem uploaded\n");
				break;
			}
		}
		printf("\nclient_cert.pem upload failed\n");
		return FALSE;
	}

	// 检查、上传CLIENT密钥
	while(!DTU_ExecuteCmd("AT+QFLST=\"RAM:client_key.pem\"", "+QFLST: \"RAM:client_key.pem\"", "ERROR", buff, DTU_tmrQPendShort))
	{
		sprintf(cmd, "AT+QFUPL=\"RAM:client_key.pem\",%d", strlen(client_key));
		if(DTU_ExecuteCmd(cmd, "CONNECT", "ERROR", buff, DTU_tmrQPendShort))
		{
			UART_Transmit(&huart1, (uint8_t *) client_key, strlen(client_key));
			if(DTU_ParseResult("+QFUPL:", "ERROR", buff, DTU_tmrQPendShort))
			{
				printf("\nclient_key.pem uploaded\n");
				break;
			}
		}
		printf("\nclient_key.pem upload failed\n");
		return FALSE;
	}

	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"ignorelocaltime\",1,1", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"sslversion\",1,4", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"ciphersuite\",1,0xFFFF", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"seclevel\",1,2", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"cacert\",1,\"RAM:ca_cert.pem\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"clientcert\",1,\"RAM:client_cert.pem\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	if(!DTU_ExecuteCmd("AT+QSSLCFG=\"clientkey\",1,\"RAM:client_key.pem\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	
	DTU_sslConfig = 1;
	return TRUE;
}

uint32_t DTU_ConfigMQTT(char *product, char *device, char *secret)
{
	char cmd[100], buff[40], psn[14];
	
	if(DTU_mqttConfig)
		return TRUE;

	sprintf(psn, "20%02d%02d%02d%02d%03d", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], 
		dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3],
		(dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]); 
	
	// 每次重连服务器，需要重新订阅topic
	if(!DTU_ExecuteCmd("AT+QMTCFG=\"session\",0,1", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	// URC只报长度，不报内容
	if(!DTU_ExecuteCmd("AT+QMTCFG=\"recv/mode\",0,1,1", "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	// 阿里云授权码
	sprintf(cmd, "AT+QMTCFG=\"aliauth\",0,\"%s\",\"%s\",\"%s\"", 
		product, device, secret);
	if(!DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort))
		return FALSE;
	
	DTU_mqttConfig = 1;
	return TRUE;
}

// 获取基站定位经纬度
uint32_t DTU_GetCellLocPosition()
{
	char buff[40];
	uint8_t try_count = 2;
	char *p, *p1 = NULL;
	
	// 查询当前multi PDNs是否enabled（默认enabled）
//	if(!DTU_ExecuteCmd("AT+QCFG=\"PDP/DuplicateChk\"", "+QCFG: \"pdp/duplicatechk\"", "ERROR", buff, DTU_tmrQPendShort)
//		|| strstr(buff, ",1") == 0)
//	{
//		// 设置当前multi PDNs为enabled
//		if(!DTU_ExecuteCmd("AT+QCFG=\"PDP/DuplicateChk\",1", "OK", "ERROR", buff, DTU_tmrQPendShort))
//		{
//			printf("\nSet multi PDNs failed.\n");
//			return FALSE;
//		}
//	}
//	// 查询当前contextid是否为1（默认为1）
//	if(!DTU_ExecuteCmd("AT+QLOCCFG=\"contextid\"", "+QLOCCFG: \"contextid\"", "ERROR", buff, DTU_tmrQPendShort)
//		|| strstr(buff, ",1") == 0)
//	{
//		// 设置当前contextid为1
//		if(!DTU_ExecuteCmd("AT+QLOCCFG=\"contextid\",1", "OK", "ERROR", buff, DTU_tmrQPendShort))
//		{
//			printf("\nSet Cell-Loc contextid failed.\n");
//			return FALSE;
//		}
//	}
	// 设置token（默认为空）
	if(!DTU_ExecuteCmd("AT+QLOCCFG=\"token\"", "+QLOCCFG: \"token\"", "ERROR", buff, DTU_tmrQPendShort)
		||  strstr(buff, "exist") == 0)
	{
		if(!DTU_ExecuteCmd("AT+QLOCCFG=\"token\",\"u3S224CX18r4O045\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nSet Cell-Loc token failed.\n");
			return FALSE;
		}
	}
	// 查询当前基站定位服务器是否为www.queclocator.com:80
	if(!DTU_ExecuteCmd("AT+QLOCCFG=\"server\"", "+QLOCCFG: \"server\"", "ERROR", buff, DTU_tmrQPendShort)
		|| strstr(buff, "www.queclocator.com:80") == 0)
	{
		// 设置当前基站定位服务器为www.queclocator.com:80
		if(!DTU_ExecuteCmd("AT+QLOCCFG=\"server\",\"www.queclocator.com:80\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nSet Cell-Loc server failed.\n");
			return FALSE;
		}
	}
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+QCELLLOC", "+QCELLLOC: ", "ERROR", buff, DTU_tmrQPendSpec))
		{
			p = strstr(buff, "+QCELLLOC: ");
			if(p)
			{
				p += 11;
				p1 = strstr(p, ",");
				if(p1)
				{
					dcBuff.dtuData.posState = 1; // 基站定位成功
					
					*p1 = 0;
					dcBuff.dtuData.longitude = atof(p) * 1000000;
					p = p1 + 1;
					dcBuff.dtuData.latitude = atof(p) * 1000000;
					
					printf("\nLatitude:\t%10.6f\n", dcBuff.dtuData.latitude * 0.000001);
					printf("Longitude:\t%10.6f\n", dcBuff.dtuData.longitude * 0.000001);
					
					return TRUE;
				}
			}
		}
			
		// 有可能是原来的token不对，重新设一次
		if(!DTU_ExecuteCmd("AT+QLOCCFG=\"token\",\"u3S224CX18r4O045\"", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nSet Cell-Loc token failed.\n");
			return FALSE;
		}
		delay_ms(200);
	}

	printf("\nGet Cell-Loc position failed.\n");
	
	return FALSE;
}

// 设置普通（AT命令，非透传）模式
// ！!! 此命令在4G模块无效 !!!
uint32_t DTU_SetATMode()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(DTU_isATMode)
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+QIMODE=0","OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			DTU_isATMode = 1;
			printf("\nSet to AT cmd mode.\n");
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nSet AT mode failed.\n");

	return FALSE;
}

// 获得本机IP地址
uint32_t DTU_FetchIP()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(DTU_ipFetched)
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+QIACT?", "+QIACT: 1,1", "+QIACT: 1,0", buff, DTU_tmrQPendShort))
		{
			DTU_ipFetched = 1;
			printf("\nLocal ip is: %s\n", buff + 14);
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nFetch ip failed.\n");

	return FALSE;
}

// 设置服务器格式为DNS
// ！!! 此命令在4G模块无效 !!!
uint32_t DTU_SetDNSIP()
{
	char buff[40];
	uint8_t try_count = 2;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+QIDNSIP=1", "OK", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nSet remote server to domain name.\n");
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nSet remote server to domain name failed.\n");

	return FALSE;
}

// 连接服务器：Direct push mode
uint32_t DTU_Connect(uint8_t ssl, char *server, short port)
{
	char cmd[80], buff[40];
	uint32_t ret = FALSE;
	uint8_t try_count = 1;
	
	while(try_count--)
	{
		if(!ssl)
		{
			sprintf(cmd, "AT+QIOPEN=1,0,\"TCP\",\"%s\",%d,0,1", server, port);
			if(!DTU_ExecuteCmd(cmd, "+QIOPEN: 0,", "ERROR", buff, DTU_tmrQPendSpec))
				break;
			if(strstr(buff, "+QIOPEN: 0,0"))
			{
				ret = TRUE;
				break;
			}
		}
		else
		{
			sprintf(cmd, "AT+QSSLOPEN=1,1,1,\"%s\",%d,1", server, port);
			if(!DTU_ExecuteCmd(cmd, "+QSSLOPEN: 1,", "ERROR", buff, DTU_tmrQPendSpec))
				break;
			if(strstr(buff, "+QSSLOPEN: 1,0"))
			{
				ret = TRUE;
				break;
			}
		}
		delay_ms(200);
	}

	if(ret)
	{
		dcBuff.dtuData.connected = 1;
		printf("\nConnect to %s: %d\n", server, port);
		return TRUE;
	}
	
	dcBuff.dtuData.connected = 0;
	printf("\nCan not connect to %s: %d\n", server, port);
	
	// 如果2次失败，模块关机/关电
	if(++DTU_fail_count >= 2)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	
	return FALSE;
}

// 关闭连接
uint32_t DTU_Close(uint8_t ssl)
{
	char buff[40];
	uint8_t try_count = 2;
	uint8_t ret;
	
	if(!dcBuff.dtuData.connected)
		return TRUE;
	dcBuff.dtuData.connected = 0;
	
	while(try_count--)
	{
		// 可能返回OK，也可能返回错误（如连接已关闭，或被服务器主动关闭），都视为关闭成功
		if(!ssl)
			ret = DTU_ExecuteCmd("AT+QICLOSE=0", "OK", "ERROR", buff, DTU_tmrQPendSpec);
		else
			ret = DTU_ExecuteCmd("AT+QSSLCLOSE=1", "OK", "ERROR", buff, DTU_tmrQPendSpec);
		if(ret)
		{
			printf("\nConnection closed.\n");
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nConnection close failed.\n");
	return FALSE;
}

// 读取sim卡电话号码
uint32_t DTU_ReadPhoneNo()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(strlen(dcBuff.powerInfo.simNumber))
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+QCCID", "+QCCID: ", "ERROR", buff, DTU_tmrQPendShort))
		{
			strcpy(dcBuff.powerInfo.simNumber, buff + 8);
			printf("\nThe phone no is: %s\n", dcBuff.powerInfo.simNumber);
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nRead phone no failed.\n");
	return FALSE;
}

// 读取IMSI（15位卡号）
uint32_t DTU_ReadIMSI()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(strlen(dcBuff.powerInfo.simNumber))
		return TRUE;
	
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+CIMI", "", "ERROR", buff, DTU_tmrQPendShort))
		{
			if(strlen(buff) == 15)
			{
				strcpy(dcBuff.powerInfo.simNumber, buff);
				printf("\nThe phone no is: %s\n", dcBuff.powerInfo.simNumber);
				return TRUE;
			}
		}
		delay_ms(200);
	}

	printf("\nRead phone no failed.\n");
	return FALSE;
}

// 读取信号强度
uint32_t DTU_ReadRssi(uint8_t *rssi)
{
	char buff[40];
	uint8_t try_count = 6;
	char *pCSQ, *pCommon;
	uint8_t csq;
	
	*rssi = 0;
	while(try_count--)
	{
		if(DTU_ExecuteCmd("AT+CSQ", "+CSQ:", "ERROR", buff, DTU_tmrQPendShort))
		{
			pCSQ = strstr(buff, "+CSQ: ");
			pCommon = strstr(buff, ",");
			if(pCommon)
				*pCommon = 0;
			// 将0~31的强度值转换为百分比
			csq = atoi(pCSQ + 6);
			printf("\nThe CSQ is: %d\n", csq);
			if(csq != 99 && csq != 199)
			{
				if(csq < 100)
				{
					if(csq <= 31)
						*rssi = csq * 100 / 31;
				}
				else
				{
					if(csq <= 191)
						*rssi = csq - 100 + 9;
				}
				if(*rssi > 100)
					*rssi = 100;
				printf("\nThe rssi is: %d\n", *rssi);
				return TRUE;
			}
		}
		delay_ms(500);
	}

	printf("\nRead rssi failed.\n");
	return FALSE;
}

// 读取入网标志
uint32_t  DTU_ReadRegistry(uint8_t *reg)
{
	char buff[40];
	char *pReg;
	uint32_t check_time;
	uint16_t DTU_regTime = 60;
	uint8_t rssi = 0;
    S_RTC_TIME_DATA_T sRTC;
	
	if(DTU_simReg)
	{
		*reg = 1;
		return TRUE;
	}
	
	DTU_ReadRssi(&rssi);
	if(rssi >= 50)
		DTU_regTime = 150;
	
	// 获取当前时间
	RTC_GetDateAndTime(&sRTC);
	check_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

	*reg = 0;
	do
	{
		if(DTU_ExecuteCmd("AT+CREG?", "+CREG:", "ERROR", buff, DTU_tmrQPendShort))
		{

			pReg = strstr(buff, ",");
			if(pReg)
			{
				*reg = *(pReg + 1) - '0';
				if(*reg == 0)
					break;
			}
			//printf("\n%s\n", buff);
			if(*reg == 1 || *reg == 5)
			{
				printf("\nRegistry status: %d.\n", *reg);
				*reg = 1;
				DTU_simReg = 1;
				return TRUE;
			}
		}
		
		delay_ms(1000);
		RTC_GetDateAndTime(&sRTC);
	} while(Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) < check_time + DTU_regTime);

	printf("\nRegistry status: %d.\n", *reg);
	
	// 如果2次失败，模块关机/关电
	if(++DTU_fail_count >= 2)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	else
	{
		DTU_gprsReg = 0;
		DTU_gprsAttached = 0;
		DTU_linkEstablished = 0;
		DTU_sslConfig = 0;
		DTU_mqttConfig = 0;
		DTU_ipFetched = 0;
	}
	
	return FALSE;
}

// 读取GPRS入网标志
uint32_t  DTU_ReadGPRSRegistry(uint8_t *reg)
{
	char buff[40];
	char *pReg;
	uint32_t check_time;
    S_RTC_TIME_DATA_T sRTC;
	
	if(DTU_gprsReg)
	{
		*reg = 1;
		return TRUE;
	}
	
	// 获取当前时间
	RTC_GetDateAndTime(&sRTC);
	check_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
		
	*reg = 0;
	do
	{
		if(DTU_ExecuteCmd("AT+CGREG?", "+CGREG:", "", buff, DTU_tmrQPendShort))
		{
			pReg = strstr(buff, ",");
			if(pReg)
			{
				*reg = *(pReg + 1) - '0';
				if(*reg == 0)
					break;
			}
			if(*reg == 1 || *reg == 5)
			{
				printf("\nGPRS registry status: %d.\n", *reg);
				*reg = 1;
				DTU_gprsReg = 1;
				return TRUE;
			}
		}
		
		delay_ms(1000);
		RTC_GetDateAndTime(&sRTC);
	} while(Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) < check_time + 60);

	printf("\nGPRS registry status: %d.\n", *reg);
	
	return FALSE;
}

char *DTU_DecideAPN()
{
	if(strncmp(dcBuff.powerInfo.simNumber, "898604", 6) == 0)
		return "CMIOT";
	if(strncmp(dcBuff.powerInfo.simNumber, "898607", 6) == 0)
		return "CMIOT";
	if(strncmp(dcBuff.powerInfo.simNumber, "898602", 6) == 0)
		return "CMIOT";
	if(strncmp(dcBuff.powerInfo.simNumber, "898600", 6) == 0)
		return "CMIOT";
	if(strncmp(dcBuff.powerInfo.simNumber, "898608", 6) == 0)
		return "CMIOT";
	if(strcmp(dcBuff.configDisplay.APN, "CMNET") == 0)
		return "CMIOT";
	return dcBuff.configDisplay.APN;	
}
	
char *DTU_DecideAPNUser()
{
	if(strncmp(dcBuff.powerInfo.simNumber, "898604", 6) == 0)
		return "";
	if(strncmp(dcBuff.powerInfo.simNumber, "898607", 6) == 0)
		return "";
	if(strncmp(dcBuff.powerInfo.simNumber, "898602", 6) == 0)
		return "";
	if(strncmp(dcBuff.powerInfo.simNumber, "898600", 6) == 0)
		return "";
	if(strcmp(dcBuff.configDisplay.APN, "CMNET") == 0)
		return "";
	return dcBuff.configDisplay.User;	
}
	
char *DTU_DecideAPNPwd()
{
	if(strncmp(dcBuff.powerInfo.simNumber, "898604", 6) == 0)
		return "";
	if(strncmp(dcBuff.powerInfo.simNumber, "898607", 6) == 0)
		return "";
	if(strncmp(dcBuff.powerInfo.simNumber, "898602", 6) == 0)
		return "";
	if(strncmp(dcBuff.powerInfo.simNumber, "898600", 6) == 0)
		return "";
	if(strcmp(dcBuff.configDisplay.APN, "CMNET") == 0)
		return "";
	return dcBuff.configDisplay.Pwd;	
}

// 读取GPRS网络信息信息
uint32_t Sim808_ReadGPRS()
{
	uint8_t val;

	printf("\nRead RSSI data ....\n");
	DTU_PowerOn();
	if(!DTU_ReadIMEI())
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "EC20");
		return FALSE;
	}
	if(!DTU_CheckSimCard())
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "SIM");
		return FALSE;
	}
	if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_CHAOYANG)
		DTU_ReadIMSI();
	else
		DTU_ReadPhoneNo();
	if(!DTU_SetAPN(DTU_DecideAPN(), DTU_DecideAPNUser(), DTU_DecideAPNPwd()))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "APN");
		return FALSE;
	}
	if(!DTU_ReadRegistry(&val))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "REG");
		return FALSE;
	}
	dcBuff.dtuData.networked = (val == 1 ? 1 : 0);
	if(DTU_ReadRssi(&val))
		dcBuff.dtuData.rssi = val;
	
	return TRUE;
}

void DTU_setOffsetSeconds()
{
	char buff[40], *p;
	S_RTC_TIME_DATA_T sRTC;
	uint32_t totalSeconds1, totalSeconds2;
	int8_t zz;

	if(DTU_ExecuteCmd("AT+QLTS=2", "+QLTS: ", "ERROR", buff, DTU_tmrQPendShort)) // Get UTC time
	{
		// 获取当前时间
		RTC_GetDateAndTime(&sRTC);
		totalSeconds1 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
				sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);

		// UTC日期
		p = strstr(buff, "+QLTS: \"") + 8;
		printf("\n%s\n", p);
		// 4位年份
		p[4] = 0;
		sRTC.u32Year = atoi(p);
		p += 5;
		// 2位月份
		p[2] = 0;
		sRTC.u32Month = atoi(p);
		p += 3;
		// 2位日期
		p[2] = 0;
		sRTC.u32Day = atoi(p);
		p += 3;
		// 2位小时
		p[2] = 0;
		sRTC.u32Hour = atoi(p);
		p += 3;
		// 2位分钟
		p[2] = 0;
		sRTC.u32Minute = atoi(p);
		p += 3;
		// 2位秒
		sRTC.u32Second = (*p - '0') * 10 + (*(p + 1) - '0');
		p += 2;
		// 3位时差（按1/4小时, 带符号）
		p[3] = 0;
		zz = atoi(p);
		
		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;
	}
}

// GPRS拨号
uint32_t Sim808_GPRSDial()
{
	uint8_t reg;
	
	printf("\nGPRS Dialing ....\n");
	DTU_PowerOn();
	if(!DTU_ReadIMEI())
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "EC20");
		return FALSE;
	}
	if(!DTU_CheckSimCard())
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "SIM");
		return FALSE;
	}
	if(!DTU_SetAPN(DTU_DecideAPN(), DTU_DecideAPNUser(), DTU_DecideAPNPwd()))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "APN");
		return FALSE;
	}
	if(!DTU_ReadRegistry(&reg))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "REG");
		return FALSE;
	}
	DTU_ReadGPRSRegistry(&reg);
//	if(!DTU_CheckGprs())
//	{
//		strcpy(dcBuff.powerInfo.gprsFailCode, "GPRS");
//		return FALSE;
//	}
//	if(!DTU_SetATMode())
//	{
//		strcpy(dcBuff.powerInfo.gprsFailCode, "AT");
//		return FALSE;
//	}
	if(!DTU_EstablishLink())
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "ACT");
		return FALSE;
	}
	
	// 修正时间基准（可显示绝对时间）
	if(RTC_offsetSeconds == 0)
		DTU_setOffsetSeconds();
	if(RTC_offsetSeconds == 0)
		DTU_setOffsetSecondsFromServer();
	
	return TRUE;
}

uint32_t Sim808_Connect(uint8_t ssl, char *server, int port)
{
	if(!Sim808_GPRSDial())
		return FALSE;

//	if(!DTU_FetchIP())
//	{
//		strcpy(dcBuff.powerInfo.gprsFailCode, "IP");
//		return FALSE;
//	}
//	if(!DTU_SetDNSIP())
//	{
//		strcpy(dcBuff.powerInfo.gprsFailCode, "DNS");
//		return FALSE;
//	}
	
	if(ssl && !DTU_ConfigSSL())
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "SSL");
		return FALSE;
	}

	printf("\nConnect to server....\n");

	if(!DTU_Connect(ssl, server, port))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "CONN");
		return FALSE;
	}

	return TRUE;
}

// 获取基站定位经纬度
uint32_t Sim808_GetCellLocPosition()
{
	if(!Sim808_GPRSDial())
		return FALSE;

	printf("\nGet Cell-Loc position....\n");

	// 获取基站定位经纬度
	return DTU_GetCellLocPosition();
}

uint32_t Sim808_SendAndRecv(uint8_t ssl, uint8_t *data, uint16_t len, uint16_t *recvLen, uint8_t *recvBuff, uint16_t recvSize)
{
	return DTU_SendAndRecv(ssl, data, len, recvLen, recvBuff, recvSize);
}

// EC20一次最多只能发送1500字节
uint32_t DTU_MqttPublish(uint8_t *data, uint16_t len, char *product, char *device)
{
	static uint16_t msgid = 1;
	char cmd[100], buff[40], psn[14];
	int8_t try_count = 2;
	S_RTC_TIME_DATA_T sRTC;

	sprintf(psn, "20%02d%02d%02d%02d%03d", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], 
		dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3],
		(dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]); 
	
	while(try_count--)
	{
		// 唤醒
//		UART_Transmit(&huart1, (uint8_t *) "AT\r", 3);
//		delay_ms(5);
			
		// 清空数据
		DTU_ClearQueue();
		// 发送命令, 并附加回车换行符
		sprintf(cmd, "AT+QMTPUBEX=0,%d,1,0,\"/sys/%s/%s/thing/model/up_raw\",%d",
			msgid, product, device, len);		
//		printf("\n%s\n", cmd);
		UART_Transmit(&huart1, (uint8_t *) cmd, strlen(cmd));
		UART_Transmit(&huart1, (uint8_t *) "\r", 1);
		if(DTU_ParseResult(">", "ERROR", buff, DTU_tmrQPendShort))
		{
			delay_ms(10);
			UART_Transmit(&huart1, data, len);
			if(DTU_ParseResult("+QMTPUBEX: ", "ERROR", buff, DTU_tmrQPendSpec))
			{
				sprintf(cmd, "+QMTPUBEX: 0,%d,0", msgid);
				if(strstr(buff, cmd))
				{
					DTU_fail_count = 0;
					DTU_shutdown_count = 0;
					printf("\nSend %d bytes ok\n", len);
					msgid++;
					if(msgid == 0)
						msgid++;

					// 记录发送成功的时间
					RTC_GetDateAndTime(&sRTC);
					DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
							sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
					return TRUE;
				}
			}
		}

		strcpy(dcBuff.powerInfo.gprsFailCode, "SEND");
		delay_ms(200);
	}

	printf("\nSend failed\n");

	// 如果2次失败，模块关机/关电
	if(++DTU_fail_count >= 2)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	
	return FALSE;
}

uint32_t Sim808_MqttPublish(uint8_t *data, uint16_t len, char *product, char *device)
{
	return DTU_MqttPublish(data, len, product, device);
}

// 关闭连接
uint32_t MQTT_Close()
{
	char buff[40];
	uint8_t try_count = 2;
	
	if(!dcBuff.dtuData.connected)
		return TRUE;
	dcBuff.dtuData.connected = 0;
	
	while(try_count--)
	{
		// 可能返回OK，也可能返回错误（如连接已关闭，或被服务器主动关闭），都视为关闭成功
		if(DTU_ExecuteCmd("AT+QMTDISC=0","+QMTDISC: 0,0", "ERROR", buff, DTU_tmrQPendShort))
		{
			printf("\nConnection closed.\n");
			return TRUE;
		}
		delay_ms(200);
	}

	printf("\nConnection close failed.\n");
	return FALSE;
}

// 连接服务器：MQTT
uint32_t DTU_MqttConnect(const char *server, int port)
{
	char cmd[80], buff[40];
	uint8_t try_count = 1;

	while(try_count--)
	{
		sprintf(cmd, "AT+QMTOPEN=0,\"%s\",%d", server, port);
		if(DTU_ExecuteCmd(cmd, "+QMTOPEN: 0,0", "ERROR", buff, DTU_tmrQPendSpec) 
			&& DTU_ExecuteCmd("AT+QMTCONN=0,\"Anjiehui_4G\"","+QMTCONN: 0,0,0", "ERROR", buff, DTU_tmrQPendShort))
		{
			dcBuff.dtuData.connected = 1;
			printf("\nConnect to %s:%d\n", server, port);
			return TRUE;
		}
		delay_ms(200);
	}
	
	dcBuff.dtuData.connected = 0;
	printf("\nCan not connect to %s:%d\n", server, port);
	
	// 如果2次失败，模块关机/关电
	if(++DTU_fail_count >= 2)
	{
		if(DTU_shutdown_count >= 1 || !DTU_Shutdown())
			DTU_PowerOff();
	}
	
	return FALSE;
}

uint32_t Sim808_MqttConnect(const char *server, int port, char *product, char *device, char *secret)
{
	if(!Sim808_GPRSDial())
		return FALSE;

//	if(!DTU_FetchIP())
//	{
//		strcpy(dcBuff.powerInfo.gprsFailCode, "IP");
//		return FALSE;
//	}
//	if(!DTU_SetDNSIP())
//	{
//		strcpy(dcBuff.powerInfo.gprsFailCode, "DNS");
//		return FALSE;
//	}
	
	if(!DTU_ConfigMQTT(product, device, secret))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "MQTT");
		return FALSE;
	}

	printf("\nConnect to MQTT-Server....\n");

	if(!DTU_MqttConnect(server, port))
	{
		strcpy(dcBuff.powerInfo.gprsFailCode, "CONN");
		return FALSE;
	}

	return TRUE;
}
