赞
踩
在单片机使用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;
/* 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); } }
/* 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实现步骤,只要按步骤实现,基本可以完成,但也需要根据个人要求更改。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。