切换到宽版
  • 6403阅读
  • 29回复

[ARM]基于STM32 ESP8266 AT指令的MQTT 移植 [复制链接]

上一主题 下一主题
离线sangarr

发帖
28
M币
53
专家
0
粉丝
6
只看该作者 10楼 发表于: 06-03
书接上回
2.3客户端订阅主题
在实际应用场景中,每个客户端可以根据自己的需要,来订阅需要接收的消息(数据),并且完成相应的动作。对于刚接触MQTT这个协议的人来说,很多人分不清楚“订阅”和“发布”到底是怎么回事儿。我的理解比较简单直接,对于客户端来说,“订阅”相当于从服务器接收数据;“发布”相当于发送数据到服务器。那么问题来了,服务器在向客户端发送消息的时候,是不是把每一条消息发送给所有的客户端呢?答案是否定的!实际上,服务器只会把消息发送到订阅了“主题(topic)”的客户端。举个例子来说,我自己作为一个客户端,CCTV作为一个服务器,我要想接收关于俄罗斯世界杯的消息,那么我就需要先去CCTV订阅“俄罗斯世界杯”的主题。
      如何订阅呢,总共分两步:
2.3.1 客户端向服务器发送订阅主题(我向CCTV发送“俄罗斯世界杯”)
2.3.2服务器向客户端发送订阅成功/失败的消息。(“恭喜你,订阅成功”)
下面,我们结合实际的数据看一看,客户端订阅主题的时候,向服务器发送了什么内容。回到我们的例子,我们要向服务器发送的订阅消息是“/report/888888/05dcff373234544843166328”,还是用咱们的Wireshark软件,抓取数据来分析。


由上图可以看出,客户端向服务器发送的数据为(HEX):82
82的二进制是1000 0010,打开MQTT-3.1.1-CN.pdf第37页


接下来一个数据(HEX):2C,这个对应pdf里面的协议,应该是这一帧数据的长度,十进制是44,就是wireshark软件抓取数据的msg len:44.
这里我们分析2个字节的数据,后面的大家可以根据协议自己去分析了。
到这里,我作为一个客户端,已经完成了,向CCTV发送订阅“俄罗斯世界杯”这个主题,如果我订阅成功的话,服务器告诉客户端,你订阅成功了。
作为服务器,如果客户端订阅成功的话,应该向客户端发送什么样的数据呢?大家可以根据MQTT-3.1.1-CN.pdf的协议内容,先猜一下。
看下图,服务器向客户端发送了90 03 00 01 00,表示客户端订阅成功。也就是说,CCTV告诉我说,你订阅的主题“俄罗斯世界杯”,成功了。


至此,我们提纲中的2.3 客户端订阅”就讲完了。如果你有什么问题,可以在帖子下面留言。
由于时间关系,2.4 客户端发布”我就简单带过,大家可以用抓包软件和mqtt.fx自己进行分析。下次更新帖子的时候,我们就开始进行移植教程。这里,我还是简单介绍一下“发布”,客户端向服务器发送一条消息,服务器是否接收到,要不要给客户端一个回执,是根据协议里面的Qos来判断的。
没有回执的发布:Qos=0,
有回执的发布:Qos = 1或者Qos = 2,大家看下图,一下就明白了








本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
离线sangarr

发帖
28
M币
53
专家
0
粉丝
6
只看该作者 11楼 发表于: 06-03
硬件连接和软件下载
因为后面我们就要进行软件移植了,这里先大概介绍一下我们用到的资源
硬件方面:单片机开发板(STM32F103VET6+ESP8266)

1、单片机usart2连接esp8266串口0
2、单片机可以通过IO口给esp8266复位
如下图




感谢我的好兄弟“金老师”给我的开发板,如果他能看到本帖的话,相信他会很想念我的。
软件方面:
1、FreeRTOS 会点基础就行,知道怎么用消息队列来进行线程间通信

2、STM32串口2空闲中断、DMA接收
下载MQTT软件包,准备移植。

1、打开MQTT主页http://mqtt.org/


2、点击Software,进入后点击Client libraries


3、在各种编程语言中,选择C语言下面的”Eclipse Paho Embedded C“


4、进入GitHub下载链接,下载解压。




5、下载后将MQTTPacket下面的src文件都加入到自己的MDK工程中。
6、将MQTTPacket\samples目录下的transport.c和pub0sub1.c添加到MDK工程中MQTT目录下
下次继续吧,明天还要上班。



本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
离线sangarr

发帖
28
M币
53
专家
0
粉丝
6
只看该作者 12楼 发表于: 06-03
已经下载好的mqtt固件包


这个是已经下载好的固件包
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
离线sangarr

发帖
28
M币
53
专家
0
粉丝
6
只看该作者 13楼 发表于: 06-03
ESP8266 AT指令手册


这2个文档是ESP8266 AT命令的手册,以后只要用到命令有
1、查询ESP8266连接状态
2、ESP8266连接WIFI
3、ESP8266连接TCP (IP+Port)
4、ESP8266向服务器发送数据
5、ESP8266配网(smart config)
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
离线tempchar

发帖
133
M币
3323
专家
5
粉丝
31
只看该作者 14楼 发表于: 06-04
曾经我想用at指令实现mqtt,琢磨了字符串处理、状态机发现太tmd难写了!果断放弃,用nodemcu重写at固件
离线sangarr

发帖
28
M币
53
专家
0
粉丝
6
只看该作者 15楼 发表于: 06-04
等我给你上传一个状态机的代码,没有使用固件,自己实现的mqtt协议。
离线沙学政
发帖
1
M币
473
专家
0
粉丝
0
只看该作者 16楼 发表于: 06-05
楼主写的很详细,非常感谢,学到新东西了,开心
离线gxiao69
发帖
1
M币
-497
专家
0
粉丝
0
只看该作者 17楼 发表于: 06-13
刚好最近也想弄这个玩意,跟着楼主学习学习。非常期待楼主的更新
离线冢中枯骨

发帖
72
M币
992
专家
0
粉丝
7
只看该作者 18楼 发表于: 06-13
加油 ,不容易的
离线sangarr

发帖
28
M币
53
专家
0
粉丝
6
只看该作者 19楼 发表于: 06-25
完结篇

3.2 需要用户实现的函数
3.2.1发送数据函数 int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen),以下是函数实现

int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen){
    int rc = 0;

    if(Esp8266_GetTcpStatus())    {
        rc = Esp8266_Tcp_Send(sock, buf, buflen);    }

    else    {
        transport_close(0);        rc = -1;
    }    return rc;
}3.2.2 读取数据函数 int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)),以下是函数实现
这里要特别强调一下,MQTTPacket_read()是阻塞方式读取的数据,getfn是函数指针,调用如下
if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK)

int transport_getdata(unsigned char* buf, int count){
    int rc = MQTT_RB_Read(buf, count);    return rc;
}其实封装好了这2个函数以后,MQTT发送和接收数据的函数就写完了。接着,我们就可以来连接服务器、订阅消息、发布消息、发送心跳了
3.2.3 vMQTT_Handler_Task这个就是mqtt的服务线程,里面用了一个状态机来完成上述过程。
3.2.4说明
由于推送服务器是要收费的,目前没有找到免费的推送服务器,所以,我在调试的时候也是用的公司服务器,在我上传的源码里,本着人道主义精神,我会把服务器的域名和端口号删掉,以注释的方式出现。这一点,还请大家见谅。如果想看到发布订阅的过程,可以自己搭建阿波罗服务器,在本地实现推送消息的功能。搭建这个服务器的教程,网上非常多。以后我们有时间,再来写一写搭建服务器的教程。另外,由于时间紧迫,代码没有优化和测试,如果你有好的意见或者建议,可以留言,一起讨论,共同进步。

3.3 测试及优化
上传调试通过的代码

本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限