这篇帖子,在之前 【得捷电子Follow me第3期】任务5:使用外部传感器:温湿度传感器 的基础上,加上MQTT,使得温湿度信息通过MQTT发布到服务端,然后,再使用手机端App接受,并进行呈现。
一、mqtt服务器
可以自己搭建mqtt服务器:https://www.emqx.io/zh/downloads?os=Ubuntu ;搭建好了以后,在管理界面,添加一个用户,以便连接。
当然,也可以使用EMQX官方提供的公共服务器进行测试:https://www.emqx.com/zh/mqtt/public-mqtt5-broker
二、micropython连接MQTT服务
在Seeed Studio XIAO ESP32C3的micropython中连接MQTT服务,可以使用umqttsimple库,下载地址为:https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/MQTT/umqttsimple.py
连接到mqtt并发送信息,可以使用如下的代码进行测试:
import time
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
esp.osdebug(None)
import gc
gc.collect()
ssid = 'OpenBSD'
password = '********'
mqtt_server = '192.168.1.15'
mqtt_user = 'user_esp32c3'
mqtt_pass = '123456'
client_id = ubinascii.hexlify(machine.unique_id())
topic_sub = b'/device/cmd'
topic_pub = b'/device/report'
last_message = 0
message_interval = 5
counter = 0
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Connection successful')
print(station.ifconfig())
def sub_cb(topic, msg):
print((topic, msg))
def connect_and_subscribe():
global client_id, mqtt_server, mqtt_user, mqtt_pass, topic_sub
client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_pass)
client.set_callback(sub_cb)
client.connect()
client.subscribe(topic_sub)
print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))
return client
def restart_and_reconnect():
print('Failed to connect to MQTT broker. Reconnecting...')
time.sleep(10)
machine.reset()
try:
client = connect_and_subscribe()
except OSError as e:
restart_and_reconnect()
while True:
try:
new_message = client.check_msg()
if new_message != 'None':
client.publish(topic_pub, b'received')
time.sleep(1)
except OSError as e:
restart_and_reconnect()
注意,上述代码中,mqtt服务的设置请修改为对应的:
mqtt_server = '192.168.1.15'
mqtt_user = 'user_esp32c3'
mqtt_pass = '123456'
连接mqtt服务成功后,使用下面的调用,即可发布消息:
client.publish(topic_pub, b'需要发布的消息')
在EMQX的管理后台,使用WebSocket工具,就可以查看发布的消息,已经发送消息给开发板:
三、完成温湿度信息的发布
完整的代码,在 【得捷电子Follow me第3期】任务5:使用外部传感器:温湿度传感器 的基础上,结合上面的MQTT部分的代码,具体如下:
import utime
from machine import Pin, SoftI2C
import ahtx0
from color_setup import ssd
from color_setup import i2c
from gui.core.nanogui import refresh
from gui.core.writer import CWriter
from gui.widgets.textbox import Textbox
from gui.widgets.label import Label
from gui.core.colors import *
# 字体调用
import gui.fonts.arial10 as arial10
import machine
import network
from umqttsimple import MQTTClient
import ubinascii
import gc
gc.collect()
mqtt_server = '192.168.1.15'
mqtt_user = 'user_esp32c3'
mqtt_pass = '123456'
client_id = ubinascii.hexlify(machine.unique_id())
topic_sub = b'/device/cmd'
topic_pub = b'/device/report'
last_message = 0
message_interval = 5
counter = 0
# 无线连接设置
wifi_ssid = "OpenBSD"
wifi_password = "********"
def sub_cb(topic, msg):
print((topic, msg))
def connect_and_subscribe():
global client_id, mqtt_server, mqtt_user, mqtt_pass, topic_sub
client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_pass)
client.set_callback(sub_cb)
client.connect()
client.subscribe(topic_sub)
print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))
return client
def restart_and_reconnect():
print('Failed to connect to MQTT broker. Reconnecting...')
time.sleep(10)
machine.reset()
# 清屏
refresh(ssd, True)
# 显示输出
CWriter.set_textpos(ssd, 0, 0)
wri = CWriter(ssd, arial10, verbose=False)
wri.set_clip(True, True, False)
# 联网处理
def scan_and_connect():
station = network.WLAN(network.STA_IF)
station.active(True)
if not station.isconnected():
print("Scanning for WiFi networks, please wait...")
for ssid, bssid, channel, RSSI, authmode, hidden in station.scan():
print("* {:s}".format(ssid))
print(" - Channel: {}".format(channel))
print(" - RSSI: {}".format(RSSI))
print(" - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid))
print()
while not station.isconnected():
print("Connecting...")
station.connect(wifi_ssid, wifi_password)
utime.sleep(10)
print("Connected!")
print("My IP Address:", station.ifconfig()[0])
# 联网
ssd.fill(0)
refresh(ssd)
Label(wri, 5, 0, "WiFi Connect...")
refresh(ssd)
scan_and_connect()
Label(wri, 5, 0, "WiFi Connect OK.")
refresh(ssd)
utime.sleep(2)
try:
Label(wri, 5, 0, "MQTT Connect...")
refresh(ssd)
client = connect_and_subscribe()
Label(wri, 5, 0, "MQTT Connect OK.")
refresh(ssd)
utime.sleep(2)
except OSError as e:
restart_and_reconnect()
ssd.fill(0)
refresh(ssd)
# 显示日期
txt = Label(wri, 0, 0, "Environmental information")
pargs = (13, 2, 124, 4) # Row, Col, Width, nlines
tb = Textbox(wri, *pargs, clip=False)
sensor = ahtx0.AHT10(i2c)
last_time = 0
cron_time = 10 # 定时间隔时间
while True:
if last_time == 0 or utime.time() - last_time == cron_time:
last_time = utime.time()
else:
utime.sleep(1)
continue
print("\nlast_time: %d" % last_time)
print("Temperature: %0.2f C" % sensor.temperature)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
tb.clear()
tb.append("\n", ntrim = 100)
tb.append(" Temperature: %0.2f C" % sensor.temperature, ntrim = 100)
tb.append(" Humidity: %0.2f %%" % sensor.relative_humidity, ntrim = 100)
refresh(ssd)
client.publish(b"%s/temp" % topic_pub, b'{"value":%0.1f}' % sensor.temperature)
client.publish(b"%s/hum" % topic_pub, b'{"value":%0.1f}' % sensor.relative_humidity)
utime.sleep(5)
上面代码的核心在于循环部分,原来是显示,现在多了:
client.publish(b"%s/temp" % topic_pub, b'{"value":%0.1f}' % sensor.temperature)
client.publish(b"%s/hum" % topic_pub, b'{"value":%0.1f}' % sensor.relative_humidity)
这两行代码,负责发布温度信息和湿度信息到MQTT服务,需要注意发布的topic:
完成上面的代码,并在设备上运行后,就可以在手机端进行操作了。
上面代码中的演示定时时间为cron_time=10秒,可以按照实际需要进行设置。
四、手机App接受发布的信息
手机端,使用mqtt dashboard工具,可以非常方便的进行接收。
具体设置步骤如下:
1. mqtt服务设置:
2. 添加温度信息:
3. 添加湿度信息:
4. 查看获取的数据:
设置完成后,就可以在界面上,直接查看到开发板通过MQTT发送的温湿度信息了。
五、总结
MQTT是互联网通信的标准,通过MQTT协议和服务,可以让嵌入式的设备,方便快速的发布信息,然后使用其他设备进行接受和处理。
Seeed Studio XIAO ESP32C3的micropython也能够很好的接入MQTT服务,让开发板的功能不只限于开发板本身。
另外,上面的演示代码中,还包含了接受命令的部分,感兴趣的同学可以研究,通过手机App发送命令过来,控制灯或者蜂鸣器。
引用: Jacktang 发表于 2023-12-11 07:33 通过手机App发送命令过来,控制灯或者蜂鸣器这个可以玩
好好利用,这个工具能有很多用途