前面我们已经实现了 ESP8266 通过 MQTT 控制继电器灯的开关。 接下来,我们将设备接入 Home Assistant(HA),这样就可以在 HA 的界面中直接控制灯的开关。

我们需要在 Home Assistant(HA) 中安装一个 MQTT Broker。 这个 Broker 相当于一个消息中间桥梁,ESP8266 和 HA 都通过它进行通信。

ESP8266 和 HA 都会连接到同一个 MQTT Broker:

  • ESP8266 订阅控制灯开关的主题(Topic)
  • HA 向该主题发布开关指令

当 ESP8266 收到来自 Broker 的控制指令时,就会执行相应的操作(例如打开或关闭继电器),并将当前灯的状态通过 MQTT 回传给 HA。

通过这种 发布 / 订阅(Publish / Subscribe)机制,HA 就可以实时控制并获取设备的状态。

配置MQTT集成

  • 进入:Settings > Devices & Services

  • 点击右下角的“Add Integration”按钮,在弹出框中搜索并选择“MQTT”

  • 在弹出的配置框中选择“Use the official Mosquitto Mqtt Broker add-on”选项。该选项会自动安装 Mosquitto MQTT Broker,无需手动配置 Broker 的 IP 地址和端口号等。

添加灯实体

在 Home Assistant 中,可以通过两种方式添加设备实体:

  • 手动配置
  • MQTT Discovery 自动发现

方法一、手动配置

  1. 安装File Editor
  • 进入:Settings > Add-ons > Add-on Store 搜索 File Editor 并安装
  • 勾选“Show in sidebar”以便在侧边栏中快速访问

  1. 通过File Editor编辑configuration.yaml

在侧边栏中点击 File Editor,打开 configuration.yaml 文件。这是 Home Assistant 的主配置文件,我们将在这里添加 MQTT 相关的配置。

mqtt:
  light:
    - name: "书房灯"          # 在 HA 中显示的名字
      unique_id: "study_room_light_01" # 随便起个唯一 ID
      state_topic: "home/study/status"   # 灯上报状态的主题
      command_topic: "home/study/switch" # HA 发送指令的主题
      payload_on: "on"                   # 开启指令(通常是 ON 或 1)
      payload_off: "off"                 # 关闭指令(通常是 OFF 或 0)
      optimistic: false                  # 如果没有状态反馈主题,请设为 true
      qos: 1
      retain: true

方法二、MQTT Discovery 自动发现

Home Assistant 支持 MQTT Discovery 自动发现设备,无需手动修改 configuration.yaml。

MQTT Discovery 使用以下主题结构:

<discovery_prefix>/<component>/[<node_id>/]<object_id>/config 
  • discovery_prefix: 默认为 homeassistant。
  • component: 设备类型,如 sensor(传感器)、switch(开关)、light(灯)。
  • object_id: 设备的唯一标识(通常使用 ESP8266 的 MAC 地址)。

ESP8266 只需向对应主题发布设备配置,HA 就会自动创建实体。

代码示例

void setup_discovery() {
    // 构建发现主题
    String chipId = String(ESP.getChipId());
    String topic = "homeassistant/switch/esp8266_" + chipId + "/config";

    //构建 JSON 配置信息
    StaticJsonDocument<512> doc;
    doc["name"] = "书房灯";
    doc["state_topic"] = state_topic;
    doc["command_topic"] = command_topic;
    doc["unique_id"] = "esp8266_study_room_light_01_" + chipId;
    doc["payload_on"] = "on";
    doc["payload_off"] = "off";

    char buffer[512];
    serializeJson(doc, buffer);

    // 发布配置信息 (必须设置为 retain: true)
    client.publish(topic.c_str(), buffer, true);
}

创建 MQTT 用户

为了安全起见,建议在 MQTT Broker 中创建一个专门的用户账号,用于 Home Assistant 连接。

  • 进入: Settings->person->Add User 创建一个新用户,设置用户名和密码,并记住这些信息。

后续 ESP8266 连接 MQTT Broker 时需要使用该账号。

修改 ESP8266 代码连接 MQTT Broker

首先查看 MQTT Broker 所在设备的 IP 地址:

进入:

Settings → System → Network

找到 Home Assistant 主机的 IP 地址。

然后修改 ESP8266 代码中的 MQTT 配置:

  • MQTT Broker IP
  • 用户名
  • 密码

同时在代码中加入 状态回传,当灯状态改变时,向 HA 上报当前状态。

示例代码如下:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// 定义继电器连接的引脚为 GPIO 4
#define RELAY 4

// WiFi 配置
const char *ssid = "";           // 输入你的 WiFi 名称
const char *password = "";    // 输入 WiFi 密码

// MQTT 服务器配置
const char *mqtt_broker = ""; // 输入 MQTT Broker 的 IP 地址
const char *command_topic = "home/study/switch";
const char *state_topic = "home/study/status";
const char *mqtt_username = ""; // 输入 MQTT 用户名(刚才创建的用户账号的用户名)
const char *mqtt_password = ""; // 输入 MQTT 密码(刚才创建的用户账号的密码)
const int mqtt_port = 1883;

bool relayState = false; // 记录继电器状态

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
    // 设置串口波特率为 9600
    Serial.begin(9600);
    delay(1000); // 等待系统稳定

    // 连接 WiFi 网络
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.println("正在连接 WiFi...");
    }
    Serial.println("WiFi 已连接");

    // 设置继电器引脚为输出模式
    pinMode(RELAY, OUTPUT);
    digitalWrite(RELAY, LOW);  // 初始状态关闭继电器(或 LED)

    // 设置 MQTT 服务器并配置回调函数
    client.setServer(mqtt_broker, mqtt_port);
    client.setCallback(callback);

    // 循环直到连接上 MQTT 服务器
    while (!client.connected()) {
        String client_id = "esp8266-client-";
        client_id += String(WiFi.macAddress());
        Serial.printf("客户端 %s 正在连接HA MQTT 服务器...\n", client_id.c_str());
        
        if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("已连接到 HA MQTT 服务器");
        } else {
            Serial.print("连接失败,错误状态码:");
            Serial.print(client.state());
            delay(2000);
        }
    }

    // 发布配置信息
    setup_discovery();

    // 订阅主题
    client.publish(state_topic, "off");
    client.subscribe(command_topic);
}

// 收到 MQTT 消息时的回调函数
void callback(char *topic, byte *payload, unsigned int length) {
    Serial.print("收到主题消息: ");
    Serial.println(topic);
    Serial.print("消息长度: ");
    Serial.println(length);
    Serial.print(" 内容: ");
    
    String message;
    for (int i = 0; i < length; i++) {
        message += (char) payload[i];  // 将字节数据转换为字符串
    }

    Serial.println(message);

    // 如果收到 "on" 且当前是关闭状态,则开启继电器
    if ((message == "on") && !relayState) {
        digitalWrite(RELAY, HIGH);  // 开启继电器(点亮)
        relayState = true;
        client.publish(state_topic, "on");
        Serial.println(" -> 执行:开启");
    }
    // 如果收到 "off" 且当前是开启状态,则关闭继电器
    if ((message == "off") && relayState) {
        digitalWrite(RELAY, LOW); // 关闭继电器(熄灭)
        relayState = false;
        client.publish(state_topic, "off");
        Serial.println(" -> 执行:关闭");
    }
    Serial.println();
    Serial.println("-----------------------");
}

void loop() {
    // 保持 MQTT 客户端的心跳处理
    client.loop();
    delay(100); // 每次循环轻微延迟
}

通过Home Assistant控制

完成上述配置后, HA 的界面中,你应该能够看到一个新的灯控实体,点击它就可以控制继电器灯的开关了!

通过HomeKit控制

如果已经安装了 Homebridge 插件, 该设备还可以同步到 Apple HomeKit。

在 Home App 中同样可以看到 书房灯, 并且可以通过 Siri 语音控制:

例如:

“Hey Siri,打开书房灯。”

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐