我是靠谱客的博主 动人橘子,最近开发中收集的这篇文章主要介绍单片机使用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();
//Á¬½Ó·þÎñÆ÷
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] = '';
}
if(SysInfo.MqttUserName[MQT_TXT_DATLEN] == 0)
{
//MQTT用户名为空 用默认值
for(i = 0; i < 4; i++)
{
m_mqttBuf[i + MQTT_PWD] = mqttDef[i];
}
m_mqttBuf[i] = '';
}
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] = '';
}
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] = '';
}
for(i = 0; i < 60; i++)
{
if(!ISASCCHAR(m_mqttBuf[i]))
{
break;
}
}
m_mqttBuf[i++] = '/';
m_mqttBuf[i++] = '+';
m_mqttBuf[i++] = '';
}
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] = '';
}
}
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实现步骤,只要按步骤实现,基本可以完成,但也需要根据个人要求更改。

最后

以上就是动人橘子为你收集整理的单片机使用C语言实现MQTT协议的全部内容,希望文章能够帮你解决单片机使用C语言实现MQTT协议所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部