【Follow me第二季第2期】进阶任务 :通过Wi-Fi,利用MQTT协议接入HA
本帖最后由 sinc_sila 于 2024-10-16 09:54 编辑<p><span style="font-size:20px;"><span style="color:#e74c3c;"><strong>MQTT部署:</strong></span></span></p>
<p><span style="font-size:18px;"><b>我通过UNRAID NAS系统中的Docker部署EMQX:</b></span></p>
<div style="text-align: left;"></div>
<div><strong><span style="font-size:18px;">通过18083端口来进行web端访问:</span></strong></div>
<div>
<div style="text-align: left;"></div>
<p> </p>
</div>
<div><span style="font-size:18px;"><b>测试MQTT连接:</b></span></div>
<div><span style="font-size:18px;"><b>1.</b>Arduino UNO R4 WiFi 烧录以下代码:</span>
<pre>
<code>#include <ArduinoMqttClient.h> // 引入MQTT客户端库
#include <WiFiS3.h> // 引入WiFi库
#include <WiFiClient.h> // 引入WiFi客户端库
char ssid[] = "Sinc"; // WiFi网络名称
char pass[] = "xc12345678"; // WiFi密码
int status = WL_IDLE_STATUS; // WiFi连接状态
const char broker[] = "xxxx"; // MQTT代理服务器地址
int port = 1883; // MQTT代理服务器端口
const char topic[] = "Aht10"; // MQTT主题
WiFiClient wifiClient; // 创建WiFi客户端对象
MqttClient mqttClient(wifiClient); // 创建MQTT客户端对象,并传入WiFi客户端对象
void setup() {
Serial.begin(9600); // 初始化串口通信
while (!Serial) {} // 等待串口监视器打开
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("与WiFi模块通信失败!"); // 如果没有检测到WiFi模块,则停止程序
while (true);
}
String fv = WiFi.firmwareVersion(); // 获取WiFi固件版本
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("请升级固件"); // 如果固件版本过低,则提示升级
}
// 尝试连接到WiFi网络
while (status != WL_CONNECTED) {
Serial.print("尝试连接到WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // 连接到WiFi网络
delay(10000); // 等待10秒看是否连接成功
}
Serial.println("已连接到网络"); // 连接成功后的提示
printCurrentNet(); // 打印当前网络信息
printWifiData(); // 打印WiFi数据
// 尝试连接到MQTT代理服务器
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT连接失败!错误代码 = ");
Serial.println(mqttClient.connectError()); // 如果连接失败,则打印错误代码
while (1); // 停止程序
}
Serial.println("已连接到MQTT"); // 连接成功后的提示
}
// 打印当前网络信息
void printCurrentNet() {
Serial.print("SSID: "); Serial.println(WiFi.SSID()); // 打印网络名称
byte bssid; WiFi.BSSID(bssid); printMacAddress(bssid); // 打印路由器MAC地址
Serial.print("信号强度 (RSSI):"); Serial.println(WiFi.RSSI()); // 打印信号强度
Serial.print("加密类型: "); Serial.println(WiFi.encryptionType(), HEX); // 打印加密类型
Serial.println();
}
// 打印MAC地址
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) Serial.print(":");
if (mac < 16) Serial.print("0");
Serial.print(mac, HEX);
}
Serial.println();
}
// 打印WiFi数据
void printWifiData() {
IPAddress ip = WiFi.localIP(); // 获取本地IP地址
Serial.print("IP地址: "); Serial.println(ip); // 打印IP地址
byte mac; WiFi.macAddress(mac); Serial.print("MAC地址: "); printMacAddress(mac); // 打印MAC地址
}
// 主循环
void loop() {
mqttClient.beginMessage(topic); // 开始发送MQTT消息
mqttClient.print("Hello EEworld and Digikey!"); // 发送消息内容
mqttClient.endMessage(); // 结束发送MQTT消息
delay(1000); // 延迟1秒
}</code></pre>
<p><span style="font-size:18px;">烧录后串口通讯显示:</span></p>
<div style="text-align: left;"></div>
<p> </p>
</div>
<p><span style="font-size:18px;">下载MQTT 客户端工具可以直观的观察到MQTT主题通讯:</span></p>
<div style="text-align: left;"></div>
<hr />
<p><span style="color:#e74c3c;"><span style="font-size:20px;"><strong>Home Assistant部署:</strong></span></span></p>
<p><b>同样UNRAID NAS系统中的Docker部署</b><strong>Home Assistant</strong><b>:</b></p>
<div style="text-align: left;"></div>
<div style="text-align: left;"><span style="font-size:18px;"><strong>通过18083端口来进行web端访问:</strong></span></div>
<div style="text-align: left;"></div>
<div style="text-align: left;">
<h2>配置MQTT:</h2>
<h3><span style="font-size:18px;">参考官方配置方式: <a href="https://www.home-assistant.io/integrations/mqtt" rel="nofollow" title="MQTT - Home Assistant (home-assistant.io)">MQTT - Home Assistant (home-assistant.io)</a></span></h3>
<p><span style="font-size:18px;">配置-->设备与服务-->集成-->添加集成-->搜索MQTT-->点击配置域名端口等信息:</span></p>
<div style="text-align: left;"></div>
<div style="text-align: left;"></div>
<div style="text-align: left;"><span style="font-size:18px;">然后完成就配置成功了,下面是成功界面<strong>:</strong></span></div>
<div style="text-align: left;"></div>
<div style="text-align: left;">
<hr />
<p><strong><span style="font-size:18px;">通过配置<span style="color:#e74c3c;">configuration.yml</span>文件,在Home Assistant首页创建了一个开关控制板载LED灯:</span></strong></p>
<p><span style="font-size:16px;">找到homeassistant的根目录中的configuration.yml文件打开:</span></p>
<div style="text-align: left;"></div>
<div style="text-align: left;"><span style="font-size:16px;"><strong>在此代码基础上增加以下代码:</strong></span></div>
<pre>
<code>mqtt:
switch:
- unique_id: R4_led #设备ID
name: "R4_led" #设备名称
state_topic: "Aht10" #订阅端口
command_topic: "Aht10" #同上
payload_on: "1" #开灯的指令
payload_off: "2" #关灯的指令</code></pre>
<p><strong><span style="font-size:16px;">保存代码后重启homeassistant,显示以下按钮表示创建成功:</span></strong></p>
</div>
</div>
<div style="text-align: left;">
<ol>
<li style="text-align: left;"></li>
</ol>
<hr />
<p><strong>修改代码来控制板载led:</strong><br />
</p>
<pre>
<code>#include <ArduinoMqttClient.h> // 引入MQTT客户端库
#include <WiFiS3.h> // 引入WiFi库
#include <WiFiClient.h> // 引入WiFi客户端库
char ssid[] = "Sinc"; // WiFi网络名称
char pass[] = "xc12345678"; // WiFi密码
int status = WL_IDLE_STATUS; // WiFi连接状态
const char broker[] = "XXXX"; // MQTT代理服务器地址
int port = 1883; // MQTT代理服务器端口
const char topic[] = "Aht10"; // MQTT主题
WiFiClient wifiClient; // 创建WiFi客户端对象
MqttClient mqttClient(wifiClient); // 创建MQTT客户端对象,并传入WiFi客户端对象
void setup() {
Serial.begin(9600); // 初始化串口通信
while (!Serial) {} // 等待串口监视器打开
// 初始化内置LED引脚为输出模式。
pinMode(LED_BUILTIN, OUTPUT);
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("与WiFi模块通信失败!"); // 如果没有检测到WiFi模块,则停止程序
while (true);
}
// 尝试连接到WiFi网络
while (status != WL_CONNECTED) {
Serial.print("尝试连接到WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // 连接到WiFi网络
delay(10000); // 等待10秒看是否连接成功
}
Serial.println("已连接到网络"); // 连接成功后的提示
printCurrentNet(); // 打印当前网络信息
printWifiData(); // 打印WiFi数据
// 尝试连接到MQTT代理服务器
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT连接失败!错误代码 = ");
Serial.println(mqttClient.connectError()); // 如果连接失败,则打印错误代码
while (1); // 停止程序
}
Serial.println("已连接到MQTT"); // 连接成功后的提示
// 订阅主题
mqttClient.subscribe(topic);
Serial.print("等待主题上的消息: ");
Serial.println(topic);
Serial.println();
// 设置消息接收回调
mqttClient.onMessage(onMqttMessage);
}
void printCurrentNet() {
Serial.print("SSID: "); Serial.println(WiFi.SSID()); // 打印网络名称
byte bssid; WiFi.BSSID(bssid); printMacAddress(bssid); // 打印路由器MAC地址
Serial.print("信号强度 (RSSI):"); Serial.println(WiFi.RSSI()); // 打印信号强度
Serial.print("加密类型: "); Serial.println(WiFi.encryptionType(), HEX); // 打印加密类型
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) Serial.print(":");
if (mac < 16) Serial.print("0");
Serial.print(mac, HEX);
}
Serial.println();
}
void printWifiData() {
IPAddress ip = WiFi.localIP(); // 获取本地IP地址
Serial.print("IP地址: "); Serial.println(ip); // 打印IP地址
byte mac; WiFi.macAddress(mac); Serial.print("MAC地址: "); printMacAddress(mac); // 打印MAC地址
}
void loop() {
// 定期调用poll()以允许库接收MQTT消息并
// 发送MQTT保持活动信号,以避免被代理断开连接
mqttClient.poll();
}
void onMqttMessage(int messageSize) {
// 我们收到了一条消息,打印出主题和内容
Serial.println("收到一条消息:");
Serial.print(mqttClient.messageTopic());
Serial.print(", 长度 ");
Serial.print(messageSize);
Serial.println(" 字节:");
// 使用Stream接口打印内容
String message;
while (mqttClient.available()) {
message += (char)mqttClient.read();
}
Serial.println(message);
// 检查消息内容并控制LED
if (message == "1") {
digitalWrite(LED_BUILTIN, HIGH); // 打开LED
Serial.println("LED_BUILTIN 已打开");
} else if (message == "2") {
digitalWrite(LED_BUILTIN, LOW); // 关闭LED
Serial.println("LED_BUILTIN 已关闭");
}
Serial.println();
}</code></pre>
<p><span style="font-size:18px;">串口显示消息:</span><br />
</p>
<div style="text-align: left;"></div>
<p><span style="font-size:18px;">演示视频:</span><br />
4056f1eecec4d50c1ad10007071d7470<br />
</p>
</div>
<p> </p>
页:
[1]