UNO R4 Wi-Fi 接入 Home Assistant

项目介绍

本项目是Funpack第五期板卡三的任务1实现.
任务目标是让UNO R4 Wi-Fi通过网络连接到智能云端, 并模拟成一个可以控制的灯, 通过远程控制调整自带的LED矩阵点亮范围.

实现思路

将UNO R4作为灯装置接入IOT平台, 随后在IOT平台上下发命令来操作UNO R4, 调整这个”灯”的亮度.
这里我选择的是可以部署在内网环境下的Home Assistant.

UNO R4通过MQTT服务器与Home Assistant进行通信. MQTT服务器选择EMQX开源版.

结构图

插件安装

代码编写

注册到Home Assistant

publish 指定格式的payload到topic
其中topic格式为homeassistant/设备类型/自定义名称/config,根据格式要求.
得到主题应当为homeassistant/light/fun_matrix/config.
payload内容是一个描述设备的json字符串, 如下代码所示.

  • 其中name是设备名称;
  • device_class要和注册topic中设备类型对应;
  • command_topic代表设备的开关状态;
  • brightness_command_topic灯的亮度控制;
  • unique_id装置唯一ID;
  • device设备描述;
  • schema代表当前为json格式;
  • brightness代表本装置支持亮度控制;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    void registerToHomeAssistantServer() {
    const char* topic = "homeassistant/light/fun_matrix/config";
    std::string message = R"({
    "name": "led",
    "device_class": "light",
    "command_topic": "fun_matrix/light/state",
    "brightness_command_topic": "fun_matrix/light/brightness/set",
    "unique_id": "fun_matrix",
    "device": {
    "identifiers": "fun_matrix",
    "name": "UnoR4WiFi"
    },
    "schema": "json",
    "brightness": true
    }
    )";
    bool retained = false;
    int qos = 1;
    bool dup = false;
    mqttClient.beginMessage(topic, message.length(), retained, qos, dup);
    mqttClient.print(message.c_str());
    mqttClient.endMessage();
    }

响应HomeAssistant命令

根据注册时候payload中brightness_command_topic和command_topic, 来响应具体的动作即可.
其中command_topic固定传递ON和OFF字符串, brightness_command_topic传递亮度值0-255.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void onMqttMessage(int messageSize) {
String topic = mqttClient.messageTopic();
Serial.println(topic);
String payload;
while (mqttClient.available()) {
payload = mqttClient.readString();
Serial.println(payload);
}

if (topic.endsWith("state")) {
Serial.print("brightness_state_topic");
bool enable = payload.equals("ON");
if (lightIsOn != enable) {
lightIsOn = enable;
if (lightIsOn) {
showFrame(level);
} else {
showFrame(0);
return;
}
}
}
if (topic.endsWith("set")) {
Serial.print("brightness_command_topic");
level = payload.toInt() / 25;
Serial.println(level);
showFrame(level);
return;
}
}

成果展示