Flash an AirGradient ONE from the Command Line

Michael Lynch

从命令行给 AirGradient ONE 刷固件

我购买了两台 AirGradient ONE 室内空气质量监测仪,用来测量家里的空气质量。AirGradient 设备是开源的,因此你可以刷入自己的自定义固件,在本地收集空气质量数据,而不必把数据发送到 AirGradient 的专有云端仪表板。

我在办公室放了一台 AirGradient ONE 空气质量监测仪,用来测量 CO2 和污染情况。

现有的刷固件文档要求你使用 Arduino IDE,一个笨重的 GUI 程序:

现有的 AirGradient ONE 刷机说明依赖于 Arduino IDE,一个笨重的 GUI 程序。

我找不到用命令行刷 AirGradient 设备的说明,花了好几个小时才摸索出来,所以我把步骤写在下面。

题外话:我不理解 AirGradient 为什么这么火

每次我在论坛讨论中看到有人提到 AirGradient,大家都对他们的产品赞不绝口。但我觉得我的 AirGradient ONE 表现平平。软件 bug 极多,文档也很匮乏。不过他们是我找到的唯一一家出售预装成品且开源的空气质量监测仪的公司,所以我又买了第二台 AirGradient 监测仪。

多年来,AirGradient 一直懒得发布给 AirGradient ONE 刷软件的说明。我是从下面这些博客文章学会怎么做的:

今年,AirGradient 终于发布了官方刷机说明,但它们仍然有点难找

环境

我在 Debian 13.0 上测试了这些步骤,但它们应该适用于任何 Debian/Ubuntu 类系统。

安装软件包

首先,我安装所需的基础软件包:

sudo apt update && \
  sudo apt install -y \
    git \
    curl \
    python3 \
    python3-serial

安装 arduino-cli

接下来,我安装 Arduino CLI 工具:

ARDUINO_CLI_VERSION='1.2.2'
ARDUINO_BIN_DIR="${HOME}/.local/arduino-cli"

mkdir -p "${ARDUINO_BIN_DIR}" && \
  curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh \
  | BINDIR="${ARDUINO_BIN_DIR}" sh -s "${ARDUINO_CLI_VERSION}"
export PATH="${PATH}:${ARDUINO_BIN_DIR}"

为了验证安装成功,我打印出 arduino-cli 的版本字符串:

$ arduino-cli version
arduino-cli  Version: 1.2.2 Commit: c11b9dd5 Date: 2025-04-22T13:51:01Z

下载 ESP32 库

AirGradient ONE 依赖 ESP32 Arduino 库。截至撰写本文时,AirGradient 尚不兼容 Arduino 的 3.x 版本,所以我必须使用最新的稳定版 2.x 版本。

ARDUINO_ESP32_VERSION='2.0.17'

arduino-cli config init \
  --additional-urls https://espressif.github.io/arduino-esp32/package_esp32_index.json && \
  arduino-cli core install "esp32:esp32@${ARDUINO_ESP32_VERSION}"

找到设备路径

接下来,我需要拿到我的 AirGradient ONE 的设备路径。查找设备路径最简单的方法是:

  1. 运行 dmesg --follow
  2. 通过 USB 把我的 AirGradient ONE 接到系统上
  3. dmesg 输出中寻找出现的设备路径

在我的系统上是这样的:

$ sudo dmesg --follow
[517021.978880] usb 1-4: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.01
[517021.978884] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[517021.978894] usb 1-4: Product: USB JTAG/serial debug unit
[517021.978896] usb 1-4: Manufacturer: Espressif
[517021.978898] usb 1-4: SerialNumber: D8:3B:DA:1A:EE:C4
[517022.017678] cdc_acm 1-4:1.0: ttyACM0: USB ACM device
                                 ^^^^^^^
                                 Path name

根据这个输出,我的系统中 AirGradient ONE 的路径是 /dev/ttyACM0

AIRGRADIENT_PATH='/dev/ttyACM0'

使设备路径可写

接下来,我确保自己能写入 AirGradient 文件路径:

sudo chmod a+rw "${AIRGRADIENT_PATH}"

现在 AirGradient 路径应该具有以下权限:

$ ls -l "${AIRGRADIENT_PATH}"
crw-rw-rw- 1 root dialout 166, 0 Aug 10 10:34 /dev/ttyACM0
 ^^^^^^^^

我还把自己加入了 dialout 组,以便能写入该路径:

sudo adduser "$(whoami)" dialout

获取 AirGradient 源代码

接下来,我查看 AirGradient 出厂刷机页面,找出最新的正式发布版本。

# Current production release, as of this writing.
AIRGRADIENT_RELEASE='3.3.8'

警告:AirGradient 网站上的最新版本与 AirGradient 的 GitHub 仓库上的最新发布标签不一致。我测试 3.3.9 时,两台设备都无法测量 CO2 和温度,所以我不确定 3.3.9 是否是一个已知有 bug 的版本。

拿到版本号后,我从 AirGradient 的 GitHub 仓库获取源代码:

git clone --recurse-submodules \
  --branch "${AIRGRADIENT_RELEASE}" \
  --depth 1 \
  https://github.com/airgradienthq/arduino.git \
  ~/airgradient-one

把固件刷入 AirGradient ONE 设备

最后,是时候把软件刷入我的设备了:

cd ~/airgradient-one && \
  arduino-cli compile \
    --verbose \
    --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc,PartitionScheme=min_spiffs,DebugLevel=info \
    --library . \
    --port "${AIRGRADIENT_PATH}" \
    --verify \
    --upload \
    examples/OneOpenAir/OneOpenAir.ino

注意:要擦除 AirGradient ONE 设备上的持久化数据(即硬重置,包括配置数据),请在 --fqbn 参数末尾加上 ,EraseFlash=all

如果刷机成功,我会看到设备重启,并且过程结束时出现如下输出:

Wrote 1753792 bytes (967231 compressed) at 0x00010000 in 14.7 seconds (effective 952.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

可选:查看串口日志输出

当我的 AirGradient 连接到电脑时,我可以使用 arduino-cli monitor 命令通过串口查看它的日志输出:

$ arduino-cli monitor --port "${AIRGRADIENT_PATH}"
Using default monitor configuration for board: esp32:esp32:heltec_wifi_kit_32_V3
Monitor port settings:
  baudrate=9600
  bits=8
  dtr=on
  parity=none
  rts=on
  stop_bits=1

Connecting to /dev/ttyACM0. Press CTRL-C to exit.
[1] Standard Particle PM 2.5 = 7.00 ug/m3
[1] Particle Count 0.3 = 1298.5
[1] Particle Count 0.5 = 383.5
[1] Particle Count 1.0 = 39.7
[1] Particle Count 2.5 = 2.0
[1] Particle Count 5.0 = 2.0
[1] Particle Count 10 = 0.0

替代方案:Nix flake

如果你是个 Nix 发烧友,可能想用 Nix 的方式来做这件事。我创建了一个 Nix flake 来自动化上述所有步骤:

当我想刷入我的仓库时,只需运行:

nix run .#flash

当我想查看串口输出时,运行:

nix run .#monitor

我不确定我的 Nix flake 在不同系统上的表现如何,所以你可能需要稍微折腾一下才能让它在你自己的系统上跑起来。

结语

希望这些说明能让你更轻松地给自己的 AirGradient ONE 刷固件,并随心所欲地自定义固件。

原文由 Michael Lynch 发布

本文章由 stealth/ox-alpha 进行翻译