Commit Graph
124 Commits
Author SHA1 Message Date
Kaj SchittecatandClaude Opus 5.5 8daf59bdd7 doc: DOC_APPS_AUDIT capture tour for every Store app
Launches each catalog app (kAuditStore, generated by gen-radio-audit-apps.py
into the gitignored doc_radio_apps.h) and captures store_<id> for the
website's App Store page. Music gets two bench tracks and a play tap first.
Capture builds only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:54:31 +02:00
Kaj SchittecatandClaude Opus 5.5 8109bbf43a site: App Store page listing every Store app, with the SDK and how to submit
apps.html is generated from deploy/apps/apps.json (the catalog the devices
read) plus the site-only write-ups in deploy/site/apps-info.json, by
scripts/build/gen-apps-page.py, which deploy-site.sh now runs on every
deploy. Linked from the home page (Apps button + resource card), the SDK
guide and the sitemap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:17:59 +02:00
Kaj SchittecatandClaude Opus 5.5 b85eef6fec touch: beta_95, MeshCore 1.18 via meshcomod v1.18.0.1
About (Build) and the boot log name the meshcomod release the core is:
"on meshcomod v1.18.0.1". release.sh reads it from the pinned core's own
examples/companion_radio/MyMesh.h, keeps the in-tree defaults in step and checks
every staged image carries it. Language store v26 (this build's new texts),
release notes for beta_95.

Bench (T-Deck, 1.18): device and self info, 404-contact sync, the companion CLI
(ver, board, get name/radio/tx/freq, unknown command), 4 packets received and a
zero-hop advert sent in 90 s, correct device time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:07:34 +02:00
Kaj SchittecatandClaude Opus 5.5 ef0b27f1e0 core: MeshCore 1.18 (core-v1.18.0 = meshcomod 8aba438f), V4 language table deflated
Pins move from core-v1.17.4 to core-v1.18.0, cut from the main meshcomod
companion-v1.18.0.1 was released from. The companion changes are ported from
meshcomod's rebase into wadamesh's own MyMesh:

- onCLICommandRecv: a contact's remote CLI command runs when the user granted
  that contact remote CLI, and lands in the chat as a CLI message otherwise.
- CMD_RUN_CLI_COMMAND (66) / RESP_CODE_CLI_REPLY (29) and the local companion CLI
  (name, pin, Wi-Fi, radio, af/dutycycle, rxgain, tx, rxdelay, path.hash.mode,
  multi.acks, board, ver), also reachable from the serial CLI. Settings without a
  prefs field answer "unsupported". NodePrefs layout unchanged.
- TXT_TYPE_CLI_COMMAND is accepted for sending; sendCommandData (and our queue-
  preserving wrapper) carry the text type.
- Channel data is delivered to the app (onChannelDataRecv), unsolicited responses
  (pushed telemetry) reach it as PUSH_CODE_BINARY_RESPONSE, and raw-data sends
  decode multi-byte-hash paths.

Clock: 1.18 seeds an unsynced ESP32 clock at 1 Mar 2026, so ClockFloorRTC's
MIN_VALID_EPOCH follows it (a set equal to the seed must stay invalid).
Pager LR1121: the AGC reset re-applies the boosted-gain setting (new core arg).
IDF builds exclude the new CommonRadioPrefs.cpp (needs <target.h>/radio_driver).

The 2 MB Heltec V4 went to 100.0% with the CLI. Its built-in language table is now
one raw-deflated blob per language (895 KB -> 312 KB), inflated into PSRAM by the
S3 ROM on first use (~10 ms, ~75 KB for the active language): 91.7% flash. Checked
on a T-Deck forced onto the table (nl, hu, el) and by the post-link key check.

Builds: all 15 S3 touch envs, Tanmatsu (3,237,024 B), T-Display P4 SX1262 + LR2021.
T-Deck boots and runs on 1.18.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:50:32 +02:00
Kaj SchittecatandClaude Opus 5.5 d3a9cf1453 touch: radio tools redesign, Music app, Store update badge, triage fixes
Spectrum: stat tiles (peak, floor, our channel, busy), plot and waterfall drawn
at screen size (the lv_chart and zoomed waterfall were the page's render cost),
dark-to-yellow waterfall, peak hold, our-channel marker, Band/Channel and
Live/1 min/10 min chips. RF Monitor 1.4 (tiles, filled chart, typed feed, packet
detail card; the old type table did not match MeshCore payload types) and
Airtime 1.6 (big figure, tiles, duty line, rx/tx split).

Lua SDK: ui.panel, bold labels and a size-24 figure font, colors.warn/border,
app.on_audio (fires with the screen off), read-only wada.sd.list and sd: audio on
the SD_MMC boards (P4, Tanmatsu, Wio L2), caps panel/audio_events/epaper, a
"music" icon and an "audio" Store requirement. button:set() no longer writes
label fields into the button object (heap corruption, every earlier firmware).
The SDK page's input table described events the firmware never sent.

Music 1.0 (Store app): plays MP3/WAV from the card's Music folder, shuffle,
repeat, keeps going through the list with the screen off. Verified on the
T-Display P4 end to end.

Store: the update check also fetches the app catalog and badges the Store tile
with the number of installed apps that have a newer version. Baked Lua apps are
raw-deflated and inflated by the S3 ROM (14.6 KB back on the V4); the V4 language
table keeps only texts of apps it can run.

Fixes: the SD-card notice no longer fires when the card mounts fine (#667); the
Control Center clock keeps time while open (#666); M9 keyboard brightness (#664);
the battery widget's number no longer sits on a ring too small for it (Discord);
M9 shortcuts doc follows #669's composer order. New texts in all 14 languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:07:11 +02:00
Kaj Schittecat 806ecb0f71 Merge PR #655 (oumike): Add the Elecrow CrowPanel Advance 5.0 (#651) 2026-10-14 10:16:48 +02:00
Michael A. Cojocari b0960cdcf1 Merge remote-tracking branch 'upstream/main' into crowpanel-50
# Conflicts:
#	scripts/build/gen-touch-fonts.sh
#	src/ui-touch/ui_font_18.c
#	src/ui-touch/ui_font_20.c
#	src/ui-touch/ui_font_24.c
2026-10-13 08:59:08 -04:00
Kaj SchittecatandClaude Opus 5.5 bec56ba814 reader: page through big text files, open card documents from Files, and a tool to fill a card
Asked for on Discord (prepper use: books and documentation offline on the card).

- The Reader opens a .txt or .md file on the card as a 16 KB window at an
  offset carried in the URL (sd:/x.txt?o=49152), cut back to a line (or a whole
  UTF-8 character), with Next page / Previous page / Back to the start links and
  the position in percent. A book of any size pages through; Back works as usual.
- Files opens HTML on the card in the Reader (its links work there, so a folder of
  pages browses offline) and text or markdown too big for the 8 KB editor; small
  text files keep the editor.
- scripts/sdpack.py (standard library only): an EPUB becomes /library/<name>/ with
  one page per chapter (long chapters split under 30 KB, linked in order) and a
  contents page; .txt/.md are copied as they are; /home.htm lists everything, so
  the Reader, which opens sd:/home.htm, starts on the library. Tested with a
  generated EPUB.
ZIM (Wikipedia) files are not read on the device: their clusters are zstd/xz
blobs of 1-2 MB and the files run to tens of GB on FAT32; converting on a
computer keeps the device side small.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 11:48:26 +02:00
Kaj SchittecatandClaude Opus 5.5 083d422a2d i18n: the V4 bakes the live translations, trimmed to keys the firmware can show
beta_93 pinned the Heltec V4 to the beta_92 .lang files because the full table
no longer fit. lang_reach.py now works out which keys any source can look up:
a .lang key is kept when it equals a C string literal anywhere in the sources
(every #if branch, adjacent literals joined, LV_SYMBOL_*/UI_ICON_* and other
string macros expanded, escapes decoded as GCC does), or that literal with TR()'s
glyph prefix stripped, or a string in any Lua app. 1818 of 1925 keys survive; the
107 dropped look unused (old dropdown strings, texts the source has reworded).

The trimmed live table is 15.5 KB smaller than the pinned one (V4 4,025,365 B
used, 37.9 KB free) and carries every translation added since beta_92.

Guards: the generator refuses to trim when an input is missing (lv_symbol_def.h,
UITask.cpp, or under 80% kept) and leaves the header alone; after linking the V4,
--check-objects reads the strings the compiler emitted and fails the build if a
translated key among them was dropped (proved by dropping a live one). The
pre-build hook regenerates on source changes too, and the header is only
rewritten when its content changes. The pinned copy is gone (git history).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 11:20:12 +02:00
Kaj Schittecat 4e73bcc34a Merge PR #645 (oumike): T-Deck Pro / Max: Normal, Large and Huge text sizes, as on the T-Deck (#639) 2026-10-13 09:18:17 +02:00
bfindlay 7025f79b30 no-mistakes(lint): Guard host-test runner against failed directory changes 2026-10-13 15:00:33 +11:00
bfindlay ad13d42a12 Fix M9 keyboard detection at the V1.1 I2C address
Signed-off-by: bfindlay <bfindlay@acm.org>
2026-10-13 14:43:28 +11:00
Michael A. CojocariandCopilot 3ce6b065e4 Add Elecrow CrowPanel Advance 5.0 build target
New env crowpanel_50_companion_radio_touch for the 800x480 ST7262 RGB panel,
GT911 touch and an SX1262 in the wireless slot. Board quirks follow Camillia-MT:
14 MHz pixel clock, internal-RAM draw band, PCA9557 (V1.0) / MCU (V1.1+)
backlight controller detection with GT911 reset at 0x5D or 0x14, NSS on GPIO8
(V1.2+), no SD/GPS/battery. Large-screen layouts and UI-size fonts; browser
file transfer to the internal tiles partition. Added to the upload helper,
release script, flasher manifests, site, DEVICES.md, README and NOTICE.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-11 15:07:32 -04:00
Michael A. CojocariandCopilot 67680763ed T-Deck Pro / Max: Normal, Large and Huge text sizes, as on the T-Deck (#639)
Enable CAP_UI_SIZE and the font-only text-size presets (montserrat
12/14/16, 16/18/20, 18/20/24) for HAS_TDECK_PRO boards, compile the
18/20/24 px UI fonts for them, and size the status bar to match.
Docs list the T-Deck Pro and Max under Text size.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-10 21:44:37 -04:00
Kaj SchittecatandClaude Opus 5.5 d68f276b06 touch: beta_93, contact nicknames, new control panel, tooltips, Pager shortcuts, speed and battery
Contact nicknames: TouchPrefsStore nick blob (48 x 38 B), display-only lookups
(contactShownName, threadShownName, senderShownName), Contact options >
Nickname on the shared text prompt (an empty OK clears it).
Control panel restyled in the launcher's tile language, with a Battery saver
tile; keyboard tooltips (navSetTip), an amber cursor and touch long-press
tooltips (the T-Deck touch read hid them on every poll).
T-LoRa Pager: M/C/A/S on Home, H/S tap and hold, Backspace = Back, N = jump to
new, held Enter = long press, per-tab focus memory, Power off confirm; LVGL
-O2 and IRAM, INT-gated keyboard, idle yield, status-bar setter guards, instant
tabs; PagerGps (u-blox software standby for rests, GPS rail cut when off),
panel sleep, amp off at boot, power-off parks the radio (NSS held), GPS, panel
and keyboard light.
Fixes: the DM duplicate check keys on the attempt and a path reset clears it,
the direct timeout masks the packed path byte, web remote hops (#636);
changelog over http (#638); Lua SDK send budgets and duplicate guard (#606);
GPS speed note (#613, CAP_GPS_BAUD_AUTO); emoji chat icon (#640); default
wallpaper (#626).
Heltec V4: Tetris, 2048 and Breakout unseeded and the built-in Lua stripped of
comments (identical bytecode), 27 KB freed; the baked language table is pinned
to beta_92's files (scripts/build/lang-pin-beta92) so it still fits.
Translations: 39 new keys in 14 languages, language store v24.
Site: theme, dark mode, aurora and guide refresh, SDK send limits, nicknames.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:08:16 +02:00
Michael A. CojocariandClaude Opus 5.5 9c0cccd2fb build(m9): the LR1110 old-firmware patch applies to RadioLib 7.8.1 too
lib_deps takes RadioLib ^7.6.0, and a fresh fetch now brings 7.8.1. Its
LR11x0::config() wraps driveDiosInSleepMode in its own skip for LR1110
firmware below 0x0306, so the call sits one level deeper and the patch
script no longer found it. It failed closed, stopping every M9 build at
its pre-script.

The script now knows both shapes. The patch still matters on 7.8.1:
firmware 0x0306 and 0x0307 get past RadioLib's own skip, send the
command, answer CMD_PERR and would abort radio init with -706.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yt7fNCKmafm9LtRjyuUmS
2026-10-09 11:26:32 -04:00
Kaj SchittecatandClaude Opus 5.5 33ae4c61bd tanmatsu: drop the Wi-Fi OTA path so the app fits the launcher's load window
The launcher's AppFS bootloader maps only the first 50 x 64 KB of an app
while it checks and starts it (appfsBlMmap in badgeteam/appfs 2.1.0).
beta_91 (3,329,568 B) and the first beta_92 build (3,331,120 B) were past
it, so neither would start on a Tanmatsu.

On the Tanmatsu the launcher updates the app (CAP_OTA 0) and the only OTA
slots are the launcher's own 2 MB ones, so the core's "ota start" upload
page and URL install could never work there. DISABLE_WIFI_OTA stubs them
("ERR: OTA not supported in this build"), and with them go ElegantOTA,
the async web server and AsyncTCP: the app drops to 3,200,864 B, 75,936 B
under the window.

tanmatsu-appstore-publish.sh now refuses a binary over the window, and
its PR text no longer has an em dash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:40:02 +02:00
Kaj SchittecatandClaude Opus 5.5 9d0301b80a touch: beta_92, faster screens on most boards, Arabic fixes, GitHub fixes
Frame rate: full-width PSRAM draw band (6 bands a frame instead of 14 on the
T-Deck), the still aurora drawn once and copied, LVGL at -O2 with its blend and
label loops in IRAM (scripts/build/perf_lvgl.py, 1 KB more loop stack), circle
and gradient caches, newlib memcpy. Rolled out to the M9, Attaky, RAK, Wio,
CrowPanel and V4-R8; the Pager gets the band only, the V4 the caches only.
Frame benchmark tour (DOC_PERF_BENCH) for measuring it.

Fixes: hop counts read from the packed path length (#621); Arabic shaping
rows patched in LVGL (patch_lvgl_arabic.py), Arabic 101 shift layer, kaf,
symbols, text sent as standard letters (#582); info popup colour runs that
never wrap (#602); keypad nav reaches the chat header (#623); the browser
opens the changelog (#622, gen-changelog.py at every site deploy); the
Theme background colour picker no longer edits the accent; flasher entries
for P4 units with factory ESP-AT Wi-Fi chips (#612, #619).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:53:33 +02:00
Kaj SchittecatandClaude Opus 5.5 218bc6ed3e touch: beta_91, Home becomes widgets, backgrounds, GPS in the bar
Home is a grid of arrangeable widgets (24 kinds, presets, a layout per
orientation, Lua app widgets via wada.widget); Unread, Chat and Mentions
get a large size. Theme > Background puts an aurora (still by default, or
moving), a colour, a picture or nothing behind every screen, with glass
cards and a smoked-glass top bar. A GPS icon in the bar, a GPS battery
saver (u-blox GNSS stop/start where there is no power switch), and a
battery saver that no longer waits for Bluetooth and Wi-Fi to be off.
Also: navigation bar position, every settings page on the redesign's
cards, a faster app drawer, slower screensaver drift for burn-in, text
wrapping at spaces only, the V4-R8 Store Apps tab, and SDK Test marked
extended-SDK only (keeps the 2 MB V4 at 99.8%).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:14:04 +02:00
Kaj SchittecatandClaude Opus 5.5 662665e6de touch: beta_89, the UI overhaul
Every screen redesigned to the Oct 2026 mockups, on one design system:
palette, type roles (generated Montserrat faces with Lucide line icons on the
LV_SYMBOL codepoints), a theme apply-cb that styles every LVGL widget, button
kinds, list rows, sheets as action lists, toasts and key-glyph avatars.

Rebuilt: status bar, Chats (filters, + and menu), conversation (route header,
hop meta, "Heard by N repeaters", delivery states, pill composer), lock screen
(mark, clock, 24 h activity, unread cards), Constellation screensaver, Home
launcher and launcher sheet, Status page, grouped Settings home, animated boot
splash, and the message glance as a notification card.

New: optional PIN lock (salted SHA-256, keyboard / touch pad / number pad per
board, backoff that survives reboot), screensaver on battery with its own
duration, T-Deck text sizes, trackball hold to switch Scroll and Cursor (Scroll
default, prefs v69/v70), hold Settings tab for the control panel. M9 bottom
notices removed. Every screen measured for the Large and Huge text sizes.

Fix: adverts over 2/3-byte path hashes never reached the recently heard table
(packed path_len compared as a byte count); ADVERT_PATH replies now carry the
whole multi-byte path.

English placeholders for the 204 untranslated keys in every .lang file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 23:26:41 +02:00
Kaj SchittecatandClaude Opus 5 820bc21f46 build: verify the P4 artifacts, and make the host tests runnable
The T-Display P4 ships EIGHT images: panel (AMOLED/LCD) x radio (SX1262/LR2021)
x C6 stack (esp-hosted/ESP-AT). The C6 axis is new and it is the dangerous one,
because the two builds are identical apart from the artifact name they carry,
and flashing the wrong one at an older unit used to boot-loop the board.

scripts/build/p4-release.sh builds all eight and VERIFIES each image against the
OTA name baked into it before accepting it. That is the same string the device
builds its self-update URL from, so a disagreement with the filename is exactly
the failure that bricks people -- the T-Deck Max self-updating to Pro firmware,
and this table has been wrong three times. A mismatch aborts the release.

It earned that check immediately: building the eight by hand produced two
mislabelled images, and every mechanism meant to prevent it was itself broken.

  * build.sh fullclean has NEVER worked from a plain shell. It ran `cmake -E
    remove_directory` above the esp-idf/export.sh that puts cmake on PATH, so it
    printed that it had removed the tree, exited 0, and removed nothing. Now a
    plain rm -rf, and it verifies the directory is gone instead of assuming.
    This matters beyond tidiness: the hosted and ESP-AT builds SHARE a build dir
    (the C6 axis does not change P4_BUILD_TARGET), the backend is read from the
    environment at CMake CONFIGURE time, and CMake does not reconfigure because
    an env var changed -- so a clean that silently did nothing yields an
    incremental build of the OTHER variant, with no configure output to show for
    it. That is precisely how the two mislabelled images were produced.
  * Deleting CMakeCache.txt alone is not a clean either; it leaves CMakeFiles/
    behind and the next configure dies in CMakeDetermineCCompiler.
  * Detecting failure by grepping a log for "error:" misses a failed CMake
    configure, which prints "Configuring incomplete" and no such line -- and the
    previous application.bin is still sitting in the directory to be picked up.
    Exit codes now.

gen-flasher-meta.py gains the four ESP-AT entries, labelled "older unit, ESP-AT
C6": someone choosing in the web flasher has no serial log and needs to pick on
something they can check.

scripts/run-host-tests.sh runs test/ as one command. Nothing ever did, which is
why test_touch_prefs_schema had been failing to COMPILE since v64 appended
report_ping and report_done_n without updating its sums -- and a static_assert
that does not compile is not a guard. That one exists to catch the mid-struct
insert that broke v44 and shipped the poisoned beta_57 layout. Repaired, with a
note where the next person appending a field will read it. 17 pass, 0 fail, 2
skipped with their reasons stated rather than quietly dropped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-05 11:31:36 +02:00
Kaj SchittecatandClaude Opus 5 66e1f37d2c harness: model the filesystem, and stop apps running other apps' tests
Two things made a full harness run untrustworthy, and together they produced a
false accusation against a community app.

wada.fs was stubs. append threw the data away, remove always said true, and
read, write and list were not there at all — although the firmware registers
all five (LuaAppHost.cpp). Any app that writes a file and reads it back
therefore failed here while working perfectly on device. wardrive 1.2 is
exactly that app: it errors on a nil fs.read at its first log flush, long
before it renders anything, and the emoji scenario then reported the repeater
name as unrendered. Read as "1.2 regressed the beta_70 emoji fix", which it
did not. It passes untouched once fs is real.

wada.fs is now an in-memory filesystem following LuaAppHost's semantics: read
returns the data plus the file's TOTAL size so a caller can window a growing
log, an offset at or past the end gives an empty string rather than nil, a
missing file gives nil, and list is sorted so a hash order cannot make a test
flaky.

The second: the gpscompass scenario list was acting as the dispatch default,
so an app with no branch of its own was run against tests written for a
different app. Six store apps have no branch (2048, airtime, monitor, nearby,
sdktest, snake), so a full sweep came back with six red apps as its normal
state — and a real regression would not have stood out against that. Those
apps now say they have no scenarios and run none. They are untested, which is
worth saying out loud, but that is not the same as broken.

A sweep of every store app is now 8 apps passing their own scenarios, 6
reported untested, 0 failures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-04 12:42:12 +02:00
Kaj Schittecat 3171f5adea Merge PR #586 from samuelcoustet: Breakout and Trip Odometer Lua apps
Stacked on #585 and merged after it, as the PR asks. Two conflicts, both from
the stack base moving:

  apps.json: unioned by id, so all fourteen apps survive.
  harness.lua: the additive blocks came from #586. Where both sides edited the
  same code, #585's is newer and wins: its ping scenarios pass cfg.gps as a
  FUNCTION, which is what the harness calls (cfg.gps()); #586 still passed the
  table and would have failed. Taking #586 there would have broken ping.

  Then restored the two dispatch branches my first resolution dropped. The
  breakout and tripodometer scenarios existed but nothing ran them, so both
  apps silently fell through to the gpscompass scenarios and "failed".

All five new apps pass their own scenarios, and so do gpscompass and sdscan.
2026-10-03 17:24:15 +02:00
Kaj Schittecat ee20089e30 Merge PR #585 from samuelcoustet: Tetris, Ping and ProTreck Lua apps 2026-10-03 17:20:09 +02:00
Michael A. CojocariandClaude Opus 5.5 dbecef0b6f feat(crowpanel-35): add Elecrow CrowPanel 3.5" (ESP32-S3, ILI9488 + GT911) touch target
- New crowpanel_35 variant: display, SD, board and target files, plus board JSON
- Portrait mode is drawn rotated 180°; landscape stays at rotation 3
- Share the GT911 touch driver between Wio Tracker L2 and CrowPanel
  (WioTrackerL2Touch.cpp -> src/helpers/input/LgfxGt911Touch.cpp)
- platformio envs, flasher/site entries, release and merge-bin support
- Tests for the CrowPanel SD codec and merge-bin

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0132MkJ7RUV32mV9F7o4PJMm
2026-10-02 20:16:06 -04:00
SamandClaude Sonnet 4.6 06f9c6e549 feat(apps): ProTreck 1.0 — outdoor watch Lua app (Astro/Chrono/Timer/Alti)
Sun/Moon rise+set from GPS lat/lon + date (Spencer 1971), moon phase 0-29.
Chronometer with lap times, countdown timer with alarm beep and preset
cycling, altimeter with GPS alt_m, min/max persistence and trend graph.
Swipe left/right to switch tabs. 4 tabs fit any screen size.

test(harness): add 7 ProTreck scenarios (tdeck, v4, no_gps, chrono,
timer, alti, cost). ALL OK 7/7.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-02 22:52:51 +02:00
rootandClaude Sonnet 4.6 7254b9cca6 feat(apps): Ping 1.0 — mesh DM ping with GNSS position and RTT
Send a DM to any contact, measure round-trip time.  Both devices
exchange their GPS coordinates; the result shows RTT, distance and
cardinal bearing when both have a fix.  The app also auto-replies to
incoming pings so two devices running Ping can time each other.

Harness additions: send_dm mock, wada.geo (haversine), deliver_dm
helper, and 6 scenarios (tdeck, v4, no_contacts, round_trip,
auto_reply, cost) — all pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-02 22:50:22 +02:00
SamandClaude Sonnet 4.6 9b7ca27747 feat(apps): Trip Odometer 1.0 — GPS trip computer as a Lua app
Tracks total distance (Haversine accumulation), elapsed time, current
speed, max speed, and altitude from live GPS fixes.  Start/Stop button
pauses accumulation; Reset clears the trip.  The current trip persists
across app restarts via wada.store.

Also adds 6 harness scenarios (no-fix, T-Deck, moving, persist, reset,
cost) and registers the app in apps.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-02 22:41:14 +02:00
SamandClaude Sonnet 4.6 ec57effffb feat(apps): Breakout 1.0 — classic brick-breaker as a Lua app
Ball + paddle + 8×5 brick grid. Swipe left/right (or arrow keys) to
move the paddle; swipe up / Enter / Space to launch. Angle on bounce
varies by paddle-hit position. Speed increases each level; high score
persists via wada.store.

Adds 6 harness scenarios (tdeck, v4, keyboard, logic, hiscore, cost).
Worst tick ~8k instructions, 8% of the 100k budget.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-02 22:37:57 +02:00
SamandClaude Sonnet 4.6 44f5dae4eb test(harness): add Tetris scenarios — tdeck, v4, keyboard, logic, hiscore, cost
Detects /tetris/ in the app path and routes to 6 dedicated scenarios:
- tetris_tdeck/v4: open + swipe input on touch screens
- tetris_keyboard: arrow + enter input on keyboard boards
- tetris_logic: hard-drop to game-over, verify restart resets timer to 700 ms
- tetris_hiscore: verify high score is stored as a number after game-over
- tetris_cost: 100 ticks, worst ~6000 instructions (budget 100000)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-02 22:21:44 +02:00
Michael A. Cojocari 500b24e38c feat(tdisplay-p4): support LR2021 radio variants (#504) 2026-09-26 21:59:58 -04:00
Michael A. CojocariandClaude Opus 5.5 b60c26ac85 feat(tdisplay-p4): esp-hosted C6 backend for Wi-Fi
Current T-Display P4 V1 units ship the C6 with esp-hosted firmware
(2.12.3), and main's P4 build only spoke ESP-AT, so Wi-Fi could not come
up on them at all. This is a one-time import of the esp-hosted backend

- TDP4_C6_HOSTED build switch (default hosted; WADA_P4_LEGACY_AT=1 keeps
  the ESP-AT path for older units), with the ESP-AT socket/WiFi facades
  and the single-listener TCP router guarded to the legacy build.
- tdisplay_p4: build.sh hosted patches and fullclean handling,
  idf_component.yml esp-hosted pin, sdkconfig, main.cpp hosted bring-up
  and SNTP, c6_at updates, and the C6 reset hook in target.cpp.
- P4 Wi-Fi scan wait in UITask.
- TDISPLAY_P4_C6_FIRMWARE_PLAN.md.

Not imported from that commit: UI-scale default, GPS log lines, UI

build-upload-monitor.sh: run build.sh's own fullclean for the P4 (idf.py
fullclean rejects the patched managed components).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 15:28:50 -04:00
Michael A. CojocariandClaude Opus 5.5 ed9a49c506 scripts: T-Display P4 targets in build-upload-monitor and build-all
build-upload-monitor.sh gains --tdisplay-p4 (AMOLED) and
--tdisplay-p4-lcd (HI8561 LCD SKU). The P4 is an ESP-IDF app, so these
drive tdisplay_p4/build.sh (build/flash/monitor, --erase, --fullclean,
PORT= for the serial port) instead of pio; both appear in the interactive
menu and the --just-build sweep, which skips them when ESP-IDF is absent.
PlatformIO is only required when a PlatformIO board is chosen.

build-all-targets.sh also builds the LCD SKU. Both SKUs share
build/tdisplay_p4 and WADA_P4_LCD is read only at configure time, so each
P4 build reconfigures first; before this, the AMOLED entry rebuilt
whichever panel had been configured last.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 15:28:04 -04:00
Michael A. Cojocari a3090aebbe fix(tdeck-pro): split v1.0 and v1.1 targets 2026-09-23 16:43:29 -04:00
Kaj Schittecat c955c52aa0 Merge PR #550 from oumike: M9 navigation, Advert exit, T-Deck Pro/Max UX, backups and the timeout slider
Closes #548, #537, #553, #555, #556, #559, #560 and addresses #532.
2026-09-23 13:01:18 +02:00
Kaj SchittecatandClaude Opus 5 b2030528a0 site: a test-matrix card on the front page, and no GitHub token by choice
The matrix was only reachable from a corner button and a line buried in the
channel explainer. It now has a card in "Docs, tools and help", next to the
others, which is where people actually look.

The tracking issue is dropped: the matrix lives on the site and no write
credential for it exists anywhere. The publishing code stays in place and
dormant, so it is one line in /etc/wadamesh-reports.env if that changes, and
the service and deploy script now say publishes:false is the intended state
rather than a missing piece.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:57:18 +02:00
Kaj SchittecatandClaude Opus 5 a80a48988e touch: report a build from the device, and a QR that files a bug
Settings, About gains "Report this build": works or a problem, five tick
boxes for what you actually exercised, how long you have run it, an optional
line. It posts to the report service and lands on wadamesh.com/beta, which is
what the next promote is decided on. Ticking matters: "it works" from somebody
who watched it boot and "it works" from somebody who messaged on it all week
are not the same claim, and a board only goes green on two of the second kind.

"Report a bug" draws a QR for a prefilled GitHub issue form. The issue is filed
from the reporter's phone under their own account, so no write token has to
exist in a public firmware image and the reporter gets the replies.

"Count this device" is off by default. It lets the update check say which board
and version it is running, so a board with no reports can be told apart from a
board nobody owns. Those need opposite responses and nothing could tell them
apart before.

Mechanics: the POST rides the existing core-0 tile/update worker and its
WiFiClient/HTTPClient, like the version check, because a second pair on that
~8 KB stack overflows it. The device id is a salted SHA-256 of the public key
truncated to 64 bits, so a second report replaces the first without saying who
sent it. Sending is two taps and the second lists every field that leaves.
Prefs v64 appends report_ping + report_done_n at the tail, which the schema's
trailing static_assert now checks.

Also here: scripts/build/matrix-check.sh prints what testers reported for a tag,
and release.sh runs it before a --promote. It never blocks; a board nobody owns
can never go green. With no reports at all it now says so rather than reporting
a clean bill of health, which is the habit this is meant to replace.

Built on all eleven S3 envs and the T-Display P4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:29:20 +02:00
Kaj SchittecatandClaude Opus 5 3729c821b3 reports: a test matrix a beta can be promoted on
A beta goes stable today because it has been out a while and nobody shouted.
With 13 board images, most of them in hands we never hear from, "nobody
shouted" mostly means nobody with that board was listening. This makes the
evidence explicit: testers report per board per tag from the device, and the
promote decision reads off a grid.

The device cannot talk to GitHub itself. TLS does not fit (mbedTLS wants ~30 KB
of heap for a handshake and ~5 KB survives Wi-Fi association on the 2 MB
boards), and a token in a GPL image is a token everybody has. So the split is:

  * Structured test reports go to a small service on the firmware VPS over the
    plain HTTP the device already speaks, and it holds the only write
    credential. SQLite is the database; the per-tag tracking issue is rendered
    from it and rewritten in place, so GitHub can be down or rebuilt at will.
  * Bug reports do not come through here at all. The device draws a QR that
    opens .github/ISSUE_TEMPLATE/bug.yml prefilled with board, version and
    diagnostics, and the reporter files it under their own GitHub account:
    right attribution, GitHub's own spam controls, no token.

Green needs two separate devices whose owners ran the build for a day or more.
A board nobody runs cannot go green and does not block a promote; a board
somebody runs and has not vouched for does. That rule is the whole point: it
distinguishes untested from unowned, which "nobody shouted" cannot.

wadamesh.com/beta.html renders the same JSON for the promote decision.

Two things found while deploying, both repo-vs-box drift that would have bitten
somebody eventually:

  * The repo's copy of the firmware vhost was missing /apps/ and /bringup/,
    which had been added on the box and never committed. Deploying it would
    have 404'd the Lua app and language store for every device. The repo copy
    is now taken from the box, and the deploy script refuses to push a vhost
    that has fewer locations than the live one.
  * The repo's tile-transcode unit named a venv interpreter that does not exist
    on the box (python3.14 there has no ensurepip, so venv cannot bootstrap pip
    at all). The live unit uses the system python; the repo now says so too.

The firmware side (the report page, the QR, the opt-in ping) is not in this
commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:06:07 +02:00
Michael A. Cojocari 6d9c25d064 tools: add build upload monitor helper
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-09-21 14:30:15 -04:00
Kaj SchittecatandClaude Opus 5 5d5f7bc638 release: beta_84 notes, and let a promotion skip boards it predates
A board added mid-cycle (the T-Deck Max) has no images in an older tag, so
promoting that tag copied a file that does not exist and, with set -e, took
the whole promotion down. It is skipped with a note now, and the flasher
manifest generator leaves out any board with no image in the channel it is
writing, rather than handing the flasher a 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:39:22 +02:00
Kaj SchittecatandClaude Opus 5 9c47a9e50d touch: fixes on the merged PRs, and ship the T-Deck Max
Review of #531 turned up four things that had to be fixed before release:

- An unusable region name no longer discards the radio settings. The save
  returned early, so frequency, bandwidth, SF, CR and TX power were thrown
  away, and the rule rejects names with capitals or a "$private" scope, so
  anyone carrying an older region could not change their radio at all. On the
  pager that path is the silent blur save, so it failed with nothing on screen.
  Now only the region is skipped, and it says so.
- Restored useChainedFont() on the telemetry Show button: without the fallback
  chain that label is boxes in Russian, Ukrainian, Bulgarian, Serbian, Greek.
- Region scanning installs unknown repeaters as transient contacts so their
  encrypted replies can be matched. They were never removed, so each scan left
  up to 16 nameless entries in the contact table (and in Contacts). They are
  dropped when the scan ends or the page closes.
- One radio request per scan tick. The loop ran through all 16 repeaters in a
  single 200 ms tick, which is that many key derivations back to back.

The V4-R8 also did not build (its src/ files see a vendored lv_conf.h, so the
new text-size fonts were missing) and then did not fit at 101.3%. It builds at
85.6% now: the board no longer carries the compiled-in translations it
inherited from the V4, which it never needed, since with 8 MB of PSRAM its
store works like any other 8 MB board.

T-Deck Max (#545) joins the release matrix: build list, flasher manifest,
DEVICES.md and the site's board list. Board names in the flasher lost their
em dashes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:04:24 +02:00
Kaj SchittecatandClaude Opus 5 4df42eedf4 Merge PR #531 from oumike: device usability, input and accessibility
M9 Back and Bluetooth-keyboard Esc stop at the locked app-drawer root, M9
focus fixes, optional M5Stack CardKB on the V4 and V4-R8, V4-R8 touch and
text-size accessibility, Wio L2 SD retry, high-contrast day and night themes
(#544), channel region discovery (#541) and the Czech translation
contributed in #540 by brebtatv.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 13:54:09 +02:00
Michael A. Cojocari 36f9628e11 feat: add Czech translation 2026-09-20 20:45:14 -04:00
Kaj SchittecatandClaude Opus 5 6fe6b9f063 touch: beta_83, USB Files (files.wadamesh.com over the USB cable)
A built-in USB Files app (T-Deck and Heltec V4 for now) lets the page at
files.wadamesh.com browse, upload, download, rename and delete files on the
SD card, internal storage and the map tiles over Web Serial. File level, not
USB mass storage: the device keeps its filesystems mounted, the radio keeps
running, and the firmware enforces what may change. Live data (identity,
contacts, settings, history; /meshcomod on the card) is download-only.

- UsbFilesProtocol.h: framed messages (E7 5A, CRC32), a resyncing parser,
  path checks and the access policy; host tests in test/.
- UsbFilesSession: one request at a time (both Arduino USB serial drivers
  drop bytes when their RX queue is full), RX queue sized per session, SD
  data through a DMA-capable bounce buffer, FatFs listings with sizes, a
  beacon so the page never talks first, SD Scan's malware verdict per file.
- The companion link and MyMesh's console step off USB while it runs.
- Website: labelled side buttons, a USB Files button and card; the
  files.wadamesh.com page, vhost and deploy script.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 11:52:34 +02:00
Kaj SchittecatandClaude Opus 5 80f6aa97ea apps: SD Scan 1.1, buttons above the findings list
An infected M9 card turned up with 373 findings. Every list row is a focus
stop on a keyboard board, and the firmware's key navigation collects at most
160 of them per screen, so in 1.0 the Remove all and Scan again buttons below
the list could not be reached on an M9 at all.

1.1 puts the buttons above the list, first in focus order, on the results
and failed-removal screens, and shows at most 60 rows plus an "and N more"
row (the title carries the full count). App-only: no firmware change.

Harness: a 373-finding scenario, and a check on every list screen that the
buttons come first and the focus stops stay under 160. It fails on 1.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 09:13:43 +02:00
Kaj SchittecatandClaude Opus 5 6868911f59 touch: SD Scan, find and remove Windows malware on the SD card
Some ThinkNode M9 cards shipped with a dormant Windows worm (Elecrow
security advisory, September 2026). An infected card seen since carries
autorun.inf in the root, launching xlfqf.pif on open, explore and autoplay
with random-junk comment lines in between: the Sality autorun pattern.

- SD Scan store app (deploy/apps/sdscan/1.0, requires "sd", not seeded):
  walks the card a small page per tick, lists what it finds and why, and
  removes it after a confirmation screen with Cancel first. It says on
  every screen that it only removes files it recognises and that
  formatting the card is the safe fix. On older firmware it still finds
  threats by name but cannot remove them.
- Firmware: wada.sd.check(path) and wada.sd.remove(path), plus paging for
  wada.sd.list(path, start, max) and caps().sd_clean. What counts as a
  threat lives in SdThreat.h: autorun.inf, Windows program, script and
  shortcut extensions, or a real MZ+PE header under any name. remove()
  classifies again in firmware and refuses anything else, so no app can
  use it to delete tiles, backups or chat history. It clears read-only,
  hidden and system first, because FAT refuses to delete a read-only file.
- A warning when a card with Windows malware in its top folder is mounted,
  at boot or on insert, offering SD Scan (or the Store).
- Tests: test/test_sd_threat.cpp, and SD Scan harness scenarios including
  the real infected card's root. Removal checked on a T-Deck.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 13:33:30 +02:00
Kaj SchittecatandClaude Opus 5 2f6984443d touch: fix the chat page-scroll panic on long chats (#428, #475)
Pressing down past the last message page-scrolls the chat list with an
LVGL animation. In a long chat the list uses compressed scroll
coordinates, and chatVirtRemap1To1Scroll re-anchored the position on
every LV_EVENT_SCROLL with lv_obj_scroll_to_y(LV_ANIM_OFF). That deletes
the running animation from inside its own step. LVGL 8.4 reads the
animation again after the step, and when the step was also its last
(the UI loop was busy for longer than the animation) it finished the
freed animation and freed it a second time. By the next round that
memory belonged to something else, and anim_timer called a garbage
get_value_cb: the jump to 0x00020000 in the beta_79 and beta_80 M9 dumps,
both at the same call site.

- chatVirtRemap1To1Scroll follows a scroll that an animation drives and
  leaves the re-anchor to chatVirtOnScrollEnd. The page scroll now also
  completes on long chats; the early re-anchor stopped it after a frame.
- scripts/build/patch_lvgl_anim_uaf.py skips LVGL's completion check when
  the animation list changed during the step, as LVGL 9 does. Applied to
  every touch env as a pre-script and to the vendored P4 copy
  (fetch-deps.sh, build.sh). Idempotent, fails closed on source drift.
- test/lvgl_anim_uaf/run.sh reproduces it on the host under
  AddressSanitizer: stock LVGL with the old handler reports the
  use-after-free in anim_timer, and either fix alone runs clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 14:43:14 +02:00
Kaj SchittecatandClaude Opus 5 20d79edae9 release: publish the LilyGo T-Deck Pro as experimental
Adds LilyGo_TDeck_Pro_companion_radio_touch to release.sh (as
wadamesh-tdeck-pro), a flasher manifest labelled "(experimental)", and a
website card following the V4-R8 pattern: experimental in the heading,
"Partially supported", beta only.

The card says plainly what is known: contributed through #469, all the main
hardware works, but it has been tested on a single v1.1 unit, v1.0 units are
the least proven, and the e-paper display redraws rather than updating
instantly.

The site is not deployed with this commit: the card's install button points at
manifest-tdeck-pro.json, which only exists once a beta containing the board is
published.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 12:20:09 +02:00
Michael A. Cojocari 7cdc14a2df build: keep consolidated target builds green 2026-09-15 09:15:40 -04:00
Kaj SchittecatandClaude Opus 5 92b2ed12c9 Ship the Wio Tracker L2: release plumbing, not just the build
The PR added the board and its env, which makes it build. It does not make it
ship. Three lists decide that and none of them knew about it: release.sh ENVS
(what gets built and named into a release), gen-flasher-meta.py BOARDS (which
manifests the web flasher gets) and the flasher page itself, which lists boards
by hand.

Without these the board compiles cleanly forever and never appears in a release
or on the flasher, which looks like nothing is wrong.

Named wadamesh-wio-tracker-l2, its own Seeed Studio section on the flasher,
marked beta-channel-only like the Attaky was on arrival, since stable is still
beta_65 and this board has never been in a stable build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 23:59:06 +02:00