为什么这个 MQTT 客户端通过 MicroPython 的 webREPL 可以正常工作,但在 ESP32 的 main.py 中却失败了?

Why does this MQTT client works fine through MicroPython's webREPL but fails in the main.py of the ESP32?

我目前正在从事一个物联网项目,该项目需要在 ESP32(准确地说是 wESP32)和配置为代理的 Raspberry Pi 之间传输传感器数据。到目前为止,从我读到的内容来看,MQTT 协议似乎完全符合我的需求,因此我 运行 Pi 上的 Mosquitto 代理以及 micropython GitHub 上提供的 MQTT 简单客户端库存储库。

在 MicroPython WebREPL 中执行的第一个测试已经成功,因为我已经能够使用以下代码接收从 ESP 发布的数据:

Welcome to MicroPython!
Password:
WebREPL connected
>>> from umqtt.simple import MQTTClient
>>> c = MQTTClient("umqtt_client", "rapsberrypi")
>>> c.connect()
0
>>> c.publish(b"sensors/temperature", "{:.1f}".format(21.35))
>>> c.disconnect()
>>>

然而,一旦我尝试 运行 在 main.py 文件中启动相同的代码,或者使用以太网 screenrshell 通过串行端口,我得到了以下错误。

Started webrepl in normal mode
MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32
Type "help()" for more information.
>>> I (4379) ethernet: LAN cable connected
I (5359) event: eth ip: 192.168.1.62, mask: 255.255.255.0, gw: 192.168.1.1
I (5359) ethernet: Got IP
from umqtt.simple import MQTTClient
>>> c = MQTTClient("umqtt_client", "rapsberrypi")
>>> c.connect()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "umqtt/simple.py", line 57, in connect
IndexError: list index out of range
>>>

对于某些上下文,这里是 umqtt/simple.py 文件的第 57 行:

55  def connect(self, clean_session=True):
56      self.sock = socket.socket()
57      addr = socket.getaddrinfo(self.server, self.port)[0][-1]
58      self.sock.connect(addr)

如果你对这里发生的事情有任何线索,请告诉我!

在这行代码中:

c = MQTTClient("umqtt_client", "rapsberrypi")

构造函数的第二个参数 - "raspberrypi" - 标识代理(服务器)。

这很可能是以这样一种方式定义的,即只有您 Raspberry Pi 上的软件 运行 才能解决它。在 Pi 以外的地方,软件 运行 看不到该名称。

在您的 ESP32 上的代码 运行 中,将“raspberrypi”替换为您的 Raspberry Pi 的 IP 地址或可解析(完全限定的域名)名称。请注意,127.0.0.1 是环回接口的 IP 地址,Pi 上非 运行 的软件无法访问它。

您可以使用ifconfig 命令列出您的网络接口;寻找一个名称类似于 wlan0 的 wifi 或 eth0 的有线以太网,并使用与该接口关联的 IP 地址。

一旦您完成此操作,如果您仍然无法联系到代理,则代理可能被配置为不响应与它 运行 不在同一台机器上发出的请求。