#include "MQTTGPRSEthernet.h"
#include "StringHelper.h"
#ifdef DEBUG
Serial pc(PB_10, PB_11, 115200);
#define LOG(args...) pc.printf(args)
#define LOGC(args...) pc.putc(args)
#else
#define LOG(args...) (args)
#define LOGC(args...) (args)
#endif // DEBUG
//还需要增加一个表示已经初始化成功的变量
//后续可能要增加表示6条连接的东东,如果host,port,连接状态等
MQTTGPRSEthernet::MQTTGPRSEthernet(PinName tx, PinName rx, int baudrate)
: eth(tx, rx, baudrate){}
bool MQTTGPRSEthernet::initNet(const char* apn, const char* userName, const char* passWord, int timeout, bool isReconnect)
{
_apn = apn;
_userName = userName;
_passWord = passWord;
command("ATE0");
wait_ms(800);
command("AT+CIPMUX=0");
wait_ms(800);
//检查 GPRS 附着状态
while (!command("AT+CGATT?\r\n", "+CGATT: 1"))
{
LOG("GPRS NOT ATTACHED!\r\n");
wait_ms(1200);
eth.printf("+++");
wait_ms(1200);
command("AT");
command("AT+CIPSHUT\r\n");
}
//Select multiple connection
//单链路模式
//command("AT+CIPMUX=0");
//wait_ms(800);
//透传模式
command("AT+CIPMODE=1");
wait_ms(800);
command("AT+CIPCCFG=5,2,1024,1,0,1460,50");
wait_ms(800);
// Set APN
command(StringHelper::Format("AT+CSTT=\"%s\",\"%s\",\"%s\"", apn, userName, passWord));
wait_ms(800);
LOG(StringHelper::Format("AT+CSTT=\"%s\",\"%s\",\"%s\"\r\n", apn, userName, passWord));
uint32_t start = us_ticker_read();
do
{
// Brings up wireless connection
//建立无线链路(GPRS 或者 CSD)
bool flag = command("AT+CIICR", "OK");
// Get local IP address
eth.printf("AT+CIFSR\r\n");
char ip_addr_buf[32];
if (read_line(ip_addr_buf) <= 0) {
//LOG("failed to join network\r\n");
initialized = false;
}
else if (StringHelper::CheckIP(ip_addr_buf))
{
LOG("IP ADDRESS:");
LOG(ip_addr_buf);
LOG("\r\n");
localIP = ip_addr_buf;
initialized = true;
break;
}
else
{
initialized = false;
}
if (flag == false && initialized == false && isReconnect == false)
{
//表明此时建立无线链路返回error,得不到IP地址
//此时应使用AT+CIPSHUT关闭PDP上下文后再重新进行连接
//防止在数据状态
wait_ms(1200);
eth.printf("+++");
wait_ms(1200);
command("AT");
command("AT+CIPSHUT\r\n");
initialized = false;
return initNet(_apn, _userName, _passWord, timeout, true);
}
} while (us_ticker_read() - start < timeout);
//command("AT+CRPRXGET=0");
return initialized;
}
bool MQTTGPRSEthernet::initNet()
{
return initNet(_apn, _userName, _passWord);
}
bool MQTTGPRSEthernet::connect(char* hostname, int port, int timeout)
{
uint32_t start = us_ticker_read();
do
{
if (initialized == false)
initNet();
else
break;
} while (us_ticker_read() - start < timeout);
start = us_ticker_read();
do
{
//AT+CIPSTART=0,”TCP”,”116.228.221.51”,”8500”
char strPort[10];
itoa(port, strPort, 10);
char response[64] = { 0, };
int connectStart = us_ticker_read();
LOG(StringHelper::Format("AT+CIPSTART=TCP,%s,%s\r\n", hostname, strPort));
eth.printf(StringHelper::Format("AT+CIPSTART=TCP,%s,%s\r\n", hostname, strPort));
do
{
read_line(response);
if (strstr(response, "CONNECT") != NULL)
{
connected = true;
return connected;
}
} while (us_ticker_read() - connectStart < timeout);
} while (us_ticker_read() - start < timeout);
connected = false;
return connected;
}
//向SIM800C发送命令
//cmd:发送的命令字符串(不需要添加回车了),当cmd<0XFF的时候,发送数字(比如发送0X1A),大于的时候发送字符串.
//ack:期待的应答结果,如果为空,则表示不需要等待应答,对于那些并不关心返回结果的直接返回true
//此函数只能对应立即进行读取的情况。
//返回值:0,发送成功(得到了期待的应答结果)
// 1,发送失败
bool MQTTGPRSEthernet::command(const char* cmd, const char* ack)
{
char response[64] = { 0, };
if (StringHelper::EndWith(cmd, "\r\n"))
{
LOG(cmd);
eth.printf(cmd);
}
else if (StringHelper::EndWith(cmd, "\r"))
{
LOG(StringHelper::Add(cmd, "\n"));
eth.printf(StringHelper::Add(cmd, "\n"));
}
else
{
LOG(StringHelper::Add(cmd, "\r\n"));
eth.printf(StringHelper::Add(cmd, "\r\n"));
}
read_line(response);
if (strstr(response, ack) != NULL) {
return true;
}
return false;
}
int MQTTGPRSEthernet::read_line(char* buffer, int timeout)
{
int bytes = 0;
uint32_t start = us_ticker_read();
while (true) {
if (eth.readable()) {
char ch = eth.getc();
if ((ch == '\n' || ch == '\r') && bytes == 0)
{
//此时说明以\r\n开头,在无回显的情况下经常会出现
//此时忽略空行\r\n
continue;
}
if (ch == '\n') {
if (bytes > 0 && buffer[bytes - 1] == '\r') {
//表明读取到\r\n,此行结束
bytes--;
}
if (bytes > 0) {
buffer[bytes] = '\0';
return bytes;
}
}
else {
buffer[bytes] = ch;
bytes++;
}
}
else {
if ((uint32_t)(us_ticker_read() - start) > timeout) {
return bytes;
}
}
}
//此时表示读到最后一个字节还没有读到\n
//有两种情况,一种是len不够长,另一种是恰好读完,此时数组的末尾没有\0
return bytes;
}
int MQTTGPRSEthernet::read(unsigned char* buffer, int len, int timeout)
{
int bytes = 0;
uint32_t start = us_ticker_read();
while (bytes < len) {
if (eth.readable()) {
char ch = eth.getc();
buffer[bytes] = ch;
bytes++;
}
else {
if ((uint32_t)(us_ticker_read() - start) > timeout) {
return bytes;
}
}
}
//此时表示读到最后一个字节还没有读到\n
//有两种情况,一种是len不够长,另一种是恰好读完,此时数组的末尾没有\0
return bytes;
}
int MQTTGPRSEthernet::write(unsigned char* buffer, int len, int timeout)
{
uint32_t start = us_ticker_read();
while (!connected)
{
if ((us_ticker_read() - start) > timeout)
{
return -1;
}
initNet();
}
for (size_t i = 0; i < len; i++)
{
LOGC(buffer[i]);
eth.putc(buffer[i]);
}
return len;
}
bool MQTTGPRSEthernet::disconnect()
{
wait_ms(1200);
eth.printf("+++");
wait_ms(1200);
eth.printf("AT\r\n");
eth.printf("AT+CIPSHUT\r\n");
connected = false;
return true;
}
MQTTGPRSEthernet::~MQTTGPRSEthernet()
{
if (connected)
{
disconnect();
}
}