基于RTthread的sim800c连接mqtt服务器通信

最近在搞GPRS模块,SIM800C,具体流程是:GPRS先连接TCP服务器,再连接阿里云的MQTT物联网套件,上传给服务器一些消息,服务器收到以后再回复一些指令,或者可以通过手机微信小程序主动下发一些指令给设备。

代码是基于RTthread写的,STM32F103,系统tick 1000,标准库。

分为几个部分:

GPRS.c    //SIM800C连接TCP服务器以及MQTT服务器过程
MQTTClient.c    //MQTT的应用层接口函数

/**
  * @file   GPRS.c
  * @author yufei_qf@foxmail.com
  */ 
#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 yufei_qf@foxmail.com
  */
 
#ifndef _GPRS_H_INCLUDE_
#define _GPRS_H_INCLUDE_
 
#include <rtthread.h>    
#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 yufei_qf@foxmail.com
  */
  
#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 yufei_qf@foxmail.com
  */
 
#ifndef     _MQTT_CLIENT_H_INCLUDE
#define     _MQTT_CLIENT_H_INCLUDE

#include <rtthread.h> 

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

 

  • 3
    点赞
  • 12
    评论
  • 18
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值