Telemetry service (Pi → ESP32-S3)
The ESP32-S3 status screen shows the compute module model, CPU and NVMe temperature, fan speed, throttling flags, clock and load. The Pi sends them: a small shell script writes one line every 2 seconds to the ESP32-S3’s USB serial port.
The protocol
Section titled “The protocol”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| Field | Source |
|---|---|
model, rev |
/proc/device-tree/model (CM3 / CM4 / CM4S / CM5 …) |
cpu |
/sys/class/thermal/thermal_zone0/temp, °C |
nvme |
hwmon named nvme, °C |
fan, fanpwm, fansrc |
the fan hwmon with the highest tacho reading (else the first with a non-zero duty, else the first fan found): RPM, duty %, driver name |
thr |
vcgencmd get_throttled raw bits - the ESP32-S3 decodes them into words |
freq |
cpufreq scaling_cur_freq, MHz |
load, up |
/proc/loadavg, /proc/uptime |
Fields that cannot be read are simply left out. The ESP32-S3 firmware parses the line in its serial-command handler.
Install on stock Raspberry Pi OS
Section titled “Install on stock Raspberry Pi OS”The three files are in the image sources,
typixdeck-stage/09-pi-info/files/:
[ -d ~/typixdeck-pi-gen ] || git clone --depth 1 -b typixdeck https://github.com/TypixNode/pi-gen.git ~/typixdeck-pi-genF=~/typixdeck-pi-gen/typixdeck-stage/09-pi-info/filessudo 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-reloadsudo udevadm control --reloadsudo udevadm trigger --subsystem-match=tty --action=addsystemctl status typixdeck-pi-infoDo not systemctl enable it - udev starts it (see below).
How it is built - and how to write your own
Section titled “How it is built - and how to write your own”1. udev starts it when the ESP32-S3 appears
Section titled “1. udev starts it when the ESP32-S3 appears”SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="80c3", \ SYMLINK+="typixdeck-esp", TAG+="systemd", ENV{SYSTEMD_WANTS}+="typixdeck-pi-info.service"- Matches only the ESP32-S3 application firmware (
303a:80c3) and gives it a stable name,/dev/typixdeck-esp- no guessing betweenttyACM0andttyACM1. SYSTEMD_WANTSstarts the service the moment the port appears. The ROM download modes (303a:0009,303a:1001) deliberately do not match.
2. A system unit bound to the device
Section titled “2. A system unit bound to the device”[Unit]Description=TypixDeck: push Pi telemetry to the ESP32-S3 dashboardBindsTo=dev-typixdeck\x2desp.deviceAfter=dev-typixdeck\x2desp.device
[Service]Type=simpleExecStart=/usr/local/bin/typixdeck-pi-info /dev/typixdeck-espRestart=on-failureRestartSec=3# root is needed for /dev/vcio (vcgencmd) and the tty; lock everything else downNoNewPrivileges=yesProtectSystem=strictProtectHome=yesPrivateTmp=yesProtectKernelModules=yesProtectControlGroups=yesRestrictAddressFamilies=AF_UNIXDeviceAllow=/dev/typixdeck-esp rwDeviceAllow=/dev/vcio rwDeviceAllow=/dev/vchiq rwDevicePolicy=closed- System unit, not a user unit: it works on Lite images and before anyone logs in.
BindsTo=the device: when the ESP32-S3 is being reflashed it leaves the application mode, the device disappears and the service stops by itself, so it never fights the flasher for the serial port. When the firmware comes back, udev starts it again.- No
[Install]section: nothing but udev should start it. - It needs root only for
vcgencmd(/dev/vcio) and the tty; the sandboxing lines take everything else away.
3. The script
Section titled “3. The script”typixdeck-pi-info
is plain bash. The parts that matter if you write your own:
# raw tty: no echo (the ESP's own output would come back as "commands"),# no CR/LF translation, don't wait for carrierstty -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- Put the port in raw mode without echo first, or the ESP32-S3’s own output is echoed back to it.
- Open the port for each write instead of holding it: between lines it is free for
esptoolor other tools. - Exit on a write error; systemd (
Restart=on-failure) or udev brings it back. - Look sensors up by name (
/sys/class/hwmon/*/name), never byhwmonN- the numbers change between boots. On boards that expose several fans (a CM5 has both the board’s EMC2301 and its own 4-pinpwmfan), report the one that is actually spinning.