基于homeassitant mqtt 协议电工、照明及兼容客户端开发,写出详细的方案及代码

下面是一个基于 Home Assistant (HA) 的 MQTT 协议来实现电工、照明设备集成和客户端兼容性开发的详细方案和示例代码。该方案重点在于:

  • 使用 MQTT 协议与 Home Assistant 进行集成;
  • 利用 Home Assistant 提供的 MQTT Discovery 功能,实现设备自动发现与接入;
  • 设计一种标准化的 MQTT Topic 和 Payload 格式,适用于电工类(例如开关、插座)和照明类(灯具、调光器)设备;
  • 给出参考代码(以ESP32为例)实现 MQTT 客户端,并与 Home Assistant 进行通信;
  • 使用 Home Assistant 前端查看和控制设备状态。

1. 系统组成与总体思路

1.1 系统组成

  • 主控设备(例如ESP32)

    • 连接本地网络(通过 Wi-Fi)
    • 运行 MQTT 客户端,通过 MQTT Broker 与 Home Assistant 通信
    • 控制电工和照明外设(例如:继电器驱动开关,LED调光,电量传感器等)
    • 接收来自 Home Assistant 的指令,更新状态并上报数据
  • MQTT Broker

    • 使用 Eclipse Mosquitto 等常用MQTT Broker,通常与 Home Assistant 在同一局域网中
    • 主控设备和 Home Assistant 都通过该 Broker 通信
  • Home Assistant

    • 通过 MQTT Discovery 自动发现设备
    • 在界面中显示开关、灯具控制面板
    • 发送MQTT消息控制设备(开关、亮度、色温等)

1.2 功能目标

  • 支持电工类设备(如智能插座、继电器开关):

    • 状态上报(ON/OFF)
    • 接收控制指令(ON/OFF)
  • 支持照明类设备(如智能灯具):

    • 上报当前亮度、色温、开关状态
    • 接收控制指令调整亮度、色温和开关
  • 借助 MQTT Discovery ,无需手动在 Home Assistant 中配置,设备上线后自动出现在前端界面。

1.3 MQTT Topic 与 负载设计

参考 Home Assistant MQTT Discovery 文档(https://www.home-assistant.io/docs/mqtt/discovery/),对于开关类实体和灯光类实体,需要在特定的 discovery topic 下发布 JSON 配置。

1.3.1 MQTT Discovery Topic 格式
  • Discovery Prefix:homeassistant
  • 设备类别:
    • 开关:switch
    • 灯:light
  • 实例ID:设备的唯一ID(如 my_device_01

例如,一个开关设备的配置发布主题:

homeassistant/switch/my_device_01/config

灯设备的配置发布主题:

homeassistant/light/my_device_01/config
1.3.2 配置消息(config payload)示例

开关(switch) config payload示例:

{
  "name": "My Smart Switch",
  "unique_id": "my_device_01_switch",
  "command_topic": "my_device_01/switch/cmnd",
  "state_topic": "my_device_01/switch/state",
  "payload_on": "ON",
  "payload_off": "OFF",
  "retain": false
}

灯(light) config payload示例(包含亮度、色温支持):

{
  "name": "My Smart Light",
  "unique_id": "my_device_01_light",
  "command_topic": "my_device_01/light/cmnd",
  "state_topic": "my_device_01/light/state",
  "brightness_command_topic": "my_device_01/light/brightness/cmnd",
  "brightness_state_topic": "my_device_01/light/brightness/state",
  "color_temp_command_topic": "my_device_01/light/color_temp/cmnd",
  "color_temp_state_topic": "my_device_01/light/color_temp/state",
  "payload_on": "ON",
  "payload_off": "OFF",
  "brightness": true,
  "color_temp": true,
  "max_mireds": 500,
  "min_mireds": 153,
  "retain": false
}
1.3.3 状态与指令Topic约定
  • 开关类:

    • 状态主题:my_device_01/switch/state (payload: “ON”/“OFF”)
    • 控制主题:my_device_01/switch/cmnd (payload: “ON”/“OFF”)
  • 灯类:

    • 开关状态主题:my_device_01/light/state (payload: “ON”/“OFF”)
    • 开关控制主题:my_device_01/light/cmnd (payload: “ON”/“OFF”)
    • 亮度状态主题:my_device_01/light/brightness/state (payload: 整数0-255)
    • 亮度控制主题:my_device_01/light/brightness/cmnd (payload: 整数0-255)
    • 色温状态主题:my_device_01/light/color_temp/state (payload: 整数153-500)
    • 色温控制主题:my_device_01/light/color_temp/cmnd (payload: 整数153-500)

2. 设备端(ESP32)软件设计

2.1 初始化步骤

  1. 初始化NVS、Wi-Fi,连接到本地网络。
  2. 初始化MQTT客户端,连接MQTT Broker。
  3. 发布Home Assistant Discovery配置消息(config)到相应的config topic。
  4. 订阅控制话题(my_device_01/.../cmnd)等待指令下发。

2.2 状态上报与控制逻辑

  • 当设备启动完成后,发布 config 消息使 Home Assistant 自动发现设备。
  • 设备定期或在状态变化时,发布状态到 state 话题。
  • 当收到cmnd话题指令时,解析指令并执行本地控制(如控制GPIO驱动继电器),然后更新状态。
    在这里插入图片描述

2.3 硬件交互示例

  • 开关类设备:使用GPIO驱动继电器(例如GPIO 5接继电器模块)控制电源通断。
  • 照明类设备:使用PWM调光LED,改变占空比实现亮度调节,使用CCT调光器件实现色温调节。

3. Home Assistant 配置

使用 MQTT Discovery,无需在 Home Assistant 中手动配置,只需确保HA中已启用MQTT集成,并在 configuration.yaml 中包含:

mqtt:
  discovery: true
  discovery_prefix: homeassistant

4. 示例代码(基于ESP-IDF + MQTT + FreeRTOS)

下面的代码示例为简化版本,用ESP-IDF,假设您已有Wi-Fi连接代码以及使用idf.py menuconfig配置好MQTT Broker地址。请根据实际环境修改。

main.c 示例

#include <string.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "mqtt_client.h"
#include "esp_wifi.h"
#include "driver/ledc.h"
#include "driver/gpio.h"

#define TAG "MQTT_HA"

// 请根据实际修改
#define MQTT_URI "mqtt://192.168.1.100:1883"
#define DEVICE_ID "my_device_01"

// GPIO定义(示例)
#define RELAY_GPIO (5)
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_TIMER LEDC_TIMER_0
#define LED_GPIO (4)

static esp_mqtt_client_handle_t client = NULL;
static bool light_on = false;
static int light_brightness = 128; // 0-255
static int light_color_temp = 300; // 153-500之间
static bool switch_on = false;

// 发布config消息(在连接MQTT后调用)
static void publish_discovery_config()
{
    // 发布开关设备的config
    const char *switch_config_topic = "homeassistant/switch/" DEVICE_ID "_switch/config";
    const char *switch_config_payload = 
        "{"
        "\"name\": \"My Smart Switch\","
        "\"unique_id\": \"" DEVICE_ID "_switch\","
        "\"command_topic\": \"" DEVICE_ID "/switch/cmnd\","
        "\"state_topic\": \"" DEVICE_ID "/switch/state\","
        "\"payload_on\": \"ON\","
        "\"payload_off\": \"OFF\","
        "\"retain\": false"
        "}";

    esp_mqtt_client_publish(client, switch_config_topic, switch_config_payload, 0, 1, 1);

    // 发布灯设备的config
    const char *light_config_topic = "homeassistant/light/" DEVICE_ID "_light/config";
    const char *light_config_payload = 
        "{"
        "\"name\": \"My Smart Light\","
        "\"unique_id\": \"" DEVICE_ID "_light\","
        "\"command_topic\": \"" DEVICE_ID "/light/cmnd\","
        "\"state_topic\": \"" DEVICE_ID "/light/state\","
        "\"brightness_command_topic\": \"" DEVICE_ID "/light/brightness/cmnd\","
        "\"brightness_state_topic\": \"" DEVICE_ID "/light/brightness/state\","
        "\"color_temp_command_topic\": \"" DEVICE_ID "/light/color_temp/cmnd\","
        "\"color_temp_state_topic\": \"" DEVICE_ID "/light/color_temp/state\","
        "\"payload_on\": \"ON\","
        "\"payload_off\": \"OFF\","
        "\"brightness\": true,"
        "\"color_temp\": true,"
        "\"max_mireds\": 500,"
        "\"min_mireds\": 153,"
        "\"retain\": false"
        "}";

    esp_mqtt_client_publish(client, light_config_topic, light_config_payload, 0, 1, 1);
}

// 更新状态到MQTT
static void update_switch_state()
{
    const char *topic = DEVICE_ID "/switch/state";
    const char *payload = switch_on ? "ON" : "OFF";
    esp_mqtt_client_publish(client, topic, payload, 0, 1, 0);
}

static void update_light_state()
{
    // light开关状态
    esp_mqtt_client_publish(client, DEVICE_ID "/light/state", light_on ? "ON" : "OFF", 0, 1, 0);
    // 亮度状态:转化为字符串
    char brightness_str[8];
    snprintf(brightness_str, sizeof(brightness_str), "%d", light_brightness);
    esp_mqtt_client_publish(client, DEVICE_ID "/light/brightness/state", brightness_str, 0, 1, 0);
    // 色温状态
    char color_temp_str[8];
    snprintf(color_temp_str, sizeof(color_temp_str), "%d", light_color_temp);
    esp_mqtt_client_publish(client, DEVICE_ID "/light/color_temp/state", color_temp_str, 0, 1, 0);
}

// 根据light_on、light_brightness、light_color_temp控制硬件(PWM LED)
static void apply_light_settings()
{
    // 设置PWM占空比,实现亮度控制
    int duty = (light_brightness * 8191) / 255; // LEDC分辨率13bit
    ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL, duty);
    ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL);
    // 对色温可添加相应控制逻辑(需双通道LED实现CCT调整,这里仅示例)
    // 如果只有单色LED,这里忽略色温实际控制
    // 开关控制:如果light_on=false,则 duty=0
    if (!light_on) {
        ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL, 0);
        ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL);
    }
}

// 根据switch_on控制继电器GPIO
static void apply_switch_state()
{
    gpio_set_level(RELAY_GPIO, switch_on ? 1 : 0);
}

// MQTT事件回调
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT connected");
            // 发布discovery
            publish_discovery_config();
            // 订阅控制话题
            esp_mqtt_client_subscribe(client, DEVICE_ID "/switch/cmnd", 1);
            esp_mqtt_client_subscribe(client, DEVICE_ID "/light/cmnd", 1);
            esp_mqtt_client_subscribe(client, DEVICE_ID "/light/brightness/cmnd", 1);
            esp_mqtt_client_subscribe(client, DEVICE_ID "/light/color_temp/cmnd", 1);
            // 更新当前状态到MQTT
            update_switch_state();
            update_light_state();
            break;
        case MQTT_EVENT_DATA: {
            // 收到控制数据
            char topic[128]; 
            char data[128];
            snprintf(topic, event->topic_len+1, "%s", event->topic);
            snprintf(data, event->data_len+1, "%s", event->data);

            if (strcmp(topic, DEVICE_ID "/switch/cmnd") == 0) {
                if (strcmp(data, "ON") == 0) switch_on = true;
                else if (strcmp(data, "OFF") == 0) switch_on = false;
                apply_switch_state();
                update_switch_state();
            } else if (strcmp(topic, DEVICE_ID "/light/cmnd") == 0) {
                if (strcmp(data, "ON") == 0) light_on = true;
                else if (strcmp(data, "OFF") == 0) light_on = false;
                apply_light_settings();
                update_light_state();
            } else if (strcmp(topic, DEVICE_ID "/light/brightness/cmnd") == 0) {
                int val = atoi(data);
                if (val < 0) val = 0;
                if (val > 255) val = 255;
                light_brightness = val;
                apply_light_settings();
                update_light_state();
            } else if (strcmp(topic, DEVICE_ID "/light/color_temp/cmnd") == 0) {
                int val = atoi(data);
                if (val < 153) val = 153;
                if (val > 500) val = 500;
                light_color_temp = val;
                apply_light_settings();
                update_light_state();
            }

            break;
        }
        default:
            break;
    }
    return ESP_OK;
}

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, 
                               int32_t event_id, void *event_data)
{
    mqtt_event_handler_cb(event_data);
}

// Wi-Fi连接逻辑省略,假设已连接成功

void app_main(void)
{
    // 初始化NVS、事件循环
    nvs_flash_init();
    esp_event_loop_create_default();

    // 初始化Wi-Fi代码省略(请根据实际连接到MQTT服务器的内网Wi-Fi)
    // ...

    // 初始化GPIO、PWM
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << RELAY_GPIO),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = false,
        .pull_down_en = false,
        .intr_type = GPIO_INTR_DISABLE,
    };
    gpio_config(&io_conf);

    ledc_timer_config_t ledc_timer = {
        .speed_mode = LEDC_HIGH_SPEED_MODE,
        .duty_resolution = LEDC_TIMER_13_BIT,
        .timer_num = LEDC_TIMER,
        .freq_hz = 5000
    };
    ledc_timer_config(&ledc_timer);

    ledc_channel_config_t ledc_channel_conf = {
        .channel = LEDC_CHANNEL,
        .duty = 0,
        .gpio_num = LED_GPIO,
        .speed_mode = LEDC_HIGH_SPEED_MODE,
        .hpoint = 0,
        .timer_sel = LEDC_TIMER
    };
    ledc_channel_config(&ledc_channel_conf);

    // 初始化MQTT
    esp_mqtt_client_config_t mqtt_cfg = {
        .uri = MQTT_URI
    };
    client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(client);

    // 主循环可空转或做其他处理
    while (true) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

5. 测试步骤

  1. 启动 MQTT Broker(例如在同网段的PC上运行 Mosquitto)。
  2. 启动 Home Assistant,并确保 mqtt: 配置已启用 discovery。
  3. 烧录上面的代码到 ESP32,启动后ESP32连接Wi-Fi,连接MQTT。
  4. Home Assistant 几秒后应自动发现新设备:My Smart SwitchMy Smart Light
  5. 在 Home Assistant 前端控制该开关和灯,观察ESP32串口日志,以及实际继电器和LED的变化。

6. 扩展与优化

  • 可增加更多传感器(温度、功率计量)并通过MQTT Sensor Discovery发布数据给HA。
  • 增加离线检测机制,当MQTT断开时自动重连。
  • 根据实际硬件结构实现更复杂的灯光控制方案(如CCT双路PWM)和电工测量(电流传感器等)。

以上是基于 Home Assistant 的 MQTT 协议整合电工、照明及客户端开发的详细方案与参考代码。

Home Assistant可以通过MQTT协议与其他设备进行通信。MQTT是一种轻量级的发布/订阅协议,它可以在低带宽和不可靠的网络上运行。以下是如何将MQTT设备接入Home Assistant的步骤: 1. 配置MQTT Broker 首先,您需要配置MQTT Broker。MQTT Broker是一个中央服务器,用于管理MQTT客户端之间的通信。您可以使用公共MQTT Broker,也可以自己搭建一个。 如果您想自己搭建一个MQTT Broker,可以使用开源的Mosquitto Broker。安装Mosquitto Broker的方法取决于您使用的操作系统。您可以在Mosquitto Broker的官方网站上找到安装说明。 2. 配置MQTT设备 接下来,您需要配置MQTT设备。MQTT设备可以是任何支持MQTT协议的设备,例如智能家居设备、传感器、摄像头等等。每个MQTT设备都应该有一个唯一的主题(Topic),用于发布和订阅消息。 3. 配置Home Assistant 最后,您需要在Home Assistant中配置MQTT集成程序。首先,您需要在configuration.yaml文件中添加以下行,以启用MQTT集成程序: ``` mqtt: broker: <MQTT Broker的IP地址> ``` 然后,您需要添加MQTT设备的配置。例如,如果您有一个名为“light”的MQTT设备,则可以添加以下行: ``` light: - platform: mqtt name: "My Light" state_topic: "home/light/status" command_topic: "home/light/set" brightness_state_topic: "home/light/brightness/status" brightness_command_topic: "home/light/brightness/set" ``` 在这个例子中,“home/light/status”是设备的状态主题,用于发布设备的状态。同样,“home/light/set”是设备的命令主题,用于接收命令。如果设备支持调光功能,则可以添加亮度状态和命令主题。 现在,您可以在Home Assistant中控制MQTT设备了。例如,您可以使用自动化来根据天气预报控制灯光。您可以使用Home Assistant的模板传感器来获取天气预报信息,并使用自动化来控制灯光。例如,您可以创建以下自动化: ``` - alias: "Turn on light when it's cloudy" trigger: platform: template value_template: "{{ states('sensor.weather') == 'cloudy' }}" action: service: light.turn_on entity_id: light.my_light ``` 在这个例子中,当天气预报为“cloudy”时,自动化将打开名为“my_light”的灯光。您可以根据需要更改自动化的条件和操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值