Compare commits

...
140 Commits
Author SHA1 Message Date
Kaj SchittecatandClaude Opus 5 708f4434f5 touch: beta_73 release notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 10:32:19 +02:00
Kaj SchittecatandClaude Opus 5 875ac92a48 keyboard: let raw mode admit it guessed wrong (#341)
Vybo's older T-Deck types garbage on beta_71 and beta_72: "I get some keyboard
codes when typing". His controller has the pre-backlight firmware and does not
speak the raw column protocol, but the probe concluded it did.

A legacy controller answers a five-byte read with the pressed character in byte
0 and padding after it, and every lowercase letter has its high bit clear, so
"five bytes came back and no high bit is set" passes. Read as a column bitmap,
0x61 ('a') sets bits 0, 5 and 6 of column 0 and emits "q "; 0x6d ('m') emits
"qa ". That is exactly what he sees. Worse, the retry window I added in beta_72
gave a legacy controller more chances to look plausible, which is why it did not
help him.

The probe cannot fix this alone. Idle, both controllers answer with zeros, and
requiring proof of a real matrix before committing means an idle boot never
finds any, falls back to legacy, and everyone silently loses modifier latching.
Tried that first; it cost latching on a device where raw mode was working.

So the decision stays optimistic and becomes reversible. Raw mode now tests each
frame: three or more bits in byte 0, a printable value, and every other column
empty is not something a key matrix can report, but it is precisely an ASCII
character. On that, the driver returns the controller to key mode, switches to
legacy, and delivers the character.

Checked against the real tables rather than assumed: all 26 lowercase letters
set three or more bits, so any letter demotes on the FIRST press. Only '0', ' '
and '!' do not, and space renders correctly anyway since column 0 bit 5 IS
space. Going the other way needs three or more of {q, w, a, space} held at once
and nothing else; the printable-range test drops q+w+a (0x0B), and what remains
is a fumble that costs a reboot rather than a wrong character.

Worst case for a misdetected board is now one odd keystroke instead of a
keyboard that types nonsense until it is reflashed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 10:20:26 +02:00
Kaj SchittecatandClaude Opus 5 afecfc0224 i18n: two Hungarian strings pisti87 asked for (#340)
"Mark read" was an untranslated placeholder. "Join the public channel" had the
long form, which he wants shortened to fit the button.

His text for the second reads "nyílvános"; the file already uses "nyilvános"
everywhere else, so this follows the file rather than introducing a second
spelling. Easy to change back if the long i was deliberate.

The other line numbers in that issue are from his own build and no longer point
at what he means, so they need his source rather than mine to resolve.

Languages go to v20.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 09:38:22 +02:00
Kaj SchittecatandClaude Opus 5 2d94be4511 touch: beta_72 release notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:06:03 +02:00
Kaj Schittecat 41424ed5d2 Merge PR #337 2026-08-27 21:54:21 +02:00
Kaj Schittecat 523776eb0e Merge PR #335 2026-08-27 21:54:21 +02:00
Kaj SchittecatandClaude Opus 5 f880b5461f touch: restore accent popups for physical keyboards (#338)
Buko84 reports accent popups gone on beta_71, with the settings toggle doing
nothing. Introduced by the mention-autocomplete merge (#313).

composerSuggestRefresh() used to do both jobs in order: show the @mention picker
if the token warrants it, otherwise show the accent box. It was renamed to
composerMentionRefresh() and lost its accentBoxMaybeShow() tail. One of its two
callers got a replacement call added next to it; the other did not.

The one that did not is the composer textarea's own VALUE_CHANGED, which is
exactly the path a PHYSICAL keyboard takes. So accents kept working from the
on-screen keyboard and died on the T-Deck and the Pager, which is also why the
settings toggle looked broken: it gates a function nothing was calling any more.

Restored the fall-through. Calling it from both paths is harmless, since
accentBoxMaybeShow() hides the previous box before deciding whether to show one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 21:53:32 +02:00
Michael A. CojocariandClaude Opus 5 031b4bb1ba build: one script that compiles every target, both toolchains
"Does it still build?" spans two toolchains here. The eight S3 boards come from
platformio.ini, but the Tanmatsu and the T-Display P4 are standalone ESP-IDF apps
with their own build.sh wrappers — release.sh notes that in a comment and then
builds only the PlatformIO half. A change that broke an IDF-only board stayed
invisible until someone cut a release by hand.

build-all-targets.sh builds all ten, uploads nothing, and prints one table.

The env list is read from platformio.ini rather than hard-coded, so adding a board
to that file is enough and this cannot drift out of step with it (release.sh has
to hard-code its copy because it also needs the per-board binary names). A missing
project-local ESP-IDF is a SKIP rather than a failure, so a laptop with only
PlatformIO still gets the eight boards checked and a note pointing at
tanmatsu/fetch-deps.sh. Failures do not stop the run — which boards are broken is
the question being asked — and the exit status is non-zero if any target failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 15:24:32 -04:00
Michael A. CojocariandClaude Opus 5 45447caa7f touch: hand a contact to the node next to you (#321)
The contact action sheet could message, ping, telemetry, range-test, favorite,
share location, reset path, block and delete — but not hand the contact itself
to anyone. The plumbing was already there and only the companion protocol could
reach it: shareContactZeroHop() has backed CMD_SHARE_CONTACT all along.

So this is a button and a wrapper. uiShareContact() sits next to
uiResetContactPath() and looks the contact up in the live table the same way;
actionSheetShareContactCb mirrors actionSheetResetPathCb exactly — fetch by
index, close the sheet before acting, toast the result. No refreshContactsList():
unlike Reset path and Delete this does not touch the contact table, it only puts
a packet on the air.

Zero-hop, deliberately. Flooding a third party's advert spends the whole mesh's
airtime on a packet nobody asked for, and it re-advertises someone else's node
well beyond the room you are standing in. Zero-hop is what the companion command
already does and keeps the action to "hand this to whoever is next to me". A
flood variant is a different airtime trade-off and does not ride along with this.

Gated on !from_map like Share my loc and Block, so the map-marker sheet stays
compact, and placed after Reset path so Block and the full-width Delete keep the
bottom of the sheet.

grid_items goes 6 -> 7 for the non-from_map case. That is housekeeping, not the
fix — as the #306 note at the bottom of the function says, scrollability is
decided from the height the buttons actually reached, and that is untouched. The
#266 Share my loc row is still missing from the same tally; fixing it here would
widen the diff into behaviour this issue put out of scope.

Three new strings across the thirteen language files (Contact gone already
existed), inserted in sorted position and translated in each file's own style for
its neighbours — Contact added for the success toast, Send failed / Save failed
for the failure one, Share QR / Share channel for the button. i18n_builtin.h is
regenerated, not hand-edited; it costs ~2 KB of .rodata, which the V4 feels most.

Audit clean on all thirteen (1034 -> 1037 keys). T-Deck and Heltec V4 TFT build.
Not yet checked on hardware: a second node in direct range actually adding the
contact, and the smallest panel at the largest UI scale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 15:24:32 -04:00
Kaj SchittecatandClaude Opus 5 6aad8bf1ad console: never offer a mode the board cannot be typed into (#334)
gadgeteerza's ThinkNode M9 entered console mode on beta_70 and could not leave.
The prompt painted, "type 'ui' to go back" was on screen, and no key did
anything. A power cycle came straight back, the pinhole reset came straight
back, and reflashing failed. From the user's side the device was gone.

CAP_CONSOLE was gated on DISPLAY_CLASS: it reasoned entirely about whether
there was something to draw on, and never about whether the user could type.
The console has exactly two input drains, the T-Deck keyboard and the on-screen
keypad behind CAP_TOUCH. The M9 has an I2C keyboard and no touchscreen, so it
had neither, and nothing catches this at runtime either: the panic self-heal
only fires on ESP_RST_PANIC, and a console with no input has not crashed.

Two changes. The M9's keyboard is drained in the console loop, so that board
keeps the feature. And CAP_CONSOLE now requires CAP_CONSOLE_INPUT as well as a
display, so a board with no drain does not offer the mode at all rather than
offering a one-way door.

That guard immediately caught a second one: the T-Lora Pager has a keyboard, no
console drain for it, and was one Settings toggle away from the same state. It
no longer shows the option.

Built on all eight S3 envs and both ESP32-P4 targets. Verified by string
presence per image: T-Deck, M9 and V4 keep console mode; the Pager no longer
carries it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 21:21:40 +02:00
alphalord336 30bbefc066 Merge branch 'ALLFATHER-BV:main' into main 2026-08-27 18:17:41 +02:00
Kaj SchittecatandClaude Opus 5 799756cd94 i18n: the signal card's own strings were never wrapped
pisti87 pointed at UITask.cpp:22021 twice, and he was right both times. sigCell()
does not translate its argument, so "Signal", "Signal (stale)" and "nothing heard
yet" were raw at the call site and the card read English in every language.

Easy to miss because the home-graph signal popup has its own TR()'d copies of the
same three strings, so the text is translated in one place and not the other. It
also explains why "nothing heard yet" matched no key when his translation for it
did not appear: there was no key, only a literal.

Hungarian supplied by him.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 17:41:31 +02:00
Kaj SchittecatandClaude Opus 5 11d826bdfe touch: beta_71 release notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 13:52:38 +02:00
Kaj SchittecatandClaude Opus 5 f49a950e30 lua: wada.ui.clear(), so an app can have more than one screen
The SDK documented building widgets in on_open() and gave no way to take them
down, so an app with a second screen drew it on top of the first. pisti87 hit
this building a multi-screen app and had been working around it with buttons;
he also noted that ui.list() has clear() while the page it sits on does not.

The reason this is not just lv_obj_clean() is the handles. WidgetUd holds a raw
lv_obj_t*, guarded only by `if (u->obj)`, so a Lua variable still referring to a
label from the screen just cleared would sail past that check into freed memory.
Every handle now records the generation it was created in, clear() bumps the
generation, and the accessors null the pointer of any handle from an older one.
The null guard that every method already has then turns a stale call into a
no-op. Given the day this codebase has had with use-after-frees, a clear() that
invited one would not have been worth shipping.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 13:02:15 +02:00
Kaj SchittecatandClaude Opus 5 80b9fd1693 lua: let an app reach all its contacts, and write a bigger app
Both reported by Jade, and both were arbitrary caps rather than real limits.

wada.mesh.contacts() scanned the first 200 contacts, returned at most 100, and
said nothing about having truncated. On a device holding 2000 contacts most of
them were simply unreachable. It takes an offset and a limit now, defaulting to
the old 100 and capped at 250 per call, because every entry is an eight-field
Lua table and building thousands in one go would exhaust the per-app heap. The
window moves, so everything is reachable by asking more than once, and the new
wada.mesh.contact_count() means an app can page without probing for the end.

The app source limit was 64 KB, which an ordinary program can reach. It is
192 KB now. The source sits in PSRAM only until luaL_loadbuffer has compiled it,
so this is a transient allocation, not a per-app cost, and the compiled chunk
still has to fit the 256 KB app heap. The Store's download buffer was the other
half of that ceiling and moves with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 12:23:16 +02:00
Kaj SchittecatandClaude Opus 5 2df6f087eb keyboard: do not decide the T-Deck's capability on one I2C read (#332)
jrote1 flashed the June 2025 C3 keyboard firmware, which supports raw column
frames, and still got no modifier latching.

The probe asked for a raw frame exactly once, on the first poll after boot, and
anything other than five bytes with every high bit clear committed the device to
legacy mode for the rest of the session. The first I2C read after boot is the
least trustworthy one there is: the C3 is still starting, so a short or garbled
frame is ordinary rather than exceptional. There was no recovery except a reboot,
and a reboot re-rolls the same dice.

It now retries for 1.5 seconds before settling for legacy. A single-byte answer
is still delivered as a keystroke while probing, so nothing typed in that window
is lost, and a genuinely old controller ends up in the same place a little later.

The fallback message also says what it actually saw -- how many bytes came back,
and whether a column had its high bit set. "Update your keyboard firmware" to
someone who just did is not a diagnosis, and this is the same lesson as #274:
a failure path that says nothing produces a bug report with nothing in it.

Verified on a T-Deck with the newer firmware: still raw mode, latching works.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 12:08:42 +02:00
Kaj SchittecatandClaude Opus 5 867030ab58 touch: beta_70 release notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 10:55:20 +02:00
Kaj SchittecatandClaude Opus 5 2475cba5e7 store: do not offer an app the board cannot run
beta_69 published Wardrive and Nearby. Both need the extended SDK, and the
Heltec V4 does not have it, so the most common board in the mesh showed a
prominent Get button for two apps that download, install, open, and then refuse
to do anything. matthewjk reported exactly that on Discord and had to be told it
was a hardware limit.

An app can now declare `"requires"` in the catalog. The Store greys the button,
labels it N/A and says so on the row, rather than letting someone spend a slow
download to find out. Wardrive and Nearby declare sdk_ext.

An unknown requirement allows the install: a newer catalog must not disable apps
on firmware that has never heard of the capability name, which would be exactly
the wrong way round.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 10:54:24 +02:00
Kaj Schittecat 65ea09ea89 Merge PR #316: WAV/MP3 playback for Lua apps
oumike. Closes #315 (pisti87's request).

Two conflicts, both resolved by keeping BOTH sides rather than choosing:

  - sdRuntimeLifecycleBusy() gained an audio-playback source here and a web
    reader source in #317. They are independent consumers of the same card and
    both have to gate the mount lifecycle. The reader's self-exclusion is kept:
    it calls this from its own task while holding the card and would otherwise
    deadlock against itself.
  - The Lua harness caps table needed sd_list from #312 as well as the audio
    flags, and the test order needed the wardrive suite from #324 as well as
    audio_api.

Built on all eight S3 envs and both ESP32-P4 targets.
2026-08-27 10:49:59 +02:00
Kaj Schittecat 2cd6f93789 Merge PR #320: resolve the keyboard-modifier conflicts against #326
#326's compat stubs were placeholders for exactly the host-side modifier state
this PR implements, so pr/320's side wins in all three files.
2026-08-27 10:36:25 +02:00
Kaj Schittecat 9fb65f91c4 Merge PR #320 2026-08-27 10:28:55 +02:00
Kaj Schittecat 0987f1385f Merge PR #317 2026-08-27 10:28:15 +02:00
Kaj Schittecat eaae4374fb Merge PR #319 2026-08-27 10:28:15 +02:00
Kaj Schittecat 159d5bb709 Merge PR #324 2026-08-27 10:23:29 +02:00
Kaj Schittecat 6faeddd472 Merge PR #328 2026-08-27 10:23:29 +02:00
Kaj Schittecat a67fa69b75 Merge PR #326 2026-08-27 10:23:29 +02:00
Kaj Schittecat c2ac83b3e0 Merge PR #325 2026-08-27 10:23:29 +02:00
Kaj SchittecatandClaude Opus 5 cecede23be i18n: undo the keys my extractor invented, and stop it inventing more
pisti87 read v18 and called it chaos. He was right, and it was mine.

Two defects in the extractor I added yesterday:

  - It joined every string literal in a call argument, so a ternary became one
    key. `cut ? "Paste (move)" : "Paste (copy)"` shipped as the single key
    "Paste (move)Paste (copy)", and with it "Unblock  Block",
    "Unfav  Favorite", "Other networksNetworks", "Batteryactivityon" and
    "Stop sharing loc  Share my loc". None of those strings exist anywhere in
    the firmware. Literals are now grouped only when genuinely adjacent, which
    is what the compiler concatenates, so both branches become their own key.

  - It scanned raw source, comments included. That is how "Geblokkeerde
    gebruikers" -- Dutch, appearing only inside a comment about how a long
    translation degrades -- became a KEY in the Hungarian file. Comments are
    stripped now, string literals preserved.

202 invented rows removed across the thirteen files. Only rows that were both
unknown to the extractor AND still untranslated were touched, so no
translator's work could be lost either way.

Also his: the curly quotes in the Hungarian credits render as boxes because no
bundled font carries U+201E/U+201D. Five values de-curled. And five strings he
found raw are wrapped: the Wi-Fi rescan and hidden-network rows, the update
check, and the downgrade prompt. The two Wi-Fi rows build their label at
runtime, since TR() returns a pointer and cannot join a glyph literal at
compile time.

Languages go to v19. v18 is deleted rather than left behind: it was only ever
correct for about a day and everything in it is superseded.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 10:23:09 +02:00
Kaj SchittecatandClaude Opus 5 1ca1eab219 touch: a widget's last blur is its destructor, not a user (#330, #314)
dreirund's beta_69 core dump decodes cleanly. Open Radio & mesh, go to Known
regions, add and remove a few, leave the page: the device crashes and reboots.

obj_del_core sends LV_EVENT_DELETE, then runs the destructor, and the
destructor's lv_group_remove_obj refocuses the group. That delivers
LV_EVENT_DEFOCUSED to the object which is already half torn down. Seven
handlers in this file save on blur, and the one bound to the signal-poll
interval field did exactly what it is supposed to: read the textarea's text,
clamp it, write it back, and raise a toast -- on memory the destructor was in
the middle of freeing.

The regions overlay is deleted asynchronously, which is why it takes leaving
that page rather than opening it, and why it looked like the page itself was
broken. pisti87 reported the same screen as impossible to exit in #314, which
is the same crash seen from the other side.

DELETE always arrives before the destructor, so the fix is to record the object
in a DELETE handler and have every save-on-blur handler ignore a blur for it.
The handler goes on every settings field via attachSettingsTaEvents rather than
only the ones that save, since that is what makes the signal reliable, and the
recorded pointer is only ever compared, never dereferenced.

Decoded against a beta_69 T-Deck ELF rebuilt from the tag:
  radioSigPollSaveCb <- event_send_core(LV_EVENT_DEFOCUSED)
                     <- focus_next_core <- lv_group_remove_obj
                     <- lv_obj_destructor <- obj_del_core <- lv_obj_del_async_cb

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 10:16:25 +02:00
Michael A. Cojocari 8084955e04 Merge 2026-08-26 19:58:30 -04:00
Michael A. Cojocari 020c183937 Add M9 and Pager screenshot controls
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-25 19:04:00 -04:00
Michael A. Cojocari b5a8c99f55 Complete ThinkNode M9 keyboard parity
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-25 16:59:15 -04:00
Michael A. Cojocari 2a6aa57978 Reopen chat keyboard on composer tap
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-25 16:29:47 -04:00
Michael A. Cojocari 9791238066 Add keyboard modifier transition hooks
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-25 16:12:37 -04:00
Michael A. Cojocari 417a52caa1 Fix Wardrive UTF-8 text handling
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-25 16:12:24 -04:00
Michael A. Cojocari 5c029e7526 Latch keyboard symbol modifiers
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-24 15:09:53 -04:00
alphalord336 3dee9d62e7 Update battery voltage calculation formula 2026-08-24 19:49:47 +02:00
Tesso M Costa 190e73498c Merge branch 'main' into at-glance
# Conflicts:
#	src/ui-touch/UITask.cpp
#	src/ui-touch/extras_lat_20.c
#	src/ui-touch/extras_lat_28.c
2026-08-24 09:39:34 -06:00
Tesso M Costa 3307d87e9c touch: add master "At a glance" toggle, move while-locked switch under it
Options > Display previously only had "At a glance while locked"
(opt-in, off by default). Add a master "At a glance" switch above it
(on by default, matching the previously-unconditional behavior) that
gates the whole feature, and move the while-locked switch out of
Options > Lock screen to sit under it.

The while-locked switch's own saved preference is left alone when the
master is toggled off -- only its editability follows the master, so
re-enabling the master always restores its true prior state rather
than resetting it.

Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>
2026-08-24 09:03:41 -06:00
Michael A. Cojocari 9d7d1f2df7 Add SD home page to web reader
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-23 21:40:52 -04:00
Michael A. Cojocari acdcc6e7fc Work 2026-08-23 20:32:26 -04:00
Kaj SchittecatandClaude Opus 5 6ed73b290a Merge PR #313: @-mention autocomplete in the device composer and the web chat
oumike. Closes #301.

Suggestions come from identities whose named adverts the device actually heard
this session, not the stored contact list, so the list stays short and is
evidence the node is reachable rather than a name someone once saved.

The advert-path cache it reads was 16 entries with no validity flag and no
ordering beyond insertion, so it grew an explicit used flag, the advertised node
type and a monotonic receive sequence. Reads take a snapshot under a short
critical section and sort it outside the lock, which is the right shape: the
cache is written from packet receive and read from the UI thread.

Token parsing works from the real LVGL caret through a UTF-8 codepoint-to-byte
conversion rather than assuming one byte per character, does not fire on
email-like text, and replaces only the active token.

Built on all eight S3 envs and both ESP32-P4 targets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 13:06:59 +02:00
Kaj SchittecatandClaude Opus 5 e6678b8fe7 release: keep the firmware push away from the app store
The Lua app and language store shares a document root with the firmware but is
published by deploy-apps.sh from deploy/apps/, which is the canonical copy.
release.sh pulls the published tree into out/firmware/ before building, so
apps/ arrives as a local mirror, and the push at the end sends that mirror
back.

Today that reverted the store to sdktest 1.2 and language v15 and removed two
apps, minutes after deploy-apps.sh had published sdktest 1.6, language v18,
airtime 1.4 and gpscompass. It is also the same stale directory that
gen-lua-builtin.py was reading until yesterday, so this mirror has now caused
two separate failures and holds nothing anyone wants.

Excluded in both directions. The firmware release never publishes the store.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 10:39:43 +02:00
Kaj SchittecatandClaude Opus 5 0c158d0bce touch: the app-permission switches packed the app index over the probe bit
Reported on Discord: granting an app full permissions and then watching
wada.mesh.send come back "permission denied", with no dialog ever shown.

The Settings switches pack (app index, permission bit) into one pointer as
(i << 4) | bit. LUA_PERM_PROBE is 16, which does not fit in four bits, so the
probe switch overflowed straight into the index field: toggling it for app i
decoded as app i+1 with bit 0. That changes no permission, but it still writes
app i+1's record, and the mere presence of a record means "asked".

An app that has been asked and not granted is refused outright rather than
prompting, which is the correct rule and exactly what made this invisible: an
app the user had never touched became permanently unable to send, silently,
because they flipped a probe switch on the app above it in the list.

The shift is 8 now, with a static_assert tying it to the widest LUA_PERM_* bit
so the next permission added cannot reintroduce this. Anyone already affected
can flip the switch in Settings > App permissions, which now writes what it
says it does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 10:35:39 +02:00
Michael A. Cojocari 50473b16d2 Merge remote-tracking branch 'upstream/main' into 301 2026-08-22 18:33:35 -04:00
Kaj SchittecatandClaude Opus 5 6dd1e2514b console: the exit bridge must not sit behind CAP_TOUCH
The extern for consoleHostRebootToUi went inside the CAP_TOUCH block, so the
M9 (console, no touchscreen) stopped compiling. Every board with a console can
leave it; the declaration follows CAP_CONSOLE's reach, not the panel's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:51:32 +02:00
Kaj SchittecatandClaude Opus 5 9343e27bba touch: beta_69 release notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:42:43 +02:00
Kaj SchittecatandClaude Opus 5 e9bf6d9e17 console: make ui actually leave console mode
Typing `ui` or `exit` rebooted straight back into the console.

touchPrefsSetConsoleMode() does not write the pref, it QUEUES an A/B snapshot:
SdNvsPrefs deliberately keeps filesystem I/O off the calling thread, and
touchPrefsFlush() is what forces the queue out. The console called
ESP.restart() directly, so the queued write was discarded and the next boot
still read "console". The Settings toggle never showed this because it goes
through rebootDevice(), whose last act is that flush.

The console now exits through the same path, which also means it leaves on the
same terms as everything else: chat history, the Discovered ring and the sync
replay ring are persisted first. rebootDevice()'s save-failure branch called
lv_refr_now() unconditionally, which is not survivable with no LVGL, so that
one call is now conditional; showAlert was already console-aware.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:34:50 +02:00
Kaj SchittecatandClaude Opus 5 c2357f032e mesh: stop prefixing a guest LOGIN on requests to plain chat contacts (#293)
christianprim reported that on a T-Deck, telemetry for a contact fails and that
contact's position never updates on the map, while the phone app gets both from
the same contact.

Every device-originated STATUS and TELEMETRY request chains a blank-password
LOGIN in front of the request. That exists for a good reason: a repeater will
not decrypt a PAYLOAD_TYPE_REQ from a sender that is not in its ACL, and the
ACL is only populated by handleLoginReq. But it was applied to every contact
regardless of type, and a chat contact is another companion, which has no LOGIN
handler at all.

The two fire-and-forget helpers merely wasted a packet. The manual Request
button goes through uiSendRequestAfterGuestLogin, which deliberately does NOT
send the request until the LOGIN is acknowledged -- so against a companion it
armed a wait for a LOGIN-OK that can never arrive, the request was never sent,
and the deadline expired as a failure. The phone app sends the request directly,
which is why it always worked.

The stale map position is the same bug: a contact's position is refreshed from
the CayenneLPP GPS field in a telemetry reply, and there was no reply.

contactNeedsGuestLogin() now decides, and it decides on the only thing that
matters: whether the far end keeps an ACL. Repeaters, room servers and sensors
still get the LOGIN; chat contacts get the request itself, immediately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:12:59 +02:00
Michael A. Cojocari ab5be7764e Work 2026-08-22 17:09:51 -04:00
Kaj SchittecatandClaude Opus 5 c044f75d11 i18n: pisti87's Hungarian for the strings the audit could not see (#294, #277)
33 of the pairs he posted apply directly to keys that only became visible when
the extractor learned about helper-wrapped and table-held literals. The rest
did not, and the reasons are worth recording rather than dropping:

  - Four were escaped in his markdown, so the key read `Node\\nRegion` against a
    real key of `Node\nRegion`. Matched after unescaping.
  - `Export crash report` is `Export crash report (%uK)` in source; the size is
    part of the label. Applied with the conversion appended.
  - `Distance` and `Heard` are column headers he read off the screen; the keys
    are `Distance: km` and `Recently heard`. Not guessed.
  - `Sent only when that contact asks...` is a translation of wording the
    English has since changed. Applying it would ship a Hungarian sentence that
    no longer describes what the setting does.
  - `nothing heard yet` and `Other (hidden) network...` match no key at all,
    which usually means a raw string somewhere the audit still cannot see.

88 Hungarian rows are still English: the remainder of the newly visible keys,
plus console mode, which is new.

Languages go to v18. The v17 snapshot is deleted rather than kept: it was cut
before the audit fix added 116 keys, so it was already wrong, and it never
reached a device.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:06:11 +02:00
Kaj SchittecatandClaude Opus 5 a63e35bdaa touch: only offer Power off where something can wake the device (#310)
wb6zsu found the T-Display P4 freezes on Home > Cmdr > Control > Power > Power
off, recoverable only with the hardware switch, under a toast telling him to
click a trackball the board does not have.

Both halves are the same bug. The wake source is armed inside `#if
defined(PIN_USER_BTN)`, which platformio.ini sets per env and the two ESP32-P4
targets never see, so the P4 ran esp_deep_sleep_start() with no wake source
configured: the device is off and nothing short of the switch brings it back.
That is not a freeze, but it is indistinguishable from one.

The Power-off row was gated on `!HAS_THINKNODE_M9` instead -- a board name
standing in for "has a wakeable button", correct for the one board it was
written against and silently wrong for every board added since. It now follows
PIN_USER_BTN, the same symbol that arms the wake, so the row exists exactly when
it can be undone: the M9, the P4 and the Tanmatsu drop it, and any future board
gets the right answer without anyone remembering this.

The toast names the control the board actually has rather than assuming a
trackball.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 23:02:21 +02:00
Kaj SchittecatandClaude Opus 5 e3c9f9b2cb Merge PR #292: ThinkNode M9 compass (QMC6309), GPS motion in the SDK, GPS Compass app
cvhviz. The M9's magnetometer was documented on the board and nothing had ever
talked to it. The driver is written from the datasheet's register map rather
than SensorLib, whose setOutputDataRate() writes the ODR into the OSR bits, and
the axis orientation is measured on hardware at four headings rather than
inherited from a declaration Meshtastic marks unverified and never uses. The
+-32 G range looks absurd for a 0.5 G planet until you measure the board's own
hard-iron bias at about 7x Earth's field.

Also carries several fixes found while testing on hardware: every Lua app opened
on a white page on keypad-nav boards (the focus highlight harvested the app body
as a target and reverse-video filled the page), a use-after-free in the Lua net
worker when an app closed mid-request, an unfreed http_get buffer, canvas pixel
buffers GC'd while LVGL still drew from them, one RTC I2C read per contact, and
map re-open costing 2.5 s on every visit.

Three changes on merge:

  - The map tile-keep gate read `total && total < 4 MB`, so a board reporting
    zero PSRAM -- the most constrained case there is -- landed on the roomy side
    of the test and kept its tiles. Dropped the non-zero guard.
  - gpscompass is 55 KB of Lua, more than every other app combined, and it wants
    a magnetometer the seeded boards do not have. The author deliberately left
    it out of lua_builtin.h; that intent now lives in the catalog as
    "seed": false rather than in whether someone remembers to regenerate, since
    the generator runs from a pre-build hook as of this branch.
  - consoleModeToggleCb was defined inside a !HAS_TANMATSU region while the
    Settings row that binds it compiles on every board, so the Tanmatsu link
    broke. Moved it out. The console boot path is gated on CAP_CONSOLE alone, so
    the switch now does what it says there too.

Built on all seven S3 envs plus both ESP32-P4 targets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 22:54:26 +02:00
Kaj SchittecatandClaude Opus 5 eb439c8baa i18n: find the strings the audit could not see, and the apps it never checked
pisti87 reported a long list of text that stays English whatever the language,
and said the strings were in his language file and still did not appear (#257).
Both halves are true, and the reason is the audit.

The extractor only ever recognised TR("literal"). Three very common shapes were
therefore invisible:

  mk_row_btn("Reload tiles in view", cb)      // helper TR()s its parameter
  for (auto& r : rows) TR(r.label)            // literal lives in a local table
  TR(contactsSortOptName(m))                  // helper returns one of several

All three translate correctly at runtime, so the source looks properly wrapped.
But the literal at the call site was never emitted as a key, so it never entered
a .lang file, so no translator could ever supply it -- and adding it by hand
did nothing, because the audit's key list is what the files are checked against.
That is 51 strings across the map options sheet, the sort sheets, the contacts
filters and the home launcher.

The audit now understands all three, plus tr("...") in the Lua apps, and the
newly visible keys are in all thirteen files as placeholders so translators can
see them. 1017 keys, up from 966.

Four strings were genuinely raw and are now wrapped: the reader's idle status,
the Discover empty feed, the crash-report export button and Paste (move/copy).

Lua apps had no way to translate anything at all, so every built-in was hard
English regardless of the device language. wada.sys.tr() gives them the same
table the interface uses; airtime 1.4 is the first to use it, with the
`sys.tr or identity` fallback so it still runs on older firmware.

Two more instances of the drift this issue is really about:

  - gen-lua-builtin.py read out/firmware/apps/, which nothing writes -- the
    deploy rsyncs deploy/apps/ straight to the VPS. So the mirror was stale and
    the two apps added in beta_68 were never baked in: boards that cannot reach
    the Store shipped without them. It reads the canonical directory now, and
    regenerates from the same pre-build hook as the language table.
  - Baking a row whose translation equals its key does nothing, since TR()
    returns the key on a miss. Skipping them takes the header from 1.11 MB to
    939 KB and gives the V4 back 16 KB of flash, which matters at 89%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 22:29:05 +02:00
Kaj SchittecatandClaude Opus 5 a9cff6f113 i18n: translate the map credits sheet, and make the baked table follow the files
The map About/credits sheet was 820 bytes of raw English built with snprintf and
no TR() anywhere in it, so it stayed English in every language (#257). It is now
three keys: the two attribution headers (the OpenTopoMap variant is credited
separately because its style is CC-BY-SA) and the body, kept whole rather than
split per paragraph so translators get prose instead of fragments. The buffer
grows 820 -> 2048 because Hungarian runs about 1.5x English here and the
Cyrillic and Greek files are two bytes a letter.

Hungarian text from pisti87 (#257). Two edits to what he posted, both flagged on
the issue: the hard line breaks he inserted at the English wrap points are gone,
because the label wraps itself and a fixed break lands mid-sentence on any other
panel width; and the header reads "Terkep adatok" rather than "Map adatok",
which looked like a copy-paste artifact given the rest is fully translated. The
OpenTopoMap variant is derived from his own wording and is his to correct.

Also raw, from the same report: the Discovered auto-add hint and the four type
words it interpolates. The hint buffer goes to 240 bytes and the type list to
128, since the translated plurals are longer than "chats, repeaters".

The reason none of that would have shipped: gen-lang-builtin.py exists so the
baked-in table and the .lang files the store serves cannot drift, and its
docstring promises a pre-build step that runs it. Nothing ran it. Editing a
.lang and building produced an image carrying the OLD translations, silently.
It is now a real pre: hook on all seven PlatformIO envs and a line in both IDF
build scripts, regenerating only when a .lang is newer than the header.

deploy-apps.sh grew the matching check for the other half of that path: a
catalog version that disagrees with the file's own "# ver:" publishes
translations to a version no device asks for.

All thirteen languages snapshot to v17 -- the merged region and SD work added
keys to every file, not just Hungarian.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 22:06:39 +02:00
Kaj Schittecat 8cd8a5366c Merge PR #311: pick a region from a known-regions list
oumike. Closes #271.

Region presets stop being freq/BW/SF typed in by hand: the list carries the
legal frequency and duty-cycle for each region, so picking one sets a
coherent set rather than three fields that have to agree.
2026-08-22 21:48:52 +02:00
Kaj Schittecat 919544de2a Merge PR #312: wada.sd.list() read-only SD directory listing
oumike. Closes #309 (pisti87's request).

Bounded to 192 entries, card-rooted paths validated, and it reuses the existing
SD mount and health lifecycle rather than opening its own.
2026-08-22 21:44:59 +02:00
Kaj Schittecat a359de0c18 Merge PR #291: Pager feature gaps + finish the CAP_SD gating
oumike. Verified the reported regression is real: e2d07d8 converted two of the
regions guarding 'Save update bin to SD' to CAP_SD && CAP_OTA and left another
on the old three-board list, which excludes the T-Lora Pager.

Closes #289.
2026-08-22 21:42:48 +02:00
Kaj SchittecatandClaude Opus 5 b1beb4e4ff discover: back off the sweep instead of probing every 4 s forever
Reported from a regional packet monitor: a burst of unattributable Control
packets whenever someone had WadaMesh Discover open. Correct on both counts.
They are ours, and they cannot be attributed: a NODE_DISCOVER_REQ carries a type
filter, a random tag and a since-timestamp, and no sender identity at all.

The page swept every 4 seconds for as long as it stayed open, and scanning
defaults to ON when it opens. A probe is not one packet: it is our zero-hop
broadcast PLUS a reply from every node in earshot. So an open Discover page put
a burst on the whole neighbourhood every four seconds, indefinitely.

Worth noting the inconsistency that made this obvious: wada.mesh.discover()
enforces a 15 second floor on third-party apps, with a comment explaining that a
probe spends everyone else's airtime. The built-in was doing it nearly 4x
faster.

Now 4s, 4s, 8s, 15s, then 30s. The first seconds are when someone is actually
looking, so those stay fast and the steady state goes quiet. Opening the page or
pressing Scan resets to the fast cadence, because both mean somebody is looking
again. The existing TX-budget gate is unchanged.

Reported by kevin77.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:40:20 +02:00
Kaj SchittecatandClaude Opus 5 0a7a25324b console mode: label it experimental where it is switched on
Both toggles (Settings > General and the VNC page) now say EXPERIMENTAL on the
row itself, not only in the paragraph under it, and the description mentions the
self-heal so the risk reads as bounded rather than vague.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:31:35 +02:00
Kaj SchittecatandClaude Opus 5 93f1934889 console mode: the console was painting on a WHITE background
That is why the greens were unreadable, and it was my mistake at the root: I
built a light-on-dark palette and then painted it onto whatever UIColor
resolved to.

src/helpers/ui/UIColorPalette.cpp defines wadamesh's dark palette and its own
comment warns that the core's driver .cpps 'carry upstream definitions that stay
unlinked only while nothing references them'. The core's ST7789LCDDisplay.cpp
sets window_bkg = WHITE. The console referenced UIColor and got that one.

Fixed by not depending on which definition wins: the console now owns both ends,
painting its own near-black background and its own RGB565 palette, with the
values taken from the firmware's actual theme colours rather than invented neon.
Only the e-ink fallback still consults UIColor, where a single ink colour is the
correct answer.

Banner: the slash-and-underscore figlet art was a smear at a 6 px cell on a
240 px panel. Replaced with a ruled header, which reads at any size on any
board. A login banner exists to say what the machine is, legibly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:27:28 +02:00
Kaj SchittecatandClaude Opus 5 4b5b51ef01 console mode: three colours per line, trackball scroll, shell prompt, visible banner
Colour, properly this time. A line can carry THREE coloured segments, because
the three parts of a message answer different questions: WHERE it arrived
(channel, cyan), WHO said it (sender, yellow) and WHAT they said (grey). A DM
has no channel, so its sender takes the magenta slot and stands out in a busy
feed. Same treatment for stored history, contacts and unread.

The palette is explicit RGB565, deliberately NOT the UIColor theme names:
several of those resolve to the same value on a given board, so 'channel' and
'sender' would have come out identical. e-ink falls back to one ink colour,
where anything else would be invisible.

Banner: it WAS printing, just scrolling off. Boot output was seventeen lines on
a panel that fits fewer. The art is now three lines, identity is one, and the
menu is three-per-row instead of two, so the whole thing fits.

Prompt: 'node:recipient$' instead of a bare caret. Where you are and who you are
talking to is what a shell prompt is for, and 'to <name>' now visibly changes it.

Trackball scrolls the scrollback, accumulated so one flick does not race past
everything, and it wakes a dark screen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:19:31 +02:00
Michael A. Cojocari b04ae358b2 feat(lua): add read-only SD directory listing (#309) 2026-08-22 15:17:54 -04:00
Kaj SchittecatandClaude Opus 5 a1916cfcc7 console mode: screen timeout and keyboard backlight
Neither ran. Both live in UITask::loop() below the console early return, so the
panel stayed lit indefinitely (battery, and burn-in on the panels that suffer
from it) and the keyboard never lit at all.

Console mode now does both itself, using the same prefs and helpers as the UI:
* Idle past the screen-timeout setting -> backlight off, CPU to 80 MHz, and the
  render is skipped entirely while dark. There is nothing to draw on a dark
  panel, so an idle console now costs almost nothing.
* Keyboard backlight off / on / auto, and dark whenever the screen is.
* A key pressed on a dark screen WAKES rather than types, the same as a touch
  does in the UI. Otherwise the character you used to wake it ended up in the
  command you were typing.

And the part that would have made the above silently useless:
_screen_timeout_ms is assigned at line 49804, while the console returns at
49431, so it was still at its constructor value and the timeout could never
fire. The console branch now reads the pref itself and prints it at boot, so a
wrong value is visible rather than mysterious.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 21:03:06 +02:00
Michael A. Cojocari 98803f1f14 Merge remote-tracking branch 'upstream/main' into 271 2026-08-22 14:52:20 -04:00
Kaj Schittecat 9ce77db0a7 docs(console mode): no em dashes in the audit table 2026-08-22 20:52:07 +02:00
Kaj SchittecatandClaude Opus 5 e26894fef1 docs(console mode): the full UI-to-console audit
Enumerated from the real thing: the tab list, the APPACT_* action enum, the 19
settings categories, and CommonCLI's own command table.

Headline finding: the node CLI already covers far more than expected (advert,
clock, gps, region, get/set, log, neighbors, ota, power, sensor, time, ver), so
the console needed far fewer new commands than the UI has screens.

Also records what the remaining gaps have in common: they are either Phase 4
(anything Lua), not console-shaped (Display/Keyboard/Lock screen are settings
for a UI that is not running), or the same list-and-act pattern (files, backups,
quick replies, contact actions) which is worth building once rather than six
times.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 20:51:35 +02:00
Kaj SchittecatandClaude Opus 5 98e8e63af9 console mode: colour, a boot banner, a quick menu, and the audit's missing commands
Colour: each scrollback line carries a ConsoleColor, so meaning picks the colour
rather than the caller's taste. Incoming channel posts, DMs, your own echoed
command, successes, warnings and failures are now distinguishable at a glance.
The palette maps onto the core's UIColor names so the console tracks the rest of
the firmware instead of inventing values.

Banner: an ASCII mark, the node name and build, then the quick menu, in the
login-banner tradition. 19 columns wide so it does not break on the V4's 240 px
panel.

Quick menu: numbered, because typing 1 beats typing 'contacts' and because a
numbered list is how you find out what exists. A bare digit runs the item; it is
checked before everything else so the node CLI cannot shadow it.

The audit (full table in CONSOLE_MODE.md) compared every UI surface against what
the console offered. The node CLI already covers more than expected: advert,
clock, gps, region, get/set, log, neighbors, ota, power, sensor, time, ver. What
it does NOT cover, now added:
  chat <name>   read a thread (does NOT mark it read)
  stat          radio + traffic, the Signal page's numbers
  batt          battery
  wifi          radio state
  discover / discovered   the active probe, with BOTH link directions

luaHostBattery and luaHostMeshDiscover were CAP_LUA_SDK_EXT-gated, so the V4 --
the board this exists for -- failed to link. Widened to || CAP_CONSOLE, same as
the send path earlier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 20:50:59 +02:00
Michael A. Cojocari b643396228 Work 2026-08-22 14:47:56 -04:00
Michael A. Cojocari 83bf43df53 Work 2026-08-22 14:40:13 -04:00
Kaj SchittecatandClaude Opus 5 5c93c05a71 console mode: a live message monitor that does not mark anything read
Incoming messages now appear in the console as they arrive, for every known
channel and DM, without opening anything. On by default, persisted (v52
console_monitor), toggled with 'monitor on|off'.

The unread requirement drove the design. The previous version returned early
from newMsgImpl and printed, which skipped ALL the bookkeeping: no store, no
unread, no filters. Now console mode allocates the same chat store the UI does
(allocMessageStore(), extracted from begin() so both paths share it) and the
message takes the NORMAL path — block list, 1-character spam filter, sender
parsing, appendMessage with mark_unread = true. The console print happens AFTER
that append.

So watching a message scroll past is not reading it. It is stored, it is
counted, and it stays unread until the thread is actually opened:
  unread        what is waiting, per thread. Listing does not clear it.
  read <name>   clear one thread, deliberately.

That also means the monitor inherits the spam and block filtering for free, and
history survives a switch back to the graphical UI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 20:24:09 +02:00
Kaj SchittecatandClaude Opus 5 a9464fa131 console mode: an incoming message crashed it (null thread table)
Root cause, from the coredump against a matching elf:

  #0 UITask::findOrCreateThread (name="#test", channel=true) UITask.cpp:48598

_ui_threads is 'PSRAM-allocated in begin()' at line 49732 — AFTER the console
early-return at the top of begin(). So in console mode it is null, and the first
message to arrive dereferenced it. Because the panic rebooted straight back into
console mode, it then did that on every boot: a loop, with no way to the UI from
the device. The self-heal added earlier is what broke the loop.

This is the 'everything that assumes the UI exists' hard part from CONSOLE_MODE.md
showing up for real. showAlert and loop() were handled; the message-arrival path
was not.

* findOrCreateThread, appendMessage and the two inline accessors in UITask.h now
  tolerate a null table instead of assuming begin() ran to completion.
* newMsgImpl prints the message to the console in console mode. That also
  supplies the receiving half, which was missing: it could send but nothing
  arriving was ever shown.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 20:03:06 +02:00
Kaj SchittecatandClaude Opus 5 5b5e86c197 console mode: split CLI output on newlines, and self-heal after a panic
The overlap: the node CLI hands its whole reply to the terminal sink as ONE
buffer containing '\n' (its help text is a dozen lines in a single string).
consoleWriteLine stored that as one ring entry, so the text renderer drew the
breaks itself while our y-cursor still advanced by a single row, and every later
line landed on top of the one before it. Worsening down the screen, which is
what the photo shows. Now split on newlines first, then wrap each piece to the
panel width, so no stored line can be wider than the panel and the renderer
never wraps one on its own.

The bootloop: the device panicked, rebooted into console mode, and panicked
again, with no way back to the UI from the device. Console mode now checks
esp_reset_reason() and, if the previous boot panicked, comes up graphical and
clears the pref. That is the third way out the plan called for, and the only one
that needs the user to know nothing.

Honest about attribution: it boots clean now, but I cannot prove the newline bug
was the panic. The serial cut off right after 'serial_interface ok' because
those prints were not flushed, so the fault may have been later than it looked.
Boot breadcrumbs added (flushed) so the next one localises itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:53:14 +02:00
Kaj SchittecatandClaude Opus 5 51ea08743b console mode: stop the whole screen flashing on every blink and keystroke
startFrame() is display.fillScreen() and endFrame() is a no-op, so drawing is
direct to the panel with no buffer. render() did a full clear-and-repaint, and
it was called for the cursor blink twice a second AND for every keypress, so the
entire screen flashed continuously.

Split into three levels, cheapest that covers what changed:
* scrollback changed  -> full render (the only case that clears)
* typing              -> repaint the input row only, which never touches the
                         scrollback above it or the keypad below
* cursor blink        -> one fillRect on the cursor cell

An idle console now paints one character cell every half second instead of the
whole panel. Blink also moved to 530 ms so it does not beat against the loop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:37:44 +02:00
Kaj SchittecatandClaude Opus 5 bc87645df7 console mode Phase 3: mem, contacts, chans, to, msg
* 'mem' prints free DRAM and PSRAM plus the largest PSRAM block. This is the
  number the whole feature is justified by, so it is a command rather than
  something you have to instrument a build to see: read it in the console,
  reboot into the UI, read it there. Phase 0, self-service.

* contacts / chans / to <name> / msg <text>.

The send path is REUSED, not reimplemented. luaHostMeshSendChannel matches the
channel by name at transmit time, and a cached slot index is how messages once
went out encrypted to the wrong channel; duplicating that logic here would have
been an invitation to reintroduce it. It was gated on CAP_LUA_SDK_EXT, which is
off on the V4 -- exactly the board console mode exists for -- so the guard is
now CAP_LUA_SDK_EXT || CAP_CONSOLE.

'to' stores a name rather than an index for the same reason: an index goes
stale the moment the contact list changes underneath it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:32:38 +02:00
Christopher Van Hoose 6cc0c1e56e Make the WMM block generated, and the tests reviewable
The declination model landed as 4.7 KB of constants pasted into a Lua app,
generated by a script that lived in out/ -- which is gitignored, holds firmware
bins, and is where the app's own "Regenerate:" comment pointed. So the pointer
dangled for anyone who cloned the repo, and nobody but me could answer the
first fair question a reviewer would ask about that block of magic numbers:
where did it come from, and how do I know it is right.

  scripts/wmm/       WMM.COF + NOAA's 100 official test values (both upstream
                     and unmodified), the float64 reference, the generator,
                     verify.py, and a README covering provenance, regeneration
                     and how to move to WMM2030.
  scripts/lua-harness/  the host harness, with run.sh so it is one command.

Neither goes in test/: that is PlatformIO's directory and a harness with a
main.c would be swept into `pio test`. scripts/ already holds this repo's dev
tooling, test_companion_serial.py included.

The block in the app is now genuinely generated rather than hand-pasted:

    scripts/wmm/gen_lua.py --update <app>    rewrite it
    scripts/wmm/gen_lua.py --check  <app>    fail, with a diff, if it drifted

--check catches coefficients updated without regenerating, or a block edited by
hand. The generator owns the `local declination / do ... end` wrapper too, and
that is the point: the tables are named G/H/GD/HD, gpscompass uses a global H
for the screen height, and an unscoped `local H` silently ate it. Hand-wrapping
is how that happened, so hand-wrapping is now not a step.

Verification, all reproducible from a clean clone:
  scripts/wmm/verify.py            100 NOAA values, worst D error 0.005 deg
  scripts/lua-harness/run.sh       10 scenarios, incl. the generated Lua in
                                   the device's own LUA_32BITS interpreter --
                                   0.0002 deg vs NOAA, worst tick 12k of 100k

Also refreshes the LUA_APPS.md paragraph, which still advertised the O and F
keys that were removed and quoted harness numbers from before tilt
compensation.
2026-08-22 13:30:36 -04:00
Christopher Van Hoose d758781564 GPS Compass: put the dial and the bearings on the same north
Every contact and waypoint sat about 22 degrees west of where it belonged,
including nodes whose positions were known to be correct. The markers were
never wrong: bearings computed from coordinates are relative to TRUE north,
the magnetometer measures MAGNETIC north, and the app was drawing one against
the other. The gap between them is the local declination.

Builds the real World Magnetic Model into the app rather than a lookup table
or a hand-entered offset: WMM2025 to degree 12, coefficients and code in
4.4 KB, reproducing NOAA's own calculator to 0.0002 degrees at six sites
worldwide -- verified in this interpreter, on the module as it actually ships
in the app file, not on a copy. The secular-variation terms are included, so
it stays exact across its 2025-2030 window instead of drifting a tenth of a
degree a year from a frozen snapshot.

It is evaluated from the GPS fix, or from the node's own stored position when
there is no fix yet, and only re-evaluated once the position has moved 2 km --
about 8k VM instructions, against a 100k budget per tick. The result persists,
so a reboot starts from the last known declination rather than from zero.

Also:
- A ("set north") no longer double-counts. The offset it stores is a residual
  on top of the model, but pressed with no position at all it silently
  swallows the whole declination; that is now remembered and given back when
  the first fix arrives, so the direction the user fixed stays fixed.
- Headings and bearings carry their reference: 013 deg T, or an amber M while
  the declination is unknown. The dial's repaint key includes it, or the first
  fix would leave it claiming MAGNETIC until the heading happened to move.
- WMM ships a caution model with its coefficients; under 6000 nT of horizontal
  field the app now says the heading is unreliable instead of showing a
  confident wrong number.
- Diagnostics take the full-width bottom row for the declination and the
  position it was computed at, which is how a wrong marker gets traced to a
  bad fix rather than a bad model.

Harness: two new scenarios -- the model against NOAA reference values, and the
no-fix alignment path. The latter caught a real one: the device store takes
strings and numbers, and a boolean flag would have thrown on hardware.
2026-08-22 13:00:33 -04:00
Kaj SchittecatandClaude Opus 5 7d98d359ee console mode: bring up the input hardware ourselves
Keys did nothing on the T-Deck because nothing was scanning them. The touch and
keyboard poll task is started inside UITask::loop(), below the console early
return AND behind 'if (!g_lv.ready) return;' — and g_lv.ready is false in console
mode, since that is the LVGL flag and LVGL is never initialised. So
tdeckKeyboardBegin() was never called and the ring the drain reads was always
empty.

Console mode now starts it once itself. One call covers both: the background
poll task owns the shared I2C bus and scans the touch panel and, on the T-Deck,
the keyboard. Which is exactly why it must not be polled from two places.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 18:58:45 +02:00
Kaj SchittecatandClaude Opus 5 b73965c18f console mode: put the toggle where people look for it
I added it to openVncPage(), which is the Remote app's page and is not reachable
from Settings at all. Reported as 'I don't see the settings option', which is
exactly right.

It is now in Settings > General, above 'Run setup again': a boot mode belongs
with the other device-level switches, not behind an app. The VNC page keeps its
copy since remote mode lives there too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 18:50:58 +02:00
Kaj SchittecatandClaude Opus 5 7a32e58b3d console mode: a way in, and keyboard input
Two things that made it untestable, both found by asking what a user would
actually do rather than by the compiler.

* No way to enter it. Added a Settings > Remote & console toggle mirroring the
  Remote UI one, since that is also a boot mode: set the pref, then reboot via
  rebootDevice() so chat history is flushed rather than lost to the reset.

* Typing did nothing. The physical-keyboard drain lives inside UITask::loop()
  BELOW the console early-return, so it never ran. Console mode now drains the
  same buffer itself. T-Deck codes are ASCII with backspace 8 / enter 13, which
  is what consoleKey already expects.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 18:43:19 +02:00
Kaj SchittecatandClaude Opus 5 48dae32f8c console mode Phase 2: boot into it, and the way back out
* Prefs v51 adds console_mode. It goes at the ACTUAL tail of the struct, after
  lang_file. I first appended it after retry_echo, which is mid-struct and
  exactly the v44 mistake the schema comments warn about; the existing
  static_assert caught it at compile time. Added a second assert pinning
  console_mode immediately after lang_file, so the next person to append is told
  by the compiler rather than by a field of corrupted installs.

* The pref fails safe by construction: only the value 1 means console, so a
  corrupt or unreadable byte boots the graphical UI. The <51 migration forces it
  to 0 rather than inheriting whatever was in that position.

* UITask gains a headless personality rather than #if through main.cpp:
  begin() decides once from the pref and returns before lv_init() and before the
  draw buffer is allocated, loop() runs consoleLoop() instead of the graphical
  path, and showAlert() becomes a console line so main.cpp's ~20 Wi-Fi and
  Bluetooth reports keep working untouched.

* 'ui' or 'exit' in the console clears the pref and reboots. That is one of the
  three ways out in CONSOLE_MODE.md; the boot-key escape is next.

Also Phase 1's on-screen key grid, since the V4 cannot use console mode without
one: three layers (lower/upper/symbols) rather than a shift key that changes
every glyph, so a key's label is always what it types. Compiled out where
CAP_KEYBOARD is set.

All 9 S3 envs, the Tanmatsu and the T-Display P4 build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 18:29:26 +02:00
Christopher Van HooseandClaude Fable 5 d2c3322a41 GPS Compass: retire flip/rotate, calibrate the accelerometer, unwrap the diagnostics
Flip (F) and the "Flip" button are gone, and the stored `mirror` setting with
them. Rotate (O) had already gone. Both existed to let a user hand-tune the
sensor handedness back when it was unknown; both frames are measured now, so
the keys could only break a correct compass. A future board with different
mounting gets a measured mapping, not a key it has to be discovered.

The accelerometer has a zero-g offset -- this one reads ~0.08 g high on Y lying
flat, which is 4.6 degrees of tilt that is not there, applied by the tilt
correction against a gravity vector that is wrong by that much, and wrong in
the DEVICE's frame so it moves the heading differently at every heading.
Rotating the device every way already sweeps a 1 g sphere for the
accelerometer alongside the field sphere for the magnetometer, so the same fit
recovers it at no cost to the user: same gesture, one more set of running sums,
and it is only accepted when the sphere it fits is close to the 1 g it must be.
Simulated with a 0.08 g bias injected: recovered to within 0.02 g, and a flat
device then reads 0 degrees of tilt instead of 5.

Diagnostics: rows were wrapping onto each other. They are shorter now, and
while diagnostics are on the four rows take the whole panel width (the key
column is reclaimed) -- the harness fails if any row exceeds what fits. The
status line also reports the vertical field (d+0.42), which is the measurement
that says whether the magnetometer's Z sign -- inferred, never measured -- is
right: north of the equator, held flat, it must be positive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 12:15:44 -04:00
Kaj SchittecatandClaude Opus 5 e179653350 console mode Phase 1: the console front end (no LVGL)
src/ui-touch/ConsoleUI.{h,cpp}, new and self-contained. Draws straight to the
panel through DisplayDriver and reads input from the board drivers, so nothing
in it needs LVGL initialised.

What is here:
* Scrollback as a flat ring in PSRAM. No per-line allocation, so a chatty
  command cannot fragment the heap the way a strdup-per-line log would. Long
  replies wrap to the panel width rather than being truncated, because a reply
  that runs off the edge is the same as no reply on a screen this size.
* Render only when something changed. That is the point of the mode: an idle
  console costs a millis() comparison, not a render pass.
* Line height derived from the measured character cell (DisplayDriver has
  getTextWidth but no text height, and the drivers scale a fixed 6x8 cell), so
  it stays right at another scale instead of being a hardcoded guess.
* Commands go to the_mesh.runLocalCli(); replies arrive through the existing
  terminal sink. Only clear/help/ui are handled locally. Anything CommonCLI
  already answers belongs there, not reimplemented here.
* Touch: scroll strips wired against heltecV4CapTouchGetLive, guarded on
  CAP_TOUCH so the Tanmatsu (which excludes that driver entirely) still builds.
  The key grid is next.

CAP_CONSOLE is on wherever there is a DISPLAY_CLASS to draw on. It does NOT
imply booting into it; that is Phase 2.

Builds on all 5 S3 envs checked plus the Tanmatsu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 16:54:26 +02:00
Kaj SchittecatandClaude Opus 5 cea21dc744 docs(console mode): drop the alternative nobody asked for; correct the PSRAM claim
The 'console or a lighter skin' open decision was me reopening a settled
question. Removed.

The PSRAM section credited the draw buffer as a major saving. It is not:
LV_DRAW_BUF_LINES is 24, so the buffer is 37.5 KB on the 800 px panels and
11.2 KB on the V4. The real saving is the object tree, which is what Phase 0
measures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 16:35:25 +02:00
Christopher Van HooseandClaude Fable 5 144c4123ad Merge upstream (SDK text measurement, tall-bar and Discord fixes)
Two small conflicts, both additive on each side: upstream added ui.text_w /
ui.text_lines and a "measure" capability while this branch added the panel
colour and the compass/accel caps. Everything from both is kept and the table
hints match the merged key counts.

GPS Compass now uses ui.text_w where the firmware offers it and keeps the
character estimate as the fallback. That estimate is what once put the heading
digits off centre -- it counted UTF-8 bytes, so the degree sign read as two
characters -- and measuring removes the guess entirely, for the dial's centred
text and the satellite meter's reserve alike.

M9, V4, V4-R8, T-Deck and Pager all build; the app harness passes, including
the tilt check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 10:26:10 -04:00
Kaj SchittecatandClaude Opus 5 40839880cb docs(console mode): both decisions, and the blit that makes the translator real
* Touch boards get a drawn on-screen keypad rather than requiring a hardware
  keyboard. The V4 is the board this feature exists for, so it has to be usable
  there. The console draws its own keys and reads touch straight from the board
  driver, which is already independent of LVGL (lvglTouchRead is only an
  adapter feeding it).

* wada.ui gets a console backend behind the same names. This is far more
  capable than 'no UI' implied: console mode still owns a real pixel panel, and
  writePixelsRGB565 already exists outside LVGL on four of the six display
  drivers. So canvas works (the app's buffer is already RGB565) and map works
  (tiles are already decoded RGB565, and the projection has no LVGL in it).
  What is actually lost is LVGL's interaction model, not its drawing: scroll
  containers, focus groups, flex layout. The backend reimplements a simpler
  version of those, which is the bounded real work.

LGFXDisplay and ST7796LCDDisplay need a writePixelsRGB565 wrapper over
LovyanGFX's pushImage; until then caps().canvas is false there and apps adapt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 16:23:02 +02:00
Christopher Van HooseandClaude Fable 5 a650d7874e M9: quieten the bring-up logging, and record the measured IMU frame
Both sensors' 1 Hz debug lines were still on from the axis measurements; off
now (the flags stay, they are how the next board gets measured). Documents the
QMI8658 in M9_PORT.md -- the three attitudes and what each proved, the ADDR_AI
trap, and why tilt compensation was needed at all -- and corrects the
calibration instruction from "tumble it" to "rotate it in one place", which is
the distinction that was corrupting the fit. SDK page gains wada.sys.accel()
and wada.sys.keep_awake().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 10:22:10 -04:00
Kaj SchittecatandClaude Opus 5 7ab0d69bc6 docs: plan for a console boot mode (no LVGL, text + commands)
Grounded in what is already there rather than a wish list: CommonCLI is the
command surface, runLocalCli + setTerminalSink already run one and capture its
output, DisplayDriver is a complete non-LVGL text renderer that is already
linked, and Remote mode is a working precedent for the panel being painted
without LVGL driving it.

Records one thing that changes how the feature should be described: LVGL's
object heap AND draw buffer are both PSRAM (LV_MEM_CUSTOM_ALLOC lvglPsramAlloc,
MALLOC_CAP_SPIRAM), so the saving is PSRAM and CPU rather than internal DRAM.
That is still the right answer for the V4, whose 2 MB of PSRAM is exactly what
map tiles and the extended SDK fight over.

Phase 0 is measurement, deliberately, so the numbers come before the promises.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 16:14:21 +02:00
Kaj SchittecatandClaude Opus 5 92fb071ef3 touch: the dead second back chevron on the tall bar (#308), + SDK Test 1.5
#308 chat_open suppressed the chat's back chevron and cog over an app page, and
the comment right above it says why: otherwise they sit over the page's own
"‹ title" and swallow its back tap. But a settings detail page sets
s_settings_open_cat, not s_apppage_title, so the guard never fired for it.
Opening Settings from inside a chat therefore left TWO back chevrons on the left
of the tall bar, with the chat's clickable cog next to one of them, so a tap
near the wrong chevron went to channel settings or nowhere. Extend the guard.

SDK Test 1.5 (store): uses wada.ui.text_lines() where the firmware has it and
keeps the 1.4 character estimate where it does not, so it lays out correctly on
beta_68 as well as on the next build. It also reports which path it took, since
showing what the board offers is the app's whole job.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 16:02:56 +02:00
Christopher Van HooseandClaude Fable 5 fcc146f57a M9 IMU (QMI8658) + tilt-compensated heading
A two-axis magnetic heading assumes the device is level. At this latitude the
field dips ~60 degrees, so the vertical component is 1.6x the horizontal one
and tipping the device leaks it into the pair the heading is made from: about
1.5 degrees of heading per degree of tilt. That is what "it drifts" was once
the calibration was sound -- it was the hand holding it.

Driver: variants/thinknode_m9/M9Imu.{h,cpp}, QMI8658 at 0x6B on the peripheral
bus, accelerometer only (the gyro is most of the power budget and nothing here
needs it): +/-2 g at 62.5 Hz with the low-pass on, soft reset with a 160 ms
wait that covers both die variants, and the same idle-suspend as the compass so
it costs nothing when unused. CTRL1's ADDR_AI bit is set and read back -- with
it clear the burst read silently returns six copies of one byte, which looks
like a working sensor reporting nonsense. HAS_M9_IMU -> CAP_IMU ->
wada.sys.accel(), caps().accel.

Axes MEASURED, not guessed, by holding three attitudes and logging:
  flat, screen up        z = -1.02  -> +Z into the screen (down)
  on bottom edge, top up x = +0.97  -> +X at the top edge (forward)
  on left edge, right up y = +1.08  -> +Y at the right edge
So the IMU is already in the aerospace body frame, and it agrees with the
magnetometer's independently measured +Z-into-screen. (Meshtastic's M9 driver
passes both sensors through untransformed and mirrors the heading on the sign
of accel Z, so its compass flips when the device is turned over. Not copied.)

Heading now rotates the field back into the horizontal plane using gravity
(NXP AN4248 / ST AN3192) before taking the angle, and reports the tilt angle;
past 55 degrees it says "too steep to read" rather than lying. Calibration
returns to a 3D fit because tilt compensation needs the vertical offset too --
but the instruction is now "turn it every way ON ONE SPOT", and the
accelerometer VERIFIES it: coverage is measured by how far gravity swung, so a
flat spin is refused by name ("turn it nose over tail") instead of silently
fitting a degenerate sphere. Simulated in the harness against a modelled M9 in
a known attitude: offsets recovered exactly, and the heading holds within 3
degrees through 20 degrees of roll and pitch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 10:00:44 -04:00
Christopher Van HooseandClaude Fable 5 4e6b050cf8 Fix the calibration I broke, and calibrate flat instead of tumbling
Two faults, one of them mine from an hour ago.

CAL_SECS is 20 s and the M9's default screen timeout is also 20 s. The tick
pause added in 5a4a5a8 stopped the app the instant the screen blanked, which
is the same instant the calibration was due to finish -- so sampling stopped
half way, the auto-finish (inside on_tick) never ran, and the partial sweep was
fitted and saved without complaint. New wada.sys.keep_awake() holds the screen
AND the tick for a measuring app, and is released when the app closes.

The tumbling instruction was wrong too. Hard-iron calibration assumes the
device ROTATES in a uniform field; carrying it through the air also TRANSLATES
it through the field gradients of a laptop and a desk. Measured consequence: a
centre that moved 0.15 G between sessions against a 0.26 G horizontal signal,
i.e. tens of degrees of direction-dependent error -- which is what "it drifts
when rotating" was. The same device rotated flat in one place fitted a circle
to within 4%, so calibration is now exactly that: a 2D circle fit on x/y, which
is the only thing a heading uses.

And a bad fit can no longer be saved silently, which is how the broken one got
in. calib_solve refuses, with a reason, when the turn is partial (each axis
must span >= 1.4r), when the radius is outside Earth's real horizontal range
(0.08-0.45 G), or when the circle is too distorted (residual > 18% of r --
computed in closed form from the sums already collected). The progress line
shows coverage rather than a countdown.

Also: mag_norm is now the HORIZONTAL magnitude, which lets the app say "Hold it
level" when it departs from the calibrated radius -- the tell-tale for tilt,
which is the accuracy ceiling until the IMU is driven.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 09:28:49 -04:00
Kaj SchittecatandClaude Opus 5 0259264a74 touch: fix the batch reported over Discord (#304 #305 #306 #307, part of #257)
* #305 the home Wi-Fi status was decided from WiFi.getMode(), not from what the
  user asked for, so anything leaving the radio in STA made it announce
  "Starting…" indefinitely with Wi-Fi switched off. Gate on
  wifiConfigGetRadioEnabled().

* #304 the Wi-Fi and Bluetooth status strings were raw literals and stayed
  English everywhere. Wrapped in TR(). Most already had translations sitting
  unused in the language files, so this costs translators nothing for
  "Connecting…", "SSID not found", "Off" and "Built-in"; only "Starting…",
  "Auth failed", "Link lost" and "Init…" are new keys.

* #257 "Built-in" had two code paths and only the one you do NOT see went
  through TR(), which is why it looked inconsistent to the reporter.

* #307 the theme-colour buttons were fixed at 124/84 px, measured against
  "Save & restart" / "Reset". Hungarian's "Mentés és újraindítás" ran off both
  edges. They size to their label now, in a wrapping row, so an over-long pair
  drops to two lines rather than clipping.

* #306 the contact action sheet decided scrollability from a hand-maintained
  grid_items tally that the location-sharing button (#266) was never added to.
  When the tally is short the body is left unscrollable and the overflow is
  unreachable. Decide from the height the buttons actually reached instead, so
  the tally can drift harmlessly.

SDK: wada.ui.text_w / text_lines. An app could ask how tall a line is but not
how wide, so anything laying out its own rows had to guess whether a string
would wrap; guessing wrong draws the next row on top. That is exactly what
happened to the SDK Test app (fixed separately as store version 1.4, with
Nearby hardened the same way).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 15:15:56 +02:00
Christopher Van HooseandClaude Fable 5 8910c62d3c Lua: repeating named timers pause with the display too
beta_68 added named timers, so pausing only on_tick left the same problem one
API over: a repeating timer polling a sensor kept running into a dark screen.
One-shots still fire -- those are scheduled app logic, and skipping one would
drop the work rather than defer it, since the slot is released around the call.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 09:03:20 -04:00
Christopher Van HooseandClaude Fable 5 5a4a5a8ab6 Park the magnetometer when idle, and stop Lua apps ticking into a dark screen
Two answers to "does the compass app matter for battery life", both yes-ish
and both now fixed.

The driver put the QMC6309 into normal mode at boot and left it there, so it
converted continuously from power-on whether or not anything read it: ~1 mA at
100 Hz / OSR 8, forever, on a 2300 mAh battery. It is now parked in suspend
after configuration and woken on demand, with m9CompassIdleTick() (called from
the M9's existing per-loop branch) suspending it again two seconds after the
last read. Waking is a single register write since suspend preserves the
configuration; the waking call reports "nothing fresh" and the caller's next
poll gets data, which callers already handle because the chip may be absent.

Separately, lv_timer_handler() runs unconditionally, so a Lua app's timer kept
firing while the display slept -- GPS Compass polled the magnetometer at 10 Hz
into a dark screen, which would have held the sensor awake even after the fix
above. The host now skips the tick while the screen is off and resumes on wake;
dt comes from millis(), so an app sees one long frame rather than a broken
clock. Documented on the SDK page.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 09:01:19 -04:00
Christopher Van HooseandClaude Fable 5 08c9f2b822 GPS Compass: fit the calibration sphere instead of taking min/max midpoints
North was wrong on hardware, and the device's own saved state said why. Its
stored centre was (-0.3875, -3.465) where four measured headings put the true
centre at (-0.340, -3.378): out by 0.099 G against a horizontal field of only
0.27 G. Replaying the measured readings through that centre gives -1 deg of
error at north, -12 at east, -18 at south and +22 at west -- errors that swing
with direction, which is a wrong centre, not a wrong formula. align and mirror
were both 0, so the axis mapping was doing its job.

Min/max midpoints only find the centre from a COMPLETE sweep and are skewed by
whichever extreme was missed; with a bias ~7x the field here, a tenth of a
Gauss of skew is a third of the whole signal. Calibration now fits the sphere
that the samples actually lie on -- |p - c|^2 = r^2 is linear in (c, r^2-|c|^2),
so it is a 4x4 solve over running sums with no sample storage, which matters
inside a 256 KB app heap. Coordinates are accumulated relative to the first
sample because Lua here is single-precision and squaring raw values near 3.5 G
throws away the precision the fit depends on.

The fit is checked before it is saved: a singular system (a flat spin, where
the centre is undetermined along z) or a radius outside Earth's 0.25-0.65 G
band is refused with a reason, leaving the previous calibration alone -- the
old code would happily save the garbage. The toast now reports the fitted field
strength, which is the number that says whether a calibration is any good, and
the progress line shows the sample count.

Also adds a D key: the calibration in use, the raw vector, the horizontal
components and the stored align/mirror, so a wrong heading can be read off the
screen instead of guessed at. Harness: the fit recovers a simulated bias
exactly, and a flat-only spin is refused without touching the saved values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 08:56:45 -04:00
Christopher Van HooseandClaude Fable 5 15fa9a46e2 fix(lua): the net worker freed its buffers out from under itself
luaNetWorkerService() cleared s_net_pending as its FIRST statement and only
then made the HTTP call, so for the length of a round trip nothing told the UI
thread a request was in flight. An app closing in that window ran hostTeardown,
saw !s_net_pending, and freed s_net_buf / s_net_body while the worker task on
the other core was still reading and writing them.

The flag now stays set for the whole request and is cleared at the end, just
before s_net_done is announced -- that ordering also means a teardown observing
done=true can never also observe pending=true and hold the buffers forever. The
caller runs one service() per loop pass and re-checks afterwards, so holding it
across the call cannot re-enter, and http_get/http_post already reject a second
fetch while it is set.

Found while merging beta_68: upstream's comment said the buffers were
deliberately not freed at teardown because the worker might still be using
them, which was the right hazard behind a guard that could not actually see it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:50:43 -04:00
Christopher Van HooseandClaude Fable 5 9677dcfe19 Merge upstream beta_68 into the M9 compass / GPS work
beta_68 expanded the Lua SDK (map, lists, packet delivery, discovery, private
messages/rooms, native crypto) across the same files as this branch, so four
files conflicted. Nothing was dropped from either side:

- wada.sys.gps(): both widenings merged into one binding. Upstream's
  fix_time / lat_e6 / lon_e6 and our speed_kmh / course now share a signature,
  and our stricter gate wins -- the call returns nil when the user has GPS
  switched off, not just when there is no fix.
- Altitude is upstream's `alt_m` alone. The resolution first carried `alt`
  beside it to protect a shipped app, but gpscompass has never been published
  to the store (it exists only in this branch and on a bench device), so
  carrying a duplicate key into the API forever was the wrong trade: the app
  reads alt_m instead.
- sysCaps() carries all twelve feature flags (upstream's seven, our compass,
  the four originals) with a matching table hint.
- wada.geo (upstream) and wada.sys.compass (ours) both survive; upstream's
  "no board has a magnetometer" note is corrected in the code and on the SDK
  page, since the M9 now does.
- hostTeardown frees upstream's new POST payload buffer as well as the fetch
  buffer, under the same in-flight guard.
- The catalog keeps all three new apps: upstream's wardrive and nearby, ours
  gpscompass (8 total, every referenced file present).

M9, V4, V4-R8, T-Deck and Pager all compile; the Lua host harness passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:43:55 -04:00
Christopher Van HooseandClaude Fable 5 9d477d32df Lua apps: implement the manifest icon; GPS Compass gets the location glyph
Every installed Lua app drew the same generic play glyph in the drawer, and
the manifest's "icon" -- promised in LUA_APPS.md since the plan was written --
was never parsed. It is now read from <id>.json and mapped to a glyph by NAME
(gps / radio / chart / game / ...), not by codepoint: a name is reviewable in
a store submission, the device's JSON scanner only takes quoted strings
anyway, and an app can never ship a glyph the UI fonts lack -- anything
unrecognised falls back to the generic symbol. A bare side-loaded .lua has no
manifest and keeps that symbol too.

GPS Compass declares "icon":"gps", so it now shows the location pin the Map
tile uses.

Also corrected deploy/site/sdk.html, whose manifest table documented
"version", "min_api", "description" and "boards" -- the device has never
parsed any of them -- and described icon as "a single character".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:30:32 -04:00
Christopher Van HooseandClaude Fable 5 eb4ebe4271 GPS Compass: tighten the satellite meter, drop the now-pointless hint
The meter sat too far from the count: the reserve used text_w's
0.55-per-character estimate, which is for mixed text, while the digits and
spaces in "99 sats" run nearer 0.39 of the line height. Sized properly it now
sits beside the number, and still holds still as the count changes.

"A set north" is no longer advertised. The axis mapping is measured, so a
calibrated device points north on its own; A and F remain for an unknown
board or a stubborn environment, they just do not need to be on screen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:24:30 -04:00
Christopher Van HooseandClaude Fable 5 181240eb55 M9: record the measured compass axis mapping and bias
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:22:25 -04:00
Christopher Van HooseandClaude Fable 5 4852f06033 GPS Compass: bake the MEASURED M9 axis mapping; no orientation press needed
The sensor's orientation on the board is documented nowhere, so it was
measured: held flat, logging the raw vector at four headings 90 deg apart
(M9_COMPASS_DEBUG, now off again) gives a hard-iron centre of
(-0.340, -3.378) and, after subtracting it,

    N x'=-0.055 y'=+0.310    E x'=+0.268 y'=-0.018
    S x'=+0.013 y'=-0.275    W x'=-0.225 y'=-0.016

so atan2(x, y) reads 350/94/177/266 at N/E/S/W -- 0/90/180/270 within a few
degrees, counting up clockwise. +Y is the device's top edge, +X its left.
That is now the default: correct after calibration alone.

This also explains the reversal reported on hardware. The auto-handedness
rule assumed a Z-out-of-screen sensor was the un-mirrored case; it is the
other way round -- held flat north of the magnetic equator, a Z-INTO-screen
sensor reads the downward field as POSITIVE z. Fixed, and the stored
orientation is versioned so values saved against the old formula are
discarded rather than pushing a correct default back off north.

The bias is real and large: ~-3.4 G on Y against a ~0.27 G horizontal
signal, which is why an uncalibrated device barely moves the dial, and why
the range is +/-32 G rather than +/-8 G. Meshtastic's implausible hardcoded
extrema were right after all.

Also: the satellite meter now sits beside the count instead of at the column
edge, and UITask::loop's coarse "ui:gps" stall bucket is split into
timers/threads/input/diag so a 450 ms hitch can be attributed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:21:53 -04:00
Christopher Van HooseandClaude Fable 5 9a5cb53b70 M9: record the map re-open measurement (2598 ms cold, 245 ms re-open)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:09:01 -04:00
Christopher Van HooseandClaude Fable 5 2a06695e25 Map: keep decoded tiles across tab switches; Lua host teardown fixes
Map re-open cost ~2.5 s of blocked UI on the M9, every visit. Measured with
the existing stall instrumentation: [STALL] ui:lvgl 2597ms and 2479ms on two
consecutive opens -- identical, so it was paying full price each time rather
than only on the first paint. Cause: leaving the Map tab called freeMapTiles(),
throwing away all nine decoded tiles, so the next open re-read and re-decoded
nine JPEGs. The grid costs 9 x 128 KB = 1.15 MB of PSRAM, which only matters
on the 2 MB V4 -- the board renderMapTiles already caps to a 4-tile pool -- so
boards with room now keep the slots exactly as panning within the tab leaves
them and the re-open is renderMapTiles' match-and-reposition path, no decode.
Note releaseMapTileSlot() would NOT have worked here: it clears in_use, so the
next render treats the tile as absent and decodes it again.

Lua host teardown, from auditing "do apps close properly":
- the http_get buffer (up to 64 KB of PSRAM) was a static that no one freed, so
  an app that fetched left it allocated after closing until some later app
  happened to fetch again. Released on teardown unless a fetch is in flight.
- cvGc's comment claimed it freed canvas pixels only when the app was closing;
  it freed unconditionally, so a canvas whose Lua handle went out of scope
  could be collected while LVGL was still drawing from that buffer. Canvas
  handles are now pinned in the registry for the app's lifetime (there is no
  API to destroy one early), so the pixels die with the state. All three
  shipped canvas apps keep references, so this was latent, not live.
- both the open and close log lines now report free PSRAM: the Lua heap
  counter excludes canvas buffers, so "leaked=0" alone never proved an app
  had given everything back.

M9, V4, V4-R8, T-Deck and Pager all compile. The map timing still needs the
after-measurement on hardware.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 02:07:58 -04:00
Christopher Van HooseandClaude Fable 5 34e1b0f04a GPS Compass: per-row units, imperial by default
Up and down move a selection between the ALT and SPD rows (the selected row's
key turns accent), and OK switches that row's units -- feet/miles or metres/km
for altitude, which the target's range follows too, and mph or km/h for speed.
Imperial is the default. On touch boards a tap on the row itself does the same,
while a tap on the dial keeps stepping the target. Both settings persist.

No "enter" handler on purpose: the host answers OK with a synthetic down/up
pair AND an enter key event, so acting on both would switch the units twice
and read as nothing happening.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 01:56:11 -04:00
Christopher Van HooseandClaude Fable 5 d91737bb3f Lua apps on the firmware's black; GPS Compass: one-press north, swapped sides
The Lua app page painted itself 0x0E1216 while the rest of the firmware
paints pure black (COLOR_BG), so every app read as a lighter panel floating
over the UI. The page is now black and wada.ui.colors gains `panel` for the
raised surface an app draws on top of it -- the compass dial uses it, so the
instrument stands out instead of the page doing it.

Rotate/flip are gone from the user's side. They existed because the QMC6309's
axis orientation on the M9 is undocumented, which is not the user's problem to
solve by trial and error. `A` now does the whole job: whether the heading runs
clockwise or anticlockwise follows from which way the sensor's Z axis faces,
and that shows in the sign of the vertical field -- Earth's field dips down
north of the magnetic equator and up south of it -- so with a position (a fix,
or the node's last known one) the app reads the handedness off the sensor and
the press only has to set the offset. `F` stays as the fallback for a flat
field or no position at all.

Layout: stats column on the left, dial on the right (its status line above
it, the hint centred along the bottom).

The host harness now tumbles the simulated device during calibration rather
than spinning it flat -- min/max on an axis that never moves subtracts the
true field along it, which is precisely the case the handedness check has to
detect and refuse, and the flat mock was hiding it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 01:52:27 -04:00
Christopher Van HooseandClaude Fable 5 44b824ff3d GPS Compass: status over the dial, target detail, centred hints; label align
Layout, from on-device feedback: the magnetometer/heading-source line moved
from the stats column to a centred line over the dial; the stats panel now
starts at the top of the column, and the rows that freed up went to the
target -- name, range + bearing, how far to turn ("56 deg right", "ahead")
and when the contact was last heard. The key hint is centred along the
bottom edge of the view and spells the actions out ("C calibrate  O rotate
F flip  <> target"). The heading's DIGITS are centred with the degree sign
hanging off their right edge, so the number does not appear to shift as the
reading crosses 100/200; the width estimate also counts characters rather
than bytes now, which is what put it half a glyph off (the degree sign is
two bytes in UTF-8).

Host: label:width(px) takes an optional alignment ("center"/"right") -- an
app cannot measure glyphs, so this is the only way for it to centre a line
exactly. Also excluded the app ROOT from keyboard-nav focus: excluding only
the body moved the reverse-video highlight up one level instead of removing
it, which is why the page was still white.

sideload_app.py retries fput/fend as well as fadd -- the same UART byte loss
that garbles a long line can garble a short one ("Error: unknown command").

Calibration now reports the measured field strength in its toast, which is
the number that says whether the calibration is any good (Earth: 0.25-0.65 G).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 01:45:44 -04:00
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
Christopher Van HooseandClaude Fable 5 0771e15452 Serial sideload for Lua apps: fput/fadd/fend CLI + scripts/sideload_app.py
The ThinkNode M9's microSD is soldered on, so the SDK's "drop it on the card"
route does not exist there and the Store can only fetch from its own host.
Three console commands write into the same /apps (or /lang) the Store uses:

  fput /apps/<name>                 open (truncate); names [A-Za-z0-9._-]
  fadd <off> <len> <sum> <base64>   append a chunk, every field verified
  fend                              close

Same physical-access trust level as the existing "rm"/"erase", narrower scope
(two directories). DataStore gains a root-aware mkdirRooted(); the CLI line
buffer grows from 80 to 200 bytes.

Why the chunks are self-checking and short: the UART interrupt is not
IRAM-resident, so while the loop is inside a flash-cache pause only the
128-byte hardware FIFO buffers console input and the middle of a longer line
is lost -- observed on the M9 as a 197-char line echoed back as 120. Offset,
decoded length and byte sum reject a damaged line; the host re-sends. The
host script also waits for "[BOOT] ui ready" because the CH34x bridge resets
the board whenever the port is opened and the console is not serviced before
the UI is up.

Verified on the M9: gpscompass.lua (19055 B) + .json pushed, sizes confirmed
by the device and by `ls /apps` after a reboot. M9 and V4-R8 envs compile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 01:15:56 -04:00
Christopher Van HooseandClaude Fable 5 b273f20e26 M9 compass (QMC6309) + GPS motion for Lua apps; GPS Compass Store app
Firmware
- variants/thinknode_m9/M9Compass.{h,cpp}: QMC6309 at 0x7C on the peripheral
  bus. Probe by chip id, soft reset with the explicit clear, CTRL2 0x20
  (50 Hz, +/-32 G, set/reset on), CTRL1 0x61 (normal, OSR 8/8), read-back
  verified. Synchronous read from the Lua host bridge, 1 s cache, lazy
  re-probe while the rail-powered part is still in POR, OVFL kept + flagged +
  logged. HAS_M9_COMPASS=1 in the env -> new hardware gate CAP_COMPASS.
- src/helpers/WadaNmeaLocationProvider.h: Wadamesh-owned copy of the core
  MicroNMEALocationProvider that also exposes RMC speed/course (the core
  keeps its parser private; no libdeps patch). M9 target.cpp builds on it,
  HAS_GPS_MOTION=1, wadaGpsMotion() for UITask.
- wada.sys.gps(): + alt (m), + speed_kmh/course where the board provides
  them (course only while moving -- an empty RMC course parses as 0), and
  nil while the user has GPS switched off. wada.sys.compass(): {x,y,z,ovfl}
  Gauss, sensor frame, uncalibrated, registered only where CAP_COMPASS;
  caps().compass. Calibration, axis mapping and the heading maths live in
  the app so they can be adjusted per user without a firmware cut.
- Host: luaHostContactAt reads the RTC once per contacts() walk instead of
  once per contact (an I2C transaction each on the M9); pressCb reports
  press coordinates in body content space (scroll offset folded in).

App
- deploy/apps/gpscompass/1.0 + apps.json: rotating rose with a fixed index,
  live fix readout, bearing/range to a selected contact, magnetometer
  heading with hard-iron calibration (C), frame rotate/mirror (O/F, the
  M9's sensor orientation is undocumented), GPS-course fallback on every
  other board, saturation warning. Not baked into lua_builtin.h on purpose
  (CAP_BUILTIN_LUA_APPS also removes the Store > Apps tab).

Verified: M9, V4, V4-R8, T-Deck compile (M9 flash +2 KB); two adversarial
review passes, all confirmed findings fixed; host Lua harness (vendored
Lua, LUA_32BITS) -- calibration recovers a simulated bias exactly, heading
error 0 deg, worst tick ~10k of the 100k budget. Hardware validation list
(axis orientation, bias magnitude, 0x7C ACK) in M9_PORT.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 00:53:16 -04:00
Michael A. CojocariandClaude Opus 5 dee32e4c2c feat(touch): a list users can add regions to (#271)
The other half of the request. The previous commit made a scoped message
resolvable to a region NAME; this is the list that decides which names are on
offer. Until now the registry only filled itself from our own default region and
per-channel scope overrides, so a region you can see traffic from but do not
participate in could never be named -- which is most of them.

Settings -> Radio, under the region-scope field, opens "Known regions": a field
plus Add, and a row per region with Remove. Deliberately placed next to the
region we SEND under, because the distinction is the confusing part -- that field
is the region we transmit in, this list is the regions we can RECOGNISE, and a
region only has to be named to be recognised, since its key is SHA256 of that
name. You do not need to be in a region to identify its traffic.

Remove is a RETIRE, not a delete. The slot and name stay bound; the region simply
stops being matched from that point on. Freeing the slot for reuse would hand it
to the next region added and silently relabel every message already received
under the old one -- the exact failure #271 warned about, and the reason slots
were never list indices. Re-adding a retired region revives its original slot, so
its old and new messages stay one region rather than splitting in two.

The persisted slot file gains an active mask and a magic bump (RGS1 -> RGS2). An
RGS1 file still loads, with every assigned slot treated as live, which is what it
meant before the mask existed.

Two failures are reported rather than silently doing nothing: the list being full
(all 14 slot bindings used, retired ones included -- they are permanent), and a
name that canonicalises to nothing, like blank or a bare "#".

Not board-gated -- the page uses the standard app-page chrome, so it inherits the
tall title bar, the back chevron and focus-group navigation on the keyboard-only
boards the same way Blocked users does. Laid out and reasoned about on the T-Deck
for now; the short-panel boards want a look on real glass before anyone calls it
done there. The page title is untranslated, matching every other app page here
(Blocked users, Spectrum, Discover).

All 8 S3 envs build. Four new strings in 13 .lang files, English both sides per
4709c81; the audit's 3 remaining gaps are pre-existing on main from the beta_68
SDK work. Not hardware-tested: adding a region is verifiable on-device, but
whether a message then resolves to it needs real scoped traffic from a second
node.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 19:16:30 -04:00
Michael A. CojocariandClaude Opus 5 afaebaacc8 feat(touch): name the region a scoped message came from (#271)
Message details could only ever say "my region" or "another region". The request
was a user-maintained region list so the scope line resolves to a real name.

The mechanism was already here. transport_codes[0] is HMAC(region key, payload)
truncated to 16 bits -- per-packet, not a region id, which is why the raw hex
changes on every message (#259) and no code-to-name table can work. The only way
to name a region is to recompute the code with a key you hold and compare, while
the packet is still in hand. MyMesh has done that since #259, for exactly one
key: our own default scope. This widens it from one key to N.

Storage and key derivation are MeshCore's RegionMap + TransportKeyStore, which
already ship in every build (helpers/*.cpp is in the library's src filter) and
were simply never instantiated here. A public "#tag" region's key is plain
SHA256("#tag"), which is byte-for-byte what MyMesh::setRegionScope already
derives for our own region, so a name is the whole record.

Two things are deliberately not reused:

RegionMap::findMatch() returns the FIRST match. A 16-bit tag collides at roughly
N/65534 per packet with N keys live, and a confident wrong region name is worse
than none, so the loop here counts every match and reports ambiguity instead of
picking one.

RegionEntry::id is a uint16 that climbs as regions are added, and per-message
storage has 4 bits. So messages record a SLOT (1..14, 15 = ambiguous, 0 =
unknown) assigned once and never renumbered -- deleting or reordering regions
cannot silently relabel old history, which #271 called out specifically.

Those 4 bits are the free top nibble of meta_flags, which is already persisted at
a fixed offset. No record growth, no history version bump, and no segment
migration: messages written before a region was registered read back slot 0,
which is the honest "unknown" state for a message received before we could name
it. Note this fills meta_flags -- bits 0-3 are the existing semantics, 4-7 are
now the slot -- so the next per-message bit does need a record change.

The registry seeds itself: the default region in MyMesh::begin(), per-channel
scope overrides in UITask::begin() (touch prefs, readable only on that side), and
both save paths register on change so naming starts from the next packet rather
than the next boot. No list-management UI yet; that sits cleanly on top.

Scope reads "#denmark", or "ambiguous (several regions matched)", or falls back
to the old my-region / another-region answer when nothing matched.

Known limits, both honest states rather than bugs: private "$region" keys never
match, because TransportKeyStore::loadKeysFor/saveKeysFor are unimplemented stubs
in MeshCore 1.10 -- when the core fills them in, getTransportKeysFor() starts
returning keys and this works unchanged. And codes[1], the reply-region hint, is
still shown under "Scope" as #157 left it; giving it its own line needs a spare
meta bit, which no longer exists.

T-Deck, T-Lora Pager, ThinkNode M9, Heltec V4 and RAK Tap V2 all build. One new
string in 13 .lang files, English both sides per 4709c81; the audit's 3 other
gaps are pre-existing on main from the beta_68 SDK work. Not hardware-tested --
matching is only exercised by real scoped traffic from a second node.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 16:36:47 -04:00
Kaj SchittecatandClaude Opus 5 b15d422bdc touch: beta_68 — Lua SDK gains the map, lists, packet delivery and discovery
The four capabilities that kept third-party apps a sketch of a built-in one:

* wada.map      the firmware's own tiles, projection and cache inside an app
                page, with its own capped pool so it never evicts the Map tab's
* wada.ui.list  the missing "pick one of N" widget; rows are real buttons, so
                keyboard and trackball nav walk them for free
* on_packet     each frame delivered once instead of polling a 16-deep ring,
                which sampled rather than observed
* wada.mesh.discover  the active zero-hop probe, behind its own permission
                because it spends every neighbour's airtime, not just ours

Plus the surface those need to be useful: packet identity reported only where
the frame actually carries it, exact micro-degree coordinates (Lua is built
LUA_32BITS, so its floats were quietly costing a metre), altitude and satellite
time, wada.geo, wada.ui.input, named and one-shot timers, http_post, windowed
fs.read, and wada.sys.env on a hardware gate rather than the memory one.

Fixes:
* Both ESP32-P4 targets could not link. g_wifi_last_disc_reason was defined in
  src/main.cpp, which the IDF builds never compile, so all nine S3 envs stayed
  green while Tanmatsu and T-Display P4 were dead.
* Map zoom level was invisible in +/- buttons mode; the readout was hidden with
  the slider it was anchored to.
* Hungarian and Dutch held each other's "No SD card" translation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 21:50:01 +02:00
Michael A. CojocariandClaude Opus 5 72fb10254f docs: pager cards on the standalone flasher page, and what that page actually is (#289)
Last item on oumike's list. deploy/flasher/ carried two manifests and no pager,
so the board was missing from the standalone install page.

It now has a card per radio variant, both pointing at latest-beta -- the pager is
a beta-feed board, so latest/ is the wrong pointer for it, unlike the two stable
boards already there. Each card names its radio and says so again in the body,
because flashing an LR1121 build onto an SX1262 unit leaves the user with a
device whose radio does not come up, and the two SKUs look identical.

version is set to "beta" rather than a tag. These manifests point at a rolling
feed, so any tag hardcoded here is wrong the moment the next build ships -- which
is what happened to the two existing files, both still claiming beta_1. Worth
fixing those separately or dropping the local copies entirely.

Which leads to the caveat, now written down in deploy/README.md: no deploy script
publishes deploy/flasher/. deploy-site.sh ships deploy/site/ only, and
flasher.wadamesh.com 301s to the apex, so the page users actually reach is
deploy/site/index.html -- which has covered every board for a while. The README
also had the redirect backwards, claiming the apex redirects to the flasher.

So this is parity for a directory that may be dead. Kaj reached the same
conclusion independently in e2d07d8 and left it alone; the files are cheap and
the ticket asked for them, but the real decision is wire it up or delete it, and
that is now stated where someone will find it.

Also refreshes TLORA_PAGER_PORT.md, which still listed the release pipeline as
TODO (both envs have been in release.sh and gen-flasher-meta.py for a while) and
still described CAP_SD/CAP_FILESYSTEM as 0 by design in four places, along with a
deferred-SD list that has almost entirely landed. Only lock-screen wallpaper SD
scanning is genuinely still T-Deck/M9-only. Adds a dated status section at the
top; the milestone narrative below it is kept, since the war stories are why
several non-obvious things are the way they are.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:43:24 -04:00
Michael A. CojocariandClaude Opus 5 62d7a17034 feat(touch): give the Pager a way back from an unreadable SD card (#289)
The Pager's File Manager only drew an SD row when the card mounted. A card the
board can see but cannot read -- exFAT out of the box, or a damaged FAT --
produced no row at all, so the user could not tell "no card" from "card the
firmware refuses", and had no way to retry short of a reboot.

The Pager is the board that can actually tell those apart: it has a card-detect
line on the expander (XL9555 ch10), which the T-Deck does not. So a detected but
unmounted card now draws greyed as "SD card (unreadable - tap to retry)", and
tapping it clears the mount backoff and retries. An absent card still draws
nothing, which is the existing deliberate behaviour.

The retry is the same single 4 MHz attempt fmSdTryMount() already makes. No retry
ladder, no teardown of the live shared display/radio bus -- both of which that
function's comment forbids on this board, and both of which were learned the hard
way in M7.

In-app formatting stays off for the Pager. That was already true but read as an
oversight, so the reasoning now sits on the format-helper guard: f_mkfs needs an
SD.end() + sdcard_init/uninit lifecycle teardown on that shared bus; with no
touchscreen the T-Deck's hold-to-format gesture maps to holding ENTER, which is
an undiscoverable way to erase a card on a device where ENTER is how you move;
and it has never been run on Pager hardware. Formatting on a computer costs
30 seconds and carries none of that. The Arduino SD library never calls
spi->begin()/end(), so it is probably safe -- "probably" is not enough for a
one-way whole-card erase.

Two new strings, added to all 13 .lang files with English on both sides.
i18n-audit: 954 keys, nothing missing. Pager and T-Deck build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:41:44 -04:00
Michael A. CojocariandClaude Opus 5 d7b981bc62 fix(touch): stop telling three boards to flash from a Launcher they do not have
Gating "Save update bin to SD" on CAP_SD gave it to the Pager, the ThinkNode M9
and the Heltec V4-R8 as well as the T-Deck. The two strings it shows still name
bmorcelli's Launcher -- "For Launcher installs: ..." on the button, and
"Saved: %s\nFlash it from the Launcher." when it finishes -- which is the T-Deck's
update path and means nothing on the other three. Those users get told to open
something that does not exist on their device.

The obvious fix is to reword the strings, and that is the trap: both are
translated in all 13 .lang files, TR() looks rows up by their English text, and
editing the English orphans every translation of them silently. So the T-Deck
keeps its strings byte-identical and the other boards get their own keys, chosen
at compile time. Two new keys, added to all 13 files with English on both sides,
which is this repo's convention for a row awaiting a translator (see 4709c81).

i18n-audit: 13/13 languages, 952 keys, nothing missing. audit-lang: no UNSAFE
format mismatches, which matters here because SDFW_SAVED_FMT is handed to
snprintf as the format string. T-Deck (the #if arm), Pager, M9 and V4-R8 (the
#else arm) all build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:39:01 -04:00
Michael A. CojocariandClaude Opus 5 4b9c9f1f24 docs: the Pager is an LCD on the beta channel, and so are two of its neighbours (#289)
e2d07d8 added the four missing boards to the support matrix, which was the right
call -- the docs were listing five of ten. Three details in it do not match what
we actually publish.

The T-Lora Pager's display is listed as AMOLED. It is a 2.33" IPS ST7796U LCD at
480x222 (TLORA_PAGER_PORT.md's hardware table, and the ST7796LCDDisplay driver
it boots). The AMOLED is the T-Display P4, one row down.

The Pager, the Heltec V4-R8 and the T-Display P4 are all marked Stable. All
three install from latest-beta on the site and all three carry data-dl-betaonly
there; only the T-Deck and the Heltec V4 + TFT are on the stable feed. Marking a
board Stable in DEVICES.md while the install button pulls a beta build tells a
user the wrong thing about what they are getting. All three now say
"Beta (new in beta_45)", which is the release the three of them debuted in.

Also adds the per-board feature note the Pager was missing: the two radio SKUs
and what happens if you flash the wrong one, and the microSD behaviour
(detected-but-unreadable cards offer a retry; formatting stays a host-side job).

The V4-R8, T-Display P4 and Attaky rows still have no feature note. Left for
someone who has the hardware.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:19:56 -04:00
Michael A. CojocariandClaude Opus 5 f9053d0afb fix(touch): finish the CAP_SD gating for "Save update bin to SD" (#289)
e2d07d8 moved this feature off a board-name list and onto CAP_SD && CAP_OTA,
which is the right gate. It changed two of the six #if regions the feature is
spread across. The other four still carried the old three-board list, so the
T-Lora Pager (CAP_SD=1, not on that list) got the button and the state without
the worker behind it.

The result is not a build failure, which is why "all 8 S3 boards build" did not
catch it: sdFwWorkerRun's only caller sits behind the same gate that excluded
the worker, so nothing link-errors. It fails at runtime instead. Pressing the
button sets s_sdfw_request and starts the 400 ms poll timer, nothing ever
services the request, so s_sdfw_state stays 1 and the row sits at
"Saving to SD... 0%" forever. Then closeSettingsCategory -- also still on the
old list -- does not null s_sdfw_status_lbl when the sheet is freed, and the
timer keeps calling lv_label_set_text on the dead object. Open About, tap the
button, leave settings, and it is a use-after-free every 400 ms.

Verified by building the pager before and after: on the unfixed tree
sdFwWorkerRun's strings ("can't create /BINS", "SD open failed") are absent
from firmware.elf while the button is present; after, both are in.

All six regions are now character-for-character identical, with a comment at
the worker saying so and why a partial widening still compiles. Pager, T-Deck
and ThinkNode M9 all build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:10:49 -04:00
Kaj SchittecatandClaude Opus 5 a6464e7128 docs: explain Discover and wardriving
Neither was documented. The Discover app has been in since beta_47 and the user
guide never mentioned it, so the only way to find out what it did was to open it.

The section leads with the thing that makes it different from everything else in
the firmware: Discover ASKS rather than listens. It broadcasts a request that
neighbouring repeaters answer directly, so a reply proves reachability from the
exact spot you are standing, which is also what makes the wardrive data mean
something.

Explicitly separates two names that are one word apart and are not the same
thing: the "Discovered" list in the Contacts overflow is passive, built from
overheard adverts, while the "Discover" app is active. Cross-linked from the
Contacts section where that confusion actually happens, and from the Map section
where the coverage dots show up with no explanation of where they came from.

Covers what a user needs to actually do one: SD card in, wait for a GPS fix, open
Discover and leave it open, then read the map. States the sampling rule (~15 m of
movement, or 20 seconds standing still) so the behaviour is predictable rather
than mysterious, and says plainly that it transmits continuously while open, so
it costs power and airtime and is not something to leave running all day.

Documents the two real limitations rather than leaving them to be discovered: the
map keeps only the newest 160 samples in memory, and the CSV on the card is the
only part that survives a reboot; and there is no on-device viewer for that log,
so reading it back means taking the card to a computer.

Live on wadamesh.com/docs.html.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 19:42:38 +02:00
Kaj SchittecatandClaude Opus 5 a6c447e7d7 docs + tools: sideloading wadamesh on the Tanmatsu
There was no way for anyone but me to put a self-built wadamesh on a Tanmatsu.
The repo carried tanmatsu/build.sh and nothing that could install what it built:
the AppFS writer lived only on my machine, so a fresh clone produced a binary and
no path onto the device. Anyone trying would land on `idf.py flash`, which
replaces the launcher OS.

tanmatsu/tools/ now carries the loop, generalised out of my local copy:

  fetch-appfs.sh     one-time, clones badge.team's esp32-component-appfs
  dump-pristine.sh   one-time, dumps YOUR device's AppFS partition as the baseline
  tan_deploy.py      builds the write-images and works out the changed sectors
  tan_flash.sh       detects the P4, writes app then metadata, verifies the commit
  sermon.py          non-resetting serial monitor

Three things had to change before this could work for anybody else. Absolute
paths to my checkout are gone. The hardcoded MAC of MY Tanmatsu is replaced by
detecting whichever port answers as an ESP32-P4, which is also more robust since
the board exposes two ports whose names move between replugs. And tan_flash.sh no
longer invokes tan_deploy.py twice: the second run would have read the metadata
the first had just written and bumped the version an extra time.

appfs.py is deliberately NOT vendored. It is badge.team's and the copy in
circulation has no licence header, so it is cloned instead. dev_appfs.bin is not
committed either: it is 8 MB and device-specific, and using someone else's dump
risks overwriting apps you have, since the deploy writes only what differs from
it. Both are gitignored.

Written up in TANMATSU_SIDELOAD.md and as a page on the site, linked from the
user guide, the homepage resources section and the README. The guide leads with
the model rather than the commands, because the failure that matters is not a
typo, it is not knowing that this board runs wadamesh as an app under a launcher
and that flashing it normally destroys that launcher.

Not re-verified on hardware: the tooling is the same loop that has been deploying
to my Tanmatsu, with the paths and device detection generalised. The first person
to run it on another machine is the real test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 19:32:50 +02:00
Kaj SchittecatandClaude Opus 5 25c76a3798 i18n: the audit could not see strings reached through a table, and one was missing
pisti87 asked whether the obsolete entries in the language files will be removed
(#262). Measuring it first was the right move, because the tool that would have
driven that cleanup was wrong.

source_keys() only ever matched TR("literal"). Strings reached indirectly, as in
TR(kSettingsCats[c].label), were invisible to it, so every settings-category name
looked unreferenced: About, Backups, Language, MQTT bridge, App permissions and
the rest. Anyone pruning the .lang files on that output would have deleted live
translations for some of the most visible labels in the UI.

The audit now also pulls literals out of any table whose name appears inside a
TR(...) subscript. Deliberately greedy: over-collecting keeps a translation alive,
under-collecting deletes one.

That immediately found a real gap it had been hiding. "App permissions", the
settings category added with the permissions page, was missing from all 13
languages and the old audit reported everything as covered. Added, builtin
regenerated, published as language v15.

Also adds --obsolete, the reverse check pisti87 actually needs: rows in each .lang
file that no TR() key matches. It reports and never deletes, and says plainly that
these are candidates to check rather than a delete list, for the reason above.
Numbers now: 950 keys reachable, hu.lang carries 1044 rows, 94 unreferenced. The
earlier figure was 119, so 25 of those were the false positives just fixed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 19:19:21 +02:00
Kaj SchittecatandClaude Opus 5 812a206f3e docs: document the instruction budget, and finish covering the new SDK
The page said only "there is an instruction budget: an app that spins forever is
stopped", which is why an app developer had to ask what it actually is. Now there
is a section answering the four questions that were asked: 100,000 Lua VM
instructions per callback, counted as VM OPCODES by Lua's own LUA_MASKCOUNT hook,
re-armed per callback rather than per session, 5x for on_open, and native wada.*
call time does not count against it.

It also says what to do when you hit it, because the honest answer is usually not
"optimise your Lua": a pure-Lua HMAC genuinely exceeds 100,000 instructions and
the fix is wada.crypto, which the section links to. The alternative, splitting a
long job across ticks using state on the app table, is spelled out too.

Audited the whole page against the firmware afterwards rather than trusting that
I had covered everything: every one of the 50 registered wada.* names and all
five lifecycle callbacks now appear on the page. The stale "ext" list in Sandbox
limits also gained send_dm.

Live on wadamesh.com/sdk.html.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 18:53:06 +02:00
Kaj SchittecatandClaude Opus 5 4ab3ab98a4 credits: istvan and pisti87 are one person, and stop @-mentioning chat handles
Two corrections from Kaj, both mine.

istvan is pisti87. I had been thanking them as two people across beta_64 and the
beta_65 stable notes, which splits one person's contribution in half and reads as
if a second reporter existed. Merged into pisti87 everywhere: both notes files,
the source comment that cited the report, both published GitHub bodies, and the
on-device stable notes, which are generated from the cumulative notes file and
had to be regenerated and redeployed.

And in beta_67 I turned Discord names into GitHub @-mentions. "@Jade" resolves to
an unrelated GitHub account, so a stranger got tagged on our release, and the
handle credited was not the person who did the work. The names stay, as plain
text, and the @ is gone.

The rule I should have been following: an @-mention is only safe when the handle
came from GitHub itself, i.e. the author of a PR, issue or commit. @cvhviz,
@pisti87, @oumike, @wb6zsu, @Yoss101 all came from GitHub and are fine. A name
seen in chat is a display name, not a handle, and mapping one to the other is a
guess that lands on somebody real.

Not rewritten: commit messages already pushed that mention istvan. History stays
as it is; the user-facing credits are what matter and those are corrected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 18:43:57 +02:00
Kaj SchittecatandClaude Opus 5 5e33e341cb release: beta_67 notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 18:04:58 +02:00
Kaj SchittecatandClaude Opus 5 42207bca2e docs + i18n: cover the new SDK surface before it ships
Pre-release tidy-up, so the same mistake as last week does not repeat: the SDK
page described a lifecycle the firmware never had, and shipping an expanded SDK
against a page describing the old two-permission model would be the same thing
again.

sdk.html now documents wada.mesh.send_dm and wada.mesh.channels, the m.kind field
on on_message, all four permissions with why they are four rather than one, and a
new wada.crypto section including why it exists (pure-Lua HMAC does not fit the
instruction budget) and why it is on every board rather than ext-gated.

i18n: 11 keys were missing across all 13 languages, six from the SDK work and
five from PR #287 which added strings without lang entries. All covered; audit
reports 924 keys with nothing missing, builtin fallback regenerated, published as
language v14 and the store is live.

Also removes an em dash from "Wi-Fi off, new map areas can't download", new in
#287 and not yet translated, so the key could be corrected for free.

All 8 S3 boards build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 17:50:37 +02:00
Kaj SchittecatandClaude Opus 5 c8da92bf38 feat(lua): private messages, rooms, channel discovery and native crypto
Apps could post to a channel and read channel traffic. They can now hold a whole
conversation.

  wada.mesh.send_dm(to, text)  -> ok, "sent"|"room"|err
  wada.mesh.channels()         -> names of the configured channels
  app.on_message(m)            -> m.kind is "channel" | "dm" | "room"

send_dm takes a contact NAME as it appears in wada.mesh.contacts(). A room server
is a contact too, so one call covers both and the second return says which it was.
Sends are mirrored into the on-device thread and register the expected ACK exactly
as a composer send does, so an app-sent message is a real message rather than
something that leaves the radio with no local trace. Private channels needed no
work: channel send already matches any configured channel by name, and channels()
now lets an app discover them instead of being told the name. Names only - the
channel secret is never exposed to Lua.

Permissions go from two to four, split the way the risk actually splits:

  Post to channels as me      LUA_PERM_SEND
  Read channel messages       LUA_PERM_READ
  Send private messages as me LUA_PERM_DM_SEND
  Read private messages       LUA_PERM_DM_READ

Posting to a channel you are already in is not the same act as writing to one
person as you, and channel traffic is not somebody's DMs. Each is granted on its
own. The DM prompt is worded harder than the channel one because a direct message
lands in a private thread looking exactly like something the user typed.

Fixes a latent bug this would have made real: luaPermWrite() wrote a WHOLE mask,
so the send prompt silently revoked a read grant given in Settings. Harmless with
one bit, wrong with four. Writes are per-bit now.

on_message also moved: it ran before the sender/body parsing, so it could only
ever be handed a channel post. It now sits after the block and spam filters, so
an app sees exactly the messages the user does, and DMs and room posts reach it.

Also adds wada.crypto (sha256, sha1, hmac_sha256, hmac_sha1, hex). Tiamat and
Jade's OTP app was dying on "instruction budget exceeded" doing HMAC-SHA1 in pure
Lua, which is a legitimate use of 100k VM instructions rather than a runaway: SHA-1
is 80 bit-twiddling rounds per block and the interpreter overhead multiplies it.
mbedTLS is already linked, so the same work is now microseconds and a few VM
instructions. Deliberately NOT gated on CAP_LUA_SDK_EXT: it is pure computation
over data the app already holds, reads nothing of the user's and transmits nothing,
so the small boards get it too.

All 8 S3 boards build. Not yet exercised on hardware.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 17:37:12 +02:00
Kaj SchittecatandClaude Opus 5 28e4f0f332 fix(p4): battery flickered between 0% and the real value (regression from #273)
Mine, from the fuel-gauge change earlier today.

bq27220ReadU16() returned 0 on an I2C failure, which is indistinguishable from a
real reading of zero. The voltage reader had always defended against that by
range-checking (2500-4600 mV) and keeping the last good value, but the new
state-of-charge reader accepted anything <= 100 — so every lost transaction was
taken as a genuine 0%, and the display alternated between 0 and the real figure
as reads succeeded and failed.

The gauge shares this I2C bus with the XL9535 expander, the RTC and the touch
controller, so an occasional lost transaction is normal rather than exceptional.
Encoding that as a valid measurement was the mistake.

The transport now returns false when the gauge does not answer, and both readers
keep their previous good value on a failure. Once the gauge has answered once,
the percentage never falls back to the voltage curve either, so the number cannot
jump between two different scales.

Reported by Kaj on hardware. P4 builds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 17:16:01 +02:00
Kaj SchittecatandClaude Opus 5 e2d07d8428 fix + docs: "Save update bin to SD" on every board with a card, and list the boards we actually ship (#289)
oumike's gap list. Three of the four are closed here.

"Save update bin to SD" was gated on a list of board names that had grown to
three entries and still left the T-Lora Pager out, despite it having both a card
and OTA. It is now gated on the capability that actually decides it, CAP_SD &&
CAP_OTA (plus the ESP32 / companion conditions it already carried), which is what
device_caps.h exists for: a new board with a card no longer has to remember to
add itself to a list.

Both halves were gated separately - the helper block and the button that uses it
- so widening only the button broke the pager build on undefined symbols. They
are now character-for-character identical, which is the point: they cannot drift
apart again.

Docs were further behind than the issue said. DEVICES.md listed five boards and
we ship ten: the T-Lora Pager, Heltec V4-R8, T-Display P4 and Attaky Mesh Series
were all missing from the support matrix, and the Pager was still sitting under
"Requested boards" with an open issue link. README listed five envs and claimed
the repo covers "the two boards". Both now match what release.sh actually builds.

Still open from #289: the static deploy/flasher/ page carries only two manifests.
Left alone for now - flasher.wadamesh.com redirects to the site flasher, which
generates its manifests from gen-flasher-meta.py and already covers every board,
so that directory may simply be dead. Worth confirming before adding files to it.

All 8 S3 boards build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 17:08:29 +02:00
Kaj SchittecatandClaude Opus 5 888e66cc09 fix: map tiles in /MAPS were never found, only /maps (#286)
w7aaf put tile packs in MAPS/osm/z/x/y and the device drew nothing. pisti87 could
not reproduce it on his own card, which is the shape of a case-resolution
difference rather than a wrong path.

It is our inconsistency. The card bootstrap CREATES "/MAPS" and the README we
write onto the card says "MAPS/ offline map tile packs", but both the tile loader
and the zoom-availability probe only ever asked for "/maps". FAT is nominally
case-insensitive, but whether that lookup resolves depends on the card's
long-filename entries and the FATFS build, so a user who followed our own
instructions to the letter could end up with a directory the loader never looked
in — while the same layout worked fine for someone else.

Both spellings are now tried, upper first since that is the one we create, in
tileFromSd() and in tileExistsAt(). The second one matters as much as the first:
it drives zoom reachability, so leaving it behind would have advertised zoom
levels as available and then drawn nothing.

Documentation left as MAPS/, which is what the device itself creates.

All 8 S3 boards build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 16:57:56 +02:00
Kaj 78f18bcc3f Merge pull request #287 from cvhviz/m9-audit-pass
ThinkNode M9 + Heltec V4-R8: 2026-08 audit passes (nav soft-locks, storage, deep sleep, Spectrum at spec)
2026-08-21 16:51:03 +02:00
Kaj SchittecatandClaude Opus 5 1c686553e7 i18n: pisti87's Hungarian, plus the compiled-in table I forgot to regenerate (#277)
pisti87 pointed at a commit of his (dc94f44) with 64 Hungarian rows, including
translations for the strings added over the last few releases.

He put them in src/ui-touch/i18n_builtin.h, which says "DO NOT EDIT" at the top
because it is GENERATED from deploy/apps/lang/*.lang. That turns out to be my
fault rather than his: yesterday I added 29 keys to the .lang files and never
ran gen-lang-builtin.py, so the compiled-in fallback still had the old table and
a device that has not downloaded a pack still showed English. Editing the
generated file was a reasonable guess at where the strings lived.

So: his rows are merged into deploy/apps/lang/hu.lang, the canonical source, and
the builtin is regenerated from it (13 languages, 12514 rows). Both paths agree
again.

Four of his rows would not have compiled - two used a tab where a comma belongs,
and two left the quotes inside the English unescaped, one of which had pasted
"Nincs válasz." into the middle of the English key. Reconstructed rather than
dropped; the intent was unambiguous in each.

A fifth pointed at something real: he translated "Battery life: geathering
data..." and no such key exists. Ours has no typo, but more importantly it was
never wrapped in TR() at all - a bare literal snprintf'd straight into a
user-visible buffer, which the unwrapped-literal scanner does not look at since
it only inspects LVGL setters. It is wrapped now, along with the one literal the
scanner did flag (the UI size dropdown), so the scan is at zero and both strings
are translatable for the first time.

Audit: 916 keys covered in all 13 languages. Published as language v13 and the
store is live.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 16:35:00 +02:00
Christopher Van HooseandClaude Opus 5 7060a38dba Fix V4-R8 crash on Wi-Fi association with BLE on; widen companion ATT MTU
Wi-Fi power save: remove the preference, always use DTIM modem sleep.

An R8 with saved credentials and Bluetooth enabled aborted every time Wi-Fi
associated. Coredump: crashing task "wifi", abort() inside pm_set_sleep_type,
with nimble_host and btController both live.

WIFI_PS_NONE is not a legal sleep mode while the BT controller is running --
modem sleep is precisely what yields airtime to BLE -- and the Wi-Fi PM blob
aborts rather than refusing. 844d8c3 made power save a preference defaulting
OFF on the V4-R8, which is why only that board crashed; the comment above the
apply site already stated the invariant it broke ("gives BLE coexistence
airtime").

The latency it was buying does not exist either. Profiling the companion link
on hardware: an app sync is ~40 CMD_GET_CHANNEL round trips (the device reports
MAX_GROUP_CHANNELS=40 and the app reads every slot individually), 165ms each,
with this firmware accounting for 28ms of 8264ms -- 0.3%. Sync cost is
round-trip COUNT, not link latency, so there was nothing to trade away.

Guarding the setting was considered and rejected: it would have to be silently
inert whenever Bluetooth is on, which is a confusing thing to leave in a
Settings screen. Removed instead -- toggle, prefs accessors and R8 default.
The stored wifi_ps NVS key is simply never read again; no migration needed.

Companion BLE: ATT MTU MAX_FRAME_SIZE -> MAX_FRAME_SIZE + 3.

A notification payload is ATT_MTU-3, so SerialBLEInterface::begin()'s
setMTU(MAX_FRAME_SIZE) left a full-length frame 3 bytes too big and NimBLE
silently dropped the overflow (ble_att_truncate_to_mtu). MyMesh::queueMessage()
clamps message text to exactly MAX_FRAME_SIZE, so maximum-length messages lost
their last 3 bytes -- over BLE only; USB/TCP/WS were unaffected. Applied from
the vendored transport rather than the core: setMTU() is a public static, so
MeshCore needs no change. Verified on an M9, which now negotiates 179.

All 8 environments build. R8 flashed and confirmed to be the booting slot
(otadata seq 1 -> ota_0); its boot log is not observable over USB because
opening the port drops that board into ROM download mode.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 00:53:41 -04:00
Christopher Van HooseandClaude Fable 5 844d8c3357 V4-R8 perf pass + M9 UI polish (prefs v49/v50)
Heltec V4-R8 — "are we getting full performance?" audit. Compute side was already
at spec; six gaps closed (record: variants/heltec_v4/R8_AUDIT.md "Perf pass"):
- FEM LNA defaulted OFF on a KCT8103L board: prefs v49 defaults it ON on the R8
  (one-time flip of existing installs, no new field). Toggle stays in Radio & Mesh.
- Display SPI 40 -> 80 MHz (LGFX_SPI_WRITE_HZ; -D to 40000000 steps back).
- Async DMA band flush (LGFXDisplay::flushBandRGB565): swap into a 12 KB internal
  DMA buffer, one no-convert DMA per band, lv_disp_flush_ready at once so LVGL
  renders band N+1 while band N drains; lv_disp_flush_is_last closes the frame
  transaction so the shared micro-SD gets the bus between frames. Sync fallback.
- Wi-Fi modem power save is a pref (wifi_ps; toggle in Wi-Fi settings, live once
  associated). Default ON everywhere (unchanged), OFF on the R8.
- micro-SD 4 -> 20 MHz after the proven mount, read-verified (probe-file head
  captured at 4 MHz and byte-compared after the raise; falls back). Wired at all
  three mount sites; no-op without SD_SPI_FAST_HZ. Note: SDFS::begin returns true
  if already mounted, so every clock change goes through SD.end() first.
- R8 env boots at ESP32_CPU_FREQ=240 (setup() no longer runs at the V4's 80 MHz).
- Settings -> About "Perf:" row on the R8 (no serial console on that board):
  "CPU 240 · TFT 80 MHz DMA · SD 20 MHz · LNA on" is the all-green reading.

ThinkNode M9 UI:
- Spectrum page root gets NAV_SKIP_FLAG: nothing on it is actionable, so the
  d-pad no longer highlights the chart / scale box; Back closes it as before.
- Map "Show tile z/x/y" line defaults OFF (prefs v50, one-time flip; toggle kept).
- The tab bar is bypassed entirely on the M9: the accent "glow" indicator lived on
  the screen, not in the bar, so hiding the zero-height bar left it glowing over
  the content's bottom edge. No bar styling / gestures / key hints / indicator
  are built on the M9 now.

Cross-compiled: R8, V4, M9, T-Deck. Flashed + booted on the user's R8 and M9.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 13:51:11 -04:00
Christopher Van HooseandClaude Fable 5 16e883187c M9 + all boards: persist the companion app-sync ring across power cycles
User report: the M9 "does not remember chats or sync them to the app" while
the V4-R8 does. The companion sync ring (MyMesh::history_ring + per-client
cursors) was RAM-only on every board — invisible on a USB-powered V4 that
rarely loses power, fatal on the M9 whose only off is the hard-cut slider.

Shared fix: the ring is now an append log (/synchist) plus client cursors
(/synccur) on DataStore::getHotDataFS(), restored in MyMesh::begin() and
flushed by persistSyncHistoryNow() on the paths that lose RAM (deep sleep,
power-off, explicit save). Record + bench-test recipe: M9_PORT.md Deferred #13.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 13:50:48 -04:00
Christopher Van HooseandClaude Fable 5 c9251aec61 docs: ThinkNode M9 keyboard & d-pad guide (THINKNODE_M9_SHORTCUTS.md)
User-facing key map and mode tour in the TLORA_PAGER_SHORTCUTS.md mold:
inputs, the close-what-you-see Back rule, function-key table with hold
actions, map pan, editing, lock screen, apps, and a user-terms summary
of the beta_66-branch navigation improvements. Linked from the README
board list and the DEVICES.md feature note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 09:57:59 -04:00
Christopher Van HooseandClaude Fable 5 e56ac117b4 M9: Spectrum brought to LR1110 spec (STDBY_XOSC between bins, span-wide image cal, TX-safe seize)
Spec-check of the sweep on the LR1110 (two analysts + adversarial
verify): per-bin standby() parked in STDBY_RC and re-paid the ~5 ms
DIO3-TCXO startup every bin (~10 ms/bin, ~2x the budget) — bins now
park in STDBY_XOSC via the raw 0x01 byte (RadioLib's STANDBY_XOSC
define is bugged identical to STANDBY_RC); one CalibImage over the
whole swept span per open (begin() only calibrates mesh_freq +/-4 MHz,
not the +/-12 span the old comment claimed), mesh cal restored exactly
on close; sweep clamps corrected to the driver-enforced 150-960 MHz on
BOTH driver families and a failed retune now skips the bin instead of
mis-attributing the previous bin's RSSI; failed-read 0 dBm sentinel no
longer wins the peak-hold (one SPI hiccup squashed the auto-scaled
trace for ~30 s); config block enters standby first; opening Spectrum
mid-TX now waits (bounded, dispatcher's own airtime budget, 6 s cap)
for the packet to finish instead of truncating it on the air; stale
SX126x-era comments refreshed, dead gain readout removed, bin-pitch
vs RBW coverage (42%) documented as the deliberate trade-off it is.

On-device verification wanted: sweep timing (micros() log), mesh RX
sensitivity after a Spectrum session, mid-TX open completing the send.
All four touch envs compile clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 09:18:27 -04:00
Christopher Van HooseandClaude Fable 5 1b7d793ceb M9: audit pass 2 — 29 verified fixes (nav soft-locks, gate parity, deep sleep, build hardening)
Second 7-dimension adversarially-verified audit over the 08-19 tree.
Headliners: SUB_MAP over a display-only Lua app orphaned the app page
(key-only soft-lock); Back-ladder z-order redesign (CC/power always-
frontmost, confirm-modal deference, Lua key-forward suppressed while a
confirm is up — the send-permission dialog was unanswerable); map pan
flag could go stale across tab jumps/popups; null-close progress rows
now genuinely block the registry dismiss (shared fix); terminal RX
mirror, fullscreen title, wallpaper caption, storage-error guidance
widened to M9; accent/@-mention pickers suppressed (dead chrome on a
touchless board); kb-backlight cache only latches ACKed duties (0xFF
sentinel == duty 255 skipped the first write every boot); deep sleep
actually drops the rails now (display refcount, LEDC pin re-route,
RTC/digital holds) and powers off radio+GPS; TCXO fallback no longer
codifies the disproven 0.0f; RadioLib old-FW patch fail-closes at
link; ENV_SKIP_GPS_DETECT + CORE_DEBUG_LEVEL=0 added to the env.

Full round log in M9_PORT.md 'Audit pass 2 (2026-08-20)'. All four
touch envs (M9, T-Deck, V4-R8, pager) compile clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 08:07:37 -04:00
Christopher Van HooseandClaude Fable 5 68e3b45932 M9 + V4-R8: 2026-08-19 audit passes
ThinkNode M9 (see M9_PORT.md audit section): restore nav-mode HW Back,
Lua-app key forwarding + d-pad support, popup-registry gates widened,
SD-backed data store + chat history, ADC2 battery sample filter,
keyboard poll throttle + backlight, map tile cache to SD, spectrum
sweep LR1110 fix, power-menu cleanup for buttonless hardware.

Heltec V4 R8 (see R8_AUDIT.md): chat history/battery log follow SD
adoption, reinsert watch no longer unmounts live store, tile cache
prefers SD, CAP_ROTATABLE reboot trap defused, SD CS parked at boot.

Shared: atomic threads-index write (tmp+rename), recursive
scroll-into-view during keypad nav, textarea focus highlight.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 07:25:18 -04:00
Tesso M Costa 808ee6e1b4 Merge remote-tracking branch 'origin/main' into at-glance 2026-07-30 10:32:23 -06:00
Tesso M Costa 14d5fdb8b3 touch: add "at a glance while locked" opt-in, fix glance multi-line body
New Options > Lock screen toggle lets the at-a-glance overlay fire while
the device is manually locked too, not just unlocked+idle-dimmed -- off
by default since it makes message text readable off a locked device.
Persisted via TouchPrefsStore (touchPrefsGetGlanceWhenLocked). When it
fires from a locked state, mirrors lockscreenReveal()'s peek path (panel
lit, _manual_lock left alone) rather than wakeScreen() (which would
silently clear the lock).

Also fixes the glance body label: LV_LABEL_LONG_DOT only wraps/dot-
ellipsizes across multiple lines when the label has a fixed height, so
left at auto-height it was effectively single-line everywhere, cropping
longer messages instead of continuing to a second line. Now sized to
the actual space available below it for the current board's resolution
and font.

Adds a T-Deck-only experiment shrinking the glance body font from 28px
to 20px (extras_lat_20 gate widened past Tanmatsu-only to cover it);
easy to revert in isolation per the comments at each site.

Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>
2026-07-30 09:12:05 -06:00
Tesso M Costa 61ed43bc40 touch: add "at a glance" idle-dim notification overlay
While unlocked but idle-dimmed to off, an incoming message (DND
permitting) briefly lights a plain black overlay with the sender/
channel name and message text, then auto-dims after a fixed window
without opening the chat or marking the message read. Board-agnostic,
distinct from the T-Deck's existing opt-in msgFlash.

extras_lat_28 (accented Latin/em-dash/ellipsis at 28px) moves from
Tanmatsu-only to every board, since the glance body needs that
coverage everywhere.

Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>
2026-07-28 09:36:36 -06:00
234 changed files with 92982 additions and 2008 deletions

No files matched your search

+10
View File
@@ -11,6 +11,10 @@
.vscode/extensions.json
out/*
!out/README.md
# host Lua harness: the compiled binary, not the sources (scripts/lua-harness)
scripts/lua-harness/luah
scripts/lua-harness/*.o
.DS_Store
.idea
cmake-*
@@ -36,3 +40,9 @@ CLAUDE.md
# Local reconstruction notes (scratch, never publish)
/.notes/
# Tanmatsu sideload tooling: fetched/dumped per developer, never committed.
# appfs-src is badge.team's repo (fetch-appfs.sh); dev_appfs.bin is a dump of YOUR
# device's AppFS partition and is both large and device-specific.
tanmatsu/tools/appfs-src/
tanmatsu/tools/dev_appfs.bin
+156
View File
@@ -0,0 +1,156 @@
# Testing Lua audio playback
This guide tests issue #315 with a real WAV or MP3. The examples use the
T-Deck environment and the provided `scripts/audio_test.lua` app.
## Build and flash
Build and upload the branch as usual:
```sh
pio run -e LilyGo_TDeck_companion_radio_touch
pio run -e LilyGo_TDeck_companion_radio_touch -t upload
```
Keep the serial monitor available for `[LUAAPP]` or storage errors:
```sh
pio device monitor -b 115200
```
## Quick MP3 test from SD
1. Use a FAT32 SD card and create these paths on it:
```text
/Music/test.mp3
/meshcomod/apps/audio_test.lua
```
2. Copy `scripts/audio_test.lua` from this repository to the second path. Rename
your MP3 to `test.mp3`, or edit `SD_PATH` near the top of the Lua file.
3. Insert the card before boot, then reboot the T-Deck.
4. Enable **Settings > Sound** and set volume above zero.
5. Open **Apps > audio_test**. The screen should report
`audio=true`, `wav=true`, and `mp3=true`.
6. Press **Play**. Expected status:
```text
State: playing
Source: sd Format: mp3
```
7. Exercise **Pause**, **Resume**, and **Stop**. Pressing **Play** while already
playing must restart/replace the current track without overlapping it.
8. Start playback and leave the app. Audio must stop immediately when the app
closes.
The direct SD API used by the test is:
```lua
local ok, err = wada.audio.play("sd:/Music/test.mp3")
```
`sd:` paths are absolute from the physical card root. Empty segments,
backslashes, trailing slashes, `.` and `..` are rejected.
## Test app-local/internal storage
A plain filename is resolved inside the current app's private directory. For
`audio_test.lua`, the logical files are:
```text
/apps/audio_test.lua
/apps/audio_test.d/test.mp3
```
On T-Deck and Pager, internal app storage is SPIFFS. The least destructive way
to populate it is the repository's serial uploader:
1. Power off, remove the SD card, and reboot. This forces T-Deck app storage to
the internal SPIFFS backend.
2. Make a short internal-storage fixture. T-Deck has a 3.375 MB SPIFFS partition
shared with settings and history, so use the full song for SD testing and a
small clip here:
```sh
ffmpeg -y -i "/path/to/your/file.mp3" \
-t 10 -ac 1 -ar 22050 -b:a 48k \
/tmp/wadamesh-audio-test.mp3
```
3. Find the serial port with `pio device list`.
4. Install `pyserial` once if needed:
```sh
python3 -m pip install pyserial
```
5. Upload the app and short MP3. Replace the port as needed:
```sh
python3 scripts/sideload_app.py \
--port /dev/cu.usbmodem101 \
--remote /apps/audio_test.lua \
scripts/audio_test.lua
python3 scripts/sideload_app.py \
--port /dev/cu.usbmodem101 \
--remote /apps/audio_test.d/test.mp3 \
--reboot \
/tmp/wadamesh-audio-test.mp3
```
6. Open **Apps > audio_test** after reboot. With no card inserted, the app
selects `test.mp3`; press **Play**.
7. Expected status is `Source: app Format: mp3`.
The app-local API is simply:
```lua
local ok, err = wada.audio.play("test.mp3")
```
Tanmatsu uses internal FFat and T-Display P4 uses internal LittleFS. The same
serial destination `/apps/audio_test.d/test.mp3` follows the active internal
backend, so no Lua code changes are needed. Direct `sd:` playback is shown only
when `wada.sys.caps().audio_sd` is true.
Do not use `uploadfs` on a device with data you need to keep: a filesystem-image
upload replaces the internal storage partition, including settings and history.
## Error and lifecycle checks
- Disable Sound, then press **Play**: expect `Command: muted`.
- Rename the file or remove the card: expect `not found` or `no sd`.
- Try a non-WAV/MP3 extension: expect `unsupported format`.
- Remove the card during SD playback only after the baseline test. Playback must
enter `error` or stop without rebooting; reinserting the card should allow a
later play after the normal SD recovery delay.
- Receive a mesh notification during playback: it must not start a second audio
stream over the media track.
- Repeatedly open/play/close the app: each close must release the worker, codec,
amplifier, file handle, and storage lease.
## Host decoder regression test
The standalone test validates the pinned decoder and the same rolling 16 KB
input algorithm used by firmware:
```sh
c++ -std=c++17 -O2 test/test_minimp3_decoder.cpp -o /tmp/test_minimp3_decoder
/tmp/test_minimp3_decoder /path/to/your/file.mp3
```
A successful run prints decoded frames, samples per channel, sample rate,
channels, and bitrate changes. The implementation has also been checked with
CBR, VBR, leading ID3v2, trailing ID3v1, and trailing APEv2 metadata.
## Supported formats
- WAV: PCM, 16-bit, mono or stereo, 8-48 kHz.
- MP3: MPEG Layer III, mono or stereo, 8-48 kHz, CBR or VBR, with common ID3 and
APEv2 metadata.
Stereo is downmixed to the device's mono speaker path. `status()` reports
`stopped`, `playing`, `paused`, `ended`, or `error`.
+382
View File
@@ -0,0 +1,382 @@
# Console mode
A boot mode where the device runs with **no LVGL**: a text console driven by
typed commands, with core mesh functionality and Lua apps. For boards that
struggle under the UI, and for people who would rather type than tap.
Regular mode is unaffected and you can go back at any time.
---
## Short answer
**Possible: yes, and considerably more of it already exists than you would
expect.** Four of the five pieces are built and shipping today.
**A lot of work: no, not for a usable console.** The work is not the console
itself, it is everything that currently assumes the UI is there. Realistic
shape: a useful console in a few days of work, a polished one that runs Lua
apps in a couple of weeks.
**Saves resources: yes, but not the resource you might think.** See
[What it actually saves](#what-it-actually-saves) below, because this changes
how the feature should be sold and to whom.
---
## What already exists
This is the reason the estimate is not larger.
| Piece | Where | State |
|---|---|---|
| **Command surface** | `CommonCLI::handleCommand` (MeshCore core) | Done. The full command set the node already answers over serial and over the mesh. |
| **Run a command locally, capture its output** | `MyMesh::runLocalCli()` + `MyMesh::setTerminalSink()` | Done. Feed it a line, get reply lines back through a callback. |
| **Text rendering with no LVGL** | `DisplayDriver` (core): `startFrame`, `setCursor`, `print`, `printWordWrap`, `getTextWidth`, `fillRect`, `drawTextEllipsized`, `endFrame`, UTF-8 to blocks | Done, and linked into the touch build already. |
| **A mode where LVGL does not drive the panel** | Remote mode (`s_remote_mode` in `UITask.cpp`) | Done and shipping. It paints the physical screen with `display.drawTextCentered(...)` directly while LVGL renders elsewhere. This is the exact precedent. |
| **An on-device terminal** | `homeTerminalCb` / `s_term_log_box` in `UITask.cpp` | Done, but built out of LVGL widgets. The *behaviour* is the model; the widgets are what console mode replaces. |
So the console does not need a new command language, a new renderer, or a new
way of talking to the mesh. It needs a different **front end** over machinery
that is already there and already tested.
---
## What it actually saves
Worth being precise, because the obvious assumption is wrong in one direction
and right in another.
### PSRAM: a real saving, and it is the object tree, not the draw buffer
Everything LVGL allocates is PSRAM: `include/lv_conf.h` sets `LV_MEM_CUSTOM 1`
with `LV_MEM_CUSTOM_ALLOC lvglPsramAlloc`, so every object, style and font cache
entry is a PSRAM allocation, and the draw buffer is `MALLOC_CAP_SPIRAM` too.
**The draw buffer is not the prize.** `LV_DRAW_BUF_LINES` is 24, so it is
37.5 KB on the 800 px panels and **11.2 KB on the V4**. Worth having back, not
worth building a mode for.
The saving is the **object tree**: every screen, tab, list row, label, style and
cached glyph, all of it live for the life of the session. That is the number
Phase 0 exists to measure, because it is the one nobody here can quote from
memory.
For scale on the V4, its PSRAM is also carrying up to four 128 KB map tiles, so
whatever LVGL is holding sits alongside that. Console mode frees the LVGL half
outright.
**This matters most exactly where you said it hurts.** The Heltec V4 has 2 MB of
PSRAM, and PSRAM pressure there is a recurring source of real bugs: map tiles
fragmenting the heap, the tile pool needing a cull and a cap, the extended Lua
SDK gated off the board entirely for want of memory. Console mode gives that
board its PSRAM back.
### Internal DRAM: a smaller saving than it looks
The scarce resource on these boards is internal DRAM, and LVGL is largely not
in it. What *is* in it is UITask's static data: the contact cache, message
rings, layout tables. Most of that is data the console still needs to do the
same job, so it does not simply disappear.
Two caveats worth keeping honest:
- There is a fallback at boot: if the PSRAM draw-buffer allocation fails,
`malloc()` puts it in internal DRAM instead. On a board already under
pressure that is exactly when it happens, so for the worst-off devices the
DRAM saving is real after all.
- A meaningful DRAM number needs measuring, not guessing. See Phase 0.
### CPU: a real saving, and probably the one users feel
`lv_timer_handler()` runs on every pass of the main loop, alongside input-device
polling and any animation or scroll in flight, and a redraw blits through SPI.
A console redraws only when a line is added.
This is also the mechanism behind several bugs we have already fixed: the loop
being stalled by the UI is what starved the GPS UART ring, and what made SPIFFS
garbage collection visible as a freeze. Less time in the UI is less exposure to
that whole class of problem.
**How to describe the feature honestly:** it buys back PSRAM and CPU. On the
V4 that is the difference between comfortable and not. It is not a fix for
internal-DRAM exhaustion on its own.
---
## The hard parts
Not the console. These three.
### 1. Everything that assumes the UI exists
`src/main.cpp` calls `ui_task.showAlert(...)` in roughly twenty places to report
Wi-Fi and Bluetooth outcomes, and `ui_task.loop()` unconditionally. UITask is
also the owner of things the console still wants: the storage root, the Lua app
host, the update check.
The wrong fix is `#if` sprinkled through main. The right one is that UITask
keeps its role as the front end and gains a **headless personality**: the same
entry points, LVGL never initialised, `showAlert` becoming a console line.
### 2. Lua apps: the `wada.ui` translator
Decided: `wada.ui` gets a **console backend** behind the same names, so an app
keeps working without knowing which mode it is in.
This turns out to be far more achievable than "no UI" suggests, because console
mode is **not a text-only terminal**. It still owns a real pixel panel. The
thing being removed is LVGL's object tree, not the ability to draw.
The enabler is a raw framebuffer blit that already exists outside LVGL:
```
ST7789LCDDisplay::writePixelsRGB565(x, y, w, h, const uint16_t* pixels)
```
Present today on `ST7789LCDDisplay` (V4 TFT, T-Deck), `TanmatsuDisplay`,
`RM69A10Display` and `HI8561Display`. Missing only on `LGFXDisplay` (V4-R8) and
`ST7796LCDDisplay` (the pagers), and LovyanGFX has `pushImage` underneath, so
those are a wrapper method rather than new work.
That changes the answer on the two APIs that looked impossible:
| API | Console backend | Why it works |
|---|---|---|
| `label` | Text at a cursor. | `print` / `printWordWrap` / `drawTextEllipsized`. |
| `button` | A highlighted line with a selection index; activated by key or tap. | Text plus `fillRect` for the highlight. |
| `list` | Numbered lines, one selected. | Same. |
| `input` | A prompt, using the console's own keypad. | Phase 1 already builds it. |
| `text_w` / `text_lines` | `getTextWidth`, honestly measured. | Already the right shape. |
| `chart` | Drawn directly. | It is bars and lines; `fillRect` does it. |
| **`canvas`** | **Works.** The app already gets an RGB565 buffer and draws into it; console mode blits that buffer instead of handing it to LVGL. | `writePixelsRGB565`. |
| **`map`** | **Works.** Tiles are already decoded to RGB565 buffers (`MapTile.rgb565`); the projection and cache are ours and have no LVGL in them. | Same blit, plus markers as `fillRect`. |
| Everything non-UI | Unchanged. | `mesh`, `fs`, `net`, `crypto`, `geo`, `sys`, `timer`, `store` never touched LVGL. |
**What is genuinely lost is interaction, not drawing.** LVGL supplies scrolling
containers, a focus group, flex layout and event bubbling. The console backend
has to provide its own much simpler version: a line cursor, a selection index,
a scroll offset. That is the real work in this phase, and it is bounded.
So the honest expectation is that **most apps work**, including the graphical
ones, and a few that lean on LVGL behaviour we do not reimplement will not.
Apps already feature-detect through `wada.sys.caps()`, so anything that cannot
be supported is reported rather than broken, and `caps().console` lets an app
adapt its layout deliberately.
### 3. Getting back out
A boot flag that lands you in a console with no way back is a device that feels
bricked, and it will happen to somebody. This needs to be designed, not bolted
on. See [Safety](#safety).
---
## Plan
Each phase is shippable and useful on its own. Stop after any of them and
nothing is half-built.
### Phase 0: measure first
Before building anything, get the numbers the feature is being justified by.
- Free internal DRAM and free PSRAM at the home screen, on a V4 and a T-Deck.
- The same with `lv_timer_handler()` stubbed out and nothing built.
- Loop iterations per second, both ways.
Cheap, and it either confirms the case or changes what to build. If the DRAM
saving turns out to be negligible on the V4 and the PSRAM saving large, that is
worth knowing before the docs promise anything.
**Output:** real numbers in this file.
### Phase 1: the console front end
A `ConsoleUI` that owns the panel through `DisplayDriver`, with no LVGL.
- Scrollback ring in PSRAM, N lines, prune oldest.
- Prompt line, cursor, word wrap via `printWordWrap`.
- Input from the hardware keyboard where there is one.
- **An on-screen keypad on touch boards.** Decided: the V4 is the board that
most needs its resources back, so console mode has to be usable there without
a keyboard. The existing on-screen keyboard is LVGL and cannot be reused, so
the console draws its own: `fillRect` + `drawRect` + `print` for the keys, and
touch read straight from the board driver (`heltecV4CapTouchCheck()` and its
equivalents), which is already independent of LVGL. `lvglTouchRead` is only an
adapter feeding LVGL, so nothing needs to be untangled first.
- Commands go straight to `the_mesh.runLocalCli()`; output arrives through
`setTerminalSink`. This part is close to free.
- One touch affordance, as you said: a back/exit target.
At the end of this phase the device is usable over the mesh from a console.
### Phase 2: boot into it, and back out
- A pref, `touchPrefsGetBootMode()`, read early in `setup()`.
- In console mode: never call `lv_init()`, never allocate the draw buffer, never
build the UI. This is where the saving comes from, so it has to be a genuine
skip and not a hidden LVGL instance.
- `ui_task.showAlert()` and friends route to the console.
- Commands to switch: `ui` reboots into the graphical mode, `console` reboots
into this one. Also a Settings toggle in normal mode.
### Phase 3: the things the CLI does not cover
`CommonCLI` is a node CLI, not a messenger. Console mode needs conversational
commands, some of which the existing on-device terminal already has (`to <name>`
sets a recipient):
- `msg`, `to`, `reply`, unread counts, reading a thread's scrollback
- `contacts`, `chans`, `discover` with the results table
- `apps`, `run <id>`
Most of this is a thin layer over calls that already exist for the UI.
### Phase 4: Lua apps in the console
- A `WADA_UI_CONSOLE` backend behind the same `wada.ui` names, per the table
above.
- `caps()` gains `console`, `canvas`, `map` so apps can adapt, and the docs say
which apps work.
- Store apps audited; those that cannot work say so on launch rather than
failing oddly.
### Phase 5: polish
- Command history and tab completion.
- Colour, where the panel has it.
- A `help` that is actually good, since there is no discoverable UI.
- Docs page, and a section in the user guide.
---
## Safety
The failure that matters is a device that boots to a console the owner cannot
leave. Three independent ways out, because one is not enough:
1. **A command.** `ui` then reboot.
2. **A key held at boot.** Any boot with the key down forces graphical mode
regardless of the pref, the same shape as the existing recovery paths.
3. **The web flasher and the serial CLI** can always clear the pref.
And the pref should be stored so that a corrupt or unreadable value means
*graphical*, never console. Fail toward the mode everyone can use.
---
## Risks
| Risk | Containment |
|---|---|
| Console mode rots because nobody builds it | It compiles into every build from Phase 1, and SDK Test runs in it. A broken console fails the build, not a user. |
| Two front ends drift apart | The console consumes the same `runLocalCli` and the same MyMesh accessors the UI does. Do not let it grow a private copy of anything. |
| Touch-only boards get a console they cannot type into | Decide in Phase 1. Requiring a keyboard is a legitimate answer. |
| It quietly degrades normal mode | Everything new is behind the boot pref, and the graphical path keeps its current code path unchanged. Phase 0's numbers are the regression check. |
| Lua apps half-work and look broken | `caps()` first, refuse to launch second, document third. Less likely now that canvas and map can actually be drawn. |
| Two display drivers lack a raw blit | `LGFXDisplay` and `ST7796LCDDisplay` need a `writePixelsRGB565`; LovyanGFX's `pushImage` does the work. Until then `caps().canvas` is false on those boards and apps adapt. |
---
## Effort
Honest, assuming no surprises:
| Phase | Effort |
|---|---|
| 0 measure | Half a day |
| 1 console front end (incl. the drawn keypad) | 3 to 4 days |
| 2 boot mode and back out | 1 to 2 days |
| 3 messaging commands | 2 to 3 days |
| 4 `wada.ui` console backend | 4 to 6 days |
| 5 polish and docs | 2 days |
**A console you can actually use on the mesh: Phases 0 to 3, about a week.**
Phase 4 is the one that can grow, because it is the one with a design question
in it rather than just code.
---
## Open decisions
Worth settling before Phase 1 rather than during it.
1. ~~Keyboard required?~~ **Decided: no.** Touch boards get a drawn on-screen
keypad, because the V4 is exactly the board this feature is for.
2. **Do Lua apps matter in v1?** Phases 0 to 3 are worth shipping without them.
The translator is now a known quantity rather than a question mark, so it can
follow safely.
3. **Does this replace the Terminal app** in graphical mode eventually, or do
both stay?
---
## Audit: every UI surface, and its console equivalent
Done by enumerating the real thing rather than from memory: the tab list, the
app-drawer action enum (`APPACT_*`), the 19 settings categories, and the node
CLI's own command table in `CommonCLI.cpp`.
**The single most useful finding: the node CLI already covers far more than
expected.** `advert`, `board`, `clock`, `clock sync`, `erase`, `get`/`set`,
`gps` (on/off/sync/setloc/advert), `log`, `neighbors`, `ota url`, `password`,
`poweroff`, `powersaving`, `reboot`, `region`, `sensor list/get/set`,
`shutdown`, `start ota`, `tempradio`, `time`, `ver`. All of that arrives free,
which is why the console needed far fewer new commands than the UI has screens.
### Tabs and apps
| UI surface | Console | State |
|---|---|---|
| Chats: read a thread | `chat <name>` | **done** |
| Chats: send | `to <name>` + `msg <text>` | **done** |
| Chats: unread badges | `unread`, `read <name>` | **done**, and the monitor never clears them |
| Live incoming messages | the monitor, `monitor on\|off` | **done** |
| Contacts list | `contacts` | **done** |
| Contacts: favourite / block / delete | none | gap |
| Channels list | `chans` | **done** |
| Discover | `discover`, `discovered` | **done**, with both link directions |
| Advertise | CLI `advert` | free |
| Signal / traffic | `stat` | **done** |
| Map | none | needs the `wada.map` blit path; not console-shaped yet |
| Terminal | this *is* the console | n/a |
| Files | none | gap |
| Spectrum | none | gap, and heavy |
| Store / Lua apps | none | Phase 4 |
| Web reader | none | gap |
| VNC / Remote | none | deliberate: another front end, not a console feature |
| Power menu | CLI `poweroff` / `reboot` | free |
| Mentions | `unread` shows counts | partial |
### Settings, all 19 categories
| Category | Console | State |
|---|---|---|
| Radio & Mesh | CLI `get`/`set`, `region`, `tempradio` | free |
| GPS | CLI `gps *` | free |
| Clock & time | CLI `clock`, `time` | free |
| Sensors | CLI `sensor *` | free |
| About | CLI `ver`, `board`; `mem` | free |
| Battery | `batt` | **done** |
| Wi-Fi | `wifi` (state only) | partial |
| Bluetooth | none | gap |
| Auto-add | none | gap |
| Display / Keyboard / Sound / Lock screen | none | not meaningful without the UI |
| Quick replies | none | gap |
| Backups | none | gap |
| Language | none | gap |
| MQTT bridge | none | gap |
| App permissions | none | with Phase 4 |
| General | `console`/`ui` toggle | partial |
### What the gaps have in common
Almost everything still missing is either **Phase 4** (anything Lua), **not
console-shaped** (Display, Keyboard, Lock screen: settings for a UI that is not
running), or **a list-and-act flow** (files, backups, quick replies, contact
actions) that all wants the same small pattern: number the list, act on the
number. That pattern is worth building once rather than six times.
The two genuinely interesting gaps are **Files** and **contact actions**
(favourite, block, delete), because both are things people do reach for.
+22 -3
View File
@@ -13,12 +13,20 @@ 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" 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
- **T-Deck**: the everything device: touch, physical keyboard, trackball cursor
or d-pad navigation, microSD (deep 5000-message chat history, map tile packs,
data storage), GPS on the Plus, notification sounds through the I2S speaker.
Tap Sym or Alt for one symbol, or double-tap either to lock the symbol layer;
this needs [LilyGO keyboard-controller firmware with raw matrix mode](https://github.com/Xinyuan-LilyGO/T-Deck/tree/master/examples/Keyboard_ESP32C3)
(June 2025 or newer). Older controller firmware keeps normal typing and
reports the unavailable latch mode on Serial.
- **Heltec V4 + TFT**: touch UI with the on-screen keyboard; the optional
Expansion Kit adds environment sensors (home-screen chart) and a piezo
buzzer. V4.3 boards get the switchable high-gain receive LNA toggle.
@@ -26,9 +34,21 @@ 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).
Tap Fn/Alt for one symbol or double-tap it to lock the symbol layer; physical
hold combinations keep their existing behavior.
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. New in beta_38; expect rough
edges and report them.
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;
report anything that feels off.
- **RAK WisMesh Tap V2**: newest port, touch-driven. The browser-flash path is
fresh; if the flasher cannot open the serial port, put the board in download
mode manually and retry, and please report it.
@@ -40,7 +60,6 @@ Open hardware requests, roughly in demand order. Ports are welcome, see
PRs.
- LilyGo T-Deck Pro Max: [#62](https://github.com/ALLFATHER-BV/wadamesh/issues/62)
- LilyGo T-pager: [#60](https://github.com/ALLFATHER-BV/wadamesh/issues/60)
- SenseCAP Indicator D1L: [#14](https://github.com/ALLFATHER-BV/wadamesh/issues/14)
## Channels
+38 -1
View File
@@ -50,7 +50,8 @@ We do NOT bind LVGL wholesale. We bind a stable, versioned surface we own
- `wada.store` — per-app KV: `get/set(key, value)` under an `app.<id>.` prefix
in the file-mode prefs. Quota 2 KB/app (respects the SdNvsPrefs blob cap).
- `wada.sys` — `millis()`, `board()` (id, screen w/h, caps: keyboard,
trackball, gps), `version()`, `toast(msg)`.
trackball, gps), `version()`, `toast(msg)`, `tr(s)` (the firmware's own
translation table, so an app is not stuck in English).
- `wada.timer` — `every(ms)` drives `on_tick` cadence (min 33 ms).
Sandbox env (no `io`, `os`, `require`, `dofile`, `load` of new chunks;
@@ -190,3 +191,39 @@ file loads into PSRAM and overlays TR() (bsearch; file → built-in column →
EN). Users can sideload/edit their own .lang files. Built-in table stays as
fallback this beta; dropping its columns for the flash win is the follow-up
once files are field-proven.
- 2026-08-22: **wada.sys.gps() widened + wada.sys.compass() + GPS Compass
app.** gps() now carries `alt` (m) everywhere and `speed_kmh`/`course` on
boards that build their GPS on `src/helpers/WadaNmeaLocationProvider.h`
(a Wadamesh-owned copy of the core provider exposing the RMC motion fields
it keeps private; M9 first, flag `HAS_GPS_MOTION`), and it returns nil while
the user has GPS switched off. compass() is on a new HARDWARE gate
`CAP_COMPASS` (the M9's QMC6309, driver `variants/thinknode_m9/M9Compass.*`,
exposed in `caps().compass`) and hands out the raw field vector in Gauss —
calibration, axis mapping and the heading maths live in the app so they can
be adjusted per user without a firmware cut. `deploy/apps/gpscompass/1.0`
is that app: rotating rose, live fix readout, bearing/range to a contact,
C to calibrate (a 3D sphere fit that also calibrates the accelerometer's
zero-g offset from the same sweep), tilt compensation off the M9's QMI8658,
GPS-course fallback on every other board. It carries a real WMM2025
declination model (`scripts/wmm/`) so the dial and the bearings share a
north: the magnetometer measures magnetic north, every bearing computed from
coordinates is true, and drawing one against the other put every waypoint
~22° out. Headings and bearings are labelled `T` or an amber `M` accordingly.
Verified on the host harness in `scripts/lua-harness` (same vendored Lua,
same LUA_32BITS numeric model): calibration recovers a simulated hard-iron
bias exactly, heading error 0° at six test angles, bearings checked against
absolute compass directions, declination within 0.0002° of NOAA, worst tick
≈12k of the 100k instruction budget. Hardware validation (axis orientation,
real bias magnitude) is in M9_PORT.md. Not seeded into lua_builtin.h on
purpose: CAP_BUILTIN_LUA_APPS also hides the Store > Apps tab.
- 2026-08-22: **manifest `icon` implemented.** The drawer gave every Lua app
the same generic glyph while `LUA_APPS.md` had promised manifests an icon
field since the plan was written. `icon` is now read from `<id>.json` and
mapped to a glyph by NAME (`gps`, `radio`, `chart`, `game`, ...) — names,
not codepoints, so a store submission stays reviewable and an app can never
ship a missing-glyph box; anything unrecognised falls back to the generic
symbol. `deploy/site/sdk.html`'s manifest table was corrected at the same
time: it documented `version` / `min_api` / `description` / `boards`, none
of which the device has ever parsed.
+7
View File
@@ -54,6 +54,13 @@ ed25519 (bundled in lib/ed25519)
Orson Peters / orlp — public domain (Creative Commons Zero / zlib)
https://github.com/orlp/ed25519
minimp3 (bundled in lib/minimp3)
lieff/minimp3 contributors — CC0 1.0 Universal
https://github.com/lieff/minimp3
Pinned at ea99364f61c14656440e8d77e9c233ccf3124633. The bundled header has
a small opt-in scratch-storage hook so the decoder workspace can live in
PSRAM; default upstream behavior is unchanged when that hook is not used.
AsyncElegantOTA (vendored in arch/esp32/AsyncElegantOTA)
Copyright (c) Ayush Sharma — MIT License
+12 -4
View File
@@ -8,7 +8,7 @@
<p align="center"><b>A real touchscreen UI for your mesh radio.</b> &middot; open source &middot; GPL-3.0</p>
Touch-UI [MeshCore](https://github.com/meshcore-dev/MeshCore) companion-radio
firmware for the **LilyGo T-Deck / T-Deck Plus** and **Heltec V4 + TFT**
firmware for the **LilyGo T-Deck / T-Deck Plus**, **Heltec V4 + TFT** and eight other boards
(ESP32-S3).
An LVGL touch UI — map, chat, contacts, channels, settings — split out of
@@ -22,14 +22,18 @@ per-board status.
- LilyGo T-Deck / T-Deck Plus — env `LilyGo_TDeck_companion_radio_touch` (stable)
- Heltec V4 + TFT + CHSC6x touch — env `heltec_v4_tft_companion_radio_usb_tcp_touch` (stable)
- Tanmatsu (ESP32-P4) — built from `tanmatsu/` (ESP-IDF), ships via the Tanmatsu app store
- Elecrow ThinkNode M9 — env `ThinkNode_M9_companion_radio_touch` (beta)
- 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` (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
This repo holds only the **app**: the `companion_radio` glue, the `ui-touch`
LVGL UI, the two boards' glue/variants, and `platformio.ini`. The **MeshCore
LVGL UI, each board's glue/variants, and `platformio.ini`. The **MeshCore
core is not vendored here** — it's pulled as a library via `lib_deps` from the
[`ALLFATHER-BV/meshcomod`](https://github.com/ALLFATHER-BV/meshcomod) monorepo
(the same repo as the non-touch firmware), pinned by a lean source-only `core-*`
@@ -38,6 +42,10 @@ the transports, …) are dropped from the lib via `-DMC_VENDORED_TOUCH_APP` so t
aren't compiled twice. The build is byte-identical to the original in-tree
meshcomod firmware.
Lua apps use the on-device SDK described in [LUA_APPS.md](LUA_APPS.md). For
WAV/MP3 playback, including a ready-to-sideload transport test app and exact SD
and internal-storage paths, see [AUDIO_PLAYBACK_TESTING.md](AUDIO_PLAYBACK_TESTING.md).
## Build
[PlatformIO](https://platformio.org/) pulls the core fork and all libraries
+151
View File
@@ -0,0 +1,151 @@
# Sideloading wadamesh on the Tanmatsu
For developers building wadamesh from source and putting it on a Tanmatsu.
If you just want to run it, install **WadaMesh** from the launcher's app store
instead; this document is about running your own build.
## Understand the model first, or you will brick the launcher
wadamesh is **not** standalone firmware on this board. The Tanmatsu boots
badge.team's launcher, and wadamesh runs as an **AppFS app** underneath it,
exactly like the launcher's own apps.
So you never flash the whole device. You write **one app image plus one metadata
sector** into the AppFS partition and leave the bootloader, the partition table
and the OTA slots alone.
> **Never run `idf.py flash` on a Tanmatsu.** It writes the bootloader, partition
> table and OTA data, which replaces the launcher OS itself. Recovering means
> reflashing the launcher from badge.team. Every command in this guide touches
> only the AppFS partition.
The board has three processors and only one of them is yours: the **ESP32-P4**
runs the launcher and your app, an **ESP32-C6** handles Wi-Fi, Bluetooth and LoRa
over esp-hosted, and a **CH32** runs the keyboard and power. You flash the P4.
## One-time setup
You need ESP-IDF 5.5.1. The build script uses a project-local copy in
`tanmatsu/esp-idf` (gitignored, around 3 GB); `make prepare` from `tanmatsu/`
fetches it.
Then two one-off steps:
```bash
tanmatsu/tools/fetch-appfs.sh
```
This clones badge.team's `esp32-component-appfs`, whose `appfs.py` reads and
rewrites the AppFS image. It is not vendored into this repo on purpose: it is
their code, and the copy in circulation has no licence header.
```bash
tanmatsu/tools/dump-pristine.sh /dev/cu.usbmodemXXXX
```
This dumps **your** device's AppFS partition as the baseline that later deploys
diff against. Do it while the launcher's own apps are installed and wadamesh is
not, so the baseline is the device as it ships.
Use your own dump, not someone else's. The deploy writes only the sectors that
differ from this file, so if it describes a different device you can overwrite
apps you actually have.
## Build
```bash
cd tanmatsu && ./build.sh build
```
Use `build.sh`, not `idf.py` directly: it applies two build-time patches to
`managed_components` (esp-hosted Wi-Fi-init tolerance, and an Arduino BLE stub)
that the build needs.
**The build ends with an error and that is expected:**
```
Generated .../application.bin
Error: All app partitions are too small
```
The ~2.9 MB app is being size-checked against the 2 MB `ota_0` slot, but it does
not live there: it lives in the 8 MB `appfs` partition. Judge success by
`Generated ... application.bin` appearing with no `error:` or `undefined
reference` above it.
## Install
```bash
tanmatsu/tools/tan_flash.sh
```
With no port argument it probes each USB serial device and picks the one that
answers as an ESP32-P4. The Tanmatsu exposes **two** ports, the P4 and the C6,
and which name each gets changes between replugs, so detecting by chip beats
guessing. Pass a port explicitly if you prefer.
What it does, and why in this order:
1. Builds the AppFS image from your pristine baseline plus the new
`application.bin`, and works out the minimum set of 64 KB sectors that changed.
2. Writes the **app data first**, with no reset afterwards.
3. Writes the **metadata sector last**, then resets. That sector is what makes the
app visible to the launcher, so writing it last means an interrupted flash
leaves the previous app intact instead of a half-written one marked complete.
4. Reads the metadata back and compares it. The commit write is the one that can
silently drop, and without this check the launcher would quietly keep showing
the old build.
Expect `metadata verified — installed`. Anything else means re-run it.
The version number increments automatically on each deploy. It has to: the
launcher keys updates on name plus version, so republishing the same number
leaves you on the old binary with no error anywhere.
## Verify
Launch **WadaMesh** from the launcher menu. An empty serial log immediately after
flashing is normal, because the launcher is a silent GUI OS on USB-CDC; the boot
log appears once the app itself starts.
```bash
python3 tanmatsu/tools/sermon.py /dev/cu.usbmodemXXXX /tmp/wada.log
```
`sermon.py` is a non-resetting monitor that survives the USB re-enumeration when
an app launches. Prefer it to a monitor that asserts DTR/RTS: **resetting the P4
also desynchronises the C6**, which has no reset line of its own, and the launcher
then hangs on "Initializing radio" until you fully power-cycle the board.
## When it goes wrong
**No serial ports at all.** The C6 has wedged. Fully power-cycle the board, off
then on. A reset is not enough.
**"No ESP32-P4 found"** with ports present. Something else is holding the port,
often a still-running monitor. Close it and retry.
**"metadata DIFFERS".** The commit write did not land. Re-run; nothing is broken,
the device still has the previous app.
**A crash to decode.**
```bash
riscv32-esp-elf-addr2line -e tanmatsu/build/tanmatsu/application.elf -fpC <MEPC> <RA> <stack RAs>
```
## Before you ship anything
The Tanmatsu shares one `src/` with the ESP32-S3 boards, so a change here can
break them without you noticing. Build at least:
```bash
pio run -e LilyGo_TDeck_companion_radio_touch
pio run -e heltec_v4_tft_companion_radio_usb_tcp_touch
```
## Related
- `TANMATSU_PORT.md` — the port's status and outstanding work
- [wadamesh.com/sdk.html](https://wadamesh.com/sdk.html) — writing Lua apps, which
needs no firmware build at all
+97
View File
@@ -0,0 +1,97 @@
# ThinkNode M9: Keyboard & D-pad Guide
The Elecrow ThinkNode M9 has **no touchscreen** — every screen, every setting,
and every chat is driven by the d-pad, the dedicated function keys, and the
QWERTY keyboard. If you're coming from the T-Deck or Heltec V4 (touch-first),
this page is the five-minute tour that makes the board feel native.
## The inputs
- **D-pad** — four arrows around a centre button (**OK**). Arrows move the
on-screen focus highlight; OK activates whatever is focused. **Holding OK**
is the board's long-press: it fires the held item's long-press action (a
chat message's context menu, the SD row's hold-to-format) and unlocks the
lock screen.
- **Function row** — dedicated keys for Chats, Home, Mentions, Advert, Map,
Back, Mic and Ctrl (see the table below).
- **QWERTY keyboard** — the keyboard controller resolves Shift/symbol layers
itself, so keys always deliver their final character. It latches one key at
a time, which is why there are no chords on this board — long-press carries
the second layer instead. Start typing in a chat and the composer focuses
itself; any key wakes the screen from idle.
## The one rule: Back closes what you see
**Back** always closes the *top* layer, one per press: map pan mode → an open
dropdown → the power menu → the Control Center → a full-screen app → a dialog
→ any popup → an open chat → back out of the page. Nothing ever closes
invisibly beneath something else. The only exception is deliberate: progress
overlays (SD format, bulk delete) block all keys until the operation finishes.
## Function keys
| Key | Press | Hold |
|---|---|---|
| **MSG** | Jump to the Chats tab (closes an open app first) | — |
| **HOME** | Peel one layer off an open app; on the Home tab, toggle the app drawer; otherwise jump Home | — |
| **@ (Mentions)** | Open the Mentions screen | — |
| **ADV** | Open the Send Advert page | **Toggle GPS on/off** |
| **MAP** | Jump to the Map tab — press again *on* the map to toggle pan mode | — |
| **BACK** | Close the top layer (see above) | — |
| **CTRL** | Open the Control Center (quick toggles, incl. the keyboard light: off / on / auto) | — |
| **MIC** | Nothing yet — deliberately reserved | — |
| **OK / Enter** | Activate the focused item; send a message; run a terminal command; newline in the editor | **Long-press the focused item / unlock the lock screen** |
## Map pan mode
On the Map tab, press **MAP** again: the arrows now pan the map instead of
moving focus. **MAP** or **BACK** exits. Pan mode switches itself off whenever
you leave the map or anything opens over it, so a stale pan can never eat a
key press later. Auto-follow pauses while you pan and resumes when you exit.
Entering the map fresh always starts in normal navigation.
## Typing & editing
Inside a text field the left/right arrows move the caret — and when the caret
is already at the edge of the text, the same press steps focus *out* of the
field, so you're never stuck. Enter sends (toggleable under Settings), Back
leaves the field. In the Terminal, Enter runs the command; in the text editor
it inserts a newline.
## Lock screen
**Hold OK** to unlock — the keyboard's hardware long-press stands in for the
hold-to-unlock other boards do by touch. With "Flash on new message" enabled,
an incoming message wakes (or lock-reveals) the screen and pulses the keyboard
backlight.
## Inside apps
Store apps (Snake and friends) get the d-pad natively: arrows steer, OK taps
the centre — start, steer, and tap-to-retry all work. Display-only apps
(Airtime, RF Monitor) keep normal navigation: arrows move between the app's
own buttons or scroll the feed. **Back and Home always escape an app** — no
app can trap the keys, even while the screen is locked.
## Recent improvements (beta_66 branch)
If you last used the M9 on an earlier beta, the notable navigation changes:
- **Back restored and made consistent** — it had regressed to doing nothing
outside text fields, and could close hidden popups beneath the Control
Center. Both fixed; the close-what-you-see rule above now holds everywhere.
- **Apps can't strand you** — opening Advert/Mentions over a running app used
to orphan it with no key path back; app permission dialogs are now
answerable with the d-pad.
- **Map pan cleans up after itself** (see above — it used to leak across tab
jumps).
- **Keyboard light "On" applies at boot**, not after the first dim cycle.
- **Terminal chat shows incoming replies**, not just your own sent lines.
- **GPS works from a cold boot** — the toggle (and ADV-hold) no longer depends
on a boot-time detection race.
- **Spectrum analyzer** sweeps roughly twice as fast, survives read glitches
without flattening the trace, and waits for an in-flight transmission
instead of cutting it off when opened mid-send.
The engineering record behind these lives in
[`variants/thinknode_m9/M9_PORT.md`](variants/thinknode_m9/M9_PORT.md).
+131 -39
View File
@@ -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
@@ -170,8 +225,8 @@ WASD-panning).
`updatePagerAltShiftChord()` toggles Caps Lock ONLY while a text field is
actually being edited (same "ta" derivation `handleHwKey()`'s TLORA_PAGER
branch already uses to tell a bound-but-unfocused field apart from one
actually being edited), and jumps straight to Home (`navGoToMainTab`)
everywhere else.
actually being edited), and is a no-op everywhere else. Alt+Backspace is
the context-independent Home shortcut.
3. **@-mention contact picker made encoder-navigable** (commit `57802eb`) —
the same unreachable-without-touch problem the accent box had, fixed the
same way (`mentionNavRestyle()`/`mentionNavConfirm()` mirror
@@ -567,9 +622,9 @@ existing boards. Notes:
`pagerKeyboardConsumeAltShiftChord()`; `UITask.cpp`'s
`updatePagerAltShiftChord()` toggles persistent Caps Lock ONLY while a text
field is actually being edited (same "ta" derivation as `handleHwKey()`'s
TLORA_PAGER branch), and jumps straight Home (`navGoToMainTab`) everywhere
else — toggling Caps Lock with no field to see it change in was reported as
surprising/purposeless outside of typing.
TLORA_PAGER branch), and is a no-op everywhere else — toggling Caps Lock
with no field to see it change in was reported as surprising/purposeless
outside of typing. Alt+Backspace owns the Home shortcut.
See `PagerKeyboard.cpp`'s matrix-legend comment for the one documented
edge case (Alt+Shift+O or Alt+Shift+L all three held phantom-ghosts a
stray 'q'/'a' — a diode-less-matrix limitation, not a bug, and not the
@@ -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,15 +741,17 @@ 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 |
| @-mention picker keyboard nav | Auto-arms the instant the list appears (no Fn+Space needed); same encoder walk/confirm/cancel as the accent popup (`s_mentionnav_active`/`mentionNavRestyle()`/`mentionNavConfirm()`) | medium | done |
| Encoder short click on a focused bubble | Mirrors keyboard Enter — opens the same action menu instead of a plain ENTER a bubble doesn't react to | small | done |
| Fn+Shift chord effect | Toggles Caps Lock while editing a text field; jumps to Home (`navGoToMainTab`) everywhere else — `PagerKeyboard.cpp` only reports the chord, `UITask.cpp` decides the effect | small | done |
| Fn+Shift chord effect | Toggles Caps Lock while editing a text field; no-op everywhere else. Fn+Backspace jumps Home — `PagerKeyboard.cpp` only reports the chords, `UITask.cpp` decides the effects | small | done |
| Map pan (WASD) + slider nudge (Q/E) | WASD pans the Map tab (`mapNudge()`, shared with Tanmatsu's Ctrl+Arrow); Q/E adjust a focused slider (moved off D/F to avoid colliding with WASD) | small | done |
| App-drawer tile focus highlight | `NAV_ACCENTFOCUS_FLAG` makes `navFocusCb` use the tile's own accent tint instead of the generic white reverse-fill, on every board | small | done |
| SX1262-variant env | `tlora_pager_sx1262_companion_radio_touch` — same board/pins, `CustomSX1262`/`CustomSX1262Wrapper` instead of the LR1121 classes | medium | done (worklist ⑩) |
@@ -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
+15 -22
View File
@@ -40,7 +40,7 @@ while editing a text field, where the keys type normally.
| Gesture | Action | Keyboard equivalent |
|---|---|---|
| Turn | Move focus to the next/previous item on screen | **Fn (Alt) tapped alone** moves forward one step (NEXT only — no keyboard way to go backward) |
| Turn | Move focus to the next/previous item on screen | none — encoder only |
| Short click | Select / confirm the focused item | **Enter** |
| Hold ~1 s, then release | **Back**: closes a popup → closes an open chat → goes Home → Esc (whichever applies first) | **Backspace held ~1 s** |
| **Fn (Alt) + turn**, on a main tab | Move between the 5 main tabs (Mail / Contacts / Home / Map / Settings) | **M / C / H / A / S** jumps directly |
@@ -93,29 +93,19 @@ text box → Send**, in that order, in both directions — nothing is skipped.
Turning past the △ chip (toward the messages) always jumps straight to the
newest message, regardless of channel or DM.
### Backspace and Fn (Alt) — leaving vs. catching up
### Backspace — catching up
These two keys are your shortcuts in and out of "reading mode" on this
screen, and they do different things depending on whether you've got unread
messages:
**Backspace (tap)** jumps to whichever message needs your attention:
- **Fn (Alt) tapped alone** — jumps straight to the **newest** message and
moves focus into the text box, ready to type a reply. This is the
deliberate "I'm done reading, let me respond" gesture — it works regardless
of where your focus currently is in the chat.
- **Backspace (tap)** — jumps to whichever message needs your attention:
- If there are unread messages, it jumps to the first one — right below the
**"NEW ----"** divider — and selects it, so you can then turn forward
through your unread messages in order, oldest-of-the-unread first.
- If nothing is unread, it jumps to the newest message instead (same
destination as Fn+Alt, but leaves focus on the message itself rather than
the text box).
- If there are unread messages, it jumps to the first one — right below the
**"NEW ----"** divider — and selects it, so you can then turn forward
through your unread messages in order, oldest-of-the-unread first.
- If nothing is unread, it jumps to the newest message instead (same
destination, with focus left on the message).
Backspace's override above only applies while you're inside an open chat and
*not* actively editing the text box — the usual rule from the top of this
guide; with a field focused, Backspace deletes a character as normal.
Fn (Alt) tap's override fires the same way whether or not the text box
already has focus, since landing there is the whole point of the gesture.
## Keyboard layout
@@ -128,7 +118,9 @@ a s d f g h j k l [Enter]
[Space]
```
Hold **Fn (Alt)** for numbers/symbols instead:
Hold **Fn (Alt)** for numbers/symbols, or tap it once to apply this layer to
the next key only. Double-tap Fn to lock the symbol layer; tap it again to
return to letters.
```
1 2 3 4 5 6 7 8 9 0
@@ -162,7 +154,7 @@ Hold **Fn (Alt)** for numbers/symbols instead:
| **Space** (tap) | Types a space | — |
| **Space** (double-tap, within 250 ms) | Switches between English and your configured secondary keyboard layout | — |
| **Space** (hold ~1 s) | — | Locks the screen (shows a "Locking…" progress bar; tapping any key cancels) |
| **Fn (Alt)** tapped alone (press+release, nothing else) | — | Moves focus to the next field/item — a keyboard-only substitute for a turn of the encoder. In an open chat: jumps to the newest message and focuses the text box instead — see [Chat screen](#chat-screen) |
| **Fn (Alt)** (tap / double-tap) | Next key uses symbols / lock symbols until tapped again | Same |
The **BOOT** button (top of the device) instantly wakes the screen from
idle-dim. It does *not* unlock a screen you've manually locked with the
@@ -249,13 +241,14 @@ that changes keyboard language.
| Input | Action |
|---|---|
| M / C / H / A / S (top-level main screens only) | Open Mail / Contacts / Home / Map / Settings |
| Turn encoder (or Fn tap = NEXT only) | Move focus |
| Turn encoder | Move focus |
| Turn, at the loaded edge of a chat | Load more history, keep moving — only exits the list at the true oldest/newest message |
| Click encoder (or Enter) | Select / confirm |
| Hold encoder ~1s (or hold Backspace ~1s) | Back |
| Fn + turn (main tab) | Switch tabs |
| Fn + turn (page/chat) | Scroll |
| Fn tap alone | Next field (in a chat: jump to newest message + focus the text box) |
| Fn tap alone | Use the symbol layer for the next key |
| Fn double-tap | Lock the symbol layer; tap Fn again to unlock |
| Hold Shift + letter | Momentary uppercase |
| Fn + Shift (editing a field) | Toggle Caps Lock |
| Fn + Shift (not editing a field) | Nothing |
+14 -7
View File
@@ -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_<N>`, 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
+31 -4
View File
@@ -13,9 +13,20 @@ 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.
API — `wada.ui` (widgets, colours, a text prompt), `wada.sys`, `wada.store`
(persistence), `wada.timer`, and on the larger boards `wada.fs`, `wada.net`,
`wada.crypto` and the writable half of `wada.mesh`. Supported boards also expose
asynchronous WAV/MP3 playback through `wada.audio`; plain filenames come from the
app sandbox on internal flash, SD, or SD_MMC. Read-only physical-SD directory
metadata is available through `wada.sd`, and direct card playback uses an explicit
`sd:/...` path. There is no general-purpose filesystem or network access; the API
is the whole surface, which is what makes reviewing tractable. It is documented at
[wadamesh.com/sdk.html](https://wadamesh.com/sdk.html).
Two numbers worth knowing before you start: every callback runs under a
**100,000 Lua instruction** budget, and Lua here is built with **32-bit numbers**,
so its floats are single precision. If you are logging coordinates, use the
`lat_e6` / `lon_e6` integers rather than `lat` / `lon`.
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
@@ -34,12 +45,18 @@ deploy/apps/<id>/<ver>/<id>.lua the app
The manifest is one line:
```json
{"id":"snake","name":"Snake","ver":"1.0","desc":"The classic, in Lua. Swipe to steer."}
{"id":"snake","name":"Snake","ver":"1.0","desc":"The classic, in Lua. Swipe to steer.","icon":"game"}
```
`desc` is what people read in the store listing before installing, so make it say
what the app *does*. One sentence.
`icon` is optional and picks the drawer tile's glyph by NAME — an app cannot
ship its own artwork, so anything unrecognised falls back to the generic app
symbol. Choose from: `gps` / `compass` / `map`, `radio`, `signal`, `chart`,
`list`, `message`, `person`, `group`, `bell`, `star`, `search`, `settings`,
`battery`, `game`.
**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.
@@ -49,6 +66,11 @@ some users silently run different code from others under the same version number
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).
Add `"seed": false` to that row if your app should be downloadable but not
compiled into the firmware. Apps in the catalog are baked into the image as
built-ins for boards that cannot reach the Store, and that is flash spent on
the boards with the least of it. A large app, or one that needs hardware
those boards do not have, is better left to the Store.
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`.
@@ -84,6 +106,11 @@ people's devices. We read every submission for:
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.
- **Probing** — `wada.mesh.discover()` costs a transmission from the user *and a
reply from every node that hears it*, so it spends other people's airtime as
well as theirs. The firmware enforces 15 seconds between probes, but a survey
app is still expected to probe on a cadence a person chose and to stop when it
is not on screen. Probing in a loop for no stated reason gets sent back.
- **Where data goes** — anything leaving the device has to be something the user
asked for and can see.
+6
View File
@@ -0,0 +1,6 @@
{
"id": "airtime",
"name": "Airtime",
"ver": "1.4",
"desc": "Utilization bars with a % axis, rx/tx split, duty ceiling, budget. Reset button top-right."
}
+95
View File
@@ -0,0 +1,95 @@
-- Airtime (Lua) — channel utilization over time: live + average bars with a %
-- axis, rx/tx air split, duty ceiling, tx budget and packet counters.
local ui, sys, mesh, timer = wada.ui, wada.sys, wada.mesh, wada.timer
-- Translate through the device's language table (wada.sys.tr, added for #257).
-- Older firmware has no sys.tr, so fall back to the English string rather than error.
local tr = sys.tr or function(x) return x end
local C = ui.colors
local app = {}
local W, narrow
local head, sub, legend, detail, chart
local base, t0, last
local peak_pct = 0
local function restart_window()
local st = mesh.stats()
base = { rx = st.rx_air_s, tx = st.tx_air_s }
t0 = sys.millis()
last = { ms = t0, rx = st.rx_air_s, tx = st.tx_air_s }
peak_pct = 0
chart:fill(1, 0)
chart:fill(2, 0)
head:set(tr("sampling..."))
head:color(C.accent)
sys.toast(tr("window restarted"), 900)
end
local function refresh()
local st = mesh.stats()
local now = sys.millis()
local wall = (now - t0) / 1000
if wall < 0.5 then return end
local rx_air, tx_air = st.rx_air_s - base.rx, st.tx_air_s - base.tx
local avg = math.min(100, (rx_air + tx_air) * 100 / wall)
local dw = (now - last.ms) / 1000
local live = 0
if dw > 0 then
live = math.min(100, ((st.rx_air_s - last.rx) + (st.tx_air_s - last.tx)) * 100 / dw)
end
last = { ms = now, rx = st.rx_air_s, tx = st.tx_air_s }
if live > peak_pct then peak_pct = live end
chart:push(1, math.floor(live))
chart:push(2, math.floor(avg))
head:set(string.format(tr("channel busy %.1f%%"), live))
head:color(live > 50 and C.bad or live > 20 and 0xE8A33D or C.good)
sub:set(string.format(tr("avg %.1f%% peak %.1f%% over %ds"), avg, peak_pct, math.floor(wall)))
if narrow then
detail:set(string.format("air rx %ds / tx %ds\nduty %d%% budget %dms\ntx %d rx %d err %d",
rx_air, tx_air, st.duty_pct, st.tx_budget_ms, st.tx_pkts, st.rx_pkts, st.rx_err))
else
detail:set(string.format("air rx %ds / tx %ds duty %d%% budget %dms\ntx %d rx %d err %d drop %d SF%d",
rx_air, tx_air, st.duty_pct, st.tx_budget_ms, st.tx_pkts, st.rx_pkts, st.rx_err, st.rx_dropped, st.sf))
end
end
function app.on_open(w, h)
W, narrow = w, w < 280
local LH12, LH16 = ui.text_h(12), ui.text_h(16)
local y = 2
head = ui.label(tr("sampling..."), 4, y, 16, C.accent); head:width(w - 86)
ui.button(tr("Reset"), w - 76, y, 70, 30, function() restart_window() end) -- top-right
y = y + LH16 + 4
sub = ui.label("", 4, y, 12, C.sub); sub:width(w - 10)
y = y + LH12 + 5
local AX = 34
local det_lines = narrow and 3 or 2
local ch_h = h - y - (det_lines * LH12) - LH12 - 14
if ch_h < 48 then ch_h = 48 end
if ch_h > 110 then ch_h = 110 end
chart = ui.chart(w - AX - 8, ch_h, 60, C.accent, 0x4F9DF7, true)
chart:pos(AX, y)
chart:range(0, 100)
chart:axis(3, AX)
y = y + ch_h + 4
legend = ui.label(tr("teal = now blue = average"), 4, y, 12, C.sub); legend:width(w - 10)
y = y + LH12 + 2
detail = ui.label("", 4, y, 12, C.text); detail:width(w - 10)
local st = mesh.stats()
base = { rx = st.rx_air_s, tx = st.tx_air_s }
t0 = sys.millis()
last = { ms = t0, rx = st.rx_air_s, tx = st.tx_air_s }
timer.every(1000)
end
function app.on_tick(dt) refresh() end
return app
+24 -3
View File
@@ -9,7 +9,7 @@
{
"id": "airtime",
"name": "Airtime",
"ver": "1.3",
"ver": "1.4",
"desc": "Utilization bars with a % axis, rx/tx split, duty ceiling, budget. Reset button top-right."
},
{
@@ -21,14 +21,35 @@
{
"id": "sdktest",
"name": "SDK Test",
"ver": "1.1",
"desc": "Developer tool. Checks the extended Lua SDK on this board: capabilities, clock, battery, GPS, file access and its limits, keyboard input. Has a button that TRANSMITS a test message to Public (asks permission first)."
"ver": "1.7",
"desc": "Developer tool. Checks the extended Lua SDK on this board: capabilities, clock, battery, GPS, private file access, audio API, read-only SD listing, crypto against published RFC vectors, channel discovery, and buttons that TRANSMIT test messages."
},
{
"id": "2048",
"name": "2048",
"ver": "1.2",
"desc": "The classic sliding-tile puzzle. Swipe to move, tap to restart. Keeps your best score. Contributed by pisti87."
},
{
"id": "wardrive",
"name": "Wardrive",
"ver": "1.1",
"desc": "LoRa coverage survey. Probes every 20s and logs each reply with GPS position, altitude and BOTH link directions (how well you heard them, how well they heard you) to a CSV. Reference app for wada.mesh.discover.",
"requires": "sdk_ext"
},
{
"id": "nearby",
"name": "Nearby",
"ver": "1.0",
"desc": "Your contacts on a real map, sorted by distance, with bearing and a live frame counter. Reference app for wada.map, wada.ui.list, wada.geo and app.on_packet.",
"requires": "sdk_ext"
},
{
"id": "gpscompass",
"name": "GPS Compass",
"ver": "1.0",
"desc": "Compass rose: magnetometer or GPS course, live fix, bearing to contacts",
"seed": false
}
]
}
@@ -0,0 +1 @@
{"id":"gpscompass","name":"GPS Compass","ver":"1.0","desc":"Compass rose: magnetometer or GPS course, live fix, bearing to contacts","icon":"gps"}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+102 -7
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: bg
# ver: 12
# ver: 20
# name: Български
# base: bg
(device behind) (устройството изостава)
@@ -184,6 +184,7 @@ Contact added Контактът е добавен
Contact deleted Контактът е изтрит
Contact gone Контактът изчезна
Contact missing Контактът липсва
Contact shared Контактът е споделен
Contacts Контакти
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Контактите са във вътрешната памет - SD картата не се монтира при старт. Постави картата отново и рестартирай.
Contacts are on internal flash. Контактите са във вътрешната памет.
@@ -282,6 +283,7 @@ End time Краен час
Enter SSID first Първо въведете SSID
Enter a name Въведете име
Enter a network name Въведете име на мрежа
Enter a region name Enter a region name
Enter adds a new line Enter добавя нов ред
Enter exactly 32 hex characters. Въведете точно 32 hex знака.
Enter key sends message Клавишът Enter изпраща съобщението
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Клавиатурна навиг.: WASDZ вкл.
Keyboard nav: off Клавиатурна навиг.: изкл.
Keyboard navigation Навигация с клавиатура
Keys
Known regions Known regions
LOS → %s Пряка видимост → %s
Landscape (desktop) Пейзаж (десктоп)
Landscape set - applies when remote mode starts. Пейзажът е зададен - прилага се при стартиране на отдалечения режим.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Няма намерени мрежи (само
No onboard GPS Няма вграден GPS
No other networks found Не са открити други мрежи
No position yet. A cold start needs a clear view of the sky and can take several minutes. Още няма позиция. Студен старт изисква чисто небе и може да отнеме няколко минути.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Няма отговор от %s
No reply. Check password, server,\nor device clock (device: %s) Няма отговор. Проверете паролата, сървъра\nили часовника на устройството (устройство: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Тук няма запазени плочки.\n\nСвържете се с Wi-Fi (Настройки → Wi-Fi),\nза да изтеглите този район.\nЗапазените плочки остават достъпни офлайн.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Наскоро чути
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Форматиране на SD като MESHCOMOD (FAT32)?\nВСИЧКИ данни на картата ще бъдат изтрити.
Region & scope Регион и обхват
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Регионален обхват (#tag) за този канал.\nПразно = обхват по подразбиране.
Region scope (#tag), blank = default. Обхват на регион (#tag), празно = по подразбиране.
Region scope (#tag, blank = none) Регионален обхват (#tag, празно = няма)
@@ -683,6 +688,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 +701,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 +729,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 Сканирай, за да отвориш на телефона
@@ -770,6 +779,8 @@ Settings Настройки
Setup complete Настройката е готова
Share QR Сподели QR
Share channel Сподели канала
Share contact Сподели контакт
Share failed Споделянето неуспешно
Share location in advert Споделяй местоположението в advert
Share secret Сподели ключа
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Споделете 32-символната тайна, за да се присъединят други. Празно = случайна.
@@ -818,7 +829,7 @@ TCP on TCP вкл
TOUCH BETA TOUCH BETA
TX TX
Tab hotkeys — tap a row, then press a key Клавиши за раздела — докосни ред, после натисни клавиш
Tap Use to switch - the device reboots to apply. Натиснете „Избери“, за да превключите — устройството ще се рестартира.
Tap Use to switch - the device reboots to apply. Натиснете "Избери", за да превключите — устройството ще се рестартира.
Tap Use to switch - the device reboots to apply. Language files live in /lang on the storage; edit them or add your own. Докосни «Избери» за смяна - устройството се рестартира. Езиковите файлове са в /lang в паметта; редактирай ги или добави свои.
Tap a language; the device reboots to apply. Изберете език; устройството ще се рестартира.
Taste the rainbow! Вкуси дъгата!
@@ -926,6 +937,7 @@ Your own apps Твоите приложения
Zero-hop Без препредаване
Zero-hop advert sent Zero-hop advert изпратен
Zoom: +/- buttons Мащаб: бутони +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected клиент свързан
command команда
contacts (%d): контакти (%d):
@@ -968,8 +980,6 @@ tap to exit full screen докоснете за изход от цял екра
zoom мащаб
zoom %d мащаб %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. усилвател ~17 dB за тихи/отдалечени места; изключи в шумни.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1001,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1014,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+102 -11
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: de
# ver: 12
# ver: 20
# name: Deutsch
# base: de
(device behind) (Gerät geht nach)
@@ -184,6 +184,7 @@ Contact added Kontakt hinzugefügt
Contact deleted Kontakt gelöscht
Contact gone Kontakt weg
Contact missing Kontakt fehlt
Contact shared Kontakt geteilt
Contacts Kontakte
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Kontakte liegen im internen Flash - die SD-Karte wurde beim Start nicht eingebunden. Karte neu einsetzen und neu starten.
Contacts are on internal flash. Kontakte liegen im internen Flash.
@@ -282,6 +283,7 @@ End time Endzeit
Enter SSID first Zuerst SSID eingeben
Enter a name Namen eingeben
Enter a network name Netzwerknamen eingeben
Enter a region name Enter a region name
Enter adds a new line Enter fügt neue Zeile ein
Enter exactly 32 hex characters. Genau 32 Hex-Zeichen eingeben.
Enter key sends message Enter-Taste sendet Nachricht
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Tastaturnav.: WASDZ an
Keyboard nav: off Tastaturnav.: aus
Keyboard navigation Tastaturnavigation
Keys Tasten
Known regions Known regions
LOS → %s Sichtlinie → %s
Landscape (desktop) Querformat (Desktop)
Landscape set - applies when remote mode starts. Querformat gesetzt - gilt beim Start des Fernmodus.
@@ -450,7 +453,6 @@ Login OK (perms %u) Anmeldung OK (Rechte %u)
Login failed Anmeldung fehlgeschlagen
Logs Protokolle
Longitude Längengrad
Lua Store Lua Store
MHz MHz
MQTT bridge MQTT-Brücke
Map Karte
@@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Keine Netzwerke gefunden (nur 2,4 GHz)
No onboard GPS Kein integriertes GPS
No other networks found Keine anderen Netzwerke gefunden
No position yet. A cold start needs a clear view of the sky and can take several minutes. Noch keine Position. Ein Kaltstart braucht freie Sicht zum Himmel und kann mehrere Minuten dauern.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Keine Antwort von %s
No reply. Check password, server,\nor device clock (device: %s) Keine Antwort. Prüfe Passwort, Server\noder Geräteuhr (Gerät: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Hier keine gespeicherten Kacheln.\n\nMit Wi-Fi verbinden (Einstellungen → Wi-Fi),\num dieses Gebiet zu laden.\nGespeicherte Kacheln bleiben offline verfügbar.
@@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Kürzlich gehört
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. SD als MESHCOMOD (FAT32) neu formatieren?\nALLE Daten auf der Karte werden gelöscht.
Region & scope Region & Reichweite
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Regionsbereich (#tag) für diesen Kanal.\nLeer = Standardbereich verwenden.
Region scope (#tag), blank = default. Regionsbereich (#tag), leer = Standard.
Region scope (#tag, blank = none) Regionsbereich (#tag, leer = keiner)
@@ -683,18 +687,20 @@ 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
SD card removed SD-Karte entfernt
SD data is unavailable - contacts and channels cannot be saved until the card is reinserted. SD-Daten nicht verfügbar – Kontakte und Kanäle können erst nach Einsetzen der Karte gespeichert werden.
SD data is unavailable - identity, settings, contacts and channels cannot be saved until the card is reinserted. SD-Daten nicht verfügbar – Identität, Einstellungen, Kontakte und Kanäle können erst nach Einsetzen der Karte gespeichert werden.
SD data migration is incomplete. Identity and settings remain internal; use Copy internal data to SD to retry. SD-Datenübertragung unvollständig. Identität und Einstellungen bleiben intern; „Interne Daten auf SD kopieren“ zum erneuten Versuch verwenden.
SD data migration is incomplete. Identity and settings remain internal; use Copy internal data to SD to retry. SD-Datenübertragung unvollständig. Identität und Einstellungen bleiben intern; "Interne Daten auf SD kopieren" zum erneuten Versuch verwenden.
SD download failed: %s SD-Download fehlgeschlagen: %s
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 +728,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
@@ -770,6 +778,8 @@ Settings Einstellungen
Setup complete Einrichtung abgeschlossen
Share QR QR teilen
Share channel Kanal teilen
Share contact Kontakt teilen
Share failed Teilen fehlgeschlagen
Share location in advert Standort im Advert teilen
Share secret Geheimnis teilen
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Teilen Sie das 32-Zeichen-Geheimnis, damit andere beitreten. Leer lassen für ein zufälliges.
@@ -789,7 +799,6 @@ Sleep ready Bereit zum Schlafen
Slot %d cleared Slot %d gelöscht
Slot empty Slot leer
Small\nMedium\nLarge Klein\nMittel\nGroß
Snake Snake
Snake — swipe or roll the trackball Snake — wischen oder Trackball rollen
Sort Sortieren
Sound Ton
@@ -797,7 +806,6 @@ Sound off Ton aus
Sound on Ton ein
Sound: %s Ton: %s
Start time Startzeit
Status Status
Step 1 of 3 Schritt 1 von 3
Step 2 of 3 Schritt 2 von 3
Step 3 of 3 Schritt 3 von 3
@@ -810,7 +818,6 @@ Streams the device screen as a live picture you tap to control. Heavier; the pan
Switch Wechseln
Switch to the external antenna?\n\nMake sure an antenna is actually connected to the external antenna socket first. Transmitting with nothing attached can damage the radio.\n\nResets to the on-board antenna on every reboot. Auf die externe Antenne wechseln?\n\nErst sicherstellen, dass wirklich eine Antenne an der Buchse steckt. Senden ohne Antenne kann das Funkmodul beschädigen.\n\nFällt bei jedem Neustart auf die interne Antenne zurück.
Sync clock from system Uhr synchronisieren
System System
System info Systeminfo
TCP %s BLE %s\nWS clients %d GPS %s Buzzer %s TCP %s BLE %s\nWS-Clients %d GPS %s Summer %s
TCP off TCP aus
@@ -926,6 +933,7 @@ Your own apps Eigene Apps
Zero-hop Ohne Hop
Zero-hop advert sent Zero-Hop-Advert gesendet
Zoom: +/- buttons Zoom: +/- Tasten
ambiguous (several regions matched) ambiguous (several regions matched)
client connected Client verbunden
command Befehl
contacts (%d): Kontakte (%d):
@@ -968,8 +976,6 @@ tap to exit full screen tippen zum Verlassen des Vollbilds
zoom Zoom
zoom %d Zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. ~17 dB Verstärker für ruhige/abgelegene Gebiete; in lauten Zonen aus.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +997,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1010,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -6
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: el
# ver: 12
# ver: 20
# name: Ελληνικά
# base: el
(device behind) (συσκευή πίσω)
@@ -184,6 +184,7 @@ Contact added Η επαφή προστέθηκε
Contact deleted Η επαφή διαγράφηκε
Contact gone Η επαφή χάθηκε
Contact missing Η επαφή λείπει
Contact shared Η επαφή κοινοποιήθηκε
Contacts Επαφές
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Οι επαφές είναι στην εσωτερική μνήμη - η κάρτα SD δεν προσαρτήθηκε στην εκκίνηση. Επανατοποθετήστε την και επανεκκινήστε.
Contacts are on internal flash. Οι επαφές είναι στην εσωτερική μνήμη.
@@ -282,6 +283,7 @@ End time Ώρα λήξης
Enter SSID first Εισαγάγετε πρώτα το SSID
Enter a name Εισαγάγετε όνομα
Enter a network name Εισαγάγετε όνομα δικτύου
Enter a region name Enter a region name
Enter adds a new line Το Enter προσθέτει γραμμή
Enter exactly 32 hex characters. Εισαγάγετε ακριβώς 32 hex χαρακτήρες.
Enter key sends message Το πλήκτρο Enter στέλνει το μήνυμα
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Πλοήγηση πληκτρ.: WASDZ ενεργό
Keyboard nav: off Πλοήγηση πληκτρ.: κλειστό
Keyboard navigation Πλοήγηση με πληκτρολόγιο
Keys
Known regions Known regions
LOS → %s Οπτική επαφή → %s
Landscape (desktop) Οριζόντια (desktop)
Landscape set - applies when remote mode starts. Ορίστηκε οριζόντια - ισχύει όταν ξεκινήσει η απομακρυσμένη λειτουργία.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Δεν βρέθηκαν δίκτυα (μόνο
No onboard GPS Χωρίς ενσωματωμένο GPS
No other networks found Δεν βρέθηκαν άλλα δίκτυα
No position yet. A cold start needs a clear view of the sky and can take several minutes. Δεν υπάρχει ακόμη θέση. Η ψυχρή εκκίνηση θέλει ανοιχτό ουρανό και μπορεί να πάρει λεπτά.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Καμία απάντηση από %s
No reply. Check password, server,\nor device clock (device: %s) Καμία απάντηση. Ελέγξτε κωδικό, διακομιστή\nή ρολόι συσκευής (συσκευή: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Δεν υπάρχουν αποθηκευμένα πλακίδια εδώ.\n\nΣυνδεθείτε στο Wi-Fi (Ρυθμίσεις → Wi-Fi)\nγια λήψη αυτής της περιοχής.\nΤα αποθηκευμένα πλακίδια μένουν διαθέσιμα εκτός σύνδεσης.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Ακούστηκε πρόσφατα
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Επαναδιαμόρφωση SD ως MESHCOMOD (FAT32);\nΟΛΑ τα δεδομένα στην κάρτα θα διαγραφούν.
Region & scope Περιοχή & εμβέλεια
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Εύρος περιοχής (#tag) για αυτό το κανάλι.\nΚενό = προεπιλεγμένο εύρος.
Region scope (#tag), blank = default. Εύρος περιοχής (#tag), κενό = προεπιλογή.
Region scope (#tag, blank = none) Εύρος περιοχής (#tag, κενό = κανένα)
@@ -683,6 +688,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 +701,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 +729,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 Σαρώστε για άνοιγμα στο κινητό
@@ -770,6 +779,8 @@ Settings Ρυθμίσεις
Setup complete Η ρύθμιση ολοκληρώθηκε
Share QR Κοινοποίηση QR
Share channel Κοινή χρήση καναλιού
Share contact Κοινοποίηση επαφής
Share failed Αποτυχία κοινοποίησης
Share location in advert Κοινή χρήση θέσης στο advert
Share secret Κοινοποίηση μυστικού
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Μοιραστείτε το μυστικό 32 χαρακτήρων για να συμμετάσχουν άλλοι. Κενό = τυχαίο.
@@ -926,6 +937,7 @@ Your own apps Οι δικές σας εφαρμογές
Zero-hop Χωρίς άλμα
Zero-hop advert sent Στάλθηκε zero-hop advert
Zoom: +/- buttons Ζουμ: κουμπιά +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected ο πελάτης συνδέθηκε
command εντολή
contacts (%d): επαφές (%d):
@@ -968,8 +980,6 @@ tap to exit full screen πατήστε για έξοδο από πλήρη οθ
zoom ζουμ
zoom %d ζουμ %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. ενισχυτής ~17 dB για ήσυχες/απομακρυσμένες περιοχές· κλείστε σε θορυβώδεις.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1001,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1014,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -6
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: es
# ver: 12
# ver: 20
# name: Español
# base: es
(device behind) (dispositivo atrasado)
@@ -184,6 +184,7 @@ Contact added Contacto añadido
Contact deleted Contacto eliminado
Contact gone Contacto perdido
Contact missing Falta el contacto
Contact shared Contacto compartido
Contacts Contactos
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Los contactos están en memoria interna - la tarjeta SD no se montó al arrancar. Reinserta la tarjeta y reinicia.
Contacts are on internal flash. Los contactos están en la memoria interna.
@@ -282,6 +283,7 @@ End time Hora de fin
Enter SSID first Introduce primero el SSID
Enter a name Introduce un nombre
Enter a network name Introduce un nombre de red
Enter a region name Enter a region name
Enter adds a new line Enter añade una línea
Enter exactly 32 hex characters. Introduce exactamente 32 caracteres hex.
Enter key sends message La tecla Enter envía el mensaje
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Nav. teclado: WASDZ act.
Keyboard nav: off Nav. teclado: desact.
Keyboard navigation Navegación por teclado
Keys
Known regions Known regions
LOS → %s Línea de vista → %s
Landscape (desktop) Horizontal (escritorio)
Landscape set - applies when remote mode starts. Horizontal fijado - se aplica al iniciar el modo remoto.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) No se encontraron redes (solo 2.4 GHz)
No onboard GPS Sin GPS integrado
No other networks found No se encontraron otras redes
No position yet. A cold start needs a clear view of the sky and can take several minutes. Aún sin posición. Un arranque en frío necesita cielo despejado y puede tardar varios minutos.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Sin respuesta de %s
No reply. Check password, server,\nor device clock (device: %s) Sin respuesta. Revisa contraseña, servidor\no reloj del dispositivo (dispositivo: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. No hay teselas guardadas aquí.\n\nConéctate a Wi-Fi (Ajustes → Wi-Fi)\npara descargar esta zona.\nLas teselas guardadas quedan disponibles sin conexión.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Escuchado hace poco
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. ¿Reformatear la SD como MESHCOMOD (FAT32)?\nSe borrarán TODOS los datos de la tarjeta.
Region & scope Región y alcance
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Alcance de región (#tag) para este canal.\nVacío = alcance predeterminado.
Region scope (#tag), blank = default. Ámbito de región (#tag), vacío = predeterminado.
Region scope (#tag, blank = none) Alcance de región (#tag, vacío = ninguno)
@@ -683,6 +688,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 +701,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 +729,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
@@ -770,6 +779,8 @@ Settings Ajustes
Setup complete Configuración completa
Share QR Compartir QR
Share channel Compartir canal
Share contact Compartir contacto
Share failed Error al compartir
Share location in advert Compartir ubicación en anuncio
Share secret Compartir secreto
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Comparte el secreto de 32 caracteres para que otros se unan. Déjalo vacío para uno aleatorio.
@@ -926,6 +937,7 @@ Your own apps Tus propias apps
Zero-hop Cero saltos
Zero-hop advert sent Anuncio zero-hop enviado
Zoom: +/- buttons Zoom: botones +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected cliente conectado
command comando
contacts (%d): contactos (%d):
@@ -968,8 +980,6 @@ tap to exit full screen toca para salir de pantalla completa
zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. amplificador ~17 dB para zonas tranquilas/remotas; apaga en zonas ruidosas.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1001,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1014,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -7
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: fr
# ver: 12
# ver: 20
# name: Français
# base: fr
(device behind) (appareil en retard)
@@ -184,6 +184,7 @@ Contact added Contact ajouté
Contact deleted Contact supprimé
Contact gone Contact perdu
Contact missing Contact manquant
Contact shared Contact partagé
Contacts Contacts
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Les contacts sont en mémoire interne - la carte SD ne s'est pas montée au démarrage. Réinsérez la carte et redémarrez.
Contacts are on internal flash. Les contacts sont sur la mémoire interne.
@@ -282,6 +283,7 @@ End time Heure de fin
Enter SSID first Saisissez d'abord le SSID
Enter a name Saisissez un nom
Enter a network name Saisir un nom de réseau
Enter a region name Enter a region name
Enter adds a new line Entrée ajoute une ligne
Enter exactly 32 hex characters. Saisissez exactement 32 caractères hex.
Enter key sends message La touche Entrée envoie le message
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Nav. clavier : WASDZ activé
Keyboard nav: off Nav. clavier : désactivé
Keyboard navigation Navigation clavier
Keys
Known regions Known regions
LOS → %s Vue directe → %s
Landscape (desktop) Paysage (bureau)
Landscape set - applies when remote mode starts. Paysage défini - s'applique au démarrage du mode distant.
@@ -450,7 +453,6 @@ Login OK (perms %u) Connexion OK (perms %u)
Login failed Échec de connexion
Logs Journaux
Longitude Longitude
Lua Store Lua Store
MHz MHz
MQTT bridge Pont MQTT
Map Carte
@@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Aucun réseau trouvé (2,4 GHz uniquement)
No onboard GPS Pas de GPS intégré
No other networks found Aucun autre réseau trouvé
No position yet. A cold start needs a clear view of the sky and can take several minutes. Pas encore de position. Un démarrage à froid demande un ciel dégagé et peut prendre plusieurs minutes.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Pas de réponse de %s
No reply. Check password, server,\nor device clock (device: %s) Pas de réponse. Vérifiez mot de passe, serveur\nou horloge de l'appareil (appareil : %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Aucune tuile enregistrée ici.\n\nConnectez-vous au Wi-Fi (Réglages → Wi-Fi)\npour télécharger cette zone.\nLes tuiles enregistrées restent hors ligne.
@@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Entendu récemment
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Reformater la SD en MESHCOMOD (FAT32) ?\nTOUTES les données de la carte seront effacées.
Region & scope Région et portée
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Portée régionale (#tag) pour ce canal.\nVide = portée par défaut.
Region scope (#tag), blank = default. Portée de région (#tag), vide = défaut.
Region scope (#tag, blank = none) Portée régionale (#tag, vide = aucune)
@@ -683,6 +687,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 +700,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 +728,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
@@ -770,6 +778,8 @@ Settings Paramètres
Setup complete Configuration terminée
Share QR Partager le QR
Share channel Partager le canal
Share contact Partager le contact
Share failed Échec du partage
Share location in advert Partager la position dans l'annonce
Share secret Partager le secret
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Partagez le secret de 32 caractères pour que d'autres rejoignent. Laissez vide pour un aléatoire.
@@ -926,6 +936,7 @@ Your own apps Vos propres applis
Zero-hop Zéro saut
Zero-hop advert sent Annonce zero-hop envoyée
Zoom: +/- buttons Zoom : boutons +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected client connecté
command commande
contacts (%d): contacts (%d) :
@@ -968,8 +979,6 @@ tap to exit full screen toucher pour quitter le plein écran
zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. ampli ~17 dB pour zones calmes/isolées ; désactiver en zone bruyante.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1000,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1013,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+166 -74
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: hu
# ver: 12
# ver: 20
# name: Magyar
# base: hu
(device behind) (készülék hátulján)
@@ -29,7 +29,7 @@ AF AF
AUTOMATIC ADVERTS AUTOMATIKUS ADVERTEK
About Névjegy
About the map A térképről
Accent popups Accent popups
Accent popups Ékezetes felugró ablakok
Accent popups: off Accent popups: kikapcsolva
Accent popups: on Accent popups: bekapcsolva
Ack Ack
@@ -40,13 +40,13 @@ Add contact Névjegy hozzáadás
Added Hozzáadva
Added to contacts Hozzáadva a névjegyekhez
Added to favorites Hozzáadva a kedvencekhez
Admin Adminisztráció
Admin Admin
Advert Advert
Advert failed Advert sikertelen
Advert location Advert helye
Advert policy saved Advert szabályzat mentve
Advert sent Advert elküldve
All marked read Összes megjelölve olvasottnak
All marked read Össz. olvasottnak
Already exists Már létezik
Already exists or table full. Már létezik, vagy a tábla megtelt.
Already in contacts Már a névjegyek közt
@@ -65,17 +65,17 @@ Apps Appok
Arrows + Enter always work. These letters are extra — tap a row, then press a key. A nyilak + Enter mindig működik. Ezek a betűk extra – koppintson egy sorra, majd nyomjon meg egy billentyűt.
Auto advert Auto. advert
Auto chat Auto. csevegés
Auto repeater Auto repeater
Auto room Auto room
Auto repeater Auto. repeater
Auto room Auto. room
Auto sensor Auto szenzor
Auto-Join Auto. csatlakozás
Auto-add Auto. hozzáad.
Auto-add contacts Névjegyek automatikus hozzáadása
Auto-add saved Auto. hozzáadás mentve
Auto-add settings Auto. hozzáadás beállításai
Auto-delete above hops Auto. törlés a fenti hops-ok felett
Auto-delete oldest Legrégebbi automatikus törlése
Auto-delete oldest makes room when full. Hops: 0 = keep all; nodes heard via more hops are removed. A legrégebbi automatikus törlése helyet szabadít fel, ha megtelik. Hops-ok: 0 = összes megtartása; a további hops-on keresztül hallott nodeok eltávolításra kerülnek.
Auto-add settings Auto. hozzáadás
Auto-delete above hops Auto. törlés hop felett
Auto-delete oldest Régebbi auto. törlése
Auto-delete oldest makes room when full. Hops: 0 = keep all; nodes heard via more hops are removed. Ha megtelik, a legrégebbi törlődik. Hops: 0 = összes; távolabbi node-ok törlődnek.
Auto-discover Auto. felismerés
Auto-discover off Auto. felismerés kikapcsolva
Auto-discover on Auto. felismerés bekapcsolva
@@ -89,7 +89,7 @@ BT BT
Back Vissza
Backups Mentés
Battery Akkumlátor
Battery & power history Akkumulátor és teljesítmény előzményei
Battery & power history Akku és teljesítmény előzményei
Battery (V) Akkumlátor (V)
Battery calibration reset to default Az akkumulátor kalibrálása visszaállt az alapértelmezett értékre
Battery read too low — charge fully first Az akkumulátor túl alacsony állapotban van – először töltse fel teljesen
@@ -97,7 +97,7 @@ Battery saver (experimental) Akkumulátorkímélő (kísérleti)
Battery — last 24h Akkumulátor – elmúlt 24 óra
Battery: Akkumlátor
Block Tiltás
Block list full A feketelista megtelt
Block list full A tiltólista megtelt
Blocked list Tiltólista
Blocked users Letiltott felhasználók
Blocked — their messages are hidden Blokkolt – az üzeneteik rejtve vannak
@@ -153,12 +153,12 @@ Chat save fallback (failed tries) Csevegésmentés tartalék (hibás próbák)
Chats, contacts, settings and a mesh terminal - all in the browser. No reboot; the device keeps its normal screen. Csevegések, névjegyek, beállítások és mesh-terminál - mind a böngészőben. Nincs újraindítás; az eszköz képernyője változatlan marad.
Choose .wav from files .wav választása a fájlokból
Choose your name Válaszd ki a neved
Choose your region Válassza ki a régióját
Choose your region Válaszd ki a régiód
Clear Tisztít
Clear battery history? Törli az akkumulátorelőzményeket?
Clear history Előzmények törlése
Clear telemetry history for this node? Törli a telemetriai előzményeket ehhez a csomóponthoz?
Client repeat Client repeat
Client repeat Kliens repeat
Clock & time Idő és dátum
Clock synced Óra szinkronizálva
Clock: 12-hour Óra: 12 órás
@@ -186,6 +186,7 @@ Contact added Névjegy hozzáadva
Contact deleted Névjegy törölve
Contact gone Eltűnt névjegy
Contact missing Hiányzó névjegy
Contact shared Névjegy megosztva
Contacts Névjegyek
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. A névjegyek a belső tárolón vannak - az SD-kártya nem csatolódott induláskor. Helyezd be újra a kártyát, és indítsd újra.
Contacts are on internal flash. A névjegyek a belső tárolón vannak.
@@ -218,7 +219,7 @@ Couldn't start the analyzer.\nTry again. Nem sikerült elindítani az analizáto
Crash export failed A Crash exportálása sikertelen volt
Create Létrehoz
Create QR QR készítése
Create a private channel Privát csatorna létrehozása
Create a private channel Privát létrehozása
Create failed Létrehozás sikertelen
Create private channel Privát csatorna létrehozása
Current tile transfer is busy - retry Az aktuális csempeátvitel folyamatban van – próbáld újra később.
@@ -286,6 +287,7 @@ End time Befejezés
Enter SSID first Először adja meg az SSID-t
Enter a name Írjon be egy nevet
Enter a network name Adjon meg egy hálózatnevet
Enter a region name Enter a region name
Enter adds a new line Az Enter új sort ad hozzá
Enter exactly 32 hex characters. Pontosan 32 hex karaktert adjon meg.
Enter key sends message Az Enter billentyű elküldi az üzenetet
@@ -394,12 +396,12 @@ Invalid lat/lon Hosszúság/szélesség érvénytelen
Invalid max hops Érvénytelen maximális ugrásszám
Invalid radio values Érvénytelen rádióértékek
Join Csatlakozás
Join a hashtag channel Csatlakozás hashtag csatornához
Join a private channel Csatlakozás privát csatornához
Join hashtag channel Csatlakozz a hashtag csatornához
Join a hashtag channel Belépés # csatornához
Join a private channel Belépés priváthoz
Join hashtag channel Csatlakozz # csatornához
Join network Csatlakozás a hálózathoz
Join private channel Csatlakozz privát csatornához
Join the public channel Csatlakozás a nyilvános csatornához
Join the public channel Belépés a nyilvánoshoz
Joined %.40s Csatlakozott %.40s alatt
Keep per chat (messages) Megőrzés csevegésenként (üzenet)
Key already in use Kulcs már hozzárendelve
@@ -412,6 +414,7 @@ Keyboard nav: WASDZ on Billentyűzet navigáció: WASDZ bekapcsolva
Keyboard nav: off Billentyűzetnavigáció: kikapcsolva
Keyboard navigation Billentyűzetnavigáció
Keys Kulcsok
Known regions Known regions
LOS → %s Rálátás → %s
Landscape (desktop) Fekvő (asztali)
Landscape set - applies when remote mode starts. Fekvő beállítva - a távoli mód indulásakor lép életbe.
@@ -469,7 +472,7 @@ Map — no tile pack on SPIFFS yet.\n\nUpload a tile pack to /tiles/<z>/<x>/<y>.
Map — set your location\nin Settings → Profile to\nshow the map here. Térkép – a Beállítások → Profil menüpontban állítsd be a tartózkodási helyedet, hogy itt jelenjen meg a térkép.
Mark all chats and channels as read? Az összes csevegést és csatornát megjelölöd olvasottként?
Mark as read Olvasottnak jelöl
Mark read Mark read
Mark read Olvasott
Marked read Olvasottként megjelölve
Max hops (0..64) Max ugrások (0-64)
Max zoom for this pack Maximális zoom ehhez a csomaghoz
@@ -520,7 +523,7 @@ No Bluetooth on this device Nincs Bluetooth ezen az eszközön
No DM key Nincs DM kulcs
No GPS module on this device. Nincs GPS modul ezen a készüléken.
No JPEGs found in /lock/.\nAdd images via the file\nmanager or an SD card. Nem található JPEG fájl a /lock/ mappában.\nKépek hozzáadása a fájlkezelőn vagy SD-kártyán keresztül.
No SD card Geen SD-kaart
No SD card Nincs SD-kártya
No SD card (or unreadable format) Nincs SD-kártya (vagy olvashatatlan formátumú)
No backups yet. Tap Export new backup above to create one. Még nincsenek biztonsági mentések. Koppintson a fenti Új biztonsági mentés exportálása gombra egy létrehozásához.
No battery history yet.\n\nLogged every 5 minutes. Még nincsenek akkumulátor-előzmények.\n\n5 percenként naplózva.
@@ -539,6 +542,7 @@ No networks found (2.4 GHz only) Nem található hálózat (csak 2,4 GHz)
No onboard GPS Nincs beépített GPS
No other networks found Nem található más hálózat
No position yet. A cold start needs a clear view of the sky and can take several minutes. Még nincs pozíció. A hidegindításhoz szabad égbolt kell, és több percig is tarthat.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Nincs válasz %s-tól
No reply. Check password, server,\nor device clock (device: %s) Nincs válasz. Ellenőrizze a jelszót, a szervert,\nvagy az eszköz óráját (eszköz: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Nincsenek mentett térképszeletek. \n\nCsatlakozzon Wi-Fi-hez (Beállítások → Wi-Fi) a terület letöltéséhez.\nA mentett szeletek offline is elérhetők maradnak.
@@ -547,7 +551,7 @@ No telemetry in this window.\nRequest one, or widen the range below. Nincs telem
No tiles (non-ESP32) Nincsenek csempék (nem ESP32)
No version known yet. Wi-Fi and a completed update check are needed first. Egyelőre nincs ismert verzió. Először Wi-Fi-kapcsolat és egy frissítés-ellenőrzés szükséges.
Node name Node név
Node\nRegion\nRadio\nSignal\nContacts\nChannels\nBattery\nUptime Node\nRegion\nRadio\nSignal\nContacts\nChannels\nBattery\nUptime
Node\nRegion\nRadio\nSignal\nContacts\nChannels\nBattery\nUptime Node\nRégió\nRádió\nJel\nNévjegyekk\nCsatornák\nAkkumulátor\nÜzemidő
Normal (100%)\nLarge (150%)\nHuge (200%) Normál (100%)\nLarge (150%)\nHuge (200%)
Not enough free memory for Bluetooth. Turn Wi-Fi off first. Nincs elég szabad memória a Bluetooth-hoz. Először kapcsold ki a Wi-Fi-t.
Not enough free memory for Wi-Fi. Turn Bluetooth off first. Nincs elég szabad memória a Wi-Fi-hez. Először kapcsold ki a Bluetooth-t.
@@ -622,7 +626,7 @@ Public key (64 hex chars) Nyilvános kulcs (64 hex karakter)
Public key: Nyilvános kulcs
Publish channel messages Csatornaüzenetek közzététele
Publish direct messages Közvetlen üzenetek közzététele
Purge Purge
Purge Törlés
Purge all discovered nodes? Törölje az összes felfedezett csomópontot?
Quick replies Gyors válaszok
Quick reply Gyors válasz
@@ -649,6 +653,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Nemrég hallottam
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Újraformázza az SD kártyát MESHCOMOD (FAT32) formátumban?\nA kártyán lévő ÖSSZES adat törlődik.
Region & scope Régió és hatókör
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Régió hatóköre (#tag) ehhez a csatornához.\nÜres = az alapértelmezett hatókör használata.
Region scope (#tag), blank = default. Régió hatóköre (#tag), üres = alapértelmezett.
Region scope (#tag, blank = none) Régió hatóköre (#címke, üres = nincs)
@@ -663,7 +668,7 @@ Remote terminal off Távoli terminál kikapcsolva
Remove Eltávolítás
Remove %s? Eltávolítod: %s?
Remove channel Csatorna eltávolítása
Remove channel "%s"?\nLeaves it on this device only. Eltávolítja a(z) “%s” csatornát?\nCsak ezen az eszközön hagyja.
Remove channel "%s"?\nLeaves it on this device only. Eltávolítja a(z) "%s" csatornát?\nCsak ezen az eszközön hagyja.
Removed Eltávolítva
Removed from favorites Eltávolítva a kedvencek közül
Rename Átnevezés
@@ -692,18 +697,20 @@ 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
SD card removed SD-kártya eltávolítva
SD data is unavailable - contacts and channels cannot be saved until the card is reinserted. Az SD-kártya adatai nem érhetők el – a névjegyek és a csatornák nem menthetők a kártya újbóli behelyezéséig.
SD data is unavailable - identity, settings, contacts and channels cannot be saved until the card is reinserted. Az SD-kártya adatai nem érhetők el – az azonosító, a beállítások, a névjegyek és a csatornák nem menthetők a kártya újbóli behelyezéséig.
SD data migration is incomplete. Identity and settings remain internal; use Copy internal data to SD to retry. Az SD-kártya adatainak áthelyezése nem teljes. Az azonosító és a beállítások továbbra is a belső tárhelyen vannak; a folytatáshoz használd a „Belső adatok másolása SD-kártyára” lehetőséget.
SD data migration is incomplete. Identity and settings remain internal; use Copy internal data to SD to retry. Az SD-kártya adatainak áthelyezése nem teljes. Az azonosító és a beállítások továbbra is a belső tárhelyen vannak; a folytatáshoz használd a "Belső adatok másolása SD-kártyára" lehetőséget.
SD download failed: %s SD-letöltés sikertelen: %s
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 +740,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
@@ -783,6 +792,8 @@ Settings Beállítások
Setup complete Beállítás kész
Share QR QR megosztása
Share channel Csatorna megosztása
Share contact Névjegy megosztása
Share failed Megosztás sikertelen
Share location in advert Helyszín megosztása a hirdetésben
Share secret Titok megosztása
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Oszd meg a 32 karakteres titkot, hogy mások is csatlakozhassanak. Hagyd üresen a titkot, hogy véletlenszerű titkos kódot generálj.
@@ -804,7 +815,6 @@ Sleep ready Készen áll az alvásra
Slot %d cleared %d hely kiürítve
Slot empty Üres hely
Small\nMedium\nLarge Kicsi\nKözepes\nNagy
Snake Snake
Snake — swipe or roll the trackball Kígyó – pöccintsd vagy görgesd a görgetőgolyót
Sort Sort
Sound Hang
@@ -870,7 +880,7 @@ Today Ma
Toggle GPS GPS be-/kikapcs.
Too large to edit (>8 KB) Túl nagy a szerkesztéshez (>8 KB)
Topographic map Topográfiai térkép
Trace Trace
Trace Nyomkövetés
Trace SNR SNR nyomkövetés
Trace failed Nyomkövetés sikertelen
Trace route Útvonal nyomkövetése
@@ -946,6 +956,7 @@ Your own apps Saját appok
Zero-hop Zero-hop
Zero-hop advert sent Zero-hop advert elküldve
Zoom: +/- buttons Nagyítás: +/- gombok
ambiguous (several regions matched) ambiguous (several regions matched)
client connected kliens csatlakozva
command parancs
contacts (%d): névjegyek (%d):
@@ -975,7 +986,7 @@ now talking to %s most %s-szel beszélgetek
off ki
off = Enter adds a new line; tap Send to send ki = Az Enter új sort hoz létre; a küldéshez koppintson a Küldés gombra
on be
peak -- peak
peak -- peak --
pick accented letters as you type; off = plain typing ékezetes betűk kiválasztása gépelés közben; kikapcsolva = sima gépelés
press Volume Down to unlock Nyomja meg a hangerő csökkentését a feloldáshoz
push past a screen edge to scroll content Görgetéshez húzza végig az ujját a képernyő szélén
@@ -988,49 +999,130 @@ tap to exit full screen koppintson a teljes képernyős kilépéshez
zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. ~17 dB erősítővel csendes/távoli helyeken; zajos helyeken kapcsold ki.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
Save FAIL x%u
Save migrating
Saved %s
Sort discovered
Sort by
Peers
Favorites
Has location
Direct (0-hop)
Heard %s
Traffic (since boot)\n Sent %u flood, %u direct\n Recv %u flood, %u direct
Overwrite oldest non-favorite
"%s" wants to send messages on the mesh.\n\nThey will be sent as %s and cannot be told apart from messages you typed.\n\nOnly allow this for an app you trust. "%s" wants to send messages on the mesh.\n\nThey will be sent as %s and cannot be told apart from messages you typed.\n\nOnly allow this for an app you trust.
%d of %d on map %d of %d on map
1-character messages will be ignored 1-character messages will be ignored
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
Location shared with anyone who asks Location shared with anyone who asks
Location shared with chosen contacts only Location shared with chosen contacts only
Location shared with this contact Location shared with this contact
Location sharing off Location sharing off
Max dots Max dots
Most mesh spam is a single character, because it is the cheapest message to send. Dropped silently: no chat entry, no notification, no sound. Most mesh spam is a single character, because it is the cheapest message to send. Dropped silently: no chat entry, no notification, no sound.
Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone who asks
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Csak akkor küldi el, ha az adott névjegy kéri, és titkosítva, kizárólag neki küldi. Semmi nem kerül közzétételre. Az „Telemetriai kérések megválaszolása” engedélynek be kell lennie kapcsolva. A névjegyeket a névjegy menüjében választhatod ki.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Scope Hatókör
another region másik régió
my region saját régió
Save FAIL x%u Mentési hiba x%u
Save migrating Mentés áthelyezése
Saved %s Mentve: %s
Sort discovered Felfedezettek rendezése
Sort by Rendezés szerint
Peers Partnerek
Favorites Kedvencek
Has location Van helyadata
Direct (0-hop) Közvetlen (0 ugrás)
Heard %s Észlelve: %s
Traffic (since boot)\n Sent %u flood, %u direct\n Recv %u flood, %u direct Forgalom (indítás óta)\n Küldve %u flood, %u közvetlen\n Fogadva %u flood, %u közvetlen
Overwrite oldest non-favorite Legrégebbi nem kedvenc felülírása
"%s" wants to send messages on the mesh.\n\nThey will be sent as %s and cannot be told apart from messages you typed.\n\nOnly allow this for an app you trust. "%s" üzeneteket szeretne küldeni a mesh hálózaton.\n\nAz üzeneteket %s néven küldi, és nem különböztethetők meg az általad beírt üzenetektől.\n\nCsak megbízható alkalmazásnak engedélyezd.
%d of %d on map %d / %d a térképen
1-character messages will be ignored Az 1 karakteres üzenetek figyelmen kívül lesznek hagyva
1-character messages will be shown Az 1 karakteres üzenetek megjelennek
All Összes
Allow Engedélyezés
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Azok az alkalmazások, amelyek üzeneteket küldhetnek a mesh hálózaton. Az általuk küldött üzenetek a csomópontod neve alatt jelennek meg, és nem különböztethetők meg az általad beírt üzenetektől. Kapcsold ki az engedélyt annak visszavonásához.
Ignore 1-character messages 1 karakteres üzenetek figyelmen kívül hagyása
Join w/ password Csatlakozás jelszóval
Location no longer shared A helyzetmegosztás megszűnt
Location shared with anyone who asks A helyzet megosztása bárkivel, aki kéri
Location shared with chosen contacts only A helyzet megosztása csak a kiválasztott névjegyekkel
Location shared with this contact A helyzet megosztása ezzel a névjeggyel
Location sharing off Helyzetmegosztás kikapcsolva
Max dots Max. pontok
Most mesh spam is a single character, because it is the cheapest message to send. Dropped silently: no chat entry, no notification, no sound. A legtöbb mesh spam jelenleg egyetlen karakterből áll, mert ez a legolcsóbban elküldhető üzenet. Csendben eldobva: nem jelenik meg a csevegésben, nincs értesítés és nincs hangjelzés.
Never\nChosen contacts only\nAnyone who asks Soha\nCsak a kiválasztott névjegyek\nBárki, aki kéri
No apps installed. Nincsenek telepített alkalmazások.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) Nincs válasz. Az útvonal hash értéke %u bájt;\na régebbi átjátszók eldobhatják ezeket.\nPróbáld 1 bájttal (Beállítások > Rádió és Mesh)
Not supported on this board Ezen az eszközön nem támogatott.
Read incoming messages Beérkező üzenetek olvasása
Reconnected to %.40s Újracsatlakozva ehhez: %.40s
Send messages as me Üzenetek küldése a nevemben
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Csak akkor küldi el, ha az adott névjegy kéri, és titkosítva, kizárólag neki küldi. Semmi nem kerül közzétételre. Az "Telemetriai kérések megválaszolása" engedélynek be kell lennie kapcsolva. A névjegyeket a névjegy menüjében választhatod ki.
Server has forgotten you.\nJoin with the room password. A szerver elfelejtett téged.\nCsatlakozz a szoba jelszavával.
Share my loc Helyzetem megosztása
Share my location when asked Helyzetem megosztása kérésre
Stop sharing loc Helyzetmegosztás leállítása
not asked yet Még nem kérték
Battery life: gathering data… Üzemidő: adatok gyűjtése…
Small\nMedium\nLarge\nJumbo Kicsi\nKözepes\nNagy\nÓriási
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" privát üzenetek küldését kéri a nevedben.\n\nÜzenetet küldhet bármelyik kontaktodnak, vagy írhat egy roomba, és az üzenet pontosan úgy fog kinézni, mintha te írtad volna.\n\nCsak olyan appnak engedélyezd ezt, amelyben megbízol.
Map pan off Térképmozgatás kikapcsolva
Map pan: arrows pan, Back exits Térképmozgatás: a nyilakkal mozgatod, a Back kilép
Perf: Perf:
Post to channels as me Üzenetek küldése a csatornákra a nevemben
Powering off… press BOOT to wake Kikapcsolás… a BOOT gombbal ébresztheted fel
Read channel messages Csatornaüzenetek olvasása
Read private messages Privát üzenetek olvasása
Send private messages as me Privát üzenetek küldése a nevemben
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. Az egyes telepített appok engedélyei. Az app által küldött üzenetek a node neved alatt jelennek meg, mintha te küldted volna. A privát üzenetek a közvetlen és room-üzenetekre vonatkoznak, külön a csatornáktól. Az engedély kikapcsolásával visszavonhatod.
Wi-Fi off, new map areas can't download A Wi-Fi ki van kapcsolva, az új térképrészletek nem tölthetők le
App permissions Appengedélyek
About / credits Névjegy / köszönet
chats csevegések
repeaters ismétlők
rooms szobák
sensors érzékelők
Auto-add on for %s — new %s land in Contacts automatically. Automatikus hozzáadás bekapcsolva: %s — az új %s automatikusan a Névjegyek közé kerülnek.
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Térkép adatok © OpenStreetMap közreműködői.\nopenstreetmap.org/copyright\nAz Open Database License (ODbL) licenc alatt.\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Térkép stílus © OpenTopoMap (CC-BY-SA) — opentopomap.org\nTérkép adatok © OpenStreetMap közreműködői (ODbL) + SRTM.\n\n
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. A csempék működése:\nA térkép 256×256 képpontos "slippy" csempékből épül fel. Csak a megtekintett területhez szükséges csempék töltődnek le — nincs tömeges előzetes letöltés.\n\nMivel az eszköz nem támogatja a HTTPS-t (a Wi-Fi elindítása után nincs elegendő heap memória), és a JPEG képek dekódolása sokkal kevesebb erőforrást igényel, mint a PNG-é, a csempék a wadamesh proxyn keresztül érkeznek: a proxy HTTPS-en keresztül lekéri a forrásból a PNG-t egy azonosító User-Agent használatával, JPEG formátumba kódolja át, majd eltárolja a gyorsítótárban. Az eszköz ezután minden csempét a saját flash memóriájában is eltárol, így egy csempét csak egyszer kell letölteni.\n\nAz Options → Reload tiles lehetőséggel újra letöltheted a jelenleg megtekintett terület csempéit, ha valamelyik hibásan jelenik meg.
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" felfedezési probe-ok küldését kéri.\n\nMinden probe válaszra kéri a hatótávolságon belüli node-okat, ezért a teljes helyi mesh hálózat airtime-ját használja, nem csak a tiédet.\n\nSemmi sem kerül elküldésre a nevedben, és üzenet sem kerül továbbításra.
? ?
Auth failed Auth failed
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Csak közvetlen (0-hop)
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Szöveg megadása
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Name (A-Z) Név (A–Z)
Nearest first Legközelebbi elöl
Recent message Legutóbbi üzenet
Reload tiles in view Csempék újratöltése
Repeaters Repeaters
SIGNAL SIGNAL
Select to delete Törléshez válassz ki
Send discovery probes Discovery probe-ok küldése
Show contacts Névjegyek megjelenítése
Show coordinates Koordináták
Show tile z/x/y Csempe z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Csempe hiba keret
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Hibajelentés exportálása (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Beszúrás (másolt)
Paste (move) Beszúrás (mozgat)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. A beta_%d telepítése?\nEz leminősíti a firmware-t és újraindul.
Other (hidden) network… Other (hidden) network…
Paused Paused
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal (stale) Jel (elavult)
nothing heard yet Még semmi hír.
+101 -7
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: it
# ver: 12
# ver: 20
# name: Italiano
# base: it
(device behind) (dispositivo indietro)
@@ -184,6 +184,7 @@ Contact added Contatto aggiunto
Contact deleted Contatto eliminato
Contact gone Contatto perso
Contact missing Contatto mancante
Contact shared Contatto condiviso
Contacts Contatti
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. I contatti sono sulla memoria interna - la scheda SD non si è montata all'avvio. Reinserisci la scheda e riavvia.
Contacts are on internal flash. I contatti sono sulla memoria interna.
@@ -282,6 +283,7 @@ End time Ora di fine
Enter SSID first Inserisci prima l'SSID
Enter a name Inserisci un nome
Enter a network name Inserisci un nome di rete
Enter a region name Enter a region name
Enter adds a new line Invio aggiunge una riga
Enter exactly 32 hex characters. Inserisci esattamente 32 caratteri hex.
Enter key sends message Il tasto Invio invia il messaggio
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Nav. tastiera: WASDZ on
Keyboard nav: off Nav. tastiera: off
Keyboard navigation Navigazione da tastiera
Keys
Known regions Known regions
LOS → %s Vista diretta → %s
Landscape (desktop) Orizzontale (desktop)
Landscape set - applies when remote mode starts. Orizzontale impostato - vale all'avvio della modalità remota.
@@ -450,7 +453,6 @@ Login OK (perms %u) Accesso OK (permessi %u)
Login failed Accesso non riuscito
Logs Log
Longitude Longitudine
Lua Store Lua Store
MHz MHz
MQTT bridge Ponte MQTT
Map Mappa
@@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Nessuna rete trovata (solo 2.4 GHz)
No onboard GPS Nessun GPS integrato
No other networks found Nessun'altra rete trovata
No position yet. A cold start needs a clear view of the sky and can take several minutes. Ancora nessuna posizione. Un avvio a freddo richiede cielo libero e può durare diversi minuti.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Nessuna risposta da %s
No reply. Check password, server,\nor device clock (device: %s) Nessuna risposta. Controlla password, server\no orologio del dispositivo (dispositivo: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Nessuna tessera salvata qui.\n\nConnettiti al Wi-Fi (Impostazioni → Wi-Fi)\nper scaricare quest'area.\nLe tessere salvate restano disponibili offline.
@@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Sentito di recente
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Riformattare la SD come MESHCOMOD (FAT32)?\nTUTTI i dati sulla scheda saranno cancellati.
Region & scope Regione e ambito
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Ambito regione (#tag) per questo canale.\nVuoto = ambito predefinito.
Region scope (#tag), blank = default. Ambito regione (#tag), vuoto = predefinito.
Region scope (#tag, blank = none) Ambito regione (#tag, vuoto = nessuno)
@@ -683,6 +687,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 +700,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 +728,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
@@ -770,6 +778,8 @@ Settings Impostazioni
Setup complete Configurazione completata
Share QR Condividi QR
Share channel Condividi canale
Share contact Condividi contatto
Share failed Condivisione non riuscita
Share location in advert Condividi posizione in advert
Share secret Condividi segreto
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Condividi il segreto di 32 caratteri per far unire altri. Lascia vuoto per uno casuale.
@@ -926,6 +936,7 @@ Your own apps Le tue app
Zero-hop Zero hop
Zero-hop advert sent Advert zero-hop inviato
Zoom: +/- buttons Zoom: pulsanti +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected client connesso
command comando
contacts (%d): contatti (%d):
@@ -968,8 +979,6 @@ tap to exit full screen tocca per uscire da schermo intero
zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. ampli ~17 dB per zone tranquille/remote; spegni in zone rumorose.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1000,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1013,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+102 -10
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: nl
# ver: 12
# ver: 20
# name: Nederlands
# base: nl
(device behind) (apparaat loopt achter)
@@ -184,6 +184,7 @@ Contact added Contact toegevoegd
Contact deleted Contact verwijderd
Contact gone Contact weg
Contact missing Contact ontbreekt
Contact shared Contact gedeeld
Contacts Contacten
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Contacten staan op intern flash - de SD-kaart is bij het opstarten niet gekoppeld. Plaats de kaart opnieuw en herstart.
Contacts are on internal flash. Contacten staan op intern flashgeheugen.
@@ -282,6 +283,7 @@ End time Eindtijd
Enter SSID first Voer eerst SSID in
Enter a name Voer een naam in
Enter a network name Voer een netwerknaam in
Enter a region name Enter a region name
Enter adds a new line Enter voegt een nieuwe regel toe
Enter exactly 32 hex characters. Voer precies 32 hex-tekens in.
Enter key sends message Enter verstuurt bericht
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Toetsenbordnav.: WASDZ aan
Keyboard nav: off Toetsenbordnav.: uit
Keyboard navigation Toetsenbordnavigatie
Keys Toetsen
Known regions Known regions
LOS → %s Zichtlijn → %s
Landscape (desktop) Liggend (desktop)
Landscape set - applies when remote mode starts. Liggend ingesteld - geldt zodra de externe modus start.
@@ -450,7 +453,6 @@ Login OK (perms %u) Inloggen OK (rechten %u)
Login failed Inloggen mislukt
Logs Logboeken
Longitude Lengtegraad
Lua Store Lua Store
MHz MHz
MQTT bridge MQTT-brug
Map Kaart
@@ -514,7 +516,7 @@ No Bluetooth on this device Geen Bluetooth op dit apparaat
No DM key Geen DM-sleutel
No GPS module on this device. Geen GPS-module op dit apparaat.
No JPEGs found in /lock/.\nAdd images via the file\nmanager or an SD card. Geen JPEG's gevonden in /lock/.\nVoeg afbeeldingen toe via de\nbestandsbeheerder of een SD-kaart.
No SD card Nincs SD-kártya
No SD card Geen SD-kaart
No SD card (or unreadable format) Geen SD-kaart (of onleesbaar formaat)
No backups yet. Tap Export new backup above to create one. Nog geen back-ups. Tik hierboven op Nieuwe back-up om er een te maken.
No battery history yet.\n\nLogged every 5 minutes. Nog geen batterijgeschiedenis.\n\nElke 5 minuten gelogd.
@@ -533,6 +535,7 @@ No networks found (2.4 GHz only) Geen netwerken gevonden (alleen 2.4 GHz)
No onboard GPS Geen ingebouwde GPS
No other networks found Geen andere netwerken gevonden
No position yet. A cold start needs a clear view of the sky and can take several minutes. Nog geen positie. Een koude start heeft vrij zicht op de lucht nodig en kan enkele minuten duren.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Geen antwoord van %s
No reply. Check password, server,\nor device clock (device: %s) Geen antwoord. Controleer wachtwoord, server,\nof apparaatklok (apparaat: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Hier geen opgeslagen kaarttegels.\n\nMaak verbinding met Wi-Fi (Instellingen → Wi-Fi)\nom dit gebied te downloaden.\nOpgeslagen tegels blijven offline beschikbaar.
@@ -641,6 +644,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Recent gehoord
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. SD herformatteren als MESHCOMOD (FAT32)?\nALLE data op de kaart wordt gewist.
Region & scope Regio en bereik
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Regiobereik (#tag) voor dit kanaal.\nLeeg = standaardbereik gebruiken.
Region scope (#tag), blank = default. Regiobereik (#tag), leeg = standaard.
Region scope (#tag, blank = none) Regiobereik (#tag, leeg = geen)
@@ -683,6 +687,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 +700,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 +728,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
@@ -770,6 +778,8 @@ Settings Instellingen
Setup complete Installatie voltooid
Share QR QR delen
Share channel Kanaal delen
Share contact Contact delen
Share failed Delen mislukt
Share location in advert Locatie delen in advert
Share secret Geheim delen
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Deel het 32-teken geheim zodat anderen kunnen deelnemen. Leeg laten voor een willekeurig geheim.
@@ -789,7 +799,6 @@ Sleep ready Klaar voor slaap
Slot %d cleared Slot %d gewist
Slot empty Slot leeg
Small\nMedium\nLarge Klein\nMiddel\nGroot
Snake Snake
Snake — swipe or roll the trackball Snake — veeg of rol de trackball
Sort Sorteer
Sound Geluid
@@ -797,7 +806,6 @@ Sound off Geluid uit
Sound on Geluid aan
Sound: %s Geluid: %s
Start time Starttijd
Status Status
Step 1 of 3 Stap 1 van 3
Step 2 of 3 Stap 2 van 3
Step 3 of 3 Stap 3 van 3
@@ -926,6 +934,7 @@ Your own apps Je eigen apps
Zero-hop Zero-hop
Zero-hop advert sent Zero-hop advert verzonden
Zoom: +/- buttons Zoom: +/- knoppen
ambiguous (several regions matched) ambiguous (several regions matched)
client connected client verbonden
command opdracht
contacts (%d): contacten (%d):
@@ -968,8 +977,6 @@ tap to exit full screen tik om volledig scherm te verlaten
zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. ~17 dB versterker voor stille/afgelegen gebieden; uit in drukke plekken.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +998,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1011,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -7
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: pt-br
# ver: 12
# ver: 20
# name: Português (BR)
# base: pt-br
(device behind) (dispositivo atrasado)
@@ -184,6 +184,7 @@ Contact added Contato adicionado
Contact deleted Contato excluído
Contact gone Contato sumiu
Contact missing Contato ausente
Contact shared Contato compartilhado
Contacts Contatos
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Os contatos estão na memória interna - o cartão SD não montou na inicialização. Recoloque o cartão e reinicie.
Contacts are on internal flash. Os contatos estão na memória interna.
@@ -282,6 +283,7 @@ End time Hora de término
Enter SSID first Digite o SSID primeiro
Enter a name Digite um nome
Enter a network name Digite um nome de rede
Enter a region name Enter a region name
Enter adds a new line Enter adiciona uma linha
Enter exactly 32 hex characters. Digite exatamente 32 caracteres hex.
Enter key sends message A tecla Enter envia a mensagem
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Nav. teclado: WASDZ ligado
Keyboard nav: off Nav. teclado: desligado
Keyboard navigation Navegação por teclado
Keys
Known regions Known regions
LOS → %s Linha de visada → %s
Landscape (desktop) Paisagem (desktop)
Landscape set - applies when remote mode starts. Paisagem definida - vale quando o modo remoto iniciar.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Nenhuma rede encontrada (só 2.4 GHz)
No onboard GPS Sem GPS integrado
No other networks found Nenhuma outra rede encontrada
No position yet. A cold start needs a clear view of the sky and can take several minutes. Ainda sem posição. Uma partida a frio precisa de céu aberto e pode levar vários minutos.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Sem resposta de %s
No reply. Check password, server,\nor device clock (device: %s) Sem resposta. Verifique senha, servidor\nou relógio do dispositivo (dispositivo: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Sem blocos salvos aqui.\n\nConecte-se ao Wi-Fi (Ajustes → Wi-Fi)\npara baixar esta área.\nOs blocos salvos ficam disponíveis offline.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Ouvido recentemente
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Reformatar o SD como MESHCOMOD (FAT32)?\nTODOS os dados do cartão serão apagados.
Region & scope Região e alcance
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Escopo de região (#tag) para este canal.\nVazio = usar o escopo padrão.
Region scope (#tag), blank = default. Escopo da região (#tag), vazio = padrão.
Region scope (#tag, blank = none) Escopo de região (#tag, vazio = nenhum)
@@ -683,6 +688,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 +701,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 +729,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
@@ -770,6 +779,8 @@ Settings Ajustes
Setup complete Configuração concluída
Share QR Compartilhar QR
Share channel Compartilhar canal
Share contact Compartilhar contato
Share failed Falha ao compartilhar
Share location in advert Compartilhar local no advert
Share secret Compartilhar segredo
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Compartilhe o segredo de 32 caracteres para outros entrarem. Deixe vazio para gerar um aleatório.
@@ -797,7 +808,6 @@ Sound off Som desligado
Sound on Som ligado
Sound: %s Som: %s
Start time Hora de início
Status Status
Step 1 of 3 Passo 1 de 3
Step 2 of 3 Passo 2 de 3
Step 3 of 3 Passo 3 de 3
@@ -926,6 +936,7 @@ Your own apps Seus próprios apps
Zero-hop Sem salto
Zero-hop advert sent Zero-hop advert enviado
Zoom: +/- buttons Zoom: botões +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected cliente conectado
command comando
contacts (%d): contatos (%d):
@@ -968,8 +979,6 @@ tap to exit full screen toque para sair da tela cheia
zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. amplificador ~17 dB para áreas silenciosas/remotas; desligue em locais ruidosos.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1000,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1013,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -5
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: ro
# ver: 12
# ver: 20
# name: Română
# base: ro
(device behind) (dispozitiv în urmă)
@@ -184,6 +184,7 @@ Contact added Contact adăugat
Contact deleted Contact şters
Contact gone Contact dispărut
Contact missing Contact lipsă
Contact shared Contact partajat
Contacts Contacte
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Contactele sunt pe memoria internă - cardul SD nu s-a montat la pornire. Reaşază cardul şi reporneşte.
Contacts are on internal flash. Contactele sunt pe memoria internă.
@@ -282,6 +283,7 @@ End time Ora de sfârşit
Enter SSID first Introdu mai întâi SSID-ul
Enter a name Introdu un nume
Enter a network name Introdu un nume de reţea
Enter a region name Enter a region name
Enter adds a new line Enter adaugă un rând nou
Enter exactly 32 hex characters. Introdu exact 32 caractere hex.
Enter key sends message Tasta Enter trimite mesajul
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Navigare tastatură: WASDZ pornit
Keyboard nav: off Navigare tastatură: oprită
Keyboard navigation Navigare cu tastatura
Keys
Known regions Known regions
LOS → %s Linie vizuală → %s
Landscape (desktop) Peisaj (desktop)
Landscape set - applies when remote mode starts. Peisaj setat - se aplică la pornirea modului la distanţă.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Nicio reţea găsită (doar 2,4 GHz)
No onboard GPS Fără GPS integrat
No other networks found Nicio altă reţea găsită
No position yet. A cold start needs a clear view of the sky and can take several minutes. Încă nicio poziţie. O pornire la rece are nevoie de cer liber şi poate dura câteva minute.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Niciun răspuns de la %s
No reply. Check password, server,\nor device clock (device: %s) Niciun răspuns. Verifică parola, serverul\nsau ceasul dispozitivului (dispozitiv: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Fără dale salvate aici.\n\nConectează Wi-Fi (Setări → Wi-Fi)\npentru a descărca zona.\nDalele salvate rămân offline.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Auzite recent
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Reformatezi SD ca MESHCOMOD (FAT32)?\nTOATE datele de pe card vor fi şterse.
Region & scope Regiune şi acoperire
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Domeniu regional (#tag) pentru acest canal.\nGol = domeniul implicit.
Region scope (#tag), blank = default. Domeniu regional (#tag), gol = implicit.
Region scope (#tag, blank = none) Domeniu regional (#tag, gol = niciunul)
@@ -683,6 +688,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 +701,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 +729,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
@@ -770,6 +779,8 @@ Settings Setări
Setup complete Configurare finalizată
Share QR Partajează QR
Share channel Partajează canalul
Share contact Partajează contactul
Share failed Partajare eşuată
Share location in advert Partajează locaţia în advert
Share secret Partajează secretul
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Partajează secretul de 32 caractere ca să poată intra şi alţii. Lasă secretul gol pentru a genera unul aleatoriu.
@@ -926,6 +937,7 @@ Your own apps Aplicaţiile tale
Zero-hop Fără salt
Zero-hop advert sent Advert zero-hop trimis
Zoom: +/- buttons Zoom: butoane +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected client conectat
command comandă
contacts (%d): contacte (%d):
@@ -969,7 +981,6 @@ zoom zoom
zoom %d zoom %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. amplificator ~17 dB pentru zone liniştite/izolate; opreşte-l în locuri zgomotoase.
© OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1002,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1015,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -6
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: ru
# ver: 12
# ver: 20
# name: Русский
# base: ru
(device behind) (устройство отстаёт)
@@ -184,6 +184,7 @@ Contact added Контакт добавлен
Contact deleted Контакт удалён
Contact gone Контакт пропал
Contact missing Контакт отсутствует
Contact shared Контакт отправлен
Contacts Контакты
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Контакты во внутренней памяти - SD-карта не смонтировалась при загрузке. Переустановите карту и перезагрузитесь.
Contacts are on internal flash. Контакты во внутренней памяти.
@@ -282,6 +283,7 @@ End time Время окончания
Enter SSID first Сначала введите SSID
Enter a name Введите имя
Enter a network name Введите имя сети
Enter a region name Enter a region name
Enter adds a new line Enter добавляет строку
Enter exactly 32 hex characters. Введите ровно 32 hex-символа.
Enter key sends message Клавиша Enter отправляет сообщение
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Навигация клавиатурой: WASDZ вкл.
Keyboard nav: off Навигация клавиатурой: выкл.
Keyboard navigation Навигация клавиатурой
Keys
Known regions Known regions
LOS → %s Прямая видимость → %s
Landscape (desktop) Альбомная (десктоп)
Landscape set - applies when remote mode starts. Альбомная выбрана - применится при запуске удалённого режима.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Сети не найдены (только 2.4
No onboard GPS Нет встроенного GPS
No other networks found Другие сети не найдены
No position yet. A cold start needs a clear view of the sky and can take several minutes. Позиции пока нет. Холодный старт требует открытого неба и может занять несколько минут.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Нет ответа от %s
No reply. Check password, server,\nor device clock (device: %s) Нет ответа. Проверьте пароль, сервер\nили часы устройства (устройство: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Здесь нет сохранённых тайлов.\n\nПодключитесь к Wi-Fi (Настройки → Wi-Fi),\nчтобы загрузить этот район.\nСохранённые тайлы остаются доступны офлайн.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Недавно слышно
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Отформатировать SD как MESHCOMOD (FAT32)?\nВСЕ данные на карте будут стёрты.
Region & scope Регион и охват
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Регион (#tag) для этого канала.\nПусто = область по умолчанию.
Region scope (#tag), blank = default. Область региона (#tag), пусто = по умолчанию.
Region scope (#tag, blank = none) Регион (#tag, пусто = нет)
@@ -683,6 +688,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 +701,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 +729,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 Отсканируйте, чтобы открыть на телефоне
@@ -770,6 +779,8 @@ Settings Настройки
Setup complete Настройка завершена
Share QR Поделиться QR
Share channel Поделиться каналом
Share contact Поделиться контактом
Share failed Не удалось отправить контакт
Share location in advert Делиться местоположением в advert
Share secret Поделиться ключом
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Поделитесь секретом из 32 символов, чтобы другие присоединились. Пусто = случайный.
@@ -926,6 +937,7 @@ Your own apps Ваши приложения
Zero-hop Без ретрансляции
Zero-hop advert sent Zero-hop advert отправлен
Zoom: +/- buttons Масштаб: кнопки +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected клиент подключён
command команда
contacts (%d): контакты (%d):
@@ -968,8 +980,6 @@ tap to exit full screen нажмите для выхода из полноэкр
zoom масштаб
zoom %d масштаб %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. усилитель ~17 дБ для тихих/удалённых мест; выключайте в шумных.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1001,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1014,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+102 -7
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: sr
# ver: 12
# ver: 20
# name: Српски
# base: sr
(device behind) (уређај касни)
@@ -184,6 +184,7 @@ Contact added Контакт додат
Contact deleted Контакт обрисан
Contact gone Контакт нестао
Contact missing Контакт недостаје
Contact shared Контакт подељен
Contacts Контакти
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Контакти су у унутрашњој меморији - SD картица се није монтирала при покретању. Поново убаци картицу и рестартуј.
Contacts are on internal flash. Контакти су у унутрашњој меморији.
@@ -282,6 +283,7 @@ End time Време краја
Enter SSID first Прво унесите SSID
Enter a name Унесите име
Enter a network name Унесите име мреже
Enter a region name Enter a region name
Enter adds a new line Enter додаје нови ред
Enter exactly 32 hex characters. Унесите тачно 32 hex знака.
Enter key sends message Тастер Enter шаље поруку
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Навиг. тастатуром: WASDZ укљ.
Keyboard nav: off Навиг. тастатуром: искљ.
Keyboard navigation Навигација тастатуром
Keys
Known regions Known regions
LOS → %s Оптичка видљивост → %s
Landscape (desktop) Положено (десктоп)
Landscape set - applies when remote mode starts. Положено подешено - важи кад крене даљински режим.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Нема мрежа (само 2.4 GHz)
No onboard GPS Нема уграђеног GPS
No other networks found Нема других мрежа
No position yet. A cold start needs a clear view of the sky and can take several minutes. Још нема позиције. Хладан старт тражи чист поглед на небо и може да потраје неколико минута.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Нема одговора од %s
No reply. Check password, server,\nor device clock (device: %s) Нема одговора. Проверите лозинку, сервер\nили сат уређаја (уређај: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Овде нема сачуваних плочица.\n\nПовежите се на Wi-Fi (Подешавања → Wi-Fi)\nда преузмете ову област.\nСачуване плочице остају доступне ван мреже.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Недавно чути
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Форматирати SD као MESHCOMOD (FAT32)?\nСВИ подаци на картици биће обрисани.
Region & scope Регион и опсег
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Опсег региона (#tag) за овај канал.\nПразно = подразумевани опсег.
Region scope (#tag), blank = default. Опсег региона (#tag), празно = подразумевано.
Region scope (#tag, blank = none) Опсег региона (#tag, празно = ниједан)
@@ -683,6 +688,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 +701,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 +729,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 Скенирај да отвориш на телефону
@@ -770,6 +779,8 @@ Settings Подешавања
Setup complete Подешавање завршено
Share QR Подели QR
Share channel Подели канал
Share contact Подели контакт
Share failed Дељење није успело
Share location in advert Дели локацију у advert-у
Share secret Подели тајну
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Поделите тајну од 32 знака да се други придруже. Празно = насумична.
@@ -818,7 +829,7 @@ TCP on TCP укљ
TOUCH BETA TOUCH BETA
TX TX
Tab hotkeys — tap a row, then press a key Пречице картице — додирни ред, па притисни тастер
Tap Use to switch - the device reboots to apply. Додирните „Користи“ да промените — уређај ће се поново покренути.
Tap Use to switch - the device reboots to apply. Додирните "Користи" да промените — уређај ће се поново покренути.
Tap Use to switch - the device reboots to apply. Language files live in /lang on the storage; edit them or add your own. Додирни «Користи» за промену - уређај се поново покреће. Датотеке језика су у /lang на меморији; уреди их или додај своје.
Tap a language; the device reboots to apply. Изаберите језик; уређај ће се рестартовати.
Taste the rainbow! Окуси дугу!
@@ -926,6 +937,7 @@ Your own apps Твоје апликације
Zero-hop Без скока
Zero-hop advert sent Zero-hop advert послат
Zoom: +/- buttons Зум: тастери +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected клијент повезан
command команда
contacts (%d): контакти (%d):
@@ -968,8 +980,6 @@ tap to exit full screen додирните за излаз из целог ек
zoom зум
zoom %d зум %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. појачало ~17 dB за тиха/удаљена места; искључи у бучним.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1001,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1014,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+101 -6
View File
@@ -1,7 +1,7 @@
# wadamesh language file
# canonical source - translators: edit this file and PR it
# code: uk
# ver: 12
# ver: 20
# name: Українська
# base: uk
(device behind) (пристрій відстає)
@@ -184,6 +184,7 @@ Contact added Контакт додано
Contact deleted Контакт видалено
Contact gone Контакт зник
Contact missing Контакт відсутній
Contact shared Контакт надіслано
Contacts Контакти
Contacts are on internal flash - the SD card did not mount at boot. Re-seat the card and reboot. Контакти у внутрішній пам'яті - SD-карта не змонтувалася під час завантаження. Переставте картку і перезавантажте.
Contacts are on internal flash. Контакти у внутрішній пам'яті.
@@ -282,6 +283,7 @@ End time Час завершення
Enter SSID first Спочатку введіть SSID
Enter a name Введіть ім'я
Enter a network name Введіть назву мережі
Enter a region name Enter a region name
Enter adds a new line Enter додає новий рядок
Enter exactly 32 hex characters. Введіть рівно 32 hex-символи.
Enter key sends message Клавіша Enter надсилає повідомлення
@@ -407,6 +409,7 @@ Keyboard nav: WASDZ on Навігація клавіатурою: WASDZ увім
Keyboard nav: off Навігація клавіатурою: вимк.
Keyboard navigation Навігація клавіатурою
Keys
Known regions Known regions
LOS → %s Пряма видимість → %s
Landscape (desktop) Альбомна (десктоп)
Landscape set - applies when remote mode starts. Альбомну вибрано - застосується під час запуску віддаленого режиму.
@@ -533,6 +536,7 @@ No networks found (2.4 GHz only) Мережі не знайдено (лише 2.
No onboard GPS Немає вбудованого GPS
No other networks found Інших мереж не знайдено
No position yet. A cold start needs a clear view of the sky and can take several minutes. Позиції ще немає. Холодний старт потребує відкритого неба і може тривати кілька хвилин.
No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details. No regions yet.\n\nAdd a #region to have messages\nscoped to it named in message details.
No reply from %s Немає відповіді від %s
No reply. Check password, server,\nor device clock (device: %s) Немає відповіді. Перевірте пароль, сервер\nабо годинник пристрою (пристрій: %s)
No saved map tiles here.\n\nConnect to Wi-Fi (Settings → Wi-Fi)\nto download this area.\nSaved tiles stay available offline. Тут немає збережених плиток.\n\nПідключіться до Wi-Fi (Налаштування → Wi-Fi),\nщоб завантажити цю ділянку.\nЗбережені плитки лишаються доступні офлайн.
@@ -641,6 +645,7 @@ Receive unreleased test firmware — newer features, but less tested. The update
Recently heard Нещодавно чуто
Reformat SD as MESHCOMOD (FAT32)?\nALL data on the card will be erased. Переформатувати SD як MESHCOMOD (FAT32)?\nУСІ дані на картці будуть стерті.
Region & scope Регіон і охоплення
Region list is full Region list is full
Region scope (#tag) for this channel.\nBlank = use the default scope. Регіон (#tag) для цього каналу.\nПорожньо = область за умовчанням.
Region scope (#tag), blank = default. Область регіону (#tag), порожньо = за замовчуванням.
Region scope (#tag, blank = none) Регіон (#tag, порожньо = немає)
@@ -683,6 +688,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 +701,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 +729,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 Відскануйте, щоб відкрити на телефоні
@@ -770,6 +779,8 @@ Settings Налаштування
Setup complete Налаштування завершено
Share QR Поділитися QR
Share channel Поділитися каналом
Share contact Поділитися контактом
Share failed Не вдалося надіслати контакт
Share location in advert Ділитися місцезнаходженням в advert
Share secret Поділитися ключем
Share the 32-char secret so others can join. Leave the secret empty to generate a random one. Поділіться секретом із 32 символів, щоб інші приєдналися. Порожньо = випадковий.
@@ -926,6 +937,7 @@ Your own apps Ваші застосунки
Zero-hop Без ретрансляції
Zero-hop advert sent Zero-hop advert надіслано
Zoom: +/- buttons Масштаб: кнопки +/-
ambiguous (several regions matched) ambiguous (several regions matched)
client connected клієнт під'єднано
command команда
contacts (%d): контакти (%d):
@@ -968,8 +980,6 @@ tap to exit full screen торкніться, щоб вийти з повное
zoom масштаб
zoom %d масштаб %d
~17 dB amp for quiet/remote areas; turn off in noisy spots. підсилювач ~17 дБ для тихих/віддалених місць; вимикайте в галасливих.
© OpenStreetMap © OpenStreetMap
© OpenTopoMap © OpenTopoMap
Scope
another region
my region
@@ -991,7 +1001,6 @@ Overwrite oldest non-favorite
1-character messages will be shown 1-character messages will be shown
All All
Allow Allow
Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back. Apps that may send messages on the mesh. Anything they send goes out under your node name and cannot be told apart from a message you typed. Turn one off to take the permission back.
Ignore 1-character messages Ignore 1-character messages
Join w/ password Join w/ password
Location no longer shared Location no longer shared
@@ -1005,12 +1014,98 @@ Never\nChosen contacts only\nAnyone who asks Never\nChosen contacts only\nAnyone
No apps installed. No apps installed.
No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh) No reply. Path hash is %u bytes;\nolder repeaters drop those.\nTry 1 byte (Settings > Radio & Mesh)
Not supported on this board Not supported on this board
Read incoming messages Read incoming messages
Reconnected to %.40s Reconnected to %.40s
Send messages as me Send messages as me
Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu. Sent only when that contact asks, encrypted to them. Nothing is broadcast. Needs "Answer telemetry requests" on. Pick contacts in a contact's menu.
Server has forgotten you.\nJoin with the room password. Server has forgotten you.\nJoin with the room password.
Share my loc Share my loc
Share my location when asked Share my location when asked
Stop sharing loc Stop sharing loc
not asked yet not asked yet
Battery life: gathering data… Battery life: gathering data…
Small\nMedium\nLarge\nJumbo Small\nMedium\nLarge\nJumbo
"%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust. "%s" wants to send PRIVATE messages as you.\n\nIt could write to any of your contacts, or post to a room, and the message will look exactly like one you typed.\n\nOnly allow this for an app you trust.
Map pan off Map pan off
Map pan: arrows pan, Back exits Map pan: arrows pan, Back exits
Perf: Perf:
Post to channels as me Post to channels as me
Powering off… press BOOT to wake Powering off… press BOOT to wake
Read channel messages Read channel messages
Read private messages Read private messages
Send private messages as me Send private messages as me
What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back. What each installed app is allowed to do. Anything an app sends goes out under your node name and cannot be told apart from a message you typed. Private covers direct messages and room posts, and is kept separate from channels on purpose. Turn one off to take it back.
Wi-Fi off, new map areas can't download Wi-Fi off, new map areas can't download
App permissions App permissions
"%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted. "%s" wants to send discovery probes.\n\nEach probe asks every node in range to reply, so it uses airtime on the whole local mesh, not just yours.\n\nNothing is sent under your name and no message is transmitted.
? ?
About / credits About / credits
Auth failed Auth failed
Auto-add on for %s — new %s land in Contacts automatically. Auto-add on for %s — new %s land in Contacts automatically.
Console mode Console mode
Console mode (experimental) Console mode (experimental)
Direct (0-hop) only Direct (0-hop) only
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back, and if it ever fails to start the device returns here on its own. Toggling reboots.
EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots. EXPERIMENTAL. Boots into a text console with no graphical interface: type commands, read replies. Frees the memory and processor time the interface uses. Type 'ui' in the console to come back. Toggling reboots.
Enter text Enter text
Entering console mode - rebooting... Entering console mode - rebooting...
Favorite Favorite
How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted. How tiles work:\nThe map is built from 256×256 "slippy" tiles. Only the tiles for the area you're viewing are fetched — there is no bulk pre-download.\n\nBecause this device can't do HTTPS (not enough heap after Wi-Fi starts) and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh proxy: it fetches the upstream PNG over HTTPS with an identifying User-Agent, re-encodes it as JPEG, and caches it. Your device then caches each tile to its own flash, so a tile is only downloaded once.\n\nUse Options → Reload tiles to re-download the tiles currently in view if one looks corrupted.
Init… Init…
Leaving console mode - rebooting... Leaving console mode - rebooting...
Link lost Link lost
MESH MESH
Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n Map data © OpenStreetMap contributors.\nopenstreetmap.org/copyright\nLicensed under the Open Database License (ODbL).\n\n
Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n Map style © OpenTopoMap (CC-BY-SA) — opentopomap.org\nMap data © OpenStreetMap contributors (ODbL) + SRTM.\n\n
Name (A-Z) Name (A-Z)
Nearest first Nearest first
Recent message Recent message
Reload tiles in view Reload tiles in view
Repeaters Repeaters
SIGNAL SIGNAL
SSID not found SSID not found
Saved networks Saved networks
Select to delete Select to delete
Send discovery probes Send discovery probes
Show contacts Show contacts
Show coordinates Show coordinates
Show tile z/x/y Show tile z/x/y
Starting… Starting…
Text console (experimental) Text console (experimental)
Tile debug overlay Tile debug overlay
chats chats
repeaters repeaters
rooms rooms
sensors sensors
tap to cycle off / on / auto tap to cycle off / on / auto
#7A7F87 Scanning… nothing has answered yet# #7A7F87 Scanning… nothing has answered yet#
Export crash report (%uK) Export crash report (%uK)
On-device text browser · no proxy, no tracking On-device text browser · no proxy, no tracking
Paste (copy) Paste (copy)
Paste (move) Paste (move)
avg %.1f%% peak %.1f%% over %ds avg %.1f%% peak %.1f%% over %ds
channel busy %.1f%% channel busy %.1f%%
sampling... sampling...
teal = now blue = average teal = now blue = average
window restarted window restarted
Filter Filter
Hide system files Hide system files
Networks Networks
Other networks Other networks
Show system files Show system files
Unfav Unfav
Firmware beta_%d\nChecking for updates over Wi-Fi… Firmware beta_%d\nChecking for updates over Wi-Fi…
Install beta_%d?\nThis downgrades the firmware and reboots. Install beta_%d?\nThis downgrades the firmware and reboots.
Other (hidden) network… Other (hidden) network…
Paused Paused
Scan again Scan again
At a glance At a glance
At a glance disabled At a glance disabled
At a glance enabled At a glance enabled
At a glance while locked At a glance while locked
Glance only shows when unlocked Glance only shows when unlocked
Glance shows message previews\nwhile the screen is locked Glance shows message previews\nwhile the screen is locked
Snake — swipe, roll, or press a direction Snake — swipe, roll, or press a direction
N/A N/A
This board cannot run this app. This board cannot run this app.
Signal Signal
Signal (stale) Signal (stale)
nothing heard yet nothing heard yet
+67 -67
View File
@@ -1,69 +1,69 @@
{
"langs": [
{
"code": "bg",
"name": "Български",
"ver": "12"
},
{
"code": "de",
"name": "Deutsch",
"ver": "12"
},
{
"code": "el",
"name": "Ελληνικά",
"ver": "12"
},
{
"code": "es",
"name": "Español",
"ver": "12"
},
{
"code": "fr",
"name": "Français",
"ver": "12"
},
{
"code": "hu",
"name": "Magyar",
"ver": "12"
},
{
"code": "it",
"name": "Italiano",
"ver": "12"
},
{
"code": "nl",
"name": "Nederlands",
"ver": "12"
},
{
"code": "pt-br",
"name": "Português (BR)",
"ver": "12"
},
{
"code": "ro",
"name": "Română",
"ver": "12"
},
{
"code": "ru",
"name": "Русский",
"ver": "12"
},
{
"code": "sr",
"name": "Српски",
"ver": "12"
},
{
"code": "uk",
"name": "Українська",
"ver": "12"
}
]
"langs": [
{
"code": "bg",
"name": "Български",
"ver": "20"
},
{
"code": "de",
"name": "Deutsch",
"ver": "20"
},
{
"code": "el",
"name": "Ελληνικά",
"ver": "20"
},
{
"code": "es",
"name": "Español",
"ver": "20"
},
{
"code": "fr",
"name": "Français",
"ver": "20"
},
{
"code": "hu",
"name": "Magyar",
"ver": "20"
},
{
"code": "it",
"name": "Italiano",
"ver": "20"
},
{
"code": "nl",
"name": "Nederlands",
"ver": "20"
},
{
"code": "pt-br",
"name": "Português (BR)",
"ver": "20"
},
{
"code": "ro",
"name": "Română",
"ver": "20"
},
{
"code": "ru",
"name": "Русский",
"ver": "20"
},
{
"code": "sr",
"name": "Српски",
"ver": "20"
},
{
"code": "uk",
"name": "Українська",
"ver": "20"
}
]
}
+1
View File
@@ -0,0 +1 @@
{"id":"nearby","name":"Nearby","ver":"1.0","desc":"Your contacts on a real map, sorted by distance, with bearing and a live frame counter. Reference app for wada.map, wada.ui.list, wada.geo and app.on_packet."}
+137
View File
@@ -0,0 +1,137 @@
-- Nearby (Lua) — contacts on a real map, with distance and bearing, and a live
-- packet counter.
--
-- Reference app for the four things the SDK gained alongside it: wada.map (the
-- firmware's own tiles inside an app page), wada.ui.list (scrollable selectable
-- rows), app.on_packet (each frame delivered once instead of polled), and
-- wada.geo (great-circle maths in C rather than in your instruction budget).
local ui, sys, mesh, geo, timer = wada.ui, wada.sys, wada.mesh, wada.geo, wada.timer
local C = ui.colors
local app = {}
local map, list, hdr, detail = nil, nil, nil, nil
local pts, sel = {}, 0
local pkt_count, pkt_adverts = 0, 0
local W, H
local function here()
local fix = sys.gps()
if fix then return fix.lat, fix.lon, true end
local me = mesh.self()
-- self() is the last known position, which may be old. Say which one is in
-- use rather than presenting a stale fix as a live one.
if me.lat ~= 0 or me.lon ~= 0 then return me.lat, me.lon, false end
return nil
end
local function fmt_dist(m)
if m < 1000 then return string.format("%.0f m", m) end
return string.format("%.1f km", m / 1000)
end
local function rebuild()
local lat, lon, live = here()
pts, sel = {}, 0
for _, c in ipairs(mesh.contacts()) do
if c.lat ~= 0 or c.lon ~= 0 then
local e = { name = c.name, lat = c.lat, lon = c.lon, type = c.type, pubkey = c.pubkey }
if lat then
e.dist = geo.distance(lat, lon, c.lat, c.lon)
e.brg = geo.bearing(lat, lon, c.lat, c.lon)
end
pts[#pts + 1] = e
end
end
if lat then table.sort(pts, function(a, b) return (a.dist or 1e9) < (b.dist or 1e9) end) end
list:clear()
for i, e in ipairs(pts) do
local label = e.dist
and string.format("%-12s %8s %-2s", e.name:sub(1, 12), fmt_dist(e.dist), geo.cardinal(e.brg))
or e.name
list:add(label, function() app.pick(i) end)
end
if #pts == 0 then list:add("no contacts have a position yet") end
hdr:set(string.format("%d placed | %s | %d frames (%d adverts)",
#pts, lat and (live and "GPS fix" or "last known position") or "no position", pkt_count, pkt_adverts))
hdr:color(lat and C.accent or C.bad)
if lat then app.draw(lat, lon) end
end
function app.draw(lat, lon)
if not map then return end
map:center(lat, lon)
map:clear()
if map:tiles() == 0 then
-- An empty rectangle looks like open water. Say what it actually is.
detail:set("no map tiles cached here at zoom " .. map:zoom())
detail:color(C.sub)
end
for i, e in ipairs(pts) do
map:line(lat, lon, e.lat, e.lon, i == sel and C.good or 0x2A3340, i == sel and 2 or 1)
end
for i, e in ipairs(pts) do
map:marker(e.lat, e.lon, i == sel and C.good or C.accent, i == sel and 12 or 8)
end
map:marker(lat, lon, 0xE8A33D, 10) -- us, last so it sits on top
end
function app.pick(i)
sel = i
list:select(i)
local e = pts[i]
if not e then return end
local lat, lon = here()
if e.dist then
detail:set(string.format("%s %s %.0f deg (%s) %s",
e.name, fmt_dist(e.dist), e.brg, geo.cardinal(e.brg), e.pubkey))
else
detail:set(e.name .. " " .. e.pubkey)
end
detail:color(C.text)
if lat then app.draw(lat, lon) end
end
function app.on_open(w, h)
W, H = w, h
local LH = ui.text_h(12)
hdr = ui.label("", 4, 4, 12, C.accent); hdr:width(w - 10)
-- hdr and detail below are width-limited, which turns wrapping on, and both
-- carry variable-length text (node names, a status phrase). Reserve two lines
-- for each: a wrapped line would otherwise be drawn over by whatever follows.
local map_h = math.floor(h * 0.45)
local y = 4 + LH * 2 + 4
if sys.caps().map then
map = wada.map.view(4, y, w - 8, map_h)
else
ui.label("this board has no map support", 6, y + 10, 12, C.sub)
end
y = y + map_h + 4
detail = ui.label("pick a contact", 4, y, 12, C.sub); detail:width(w - 10)
y = y + LH * 2 + 4
list = ui.list(4, y, w - 8, h - y - 4)
rebuild()
-- Two cadences, which is what wada.timer.after/every made possible: a slow
-- rebuild (contacts and GPS move slowly) and no fast tick at all, because
-- packets now arrive by callback instead of being polled for.
timer.every(5000, rebuild)
end
-- One call per frame the radio received, in arrival order. Counting was simply
-- not possible against a polled 16-entry ring.
function app.on_packet(p)
pkt_count = pkt_count + 1
if p.pubkey then pkt_adverts = pkt_adverts + 1 end
end
function app.on_close()
if map then map:close() end
end
return app
+1
View File
@@ -0,0 +1 @@
{"id":"sdktest","name":"SDK Test","ver":"1.2","desc":"Developer tool. Checks the extended Lua SDK on this board: capabilities, clock, battery, GPS, file access, crypto against published RFC vectors, channel discovery, and buttons that TRANSMIT a test message to Public and a DM to your first contact (each asks permission first)."}
Loaded 100 of 234 files, more files were not shown because too many files have changed in this diff. Show more