树莓派mqtt连接onenet平台实现消息订阅与发布

本文介绍了作者如何基于STM32开发板的MQTT教程,将代码移植到树莓派上实现与onenet平台的连接。通过MQTT协议,实现了数据上传、接收服务器指令并作出响应的功能。代码中包含了连接、订阅、发布和心跳包处理等功能,并在遇到连接或订阅失败时进行了重试。测试中,使用mqtt.fx工具验证了树莓派与onenet平台的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、引言

由于毕设需求,需要通过MQTT上传数据与下发命令,所以小白的我学习了MQTT,虽然理论部分还是懵懵懂懂,但别人的实现代码看懂也还算凑合。对于mqtt的入门我是跟着B站一位up主物联网技术大神的教学视频学习的,他是以stm32开发板来讲解的。由于个人能力薄弱所以自己整合的代码有很大一部分是直接copy这位up主的(嘿嘿 😮),特别mqtt.c中的,不过也做了些许修改以适用于树莓派,在此多谢这位up主。由于onenet是一个免费开放平台,所以对于没钱党的我选择了它。
我选择把它整合为树莓派可用也是有原因的:第一,该up主的代码适用于stm32,并且我也直接用他的mqtt框架在STM32上开发,但后来发现不跑系统直接用一个while循环后面有很多问题就难以解决,而自己又没学过可在stm32上运行的实时操作系统,但对Linux有一点了解,所以这是原因之一。第二,网上也有很多mqtt源码可适用于树莓派,但为了加深对mqtt实现过程的了解,我选择自己整合一下代码,加深印象。

up主:物联网技术大神
视频地址:https://b23.tv/mJEpQh
参考文章:https://blog.youkuaiyun.com/u010835747/article/details/108485662

推荐对于mqtt入门可参考:菜鸟教程的MQTT 入门介绍
推荐网上的文章如:MQTT 嵌入式 C语言 客户端libemqtt源码解析
C语言实现mosquitto发布、订阅消息

二、代码

话不多,说先上代码。
main.c

#include "mqtt.h"
#include "tcp.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include<time.h> //C语言的头文件  
#include <pthread.h>
#include <stdlib.h>


static int subscribe_flag = 1;			//订阅标志,(订阅失败时)记载重新订阅次数;若订阅成功则置为0
static int conect_flag = 1;				//MQTT连接标志,(连接失败时)记载重新连接次数;若连接成功则置为0


/********************************************************/
/*函数:指令处理函数(可自行添加指令和处理事务)			*/
/*参数:CmdBuf----接收的指令CmdBuf					    */
/*返回值:无											    */
/********************************************************/
void Cmd_Handler(unsigned char* CmdBuf)
{
   
		char Cmd1[16] = "open_Led";
		char Cmd2[16] = "open_Beep";
		
		char buf1[24] = "{\"LED\":1}";				  //可上传数据到onenet显示
		if(!memcmp(CmdBuf,Cmd1,strlen(Cmd1))){
   
				printf("灯已打开\n");
				PayloadPublish(buf1,strlen(buf1));    //可上传数据到onenet显示
		}else if(!memcmp(CmdBuf,Cmd2,strlen(Cmd2))){
   
				printf("蜂鸣器已打开\n");
		}else{
   
				printf("未知指令\n");
		}	
}


/***********************************************************/
/*线程函数:接收和处理服务器发过来的数据								       */
/***********************************************************/
void *RcvMessage_thread(void *date)
{
   
		unsigned int send_len = 0;				//存放TCP接收到消息的长度
		unsigned char buff[256] = {
   0};			//存放TCP接收到的消息
		unsigned char MQTT_RcvData[400];		//存放处理后的TCP消息
		unsigned char back_buff[100] = {
   0};		//存放指令


		while(1){
   

				if(conect_flag == 5){
   
						printf("多次连接失败,请检查设备信息是否正确\n");
						printf("程序已退出\n");
						exit(0);
				}

				memset(MQTT_RcvData,0,sizeof(MQTT_RcvData));
				memset(buff,0,sizeof(buff));
				send_len = tcp_rcv(buff,sizeof(buff));	//获取TCP接收的数据和数据长度

				if(send_len < 0)						//长度小于0,说明TCP读取数据失败,准备重新连接
				{
   
						MY_MQTT_RECONECT();
						continue;
				}else{
   
						memcpy(&MQTT_RcvData[2],buff,send_len);  		  //拷贝数据
						MQTT_RcvData[0] = send_len/256;                   //记录数据长度高字节
						MQTT_RcvData[1] = send_len%256;                   //记录数据长度低字节
				}

				//若第一个字节0x20,则是MQTT连接状态回复
				if(MQTT_RcvData[2]==0x20){
                			
						switch(MQTT_RcvData[5]){
   					
								case 0x00 : printf("CONNECT报文成功\n"); 
											MQTT_Subscribe(S_TOPIC_NAME,QoS_0);        //MQTT连接成功,开始订阅,conect_flag置0                             
											conect_flag = 0;
											break;                                                                                                   
								case 0x01 : printf("连接已拒绝,不支持的协议版本,准备重连\r\n");
											MY_MQTT_RECONECT();                   //MQTT连接失败,准备重连,下面以此类推                     
											conect_flag++;
											continue;
											break;                                                        
								case 0x02 : printf("连接已拒绝,不合格的客户端标识符,准备重连\r\n");
											MY_MQTT_RECONECT();                                             
											conect_flag++;
											continue;                                           
											break;                                                       
								case 0x03 : printf("连接已拒绝,服务端不可用,准备重连\r\n");         
											MY_MQTT_RECONECT();                                             
											continue;                                         
											conect_flag++;
											break;                                                       
								case 0x04 : printf("连接已拒绝,无效的用户名或密码,准备重连\r\n");
											MY_MQTT_RECONECT();                                             
											conect_flag++;
											continue;                                          					
											break;                                                       
								case 0x05 : printf("连接已拒绝,未授权,准备重连\r\n"); 
											MY_MQTT_RECONECT();                                             
											conect_flag++;
											continue;                                           				
											break;                                                        		
								default   : printf("连接已拒绝,未知状态,准备重连\r\n");
											MY_MQTT_RECONECT();                                             
											conect_flag++;
											continue;                                           		
											break;                                                       							
						}

				}			
				//若第一个字节是0x90,表示收到的是SUBACK报文
				else if(MQTT_RcvData[2]==0x90){
    
						switch(MQTT_RcvData[6]){
   					
								case 0x00 :
								case 0x01 : printf("订阅成功\r\n");        
											subscribe_flag = 0;
											break;  
								default   : printf("订阅失败,准备重新订阅\r\n");
											sleep(1);
											MQTT_Subscribe(S_TOPIC_NAME,QoS_0);
											subscribe_flag++;
											if(subscribe_flag == 5){
   
													printf("
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值