跳到內容

遙測服務(樹莓派 → 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)要上報真正在轉的那一個。