IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 单片机使用C语言实现MQTT协议 -> 正文阅读

[嵌入式]单片机使用C语言实现MQTT协议

单片机使用C语言实现MQTT协议

在单片机使用MQTT协议非常普遍,特别是在物联网相关领域,在阿里云,华为云等公有云都提供MQTT协议连接物联网平台。
本篇介绍如何用C语言实现MQTT的连接

MQTT连接主要有五步骤:
1. 连接云平台
2. 登录用户名密码等
3. 订阅主题
4. 发送心跳包
5. 发布主题

1. 连接云平台跟其他网站一样,只要有服务器地址和端口号就行,在这里我使用了以太网口去连接
代码如下:

u16 AnalyTarIp(u8 *TarIp,u16 port,u8 i)
{
	static u8 dnsSel = 0;
	u16 stateStamp;
	uip_ipaddr_t ipaddr;
	u8 ip[4];
			
	g_mconn[i].flag = 0;
	stateStamp = GetSecCnt();
			//á??ó·t???÷
	g_mconn[i].port = port;		//端口
			//IP还是域名
	if(IsIPaVailable(TarIp))				//IP
	{
		if(str2ip(ip, TarIp))		//str To num
		{
			uip_ipaddr(&ipaddr, ip[0], ip[1], ip[2], ip[3]);
			uip_ipaddr_copy(g_mconn[i].ip, ipaddr);		//记录IP
			S282_Log("uip connecting...");
			g_mconn[i].tcp = uip_connect(&g_mconn[i].ip, htons(g_mconn[i].port)); 				
			g_mconn[i].state = TcpClient_Connectting;
			stateStamp = GetSecCnt();
		}								
	}
	else	//域名
	{				
		u8 HaveDns = 0;
		if(DhcpOk == 0)
		{
			if(dnsSel == 0)
			{		
				if(SysInfo.DnsIp1[1] != 0 && SysInfo.DnsIp1[0] != 0xff)
				{
					uip_ipaddr(ipaddr, SysInfo.DnsIp1[0],SysInfo.DnsIp1[1],SysInfo.DnsIp1[2],SysInfo.DnsIp1[3]);
					HaveDns = 1;
				}
				if(SysInfo.DnsIp2[1] !=0 || SysInfo.DnsIp1[2] !=0 )	
				{
					dnsSel = 1;
				}
			}
			if((HaveDns == 0) && dnsSel)
			{	//DNS2
				dnsSel = 0;
				if(SysInfo.DnsIp2[1] != 0 && SysInfo.DnsIp2[0] != 0xff)	
				{		
					uip_ipaddr(ipaddr, SysInfo.DnsIp2[0],SysInfo.DnsIp2[1],SysInfo.DnsIp2[2],SysInfo.DnsIp2[3]);
					HaveDns = 1;
				}
			}
		}
		if(HaveDns || DhcpOk)
		{//进行域名解析
			g_mconn[i].state = TcpClient_DnsRequest;
			g_mconn[i].flag &= ~e_Dns_found;
			S282_Log("Analy Target Server ip");
			if(resolv_getserver() == NULL)
			{
				resolv_conf(ipaddr);		//配置DNS服务器
			}
			g_mconn[i].dnsno = resolv_query((char*)&TarIp[0]);//请求域名解析
			g_mconn[i].dnsno |= 0x80;
			stateStamp = GetSecCnt();
		}						
	}
	return stateStamp;
}
					域名解析成功后直接连接
		g_mconn[i].tcp = uip_connect(&g_mconn[i].ip, htons(g_mconn[i].port));
		g_mconn[i].state = TcpClient_Connectting;
  1. 登录用户 需要用户名 密码和设备ID
    代码如下:
/*
	MQTT 连接
	入参 mode: 0 GPRS网络 1 以太网网络
*/
void MqttConnect(u8 mode)
{
	u8 i;
	u16 len;
	MQTTPacket_connectData mqttConnDat = MQTTPacket_connectData_initializer;
	GetMqttConnectData(m_mqttBuf,M_CLIENT);
	if(SysInfo.MqttDeviceID[MQT_TXT_DATLEN] == 0)
	{
		//设备ID为空使用IMEI码
		for(i = 0; i < 15; i++)
		{
			m_mqttBuf[i] = g_IMEI[i];
		}
		m_mqttBuf[i] = '\0';
	}
	if(SysInfo.MqttUserName[MQT_TXT_DATLEN] == 0)
	{
		//MQTT用户名为空 用默认值
		for(i = 0; i < 4; i++)
		{
			m_mqttBuf[i + MQTT_PWD] = mqttDef[i];
		}
		m_mqttBuf[i] = '\0';
	}
	
	if(SysInfo.MqttPwd[MQT_TXT_DATLEN] == 0)
	{
		//MQTT密码为空 用默认值
		for(i = 0; i < 4; i++)
		{
			m_mqttBuf[i + MQTT_PWD * 2] = mqttDef[i];
		}
		m_mqttBuf[i] = '\0';
	}
	
	mqttConnDat.clientID.cstring = (char *)m_mqttBuf;
	//心跳存活时间根据平台需求设置
	mqttConnDat.keepAliveInterval = SysInfo.MqttRepTim;

	mqttConnDat.cleansession = 1;
	mqttConnDat.username.cstring = (char *)&m_mqttBuf[MQTT_PWD];
	mqttConnDat.password.cstring = (char *)&m_mqttBuf[MQTT_PWD * 2];

	len = MQTTSerialize_connect(m_sendBuf,MQTT_PWD * 3,&mqttConnDat);
	if(mode == 0)
	{
		SendGprsDat(m_sendBuf,len);
	}
	else
	{
		UipClient2Server(m_sendBuf,len);
	}
}
  1. 订阅主题 这里我以tlink物联网平台为准
/*
	MQTT订阅主题
*/
void MqttSubscribe(u8 mode)
{
	//·服务质量
	int qos = 0;
	u16 len,i;
	GetMqttConnectData(m_mqttBuf,M_SUBSCRIBE);
	if(!ISASCCHAR(m_mqttBuf[0]))
	{//tlink平台要求订阅主题为序列号+"/+"
		GetMqttConnectData(m_mqttBuf,M_CLIENTID);
		if(!ISASCCHAR(m_mqttBuf[0]))
		{
			for(i = 0; i < 15; i++)
			{
				m_mqttBuf[i] = g_IMEI[i];
			}
			m_mqttBuf[i] = '\0';
		}
		for(i = 0; i < 60; i++)
		{
			if(!ISASCCHAR(m_mqttBuf[i]))
			{
				break;
			}
		}
		m_mqttBuf[i++] = '/';
		m_mqttBuf[i++] = '+';
		m_mqttBuf[i++] = '\0';
	}
	
	topicString.cstring = (char *)m_mqttBuf;

	len = MQTTSerialize_subscribe(m_sendBuf,MQTT_PWD * 3,0,PacketId,1,&topicString,&qos);
	PacketId++;
	if(mode == 0)
	{
		SendGprsDat(m_sendBuf,len);
	}
	else
	{
		UipClient2Server(m_sendBuf,len);
	}
}

  1. 发送心跳包,根据自己要求隔段时间发送
/*
	MQTT Ping
	防止MQTT断开连接
*/
void MqttPingReq(u8 mode)
{
	u16 len;
	len = MQTTSerialize_pingreq(m_mqttBuf,MQTT_PWD * 3);
	if(mode == 0)
	{
		SendGprsDat(m_mqttBuf,len);
	}
	else
	{
		UipClient2Server(m_mqttBuf,len);
	}
}
  1. 发布主题 根据自己要求处理
/*
	MQTT 发布主题
	入参: InBuf 要发送的数据
	           len 发送数据长度 mode 发送方式
*/
void MqttPublish(u8 *InBuf,u16 len,u8 mode)
{
	u8 qos = 1;
	u16 i;
	
	GetMqttConnectData(m_mqttBuf,M_PUBLISH);
	if(!ISASCCHAR(m_mqttBuf[0]))
	{//没有填写发布主题 用IMEI码
		GetMqttConnectData(m_mqttBuf,M_CLIENTID);
		if(!ISASCCHAR(m_mqttBuf[0]))
		{
			for(i = 0; i < 15; i++)
			{
				m_mqttBuf[i] = g_IMEI[i];
			}
			m_mqttBuf[i] = '\0';
		}		
	}
	memset(m_sendBuf,0,1000);
	topicString.cstring = (char *)m_mqttBuf;
	len = MQTTSerialize_publish(m_sendBuf, 1000, 0, qos, 0, PacketId, topicString, InBuf, len);
	PacketId++;
	if(mode == 0)
	{
		SendGprsDat(m_sendBuf,len);
	}
	else
	{
		UipClient2Server(m_sendBuf,len);
	}
}

以上是MQTT实现步骤,只要按步骤实现,基本可以完成,但也需要根据个人要求更改。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 12:54:10  更:2021-07-30 12:54:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 18:06:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码