Files
wadamesh/deploy/apps
Christopher Van HooseandClaude Fable 5 cfb083e36f Lua host: keep keypad-nav focus off the app body; GPS Compass dial layout
On the ThinkNode M9 every Lua app opened on a white page: the app body is a
clickable object (touch boards need its press events) on the top layer, so
navCollect harvested it as a leaf focus target and navFocusCb's reverse-video
fill painted it solid under the app's widgets -- the canvas on top stayed
dark, which is what gave it away. NAV_SKIP_FLAG would also hide an app's own
buttons from the d-pad, so this adds NAV_PASSTHRU_FLAG (AppPage.h, shared by
both TUs): clickable, never a target itself, children still collected.

M9 compass: low-pass depth 8 at 50 Hz (the datasheet's 0x61 example) read as
sluggish on the dial; now depth 4 at 100 Hz (CTRL1 0x41, CTRL2 0x30). The
app ticks at 100 ms with lighter smoothing to match.

GPS Compass app rebuilt in the RF Monitor's look: a dial with rings,
10/30/90-degree graduations, red north, a lubber mark and the heading in
the centre; a key/value panel (FIX/LAT/LON/ALT/SPD/TGT) with a 10-cell
satellite meter; compact strings where the column is narrow at large fonts.
Confirmed on the M9 by Chris: the dial turns and calibration holds
(gpscompass.sav persists across reboots).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 01:32:57 -04:00
..

Submitting an app to the WADAMESH store

Apps are small Lua programs that appear in the device's Apps drawer and are downloaded over Wi-Fi from firmware.wadamesh.com/apps/. Snake, RF Monitor and Airtime all ship this way — they are ordinary submissions, not special cases, so reading their source is the fastest way to see what an app looks like.

Every submission is reviewed and safety-checked before it is added. What that means in practice is spelled out under Review below. It is not a formality and it is not a judgement of you — an app runs on other people's radios, so somebody has to read it first.

What an app is

One Lua file plus a small manifest. Apps talk to the firmware through the wada.* API — wada.ui (widgets, colours), wada.sys, wada.store (persistence), wada.timer. There is no arbitrary filesystem or network access; the API is the whole surface, which is what makes reviewing tractable.

Apps run on every board that has the Apps drawer, from the 2 MB-PSRAM Heltec V4 to the 800×480 Tanmatsu. Do not hard-code pixel sizes — read the screen from the API and lay out relative to it, the way snake.lua computes its grid.

Layout

deploy/apps/<id>/<ver>/<id>.json     manifest
deploy/apps/<id>/<ver>/<id>.lua      the app

<id> is lowercase, no spaces, and is the filename stem everywhere. <ver> is major.minor.

The manifest is one line:

{"id":"snake","name":"Snake","ver":"1.0","desc":"The classic, in Lua. Swipe to steer."}

desc is what people read in the store listing before installing, so make it say what the app does. One sentence.

Version directories are immutable. Once 1.0/ is published it is never edited — a change ships as 1.1/. Devices cache by version, so editing in place means some users silently run different code from others under the same version number.

Submitting

  1. Fork ALLFATHER-BV/wadamesh and branch off main.
  2. Add your deploy/apps/<id>/<ver>/ directory with the two files.
  3. Add or update your app's row in deploy/apps/apps.json (the store catalog).
  4. Open a pull request. In the description, say what the app does, which boards you tested it on, and anything it persists via wada.store.

Please open the PR even if you are unsure about the code — a rough app that works is easier to review than a perfect one that never gets sent. If you would rather not use git at all, open an issue with the .lua file attached and say so; we would rather have the app than the paperwork.

You keep authorship: merging the PR preserves your commits, and the store listing is generated from your manifest. The repository is GPL-3.0, so your app is published under that licence too — do not submit code you are not free to license that way.

Review

Two passes. The first is ordinary code review: does it work, does it fit the screen on a small board, does the description match the behaviour.

The second is the safety check, and it exists because an app ships to other people's devices. We read every submission for:

  • Identity and keys — an app must not read, log, transmit or persist the node identity, private key, channel secrets or contact keys. This is the one that gets a submission rejected outright rather than sent back for changes.
  • Flash wear and stalls — no writes in a tight loop and none on a per-packet path. Frequent small writes to internal flash trigger garbage collection, which on ESP32 suspends the flash cache and stalls both CPU cores; we have shipped two firmware bugs of exactly this shape. Persist on a user action or a slow timer, not on every frame.
  • Blocking the UI — no busy-waits and no long synchronous work. The UI and the mesh share a loop; an app that blocks it drops packets as well as frames.
  • Memory — bounded allocations, and nothing that assumes 8 MB of PSRAM. The V4 has 2 MB and is the floor.
  • Radio behaviour — an app may read counters and statistics. Transmitting, or changing radio parameters, needs a clear reason and an explicit user action.
  • Where data goes — anything leaving the device has to be something the user asked for and can see.

If something needs changing we will say what and why on the PR, and we would rather help you land it than close it. If we reject an app we will tell you the reason plainly.

Testing before you send it

Try it on real hardware, not just one screen size. If you only have one board, say so in the PR — that is useful information, not a disqualification, and it tells the reviewer what still needs checking.