WLED Si7021_MQTT_HA Usermod:将温湿度传感器数据发布到 MQTT 并自动注册 Home Assistant
【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED
WLED 不仅是一个灯带控制器,其 usermod 扩展机制还允许把 ESP32/ESP8266 变成通用传感器节点。本文以仓库中的 Si7021_MQTT_HA usermod 为主线,讲解如何通过 I²C 读取 Si7021 温湿度传感器、按固定周期发布到 WLED 内置 MQTT 设备主题,以及自动发布 Home Assistant MQTT Auto-Discovery 配置、让传感器在 Home Assistant 中免手动配置直接出现。读完本文,你可以完成从接线、PlatformIO 编译配置到 MQTT 主题与 HA 传感器注册的完整部署,并理解该 usermod 在源码层面的生命周期与调度细节。
功能定位与 MQTT 主题设计
该 usermod 实现了 Si7021 I²C 温湿度传感器 的支持。需要注意的是:传感器数据不会显示在 WLED 的 Web UI 上,它的作用纯粹是作为传感器数据的 MQTT 发布器。核心行为如下:
- 基础数据(温度、湿度)发布到 WLED 内置 MQTT 设备主题(
$mqttDeviceTopic,即 WLED 自身 MQTT 功能所使用的设备前缀)下:
temperature: $mqttDeviceTopic/si7021_temperature humidity: $mqttDeviceTopic/si7021_humidity- 可选的衍生量(由代码调用
EnvironmentCalculations库计算得出):
heat_index: $mqttDeviceTopic/si7021_heat_index dew_point: $mqttDeviceTopic/si7021_dew_point absolute_humidity: $mqttDeviceTopic/si7021_absolute_humidity- 传感器数据每60 秒更新并发布一次(对应源码
loop()中的nextMeasure = tempTimer + 60000,见 Si7021_MQTT_HA.cpp)。 - 同时支持 Home Assistant MQTT Auto-Discovery,无需在 HA 中手写 YAML 传感器定义。
从源码结构看,该文件头部注释说明它 remix 自 sensors_to_mqtt 与 multi_relay 两个 usermod,因此其 MQTT 发布与 I²C 初始化套路与这两个成熟 usermod 一致。
依赖与编译前提
该 usermod 的 library.json 声明了以下依赖,PlatformIO 编译时会自动拉取:
{ "name": "Si7021_MQTT_HA", "build": { "libArchive": false }, "dependencies": { "finitestate/BME280": "3.0.0", "adafruit/Adafruit Si7021 Library": "1.5.3", "SPI": "*", "adafruit/Adafruit BusIO": "1.17.1" } }其中Adafruit Si7021 Library负责 I²C 寄存器级读写,EnvironmentCalculations(由 BME280 库提供)负责根据温湿度计算热指数、露点与绝对湿度。
还有一个硬性前提:构建时 MQTT 必须处于启用状态。源码开头有编译期检查:
#ifdef WLED_DISABLE_MQTT #error "This user mod requires MQTT to be enabled." #endif也就是说,如果你的构建环境使用了-D WLED_DISABLE_MQTT(platformio_override.sample.ini 的注释中也列出了该开关),该 usermod 会直接编译失败——这是作者显式拒绝支持无 MQTT 场景的方式。
运行流程:从 WiFi 上线到周期发布
理解 Si7021_MQTT_HA.cpp 的四个生命周期回调,就能掌握其完整行为链:
setup():仅在enabled为 true 时打印启动日志并调用si7021.begin()初始化 I²C 传感器(L173-L180)。此时并不触碰 MQTT。onMqttConnect():MQTT 连接建立后回调,若mqttDeviceTopic非空则执行_initializeMqtt()——拼接五个完整主题、立即执行一次「读数 + 发布」,并在开启 HA 发现时发布 discovery 配置(L168-L171)。connected():每次 WiFi(重新)连接后,将首次测量安排在 5 秒后(nextMeasure = millis() + 5000),保证 WiFi 就绪后很快就有第一份数据。loop():主循环中的看门狗逻辑(L188-L217):- 调用
yield()让出,并在!enabled或灯带正在刷新(strip.isUpdating())时直接返回,避免在效果渲染高峰期占用 CPU; - 到达
nextMeasure后将下一轮安排在 60 秒后; - 若传感器此前未初始化成功,会在 loop 中重试初始化(打印错误并等待下一轮),提供了启动时 I²C 总线尚未就绪的容错;
- 只有
WLED_MQTT_CONNECTED为真时才发布;MQTT 断开时会复位mqttInitialized并打印提示,重连后自动重新初始化主题与 discovery。
- 调用
这种「MQTT 未连接就不发布、重连后自愈」的设计,使该 usermod 在断网重连场景下不需要人工干预。
Home Assistant Auto-Discovery 配置详解
开启Home Assistant MQTT Auto-Discovery后,_publishHAMqttSensor()(L71-L104)会向标准 discovery 主题homeassistant/sensor/{mqttClientID}/{name}/config发布传感器配置,其中mqttClientID是 WLED 的 MQTT 客户端 ID。配置载荷的字段如下:
| 字段 | 取值 | 说明 |
|---|---|---|
name | {serverDescription} {友好名} | 如 "WLED Temperature" |
state_topic | 对应数据主题 | 与上文$mqttDeviceTopic/si7021_*一致 |
unique_id | {mqttClientID}{name} | HA 实体唯一标识 |
unit_of_measurement | °C/%/g/m³ | 绝对湿度单位为 g/m³ |
device_class | temperature/humidity | 仅温度类传感器携带 |
expire_after | 1800 | 30 分钟无更新则 HA 标记离线 |
device.name/model/manufacturer/identifiers/sw_version | WLED 相关信息 | 将传感器挂到同一 WLED 设备下 |
几个值得注意的实现细节:
dew_point与absolute_humidity的device_class传空字符串,源码中对空device_class/unit_of_measurement会跳过对应字段(if (deviceClass != "")判断),因此 HA 中它们仍会显示单位,只是不被归类为标准温度传感器;- 发布使用
mqtt->publish(topic, 0, true, ...)的retained(保留)消息,而数据消息使用非保留发布(_publishSensorData()中 retain 参数为 false)——discovery 配置需要保留以便 HA 重启后仍能读到; - 温度、湿度两个基础传感器始终发布 discovery,
heat_index、dew_point、absolute_humidity三个附加传感器受sendAdditionalSensors开关控制(见 L58-L66)。
硬件接线与 I²C 引脚配置
将 Si7021 传感器接到 I²C 总线即可。README 给出的默认引脚为:
// ESP32 SCL_PIN = 22; SDA_PIN = 21; // ESP8266 SCL_PIN = 5; SDA_PIN = 4;如果你的硬件使用其他 GPIO,可以通过 WLED 的构建宏I2CSCLPIN/I2CSDAPIN初始化 I²C 接口。wled00/wled.h 中可以看到全局 I²C 引脚变量由这两个宏驱动:
// global I2C SDA pin (used for usermods) WLED_GLOBAL int8_t i2c_sda _INIT(I2CSDAPIN); // global I2C SCL pin (used for usermods) WLED_GLOBAL int8_t i2c_scl _INIT(I2CSCLPIN);platformio_override.sample.ini 中也给出了用法示例:
; -D I2CSDAPIN=33 # initialise interface ; -D I2CSCLPIN=35 # initialise interface在build_flags中加上-D I2CSDAPIN=xx -D I2CSCLPIN=xx即可切换到自定义引脚;而HW_PIN_SCL/HW_PIN_SDA仅用于告知 WebUI 默认引脚提示,不会真正初始化接口。
Usermod 设置项
编译烧录后,三个运行时设置项会出现在 WLED 的 usermod 配置区(对应源码中以PROGMEM常量定义的键名,见 Si7021_MQTT_HA.cpp,usermod 显示名为 "Si7021 MQTT (Home Assistant)",ID 为USERMOD_ID_SI7021_MQTT_HA = 29,定义于 wled00/const.h):
| 配置键 | 作用 | 源码默认值 |
|---|---|---|
enabled | 使能该 usermod(关闭后loop()直接返回,不读传感器也不发布) | false |
Send Dew Point, Abs. Humidity and Heat Index | 是否同时发布露点、绝对湿度、热指数三个衍生传感器(含其 discovery 配置与计算开销) | true |
Home Assistant MQTT Auto-Discovery | 是否在 MQTT 连接时发布 HA discovery 配置 | true |
这三个布尔值同时通过addToConfig()/readFromConfig()持久化到 WLED 的 JSON 配置中,断电重启后保留。
安装步骤
接线:按上文将 Si7021 接到 I²C(SDA/SCL 各加 4.7kΩ 上拉电阻是常规做法,具体视模块而定);
编译配置:在
platformio_override.ini(复制自 platformio_override.sample.ini)的目标环境段中加入Si7021_MQTT_HA:custom_usermods = ${env:esp32dev.custom_usermods} Si7021_MQTT_HA注意
custom_usermods是环境段的独立键,多个 usermod 用空格分隔(sample 文件注释中有专门说明)。仓库自带的 platformio.ini 中的[env:usermods]环境则使用custom_usermods = *一次性展开usermods/目录下全部 usermod,适合想整体体验的场景,但会占用更多 flash;确认 MQTT 可用:确保构建未启用
-D WLED_DISABLE_MQTT,并在 WLED 的同步设置中配置好 MQTT broker 与设备主题;运行时启用:烧录后在 WLED 的 usermod 设置中打开
enabled,按需保留或关闭另外两个开关;验证:观察串口输出(初始化日志、MQTT 缺失告警),或在 MQTT 客户端订阅
$mqttDeviceTopic/si7021_temperature与homeassistant/sensor/主题树,确认数据与 discovery 配置均已到达。
边界与限制
- 数据只走 MQTT,WLED UI 不显示传感器读数,这是该 usermod 的设计定位;
- 发布节奏固定为 60 秒,且首次读数安排在 WiFi 连接后 5 秒,均写死在源码中,不提供运行时调节;
- 每轮测量会阻塞式执行 I²C 读数与浮点计算,源码特意在
strip.isUpdating()期间跳过本轮,以保护灯光效果流畅度——如果你的灯光负载重,可留意这一避让逻辑带来的测量时间抖动; - 该 usermod 属于社区贡献代码,位于
usermods/目录,按 usermods 总说明 的约定,其维护责任在各自作者,随 WLED 主版本升级可能需要同步调整。
小结
Si7021_MQTT_HA 用不到 240 行源码(Si7021_MQTT_HA.cpp)展示了一个 WLED usermod 处理「外设 + 网络服务」的完整范式:library.json声明依赖、编译期宏检查硬性前提、setup/connected/onMqttConnect/loop四个回调各司其职、retained discovery 消息 + 非 retained 数据消息区分对待、PROGMEM字符串与F()宏控制 flash 占用。如果你想给 WLED 增加其他传感器并接入 Home Assistant,这个 usermod 连同 sensors_to_mqtt 都值得一读。
【免费下载链接】WLEDControl WS2812B and many more types of digital RGB LEDs with an ESP32 over WiFi!项目地址: https://gitcode.com/GitHub_Trending/wl/WLED
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考