跳转到内容

遥测服务(树莓派 → ESP32-S3)

ESP32-S3 状态屏上显示计算模块型号、CPU 和 NVMe 温度、风扇转速、降频标志、主频和负载。这些数据由树莓派 发送:一个小 shell 脚本每 2 秒往 ESP32-S3 的 USB 串口写一行。

EGGFLY_PI_INFO model=CM5 rev=1.0 cpu=54.8 nvme=41 fan=6521 fanpwm=51 fansrc=pwmfan thr=0x0 freq=2400 load=0.52 up=1234
字段 来源
model、rev /proc/device-tree/model(CM3 / CM4 / CM4S / CM5 …)
cpu /sys/class/thermal/thermal_zone0/temp,°C
nvme 名为 nvme 的 hwmon,°C
fan、fanpwm、fansrc 转速读数最高的风扇 hwmon(没有则取第一个占空比非零的,再没有则取第一个找到的风扇):转速、占空比 %、驱动名
thr vcgencmd get_throttled 原始位——由 ESP32-S3 解码成文字
freq cpufreq scaling_cur_freq,MHz
load、up /proc/loadavg、/proc/uptime

读不到的字段直接省略。ESP32-S3 固件在它的串口命令处理函数里解析这一行。

三个文件都在镜像源码的 typixdeck-stage/09-pi-info/files/ 里:

Terminal window
[ -d ~/typixdeck-pi-gen ] || git clone --depth 1 -b typixdeck https://github.com/TypixNode/pi-gen.git ~/typixdeck-pi-gen
F=~/typixdeck-pi-gen/typixdeck-stage/09-pi-info/files
sudo install -m 755 $F/typixdeck-pi-info /usr/local/bin/
sudo install -m 644 $F/typixdeck-pi-info.service /etc/systemd/system/
sudo install -m 644 $F/99-typixdeck-esp.rules /etc/udev/rules.d/
sudo systemctl daemon-reload
sudo udevadm control --reload
sudo udevadm trigger --subsystem-match=tty --action=add
systemctl status typixdeck-pi-info

不要 systemctl enable 它——它由 udev 启动(见下文)。

它是怎么写的——以及怎么写你自己的

Section titled “它是怎么写的——以及怎么写你自己的”
/etc/udev/rules.d/99-typixdeck-esp.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="80c3", \
SYMLINK+="typixdeck-esp", TAG+="systemd", ENV{SYSTEMD_WANTS}+="typixdeck-pi-info.service"
  • 只匹配 ESP32-S3 的应用固件(303a:80c3),并给它一个固定的名字 /dev/typixdeck-esp—— 不用再猜是 ttyACM0 还是 ttyACM1。
  • SYSTEMD_WANTS 让串口一出现就启动服务。ROM 下载模式(303a:0009、303a:1001)故意不匹配。
/etc/systemd/system/typixdeck-pi-info.service
[Unit]
Description=TypixDeck: push Pi telemetry to the ESP32-S3 dashboard
BindsTo=dev-typixdeck\x2desp.device
After=dev-typixdeck\x2desp.device
[Service]
Type=simple
ExecStart=/usr/local/bin/typixdeck-pi-info /dev/typixdeck-esp
Restart=on-failure
RestartSec=3
# root is needed for /dev/vcio (vcgencmd) and the tty; lock everything else down
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_UNIX
DeviceAllow=/dev/typixdeck-esp rw
DeviceAllow=/dev/vcio rw
DeviceAllow=/dev/vchiq rw
DevicePolicy=closed
  • 系统服务,而不是用户服务:在 Lite 镜像上、在任何人登录之前都能工作。
  • BindsTo= 设备:给 ESP32-S3 刷固件时它会离开应用模式,设备消失,服务自动停止,不会和刷机工具抢串口; 固件回来后 udev 会再次启动它。
  • 没有 [Install] 段:除了 udev,不应有别的东西启动它。
  • 只有 vcgencmd(/dev/vcio)和串口需要 root 权限;那几行沙箱配置把其余权限都收掉了。

typixdeck-pi-info 是纯 bash。自己写的时候最要紧的是这几处:

Terminal window
# raw tty: no echo (the ESP's own output would come back as "commands"),
# no CR/LF translation, don't wait for carrier
stty -F "$DEV" 115200 raw -echo -echoe -echok -echoctl -echoke -onlcr -icrnl clocal || exit 1
while :; do
line="model=$MODEL"
v=$(cpu_temp); [ -n "$v" ] && line="$line cpu=$v"
# ... one field per reader, skipped when empty ...
# open/close per write: the port stays free for the flasher between lines
printf 'EGGFLY_PI_INFO %s\n' "$line" > "$DEV" || exit 1
sleep "$INTERVAL"
done
  • 先把串口设成无回显的 raw 模式,否则 ESP32-S3 自己的输出会被回显回去。
  • 每次写入时才打开串口,而不是一直占着:两行之间串口是空闲的,esptool 等工具可以用。
  • 写入出错就退出;systemd(Restart=on-failure)或 udev 会把它拉起来。
  • 按名字(/sys/class/hwmon/*/name)查找传感器,不要写死 hwmonN——编号每次开机可能不同。 有多个风扇的板子(CM5 同时有板载 EMC2301 和模块自己的四线 pwmfan)要上报真正在转的那一个。