探索如何在Arduino Uno Q上运行Home Assistant
当我拿到Uno Q板子的那一刻,一个疑问就一直萦绕在我心头:一块带有真实Linux系统的主板,旁边连接着微控制器,能否运行Home Assistant?我开始寻找相关指南,却一无所获。虽然有很多关于Bridge、App Lab以及两个处理器之间通信的文档,但没有一篇能详细说明如何实际安装Home Assistant并连接到该板子自身的GPIO接口。于是,我决定亲自尝试解决:通过SSH登录,查看系统中已有的内容,然后自己搭建桥接功能。接下来的内容就是整个过程中的所有成功步骤,以及在过程中悄然失败的细节,让你无需从头重新摸索。
你将构建什么
到本教程结束时,你将能够:
•在 Uno Q 的 Linux 端运行 Docker 中的 Home Assistant
•一个连接Linux系统与STM32微控制器的MQTT代理(Mosquitto)
•一个实际示例:在 Home Assistant 控制面板中切换开关,可使 Uno Q 的内置 LED 亮起和熄灭,设备实体会自动显示,无需手动配置控制面板。
为什么Uno Q 对于此很有趣
Arduino Uno Q 是一块“双脑”板:
•运行完整Debian Linux环境的高通QRB2210微处理器(四核Cortex-A53)
•一款STM32U585微控制器(Cortex-M33),其行为类似于经典的Arduino,可运行代码并驱动GPIO。
这两个处理器不共享内存或网络栈,它们通过一个专门设计的通信层——路由器桥接器(Router Bridge)进行通信。这意味着:
•Linux 端配备了网络、Docker、Python,以及你对小型 Debian 服务器所期待的一切功能。这里是 Home Assistant 和 MQTT 的所在地。
•MCU端本身没有独立的网络访问能力,只能通过桥接器与Linux端进行数据交换。
因此,由 Home Assistant 控制的任何物理 I/O(传感器、LED、继电器)的架构如下所示:
提前理解这一流程,能避免之后产生大量困惑。本教程中大多数“为什么这不起作用”的问题,都源于代码运行在板子的哪一侧。
你需要准备的物品
•Arduino Uno Q
•USB-C 数据线
•在同一网络中的计算机通过SSH登录并查看Home Assistant仪表板
•Arduino App Lab 已安装在您的电脑上
基础教程无需额外组件,此版本用于控制Uno Q的内置LED。最后,我会指导你如何将它替换为GPIO引脚上的外部LED,以便扩展功能。
步骤1:连接 Uno Q
通过 USB-C 为板子供电,并将其连接到网络(首次启动时通过 App Lab 设置 Wi-Fi,此处不涉及,因为不同版本的 App Lab 实现方式不同)。请按照此官方用户手册进行设置。
SSH 进入 Linux 端:
连接后,请确认您的用户名和IP地址:
请记下这个IP地址,本教程中会多次用到它(Home Assistant的仪表盘,以及后续MQTT代理连接)。
常见误区:不要假设IP地址是固定的。如果IP地址发生变化(如DHCP租约续期、路由器重启),在排查其他问题之前,应先重新运行“hostname -I”命令——过期的IP地址是导致“一切无法正常工作”的一个出人意料的常见原因。
步骤2:检查Docker
Uno Q 的 Debian 镜像自带 App Lab,而 App Lab 内部使用容器,因此 Docker 通常已经安装。在安装任何内容之前,请先检查一下:
如果返回版本字符串,请跳至第3步。
如果未安装 Docker,请使用官方脚本进行安装:
注意:如果运行安装脚本时看到提示“Docker 已经安装”,请立即取消操作(按 Ctrl+C)。在已有 Docker 环境下重新运行安装脚本,可能会破坏现有的安装,而不是进行干净的重装。
将你的用户添加到 docker 组,这样每次命令都不需要 sudo:
退出并重新登录您的 SSH 会话,以使此操作生效。
步骤3:安装Home Assistant
在 Linux 端以 Docker 容器运行 Home Assistant:
将 TZ 替换为您自己的 IANA 时区(例如:America/New_York,Europe/London)。
稍等片刻启动,然后检查是否正在运行:
在同一网络上打开浏览器并访问:
完成入职向导。
快速检查——在连接任何硬件之前,请使用其内置的演示集成来确认 HA 本身是否能实现端到端的正常工作:
设置 → 设备与服务 → 添加集成 → 演示
这会添加假的灯光、开关和传感器,以便在增加任何真实复杂性之前,确认整个系统(前端、后端)都处于正常状态。
步骤4:安装MQTT代理
Home Assistant 容器(与完整的 Home Assistant 操作系统不同)没有内置的附加组件商店,因此也没有集成的 Mosquitto 选项。你需要自行运行它作为独立容器:
陷阱 — 写配置文件时权限被拒绝:如果在执行此命令之前 ~/mosquitto/config 目录不存在,Docker 会自动创建该目录并将其所有者设为 root,因为 Docker 守护进程以 root 用户身份运行。当你以普通用户身份尝试将配置文件写入该目录时,就会出现“权限被拒绝”的错误。请在继续之前先修复此问题:sudo chown -R $USER:$USER ~/mosquitto
现在创建经纪商配置:
陷阱 — 默认配置会阻止连接:Mosquitto 2.x 的默认设置会拒绝非本地/匿名连接。如果没有在上方添加 listener 和 allow_anonymous 行,即使端口技术上是开放的,Home Assistant 的 MQTT 集成也无法成功连接。这是整个配置中最常见的故障点。在受信任网络中进行本地测试时,允许匿名(allow_anonymous true)是可以接受的,但若要长期运行,请务必在离开前添加用户名/密码认证(mosquitto_passwd)。
重启容器以便加载配置:
检查日志——你希望看到它能正常打开监听器:
直接测试经纪商,无需依赖 Home Assistant:
如果测试 hello 打印回,说明代理正常。
步骤5:将Home Assistant连接到MQTT
设置 → 设备与服务 → 添加集成 → MQTT
请输入:
•Broker:localhost
•Port:1883
•请将用户名/密码留空(与上方 allow_anonymous 为 true 相匹配)
提交。如果即使填写了字段,仍然看到“请输入您的MQTT代理连接信息”,说明HA提示无法连接,请返回并重新检查第4步(配置文件内容、容器运行状态、Docker日志mosquitto)。
步骤6:在App Lab中构建LED演示
这正是棋盘两侧真正实现连接的地方。
草图(MCU侧)
该程序运行在STM32上,并提供一个Python可以远程调用的函数:
Bridge.provide(...) 将 set_led_state 注册为 Linux/Python 端可以按名称调用的函数,这就是 Home Assistant 实现与物理硬件通信的完整机制。
Python 脚本(Linux 端)
这会连接到 MQTT,监听来自 Home Assistant 的命令,并通过 Bridge 将其转发给代码。
依赖文件
App Lab 会自动从项目中的 python/ 文件夹下的 requirements.txt 中安装 Python 依赖:
打开文件并确认其恰好只有一行空白行:paho-mqtt<2.0。
陷阱 — pin below v2:较新的 paho-mqtt(2.x)更改了回调函数的签名。上述使用的 on_connect/on_message 签名是经典的(v1)风格。在 <2.0 版本中固定 Pin,可避免连接时出现 TypeError 异常崩溃。
陷阱 — localhost 在这里不起作用,尽管在 Home Assistant 中是有效的:如果你不了解这一点,这会耗费你最多的时间。Home Assistant 的容器使用 --network=host 启动,因此容器内的 localhost 实际上指的是“Uno Q 本身”。而 App Lab 的 Python 应用程序运行在另一个独立的容器中,位于其自己的隔离 Docker 网络内,此时容器内的 localhost 指的是“这个容器”,它并没有监听端口 1883。你会看到:
解决方法是将 MQTT_BROKER 指向板子的实际局域网 IP 地址(通过 hostname -I 获取),而不是使用 localhost。由于 Mosquitto 容器会将端口 1883 发布到主机上,因此连接到主机的真实 IP 就可以从任意容器访问到它。
陷阱 — 配置文件 requirements.txt 有误:请确保该文件仅包含包规范,且单独成行。如果你不小心将 shell 命令复制粘贴到其中(例如,echo "paho-mqtt<2.0" > requirements.txt,导致内容直接成为文本文件内容,而非在终端中执行),App Lab 的依赖安装程序将无法解析它,并报错如下:error: Couldn't parse requirement in `python/requirements.txt` at position 0
打开文件并确认其恰好只有一行干净代码:paho-mqtt<2.0。
陷阱 — v2 以下的 pin:较新的 paho-mqtt(2.x)改变了回调函数的签名。上述使用的 on_connect/on_message 签名是经典的(v1)风格。pin <2.0 可避免在连接时因 TypeError 引发的崩溃。
陷阱 — 这里 localhost 不起作用,尽管它在 Home Assistant 中可以工作:如果你不了解这一点,这将耗费你最多的时间。Home Assistant 的容器以 --network=host 启动,因此容器内的 localhost 实际上指的是“Uno Q 本身”。App Lab 的 Python 应用运行在另一个独立的容器中,位于其自己的隔离 Docker 网络内,因此容器内的 localhost 指的是“这个容器”,而该容器并未监听端口 1883。你会看到:ConnectionRefusedError: [Errno 111] Connection refused
解决方法是将 MQTT_BROKER 指向板子的实际局域网 IP 地址(通过 hostname -I 获取),而不是使用 localhost。由于 Mosquitto 容器会将端口 1883 发布到主机上,因此连接到主机的真实 IP 就可以从任意容器访问到它。
步骤7:运行并验证
在 App Lab 中启动应用。观察控制台——你应该能看到草图编译并上传到 STM32,随后 Python 容器开始构建和运行。
检查 Python 容器自身的日志,以确认 MQTT 连接是否成功:
查找:
现在检查 Home Assistant:
设置 → 设备与服务 → MQTT
一个名为“Arduino Uno Q”的设备,带有“Uno Q LED”开关实体,应该已经存在了,你并未手动创建它。
切换它。机载LED应在一两秒内作出反应,且切换状态应反映LED的实际状态(而不仅仅是乐观的猜测)。
为何该实体会自动出现
这值得理解,而不是仅仅当作魔法来接受。这是你将来添加任何新传感器或执行器时都会重复使用的相同机制。
Home Assistant 的 MQTT 集成会始终在后台订阅 homeassistant/#。任何发布到 homeassistant///config 的保留 JSON 消息都被视为一条指令:“创建此实体”。我们的脚本中的 discovery_payload 向 Home Assistant 说明了这是一个开关,应向哪个主题发布命令,从哪个主题读取状态,以及将其归类到哪个设备下。Home Assistant 解析这些信息并创建了该实体,这一过程称为 MQTT 发现(MQTT Discovery),这是大多数基于 MQTT 的智能家居设备所采用的标准模式。
使用 retain=True 时,Mosquitto 将保留该配置消息永久(直到明确清除),因此即使 Home Assistant 重启,该实体也能继续存在,而无需每次重新广播。
此外,Home Assistant 默认的仪表板会自动将新注册的实体添加为卡片。这是 Home Assistant 的一种通用行为,并非 MQTT 特有功能。
故障排除检查清单
如果某件事出错,请按以下顺序检查:这些内容几乎涵盖了构建此项目时可能出现的每种故障情况。
•docker ps — homeassistant 和 mosquitto 都已启动吗?
•docker logs mosquitto — 它是否成功打开了1883监听端口,还是报告了配置问题?
•cat ~/mosquitto/config/mosquitto.conf — 它是否确实包含 listener 1883 并且 allow_anonymous 为 true?
•docker logs -main-1 — Python 端口显示“已连接到 MQTT 代理,rc = 0”还是错误堆栈?
如果在本地主机上出现 ConnectionRefusedError,说明你遇到了上面提到的容器网络陷阱;请使用该板的真实IP地址。
sudo lsof -i :1883 — 那个端口是否已被其他进程占用,与 Mosquitto 容器发生冲突?
接下来是什么
从这里开始,同样的桥接 → MQTT → Home Assistant 模式同样适用于真实传感器。接下来的自然步骤是将一个 DHT22 温湿度传感器连接到 MCU 端,并以相同的方式发布读数。不过有一个需要提前注意的常见问题:标准的 DHT 库在 Uno Q 的 MCU 上不可靠,因此建议使用 DHTesp 库,或者选择像 BME280 这样的 I2C 传感器作为更稳定的替代方案。
这将是一个不错的后续教程,目前你已经成功实现了 Home Assistant 与 Uno Q 硬件之间完全可工作的自动发现双向桥接。
这就是完整的流程,从一个空白的SSH提示符,到通过Home Assistant控制Uno Q主板上的真实硬件开关。
本文编译自hackster.io





