Two reporters on card-less Heltec V4s saw the whole UI freeze for 5-60 s at a time
with BLE, WiFi and GPS all off and no user activity, and BOTH of a reporter's two
devices froze at the same moment. About -> "Loop stalls" named the culprit
unambiguously: tag `mesh`, with peaks of 11451 / 12175 / 14592 / 18063 / 19113 ms.
That is inside the_mesh.loop(), i.e. the advert receive path, and the cost is SPIFFS
garbage collection on a partition kept permanently churned by writes that happen per
advert. The simultaneity across two units is the giveaway: the trigger is a flooded
advert both of them receive, after which each runs the same deterministic write.
This is the residue of beta_40's "card-less contacts-save stall fix", which capped how
OFTEN the contacts rewrite happens without reducing its cost, and left the
highest-frequency writer untouched.
Two frequency reductions, both keeping writes ATOMIC:
1. putBlobByKey now persists an advert blob once per key per boot. The core calls it on
EVERY advert (outside the auto-add block, so for already-known contacts too) and each
call is a full create+truncate+write. With ~200 known nodes re-advertising that is a
flash write every few seconds, forever, purely to keep the raw advert packet fresh for
the Share-contact feature. The content is effectively static, and getBlobByKey still
reads the file we already wrote, so there is no cache to keep coherent. Steady state
on the packet path becomes zero flash I/O. Costs 2 KB of DRAM.
2. A save triggered by an add/remove now has its own 30 s floor. It previously bypassed
the 5-minute refresh window entirely, so on a growing mesh every newly-heard node
forced its own full 30 KB rewrite (200 contacts x 152 B). A burst of new nodes now
coalesces into one rewrite. Kept short on purpose: a new contact still needs to reach
flash promptly, and losing one to an unclean power cut only costs a rediscovery on that
node's next advert.
Deliberately NOT done: making the contacts save incremental (seek + one 152-byte record).
It is tempting since the file is a flat fixed-stride array, and it would cut churn far
harder, but it abandons the tmp+rename atomicity that beta_46 added to fix real contact
data loss. Both reporting devices show "Last reset: Brownout", so non-atomic in-place
writes on that hardware would trade a stall for corrupted contact records. Frequency
first, atomicity intact.
Also seen in those same screenshots and NOT addressed here: ui:gps stalls of 3077 /
3769 / 3848 ms on a device whose owner says GPS is switched off, and ui:lvgl stalls up
to 2227 ms. Separate issues, worth their own investigation.
Verifiable by the same diagnostic that found it: the `mesh` entries in About -> Loop
stalls should stop appearing.
Builds clean on Heltec V4 TFT and T-Deck.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Partial fix for "no ping and telemetry response" reported from the device AND the
phone app. onContactResponse's deferred-login branch runs before every pending_*
matcher and, while armed, consumed ANY response from that contact and returned. Its
comment justifies this with "we have sent no REQ to this contact, so any RESPONSE
here is the login reply" -- true of the UI, but the companion app can independently
have a STATUS / TELEMETRY / BINARY request in flight to the same node. There is also
no distinct login-failure code on the wire (a failure is just "not
RESP_SERVER_LOGIN_OK"), so a non-OK frame is indistinguishable from the app's reply,
and the app's response was swallowed with the phone left waiting.
A LOGIN_OK is unambiguously ours, so it is still always consumed. Otherwise the
branch now falls through when the app has a request pending on that same contact,
letting its matcher see the frame; the UI's own reply deadline disarms us, which is
all the early disarm here ever provided. Behaviour is unchanged whenever the app is
not waiting, which is the common case.
Deliberately NOT changed: sendStatusPingForUI / sendTelemetryRequestForUI zero the
app's pending_status / pending_telemetry on entry. That looks like deliberate
arbitration so a UI-initiated request routes to the UI rather than the phone, and
removing it could double-handle a response. Wants its own change and a bench test.
Note this is unlikely to be the whole of #124: the leading theory remains the
repeater's per-client replay high-water mark, which no client-side change can undo.
Builds clean on T-Deck and Heltec V4 TFT.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New Discover app: active NODE_DISCOVER sweep -> signal-ranked nearby list, tap-to-add-contact, GPS wardriving log (SD CSV) + signal-coloured coverage overlay on the map. Board-agnostic.
- T-Display P4 TFT-LCD (HI8561) variant support (WADA_P4_LCD build; AMOLED bin untouched).
- Wire the Attaky Core board (#158, @attakygit) into the release matrix + web flasher.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full keyboard+encoder-driven board port: TCA8418 QWERTY matrix, rotary encoder
focus-nav, ST7796 display, ES8311 notification sound, both radio variants.
Hardware-verified by the author against a live mesh.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
# src/ui-touch/UITask.cpp
The browser control panel gains full Chats / Contacts / Discovered / Settings
tabs (search, sort, filter, per-contact actions, notifications + live refresh,
ACK/repeats, add-from-discovered, live radio settings, quick-command picker).
Heltec V4 map tiles: fixed the "only the top renders" bug on the 2 MB-PSRAM
board with a persistent tile-buffer pool + viewport culling (no more per-render
128 KB churn/fragmentation). Adds an opt-in "Tile debug overlay" (Map options).
Also: V4 physical-keyboard input in remote/VNC, clearer remote-access screen,
complete Terminal help on device + web, WADAMESH header + status icons.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fixes:
- Card-less devices (Heltec V4) froze for seconds: a full contacts rewrite to
SPIFFS on every advert refresh triggered a multi-second GC in the mesh loop.
Coalesce advert-driven saves (a contact-set change still saves promptly); SD
boards unchanged. Flush on reboot/power-off so nothing is lost.
- Long translations (FR/DE/...) overflowed fixed-width labels: new
uiFitLabelWidth() shrinks the font to fit one line instead of clipping/wrapping
- applied to the message menu, confirm dialogs, and app-drawer tiles.
- Home signal graph: "tap for details" hint moved to bottom-right so it no longer
overlaps the "Sig" chip in longer languages.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Since the beta_35 lazy history writer, message-ring flushes are spaced
up to 30 s apart on the deep SD ring. Every on-device reboot/power path
compensates by calling persistHistoryNow() first, but the companion
protocol's CMD_REBOOT (the phone app's reboot button) went straight to
board.reboot(), dropping everything since the last flush - the newest,
just-read messages, which reads as 'my channel and DM messages get
deleted after a manual reboot' (Leon P, T-Deck under Launcher, beta_35
through beta_37).
persistHistoryNow() is now an AbstractUITask hook (default no-op, so
non-touch companions are unchanged) and CMD_REBOOT calls it before
rebooting, matching the power-menu contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Boot TX power was left at a conservative 10dBm (Heltec V4's pattern) with
no way to raise it, unlike the T-Deck which boots straight at the chip's
real 22dBm ceiling. On hardware this was silently degrading outbound
range: adverts/DMs sent from the pager were unreliable while inbound
reception was fine, since the far node's own TX power was unaffected.
22dBm is confirmed as this chip's actual sub-GHz HP-PA ceiling via
RadioLib's LR1120::checkOutputPower() (LR1121 inherits it) and matches
trail-mate's own working config for this board.
Also widen the three RX-boosted-gain gates in MyMesh.cpp/DataStore.cpp
that only checked USE_SX1262/USE_SX1268 to include USE_LR1121 --
CustomLR1121Wrapper already implements setRxBoostedGainMode/
getRxBoostedGainMode, so the setting was silently a no-op for this radio.
Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>
- History flush runs on the core-0 worker (snapshot + storage-busy gate +
bounded shutdown wait): kills the V4's multi-second ui:hist stalls and
the refuses-to-wake-after-message symptom (SPIFFS GC off the UI thread).
- BLE + Wi-Fi runtime enables share the boot co-init heap guard (50 KB
free + 20 KB block): refuse with a toast + revert the switch instead of
panicking (BLE) or silently not starting while claiming on (Wi-Fi).
- Internal DRAM: static footprint 95,365 -> 64,908 B (30.5 KB freed):
serial_interface -> PSRAM; 23 keyboard layout maps const'd -> flash;
nine rings/tables -> psAlloc PSRAM (UITask/TouchPrefsStore/MyMesh);
unused TinyUSB MSC + DFU-mode class drivers stubbed out of the link
(usb_unused_class_stubs.c) — CDC + runtime-DFU untouched, double-flash
verified over the stubbed stack.
- DataStore prefs writes are crash-safe (write .tmp, swap) with a
self-healing loader (.tmp recovery) and a truthful save result up to
the profile-name toast — fixes the boots-with-default-name-once report.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Consumes the new core (buffered receive drain task + RX counters, #13
stock payload layout, GPS-date guard). Fork side:
- TouchPrefs v33 rx_queue, DEFAULT ON for the test channel (fresh
installs + a one-time migrate for upgraders); opt-out toggle
'Buffered receive (experimental)' in Radio & Mesh, applies live.
- About live tier shows LoRa RX heard/read/err/late-lost/qdrop, the
field evidence for the missed-messages fix.
- Spectrum parks/resumes the drain task around raw radio use; MyMesh
setParams sequences hold the radio mutex.
- TanmatsuLoraRadio: no-op API stubs (P4 keeps its own RX path).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Rooms: re-enable the keep-alive pinger (checkConnections), arm a 128s
keep-alive on LOGIN_OK (servers send 0), blank-relogin self-heal while a
room chat is open, 'Log in again' in the room sheet, read-only warning.
Root-caused against simple_room_server: 3 unACKed pushes freeze a client
until the server hears from it — and we never pinged (issue #89).
- Burn-in: ST7789 SLPIN/SLPOUT on screen-off (backlight-off alone kept the
panel driving the static image), lit-lock dim guard on all boards, 10s
notify-wake re-dim, lock clock pixel drift.
- wyvern.red batch: scroll-keys map zoom, backspace exits empty composer,
Reset path in the chat sheet, compact chat toggle (TouchPrefs v31),
clearer delivery glyphs + tap-to-resend on failed sends.
- OTA: hide Install-update when the running image's physical address falls
outside the esp_ota running slot (mixed/legacy tables; beta_21 coredump).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two bugs in the manual telemetry request path (the Request button in the
telemetry window):
1. Usually only the second request succeeded. The guest LOGIN and the
telemetry REQ were sent back-to-back, but a repeater drops a REQ from a
sender it hasn't added to its ACL yet, and the ACL entry isn't committed
by the time the first REQ is processed — so the first request got no reply
and the user had to tap twice. Defer the REQ: uiSendRequestAfterGuestLogin()
sends only the guest LOGIN and fires the REQ from onContactResponse once the
LOGIN-OK arrives, by which point we're in the repeater's ACL and a direct
out_path has been learned, so it lands on the first try. Also adds a
single-flight guard on telemetryRequestNow(), holds auto-poll while a manual
request is pending (so it can't clobber the pending reply tag), and disarms
the deferred login on timeout so a late LOGIN-OK can't fire a stale REQ.
2. The status-bar async spinner only blinked for ~1.5s on a telemetry request
(the markMeshRequest window) then froze, instead of blinking for the whole
pending window like a status ping. Its active predicate watched the ping
deadline but not the telemetry timers; OR in the telemetry pending state.
Auto-poll's best-effort chained send and the admin-console login path are
left unchanged.
The signal probe now sends a zero-hop NODE_DISCOVER_REQ control packet
(the standard MeshCore node-discovery that the Ultra / KiekR apps use)
instead of a trace, which repeaters do not answer. Repeaters reply
directly with a NODE_DISCOVER_RESP, captured in onControlDataRecv by
matching the probe tag into _ui_sig_* SNR/RSSI. Thanks to Tarmo for
decoding the exact packet.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signal probe: replace the beta_21 zero-hop advert (which nothing replies to, so the
signal never updated) with a directed TRACE ping to the nearest reachable repeater.
It retransmits — a real reply we measure — without flooding the mesh. New
MyMesh::uiSendSignalProbe() picks the shortest-path repeater; the reply is captured
silently in onTraceRecv via _ui_sig_probe_tag. Falls back to a zero-hop advert when
no repeater is known. Thanks to Tarmo for the insight.
Contacts (#73 part A): a contact discovered while a companion app is connected over
BLE now refreshes the device's own Contacts list + notification. onDiscoveredContact
fired the UI notify only in the standalone branch — move it out so it always fires,
and flag the list dirty for UITask::loop to rebuild on the LVGL thread.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New: stable/test update channels with an opt-in "Get test builds (beta)" toggle on
OTA devices (switches both the update check and what you install); experimental
opt-in MQTT bridge (consent-gated, payload encryption, direct messages off by
default); Portugal (Narrow) region preset (#74); saved-contacts counter in the
Contacts overflow menu (#72).
Fixed: the signal probe is now strictly zero-hop so a repeater can't re-flood it;
the contact list sorts before capping so the most relevant contacts show, with a
"+N more — search to narrow" footer (#73); the blocked-users list opened from
Contacts shows the two-line title bar with a back button; the Contacts overflow
popup fits the screen again.
Also lands the two-channel release tooling (scripts/release.sh stable/beta modes +
gen-flasher-meta channel arg), the docs site, and the MQTT reference decryptor.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New: Spectrum analyzer app; custom notification sounds (SD WAV per event);
saved Wi-Fi networks with auto-join; unified chat settings screen; per-channel
mute; Heltec V4.3 high-gain receiver (FEM LNA) toggle; Apps button on the V4
home screen; Blocked list reachable from Contacts + chat settings; Portuguese
(BR) UI language.
Fixed: touch-screen flood adverts now region-scoped so region repeaters relay
them (#68); channel sends matched by name so a message can't go out on the
wrong channel's key; opt-in "scope direct messages to region" so room-server
logins work through a region-only path (#64); Wi-Fi scan no longer cancelled
by the reconnect retry (empty SSID list).
Under the hood: flood-scope rework (channel vs direct floods); Spectrum owns
the SX1262 while open and restores mesh RX on exit; wifiScanIsActive() gate;
FEM KCT8103L LNA wired; TouchPrefsStore migrations for the new prefs. Adds the
previously-untracked device_caps.h.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The companion link is a BINARY protocol over Serial (USB-CDC). Unconditional debug
prints in operational paths — [ROOM] login send/resp, [TILE] fetch, [JPG] decode —
interleaved text into that stream and corrupted it. The MeshCore app then throws
'Bad state: Streamsink is bound to a stream' (#54) and the PC-app connect (#25) and
member-room login (#23) fail. Route them through a gated WIRE_DBG macro
(COMPANION_WIRE_DEBUG, off in release) like the existing SYNC_DEBUG_PRINTLN.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Vol+ short = top-bar dropdown toggle; long hold = sound master toggle
- Message-notification LED: flash on new message, soft green glow on unread; toggle in Display settings
- Backups use the internal FFat partition (export/scan/import) + Import button on the Backups page
- microSD browsable in the file manager (P4 SDMMC slot 0; the C6 radio's slot 1 untouched)
- Status-bar icon overlaps fixed (charging-slide + language indicator now SC-scaled with the cluster)
- Vol- screen sleep/wake/lock (screen-lock work)
- Companion link: TCP server start + BLE bond NVS persistence + app-sent channel-message mirror
All Tanmatsu changes gated #if defined(HAS_TANMATSU); T-Deck/V4 bins stay byte-identical.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A DM sent from the MeshCore companion app went out over the mesh but never
appeared on the T-Deck: the wire protocol deliberately doesn't echo sent
messages back to clients, so the on-device UI (a separate consumer) never saw
app-originated sends. Add an appSentMsgToContact() UI hook (default no-op for
non-touch UIs); the touch UI mirrors the message as a local outgoing bubble in
the recipient's thread. Called from the CMD_SEND_TXT_MSG handler on first
handling only (a client/transport retry was already mirrored).
Still open: the receive direction (T-Deck-received messages reaching the app) —
queueMessage already pushes RESP_CODE_CONTACT_MSG_RECV_V3 to all transports, so
that half needs a frame capture against the real app to pin down.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Any command arriving while s_meshcomod_pending_action is non-NONE and
the timeout hasn't expired previously fell through the confirmation
block and was processed normally, letting a second 'tcp off' / 'ble off'
silently overwrite the pending action and lose the original confirmation.
Add a final else clause that blocks the new command and reminds the user
to 'ok' or 'cancel' the in-flight request.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Post-beta_12 touch-UI fixes (T-Deck / Tanmatsu keyboard nav + composer):
Keyboard navigation
- Chat composer auto-edits on open (cursor shows, type immediately); every
OTHER field stays in navigate mode so the letter-nav keys keep working —
press select/Enter to edit it. Enter (or Esc/X on Tanmatsu) on an empty
composer drops back to navigate mode.
- Menu-bar tab-hotkey letters no longer fire while a text field is the focused
element (fixes a stray tab-jump while typing); directional nav still moves.
- New "Show menu-bar letters" setting (off by default) for the tab hotkeys.
Accent box
- The tap-to-pick accent box no longer steals the keyboard-nav focus group
(NAV_SKIP_FLAG) — it's a passive hint, so typing continues and a keybind no
longer navigates. Ready to wire arrow-key selection later.
Composer
- Dedicated "Special characters" picker (% $ @ # & ... currency/math/accents),
separate from the emoji picker.
- Long-press a sent message -> Resend.
Misc
- 12-hour clock honoured everywhere (top bar, chat bubbles, lock screen), not
just the chat overview.
- GPS UART RX buffer enlarged only when GPS is enabled (restores V4 RAM).
- Derive time-of-day from received mesh message timestamps when Wi-Fi/GPS off.
- Self-record the task-watchdog context on a TWDT reset for the crash report.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Room posts arrive as TXT_TYPE_SIGNED_PLAIN with the author in the 4-byte sender_prefix and a bare body. The display path passed the room contact's name, so every post showed the room name. Resolve the author from the prefix and pass it as the per-message sender via a new newRoomMsgFromPubWithMeta hook; the room stays the thread. Tested on T-Deck Plus.
Signed-off-by: Yazutsu <andrzej@gruziel.pl>
Headline: full keyboard navigation (on by default) — WASDZ spatial focus move, S select,
Q back, per-tab hotkeys (E/R/T/U/I) shown on the icons, plus scroll up/down (F/C). Every
key is remappable in Settings -> Keyboard. Foundation for keyboard-first devices like the
Tanmatsu T-Pager (no touchscreen) and a reliable keyboard workflow on the T-Deck today.
Also: #27 receive/flood reboot fix, on-boot crash-report prompt, map zoom +/- buttons (#26),
route-replay wide overview, 'App drawer as home' option. The in-progress Tanmatsu (ESP32-P4)
port source is now public. Mesh America catalog + release.sh kept from main.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- BLE: user-settable 6-digit pairing code (Settings -> Bluetooth), MyMesh::setBLEPin.
- Lock wallpaper: pick via the file manager (fast, any folder) + 'Set as wallpaper'
in the image viewer; downscaling JPEG decoder accepts images > 1024 px and keeps
the held buffer small; clear message for progressive JPEGs.
- Map tiles: validate JPEG magic before caching + re-fetch bad cached tiles
(fixes black quadrants).
- Channel @reply: quick-reply now appends at the cursor instead of wiping the
mention.
- Audio: heap pre-flight before i2s_driver_install (fixes the esp_timer NO_MEM
abort when toggling sound under BLE+Wi-Fi memory pressure).
- App drawer: squircle tiles. Log hygiene: CORE_DEBUG_LEVEL 1->0 (mute benign
vfs/Preferences spam off the USB-CDC companion stream).
- Core bump to core-v1.16.4 (drops the 4-byte chat-payload trailer, issue #13).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New Monitor app (app drawer): live RF sniffer — recently-heard feed
(type / RSSI / SNR / hops, colour-coded), link-margin grade, packet rate,
and an RSSI + noise-floor scope with an on-screen dBm scale; portrait /
landscape aware. Backed by a recent-RX ring buffer in MyMesh (logRxRaw).
- Chat: DM person icon / channel group icon; block non-contact senders by
name; keep scroll position when opening a thread; contacts sort popup
closes on select; long-press popup close-X no longer overlaps buttons.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Core bump: lib_deps -> meshcomod core-v1.16.3 (BLE advertises the node
name not "NimBLE"; GPS won't push a pre-fix ~1902 date).
Tim's quick-wins: Enter-key-sends toggle, 12-hour clock, lock-when-screen-off,
reverse scrollball.
Launcher / map: fix Wi-Fi tiles never downloading under Launcher (the SD-fallback
cache made tilesFsLowSpace() read the unmounted LittleFS as "full"); plot contact
markers before the tile decode so dots aren't ~2s late.
RTC / time: anchored-time guard re-applies UTC when the clock reads garbage
(GPS clobber); blank pre-2020 timestamps so empty channels don't show 1969/1970;
timezone picker (named zones with correct DST) replacing the CET-only base, with
a v2->v3 config migration mapping prior manual offsets onto a Custom zone.
BLE: persist the random pairing PIN (was re-rolled every boot).
Chat: don't auto-jump to latest on a new message when scrolled up; block-by-name
for non-contact room/channel senders (un-blockable room bots).
Power: drop CPU to 80 MHz when the screen is off; enable Wi-Fi modem-sleep only
once associated (enabling it on the unassociated STA broke the setup-wizard scan).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The graph legend now leads with the live signal ('Sig -3dB TX n RX n (tap)').
Tapping the graph (or the legend) opens a Signal & traffic popup: SNR, RSSI,
bars 0-4, how long ago we last heard the mesh, the flood/direct TX+RX totals
since boot, and the auto-discover interval. logRxRaw now also records RSSI for it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a 4-bar signal indicator to the status row, left of the connection icon.
MyMesh::logRxRaw now records the SNR (+ timestamp) of every received packet;
updateGlobalStatusBar maps that to 0-4 lit bars and dims them when nothing's been
heard for 5 min. To keep it fresh when idle, UITask::loop sends a light zero-hop
'discover' advert every 60 s (neighbours only, not flooded -> minimal airtime) so
nearby repeaters/nodes are prompted and their SNR shows up. Home-name cap shrinks
on the narrow V4 to leave room for the bars.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sent messages have no inbound route, so #30's repeater-names had nothing to show
there. Now when we hear an echo of our own flood, capture the re-flooding
repeater (the echo's last path hop) into the echo ring (deduped, bounded to 3),
and list those repeaters by name under 'Repeats heard' in the message Info.
Zero added risk: fixed-size store (no growth), hard buffer guards in the
renderer, read-only contact lookup. Covers #30 in both directions now.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- MyMesh.cpp logRxRaw: the self-echo parser tested (raw[0] & 0x80) for transport
codes, but 0x80 is the top of the payload VERSION field, not a flag. Transport
codes are present iff route_type (raw[0]&0x03) is TRANSPORT_FLOOD/DIRECT. Since
beta_12's region scope, scoped floods carry transport codes -> the parser hashed
the wrong payload slice -> the echo never matched -> 'repeats heard' showed 0 for
anyone with a region set. Now route-type aware (matches uiStashRxMeta). Also fixed
the diagnostic dst= decoder + the header-layout comment.
- MyMesh.h uiSendTraceRoute: walking c.out_path with an unchecked out_path_len
(uint8_t, can be 65..254 if a contact's path is corrupt) overran sendDirect's
payload memcpy -> reboot when tapping 'Trace route' on a sent DM. Clamp to
<= MAX_PATH_SIZE, else fall back to the single-hop trace.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- MyMesh.cpp: strcpy(p->name, contact.name) could overrun the 32-byte advert_paths
name field when an over-the-air advert carries a 32-char (unterminated) name,
corrupting the recently-heard/Found table. Bounded with strncpy + NUL-terminate.
- main.cpp: log nvs_free_entries at boot so a filling NVS (the boot-loop trigger
under Launcher) is visible in serial before it goes catastrophic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First board lands. wadamesh builds the LVGL touch firmware as its own project,
consuming the MeshCore core via lib_deps @ git tag (ALLFATHER-BV/MeshCore
#v1.16.0-wada.0) — no vendored core in this repo. Output is byte-identical to the
in-tree meshcomod build (delta = embedded build-path strings only).
Contents: companion_radio app (MyMesh/main/DataStore), ui-touch LVGL UI,
variants/heltec_v4 board glue, boards/heltec_v4.json, lv_conf, the bundled
ed25519 lib, AsyncElegantOTA, partition table, and a flattened platformio.ini
for env heltec_v4_tft_companion_radio_usb_tcp_touch.
MeshCore-derived files (app glue) remain MIT; ui-touch is GPL — see NOTICE.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Kaj Schittecat <kaj@schittecat.com>