diff --git a/DEVICES.md b/DEVICES.md index 2b75e334..a863ef68 100644 --- a/DEVICES.md +++ b/DEVICES.md @@ -13,9 +13,9 @@ USB) and the [GitHub releases](https://github.com/ALLFATHER-BV/wadamesh/releases | Tanmatsu | ESP32-P4 + ESP32-C6, SX1262 | 4" 800x480, 69-key keyboard (no touch) | Tanmatsu app store on the device (runs under the badge.team launcher, not web-flashable) | Store tracks the test channel | Fully supported; LoRa + Wi-Fi + Bluetooth simultaneously, standalone and companion in one | | Elecrow ThinkNode M9 | ESP32-S3, LR1110 | 2.4" 240x320 (no touch), I2C QWERTY + d-pad | Web flasher | Beta (new in beta_38) | Hardware-complete community port by ded (#138): GPS, microSD, buzzer, lock screen, d-pad navigation | | RAK WisMesh Tap V2 (RAK3312) | ESP32-S3, SX1262 | Touch display (LovyanGFX, 30+ fps) | Web flasher | Beta (new in beta_38) | Early community port by Ethac.chen (#136); core mesh, chat and map working | -| LilyGo T-Lora Pager | ESP32-S3, LR1121 or SX1262 | 2.33" AMOLED (no touch), QWERTY + rotary encoder | Web flasher (pick the build matching your radio) | Stable | Fully supported; keyboard-first navigation, microSD, map tile packs | -| Heltec V4-R8 + Expansion Kit V2 | ESP32-S3 (8 MB octal PSRAM), SX1262 | 2.4" touch (CHSC6x) | Web flasher | Stable | As the V4 plus microSD and the Expansion Kit sensors; buzzer supported | -| LilyGo T-Display P4 | ESP32-P4 + ESP32-C6, SX1262 | AMOLED or TFT-LCD, touch | Web flasher (AMOLED) or the .bin for the LCD SKU | Stable | Two screen SKUs; fuel-gauge battery reporting, full TX power | +| LilyGo T-Lora Pager | ESP32-S3, LR1121 or SX1262 | 2.33" IPS LCD, 480x222 (no touch), QWERTY + rotary encoder | Web flasher (pick the build matching your radio) | Beta (new in beta_45) | Fully supported; keyboard-first navigation, microSD, map tile packs | +| Heltec V4-R8 + Expansion Kit V2 | ESP32-S3 (8 MB octal PSRAM), SX1262 | 2.4" touch (CHSC6x) | Web flasher | Beta (new in beta_45) | As the V4 plus microSD and the Expansion Kit sensors; buzzer supported | +| LilyGo T-Display P4 | ESP32-P4 + ESP32-C6, SX1262 | AMOLED or TFT-LCD, touch | Web flasher (AMOLED) or the .bin for the LCD SKU | Beta (new in beta_45) | Two screen SKUs; fuel-gauge battery reporting, full TX power | | Attaky Mesh Series | ESP32-S3, SX1262 | Touch display | Web flasher | Beta (new in beta_47) | Community port by attakygit (#158/#169); detachable keyboard supported | ## Feature notes per board @@ -30,6 +30,15 @@ USB) and the [GitHub releases](https://github.com/ALLFATHER-BV/wadamesh/releases keys mapped to tabs, ALT accent picker, UI scaling (Normal/Large/Huge), microSD for all persistent data. Ships through the Tanmatsu launcher store, updates arrive as store updates. +- **T-Lora Pager**: no touchscreen at all — the QWERTY keyboard and the rotary + encoder drive everything (Alt+turn free-scrolls a page; see + [TLORA_PAGER_SHORTCUTS.md](TLORA_PAGER_SHORTCUTS.md) for the full key map). + GPS, microSD, keyboard backlight, lock screen and notification sound through + the onboard codec and amp all work. Two builds, one per radio: LR1121 and + SX1262 — flashing the wrong one leaves you with no radio, so check the label + on your unit. A card the Pager detects but cannot read shows up in File + Manager greyed, and tapping it retries the mount; formatting is deliberately + left to a computer (FAT32) rather than done on-device. - **ThinkNode M9**: keyboard plus d-pad navigation (no touch), same feature set as the other boards where the hardware allows. Every key and mode is covered in the [keyboard & d-pad guide](THINKNODE_M9_SHORTCUTS.md). New in beta_38; diff --git a/README.md b/README.md index 95510e01..60ea0cd9 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ per-board status. - Tanmatsu (ESP32-P4) — built from `tanmatsu/` (ESP-IDF), ships via the Tanmatsu app store — [sideload guide](TANMATSU_SIDELOAD.md) for running your own build - Elecrow ThinkNode M9 — env `ThinkNode_M9_companion_radio_touch` (beta) — [keyboard & d-pad guide](THINKNODE_M9_SHORTCUTS.md) - RAK WisMesh Tap V2 (RAK3312) — env `rak_tap_v2_companion_radio_touch` (beta) -- LilyGo T-Lora Pager — envs `tlora_pager_lr1121_companion_radio_touch` / `tlora_pager_sx1262_companion_radio_touch` (stable) — [keyboard shortcuts](TLORA_PAGER_SHORTCUTS.md) -- Heltec V4-R8 + Expansion Kit V2 — env `heltec_v4_r8_tft_companion_radio_usb_tcp_touch` (stable) -- LilyGo T-Display P4 — built from `tdisplay_p4/` (ESP-IDF); AMOLED by default, `WADA_P4_LCD=1` for the TFT-LCD SKU +- LilyGo T-Lora Pager — envs `tlora_pager_lr1121_companion_radio_touch` / `tlora_pager_sx1262_companion_radio_touch` (beta) — [keyboard shortcuts](TLORA_PAGER_SHORTCUTS.md) +- Heltec V4-R8 + Expansion Kit V2 — env `heltec_v4_r8_tft_companion_radio_usb_tcp_touch` (beta) +- LilyGo T-Display P4 — built from `tdisplay_p4/` (ESP-IDF); AMOLED by default, `WADA_P4_LCD=1` for the TFT-LCD SKU (beta) - Attaky Mesh Series — env `attaky_mesh_series_companion_radio_touch` (beta) ## Architecture diff --git a/TLORA_PAGER_PORT.md b/TLORA_PAGER_PORT.md index 17157513..08c1d8e7 100644 --- a/TLORA_PAGER_PORT.md +++ b/TLORA_PAGER_PORT.md @@ -5,6 +5,60 @@ Goal: run the **full** wadamesh UI + functionality on the **LilyGo T-LoRa Pager* existing boards so a UI change ships everywhere at once. This file is the running plan/status — update it as we go. +## Current status (2026-08-20) + +**The port has shipped.** Both radio variants debuted on the beta channel in +**beta_45** (community PR #149, @codemonkeybr) and are installable from +wadamesh.com; `README.md` and `DEVICES.md` list the pager as a supported beta +board rather than a request. Milestones ⓪-⑦, ⑨ and ⑩ are done. Only ⑦b (the +USB companion gate) and ⑧ (the on-device UI pass) are still open. + +Done since the milestone history below was written, and re-verified against the +code on 2026-08-20: + +- **microSD is fully wired.** `CAP_SD`/`CAP_FILESYSTEM` are **1** — the staged + per-call-site widening finished, so DataStore contacts/channels routing, the + 5000-message history ring, map-tile SD packs, settings/crash export and the + About-page `/BINS` firmware export all work. See risk 1h for what that + replaced. +- **Release pipeline complete** — both envs in `release.sh`, both flasher + manifests generated, `FIRMWARE_OTA_ENV` set on each (worklist ⑨). +- **SD recovery without formatting**: a detected-but-unmountable card now shows + a greyed tap-to-retry row. In-app format remains deliberately omitted on this + board; the reasoning lives on the format-helper guard in `UITask.cpp`. +- **"Save update bin to SD" reaches the pager** via `CAP_SD && CAP_OTA` + (upstream e2d07d8) rather than a board-name list. Note that feature is spread + over six `#if` regions: e2d07d8 converted two, which left the pager with the + button but no worker — a hang plus a use-after-free on the status label, and + it still compiled. All six are now identical; do not widen them piecemeal. + +Still open, in priority order: + +1. **⑧'s actual stated scope — the 222 px vertical-layout audit and the + screen-by-screen focus-nav coverage pass — has still never been started** + (risk 8). Everything that landed under M8 was reactive bug-fixing from + user-reported issues. This remains the single biggest item in the port. +2. **USB companion device-profile frame is still untested** (⑦b). Remove the + temporary `[DISP]` register readback in `ST7796LCDDisplay::begin()` once it + passes. +3. Lock-screen wallpaper SD scanning is still T-Deck/M9-only (risk 1h). +4. `deploy/flasher/` now carries pager cards + manifests for parity, but **no + deploy script publishes that directory** (`deploy-site.sh` ships + `deploy/site/` only) and `flasher.wadamesh.com` 301s to the apex. Decide + whether to wire it into a deploy target or retire it. + +Risk 11 (keyboard/encoder scroll not repainting) is **accepted as +workaround-final**: the Alt+turn free-scroll gesture is the intended fix for +this hardware. + +--- + +## Milestone history + +The narrative below is kept as the port's working record — the war stories are +why several non-obvious things are the way they are. Where it conflicts with +the section above, the section above is current. + Status: **M7's UI portion DONE — boot logo, full LVGL UI, QWERTY keyboard nav and rotary encoder all VERIFIED WORKING on real hardware (2026-07-07)**, after root-causing the intermittent black screen to the ST7796 @@ -30,7 +84,8 @@ milestone: the radio-settings blur-autosave lag (risk 12), the encoder not scrolling open dropdowns (fixed 2026-07-08, commit `4bbfcb5`), the keyboard backlight never being wired up (risk 9, fixed 2026-07-10), and microSD file manager + WAV-picker support (risk 1h, fixed 2026-07-10, scoped — DataStore -SD routing/chat-history/tiles/wallpaper/backup remain deferred). An +SD routing/chat-history/tiles/backup were still deferred at the time and have +all since landed; only wallpaper scanning is left, see risk 1h). An unread-message LED notification was investigated and explicitly decided against (risk 13) — this board has no onboard LED at all. Risk 11 (keyboard/encoder-driven scroll not repainting) was **ACCEPTED as @@ -601,7 +656,7 @@ existing boards. Notes: **Gate:** all three envs build — verified. - [x] ⑥ **UITask wiring**: `device_caps.h` got its `TLORA_PAGER` cap block (no touch, no rotate, no large-screen, GPS 1, OTA 1, lock-screen 1; `CAP_SD`/ - `CAP_FILESYSTEM` corrected to 0 — see below) plus widened `CAP_KEYBOARD`/ + `CAP_FILESYSTEM` set to 0 at the time — both are 1 today, see risk 1h) plus widened `CAP_KEYBOARD`/ `CAP_KEYPAD_NAV` derivations to recognize `HAS_PAGER_KEYBOARD`/ `TLORA_PAGER`. `UITask.cpp` changes, all pager-gated: KEYPAD indev registered by widening the Tanmatsu branch's `#if` to @@ -624,9 +679,10 @@ existing boards. Notes: vs. the milestone doc's assumptions, all found by compiling rather than assumed — see risks 1h/1i/1j: - `CAP_SD`/`CAP_FILESYSTEM` looked right from the hardware (real microSD - slot) but the actual mount code is hardcoded to `HAS_TDECK_GT911`, not - truly `CAP_SD`-generic — set back to 0, real support is unscheduled - follow-up. + slot) but the mount code was hardcoded to `HAS_TDECK_GT911`, not truly + `CAP_SD`-generic — set back to 0 for this milestone. *(Superseded: the + call sites were widened over the following passes and both macros are 1 + today — risk 1h.)* - `navMaybeRebuild()` (populates the LVGL focus group every screen) wasn't reachable on the pager's own cap combination — added a `#elif defined(TLORA_PAGER)` arm; without it the KEYPAD indev would have @@ -653,11 +709,23 @@ existing boards. Notes: above): still untested. **SD storage: DONE** — real mount, browse, read/write/delete, and insert/remove detection all confirmed on hardware (risk 1h). (DataStore/NVS-level SD use — routing contacts/channels to the - card — is a separate, still-deferred feature, not part of this bring-up - gate.) Remove the temporary `[DISP]` register readback in + card — was a separate feature outside this bring-up gate; it has since + landed, see risk 1h.) Remove the temporary `[DISP]` register readback in `ST7796LCDDisplay::begin()` once the USB piece passes. - [~] ⑧ **On-device UI pass** — ACTIVE: nav-coverage audit screen by screen (every interactive control reachable via focus group — the Tanmatsu work paved this), chat layout at 222 px, map pan via encoder/keys, fonts legibility at 480-wide, plus fixing any weird UI/keyboard behaviors surfaced by manual testing (human provides photos/repro steps). -- [ ] ⑨ **Release pipeline**: add the env:binname pair to `release.sh` `ENVS`, flasher manifest (`deploy/flasher/manifest-tlora-pager.json`), OTA env name via `FIRMWARE_OTA_ENV`. Separate PR. +- [x] ⑨ **Release pipeline** — DONE (verified against the scripts 2026-08-20). + Both envs are in `scripts/release.sh`'s `ENVS` + (`tlora_pager_lr1121_...:wadamesh-tlora-pager-lr1121`, + `tlora_pager_sx1262_...:wadamesh-tlora-pager-sx1262`); both manifests are + generated by `scripts/build/gen-flasher-meta.py` + (`manifest-tlora-pager-{lr1121,sx1262}.json`); both envs set + `FIRMWARE_OTA_ENV`. The install page (`deploy/site/index.html`, which + `flasher.wadamesh.com` 301s to) carries an install button + .bin download for + each variant off the beta feed. Shipped to users in **beta_45**. + One leftover, not user-facing: the legacy static `deploy/flasher/index.html` + still lists only the T-Deck and Heltec V4 cards and has no pager manifests + next to it. That page is no longer the install path — decide whether to add + the two cards for parity or retire the directory. - [x] ⑩ (Optional, cheap) `tlora_pager_sx1262_...` env for SX1262-variant owners — **DONE, hardware-verified 2026-07-13** (`tlora_pager_sx1262_companion_radio_touch`, all 4 envs green; see `TLORA_PAGER_PORT_MILESTONES.md`'s Milestone 10 for the full writeup, including the `target.h` missing-include bug found + fixed). Radio gate (M7 step 3) confirmed on real hardware: user sent + received messages on public, a custom `#` channel, and DM. ## UI-changes inventory (what actually changes in `src/ui-touch/`) @@ -673,9 +741,11 @@ existing boards. Notes: | `navMaybeRebuild()` reachability | Added `#elif defined(TLORA_PAGER)` arm — was unreachable, would've left focus group permanently empty | small | done (bug fix) | | Vertical budget | Audit `STATUSBAR_H`, `TABBAR_H`, `CHAT_KB_H`, modal/chat height helpers for 222 px | **the real work** | deferred to M8 on-device (risk 8) | | Focus-nav coverage | Screen-by-screen pass that every control is in `s_nav_group` | medium, on-device | deferred to M8 | -| device_caps.h | New `CAP_*` block: no touch, hw keyboard, encoder, 480×222, GPS, OTA, lock-screen; SD/filesystem left 0 by design — real SD support added via widened individual call sites instead (see risk 1h) | trivial | done | +| device_caps.h | New `CAP_*` block: no touch, hw keyboard, encoder, 480×222, GPS, OTA, lock-screen. `CAP_SD`/`CAP_FILESYSTEM` were 0 while SD support was staged in per call site, and are now **1** (see risk 1h) | trivial | done | | Keyboard backlight (`pagerKeyboardSetBacklight()`) | `updatePagerKbBacklight()` tick + Settings → Keyboard cycle row (off/on/auto) | small | done (risk 9) | -| microSD (file manager + WAV picker) | `fmSdTryMount()`/`fmShowRoots()`/`fmIsAudio()` etc. widened to `\|\| defined(TLORA_PAGER)`; DataStore SD routing, chat-history cap, tile/wallpaper/backup SD use still deferred | medium | done, scoped (risk 1h) | +| microSD (file manager + WAV picker) | `fmSdTryMount()`/`fmShowRoots()`/`fmIsAudio()` etc. widened to `\|\| defined(TLORA_PAGER)`; DataStore routing, 5000-msg history, tiles and backup export all landed later. Only wallpaper SD scanning is still T-Deck/M9-only | medium | done (risk 1h) | +| microSD recovery row | `fmSdPagerRetryMountCb` — a detected-but-unmountable card renders greyed with a tap-to-retry that clears the mount backoff. No in-app format on this board, by decision | small | done | +| Save update bin to SD | About-page `/BINS` firmware export widened to the pager (`sdFwWorkerRun`); board-specific wording kept as separate TR() keys so the T-Deck's translated Launcher strings are not orphaned | small | done | | Chat bubble Enter/Backspace (`handleHwKey()` ~28808) | Enter on a focused bubble opens the Ack/Mention/Copy/Info/Block menu (`navEnterBubble()`); Backspace jumps to the newest message when the scroll-to-bottom button is showing | small | done | | Shift/Caps (`PagerKeyboard.cpp`) | Held Shift = momentary uppercase; held Alt+Shift = chord (see below for what it does) | small | done | | Accent-variant popup keyboard nav | Fn+Space arms it; encoder walks variants; encoder click/Enter confirms; Backspace cancels (`s_accentnav_active`/`accentNavRestyle()`/`accentNavConfirm()`) | medium | done | @@ -776,29 +846,51 @@ MQTT, OTA) is resolution-agnostic or already keyed off caps. page-scroll backward/up instead. Fixed by negating once in `PagerEncoder.cpp`'s `pagerEncoderReadDelta()` (the driver, not UI code) so every consumer inherits the corrected sense from one place. -1h. **`CAP_SD`/`CAP_FILESYSTEM` are 0 for the pager despite real microSD - hardware — a latent gap in `device_caps.h`'s own abstraction, not a pager - bug.** **File manager browsing + WAV notification-sound picker RESOLVED - 2026-07-10** (commits `8c7fb6a`/`1514e76`), scoped deliberately: `CAP_SD` - turned out to gate ~37 call sites (file manager, WAV picker, DataStore - contacts/channels routing, tile-cache SD fallback, wallpaper scanning, - settings backup, screenshots), so flipping the macro itself would have - silently turned on ~30 unvetted, T-Deck-only-tested features at once. - Instead `CAP_SD`/`CAP_FILESYSTEM` stay 0 by design, and only the ~7 - specific call sites needed for browsing + WAV picking were widened with - `|| defined(TLORA_PAGER)` — see those commits for the full categorized - site list. Added `pagerSdCardPresent()` (XL9555 `PAGER_EXPAND_SD_DET`, - confirmed-inverted polarity) and a pager `sdSharedSPI()` (reuses - `TFT_eSPI::getSPIinstance()`, the same bus the radio already shares). - Format support is explicitly out of scope (no `f_mkfs`/`sd_diskio.h` pulled - in) — the pager's SD row is tap-to-open only. Hardware-verified: mount, - browse, read/write/delete, insert/remove detection, and picking a WAV from - SD as a notification sound all confirmed on real hardware. **Still not - done** (unscheduled follow-up, deliberately deferred): DataStore - contacts/channels routing to SD (`setSecondaryFS`, what Tanmatsu/T-Deck - do to dodge SPIFFS GC stalls), the `MAX_UI_MESSAGES_SD` chat-history cap - bump, map-tile SD fallback/offline tile packs, lock-screen wallpaper SD - scanning, and settings/telemetry backup export-import to SD. +1h. **microSD — RESOLVED; `CAP_SD`/`CAP_FILESYSTEM` are now 1.** They were 0 + from M6 onward, which looked wrong against the hardware (there is a real + slot) but was deliberate: `CAP_SD` gates ~37 call sites (file manager, WAV + picker, DataStore contacts/channels routing, tile-cache SD fallback, + wallpaper scanning, settings backup, screenshots), so flipping the macro in + one go would have switched on ~30 unvetted, T-Deck-only-tested features at + once. The support was staged in instead, a group at a time: + - **File manager browsing + WAV notification-sound picker** — 2026-07-10 + (commits `8c7fb6a`/`1514e76`), the first ~7 sites, widened with + `|| defined(TLORA_PAGER)`. Added `pagerSdCardPresent()` (XL9555 + `PAGER_EXPAND_SD_DET`, confirmed-inverted polarity) and a pager + `sdSharedSPI()` (reuses `TFT_eSPI::getSPIinstance()`, the same bus the + radio already shares). Hardware-verified: mount, browse, + read/write/delete, insert/remove detection, and picking a WAV off the card + as a notification sound. + - **The rest** — verified in code 2026-08-20: DataStore contacts/channels + routing (`src/main.cpp`'s `setSecondaryFS`/`useSdStorage` blocks admit + `TLORA_PAGER`), the `MAX_UI_MESSAGES_SD` 5000-message history ring + (`uiDataFsIsSdCard()` admits the pager), map-tile SD fallback and offline + packs (the Map "tiles from SD" toggle; the tile-cache fix shipped in + beta_46), settings backup export/import plus crash-dump export + (`doExportBackupFile`), and firmware export to `/BINS` via About → "Save + update bin to SD". + + With those vetted, both macros were flipped to 1 and `device_caps.h` + describes the hardware again. Cleanup left over: the belt-and-braces + `#if CAP_SD || defined(TLORA_PAGER)` at several sites is now redundant and + can be collapsed to plain `CAP_SD`. + + **In-app format stays deliberately out of scope** on this board (no + `f_mkfs`/`sd_diskio.h` pulled in). The full reasoning now lives on the + format-helper guard in `UITask.cpp` so it is found from the code, not only + here: `f_mkfs` needs an `SD.end()` + `sdcard_init`/`uninit` lifecycle + teardown on the live shared display/radio bus; there is no touchscreen, so + the T-Deck's hold-to-format gesture does not map; and it has never been run + on pager hardware. The *recoverable* case is covered non-destructively + instead — a card the expander's SD_DET sees but that will not mount renders + a greyed **"SD card (unreadable - tap to retry)"** row + (`fmSdPagerRetryMountCb`) which clears the mount backoff and retries the + single 4 MHz attempt, then points the user at formatting on a computer. + + **Still not done**: lock-screen wallpaper SD scanning — that picker block is + still `HAS_TDECK_GT911 || HAS_THINKNODE_M9`, so the pager keeps its baked + 480x222 wallpaper (`lockscreen_wallpaper_pager_rgb565.h`) with no way to + choose one off the card. 1i. **`navMaybeRebuild()` was unreachable for the pager in the first M6 pass.** It's only called under `#if defined(HAS_TANMATSU) ... #elif CAP_TRACKBALL ...`, neither of which the pager's cap combination matches diff --git a/deploy/README.md b/deploy/README.md index 1534d0ce..988d321a 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -5,8 +5,8 @@ Distribution stack for wadamesh: a **VPS nginx origin behind Cloudflare**. ``` tiles.wadamesh.com →CF (HTTP, edge-cached) → nginx → OpenStreetMap / OpenTopoMap firmware.wadamesh.com →CF (cache bins) → nginx → /srv/wadamesh/firmware -flasher.wadamesh.com →CF (HTTPS) → web flasher (TODO — see below) -wadamesh.com →CF (HTTPS) → landing page (later) +flasher.wadamesh.com →CF (HTTPS) → 301 → wadamesh.com +wadamesh.com →CF (HTTPS) → nginx → /srv/wadamesh/site ``` **Map tile styles.** The default `/{z}/{x}/{y}.jpg` route serves **OpenStreetMap** @@ -67,11 +67,18 @@ highest `beta_`, and (once OTA-over-Wi-Fi is re-enabled) pulls ## Done -- **Web flasher** ✅ at `flasher.wadamesh.com` — `deploy/flasher/` (esp-web-tools / - Web Serial, board picker, manifests pointing at the rolling `/latest/` merged - bins; `release.sh` refreshes `/latest/` each publish). -- **Apex** `wadamesh.com` 301-redirects to the flasher — **activate by pointing - the `wadamesh.com` A record at the VPS** in Cloudflare (it's still on the parking IP). +- **Web flasher** ✅ — the guided install page at `wadamesh.com`, served from + `deploy/site/` and published by `scripts/deploy-site.sh` (esp-web-tools / Web + Serial, per-board install buttons + .bin downloads, manifests generated per + release by `scripts/build/gen-flasher-meta.py` into the `/latest/` and + `/latest-beta/` feeds that `release.sh` refreshes each publish). +- **`flasher.wadamesh.com` 301-redirects to the apex** (see + `deploy/nginx/flasher.wadamesh.com.conf`) — it is an alias, not its own page. +- **`deploy/flasher/`** is the original standalone flasher page. **No deploy + script publishes it** — `deploy-site.sh` ships `deploy/site/` only — so it is + effectively an offline/local copy kept in parity by hand. Retire it or wire it + into a deploy target; until then, treat `deploy/site/index.html` as the only + install page users can reach. ## TODO before public launch diff --git a/deploy/apps/lang/bg.lang b/deploy/apps/lang/bg.lang index deb00095..29a52899 100644 --- a/deploy/apps/lang/bg.lang +++ b/deploy/apps/lang/bg.lang @@ -683,6 +683,7 @@ Run setup again Стартирай настройката отново SD card %s SD карта %s SD card %s (hold: format) SD карта %s (задръж: формат) SD card (tap to mount) SD карта (докоснете за монтиране) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD картата е поставена SD card lost - reinsert to recover SD картата е изгубена - поставете я отново SD card remounted SD картата е монтирана отново @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD форматирана - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB използвани @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Запазено — рестарт Saved — reconnecting… Запазено — повторно свързване… Saved: %s\nFlash it from the Launcher. Запазено: %s\nФлашнете го от Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Запис на SD… %d%% Saving to SD… 0% Запис на SD… 0% Scan to open on phone Сканирай, за да отвориш на телефона diff --git a/deploy/apps/lang/de.lang b/deploy/apps/lang/de.lang index 2cc5b54f..8ee802bd 100644 --- a/deploy/apps/lang/de.lang +++ b/deploy/apps/lang/de.lang @@ -683,6 +683,7 @@ Run setup again Setup erneut ausführen SD card %s SD-Karte %s SD card %s (hold: format) SD-Karte %s (halten: formatieren) SD card (tap to mount) SD-Karte (zum Einbinden tippen) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD-Karte eingelegt SD card lost - reinsert to recover SD-Karte verloren - neu einstecken SD card remounted SD-Karte neu eingebunden @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD formatiert - %s (MESHCOMOD) SD is busy - close tools and retry SD ist belegt – Tools schließen und erneut versuchen SD removed - card-backed data cannot be saved SD entfernt – Kartendaten können nicht gespeichert werden SD stayed busy - format cancelled, retry SD blieb belegt – Formatierung abgebrochen, erneut versuchen +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB belegt @@ -722,6 +724,8 @@ Saved — applying… Gespeichert – wird angewendet … Saved — rebooting Gespeichert — Neustart Saved — reconnecting… Gespeichert — verbinde neu… Saved: %s\nFlash it from the Launcher. Gespeichert: %s\nFlashe es über den Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Speichern auf SD… %d%% Saving to SD… 0% Speichern auf SD… 0% Scan to open on phone Scannen, um am Handy zu öffnen diff --git a/deploy/apps/lang/el.lang b/deploy/apps/lang/el.lang index 209c8b92..b329c504 100644 --- a/deploy/apps/lang/el.lang +++ b/deploy/apps/lang/el.lang @@ -683,6 +683,7 @@ Run setup again Εκτέλεση ρύθμισης ξανά SD card %s Κάρτα SD %s SD card %s (hold: format) Κάρτα SD %s (κράτημα: διαμόρφωση) SD card (tap to mount) Κάρτα SD (πατήστε για προσάρτηση) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted Η κάρτα SD εισήχθη SD card lost - reinsert to recover Η κάρτα SD χάθηκε - επανατοποθετήστε SD card remounted Η κάρτα SD επανασυνδέθηκε @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD διαμορφώθηκε - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB σε χρήση @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Αποθηκεύτηκε — επανεκκίνηση Saved — reconnecting… Αποθηκεύτηκε — επανασύνδεση… Saved: %s\nFlash it from the Launcher. Αποθηκεύτηκε: %s\nΕγκαταστήστε το από τον Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Αποθήκευση στην SD… %d%% Saving to SD… 0% Αποθήκευση στην SD… 0% Scan to open on phone Σαρώστε για άνοιγμα στο κινητό diff --git a/deploy/apps/lang/es.lang b/deploy/apps/lang/es.lang index 688ca5fa..1f98c988 100644 --- a/deploy/apps/lang/es.lang +++ b/deploy/apps/lang/es.lang @@ -683,6 +683,7 @@ Run setup again Ejecutar configuración de nuevo SD card %s Tarjeta SD %s SD card %s (hold: format) Tarjeta SD %s (mantener: formatear) SD card (tap to mount) Tarjeta SD (toca para montar) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted Tarjeta SD insertada SD card lost - reinsert to recover Tarjeta SD perdida - reinsértala SD card remounted Tarjeta SD remontada @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD formateada - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB usados @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Guardado — reiniciando Saved — reconnecting… Guardado — reconectando… Saved: %s\nFlash it from the Launcher. Guardado: %s\nFlashéalo desde el Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Guardando en SD… %d%% Saving to SD… 0% Guardando en SD… 0% Scan to open on phone Escanea para abrir en el móvil diff --git a/deploy/apps/lang/fr.lang b/deploy/apps/lang/fr.lang index 2c394201..3bd03152 100644 --- a/deploy/apps/lang/fr.lang +++ b/deploy/apps/lang/fr.lang @@ -683,6 +683,7 @@ Run setup again Relancer la configuration SD card %s Carte SD %s SD card %s (hold: format) Carte SD %s (maintenir : formater) SD card (tap to mount) Carte SD (toucher pour monter) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted Carte SD insérée SD card lost - reinsert to recover Carte SD perdue - réinsérez-la SD card remounted Carte SD remontée @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD formatée - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u Ko utilisés @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Enregistré — redémarrage Saved — reconnecting… Enregistré — reconnexion… Saved: %s\nFlash it from the Launcher. Enregistré : %s\nFlashez-le depuis le Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Enregistrement sur SD… %d%% Saving to SD… 0% Enregistrement sur SD… 0% Scan to open on phone Scannez pour ouvrir sur le téléphone diff --git a/deploy/apps/lang/hu.lang b/deploy/apps/lang/hu.lang index 841bd6a7..7f4787fc 100644 --- a/deploy/apps/lang/hu.lang +++ b/deploy/apps/lang/hu.lang @@ -692,6 +692,7 @@ Run setup again Futtassa újra a beállítást SD card %s SD-kártya %s SD card %s (hold: format) SD-kártya %s (tartás: formázás) SD card (tap to mount) SD-kártya (érintésre csatlakoztatható) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD-kártya behelyezve SD card lost - reinsert to recover SD-kártya elveszett - helyezze be újra a helyreállításhoz SD card remounted SD kártya újracsatolva @@ -704,6 +705,7 @@ SD formatted - %s (MESHCOMOD) SD formázás - %s (MESHCOMOD) SD is busy - close tools and retry Az SD-kártya foglalt – zárd be az eszközöket, majd próbáld újra. SD removed - card-backed data cannot be saved SD-kártya eltávolítva – az SD-kártyán tárolt adatok nem menthetők. SD stayed busy - format cancelled, retry Az SD-kártya továbbra is foglalt – a formázás megszakítva, próbáld újra. +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB felhasználva @@ -733,6 +735,8 @@ Saved — applying… Mentve — alkalmazás folyamatban… Saved — rebooting Mentve — újraindítás Saved — reconnecting… Mentve — újracsatlakozás… Saved: %s\nFlash it from the Launcher. Mentett: %s\nFlash-eld a Launcher-ből. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Mentés SD-kártyára… %d%% Saving to SD… 0% Mentés SD-kártyára… 0% Scan to open on phone Olvasd be a telefonos megnyitáshoz diff --git a/deploy/apps/lang/it.lang b/deploy/apps/lang/it.lang index 2f61091a..4cf77f7b 100644 --- a/deploy/apps/lang/it.lang +++ b/deploy/apps/lang/it.lang @@ -683,6 +683,7 @@ Run setup again Esegui di nuovo la configurazione SD card %s Scheda SD %s SD card %s (hold: format) Scheda SD %s (tieni: formatta) SD card (tap to mount) Scheda SD (tocca per montare) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted Scheda SD inserita SD card lost - reinsert to recover Scheda SD persa - reinserirla SD card remounted Scheda SD rimontata @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD formattata - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB usati @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Salvato — riavvio Saved — reconnecting… Salvato — riconnessione… Saved: %s\nFlash it from the Launcher. Salvato: %s\nFlashalo dal Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Salvataggio su SD… %d%% Saving to SD… 0% Salvataggio su SD… 0% Scan to open on phone Scansiona per aprire sul telefono diff --git a/deploy/apps/lang/nl.lang b/deploy/apps/lang/nl.lang index cc53d222..9d8e1d8f 100644 --- a/deploy/apps/lang/nl.lang +++ b/deploy/apps/lang/nl.lang @@ -683,6 +683,7 @@ Run setup again Setup opnieuw uitvoeren SD card %s SD-kaart %s SD card %s (hold: format) SD-kaart %s (vasthouden: formatteren) SD card (tap to mount) SD-kaart (tik om te koppelen) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD-kaart geplaatst SD card lost - reinsert to recover SD-kaart verloren - plaats opnieuw SD card remounted SD-kaart opnieuw gekoppeld @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD geformatteerd - %s (MESHCOMOD) SD is busy - close tools and retry SD is bezig - sluit tools en probeer opnieuw SD removed - card-backed data cannot be saved SD verwijderd - kaartgegevens kunnen niet worden opgeslagen SD stayed busy - format cancelled, retry SD bleef bezig - formatteren geannuleerd, opnieuw proberen +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB gebruikt @@ -722,6 +724,8 @@ Saved — applying… Opgeslagen — wordt toegepast… Saved — rebooting Opgeslagen — opnieuw opstarten Saved — reconnecting… Opgeslagen — opnieuw verbinden… Saved: %s\nFlash it from the Launcher. Opgeslagen: %s\nFlash het vanuit de Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Opslaan naar SD… %d%% Saving to SD… 0% Opslaan naar SD… 0% Scan to open on phone Scan om op je telefoon te openen diff --git a/deploy/apps/lang/pt-br.lang b/deploy/apps/lang/pt-br.lang index f93f2eef..94daca29 100644 --- a/deploy/apps/lang/pt-br.lang +++ b/deploy/apps/lang/pt-br.lang @@ -683,6 +683,7 @@ Run setup again Executar configuração de novo SD card %s Cartão SD %s SD card %s (hold: format) Cartão SD %s (segure: formatar) SD card (tap to mount) Cartão SD (toque para montar) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted Cartão SD inserido SD card lost - reinsert to recover Cartão SD perdido - reinsira-o SD card remounted Cartão SD remontado @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD formatado - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB usados @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Salvo — reiniciando Saved — reconnecting… Salvo — reconectando… Saved: %s\nFlash it from the Launcher. Salvo: %s\nInstale pelo Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Salvando no SD… %d%% Saving to SD… 0% Salvando no SD… 0% Scan to open on phone Escaneie para abrir no celular diff --git a/deploy/apps/lang/ro.lang b/deploy/apps/lang/ro.lang index dd7b3a36..95ce1d25 100644 --- a/deploy/apps/lang/ro.lang +++ b/deploy/apps/lang/ro.lang @@ -683,6 +683,7 @@ Run setup again Rulează configurarea din nou SD card %s Card SD %s SD card %s (hold: format) Card SD %s (ţine: formatare) SD card (tap to mount) Card SD (atinge pentru montare) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted Card SD introdus SD card lost - reinsert to recover Card SD pierdut - reintrodu-l pentru recuperare SD card remounted Card SD remontat @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD formatat - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB folosiţi @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Salvat — se reporneşte Saved — reconnecting… Salvat — se reconectează… Saved: %s\nFlash it from the Launcher. Salvat: %s\nInstalează-l din Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Se salvează pe SD… %d%% Saving to SD… 0% Se salvează pe SD… 0% Scan to open on phone Scanează pentru a deschide pe telefon diff --git a/deploy/apps/lang/ru.lang b/deploy/apps/lang/ru.lang index 08597ff7..bf87b113 100644 --- a/deploy/apps/lang/ru.lang +++ b/deploy/apps/lang/ru.lang @@ -683,6 +683,7 @@ Run setup again Запустить настройку снова SD card %s SD-карта %s SD card %s (hold: format) SD-карта %s (удерж.: формат.) SD card (tap to mount) SD-карта (нажмите для монтирования) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD-карта вставлена SD card lost - reinsert to recover SD-карта потеряна - переставьте её SD card remounted SD-карта перемонтирована @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD отформатирована - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u КБ занято @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Сохранено — перезагрузка Saved — reconnecting… Сохранено — переподключение… Saved: %s\nFlash it from the Launcher. Сохранено: %s\nПрошейте из Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Сохранение на SD… %d%% Saving to SD… 0% Сохранение на SD… 0% Scan to open on phone Отсканируйте, чтобы открыть на телефоне diff --git a/deploy/apps/lang/sr.lang b/deploy/apps/lang/sr.lang index 5d43d9a2..948ee56d 100644 --- a/deploy/apps/lang/sr.lang +++ b/deploy/apps/lang/sr.lang @@ -683,6 +683,7 @@ Run setup again Поново покрени подешавање SD card %s SD картица %s SD card %s (hold: format) SD картица %s (држи: формат) SD card (tap to mount) SD картица (додирни за монтирање) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD картица убачена SD card lost - reinsert to recover SD картица изгубљена - убаците поново SD card remounted SD картица поново монтирана @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD форматирана - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u KB заузето @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Сачувано — рестарт Saved — reconnecting… Сачувано — поновно повезивање… Saved: %s\nFlash it from the Launcher. Сачувано: %s\nФлешујте га из Launcher-а. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Чување на SD… %d%% Saving to SD… 0% Чување на SD… 0% Scan to open on phone Скенирај да отвориш на телефону diff --git a/deploy/apps/lang/uk.lang b/deploy/apps/lang/uk.lang index e4eb39b1..ffbea53a 100644 --- a/deploy/apps/lang/uk.lang +++ b/deploy/apps/lang/uk.lang @@ -683,6 +683,7 @@ Run setup again Запустити налаштування знову SD card %s SD-картка %s SD card %s (hold: format) SD-картка %s (утрим.: формат.) SD card (tap to mount) SD-картка (торкніться для монтування) +SD card (unreadable - tap to retry) SD card (unreadable - tap to retry) SD card inserted SD-картку вставлено SD card lost - reinsert to recover SD-картку втрачено - вставте знову SD card remounted SD-картку перемонтовано @@ -695,6 +696,7 @@ SD formatted - %s (MESHCOMOD) SD відформатовано - %s (MESHCOMOD) SD is busy - close tools and retry SD removed - card-backed data cannot be saved SD stayed busy - format cancelled, retry +SD unreadable - format it as FAT32 on a computer SD unreadable - format it as FAT32 on a computer SF SF SF / CR / TX / AF SF / CR / TX / AF SPIFFS %u/%u KB used SPIFFS %u/%u КБ використано @@ -722,6 +724,8 @@ Saved — applying… Saved — rebooting Збережено — перезавантаження Saved — reconnecting… Збережено — перепідключення… Saved: %s\nFlash it from the Launcher. Збережено: %s\nПрошийте з Launcher. +Saved: %s\nReady for offline flashing. Saved: %s\nReady for offline flashing. +Saves the latest firmware of the selected channel to the SD card (BINS folder). Saves the latest firmware of the selected channel to the SD card (BINS folder). Saving to SD… %d%% Збереження на SD… %d%% Saving to SD… 0% Збереження на SD… 0% Scan to open on phone Відскануйте, щоб відкрити на телефоні diff --git a/deploy/flasher/index.html b/deploy/flasher/index.html index d5ad86ff..19f7ce5b 100644 --- a/deploy/flasher/index.html +++ b/deploy/flasher/index.html @@ -47,6 +47,10 @@ .note b{color:var(--ink)} a{color:var(--teal-ink)} footer{color:var(--mut);font-size:.85rem;padding:0 20px 40px;text-align:center} + .card h2 .beta{display:inline-block;margin-left:8px;padding:1px 7px;border-radius:999px;font-size:.7rem; + font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#8a5a12;background:#fdf0d8; + border:1px solid #f0d6a8;vertical-align:middle} + .card .warn{color:#b4631a;font-size:.85rem} .unsupported{display:none;color:#b4631a} body.no-serial .unsupported{display:block} body.no-serial esp-web-install-button{display:none} @@ -86,11 +90,27 @@ Use Chrome or Edge on desktop (Web Serial). +
+

T-LoRa Pager Beta LR1121

+

ESP32-S3 QWERTY + rotary encoder, no touchscreen.

+

Only for units with the LR1121 radio — SX1262 units need the other Pager card.

+ + Use Chrome or Edge on desktop (Web Serial). +
+
+

T-LoRa Pager Beta SX1262

+

ESP32-S3 QWERTY + rotary encoder, no touchscreen.

+

Only for units with the SX1262 radio — LR1121 units need the other Pager card.

+ + Use Chrome or Edge on desktop (Web Serial). +
How it works: plug the device in over USB, click Connect, pick the serial port, and let it flash — a clean full install. On a T-Deck, hold the trackball while tapping reset if it - doesn't enter download mode on its own. Works in Chrome / Edge on desktop. Want the guided + doesn't enter download mode on its own. The T-LoRa Pager ships with either an LR1121 or an SX1262 + radio — check yours and pick the matching card, since the wrong build leaves the radio dead; both + install from the beta channel. Works in Chrome / Edge on desktop. Want the guided version (incl. running under bmorcelli's Launcher)? See wadamesh.com.
diff --git a/deploy/flasher/manifest-tlora-pager-lr1121.json b/deploy/flasher/manifest-tlora-pager-lr1121.json new file mode 100644 index 00000000..fca81268 --- /dev/null +++ b/deploy/flasher/manifest-tlora-pager-lr1121.json @@ -0,0 +1,13 @@ +{ + "name": "wadamesh — LilyGo T-LoRa Pager (LR1121)", + "version": "beta", + "new_install_prompt_erase": true, + "builds": [ + { + "chipFamily": "ESP32-S3", + "parts": [ + { "path": "https://firmware.wadamesh.com/latest-beta/wadamesh-tlora-pager-lr1121-merged.bin", "offset": 0 } + ] + } + ] +} diff --git a/deploy/flasher/manifest-tlora-pager-sx1262.json b/deploy/flasher/manifest-tlora-pager-sx1262.json new file mode 100644 index 00000000..e214ded0 --- /dev/null +++ b/deploy/flasher/manifest-tlora-pager-sx1262.json @@ -0,0 +1,13 @@ +{ + "name": "wadamesh — LilyGo T-LoRa Pager (SX1262)", + "version": "beta", + "new_install_prompt_erase": true, + "builds": [ + { + "chipFamily": "ESP32-S3", + "parts": [ + { "path": "https://firmware.wadamesh.com/latest-beta/wadamesh-tlora-pager-sx1262-merged.bin", "offset": 0 } + ] + } + ] +} diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index 7e5bc8af..08e089f6 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -92,7 +92,9 @@ #endif #elif defined(TLORA_PAGER) #include // microSD (CS=21) on the shared radio/display SPI bus -- - // storage + file manager/WAV access; formatting stays disabled + // storage + file manager/WAV access. No sd_diskio.h/f_mkfs + // here: formatting is deliberately off on this board (the + // reasons are on the format-helper guard in the file manager). #define PIN_SD_CS PAGER_PIN_SD_CS // from TLoraPagerBoard.h, already visible via // MyMesh.h -> target.h -> TLoraPagerBoard.h above #include // pager ES8311 codec (notification tones + WAV playback) @@ -5377,6 +5379,21 @@ static void otaButtonRefreshState() { // the ACTIVE update channel (stable, or beta when "Get test builds" is on) // into /BINS/wadamesh-beta_-.bin on the SD card. The download // streams on the tile worker; this UI side mirrors the OTA poll pattern. +// Wording is board-conditional and the two sets are SEPARATE TR() keys on purpose. +// Only the T-Deck has bmorcelli's Launcher; now that this feature is gated on +// CAP_SD it also compiles for the Pager, the ThinkNode M9 and the Heltec V4-R8, +// where "flash it from the Launcher" names something the user does not have. The +// T-Deck strings must stay byte-identical: they are translated in all 13 .lang +// files, and editing the English key orphans every translation of it (audit with +// scripts/build/audit-lang.py). +#if defined(HAS_TDECK_GT911) + #define SDFW_SAVED_FMT TR("Saved: %s\nFlash it from the Launcher.") + #define SDFW_HINT_TEXT TR("For Launcher installs: saves the latest firmware of the selected channel to the SD card (BINS folder).") +#else + #define SDFW_SAVED_FMT TR("Saved: %s\nReady for offline flashing.") + #define SDFW_HINT_TEXT TR("Saves the latest firmware of the selected channel to the SD card (BINS folder).") +#endif + static volatile bool s_sdfw_request = false; // UI -> worker static volatile int s_sdfw_state = 0; // 0 idle, 1 running, 2 ok, 3 error static volatile int s_sdfw_pct = 0; @@ -5400,7 +5417,7 @@ static void sdFwPollTimerCb(lv_timer_t* t) { if (st == 2) { if (s_sdfw_status_lbl) { char b[112]; - snprintf(b, sizeof b, TR("Saved: %s\nFlash it from the Launcher."), s_sdfw_msg); + snprintf(b, sizeof b, SDFW_SAVED_FMT, s_sdfw_msg); lv_label_set_text(s_sdfw_status_lbl, b); } if (g_lv.task) g_lv.task->showAlert(TR("Update bin saved to SD"), 3000); @@ -20037,6 +20054,27 @@ static void fmSdClickCb(lv_event_t* e) { if (s_sd_mounted) fmOpenStorage(&SD, "SD", "/"); } +#if defined(TLORA_PAGER) +// Recovery entry for a card the Pager can SEE (card-detect asserted) but cannot +// mount: exFAT/NTFS, or a damaged FAT. Without this the roots page renders no SD +// row at all (fmShowRoots below), so there is no way to tell "no card" from "card +// the firmware won't take", and no way to retry without a reboot. +// +// Deliberately NON-destructive. It clears the mount backoff and makes exactly the +// one vendor-compatible 4 MHz attempt fmSdTryMount() already makes — it does not +// add a retry ladder and never tears down the live shared display/radio bus. If +// that attempt fails the card needs formatting, and on this board that is a +// deliberate host-side task: see the format-helper guard below for why the in-app +// formatter stays off for the Pager. +static void fmSdPagerRetryMountCb(lv_event_t* e) { + if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; + s_sd_retry_after_ms = 0; // explicit user retry — bypass the backoff + if (fmSdTryMount() && s_sd_mounted) { fmShowRoots(); return; } + if (g_lv.task) + g_lv.task->showAlert(TR("SD unreadable - format it as FAT32 on a computer"), 3600); +} +#endif + #endif // HAS_TDECK_GT911 || TLORA_PAGER || HAS_THINKNODE_M9 || HELTEC_LORA_V4_R8 (microSD mount helpers; the busy overlays below are generic LVGL) // Full-screen "busy" notice (copy/move/format). Pure LVGL — used by the generic paste path too. @@ -20064,6 +20102,24 @@ static void fmHideFormatOverlay() { if (s_fm_fmt_overlay) { popupClose(&s_fm_fmt_overlay); } } +// TLORA_PAGER is deliberately NOT in this list — the in-app formatter is omitted +// on the Pager, not merely unimplemented. Three reasons, in order of weight: +// 1. f_mkfs needs SD.end() + sdcard_init/uninit around it. That is a card and +// diskio lifecycle teardown on a bus the display AND the radio are actively +// driving, and this board's mount path is explicitly documented (fmSdTryMount +// above) to make ONE 4 MHz attempt and never tear the live shared bus down. +// The Arduino SD library never touches the SPI peripheral itself, so this is +// very likely fine — but "very likely" is not a basis for a one-way, whole-card +// erase, and it has never been run on Pager hardware. +// 2. There is no touchscreen, so the T-Deck's tap-to-open / hold-to-format split +// does not map. The nearest equivalent is holding ENTER on the focused row — +// an undiscoverable gesture that destroys the card, on a device where the +// encoder and ENTER are the only ways to move at all. +// 3. The recoverable case is already covered non-destructively: +// fmSdPagerRetryMountCb above surfaces a detected-but-unmountable card and +// retries the mount, and the alert it raises on failure points at the host. +// Formatting a card on a computer is a 30-second task with no such risk. Revisit +// only with a Pager in hand and a card that is safe to lose. #if defined(HAS_TDECK_GT911) || defined(HAS_THINKNODE_M9) || defined(HELTEC_LORA_V4_R8) // SD format helpers resume (Arduino SD, T-Deck + M9 + V4-R8) // Confirm callback: paint the formatting notice, then defer the (blocking) // f_mkfs to UITask::loop so the notice is on-screen before the loop freezes. @@ -21364,7 +21420,7 @@ static void fmShowRoots() { fmStyleRow(sd, COLOR_SUB); lv_obj_add_event_cb(sd, fmSdMountOrFormatCb, LV_EVENT_CLICKED, nullptr); } -#elif defined(TLORA_PAGER) // microSD row — browse only this pass, no format (see fmSdTryMount()) +#elif defined(TLORA_PAGER) // microSD row — browse + mount recovery, no in-app format // The card-detect line makes "not present" unambiguous, unlike the T-Deck (no detect // pin at all) -- so unlike its always-shown "tap to mount/format" fallback row, a bare // pager just shows no SD row at all rather than a row that can never succeed. @@ -21376,6 +21432,13 @@ static void fmShowRoots() { lv_obj_t* sd = lv_list_add_btn(s_fm_list, LV_SYMBOL_SD_CARD, sdl); fmStyleRow(sd, COLOR_TEXT); lv_obj_add_event_cb(sd, fmSdClickCb, LV_EVENT_SHORT_CLICKED, nullptr); + } else if (board.sdCardPresent()) { + // Detected but not mounted. Surfacing it (greyed) is the whole recovery path + // on this board: it distinguishes "card the firmware won't take" from the + // absent case above, and gives a retry that bypasses the mount backoff. + lv_obj_t* sd = lv_list_add_btn(s_fm_list, LV_SYMBOL_SD_CARD, TR("SD card (unreadable - tap to retry)")); + fmStyleRow(sd, COLOR_SUB); + lv_obj_add_event_cb(sd, fmSdPagerRetryMountCb, LV_EVENT_CLICKED, nullptr); } #endif #if defined(HAS_TANMATSU) || defined(HAS_TDISPLAY_P4) @@ -26460,11 +26523,19 @@ static void otaWorkerRun(WiFiClient& client, HTTPClient& http) { s_ota_state = 2; // success -> the UI poll timer reboots into the new slot } -#if defined(HAS_TDECK_GT911) || defined(HAS_THINKNODE_M9) || defined(HELTEC_LORA_V4_R8) +#if CAP_SD && defined(ESP32) && defined(MULTI_TRANSPORT_COMPANION) && CAP_OTA // Stream the app-only bin for the active update channel onto the SD card // (/BINS/wadamesh-beta_-.bin) so the Launcher can flash it — // the no-A/B-slot counterpart to otaWorkerRun above. Same immutable versioned // URL, same worker, but the bytes go to SD instead of the spare OTA slot. +// +// This feature is spread over SIX #if regions (state+callbacks, this worker, +// the tile-worker dispatch below, the About button, the settings-close teardown, +// and the sdHealthTick bail-out). They are character-for-character identical on +// purpose. A board admitted to some but not all of them still COMPILES — the +// worker's only caller sits behind the same gate, so nothing link-errors — and +// then hangs at "Saving to SD… 0%" with a poll timer writing to a label the +// teardown never nulled. Change all six or none. static void sdFwWorkerRun(WiFiClient& client, HTTPClient& http) { s_sdfw_pct = 0; if (SD.cardType() == CARD_NONE) { snprintf(s_sdfw_msg, sizeof s_sdfw_msg, "no SD card"); s_sdfw_state = 3; return; } @@ -26721,7 +26792,7 @@ static void tileFetchTaskFn(void* arg) { otaWorkerRun(client, http); continue; } -#if defined(HAS_TDECK_GT911) || defined(HAS_THINKNODE_M9) || defined(HELTEC_LORA_V4_R8) +#if CAP_SD && defined(ESP32) && defined(MULTI_TRANSPORT_COMPANION) && CAP_OTA // SD firmware download for Launcher installs (user-initiated from About). if (s_sdfw_request) { s_sdfw_request = false; @@ -31458,7 +31529,7 @@ static void settingsCatBuild(int cat) { lv_obj_set_width(s_sdfw_status_lbl, lblw); lv_obj_set_style_text_font(s_sdfw_status_lbl, &g_font_12, LV_PART_MAIN); lv_obj_set_style_text_color(s_sdfw_status_lbl, lv_color_hex(COLOR_SUB), LV_PART_MAIN); - lv_label_set_text(s_sdfw_status_lbl, TR("For Launcher installs: saves the latest firmware of the selected channel to the SD card (BINS folder).")); + lv_label_set_text(s_sdfw_status_lbl, SDFW_HINT_TEXT); } #endif } @@ -31516,7 +31587,7 @@ static void closeSettingsCategory() { hideKb(); if (s_settings_open_cat == CAT_ABOUT) { // null the live-label ptrs (freed with the sheet) s_sysinfo_lbl = nullptr; s_sysinfo_rest_lbl = nullptr; s_update_about_lbl = nullptr; s_ota_status_lbl = nullptr; -#if (defined(HAS_TDECK_GT911) || defined(HAS_THINKNODE_M9) || defined(HELTEC_LORA_V4_R8)) && defined(ESP32) && defined(MULTI_TRANSPORT_COMPANION) && CAP_OTA +#if CAP_SD && defined(ESP32) && defined(MULTI_TRANSPORT_COMPANION) && CAP_OTA s_sdfw_status_lbl = nullptr; #endif s_ota_btn = nullptr; s_ota_btn_lbl = nullptr; @@ -52082,8 +52153,8 @@ static void sdHealthTick() { return; } #endif -#if (defined(HAS_TDECK_GT911) || defined(HAS_THINKNODE_M9) || defined(HELTEC_LORA_V4_R8)) && defined(ESP32) && defined(MULTI_TRANSPORT_COMPANION) && CAP_OTA - if (s_sdfw_request) return; // worker streaming a firmware download to /BINS (T-Deck only) +#if CAP_SD && defined(ESP32) && defined(MULTI_TRANSPORT_COMPANION) && CAP_OTA + if (s_sdfw_request) return; // worker streaming a firmware download to /BINS #endif // Probe when some SD user flagged a failure (rate-limited to 1/5 s), and // also on a slow 30 s background cadence — a card yanked while nothing is