【Follow me第二季第2期】+ 进阶任务 :通过Wi-Fi,利用MQTT协议接入HA
[复制链接]
本帖最后由 御坂10032号 于 2024-9-8 18:39 编辑
前言
在前两章我们已经学习到了如何基础的使用R4, 那么本章节我们将学习一下如何使用R4的 Wifi功能将R4接入HA
正文
在我们开始之前我希望你已经在部署好了以下服务(无论本地或者云端)。
1- HomeAssistant
2- MQTT服务
我的这两个服务是跑的本地的一块99元的香橙派上的,如下是容器示例
通过8123端口我们可以正确的访问到HomeAssistant的管理端
同时进行MQTT连接测试
前置工作已经准备好了,那么现在我们就可以开始我们的任务了。 那么这个任务一共分为以下两点
1- 连接WIFI
2- 连接MQTT并且发送消息
对于WIFI的连接比较简单, 我们可以参考S3的wifi连接示例,如下所示
我们仅仅需要的是代码中的 ssid 和 pass (我这里尝试连接5G的信号失败, 正常的2.4G没问题)
代码如下所示
#include <WiFiS3.h>
char ssid[] = "ImmortalWrt";
char pass[] = "mazha1997";
int status = WL_IDLE_STATUS;
void setup() {
Serial.begin(9600);
while (!Serial) {
}
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) {
Serial.print(":");
}
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
}
Serial.println();
}
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
}
void loop() {
}
我们将代码烧录到开发板之后呢,打开串口助手便可以看到正确的控制台输出
现在我们便开始处理我们的第二个任务, 使用MQTT连接到HA(也就是MQTT服务器,使其HA中集成的MQTT自动发现我们的配置服务)。
参考Arduino的官方文档,我们得知,可以使用ArduinoMqttClient的库来连接MQTT。 我们在上述的代码上稍作修改。
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
char ssid[] = "ImmortalWrt";
char pass[] = "mazha1997";
int status = WL_IDLE_STATUS;
const char broker[] = "192.168.1.113";
int port = 1883;
const char topic[] = "/aht10/test";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
void setup() {
Serial.begin(9600);
while (!Serial) {
}
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You are connected to MQTT");
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) {
Serial.print(":");
}
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
}
Serial.println();
}
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
}
void loop() {
mqttClient.beginMessage(topic);
mqttClient.print("Hello EEworld and Digikey!");
mqttClient.endMessage();
delay(500);
}
将程序烧录到开发板上后,我们打开MQTTX, 查看我们MQTT的目标主题.
此时我们已经可以正确的接收来自Arduino发送的消息。 接下来我们要做的就是解析数据,使其HA可以根据MQTT的格式自动识别为HA中的实体。根据HA的官方文档我们得知,可以分为自动发现或者配置configuration.yml. 我这里选择是后者。同时配置了一个灯(Switch)
根据上述配置文件得知,我们可以往两个主题内发送消息,从而控制HA的中实体的状态
1- home/bedroom/switch1 状态主题
2- home/bedroom/switch1/set 命令主题
当我们想要关闭灯的时候,只需要向命令主题中发送OFF即可, 如果想要开灯则发送ON. 但是尽管它已经可以正常的控制灯的开关。但是HA中实体的状态并不会发生变化。 如果想要实体的状态也发送变化的话,则需要向状态主题中也发送一个OFF
我们简单的修改一下代码,使其每秒切换灯的状态。
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
char ssid[] = "ImmortalWrt";
char pass[] = "mazha1997";
int status = WL_IDLE_STATUS;
const char broker[] = "192.168.1.113";
int port = 1883;
const char command_topic[] = "home/bedroom/switch1/set";
const char state_topic[] = "home/bedroom/switch1";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
bool index = true;
void setup() {
Serial.begin(9600);
while (!Serial) {
}
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You are connected to MQTT");
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) {
Serial.print(":");
}
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
}
Serial.println();
}
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
}
void loop() {
if(index)
{
mqttClient.beginMessage(command_topic);
mqttClient.print("ON");
mqttClient.endMessage();
mqttClient.beginMessage(state_topic);
mqttClient.print("ON");
mqttClient.endMessage();
}else {
mqttClient.beginMessage(command_topic);
mqttClient.print("OFF");
mqttClient.endMessage();
mqttClient.beginMessage(state_topic);
mqttClient.print("OFF");
mqttClient.endMessage();
}
index = !index;
delay(1000);
}
实验现象如下:
9月8日
代码如下:
|