sinc_sila 发表于 2024-10-15 16:21

【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>&nbsp;</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 &lt;ArduinoMqttClient.h&gt; // 引入MQTT客户端库
#include &lt;WiFiS3.h&gt; // 引入WiFi库
#include &lt;WiFiClient.h&gt; // 引入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 &lt; 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 &lt; 6; i++) {
   if (i &gt; 0) Serial.print(":");
   if (mac &lt; 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>&nbsp;</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;">参考官方配置方式:&nbsp;<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;">配置--&gt;设备与服务--&gt;集成--&gt;添加集成--&gt;搜索MQTT--&gt;点击配置域名端口等信息:</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 />
&nbsp;</p>

<pre>
<code>#include &lt;ArduinoMqttClient.h&gt; // 引入MQTT客户端库
#include &lt;WiFiS3.h&gt; // 引入WiFi库
#include &lt;WiFiClient.h&gt; // 引入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 &lt; 6; i++) {
    if (i &gt; 0) Serial.print(":");
    if (mac &lt; 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 />
&nbsp;</p>

<div style="text-align: left;"></div>

<p><span style="font-size:18px;">演示视频:</span><br />
4056f1eecec4d50c1ad10007071d7470<br />
&nbsp;</p>
</div>

<p>&nbsp;</p>
页: [1]
查看完整版本: 【Follow me第二季第2期】进阶任务 :通过Wi-Fi,利用MQTT协议接入HA