微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > 几步实现stm32上面移植mqtt

几步实现stm32上面移植mqtt

时间:10-02 整理:3721RD 点击:
最近项目需要,stm32上面使用到mqtt了,百度了下,发现网上资料还是挺少的,虽然有几份相关的资料,下载下来之后,看到了mqtt的底层代码竟然还有错误,这个问题导致了我后面一直调试不通,后来,我直接从官方下载了mqtt的源码用比较器比较后找到了原因,最后果断将官方的mqtt底层代码移植上来,mqtt的发布还是比较顺利,订阅虽然可以收到消息,但是由于没有移植os,发布消息时,订阅接受有时无法收到消息,这个还在优化,我使用的是stm32f103c8t6平台+w5500.其实只要带以太网接口就行。 首先我们从mqtt官方下载源码
http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.embedded-c.git/refs/
下载后将MQTTPacket下面的src文件都加入到自己的MDK工程中。

如果采用W5500的话,最好先用官方的TCP例子将TCP调试通,而且能保证访问外网,可以借鉴下网上那个STM32F405+W5500的例子,我觉得那个还是挺好的,我也是主要借鉴了那个例子,不过我还是不太喜欢他把TCP的建立封装到mqtt里面,一开始我也是采用他那种方法,不过一直出错,后来我采用了状态机实现,先让TCP和mqtt服务器建立TCP连接在调用mqtt的连接,发布等API,这样比较好调试。调试的话,我采用的是下面那个页面调试的http://m2m.demos.ibm.com/mqttclient/#log

其实真正要你实现的mqtt接口,主要是transport.c里面的几个API
int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
return send(SOCK_MQTT,buf,buflen);
}
/**
* @brief ×èèû·½ê½½óêÕTCP·tÎñÆ÷·¢ËíμÄêy¾Y
* @param buf êy¾Y′æ′¢ê×μØÖ·
* @param count êy¾Y»o3åÇø3¤¶è
* @retval D¡óú0±íê¾½óêÕêy¾Y꧰ü
*/
int transport_getdata(unsigned char* buf, int count)
{
return recv(SOCK_MQTT,buf,count);
}

/**
* @brief ′ò¿aò»¸ösocket2¢ᬽóμ½·tÎñÆ÷
* @param ÎT
* @retval D¡óú0±íê¾′ò¿a꧰ü
*/
int transport_open(void)
{
int32_t ret;
//D½¨ò»¸öSocket2¢°ó¶¨±¾μض˿ú5000
ret = socket(SOCK_MQTT,Sn_MR_TCP,4500,Sn_MR_ND);
if(ret != SOCK_OK){
printf("%d:Socket Error\r\n",SOCK_MQTT);
}else{
printf("%d:Opened\r\n",SOCK_MQTT);
}

//ᬽóTCP·tÎñÆ÷
ret = connect(SOCK_MQTT,domain_ip,1883);//¶Ë¿ú±ØDëÎa1883
if(ret != SOCK_OK){
printf("%d:Socket Connect Error\r\n",SOCK_MQTT);
}else{
printf("%d:Connected\r\n",SOCK_MQTT);
}
return ret;
}
/**
* @brief 1رÕsocket
* @param ÎT
* @retval D¡óú0±íê¾1رÕ꧰ü
*/
int transport_close(void)
{
close(SOCK_MQTT);
return 0;
}

以上的其实transport_open(void)我没调用,让状态机来实现了这步。
int mqtt_publish(char *pTopic,char *pMessage)
{
int32_t len,rc;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
unsigned char buf[200];
MQTTString topicString = MQTTString_initializer;
int msglen = strlen(pMessage);
int buflen = sizeof(buf);
data.clientID.cstring = "Client74925";
data.keepAliveInterval = 15;
data.cleansession = 1;
len = MQTTSerialize_connect(buf, buflen, &data); /* 1 */
topicString.cstring = pTopic;
len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen); /* 2 */
len += MQTTSerialize_disconnect(buf + len, buflen - len); /* 3 */
rc = transport_sendPacketBuffer(buf,len);
if (rc == len)
printf("Successfully published\n\r");
else
printf("Publish failed\n\r");
return 0;
}

=========================================

void do_tcp_client(void)
{
uint8 connect_State = 0;
uint16 len1;
switch(getSn_SR(SOCK_MQTT)) /*»ñè¡socketμÄ×′ì¬*/
{
case SOCK_CLOSED: /*socket′|óú1رÕ×′ì¬*/
socket(SOCK_MQTT,Sn_MR_TCP,local_port++,Sn_MR_ND);
break;
case SOCK_INIT: /*socket′|óú3õê¼»ˉ×′ì¬*/
connect(SOCK_MQTT,domain_ip,1883); /*socketᬽó·tÎñÆ÷*/
break;
case SOCK_ESTABLISHED: /*socket′|óúᬽó½¨á¢×′ì¬*/
memset(buff,0,500);
#if 0
connect_State=mqtt_subscrib("planets/earth",buff);
if(connect_State)
{
printf("%s",buff);

}
#endif
if(heartbeatflag>=TIME_5S)
{
heartbeatflag=0;
mqtt_publish("planets/earth","firstName: Brett, lastName:McLaughlin,email:aaaa");
}
break;
case SOCK_CLOSE_WAIT: /*socket′|óúμè′y1رÕ×′ì¬*/
close(SOCK_MQTT);
break;

}
}
上面的发布我每5s发送一条消息,公司的电脑加密了,无法截图,只能copy下网页测试的数据
============================================================================
(06:23:57.487) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.492) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.810) >> [planets/earth][retained] Hello world!(06:24:02.810) Subscribed to [planets/earth][qos 0](06:24:07.501) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:12.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:17.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:22.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:27.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:32.481) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:37.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:42.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:47.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa
订阅消息的函数目前暂且不公布,主要是还在优化,其次我觉得有点鸡肋,以其误导大伙,还不如不公开~~~~~~~~~~~~,如果大伙觉得有意思,可以把mqtt的ping也加上去,如果实用的话,这个还需要加入很多容错机制~~~~~~~~~~~~

do_tcp_client中有乱码

那个是中文注释,不知道为什么复制出来就乱码了

楼主本人初学者,想问下通过STM32+W5500编程实现mqtt好,还是直接用W7500的mqtt好?
哪个方案实现发布订阅更稳定、开发更快速?能否给些对比指导意见。不甚感激

w7500,你有mqtt的工程?w7500只不过自己内嵌了ARM核,都差不多。不过搞mqtt的话,一般会用到json,这个最好选择sram大些,至少三十几k最好了,我现在用20k sram,不够用

这是我们的一个工程师做的一个智能家居小屋案例教程

我们云巴是基于 MQTT 协议、采用Erlang/OTP架构设计的实时通信系统。 除了可以应用于物联网通信之外,还可以应用于APP、Web端的实时聊天以及消息推送,具有实时稳定、适应高并发的特点。

应用场景也很广泛,可以看下我们实现的一个实时弹幕的案例demo: 实时弹幕案例demo

你好,楼主,我想问下:DM9051和W5500两个芯片,W5500把TCP/IP协议固化在里面,简单方便,而DM9051则是便宜很多,这种情况下,在公司要求cost down的时候,如何选择。

我觉得两个都行,稳定可靠,开发周期短是第一位,价格可以靠后点,w5500的并发测试还是不错的。不知道你对于Lwip 熟悉吗,如果熟悉的话,可以尝试搞下dm9051方案

我下一步就准备搞lwip 整mqtt,现在并发测试w5500 500个设备下发命令没有问题,不丢包

楼主在stm32上移植的mqtt 在项目中使用情况怎么样。有带系统吗?

挺稳定的,没带系统,flash和ram都处于临界值了。

你好,关于mqtt的移植,你淘宝店里有现成的板子可以调试的吗,想进一步跟你交流,QQ1934148690

我淘宝有现成的w5100模块

你们服务器有并发个数的测试报告嘛

楼主好,我现在实现了stm32+lwip+mqtt,现在需要和云进行通信,需要用到mqtt的8883端口,所以要添加SSL加密协议,看网上说SSL加密协议会明显加重网络的负载,请问怎么破?

既然你都知道了加了SSL后会增加网络负载,那你还加?没什么破解的,个人建议是不用ssl,ssl对服务器内存消耗很大,单项加密传输的话,如果不开启ssl的话,服务器可以搞100W,可能加了就差不多20W左右。

一般加SSL对主芯片性能要求是什么啊?

首先你要tcp上移植ssl?对内存也有一定要求。还有你需要申请证书,如果网络差的话,你可能连握手这块都挂了,

你是移植好了ssl还是打算移植呢?如果要移植的话,有好多几种ssl协议栈,openssl,PolarSSL,MartixSSL,我个人建议采用PolarSSL,这个被ARM收购了改名成了mbedtls,自己移植尝试下就可以知道具体的数据

学习了,以后移植试下。

打号

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top