1676 lines
36 KiB
C
1676 lines
36 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* 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();
|
||
// 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);
|
||
|
||
if(GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA)
|
||
{
|
||
if(try_count > 0)
|
||
delay_ms(2000);
|
||
// 在这里主动打开GPS
|
||
DTU_EnableGPS();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 模块关电
|
||
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(®))
|
||
{
|
||
strcpy(dcBuff.powerInfo.gprsFailCode, "REG");
|
||
return FALSE;
|
||
}
|
||
DTU_ReadGPRSRegistry(®);
|
||
// 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;
|
||
}
|