智能家居进阶:基于MQTT协议与HomeAssistant的物联网设备集成实战
1. 项目概述为什么MQTT是智能家居的“神经系统”如果你已经跟着前两篇内容把HomeAssistant后文简称HA的基础环境搭建起来并且成功接入了一些Wi-Fi或Zigbee设备那么恭喜你你的智能家居已经迈出了坚实的第一步。但当你开始尝试接入一些更“硬核”的设备比如自己用ESP8266/ESP32开发板做的传感器、或者一些需要稳定长连接的智能开关时你可能会发现单纯依赖HA的自动发现或者厂商的云插件开始有点力不从心了。这时候一个叫做MQTT的协议就该登场了。你可以把MQTT想象成智能家居设备之间的“神经系统”和“消息总线”。它不像Wi-Fi那样直接“对话”而是通过一个中央的“消息代理服务器”Broker来中转所有信息。设备A想告诉HA“我房间温度是25℃”它不用知道HA在哪只需要把这条消息“发布”到名为“sensor/bedroom/temperature”的“主题”上。而HA作为“订阅者”早就订阅了这个主题于是就能实时收到这条消息。这种“发布/订阅”模式解耦了设备与设备、设备与平台之间的关系让整个系统变得异常灵活和健壮。为什么在HA的进阶配置里MQTT几乎无法绕开第一是稳定性。对于单片机这类资源有限的设备MQTT协议非常轻量连接稳定且断线后能自动重连并恢复状态比直接轮询HA的API要可靠得多。第二是自由度。你可以用任何支持MQTT的硬件几十块的开发板就能搞定创造任何你想要的传感器或控制器主题命名和消息格式完全自定义不受任何厂商限制。第三是跨平台。MQTT是一个开放标准你的设备数据不仅可以给HA用未来也可以轻松同步到其他支持MQTT的物联网平台或自建的数据分析系统中。这次我们就来彻底搞定HA中的MQTT配置。这不仅仅是填个服务器地址和密码我会带你理解其核心工作模式完成Mosquitto Broker的部署与安全加固并在HA中实现设备的手动与自动发现。最后我会用一个真实的ESP32温湿度传感器项目演示从硬件刷机、MQTT连接到HA实体创建的完整闭环。理解了这一套你的智能家居将真正突破厂商生态的壁垒获得无限的扩展能力。2. MQTT核心概念与在HomeAssistant中的角色解析在开始动手配置之前花点时间把MQTT在HA生态系统里的几个核心概念和角色理清楚后面所有的操作都会变得顺理成章。很多配置出错根源都在于对这些基础逻辑的理解偏差。2.1 发布/订阅模式不是打电话是广播电台这是MQTT最核心的思想和我们熟悉的客户端-服务器模式比如网页浏览器访问网站完全不同。想象一下广播电台和收音机的关系发布者就像广播电台。它只负责把节目内容消息通过某个频率主题发送出去它不关心有没有听众也不关心听众是谁。订阅者就像收音机。它需要主动调谐到某个频率订阅主题才能收听到该频率的节目。一台收音机可以收听多个频率。代理就像广播塔和无线电波。它是消息传输的媒介和枢纽负责接收发布者的消息并将其准确分发到所有订阅了该主题的订阅者。在HA的场景里ESP32温湿度传感器是一个发布者。它定期向主题home/sensor/dht22/state发布一条消息内容可能是{temperature: 25.6, humidity: 60}。HomeAssistant是一个订阅者。它在启动时就告诉代理“我订阅home/sensor/dht22/state这个主题。” 从此只要这个主题有消息HA就会立刻收到。Mosquitto就是那个代理Broker。它运行在你的服务器上负责转发所有这些消息。这种模式的好处是解耦。传感器不需要知道HA的IP地址HA也不需要主动去问传感器“你现在的数据是多少”。双方都只和代理通信任何一方的重启或网络波动对另一方的影响都降到最低。2.2 主题消息的地址和分类标签主题是一个用斜杠分隔的字符串用来标识消息的类型和来源。它就像是文件系统的路径或者邮件的收件地址。良好的主题命名规范是管理大量设备的关键。常见的命名习惯是分层结构例如home/living-room/light/switch1/state表示“家/客厅/灯/开关1/状态”home/bedroom/climate/temperature表示“家/卧室/气候传感器/温度”device/esp32-abc123/sensor表示“设备/设备ID/传感器”在HA中主题通常用于两种目的状态主题设备发布其当前状态的地方。HA订阅它来获取数据。命令主题HA发布控制命令的地方。设备订阅它来接收指令。比如HA向home/living-room/light/switch1/set主题发送ON设备收到后执行开灯。2.3 消息与保留消息最后一次的“记忆”消息就是传递的实际数据通常是JSON格式的字符串因为JSON结构清晰HA能直接解析。这里有一个非常重要的概念保留消息。当发布者发布消息时可以设置一个“保留”标志。代理会保存这条消息以及它对应的主题。任何新的订阅者一旦订阅了这个主题就会立刻收到这条最后被保留的消息。这有什么妙用想象一下你的门磁传感器。它平时发布OPEN或CLOSED状态。如果它发布最后一条状态为CLOSED时设置了保留标志。那么无论HA是刚刚启动还是你新添加了这个传感器HA在订阅主题的瞬间就能知道门是关着的而不是显示“未知”状态。这对于二进制状态开/关或传感器初始值至关重要。2.4 QoS消息送达的“服务质量保证”MQTT提供了三个级别的QoS代表不同的可靠性保证QoS 0最多一次消息发出去就完事不保证对方收到。像“温度传感器数据”丢一两条也没关系适合高频、可容忍丢失的数据。QoS 1至少一次发送方会一直重发直到收到接收方的确认。这可能导致接收方收到重复消息需要业务逻辑去重。适合重要的控制指令。QoS 2确保一次最严格的流程通过四次握手确保消息恰好被送达一次。开销最大适合非常重要的状态同步或交易类指令。对于绝大多数智能家居场景传感器数据用QoS 0开关控制命令用QoS 1是一个在可靠性和性能之间比较好的平衡。实操心得不要忽视保留消息。为你所有状态主题.../state的消息设置保留标志可以极大改善HA重启或设备初始化时的用户体验避免实体状态长时间显示为“未知”。对于命令主题.../set通常不需要保留。3. 搭建MQTT代理服务器Mosquitto的部署与安全加固HA本身不包含MQTT代理你需要单独部署一个。Mosquitto是Eclipse基金会下的开源项目轻量、稳定是HA社区最推荐的选择。我们将以在Docker中部署为例这是目前最主流、最便于管理的方式。3.1 使用Docker Compose部署Mosquitto假设你的HA也是通过Docker安装的那么使用Docker Compose来管理Mosquitto是最佳实践。创建一个专门的目录比如~/mqtt并在其中创建docker-compose.yml文件。version: 3.8 services: mosquitto: image: eclipse-mosquitto:latest container_name: mosquitto restart: unless-stopped ports: - 1883:1883 # MQTT默认非加密端口 - 9001:9001 # WebSocket端口用于一些需要WebSocket连接的客户端 volumes: - ./mosquitto/config:/mosquitto/config # 挂载配置文件目录 - ./mosquitto/data:/mosquitto/data # 挂载数据目录 - ./mosquitto/log:/mosquitto/log # 挂载日志目录 networks: - homeassistant_network # 建议与HA在同一个自定义网络 networks: homeassistant_network: external: true # 使用HA已有的网络如果HA不是Docker安装可改为host模式或新建网络关键配置解析端口映射1883标准的MQTT协议端口。HA和设备都将通过这个端口连接。9001WebSocket端口。有些运行在浏览器里的MQTT测试工具或者某些前端面板需要通过WebSocket连接。卷挂载将容器内的配置、数据、日志目录映射到宿主机。这样即使容器删除你的配置和持久化数据如保留消息也不会丢失。./mosquitto/config这个目录需要你提前创建好。网络强烈建议让Mosquitto和HA容器处于同一个自定义Docker网络中。这样它们之间可以通过容器名如mosquitto互相访问无需暴露端口到宿主机更安全。如果你的HA是HASS OS、Supervised或Core安装网络模式可能不同可能需要使用host模式或调整网络配置。创建好文件后在~/mqtt目录下执行docker-compose up -dMosquitto就会以默认配置运行起来。但默认配置没有密码这非常危险下一步我们进行安全加固。3.2 配置密码认证与ACL权限控制一个暴露在网络上且没有密码的MQTT代理相当于把你家智能锁的配置密钥贴在门口。我们必须设置密码和访问控制列表。首先在之前挂载的./mosquitto/config目录下创建两个文件mosquitto.conf和passwd。1. 主配置文件mosquitto.confpersistence true persistence_location /mosquitto/data/ log_dest file /mosquitto/log/mosquitto.log # 监听端口 listener 1883 protocol mqtt # 允许匿名连接先设为true创建密码后再关闭 allow_anonymous true # 密码文件路径 password_file /mosquitto/config/passwd # ACL文件路径可选但推荐 # acl_file /mosquitto/config/acl2. 创建密码文件在宿主机上进入./mosquitto/config目录使用Mosquitto提供的工具创建密码。如果没有该工具可以进入容器内部操作或者直接安装mosquitto客户端工具。# 进入容器 docker exec -it mosquitto sh # 在容器内创建密码文件并添加用户例如用户名为‘homeassistant’ mosquitto_passwd -c /mosquitto/config/passwd homeassistant # 根据提示输入密码比如‘YourSecurePassword123’ # 可以继续添加其他用户比如给设备用的‘device_user’ mosquitto_passwd /mosquitto/config/passwd device_user执行后passwd文件里就会保存加密后的用户名和密码。3. 禁用匿名登录编辑mosquitto.conf将allow_anonymous true改为allow_anonymous false。这样没有有效用户名和密码的客户端将无法连接。4. 高级可选配置ACL精细控制ACL文件可以控制哪个用户可以订阅或发布哪个主题。这对于多用户场景或想严格限制设备权限时非常有用。创建acl文件# 用户homeassistant可以读写所有主题 user homeassistant topic readwrite # # 用户device_user只能向自己的设备主题发布状态并从命令主题接收指令 user device_user topic write home/sensor//state topic read home/sensor//set然后在mosquitto.conf中取消注释acl_file那一行。配置完成后重启Mosquitto容器docker-compose restart。注意事项密码不要使用过于简单的并且passwd文件要妥善保管。在生产环境中还应考虑配置SSL/TLS加密使用8883端口防止密码在传输中被嗅探。对于内网环境密码认证加上网络隔离如专用Docker网络通常已足够安全。4. HomeAssistant中的MQTT集成配置与设备发现Broker准备就绪后接下来就是在HA中建立连接并开始接收和管理设备。4.1 添加MQTT集成并测试连接打开HA的网页界面进入“配置” - “设备与服务”。点击右下角的“添加集成”搜索并选择“MQTT”。在配置页面你需要填写代理如果你的HA和Mosquitto在同一台机器且Mosquitto用了host网络或与HA在同一Docker网络这里可以填localhost或mosquitto容器名。否则填写Mosquitto所在服务器的IP地址。端口默认1883。用户名/密码填写你在passwd文件中为HA创建的用户如homeassistant及其密码。其他选项保持默认即可除非你配置了SSL。点击“提交”后如果一切正常集成会添加成功。为了验证连接和熟悉操作我们可以利用集成的“配置”界面里的“配置MQTT设备”功能手动发布一条测试消息。在MQTT集成配置页面找到“配置MQTT设备”卡片点击“配置”。在“主题”栏输入一个测试主题例如test/ha/connection。在“有效载荷”栏输入Hello from HA。点击“发布消息”。然后在同一个页面下方订阅这个主题在“订阅主题”栏输入同样的主题test/ha/connection。点击“开始监听”。你应该能立刻在下方看到你刚刚发布的消息。这个测试证明了HA既能作为发布者也能作为订阅者与Broker通信正常。4.2 手动配置MQTT实体以一个虚拟开关为例自动发现虽然方便但理解手动配置是掌握MQTT精髓的关键。我们来手动创建一个最简单的MQTT开关实体。HA中手动配置MQTT设备主要通过在configuration.yaml文件中添加配置或者对于较新版本的HA更推荐在UI界面通过MQTT集成配置。这里以UI方式为例因为它更直观且不易出错。再次进入MQTT集成的“配置MQTT设备”。这次我们认真填写主题home/living-room/light/main/set这是HA发送命令的主题有效载荷ON先填一个等下测试点击“发布消息”。这步是向命令主题发送一个开指令虽然现在没有设备监听但可以创建保留消息方便后续测试。现在我们需要创建一个开关实体来关联这个主题。在HA主侧边栏进入“开发者工具” - “YAML”。在“检查YAML配置”标签页下输入以下配置并点击“检查配置”确保无误switch: - platform: mqtt name: Living Room Main Light unique_id: living_room_main_light_001 state_topic: home/living-room/light/main/state command_topic: home/living-room/light/main/set payload_on: ON payload_off: OFF retain: true qos: 1配置无误后重启HA或在“开发者工具”-“重新加载模板”中重载“开关”类别。你应该能在概览页看到一个名为“Living Room Main Light”的开关卡片但它的状态是“未知”因为我们还没有设备向state_topic发布状态。配置字段详解state_topic开关实体订阅这个主题来获取设备的真实状态。command_topic当你在HA界面上操作这个开关时HA会向这个主题发布命令ON或OFF。payload_on/off定义开和关命令对应的消息内容。retain: true建议设置为true这样设备发布的最后状态会被Broker保留HA重启后能立即恢复正确状态。qos: 1对于控制命令使用QoS 1保证至少送达一次。4.3 自动发现让设备主动向HA“报到”手动配置每个实体非常繁琐。MQTT自动发现协议允许设备在连接时自动向HA发送一个特殊的配置消息HA收到后就会自动创建对应的实体。这是接入自制ESP设备最优雅的方式。自动发现依赖于一个特定的主题结构。设备需要向以下主题发布一条配置消息通常是JSON格式homeassistant/component/device_id/object_id/configcomponentHA的实体类型如sensor,switch,binary_sensor,light等。device_id一个唯一标识设备的ID通常与设备的MQTT客户端ID相关。object_id该实体在设备内的标识符。最终实体的实体ID会是object_id_device_id的组合形式。例如一个ESP32温湿度传感器为了自动创建温度和湿度两个传感器实体它需要发布两条配置消息主题1:homeassistant/sensor/esp32_dht22/temperature/config消息1:{ name: Bedroom Temperature, device_class: temperature, state_topic: home/bedroom/sensor/state, unit_of_measurement: °C, value_template: {{ value_json.temperature }}, unique_id: esp32_dht22_temperature, device: { identifiers: [esp32_dht22], name: Bedroom ESP32 DHT22 } }主题2:homeassistant/sensor/esp32_dht22/humidity/config消息2:{ name: Bedroom Humidity, device_class: humidity, state_topic: home/bedroom/sensor/state, unit_of_measurement: %, value_template: {{ value_json.humidity }}, unique_id: esp32_dht22_humidity, device: { identifiers: [esp32_dht22], name: Bedroom ESP32 DHT22 } }注意这两个配置都指向同一个state_topic(home/bedroom/sensor/state)但通过value_template使用JSON路径提取了不同的值temperature和humidity。device字段将它们关联到同一个设备下这样在HA的“设备”页面它们会显示在一起。当设备发布这些配置消息必须设置保留标志后HA的MQTT集成会自动发现并创建实体。设备后续只需要定期向home/bedroom/sensor/state发布如{temperature: 25.6, humidity: 60}的消息两个实体的状态就会自动更新。实操心得自动发现配置消息务必设置保留标志retaintrue。这样即使HA重启它重新连接Broker后也能立即收到这些保留的配置消息并恢复实体无需设备重新发送。这是实现设备“即插即用”体验的关键。5. 实战将ESP32温湿度传感器接入HA全流程现在我们把理论付诸实践完成一个从零开始的完整项目用ESP32开发板搭配DHT22传感器通过MQTT接入HA。5.1 硬件准备与Arduino环境配置所需材料ESP32开发板如NodeMCU-32SDHT22温湿度传感器杜邦线若干微型USB数据线电路连接非常简单DHT22 VCC - ESP32 3.3VDHT22 GND - ESP32 GNDDHT22 DATA - ESP32 GPIO4 (或其他任意数字引脚)软件环境准备安装Arduino IDE。在“文件”-“首选项”的“附加开发板管理器网址”中添加ESP32支持网址https://espressif.github.io/arduino-esp32/package_esp32_index.json在“工具”-“开发板”-“开发板管理器”中搜索并安装“esp32”。安装库在“项目”-“加载库”-“管理库”中搜索并安装 “DHT sensor library” 和 “PubSubClient”MQTT客户端库。5.2 编写并上传ESP32固件代码以下是完整的Arduino代码你需要修改其中的Wi-Fi和MQTT服务器信息。#include WiFi.h #include PubSubClient.h #include DHT.h // WiFi配置 const char* ssid 你的Wi-Fi名称; const char* password 你的Wi-Fi密码; // MQTT配置 const char* mqtt_server 192.168.1.100; // 你的Mosquitto服务器IP const char* mqtt_user device_user; // MQTT用户名之前创建的 const char* mqtt_password device_password; // 对应密码 const char* clientId ESP32_DHT22_Bedroom; // 客户端ID需唯一 // DHT传感器配置 #define DHTPIN 4 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); // 主题定义 const char* state_topic home/bedroom/sensor/state; const char* temp_config_topic homeassistant/sensor/esp32_dht22_bedroom/temperature/config; const char* humi_config_topic homeassistant/sensor/esp32_dht22_bedroom/humidity/config; WiFiClient espClient; PubSubClient client(espClient); unsigned long lastMsgTime 0; const long interval 30000; // 发送间隔30秒 void setup_wifi() { delay(10); Serial.println(); Serial.print(Connecting to ); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(); Serial.println(WiFi connected); Serial.println(IP address: ); Serial.println(WiFi.localIP()); } void reconnect() { while (!client.connected()) { Serial.print(Attempting MQTT connection...); if (client.connect(clientId, mqtt_user, mqtt_password)) { Serial.println(connected); // 连接成功后发布自动发现配置保留消息 publishAutoDiscoveryConfig(); } else { Serial.print(failed, rc); Serial.print(client.state()); Serial.println( try again in 5 seconds); delay(5000); } } } void publishAutoDiscoveryConfig() { // 构建温度传感器的自动发现配置消息 String temp_config {\name\:\Bedroom Temperature\,\device_class\:\temperature\,\state_topic\:\ String(state_topic) \,\unit_of_measurement\:\°C\,\value_template\:\{{ value_json.temperature }}\,\unique_id\:\esp32_dht22_bedroom_temp\,\device\:{\identifiers\:[\esp32_dht22_bedroom\],\name\:\Bedroom Climate Sensor\}}; // 构建湿度传感器的自动发现配置消息 String humi_config {\name\:\Bedroom Humidity\,\device_class\:\humidity\,\state_topic\:\ String(state_topic) \,\unit_of_measurement\:\%\,\value_template\:\{{ value_json.humidity }}\,\unique_id\:\esp32_dht22_bedroom_humi\,\device\:{\identifiers\:[\esp32_dht22_bedroom\],\name\:\Bedroom Climate Sensor\}}; // 发布配置并设置为保留消息 client.publish(temp_config_topic, temp_config.c_str(), true); client.publish(humi_config_topic, humi_config.c_str(), true); Serial.println(Auto-discovery config published.); } void setup() { Serial.begin(115200); dht.begin(); setup_wifi(); client.setServer(mqtt_server, 1883); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); // 维持MQTT连接处理心跳 unsigned long now millis(); if (now - lastMsgTime interval) { lastMsgTime now; // 读取传感器数据 float h dht.readHumidity(); float t dht.readTemperature(); // 检查读数是否有效 if (isnan(h) || isnan(t)) { Serial.println(Failed to read from DHT sensor!); return; } // 构建JSON格式的状态消息 String payload {\temperature\: String(t) ,\humidity\: String(h) }; Serial.print(Publishing message: ); Serial.println(payload); // 发布状态消息并设置为保留消息 client.publish(state_topic, payload.c_str(), true); } }代码关键点解析publishAutoDiscoveryConfig()函数在MQTT连接成功后立即调用向特定的自动发现主题发布两条配置消息。client.publish(..., true)的最后一个参数true表示设置为保留消息。device字段在配置消息中将温度和湿度传感器通过相同的identifiers关联到同一个设备下。状态发布在循环中每30秒读取一次传感器数据拼接成JSON字符串发布到state_topic同样设置为保留消息。将代码中的Wi-Fi、MQTT服务器地址、用户名密码修改为你自己的选择正确的开发板和端口点击上传。5.3 在HomeAssistant中验证与调试上传完成后打开串口监视器查看ESP32的日志。它应该会连接Wi-Fi然后连接MQTT服务器并打印发布配置和状态的消息。此时打开HA进入“配置” - “设备与服务”。在“设备”标签页你应该能看到一个名为“Bedroom Climate Sensor”的新设备。点击该设备里面应该有两个实体“Bedroom Temperature”和“Bedroom Humidity”并且其状态应该已经显示了当前的温湿度读数。你可以将它们添加到仪表盘或者用它们来创建自动化。如果设备没有出现请按以下步骤排查检查MQTT连接在HA的MQTT集成配置页面使用“配置MQTT设备”工具订阅主题homeassistant/#。你应该能看到ESP32发布的两条配置消息。如果看不到说明ESP32没有成功连接或发布消息。检查状态主题订阅home/bedroom/sensor/state看是否有定期的JSON数据发布。检查ESP32串口日志查看是否有连接错误或者Wi-Fi、MQTT认证失败的信息。检查Mosquitto日志进入Mosquitto容器查看/mosquitto/log/mosquitto.log文件看是否有连接记录或错误信息。6. 常见问题排查与高阶技巧即使按照步骤操作也难免会遇到问题。这里汇总了一些常见坑点及其解决方案。6.1 连接类问题问题HA中MQTT集成显示“无法连接”或“已断开连接”。排查思路网络连通性确保HA主机能ping通Mosquitto服务器的IP和端口。在HA的“开发者工具”-“检查配置”右侧有“网络”检查工具可以测试telnet broker_ip 1883。认证信息双查用户名和密码注意大小写。可以尝试在Mosquitto容器内用mosquitto_sub命令测试连接mosquitto_sub -h localhost -u homeassistant -P 你的密码 -t # -v。防火墙如果Mosquitto运行在独立服务器或虚拟机上检查宿主机的防火墙是否放行了1883端口。Docker网络如果都用Docker确保它们在同一个网络。使用docker network inspect homeassistant_network查看容器是否都 attached 在该网络下。问题ESP32等设备无法连接MQTT Broker。排查思路客户端ID冲突确保每个设备的clientId是唯一的。服务器地址设备代码中的mqtt_server必须填写Broker对设备可见的IP地址。如果Broker在宿主机设备在同一个局域网填宿主机局域网IP如果Broker在容器内且网络模式为host也是填宿主机IP。库版本PubSubClient库有默认的MQTT包大小限制。如果自动发现JSON消息过长可能导致发布失败。可以尝试在代码开头增加#define MQTT_MAX_PACKET_SIZE 1024。6.2 自动发现类问题问题设备发布了自动发现消息但HA里看不到实体。排查思路主题格式确保自动发现主题格式完全正确homeassistant/component/device_id/object_id/config。最常犯的错误是component拼写错误如sensor写成sensors。保留标志必须在发布自动发现配置消息时设置retaintrue。HA在启动或重载集成时会主动查询这些保留的配置消息。JSON格式配置消息必须是合法的JSON。一个多余的逗号或缺少引号都会导致解析失败。使用在线JSON校验工具检查你的配置字符串。查看日志HA的日志文件home-assistant.log或Web界面中的“日志”页面通常会有MQTT自动发现相关的错误提示例如“Invalid config for …”这是最重要的调试信息。问题实体创建了但状态一直是“未知”。排查思路状态主题匹配检查实体配置中的state_topic和设备实际发布状态的主题是否完全一致包括大小写。值模板如果使用value_template确保JSON路径正确。例如消息是{temp: 25}但模板写成了{{ value_json.temperature }}就会解析失败。设备是否在线检查设备是否在正常运行并发布数据。在HA的MQTT集成工具里订阅状态主题即可验证。6.3 性能与稳定性优化技巧为设备使用专用低权限用户不要所有设备都用HA的账号。像上面的例子我为ESP32创建了device_user并在ACL中限制它只能读写特定的主题范围这样即使该设备凭证泄露影响范围也有限。合理设置遗嘱消息在设备连接Broker时可以设置一个“遗嘱”主题和消息。如果设备异常断开Broker会自动向这个主题发布遗嘱消息。HA可以订阅这个主题从而知道设备离线了。在PubSubClient中可以在connect函数中设置。client.connect(clientId, mqtt_user, mqtt_password, willTopic, willQos, willRetain, willMessage);注意QoS和保留消息的副作用QoS 1和2会加重Broker和客户端的负担。保留消息会永久存储在Broker磁盘上。对于高频更新的传感器如每秒一次的位置信息使用QoS 0且不保留避免磁盘写爆和网络拥堵。对于低频关键状态如门锁状态使用QoS 1和保留。监控Broker状态Mosquitto提供了$SYS/主题可以获取Broker自身的运行状态如连接数、消息数量等。你可以让HA订阅这些主题创建传感器来监控Broker健康度。当你成功将第一个自制设备通过MQTT无缝接入HA并看到数据在仪表盘上实时跳动时那种成就感是无可比拟的。MQTT为你打开了一扇门门后是一个由你完全定义、不受束缚的智能家居世界。从简单的传感器到复杂的控制器从开源硬件到老旧设备的改造桥接MQTT都是那条最可靠、最通用的“数据高速公路”。