449|0

19

帖子

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平台的任务,属实不易。具体信息的动态展示可以查看随附的视频。

        

播放器加载失败: 未检测到Flash Player,请到安装
05-Wifi+MQTT接入HA平台

点赞 关注
个人签名

就是个臭打游戏

 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
报名最后一周!2025 英飞凌消费、计算与通讯创新大会-北京站
会议时间:3月18日(周二)09:30签到
参会奖励:电动螺丝刀套装、户外登山包、京东卡

查看 »

 
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
快速回复 返回顶部 返回列表