3 Commits

Author SHA1 Message Date
Adolfo Reyna e010828e5e docs(agents): use reyna-cli for Tactility board discovery & management
Main / Build (AudioTest) (push) Has been cancelled
Main / Build (BibleVerse) (push) Has been cancelled
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (EspNowBridge) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GameBoy) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (McpScreen) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (Mp3Player) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (PocketDungeon) (push) Has been cancelled
Main / Build (ReynaBot) (push) Has been cancelled
Main / Build (RobotArm) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Build (VoiceRecorder) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
Main / PublishApps (push) Has been cancelled
Prefer reyna-cli (registry-addressed by device ID) over raw IPs/curl for the
Tactility LAN fleet. Document board ID->IP map (kidosos_* boards, esp32_screen,
little32), discover/devices/sysinfo/apps/install/run/report commands, and the
USB serial monitor for capturing ELF missing-symbol logs.
2026-08-19 21:28:02 -04:00
Adolfo Reyna 479a448900 docs(tactility-app-dev): note device_get_* not exported; use device_find_* legacy API
Main / Build (AudioTest) (push) Has been cancelled
Main / Build (BibleVerse) (push) Has been cancelled
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (EspNowBridge) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GameBoy) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (McpScreen) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (Mp3Player) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (PocketDungeon) (push) Has been cancelled
Main / Build (ReynaBot) (push) Has been cancelled
Main / Build (RobotArm) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Build (VoiceRecorder) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
Main / PublishApps (push) Has been cancelled
Flashed 0.8.0-dev firmware exports device_find_* but not the newer device_get_*
out-param API. verify_symbols.py compares vs local firmware source and can pass
even when the flashed firmware differs — confirm on-device via serial
(/dev/cu.usbmodem*, 115200). Record the local extern-declare workaround.
2026-08-19 21:19:28 -04:00
Adolfo Reyna f785bd3fb2 fix(bookplayer): use exported device_find_* API for audio stream lookup
Main / Build (AudioTest) (push) Has been cancelled
Main / Build (BibleVerse) (push) Has been cancelled
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (EspNowBridge) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GameBoy) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (McpScreen) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (Mp3Player) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (PocketDungeon) (push) Has been cancelled
Main / Build (ReynaBot) (push) Has been cancelled
Main / Build (RobotArm) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Build (VoiceRecorder) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
Main / PublishApps (push) Has been cancelled
The flashed 0.8.0-dev firmware exports the legacy device_find_by_name /
device_find_first_by_type lookup API, not the newer device_get_* out-param
API. Switching to device_get_* (to match newer SDK headers) caused
'ELF: Can't find symbol device_get_by_name' at load on .129/.114. Revert to
the exported legacy functions, declared locally since the newer SDK header
dropped them. Verified on .129 via serial: elf entry resolves, app shows.
2026-08-19 21:18:14 -04:00
3 changed files with 55 additions and 4 deletions
@@ -39,6 +39,12 @@ print(f"undef {len(undef)} missing {missing}")
### New missing from v2/v3/v4/v5 UI passes
- `device_get_by_name`, `device_get_first_by_type` (out-param API) → **Not exported** on flashed 0.8.0-dev (verified via serial on .129: `E ELF: Can't find symbol device_get_by_name`). The firmware exports the **legacy** `device_find_by_name` / `device_find_first_by_type` instead. Gotcha: newer SDK/CDN headers declare only `device_get_*` (so `device_find_*` fails to compile), but the flashed firmware only exports `device_find_*` (so `device_get_*` fails at load). Fix: call the exported legacy `device_find_*` and declare them locally in the app source since the SDK header dropped them:
```c
extern struct Device* device_find_by_name(const char* name);
extern struct Device* device_find_first_by_type(const struct DeviceType* type);
```
Verify the ACTUAL load on-device via serial (`/dev/cu.usbmodem*`, 115200) — `verify_symbols.py` compares against local firmware source and can report 0 missing even when the flashed firmware's export table differs.
- `lv_obj_set_style_bg_grad_color/dir/stop` → **Not exported** 0.8.0-dev. Gradient fails `missing symbol`. Use solid `0x0E0E14`.
- `LV_OPA_95` → **Not defined** (only 0/10/20/30/40/50/60/70/80/90/100/COVER/TRANSP). Use `COVER` or `90`.
- `lv_arc_create`, `lv_arc_set_range/value/bg_angles`, `lv_arc_get_value` → **Not exported on 0.7.0-dev**, added `dff93cb6 Add lv_arc.h symbols (#496)` after 0.7 release. Symptom blue modal `Error / Application failed to start: missing symbol / OK`, heap healthy ~31KB not OOM. Fix horizontal slide using `lv_slider_create` + `lv_indev_get_point/active`. See `book-browser.md`.
+37
View File
@@ -69,6 +69,7 @@ xtensa-esp32s3-elf-nm -D Apps/MyApp/build/cmake-build-esp32s3/MyApp.app.elf | gr
python .claude/skills/tactility-app-development/scripts/verify_symbols.py Apps/MyApp
# Install to device (dashboard API port 80, not dev port 6666)
# Preferred: use reyna-cli (see "Device discovery & management via reyna-cli" below)
$IDF_PYTHON_ENV_PATH/bin/python tactility.py Apps/MyApp install 192.168.68.112 esp32s3
# or dashboard directly:
curl -X PUT http://192.168.68.112/api/apps/install -F "file=@build/MyApp.app"
@@ -83,6 +84,41 @@ curl http://192.168.68.112/api/apps # list installed
# If 6666 refused → use dashboard PUT above
```
### Device discovery & management via reyna-cli
`reyna-cli` (at `/Users/adolforeyna/.local/bin/reyna-cli`) wraps the Tactility LAN web API with a device registry
(`~/.hermes/local_devices.yaml`). Prefer it over raw IPs/curl for fleet discovery and management. Boards are
addressed by their stable registry **ID** (not IP — DHCP IPs change); `devices list` maps IDs→IPs.
Registered Tactility boards (from `reyna-cli devices list`):
| ID | IP | Board |
|----|----|-------|
| `kidosos_a790` | `.129` | Personal 3.5-inch Tactility Board (Dev) — USB `/dev/cu.usbmodem*` for serial |
| `kidosos_5c5c` | `.114` | Grace's 2.8-inch board |
| `kidosos_5690` | `.107` | Elias's 2.8-inch board |
| `kidosos_591c` | `.128` | Kitchen 2.8-inch board |
| `esp32_screen` | `.123` | ESP32 Screen |
| `little32` | `.122` | Little32 Kitchen ESP32 Screen |
Commands:
```bash
reyna-cli tactility discover # probe all boards; online/offline + sysinfo
reyna-cli devices list # registry (id, ip, display name, status)
reyna-cli tactility sysinfo kidsos_a790 # firmware/version/heap/psram/SD
reyna-cli tactility apps kidsos_a790 # installed apps
reyna-cli tactility install kidsos_5c5c build/MyApp.app # PUT install by device id
reyna-cli tactility run kidsos_5c5c one.tactility.myapp # launch app
reyna-cli tactility report kidsos_a790 # apps + SD + bible/podcast usage
# most commands accept --json for machine-readable output
```
Use a serial monitor on the USB board for loader/ELF diagnostics: `/dev/cu.usbmodem*` @ 115200
(e.g. `idf5.5_py3.9_env/bin/python -m serial.tools.miniterm /dev/cu.usbmodem31201 115200`). This is how you
capture `E ELF: Can't find symbol X` on `.129` — `verify_symbols.py` only compares against local firmware
SOURCE and can pass even when the flashed firmware's export table differs.
### manifest.properties
```properties
@@ -121,6 +157,7 @@ Keep app source as pure C (no `auto`, no lambdas in `.c`) or rename to `.cpp`.
Tactility firmware exports symbols via `ESP_ELFSYM_EXPORT` / `DEFINE_MODULE_SYMBOL` in `firmware/Modules/lvgl-module/source/symbols.c`. If ELF references an unexported symbol → device modal `Error / Application failed to start: missing symbol`, heap still healthy (~31KB free) → NOT OOM.
Known missing on 0.8.0-dev:
- `device_get_by_name` / `device_get_first_by_type` (out-param API) → **Not exported** by flashed firmware; use legacy exported `device_find_by_name` / `device_find_first_by_type` (declare them locally — newer SDK headers dropped them). Gotcha: `verify_symbols.py` compares vs local firmware SOURCE and can pass even when the flashed firmware's export table differs — confirm on-device via serial (`/dev/cu.usbmodem*`, 115200): `E ELF: Can't find symbol X`.
- `lv_font_montserrat_14/18` → use `lvgl_get_text_font(SMALL/DEFAULT/LARGE)` via `tactility/lvgl_fonts.h`
- `lv_obj_set_style_bg_grad_color/dir/stop`, `LV_OPA_95/5`, `LV_SYMBOL_STAR` → use solid colors, COVER/90
- `lv_obj_set_style_max_width` → use `LV_PCT(92)` fixed percents for gutters
+12 -4
View File
@@ -125,14 +125,22 @@ static void play_wav(AppCtx* ctx);
static void scan_books(AppCtx* ctx);
/* ─── Audio-stream helpers ─── */
// The flashed firmware exports the legacy device_find_* lookup API; the newer
// device_get_* (out-param) API is not yet exported on 0.8.0-dev, so calling it
// fails at load with "missing symbol". The newer SDK headers dropped the legacy
// declarations, so declare them here (symbols are resolved at runtime by the ELF
// loader against the flashed firmware).
extern struct Device* device_find_by_name(const char* name);
extern struct Device* device_find_first_by_type(const struct DeviceType* type);
static bool find_audio_stream_device(AppCtx* ctx) {
struct Device* dev = NULL;
if (device_get_by_name("audio-stream", &dev) == ERROR_NONE && dev) {
struct Device* dev = device_find_by_name("audio-stream");
if (dev) {
ctx->stream_dev = dev;
return true;
}
dev = NULL;
if (device_get_first_by_type(&AUDIO_STREAM_TYPE, &dev) == ERROR_NONE && dev) {
dev = device_find_first_by_type(&AUDIO_STREAM_TYPE);
if (dev) {
ctx->stream_dev = dev;
return true;
}