單片機使用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;
- 登錄用戶 需要用戶名 密碼和設備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);
}
}
- 訂閱主題 這里我以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);
}
}
- 發送心跳包,根據自己要求隔段時間發送
/*
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);
}
}
- 發布主題 根據自己要求處理
/*
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實作步驟,只要按步驟實作,基本可以完成,但也需要根據個人要求更改,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291114.html
標籤:其他
