自学内容网 自学内容网

esp32c3开发板通过micropython的mqtt库连MQTT物联网消息服务器

MQTT介绍

MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息协议,旨在设备之间进行通信,尤其是在网络条件较差的情况下。MQTT v3.1.1 和 MQTT v5 是该协议的两个主要版本。

MQTT v3.1.1:

  • 优点:
    • 成熟和广泛支持:作为较早的版本,v3.1.1 得到了广泛的实现和支持,包括各种客户端库和服务器(代理)。
    • 稳定性:由于长时间的使用,v3.1.1 版本的稳定性和可靠性得到了验证。
    • 资源消耗低:设计上考虑了低带宽和低功耗设备,因此非常适合物联网(IoT)应用。
  • 缺点:
    • 功能限制:与 v5 相比,v3.1.1 缺少一些高级功能,如消息的精确一次性传递(Exactly-Once Delivery)和用户属性(User Properties)。
    • 可扩展性:v3.1.1 的一些限制可能使得在某些高级场景下的使用受到限制。

MQTT v5:

  • 优点:
    • 增强的功能:v5 引入了许多新特性,包括消息的精确一次性传递、用户属性、共享订阅(Shared Subscriptions)、动态消息过滤(Dynamic Message Filters)等,这些特性提高了协议的灵活性和可扩展性。
    • 更好的错误处理:v5 提供了更详细的错误代码,有助于客户端更好地理解和处理错误情况。
    • 改进的会话恢复:v5 改进了会话恢复机制,使得客户端可以在断开连接后更快地恢复状态。
  • 缺点:
    • 兼容性问题:由于是较新的版本,v5 的支持可能不如 v3.1.1 广泛,这可能导致与旧系统或客户端的不兼容问题。
    • 实现复杂性:新特性的引入可能增加了实现的复杂性,对于资源受限的设备来说,这可能是一个挑战。

总的来说,MQTT v3.1.1 由于其成熟度和广泛支持,仍然是许多应用的首选。而 MQTT v5 提供了更多的高级功能和更好的错误处理,适合需要这些特性的新应用。选择哪个版本取决于具体的应用需求、资源限制以及对新特性的需求。随着时间的推移,v5 的支持和采用可能会增加,从而减少兼容性问题。

mqtt服务器软件Mosquitto

当前比较流行的mqtt服务器是:Mosquitto、EMQTT、HiveMQ等,经过短暂的了解,最终决定使用Mosquitto。

FreeBSD下安装

pkg install mosquitto

安装好后提示:

Message from mosquitto-2.0.18:

The mosquitto MQTT Python driver is now provided by net/py-paho-mqtt

FreeBSD下启动服务,若没有写入rc.conf文件,则启动时需要加上onestart

sudo service mosquitto start
sudo service mosquitto onestart

Ubuntu下安装

安装服务器

sudo apt install mosquitto

安装客户端

sudo apt install mosquitto-clients

启动并配置服务

以Ubuntu下为例。

启动服务

可以使用service启动服务:

​sudo service mosquitto start

当然一开始不知道,直接使用运行mosquitto命令启动了服务: 

mosquitto

1731855204: Warning: Unable to drop privileges to 'mosquitto' because this user does not exist. Trying 'nobody' instead.

1731855204: mosquitto version 2.0.18 starting

1731855204: Using default config.

1731855204: Starting in local only mode. Connections will only be possible from clients running on this machine.

1731855204: Create a configuration file which defines a listener to allow remote access.

1731855204: For more details see https://mosquitto.org/documentation/authentication-methods/

1731855204: Opening ipv4 listen socket on port 1883.

1731855204: Opening ipv6 listen socket on port 1883.

1731855204: mosquitto version 2.0.18 running

后来才知道可以用service启动和停止服务

后来发现端口只绑定了本地ip,要绑定0.0.0.0,则需要修改配置。

客户端测试:

首先在服务器本机测试

执行mosquitto_sub客户端侦听服务:

mosquitto_sub -t "mytopic"

执行mosquitto_pub发布信息

另一个终端执行:

mosquitto_pub -t "mytopic" -m "Hello, MQTT!!"
1731855866: New connection from 127.0.0.1:29987 on port 1883.
1731855866: New client connected from 127.0.0.1:29987 as auto-E0721C4C-5B09-EF6C-E3B3-892DBEDC9C05 (p2, c1, k60).
1731855866: Client auto-E0721C4C-5B09-EF6C-E3B3-892DBEDC9C05 disconnected.

 就会发现刚才的信息Hello, MQTT!!被侦听端收到了:

mosquitto_sub -t "mytopic"
Hello, MQTT!!

发送消息的详细命令:

mosquitto_pub -t "mytopic" -m "Hello, MQTTexitlast1" -h "192.168.0.13"

设置了用户验证后,就需要带用户名和口令参数,比如

mosquitto_pub -t "mytopic" -m "Hello, MQTT!!" -h 192.168.0.13 -u ral -P ral

修改mosquitto配置

添加用户

在/etc/mosquitto目录下修改配置文件,修改mosquitto.conf文件,加入这样两句:

allow_anonymous false
password_file /etc/mosquitto/passwd

执行mosquitto_passwd创建用户ral并写入/etc/mosquitto/passwd文件:

sudo mosquitto_passwd -c /etc/mosquitto/passwd ral
Password: 
Reenter password: 

这样发送和接收信息都需要用户验证。

修改绑定服务到0.0.0.0 

在/etc/mosquitto/conf.d目录里创建bindip.conf文件,加入这一句:

bind_address 0.0.0.0

这样服务就能监听0.0.0.0 ,也就是其它非本机也可以连它。

 如果原来ufw防火墙没有放开,那么需要放开1883端口:

sudo ufw allow 1883

 这时候再测试一下信息:

mosquitto_pub -t 'mytopic' -m 'ehllo' -u 'ral' -P 'ral'

客户端应该能接收到信息:

mosquitto_sub -t "mytopic"
Hello, MQTT!!

重启mosquitto服务

每次修改mosquitto配置后,都要重启服务

sudo service mosquitto restart

带用户验证的测试

消息接收:

# 带上用户验证
mosquitto_sub -t "mytopic" -u 'ral' -P 'ral'
# 或是带上地址
mosquitto_sub -t "mytopic" -u 'ral' -P 'ral'  -h '192.168.0.13'

消息发送:

# 带用户验证的消息发送
mosquitto_pub -t 'mytopic' -m 'hello world' -u 'ral' -P 'ral'
# 带上服务器ip地址
mosquitto_pub -t 'mytopic' -m 'hello world2' -u 'ral' -P 'ral' -h '192.168.0.13'

接收端接收到信息:

mosquitto_sub -t "mytopic" -u 'ral' -P 'ral'  -h '192.168.0.13'
hello world

证明配置设置的正确,服务器一切正常! 

esp32c3开发板配置

esp32c3开发板烧录micropython 交互环境,参见:esp32c3安装micropython环境-CSDN博客

烧录好固件,启动开发板,进入micropython交互环境。参见:esp32-c3开发板开箱第一步:连上usb口看log信息-CSDN博客

开发板启动wifi连上网

交互界面里执行下面代码连wifi,注意wifi的名字和密码需要根据实际情况修改:

import network
import time
nic = network.WLAN(network.STA_IF)
nic.active(True)
# nic.scan()
if not nic.isconnected():
    nic.connect("wifi名字", "wifi密码")
    print("Waiting for connection...")
    while not nic.isconnected():
        time.sleep(1)


print(nic.ipconfig("addr4"))

 如果能输出网络信息,那么就证明连上了wifi

>>> print(nic.ipconfig("addr4"))
('192.168.0.104', '255.255.255.0')

开发板接收mqtt消息代码

 继续执行esp32c3开发板里的micropython代码:

from umqtt.simple import MQTTClient

# 定义 MQTT 代理的地址和端口
SERVER = "192.168.0.13"
PORT = 1883

# 定义客户端 ID、用户名和密码
CLIENT_ID = "my_client_id"
USERNAME = "ral"
PASSWORD = "ral"

# 定义要订阅的主题
TOPIC = b"mytopic"

# 创建 MQTTClient 实例,并传递用户名和密码参数
client = MQTTClient(CLIENT_ID, SERVER, PORT, user=USERNAME, password=PASSWORD)

# 连接到 MQTT 代理
client.connect()

# 订阅主题
client.subscribe(TOPIC)

# 定义消息回调函数
def sub_cb(topic, msg):
    print("Received message: ", msg)


# 设置消息回调函数
client.set_callback(sub_cb)

# 进入消息循环
while True:
    client.wait_msg()

 中文会占用输入缓冲区大小,有点干扰输入,所以可以黏贴下面去掉中文注释的代码:

from umqtt.simple import MQTTClient

SERVER = "192.168.0.13"
PORT = 1883

CLIENT_ID = "my_client_id"
USERNAME = "ral"
PASSWORD = "ral"

TOPIC = b"mytopic"

client = MQTTClient(CLIENT_ID, SERVER, PORT, user=USERNAME, password=PASSWORD)

client.connect()

def sub_cb(topic, msg):
    print("Received message: ", msg)



client.set_callback(sub_cb)

client.subscribe(TOPIC)

while True:
    client.wait_msg()

不要一次黏贴一大段,可以2-3句黏贴,比如像这句:client = MQTTClient(CLIENT_ID, SERVER, PORT, user=USERNAME, password=PASSWORD) 比较长,就单独黏贴。

开发板运行后,用一个客户端发送消息 

# 本机
mosquitto_pub -t 'mytopic' -m 'hello world' -u 'ral' -P 'ral'
# 非本机
mosquitto_pub -t 'mytopic' -m 'hello world2' -u 'ral' -P 'ral' -h '192.168.0.13'

这时候开发板交互界面里就能接收到发送的信息了!

>>> while True:
...     client.wait_msg()
... 
Received message:  b'hello'
48

这样我们这次实践就完成了!

总结

总体是一次非常愉快的esp32c3开发板与mqtt服务器通信的实践操作。但是由于是第一次使用mosquitto,对它的配置不熟悉,同时也是第一次使用micropython里的mqtt模块(umqtt)进行通信,对它也不熟悉,所以这次实践中箭走了很多弯路,碰到很多问题,幸运的是都解决了。

mqtt服务器,用了半天时间选型为mosquitto,大约这就是眼缘吧,毕竟它是eclicps旗下的,而且FreeBSD还有它的pkg包。安装mosquitto后,需要修改其配置,比如添加用户和密码到指定的文件,修改绑定ip到0.0.0.0,在Ubuntu服务器ufw防火墙中放开1883端口。

esp32c3开发板这块,首先需要烧micropython交互环境的固件,然后usb串口登录到micropython的交互界面,输入python代码。先要配置好WiFi启动tcp/ip网络,然后就是调用umqtt模块进行侦听mqtt消息。micropython的缓冲区较小,不能像普通python里面那样一下子可以黏贴太长的代码段,这也需要注意。

调试

esp32c3上mqtt连接失败

其实这是一个大问题,后来是分解成几个小问题一一解决的。

>>> mqtt_client = connect_mqtt()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "<stdin>", line 3, in connect_mqtt

  File "umqtt/simple.py", line 66, in connect

OSError: [Errno 104] ECONNRESET

想起来了,原来是mqtt服务器跨了网段,为了简化测试,后来就用了linux客户端mosquitto_pub和mosquitto_sub -t "mytopic" 先进行测试。(其实esp32的网络模块是可以联网、跨网段通信的)

在同一网段开服务器,还是不行

原来是ufw防火墙没有放开,放开1883端口

sudo ufw allow 1883

发现没有绑定0.0.0.0,修改配置文件/etc/mosquitto/conf.d/bindip.conf,加入这句:

bind_address 0.0.0.0

然后重启服务

sudo service mosquitto restart

用客户端mosquitto_pub再测试有如下报错: 

发送信息报错Connection Refused: not authorised.

mosquitto_pub -t "mytopic" -m "Hello, MQTTexitlast1" -h "192.168.0.13"

Connection error: Connection Refused: not authorised.

添加用户:

sudo mosquitto_passwd -c /etc/mosquitto/passwd ral
Password: 
Reenter password: 

在/etc/mosquitto目录下的mosquitto.conf文件中加入信息:

allow_anonymous false
password_file /etc/mosquitto/passwd

重启服务后测试: 

mosquitto_pub -t "mytopic" -m "Hello, MQTT!!" -h 192.168.0.13 -u ral -P ral

终于不报用户验证错了,现在报错:

esp32连mosquitto报错 Subscribe callback is not set

>>> client.subscribe(TOPIC)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "umqtt/simple.py", line 152, in subscribe

AssertionError: Subscribe callback is not set

是那段代码又问题,换代码:

from umqtt.simple import MQTTClient

SERVER = "mqtt.eclipse.org"
PORT = 1883

CLIENT_ID = "my_client_id"
USERNAME = "my_username"
PASSWORD = "my_password"

TOPIC = b"test/topic"

SERVER = "192.168.0.13"
PORT = 1883

CLIENT_ID = "my_client_id"
USERNAME = "ral"
PASSWORD = "ral"

TOPIC = b"mytopic"

client = MQTTClient(CLIENT_ID, SERVER, PORT, user=USERNAME, password=PASSWORD)

client.connect()

def sub_cb(topic, msg):
    print("Received message: ", msg)



client.set_callback(sub_cb)

client.subscribe(TOPIC)

while True:
    client.wait_msg()

这个代码就ok了!

esp32 micropython里黏贴python代码有时候会出错

发现黏贴代码到后面就乱了,估计是黏贴长度超限导致的,减少黏贴长度,问题解决。


原文地址:https://blog.csdn.net/skywalk8163/article/details/143831910

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!