通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
MQTT 设备的发现将使人们能够在 HomeAssistant 方面只需要很少的配置工作就可以使用 MQTT 设备。配置是在设备本身和设备使用的主题上完成的。
MQTT 发现默认启用,但可以禁用。发现主题的前缀(默认:
homeassistant
)可以更改。配置详情请参阅 MQTT 选项部分
向 MQTT 发送配置主题后, HomeAssistant 会自动发现当前传感器。 当前任务中使用了一个板载LED灯,作为 HomeAssistant 中的 Light 组件。该组件在 HomeAssistant 的 仪表盘 中可以远程控制板载LED的开和关。使用 MQTT 客户端向配置主题发送消息即可,配置主题如下:
// 板载LED灯 主题消息
{
"name":"led-builtin-Light",
"device_class": "light",
"command_topic":"homeassistant/light/FollowMe2-2-LED_BUILTIN/switch",
"state_topic":"homeassistant/sensor/FollowMe2-2/state",
"state_value_template": "{{ value_json.builtinLed }}",
"unique_id":"FollowMe2-2-LED_BUILTIN-light",
"device":{
"identifiers":[
"Arduino UNO R4 WiFi"
],
"name":"UNO R4 WiFi",
"manufacturer": "Arduino",
"model": "UNO R4 WiFi",
"hw_version": "1.0"
}
}
/**
* FollowMe 2-2 任务3:
* 1. 通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
*/
#include <WiFiS3.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>
#include "arduino_secrets.h"
#define STATE_ON "ON" // HA LED开状态
#define STATE_OFF "OFF" // HA LED关状态
char ssid[] = SECRET_SSID; // WIFI SSID
char pass[] = SECRET_PASS; // WIFI PASSWD
int status = WL_IDLE_STATUS; // WIFI 状态
// MQTT
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.2.120"; // HomeAssistant MQTT服务器地址
int port = 1883; // HomeAssistant MQTT服务器端口
char mqtt_user[] = MQTT_USER; // MQTT 用户名
char mqtt_pass[] = MQTT_PASS; // MQTT 密码
// 订阅主题(接收 HomeAssistant 控制板载LED开关指令)
const char subscribe_topic[] = "homeassistant/light/FollowMe2-2-LED_BUILTIN/switch";
bool isNeedReportLedState = true; // 是否需要更新板载LED状态到HA
bool ledState = false; // 板载LED状态
// 发布主题(上报板载LED状态至 HomeAssistant的状态主题)
const char publish_topic[] = "homeassistant/sensor/FollowMe2-2/state";
void setup() {
// 初始化串口
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); // 初始化板载LED引脚为输出
// 检查WIFI模块
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("WiFi模块通信失败!");
while (true);
}
// 连接到WIFI
Serial.print("尝试连接到 WIFI SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
Serial.print(".");
delay(5 * 1000);
}
Serial.println("WIFI 连接成功!");
// 连接MQTT
mqttClient.setUsernamePassword(mqtt_user, mqtt_pass);
Serial.print("尝试连接到MQTT服务器: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT 连接失败! ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("MQTT连接成功!");
// 订阅主题
mqttClient.onMessage(onMqttMessage);
mqttClient.subscribe(subscribe_topic);
}
void loop() {
if(isNeedReportLedState) {
// 汇报当前板载LED状态到HA
char msg[30] = {0};
sprintf(msg, "{\"builtinLed\": \"%s\"}", ledState ? STATE_ON : STATE_OFF);
mqttClient.beginMessage(publish_topic);
mqttClient.print(msg);
mqttClient.endMessage();
isNeedReportLedState = false; // 上报板载LED状态到HA后重置汇报状态
}
// 更新板载LED状态
if(ledState) { // 亮
digitalWrite(LED_BUILTIN, HIGH);
} else { // 灭
digitalWrite(LED_BUILTIN, LOW);
}
mqttClient.poll(); // 定期检查新MQTT消息
}
// MQTT 订阅消息回调,接收HA控制板载LED的指令(ON:开,OFF:关)
void onMqttMessage(int messageSize) {
// 读取消息内容
String message;
for (int i = 0; i < messageSize; i++) {
message += (char)mqttClient.read();
}
// 打印消息的内容
Serial.print("Received message: ");
Serial.println(message);
if(0 == strcmp(STATE_ON, message.c_str())) {
if(false == ledState) {
// 需要更新板载LED状态到HA
isNeedReportLedState = true;
}
ledState = true;
} else {
if(true == ledState) {
// 需要更新板载LED状态到HA
isNeedReportLedState = true;
}
ledState = false;
}
}
智能家居平台HA(HomeAssistant)中操作关灯后的效果
智能家居平台HA(HomeAssistant)中操作开灯后的效果
串口打印日志
效果动图
本帖最后由 鲜de芒果 于 2024-9-8 15:13 编辑