378|0

16

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【Follow me第二期】进阶任务 - WiFi+MQTT协议连接智能家居HA平台 [复制链接]

  本帖最后由 Aclicee 于 2024-10-7 22:41 编辑

        进阶任务主要使用的是Arduino UNO R4 WiFi板子的ESP32S3 WiFi模块。尽管我对这一领域的知识尚浅,但通过与Arduino、上位机软件、HomeAssistant(HA)这一开源智能家居平台,以及MQTT协议和EMQX消息服务器的深入交互,我得以构建了一个多平台联动的智能系统。这一过程充满了挑战,但也充满了成就感。在本文中,我将分享我的探索之旅,包括遇到的困难和解决方案,希望能为同样走在这条道路上的你提供一些启示和帮助。

1. HA平台的安装和配置

        为了实现我们智能家居项目的核心功能,我们首先需要安装并配置Home Assistant(HA),这是一个流行的开源智能家居平台。详细的安装和使用教程可以在【Home Assistant (home-assistant.io)】找到。按照“Get Started”的指引,我们可以进入官方教程,了解HA支持的多种安装方式。

        考虑到便利性和易用性,我们选择使用Docker进行安装。Docker可以从【Docker: Accelerated Container Application Development】下载。安装并注册完成后,确保Docker Engine在Docker Desktop中启动。如果你需要科学上网来访问Docker服务,请确保相应的配置已经完成。

        接下来,我们将在Docker中拉取HA的镜像。根据【Linux - Home Assistant (home-assistant.io)】中的“Installation with Docker”部分,我们首先在命令行界面(CMD)中执行docker search home-assistant命令,以查看可用的容器目录。以下是具体的命令输出:

        我们选择列表中的第一个镜像,并通过执行docker pull homeassistant/home-assistant命令来拉取它。请注意,拉取过程可能需要一些时间,并且有时会因为网络问题而中断。如果遇到失败,只需重新尝试即可。

        拉取完成后,我们需要配置Docker容器在本地的存储位置,并运行容器。与官方教程稍有不同,由于我们已经提前拉取了容器,因此不需要再次从镜像源下载。我们可以直接使用以下命令来运行容器:

docker run -d --name homeassistant -v /path/to/local/config:/config -p 8123:8123 homeassistant/home-assistant

        请将/path/to/local/config替换为你本地存放容器配置文件的实际路径,并将端口号8123替换为你希望使用的端口。

        运行上述命令后,你可以在Docker Engine中看到名为homeassistant的容器。通过访问http://localhost:8123,你可以进入Home Assistant的Web界面。

        在首次访问时,系统会提示你创建你的智能家居。按照提示完成一系列信息注册后,重新登录Home Assistant,你就可以进入主界面了。

        完成后重新登录HomeAssistant,主页显示的相关信息如下:

2. EMQX平台的安装和配置

        MQTT协议是一种轻量级的、基于发布/订阅模式的消息传输协议,广泛用于物联网和分布式系统中。它具有简单易实现、支持多种服务质量(QoS)、报文精简、基于TCP/IP等特性,特别适合于带宽有限和网络不稳定的环境。EMQX平台是一个高性能、可扩展的MQTT消息服务器,支持大规模分布式物联网设备的连接,能够实时处理和移动大量消息和事件流数据。

        EMQX的具体信息可以在其官方网站【EMQX 文档】查看,里面也提供了使用MQTT协议的相关教程。我们还是采用docker拉取容器的方式,参考【通过 Docker 运行 EMQX | EMQX文档】的文档说明。我们在指令栏中输入docker search emqx来查找可供拉取的容器列表。

        没有看到说明文档中提到的带版本号的emqx容器,就直接拉取第一个根目录,使用docker pull emqx来进行拉取。

        拉取完成后,我们可以使用以下命令来运行EMQX容器:

docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 -v /path/to/local/config:/opt/emqx/data emqx/emqx:5.8.0

        请将/path/to/local/config替换为您本地存放容器配置文件的实际路径。此时可以看到docker的容器列表中新增了emqx容器。

        使用https://localhost:18083端口可以打开EMQX平台,参考以下文档进行初步的测试【快速开始 | EMQX文档】,平台默认的账号是admin,密码是public,即可登录EMQX Dashboard,界面如下:

        接下来,我们需要在EMQX Dashboard中创建客户端认证,并添加用户作为HA平台的接入。

        完成后,我们需要在HA平台中配置MQTT服务,填写相关的配置信息,包括EMQX平台的IP、用户名和密码等。EMQX节点的名称可以在集群概览中查看,比如这边是emqx@172.17.0.2。

        通过HA平台的设置菜单,配置新的设备与服务,选择MQTT。

        配置完成后,我们可以通过HA平台的设置菜单,配置新的设备与服务,选择MQTT,并填写相关的配置信息。这样,HA平台就可以通过MQTT协议与EMQX平台进行通信了。

        最后,我们可以通过检查EMQX平台的在线连接数来验证HA平台是否已经成功接入EMQX集群。如果连接数从0变为1,说明HA平台已经成功接入。接下来,我们可以通过MQTT协议将Arduino接入EMQX平台,实现Arduino和HA之间的通信和数据传输。

3. 进阶任务(必做):ArduinoWifi连接并通过MQTT协议接入到HomeAssistant平台

        我们将探讨如何将Arduino UNO R4 WiFi开发板通过WiFi连接,并利用MQTT协议接入HomeAssistant平台。这一过程不仅涉及到硬件的配置,还包括了软件的集成,是对我们技能的一次全面考验。

        首先,我们需要启动Arduino的WiFi模块。可以参考官方文档【docs.arduino.cc/tutorials/uno-r4-wifi/wifi-examples】,里面提供了Arduino连接Wifi的示例。我们创建一个arduino_secret.h的保密文件,用于存储连接WiFi路由器的敏感信息,如网络名称(SSID)和密码等。

        由于我在学校连接校园网需要特定的账号和密码,这一部分在Arduino中实现较为复杂,因此我们选择了一个更为简便的方法:使用手机作为热点,让Arduino通过热点进行连接。

        我们直接采用官方例程中的代码,配置WiFi模块。主要包括以下几个部分:引入必要的头文件WiFiS3.h;使用WiFi.begin(ssid, pass)启用WiFi并连接;确认WiFi连接状态并打印相关信息,如网络名称、IP地址、MAC地址等。

#include <WiFiS3.h>

#include "arduino_secrets.h"

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;     // the WiFi radio's status

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the WiFi module:
  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);
  }

  // you're connected now, so print out the data:
  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();

}

void loop() {
  // check the network connection once every 10 seconds:
  delay(10000);
  printCurrentNet();
}

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 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();
}

        将代码烧录到Arduino中,我们可以看到WiFi模块成功连接到了手机热点,并且打印出了网络信息。同时手机上也显示ESP32S3模块的连接。至此完成了wifi模块的使用。

        接下来,我们需要在Arduino IDE中安装MQTT和HomeAssistant相关的库文件。可以在Library管理器中搜索并安装home-assistant-integration库。

        安装好所有所需的库文件和插件,我们可以查看一下其中涉及MQTT相关操作的例程,因为后面可选任务涉及光照和温湿度传感器的使用,所以我们以模拟传感器的例程为参考【

链接已隐藏,如需查看请登录或者注册
】,我们使用Arduino内置的DAC来暂时模拟一下传感器的输出。

        由于我们已经配置好了EMQX平台,接下来需要在arduino_secret.h文件中增加EMQX平台的用户名、密码等信息,具体如下:

//arduino_secrets.h header file
#define SECRET_SSID "Galaxy S24+ 6927"
#define SECRET_PASS "LYQ1234567890"

#define MQTT_SERVER "192.168.40.250"
#define MQTT_PORT   1883
#define MQTT_CLIENT_ID "arduino"
#define MQTT_USERNAME  "admin"
#define MQTT_PASSWORD  "admin"
#define TOPIC_SUBSCRIBE "UNO/arduino/sensor"

        因为EMQX平台是基于电脑的IP搭建的,其中MQTT_SERVER后的地址就是当前电脑无线网络的IP地址,可以在指令栏中通过ipconfig/all来查询,如下:

        将相关信息全部录入arduino_secret.h头文件,然后仿照上面的例程。因为例程中使用的Ethernet以太网,所以我们只需要学习其中涉及MQTT相关的部分,将其合并到上面的Wifi连接的程序中。

        现在,我们将WiFi连接代码与MQTT代码整合在一起。首先,我们引入ArduinoHA.h头文件,以便使用HomeAssistant平台。

        我们使用HADevice device(MQTT_CLIENT_ID)HAMqtt mqtt(client, device)来创建HA设备启用MQTT协议。然后我们实例化了几个HA订阅的传感器,比如按钮、模拟传感器和更新时间传感器等,这些可以根据后面任务的需求进行调整。也可以通过device.XX或者某个具体定义的传感器的字段进行修改,来自定义传感器在HA平台的UI上呈现的形式(比如图标、是否附加单位等)。

        以上的初始设置完成以后,我们在Wifi代码的基础上增加以下代码:

  Serial.println("\nStart connecting to MQTT server");
  if (!mqtt.begin(MQTT_SERVER, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD)){
    Serial.print("Connection falied");
    Serial.print(mqtt.getState());
    Serial.println("Try again in 5 seconds");
    delay(5000);
  }

        核心为mqtt. begin()用于启动MQTT的连接,需要输入服务器的地址、端口以及我们预设好的用户名和密码。完成后需要在程序的主循环中通过mqtt.loop()使其使用MQTT协议进行信息的发送。后面我们就仿照例程中发送传感器数据的方式,添加了两个每间隔1000ms进行一次更新采集数据和时间的代码,完整代码如下:

#include <WiFiS3.h>
#include <ArduinoHA.h>

#include "arduino_secrets.h"
#include "analogWave.h"

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;     // the WiFi radio's status
unsigned long lastUpdateAt = 0;
int freq = 1;

WiFiClient client;
HADevice device(MQTT_CLIENT_ID);
HAMqtt mqtt(client, device);

HASensorNumber analogSensor("myAnalogInput", HASensorNumber::PrecisionP1);
HASensorNumber uptimeSensor("myUptime");

HAButton buttonA("myButtonA");
HAButton buttonB("myButtonB");

analogWave wave(DAC);

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the WiFi module:
  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);
  }

  // you're connected now, so print out the data:
  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();

  Serial.println("\nStart connecting to MQTT server");
  if (!mqtt.begin(MQTT_SERVER, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD)){
    Serial.print("Connection falied");
    Serial.print(mqtt.getState());
    Serial.println("Try again in 5 seconds");
    delay(5000);
  }
  wave.sine(freq);
  wave.amplitude(0.5);

  analogReadResolution(14);

  device.setName("Arduino");
  device.setSoftwareVersion("1.0.0");
  buttonA.setIcon("mdi:fire");
  buttonA.setName("Click me A");
  buttonB.setIcon("mdi:home");
  buttonB.setName("Click me B");
}

void loop() {
  // check the network connection once every 10 seconds:
  mqtt.loop();
  if ((millis() - lastUpdateAt) > 1000) { // 1000ms debounce time
        uint16_t reading = analogRead(A0);
        float voltage = reading * 5.f / 16383.f; // 0.0V - 5.0V
        Serial.print("Volt:");
        Serial.println(voltage);
        analogSensor.setValue(voltage);

        unsigned long uptimeValue = millis() / 1000;
        Serial.print("Uptime:");
        Serial.println(uptimeValue);
        uptimeSensor.setValue(uptimeValue);

        lastUpdateAt = millis();
    }
}

        全部代码完成以后,将其烧录,同时启动docker中的HA容器和EMQX容器,并通过对应的端口号打开其网页。烧录需要花费很多时间,电脑因为开了太多的东西已经卡顿不堪了,最终结果如下:

        我们可以看到Arduino首先成功连接了wifi,并输出wifi的相关信息,然后尝试建立MQTT的连接并且成功连接,Arduino通过串口发送了采集到的传感器电压,以及更新时间。

        在HA平台的服务器上,我们可以看到Arduino已经成功接入并开始更新采样到的电压和时间信息。

        至此,我们成功完成了Arduino通过WiFi连接并通过MQTT协议接入HomeAssistant平台的任务,属实不易。具体信息的动态展示可以查看随附的视频。

        

05-Wifi+MQTT接入HA平台

点赞 关注
个人签名

就是个臭打游戏

 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
基于ARM7与μClinux的嵌入式系统多串口设计

11764

ViewSonic(优派)17"CRT显示器的电源维修

今天闲来无事,遂把昨日一友人送来维修的ViewSonic(优派)17"CRT显示器打开.稍适清理灰尘,经观察未发现明显烧损痕迹.通电测+30 ...

关于跳槽的一点看法

昨天发了一个帖子,讲述了下第一份工作的事情,呵呵,看到了朋友们的留言,三年的时间换了三个公司是不是太频繁了呢?是不是 ...

有没有想DIY 白光烙铁控制器的同学?——遇到了问题 这么晚了不知还有人在吗?

背景: 手头一直有一个T12的白光烙铁头,但只是偶尔用一下。原因是直接接的12V,怕时间长了就烧坏了。 淘宝上的二手 T12 也 ...

小梅哥和你一起深入学习FPGA之初学者指南

感谢论坛给我的诸多照顾,通过和广大电子爱好者深入交流,我真正了解到了很多初学者的困惑。特权同学的深入浅出玩转FPGA系列 ...

KiCad 5.1.7于9月30号已经正式发布了

KiCad 5.1.7于2020年9月30号已经正式发布了,喜欢的童鞋们可以试试,,, 504305504308504309

小功率开关电源设计实战

本章节以实用小型电源的设计为例,说明电源设计的方法。控制电路形式为它激式,采用UC3842为PWM控制电路。电源开关频率的选择决 ...

【2022得捷创新设计大赛】物料开箱

本帖最后由 cjjh2014 于 2022-6-13 23:35 编辑 【2022得捷创新设计大赛】物料开箱 非常荣幸参加并入围了2022年得 ...

【EETALK】当你面临选择时,你会选常闭耗尽型 (D-Mode) 的氮化镓晶体管吗?

氮化镓功率半导体器件现在是真的是很火,可以应用在很多方面。目前占主导的氮化镓半导体器件有两种:Normally-off D-mode和Norma ...

请教朋友们,开关电 源BUCK电路电压环路与电流环路都要吗?

请教朋友们,开关电 源BUCK电路电压环路与电流环路都要吗?如题,想要做 一个稳定的BUCK电源还需要哪些设计?

关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表