Files
trail-mate/apps/linux_cardputer_zero/README.md
T

389 lines
17 KiB
Markdown

# Cardputer Zero Linux App Shell
This app shell is the Trail Mate product route for the Cardputer Zero portable
Linux device. It is not the Linux simulator.
The first slice intentionally keeps the runtime entry small: the shell validates
the `cardputerzero` target profile, consumes the `boards/cardputerzero` facts,
selects the `cardputer_compact` UX pack, and builds through
`builds/linux_cmake`. The device package now owns a Wayland APPLaunch product
entry and a separate explicit fbdev/evdev debug fallback; hardware validation
still has to happen on the real device session.
The shared LVGL main-menu profile for this target is already Cardputer Zero
specific and Pager-derived: `make_cardputer_zero_profile()` starts from
`make_pager_profile()` and then shrinks geometry for the 320 x 170 display.
The remaining UI work is page-by-page Cardputer Zero closure from that visual
baseline, not a Linux-simulator or custom Linux-panel redesign.
Known hardware facts in this repo:
- display: 320 x 170 logical pixels
- input: built-in keyboard
- touch, pointer, and trackball: absent in current board facts
- external module: M5Stack Cap LoRa-1262, completing both LoRa and GPS/GNSS
capability for this target
- LoRa: SX1262 on `/dev/spidev0.1`, 500000 Hz, Reset=26, IRQ/DIO1=23,
Busy=22, DIO2 RF switch and DIO3 TCXO enabled
- GPS/GNSS: ATGM336H-6N@AT6668 on the Cap LoRa-1262 UART, NMEA 0183 4.1,
default 115200 bps, with Cardputer Zero wiring `G15=GPS_RX` and
`G14=GPS_TX`
- The `G15`/`G14` mapping is Cardputer Zero evidence and must not be inferred
from the Cardputer-Adv `G13`/`G15` table.
Known Cardputer Zero Linux session facts in this shell:
- notifications are created through the standard
`org.freedesktop.Notifications` D-Bus interface; the
`$XDG_RUNTIME_DIR/cardputer-zero/notifyd.sock` channel is status/control only
- text entry uses Fcitx5 through the normal Linux toolkit/frontend path
- the Cardputer Zero IME addon/panel pair uses
`$XDG_RUNTIME_DIR/cardputer-zero/ime-panel.sock` only to display preedit,
candidates, and input-method state
- Trail Mate does not own the notification daemon implementation, Fcitx5 UI
addon, IME panel renderer, input method engine, dictionaries, or text commit
path
- the shared embedded touch/pinyin IME is not the Cardputer Zero Linux input
method strategy
- Cardputer Zero business pages are wired through runtime/presentation ports;
this target opts out of legacy chat-delivery and legacy presentation source
compilation, and the Linux CMake helper withholds the legacy-adapter include
root for this target, so `Legacy*` compatibility adapters cannot become the
new product path
- Trail Mate must use its own Linux raw LoRa and GPS runtime paths for the Cap
LoRa-1262; the external Meshtastic daemon package is hardware-reference
evidence only, not the implementation owner
The simulator remains a separate development shell under `apps/linux_sim_shell`.
## Device Launch And Debian Package
The package route builds the real Cardputer Zero shell, not the screenshot tool
and not the simulator:
```bash
cd builds/linux_cmake
cmake --preset linux-cardputer-zero-release
cmake --build --preset linux-cardputer-zero-deb
```
On Windows/WSL, build from the helper instead so the package staging tree lives
on a Linux filesystem and does not inherit `/mnt/c` executable-bit pollution:
```bash
bash apps/linux_cardputer_zero/tools/build_cardputer_zero_deb.sh
```
The resulting package is written under `build/cardputer-zero-deb/`. The helper
builds through the Cardputer Zero Docker Compose builder, producing an actual
Docker `linux/arm64` Debian package while keeping build artifacts out of the
repository root. The first run builds the reusable
`trailmate-cardputer-zero-builder:bookworm-arm64` image and installs Debian
build dependencies into that image layer. Later package builds reuse the image
and the compose-owned CMake build volume, so they should not repeat `apt-get
install` unless the builder image is rebuilt, the APT mirror argument changes,
or the Docker cache is cleared.
The package helper still creates a filtered source snapshot under
`/tmp/trailmate-cardputer-zero-package`, excluding local object files, root
CMake state, and existing package outputs before copying that snapshot into the
builder container. This keeps Windows/WSL executable-bit behavior and accidental
root build artifacts out of the `.deb`.
The container package entrypoint validates package version `0.1.29-alpha`,
architecture, required runtime dependencies, APPLaunch paths, executable
permissions, AArch64 ELF metadata, and `ldd` resolution before copying the
`.deb` into `build/cardputer-zero-deb/`.
If Docker's Debian mirror path is unstable, override the builder image APT
mirror with `TRAIL_MATE_CARDPUTER_ZERO_APT_MIRROR`. The value should be the
Debian archive root, for example:
```bash
TRAIL_MATE_CARDPUTER_ZERO_APT_MIRROR=http://mirrors.tuna.tsinghua.edu.cn/debian \
bash apps/linux_cardputer_zero/tools/build_cardputer_zero_deb.sh
```
Using an HTTP Debian mirror here avoids the base container's pre-bootstrap
certificate gap; package integrity still comes from APT's signed repository
metadata.
To force dependency refresh after changing mirrors or base images, remove or
rebuild the builder image:
```bash
TRAIL_MATE_CARDPUTER_ZERO_APT_MIRROR=http://mirrors.tuna.tsinghua.edu.cn/debian \
docker compose \
-f apps/linux_cardputer_zero/tools/compose.cardputer-zero-builder.yml \
-p trailmate-cardputer-zero-package \
build --no-cache deb-builder
```
The package installs the Cardputer Zero APPLaunch layout:
- `/usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero`
- `/usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero-fbdev`
- `/usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero-applaunch`
- `/usr/share/APPLaunch/applications/trailmate.desktop`
- `/usr/share/APPLaunch/share/images/trailmate-cardputer-zero.png`
The default APPLaunch path is Wayland. In `auto` mode the wrapper starts
`trailmate-cardputer-zero` only when `WAYLAND_DISPLAY` is present, and exits
with a diagnostic instead of silently falling back to framebuffer when no
Wayland session exists. The fbdev binary is reached only by setting
`TRAIL_MATE_DISPLAY_BACKEND=fbdev` or another explicit framebuffer alias; that
debug path honors `APPLAUNCH_LINUX_FBDEV_DEVICE` and
`APPLAUNCH_LINUX_KEYBOARD_DEVICE`, detects the ST7789V framebuffer from
`/proc/fb`, and falls back to `/dev/fb1` plus the documented Cardputer Zero
keyboard by-path event device. Set `TRAIL_MATE_FRAMEBUFFER=/dev/fbN` or
`TRAIL_MATE_INPUT_DEVICE=/dev/input/eventN` only for manual framebuffer
debugging outside the product Wayland session.
The APPLaunch wrapper also owns the Cardputer Zero Cap LoRa-1262 runtime
defaults. Unless explicitly overridden by the environment, it launches in real
mesh mode with:
- `TRAIL_MATE_RUNTIME_MODE=mesh`
- `TRAIL_MATE_LORA_SPI=/dev/spidev0.1`
- `TRAIL_MATE_LORA_GPIOCHIP=/dev/gpiochip0`
- `TRAIL_MATE_LORA_RESET_GPIO=26`
- `TRAIL_MATE_LORA_BUSY_GPIO=22`
- `TRAIL_MATE_LORA_IRQ_GPIO=23`
- `TRAIL_MATE_LORA_SPI_HZ=500000`
- `TRAIL_MATE_LORA_DIO2_RF_SWITCH=1`
- `TRAIL_MATE_LORA_DIO3_TCXO_1V8=1`
- `TRAIL_MATE_GPS_BAUD=115200`
- `TRAIL_MATE_GPS_AUTO_SERIAL=1`
- `TRAIL_MATE_GPS_DEVICE_CANDIDATES=/dev/serial0:/dev/ttyAMA1:/dev/ttyAMA0:/dev/ttyS0:/dev/ttyS1`
- `TRAIL_MATE_DESKTOP_NOTIFICATIONS=freedesktop`
`TRAIL_MATE_GPS_DEVICE` is reserved for an explicit user override. When it is
unset, the resident GPS service probes `TRAIL_MATE_GPS_DEVICE_CANDIDATES` and
fails over to the next existing candidate when a serial endpoint opens but no
NMEA bytes arrive. Serial aliases are de-duplicated after path canonicalization,
so `/dev/serial0` and its `/dev/tty*` target do not create a false failover
loop. The app launcher therefore publishes candidates rather than hard-selecting
`/dev/serial0`.
GPS and LoRa are resident services in this product shell. The app service loop
ticks the Cap LoRa-1262 radio path and the GPS serial/NMEA path even when the
Chat, Contacts, Map, or Sky Plot page is not currently open. Pages consume
runtime state and send commands; they do not own radio polling or GPS serial
reads.
Cardputer Zero Settings follows the same ownership boundary. Trail Mate exposes
application settings that its runtime can apply. Linux session brightness and
screen timeout belong to the operating system or desktop environment and are
therefore not shown in the application Settings page. For GPS, the Linux runtime
currently exposes the GPS enable switch, receiver baud selection, and
diagnostics; ESP-only receiver initialization policy items are not shown on
Cardputer Zero until the Linux runtime owns real receiver-command behavior for
them.
## LoRa And GPS Hardware Checks
Install the package on Cardputer Zero:
```bash
sudo apt install ./trailmate-cardputer-zero_0.1.29-alpha_arm64.deb
```
Check the installed package metadata and APPLaunch entry:
```bash
dpkg -s trailmate-cardputer-zero | sed -n '/^Package:/,/^Description:/p'
dpkg -L trailmate-cardputer-zero
sed -n '1,140p' /usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero-applaunch
cat /usr/share/APPLaunch/applications/trailmate.desktop
```
Before starting Trail Mate, confirm the hardware nodes exist:
```bash
ls -l /dev/spidev0.1 /dev/gpiochip0
ls -l /dev/serial0 /dev/ttyAMA1 /dev/ttyAMA0 /dev/ttyS0 /dev/ttyS1 2>/dev/null || true
cat /proc/cmdline | tr ' ' '\n' | grep '^console=' || true
pinctrl get 14
pinctrl get 15
systemctl status serial-getty@ttyS0.service --no-pager || true
```
If `/dev/spidev0.1` is missing, LoRa cannot be brought up by Trail Mate. If all
serial paths are missing, GPS cannot be read by Trail Mate.
`console=ttyS0,115200` or `console=serial0,115200` means the OS is still using
the GPS UART as a serial console. That belongs in the Cardputer Zero OS profile,
not the Trail Mate package. Re-run the OS profile installer or manually remove
those console tokens, then reboot.
To watch the app launch logs directly from a terminal:
```bash
WAYLAND_DISPLAY=${WAYLAND_DISPLAY:-wayland-0} \
/usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero-applaunch \
2>&1 | tee /tmp/trailmate-cardputer-zero.log
```
The product path requires Wayland. For explicit framebuffer debugging only:
```bash
TRAIL_MATE_DISPLAY_BACKEND=fbdev \
/usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero-applaunch \
2>&1 | tee /tmp/trailmate-cardputer-zero-fbdev.log
```
Runtime packet logs are written under the Trail Mate settings root. By default
that is `$HOME/.trailmate_cardputer_zero/logs/`. If `TRAIL_MATE_SETTINGS_ROOT`
is set, use that root instead.
Watch LoRa packet logs:
```bash
tail -F "${TRAIL_MATE_SETTINGS_ROOT:-$HOME/.trailmate_cardputer_zero}/logs/lora.log"
```
Useful LoRa signs:
- `LoRa raw TX`, `Meshtastic raw TX`, or protocol-specific TX lines mean the
app attempted radio transmission.
- `LoRa raw RX`, `Meshtastic raw RX`, or protocol-specific RX lines mean the
SX1262 delivered received bytes to Trail Mate.
- `LoRa radio degraded`, `SX1262 endpoint present; driver not online`,
`open spidev failed`, `configure spidev failed`, or `probe failed` mean the
runtime found the candidate path but could not bind or configure the radio.
- No `lora.log` after the app has been running for a few seconds usually means
either `TRAIL_MATE_RUNTIME_MODE` is not `mesh`, `/dev/spidev0.1` is absent,
or the app did not enter the Linux service loop.
Trigger a useful LoRa check from the UI by opening Contacts and running local
scan/discovery, then watch `lora.log` for TX/RX entries. Another node nearby
should cause RX entries when it broadcasts or replies.
Watch GPS/NMEA packet logs:
```bash
tail -F "${TRAIL_MATE_SETTINGS_ROOT:-$HOME/.trailmate_cardputer_zero}/logs/gps.log"
```
Useful GPS signs:
- `GPS source opened` means Trail Mate opened the selected serial source and
configured its baud rate.
- `GPS source open failed` means the selected source path exists in config but
could not be opened; check permissions, the `dialout` group, and the selected
`/dev/tty*` path.
- `GPS serial waiting for NMEA` means the serial source is open but Trail Mate
has not yet parsed a complete NMEA sentence.
- `GPS serial no traffic` means the currently opened auto-probed source
produced no bytes within the failover window; Trail Mate will try the next
candidate and log `next_path`.
- `NMEA sentence parsed` means Trail Mate read a complete NMEA sentence and its
checksum was valid.
- `NMEA checksum failed` means UART bytes are arriving, but data integrity,
baud rate, or wiring should be checked.
- No `gps.log` after the app has been running for a few seconds usually means
the app has not reached the Linux service loop, GPS was disabled in Settings,
every configured/auto-probed serial path is absent, or
`TRAIL_MATE_SETTINGS_ROOT` points somewhere else. The Cardputer Zero GPS
service runs independently of the Sky Plot or Map page being open.
Quick raw GPS byte check:
```bash
for dev in /dev/serial0 /dev/ttyAMA1 /dev/ttyAMA0 /dev/ttyS0 /dev/ttyS1; do
[ -e "$dev" ] || continue
echo "===== $dev ====="
sudo stty -F "$dev" 115200 raw -echo -ixon -ixoff -crtscts 2>&1 || true
timeout 8s sh -c "cat '$dev' | head -c 500" | od -An -tx1 -c
done
```
Healthy output contains `$GNGGA`, `$GNRMC`,
`$GPGSV`, `$GLGSV`, `$GAGSV`, or `$BDGSV` style NMEA sentences. A no-fix GPS
can still be healthy; the key first signal is valid NMEA traffic, then later
`FIX`/satellite values on the Sky Plot page.
Map tile diagnostics:
```bash
tail -F "${TRAIL_MATE_SETTINGS_ROOT:-$HOME/.trailmate_cardputer_zero}/logs/map.log"
find "${TRAIL_MATE_SD_ROOT:-$HOME/.trailmate_cardputer_zero/sd}/maps/base" -type f | head
sqlite3 "${TRAIL_MATE_SETTINGS_ROOT:-$HOME/.trailmate_cardputer_zero}/trailmate.sqlite" \
"select source,z,x,y,status,http_status,bytes,last_error from map_tile_cache order by fetched_at desc limit 20;"
```
If `map.log` shows queued tiles followed by download failures, the Map page has
already handed the request to the Linux tile runtime. Check the network path
from the device itself:
```bash
getent ahosts tile.openstreetmap.org
curl -I -L --connect-timeout 5 https://tile.openstreetmap.org/7/100/54.png
```
Linux tile downloads use the system resolver by default. DoH is opt-in through
`TRAIL_MATE_MAP_DOH_URL` or `TRAIL_MATE_CURL_DOH_URL`; set one of them only
when that resolver is reachable from the device network. If a network prefers a
specific IP family, set `TRAIL_MATE_MAP_IP_RESOLVE=ipv4` or
`TRAIL_MATE_MAP_IP_RESOLVE=ipv6`. If the default public tile endpoint is not
reachable from the device network, configure a reachable template such as
`TRAIL_MATE_OSM_TILE_URL`.
When a local mixed HTTP proxy is already listening on `127.0.0.1:7890`, the
Cardputer Zero APPLaunch wrapper exports the standard curl proxy variables for
Trail Mate. Explicit proxy variables supplied by the session are preserved.
Check the Cardputer Zero notification path:
```bash
notify-send "Trail Mate" "Notification daemon is working"
busctl --user call org.freedesktop.Notifications \
/org/freedesktop/Notifications \
org.freedesktop.Notifications GetServerInformation
journalctl --user -u cardputer-zero-notifyd -f
```
Incoming Trail Mate chat messages call the same freedesktop notification
interface when `TRAIL_MATE_DESKTOP_NOTIFICATIONS=freedesktop`. The
`$XDG_RUNTIME_DIR/cardputer-zero/notifyd.sock` channel remains status/control
only and is not used to create notifications.
This is a CPack device-install package. It intentionally does not claim the
full LoFiBox-Zero Debian source-package flow yet: there is no `debian/`
directory, no `dpkg-buildpackage` source package, no lintian/autopkgtest gate,
and no signed APT publication path for `amd64`/`arm64`. Those belong to a later
packaging-governance slice if Cardputer Zero needs LoFiBox-style preview APT
distribution.
## Screenshot Evidence
The current shared LVGL Cardputer compact route has screenshot evidence for the
ten Cardputer Zero product pages. PC Link, SSTV, Energy Sweep / Spectrum, and
SD Storage / USB Disk are intentionally excluded from this product menu. SD
Storage is the card-access/USB mass-storage entry, not Extensions.
```powershell
$targets = @(
'dashboard',
'chat',
'contacts',
'map',
'sky_plot',
'team',
'tracker',
'walkie',
'extensions',
'settings'
)
wsl bash -lc 'cd /mnt/c/Users/VicLi/Documents/Projects/trail-mate && rm -f docs/images/cardputerzero/screenshots/*.png'
foreach ($target in $targets) {
wsl bash -lc "cd /mnt/c/Users/VicLi/Documents/Projects/trail-mate && timeout 40s env TRAIL_MATE_LORA_DISABLE=1 builds/linux_cmake/build/linux-cardputer-zero-debug/apps/linux_cardputer_zero/trailmate_linux_cardputer_zero_screenshot_capture /mnt/c/Users/VicLi/Documents/Projects/trail-mate/docs/images/cardputerzero/screenshots $target"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
```
See `docs/targets/cardputerzero-screenshots.md` for the screenshot matrix,
including the Map page's compact zoom, center, base-layer, and contour controls,
and `docs/targets/cardputerzero-adaptation.md` for the current validation state
and remaining hardware/session closure.