[作品提交] 【得捷电子Follow me第3期】任务6-2:温湿度数据记录仪

HonestQiao   2023-12-9 23:04 楼主

这篇帖子,在之前 【得捷电子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工具,就可以查看发布的消息,已经发送消息给开发板:

image.png  

三、完成温湿度信息的发布

完整的代码,在 【得捷电子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:

  • 温度:/device/report/temp
  • 湿度:/device/report/hum

完成上面的代码,并在设备上运行后,就可以在手机端进行操作了。

 

上面代码中的演示定时时间为cron_time=10秒,可以按照实际需要进行设置。

 

四、手机App接受发布的信息

手机端,使用mqtt dashboard工具,可以非常方便的进行接收。

具体设置步骤如下:

1. mqtt服务设置:

image.png  

 

2. 添加温度信息:

image.png  

image.png  

 

3. 添加湿度信息:

image.png  

4. 查看获取的数据:

image.png  

 

设置完成后,就可以在界面上,直接查看到开发板通过MQTT发送的温湿度信息了。

 

 

五、总结

MQTT是互联网通信的标准,通过MQTT协议和服务,可以让嵌入式的设备,方便快速的发布信息,然后使用其他设备进行接受和处理。

Seeed Studio XIAO ESP32C3的micropython也能够很好的接入MQTT服务,让开发板的功能不只限于开发板本身。

另外,上面的演示代码中,还包含了接受命令的部分,感兴趣的同学可以研究,通过手机App发送命令过来,控制灯或者蜂鸣器。

 

回复评论 (2)

通过手机App发送命令过来,控制灯或者蜂鸣器这个可以玩

点赞  2023-12-11 07:33
引用: Jacktang 发表于 2023-12-11 07:33 通过手机App发送命令过来,控制灯或者蜂鸣器这个可以玩

好好利用,这个工具能有很多用途

点赞  2023-12-14 23:41
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复