最近在搞GPRS模块,SIM800C,具体流程是:GPRS先连接TCP服务器,再连接阿里云的MQTT物联网套件,上传给服务器一些消息,服务器收到以后再回复一些指令,或者可以通过手机微信小程序主动下发一些指令给设备。
代码是基于RTthread写的,STM32F103,系统tick 1000,标准库。
分为几个部分:
GPRS.c //SIM800C连接TCP服务器以及MQTT服务器过程
MQTTClient.c //MQTT的应用层接口函数
/**
* @file GPRS.c
* @author [email protected]
*/
#include "GPRS.h"
#define AT_RESP_END_OK "OK"
#define AT_RESP_END_ERROR "ERROR"
#define GPRS_CMD_AT "AT\r\n" //1.AT
#define GPRS_CMD_ATE0 "ATE0\r\n" //2.关闭回显
#define GPRS_CMD_AT_CPIN "AT+CPIN?\r\n" //3.AT+CPIN? (查看SIM卡的状态)回车,返回:+CPIN:READY OK(正常)。
#define GPRS_CMD_AT_CREG "AT+CREG?\r\n" //4.网络注册及状态查询; 0, 1, 2, 3, 4, 5 ,
// 其中 0 代表没有注册网络同时模块没有找到运营商,
// 1 代注册到了本地网络, 2 代表找到运营商但没有注册网络,
// 3 代表注册被拒绝, 4 代表未知的数据, 5代表注册在漫游状态.
#define GPRS_CMD_AT_IFC "AT+IFC=0,0\r\n" //5.本地流控, 无流控, 2,2: 硬件流控 1,1 软件流控
#define GPRS_CMD_AT_CIPMODE "AT+CIPMODE=1\r\n" //6.设置为透传模式
#define GPRS_CMD_AT_CGATT "AT+CGATT?\r\n" //7. 查询是否成功附着了GPRS网络
#define GPRS_CMD_AT_CGATT_1 "AT+CGATT=1\r\n" // 模块开机后首先查询模块是否附着GPRS网络,不要主动设置AT+CGATT=1,除非待机状态
// 下主动上报+CGATT: 0,此时可以设置AT+CGATT=1,否则不要设置。
#define GPRS_CMD_AT_CSTT "AT+CSTT\r\n" //8. 设置APN,使用默认的APN
#define GPRS_CMD_AT_CIICR "AT+CIICR\r\n" //9. 激活移动场景激活移动场景模块超时设置40s,如果40s还没有激活成功,模块端会自动
//上报+PDP:DEACT。如果前面CSQ、CREG、CGATT、AT+CSTT状态都
//是正常的,移动场景激活失败,那肯定是网络侧原因所致。当然CSQ值过
//低,比如10以下,移动场景激活成功概率较低。
//如果移动场景激活失败,执行AT+CIPSHUT(关闭移动场景),模块设置超时时间20s。
#define GPRS_CMD_AT_CIFSR "AT+CIFSR\r\n" //10.获取本地IP,若指令正确,模块将返回随机IP。
//必须有这一步才能使IP STATE变成IP STATUS,后续去建立具体的连接时才能成功。
#define GPRS_CMD_AT_CIPSTATUS "AT+CIPSTATUS\r\n" //11.查看模块的IP STATE是什么状态。
#define MAX_ERR_Times 4
#define MAX_WAIT_TIME 3000 //3s
#define MAX_READ_TIME 5000
#define GPRS_DEVICE_NAME "uart4"
#define GPRS_buff_size_max 1024
typedef struct {
rt_device_t dev; //设备描述符
struct rt_semaphore r_tx; //读串口信号量
char buff[GPRS_buff_size_max];
unsigned short buff_i;
unsigned char errtime;
}GPRS_DEV ;
static GPRS_DEV GprsDev;
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t GPRS_stack[ 1024 * 2 ];
static struct rt_thread GPRS_thread;
rt_err_t GPRS_Poweron(void);
rt_err_t GPRS_config(void);
/*
串口接收的回调函数
函数中置信号量
串口一旦接收到了数据, 就调用该函数.
*/
static rt_err_t GPRS_rx_ind(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&(GprsDev.r_tx));
return RT_EOK;
}
/*
* 读取数据知道遇到"\r\n"然后再解析收到的数据中是否具有我们想要的包
* 最大等待时间maxtime,
* 返回值:
* 0: 读取超时;
* 1: 读取成功
* -1: 读取失败,CRC错误.
*/
int GPRS_waitRead(int maxtime, char *str1, char *str2)
{
rt_tick_t timeout_tick = 0;
char ch = 0, last_ch = 0;
rt_err_t ret;
RT_ASSERT(GprsDev.dev);
timeout_tick = rt_tick_get(); //rt_tick_get 获取当前tick.
/* 清空接收参数.,做接收准备 */
GprsDev.buff_i = 0;
memset(GprsDev.buff, 0, GPRS_buff_size_max);
while(1)
{
if (rt_tick_get() - maxtime > timeout_tick)
{
GprsDev.errtime++;
return 0; //读取超时
}
/* 等待信号量(信号量在回调函数中被release.) */
if ((ret = rt_sem_take(&GprsDev.r_tx, 1000)) != RT_EOK)
{
rt_kprintf("[GPRS]: Wait Serial sem timeout. reply:%s\r\n", ret);
continue;
}
/* read one character from device */
while (rt_device_read(GprsDev.dev, 0, &ch, 1) == 1)
{
if (GprsDev.buff_i < GPRS_buff_size_max)
{
GprsDev.buff[GprsDev.buff_i++] = ch;
}
else
{
/* 检查是否具有我们想要的数 */
if (str1)
{
if (strstr(GprsDev.buff, str1) != 0)
return 1;
}
if (str2)
{
if (strstr(GprsDev.buff, str2) != 0)
return 1;
}
return -1;
}
if ((ch == '\n' && last_ch == '\r'))
{
//检查是否具有我们想要的数据
if (str1)
{
if (strstr(GprsDev.buff, str1) != 0)
return 1;
}
if (str2)
{
if (strstr(GprsDev.buff, str2) != 0)
return 1;
}
}
last_ch = ch;
}
rt_thread_delay(100);
}
}
/**
* @brief GPRS_TCP_Response_Check透传模式下连接TCP的反馈结果判断.
* @return
* 0: 没有收到消息
* 1: 收到了连接成功的消息
* -1: 收到了错误消息, 命令发送的错误
* -2: 收到了服务器关闭的消息.
*/
int GPRS_TCP_Response_Check()
{
if (strstr(GprsDev.buff, AT_RESP_END_OK) != 0)
{
if (strstr(GprsDev.buff, "TCP CLOSED\r\n") != 0 || strstr(GprsDev.buff, "CONNECT FAIL\r\n") != 0)
{
rt_kprintf("[GPRS]: Connect Server Fail:%s\r\n", GprsDev.buff);
return -1;
}
else if (strstr(GprsDev.buff, "CONNECT\r\n") != 0)
{
rt_kprintf("[GPRS]: Connect Server Sucess:%s\r\n", GprsDev.buff);
return 1;
}
}
else if(strstr(GprsDev.buff, "ALREADY\r\n") != 0)
{
if (strstr(GprsDev.buff, "CONNECT\r\n") != 0)
{
rt_kprintf("[GPRS]: Connect Server Sucess:%s\r\n", GprsDev.buff);
return 1;
}
else
{
rt_kprintf("[GPRS]: Connect Server Fail:%s\r\n", GprsDev.buff);
return -1;
}
}
else if (strstr(GprsDev.buff, AT_RESP_END_ERROR) != 0)
{
rt_kprintf("[GPRS]: Connect Server Err:%s\r\n", GprsDev.buff);
return -2;
}
return 0;
}
int GPRS_WaitReadTCP(int maxtime)
{
char ch = 0;
rt_tick_t timeout_tick = 0;
rt_err_t ret;
RT_ASSERT(GprsDev.dev);
timeout_tick = rt_tick_get(); //rt_tick_get 获取当前tick.
GprsDev.buff_i = 0; /* 清空接收参数.,做接收准备 */
memset(GprsDev.buff, 0, GPRS_buff_size_max);
while(1)
{
if (rt_tick_get() - maxtime > timeout_tick)
{
if (GPRS_TCP_Response_Check() == 1)
{
return 1;
}
else {
rt_kprintf("[GPRS]: Wait TCP Connect response timeout. reply:%s\r\n", GprsDev.buff);
GprsDev.errtime++;
return 0; //read timeout
}
}
/* 等待信号量(信号量在回调函数中被release.) */
if ((ret = rt_sem_take(&GprsDev.r_tx, 1000)) != RT_EOK)
{
rt_kprintf("[GPRS]: Wait TCP Connect sem timeout:%d\r\n", ret);
continue;
}
/* read one character from device */
while (rt_device_read(GprsDev.dev, 0, &ch, 1) == 1)
{
if (GprsDev.buff_i < GPRS_buff_size_max)
{
GprsDev.buff[GprsDev.buff_i++] = ch;
}
}
if (GPRS_TCP_Response_Check() == 1)
{
return 1;
}
rt_thread_delay(10);
}
}
int GPRS_Comu_cmd(char *cmd, char *want1, char *want2, int errtimes, int waittimes)
{
rt_uint8_t ret= 0;
while(errtimes --)
{
rt_device_write(GprsDev.dev, 0, cmd, strlen(cmd));
rt_kprintf("[GPRS]: Send: %s>>>>>>>>>>>>>>>>>>>>>>>>>\r\n\r\n", cmd);
ret = GPRS_waitRead(waittimes, want1, want2);
rt_kprintf("[GPRS]: Rcve: %s<<<<<<<<<<<<<<<\r\n\r\n", GprsDev.buff);
if (ret == 1)
{
return 1;
}
}
return 0;
}
int GPRS_CheckAT(void)
{
rt_uint8_t retrytimes = 5;
while (retrytimes--)
{
if (GPRS_Comu_cmd(GPRS_CMD_AT, AT_RESP_END_OK, 0, 1, MAX_WAIT_TIME) != 1)
{
if (strstr(GprsDev.buff, "NORMAL POWER DOWN") != 0)
{
return 0;
}
}
else
return 1;
}
return 0;
}
int GPRS_CheckCGATT(void)
{
rt_uint8_t retrytimes = 5;
while (retrytimes--)
{
if (GPRS_Comu_cmd(GPRS_CMD_AT_CGATT, "+CGATT: 1", 0, 1, MAX_WAIT_TIME) != 1)
{
rt_thread_delay(500);
GPRS_Comu_cmd(GPRS_CMD_AT_CGATT_1, AT_RESP_END_OK, 0, 1, MAX_WAIT_TIME);
rt_thread_delay(1000);
}
else
return 1;
}
return 0;
}
int GPRS_CheckCIFSR(void)
{
rt_uint8_t retrytimes = 5;
while (retrytimes--)
{
if (GPRS_Comu_cmd(GPRS_CMD_AT_CIFSR, ".", 0, 1, MAX_WAIT_TIME*2) == 1)
{
if (GPRS_Comu_cmd(GPRS_CMD_AT_CIPSTATUS, "STATE: IP STATUS", 0, 1, MAX_WAIT_TIME) == 1)
{
return 1;
}
}
}
return 0;
}
int GPRS_ConnectTCP(void)
{
rt_uint8_t ret;
rt_uint8_t retrytimes = 2;
while (retrytimes--)
{
rt_device_write(GprsDev.dev, 0, GPRS_CMD_CONNECT_MQTT, sizeof(GPRS_CMD_CONNECT_MQTT));
ret = GPRS_WaitReadTCP(MAX_READ_TIME);
if (ret)
return 1;
}
return 0;
}
void GPRS_process(void *s)
{
rt_uint8_t ret = 0;
rt_uint8_t GPRS_power_on = 0;
rt_uint8_t GPRS_connect_process = 0;
rt_kprintf("[GPRS]: GPRS thread running.\r\n");
while (1)
{
if(!GPRS_power_on)
{
GPRS_Poweron();
GPRS_connect_process = 0;
}
switch(GPRS_connect_process)
{
case 0:
{
if(GPRS_CheckAT() == 1)
{
GPRS_connect_process = 1;
GprsDev.errtime = 0;
GPRS_power_on = 1;
}
else {
GPRS_power_on = 0;
}
break;
}
case 1:
{
if (GPRS_Comu_cmd(GPRS_CMD_ATE0, AT_RESP_END_OK, 0, MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 2;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 2:
{
if ( GPRS_Comu_cmd(GPRS_CMD_AT_CPIN, AT_RESP_END_OK, "+CPIN: READY", MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 3;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 3:
{
if ( GPRS_Comu_cmd(GPRS_CMD_AT_CREG, "0,1", "0,5", MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 4;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 4:
{
if ( GPRS_Comu_cmd(GPRS_CMD_AT_IFC, AT_RESP_END_OK, 0, MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 5;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 5:
{
if ( GPRS_Comu_cmd(GPRS_CMD_AT_CIPMODE, AT_RESP_END_OK, 0, MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 6;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 6:
{
if(GPRS_CheckCGATT() == 1)
{
GPRS_connect_process = 7;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 7:
{
if (GPRS_Comu_cmd(GPRS_CMD_AT_CSTT, AT_RESP_END_OK, 0, MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 8;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 8:
{
if ( GPRS_Comu_cmd(GPRS_CMD_AT_CIICR, AT_RESP_END_OK, 0, MAX_ERR_Times, MAX_WAIT_TIME) == 1)
{
GPRS_connect_process = 9;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 9:
{
if (GPRS_CheckCIFSR() == 1)
{
GPRS_connect_process = 10;
GprsDev.errtime = 0;
}
else {
GPRS_power_on = 0;
}
break;
}
case 10:
{
if(GPRS_ConnectTCP() == 1) /* TCP连接成功 */
{
g_Status.connect = MQTT_CONNECT;
GPRS_connect_process = 11;
}
else
{
rt_kprintf("[GPRS]: TCP CONNECT ERROR. \r\n");
GPRS_power_on = 0;
}
break;
}
/* 开始连接阿里云物联网套件MQTT服务器 */
case 11:
{
ret = mqtt_init(); //确认连接
if(ret)
{
g_Status.connect = CONNECT_OK;
GPRS_connect_process = 12;
GprsDev.errtime = 0;
}
else
{
GprsDev.errtime++;
g_Status.connect = GPRS_CONNECT;
GPRS_connect_process = 10;
}
break;
}
case 12:
{
//发送心跳处理;
if (mqtt_ping() != RT_EOK)
{
g_Status.connect = MQTT_CONNECT;//心跳检查失败, 我们将断掉MQTT
}
if (MQTT_gprs_cycle())
{
;
}
if (g_Status.connect != CONNECT_OK)
{
if(g_Status.connect == MQTT_CONNECT)
{
GPRS_connect_process = 10;
GprsDev.errtime = 0;
}
else
GPRS_power_on = 0; //GPRS连接掉了,电源重启
}
break;
}
case 13:
{
break;
}
}
if(GprsDev.errtime >= 5)
{
rt_kprintf("[GPRS]: CONNECT ERROR STEP: [%d].\r\n", GPRS_connect_process);
GPRS_power_on = 0; //GPRS连接掉了
}
rt_thread_sleep(500);
}
}
rt_base_t GPRS_init(void)
{
rt_err_t result;
memset(&GprsDev, 0, sizeof(GPRS_DEV));
/* 初始化信号量 */
if (RT_EOK != rt_sem_init(&(GprsDev.r_tx), "GPRSSem", 0, RT_IPC_FLAG_FIFO))
{
rt_kprintf("[GPRS]: Creat Sem error.\r\n");
return RT_ERROR;
}
rt_kprintf("[GPRS]: Creat Sem = %d \r\n", GprsDev.r_tx.value);
/* 配置GPRS电源引脚, 初始化cJSON协议 */
GPRS_config();
Protocol_init();
/* 初始化串口 */
if (GprsDev.dev == RT_NULL)
{
GprsDev.dev = rt_device_find(GPRS_DEVICE_NAME);
RT_ASSERT(GprsDev.dev);
rt_kprintf("[GPRS]: rt_device_find success.\r\n");
/* 打开串口 */
if (RT_EOK == rt_device_open(GprsDev.dev,
(RT_DEVICE_OFLAG_RDWR //读写方式打开
| RT_DEVICE_FLAG_STREAM //流式模式
| RT_DEVICE_FLAG_INT_RX //中断式接收
| RT_DEVICE_FLAG_INT_TX))) //中断式发送
{
rt_kprintf("[GPRS]: serial open success.\r\n");
//return RT_EOK;
}
else
{
rt_kprintf("[GPRS]: serial open failure.\r\n");
return RT_ERROR;
}
/* 设置串口的回调函数 */
rt_device_set_rx_indicate(GprsDev.dev, GPRS_rx_ind);
}
result = rt_thread_init(&GPRS_thread, //线程描述符
"GPRS", //线程名称
GPRS_process, //线程的入口
RT_NULL, //参数
&GPRS_stack[0], //线程的栈
sizeof(GPRS_stack), //栈的大小
22, //优先级 21 ~ 32
30); //时间片 30: 30ms
if (result == RT_EOK)
rt_thread_startup(&GPRS_thread); //启动线程
else
{
rt_kprintf("[GPRS]: thread init error.!!!\r\n");
return RT_ERROR;
}
return RT_EOK;
}
rt_base_t GPRS_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
return RT_EOK;
}
rt_base_t GPRS_Poweron(void)
{
rt_kprintf("[GPRS]: PowerON.\r\n");
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
rt_thread_delay(100);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
rt_thread_delay(1500);
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
rt_thread_delay(2000);
return RT_EOK;
}
int mqtt_sendPacketBuffer(unsigned char* buf, int buflen)
{
// int i = 0;
int rc = 0;
rc = rt_device_write(GprsDev.dev, 0, buf, buflen);
//Here for debug
// rt_kprintf("MQTT_Send[%d]:\r\n\t", buflen);
// for (i = 0; i < buflen; i++)
// {
// rt_kprintf("%02X ", buf[i]);
// if ((i+1)%16 == 0)
// rt_kprintf("\r\n\t");
// }
// rt_kprintf("\r\n");
return rc;
}
int gprs_getdata(unsigned char* buf, int buflen)
{
int rlen = 0;
rt_tick_t timeout_tick = 0;
char ch = 0;
RT_ASSERT(GprsDev.dev);
if (buflen <= 0)
return 0;
timeout_tick = rt_tick_get(); //rt_tick_get 获取当前tick.
while(1)
{
/* read one character from device */
while (rt_device_read(GprsDev.dev, 0, &ch, 1) == 1)
{
buf[rlen++] = ch;
if (rlen >= buflen)
{
return rlen;
}
}
if (rt_tick_get() - timeout_tick > MAX_READ_TIME)
{
return 0; //读取超时
}
/* 等待信号量(信号量在回调函数中被release.) */
if (rt_sem_take(&GprsDev.r_tx, 2000) != RT_EOK)
{
continue;
}
}
}
GPRS.h
/**
* @file GPRS.h
* @author [email protected]
*/
#ifndef _GPRS_H_INCLUDE_
#define _GPRS_H_INCLUDE_
#include
#include "MQTTClient.h"
#include "Protocol.h"
rt_err_t GPRS_init(void);
int mqtt_sendPacketBuffer(unsigned char* buf, int buflen);
int gprs_getdata(unsigned char* getbuff, int bufsize);
#endif
MQTTClient.c
/**
* @file MQTTClient.c
* @author [email protected]
*/
#include "MQTTClient.h"
#include "MQTTPacket.h"
#include "Public.h"
#include "GPRS.h"
#define PUB_BUF_SIZE 512
unsigned char pubBuff[PUB_BUF_SIZE];
int PUB_BUFF_SIZE = sizeof(pubBuff);
//int payloadlen_in;
//unsigned char* payload_in;
/**
* @brief mqtt_gprs_ping 发送心跳命令到服务器
* @return
*
* 我们向服务器设置keepalive时间为120秒, 我们自己定时60秒向服务器发送心跳, 并期待服务器在10秒内给出回复,
* 如果20秒内服务器没有给出回复,我们认为是离线了.
*/
#define KEEP_ALIVE_INTERVAL 60 //我们设置超时时间为120秒, 但我们实际上60秒发送一帧数据.
#define keep_alive_reply_TIMEOUT 50
rt_tick_t tick_ping; //心跳时间
rt_base_t mqtt_ping(void)
{
static rt_tick_t tick_send;
static char havesend = 0;
int len, rc;
if ( (rt_tick_get() - tick_ping) / RT_TICK_PER_SECOND > KEEP_ALIVE_INTERVAL)
{
if (!havesend)
{
//发送处理
len = MQTTSerialize_pingreq(pubBuff, PUB_BUF_SIZE);
rc = mqtt_sendPacketBuffer(pubBuff, len);
if (rc != len)
{
rt_kprintf("[MQTT]: Err, send ping should write[%d], but now write[%d]. sysTime:[%d].\r\n", len, rc, rt_tick_get());
return RT_ERROR;
}
else {
havesend = 1;
rt_kprintf("[MQTT]: Send ping. sysTime:[%d].\r\n", rt_tick_get());
tick_send = rt_tick_get ();
}
}
else {
if ( (rt_tick_get() - tick_send) / RT_TICK_PER_SECOND > keep_alive_reply_TIMEOUT) //超时检查
{
rt_kprintf("[MQTT]: Send ping wait for reply in %d sec Timeout. sysTime:[%d].\r\n", keep_alive_reply_TIMEOUT, rt_tick_get());
return RT_ERROR;
}
}
}
else {
havesend = 0;
}
return RT_EOK;
}
int mqtt_connack(void)
{
int len;
int rc;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.clientID.cstring = MyClientID1;
data.keepAliveInterval = 60;
data.cleansession = 1;
data.username.cstring = MyUsername1;
data.password.cstring = MyPassword1;
len = MQTTSerialize_connect(pubBuff, PUB_BUFF_SIZE, &data);
rc = mqtt_sendPacketBuffer(pubBuff, len);
/* wait for connack */
if (MQTTPacket_read(pubBuff, PUB_BUFF_SIZE, gprs_getdata) == CONNACK)
{
unsigned char sessionPresent, connack_rc;
rt_kprintf("[MQTT]: Connack OK.\r\n");
if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, pubBuff, PUB_BUFF_SIZE) != 1 || connack_rc != 0)
{
rt_kprintf("[MQTT]: Unable to connect, return code %d\r\n", connack_rc);
return 0;
}
return rc;
}
else
{
return 0;
}
}
int mqtt_publish(char *topic, char *msg, int msglen)
{
int rc;
int len;
MQTTString topicString = MQTTString_initializer;
topicString.cstring = topic;
len = MQTTSerialize_publish(pubBuff, PUB_BUFF_SIZE, 0, 0, 0, 0, topicString, (unsigned char*)msg, msglen);
rc = mqtt_sendPacketBuffer(pubBuff, len);
return rc;
}
int mqtt_subscribe(char *topic)
{
int len = 0;
int msgid = 1;
int req_qos = 0;
int rc = 0;
MQTTString topicString = MQTTString_initializer;
topicString.cstring = topic;
len = MQTTSerialize_subscribe(pubBuff, PUB_BUFF_SIZE, 0, msgid, 1, &topicString, &req_qos);
rc = mqtt_sendPacketBuffer(pubBuff, len);
if (MQTTPacket_read(pubBuff, PUB_BUFF_SIZE, gprs_getdata) == SUBACK) /* wait for suback */
{
unsigned short submsgid;
int subcount;
int granted_qos;
rt_kprintf("[MQTT]: Suback OK.\r\n");
rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, pubBuff, PUB_BUFF_SIZE);
return rc;
}
else
{
return 0;
}
}
int mqtt_init(void)
{
//mqtt 连接
if (mqtt_connack() == 0)
{
return 0;
}
tick_ping = rt_tick_get ();
//mqtt 订阅服务器Topic
if (mqtt_subscribe(MTopic_Server) == 0)
{
return 0;
}
return 1;
}
/**
* @brief MQTT_gprs_cycle 循环读取服务器数据并进行回复或处理
* @return
*/
int MQTT_gprs_cycle(void)
{
// read the socket, see what work is due
int packet_type = MQTTPacket_read(pubBuff, PUB_BUF_SIZE, gprs_getdata);
int len = 0,
rc = PAHO_SUCCESS;
if (packet_type == -1)
{
rc = PAHO_FAILURE;
goto exit;
}
switch (packet_type)
{
case CONNACK: //CONNACK:连接确认
case PUBACK: //新发布消息确认,是QoS 1给PUBLISH消息的回复
case SUBACK:
break;
case PUBLISH: //收到服务器新发布的消息
{
MQTTString topicName;
MQTTMessage msg;
memset(&topicName, 0, sizeof(topicName));
memset(&msg, 0, sizeof(msg));
int intQoS;
if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
(unsigned char **)&msg.payload, (int *)&msg.payloadlen, pubBuff, PUB_BUF_SIZE) != 1)
goto exit;
msg.qos = (enum QoS)intQoS;
// mqtt_msg_process(&topicName, &msg);
rt_kprintf("[MQTT Receive]: Topic:%s, Data:%s.\r\n", topicName.lenstring.data, msg.payload);
ProtocolProcess(msg.payload);
if (msg.qos != QOS0)
{
if (msg.qos == QOS1) //要对消息进行响应
len = MQTTSerialize_ack(pubBuff, PUB_BUF_SIZE, PUBACK, 0, msg.id);
else if (msg.qos == QOS2) //响应消息
len = MQTTSerialize_ack(pubBuff, PUB_BUF_SIZE, PUBREC, 0, msg.id);
if (len <= 0)
rc = PAHO_FAILURE;
else
rc = mqtt_sendPacketBuffer(pubBuff, len);
if (rc == PAHO_FAILURE)
goto exit; // there was a problem
}
break;
}
case PUBREC: //发布确认
{
unsigned short mypacketid;
unsigned char dup, type;
if (MQTTDeserialize_ack(&type, &dup, &mypacketid, pubBuff, PUB_BUF_SIZE) != 1)
rc = PAHO_FAILURE;
else if ((len = MQTTSerialize_ack(pubBuff, PUB_BUF_SIZE, PUBREL, 0, mypacketid)) <= 0)
rc = PAHO_FAILURE;
else if ((rc = mqtt_sendPacketBuffer(pubBuff, len)) != len) // send the PUBREL packet
rc = PAHO_FAILURE; // there was a problem
if (rc == PAHO_FAILURE)
goto exit; // there was a problem
break;
}
case PUBCOMP:
break;
case PINGRESP:
tick_ping = rt_tick_get();
rt_kprintf("[MQTT]: Recv ping resp. sysTime:[%d].\r\n", rt_tick_get());
break;
}
exit:
return rc;
}
MQTTClient.h
/**
* @file MQTTClient.h
* @author [email protected]
*/
#ifndef _MQTT_CLIENT_H_INCLUDE
#define _MQTT_CLIENT_H_INCLUDE
#include
enum QoS { QOS0, QOS1, QOS2 };
/* all failure return codes must be negative */
enum returnCode { PAHO_BUFFER_OVERFLOW = -2, PAHO_FAILURE = -1, PAHO_SUCCESS = 0 };
typedef struct MQTTMessage
{
enum QoS qos;
unsigned char retained;
unsigned char dup;
unsigned short id;
void *payload;
size_t payloadlen;
} MQTTMessage;
#define VersionID "V1.0.0"
#define TerminalID "08141712001"
#define MyClientID1 "qp59q810uHn.08141712001|securemode=3,signmethod=hmacsha1,timestamp=2524608000000|"
#define MyUsername1 "08141712001&qp59q810uHn"
#define MyPassword1 "1663A781DECFF1F295911D6A35B1E279046E5FE8"
#define MTopic_Heart "/qp59q810uHn/08141712001/infor"
#define MTopic_Server "/qp59q810uHn/08141712001/#"
#define MTopic_Update "/qp59q810uHn/08141712001/update"
#define MTopic_UpErr "/qp59q810uHn/08141712001/update/error"
#define GPRS_CMD_CONNECT_MQTT "AT+CIPSTART=\"TCP\",\"qp59q810uHn.iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883\r\n"
int mqtt_connack(void);
int mqtt_publish(char *topic, char *msg, int len);
int mqtt_subscribe(char *topic);
int mqtt_RcvCMD(void);
int MQTT_gprs_cycle(void);
int mqtt_init(void);
rt_base_t mqtt_ping(void);
#endif