Commit Graph
859 Commits
Author SHA1 Message Date
Kaj SchittecatandClaude Opus 5 202ea050ca touch: a self-update must never fetch another board's firmware
The per-board OTA_BIN_NAME chain ended in a bare #else naming the Heltec V4
TFT, so any board nobody had added to it silently downloaded the V4 image.
Update.end() only checks that an image is valid for an ESP32-S3, which the V4
build is, so nothing stopped it being flashed.

The Seeed Wio Tracker L2 shipped exactly like that. Its build defines only
HAS_WIO_TRACKER_L2, which the chain never tested, and the released beta_79
image carries "wadamesh-heltec-v4-tft" as its update name: an on-device update
on a Wio L2 installs Heltec V4 firmware onto Wio hardware and needs a USB
reflash to recover. The T-Deck Pro (HAS_TDECK_PRO) was in the same position
and would have done the same the moment it was published.

Every board is now listed explicitly, the V4 TFT included (the V4-R8 also
defines HELTEC_LORA_V4_TFT, and its branch already comes first), and anything
unlisted is an #error. Forgetting this table is now a build break instead of
a field brick.

Verified on all twelve OTA-capable targets: each compiles, and each binary
asks for exactly the artifact release.sh publishes for it (checked
mechanically: 10 PlatformIO envs plus both T-Display P4 SKUs, no mismatches).

Units already on beta_77 to beta_79 still have the wrong name compiled in, so
Wio L2 owners must update from the website over USB rather than on the device
until they are on a build with this fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 12:20:09 +02:00
Kaj SchittecatandClaude Opus 5 6bb98a1224 i18n: fix the "System Information" key at its source (13 languages)
#458 renamed TR("System info") to TR("System Information") and updated the
translation table to match, so the title stayed translated. But
src/ui-touch/i18n_builtin.h is GENERATED ("DO NOT EDIT") by
scripts/build/gen-lang-builtin.py from deploy/apps/lang/*.lang, and the rename
never reached those packs. Every regeneration since then -- the PlatformIO pre-hook
and the IDF build.sh both run it -- quietly wrote the old key back, so the source
asked for "System Information" while all thirteen tables answered "System info",
and the page title fell back to English in every language.

That is also why #517 appeared to revert the rename: its copy of the header was a
freshly regenerated one, faithfully reproducing the stale packs.

Rekeyed the thirteen source packs, then regenerated. The generated table changed by
exactly one key per language and nothing else, which confirms it was otherwise in
step with the packs, and the fix now survives the build's own regeneration, which is
the thing that used to undo it. The corrected packs reach devices that download a
language once the app store is republished with the next beta.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:56:25 +02:00
Michael A. Cojocari 703afb9d85 Merge issue #512 telemetry poll limit into PR #517 2026-09-15 19:49:22 -04:00
Michael A. Cojocari 07060e8a41 fix: bound telemetry auto-poll requests 2026-09-15 19:49:16 -04:00
Michael A. Cojocari 7cdc14a2df build: keep consolidated target builds green 2026-09-15 09:15:40 -04:00
Michael A. Cojocari ed69b56ed6 Merge remote-tracking branch 'refs/remotes/pr/514' into integration/all-open-prs-20260913 2026-09-13 18:58:23 -04:00
Michael A. Cojocari 78ff763b4d Merge remote-tracking branch 'refs/remotes/pr/513' into integration/all-open-prs-20260913 2026-09-13 18:58:23 -04:00
Michael A. Cojocari 6316901310 Merge remote-tracking branch 'refs/remotes/pr/509' into integration/all-open-prs-20260913 2026-09-13 18:58:23 -04:00
Michael A. Cojocari c7e7dbf894 Merge remote-tracking branch 'refs/remotes/pr/502' into integration/all-open-prs-20260913 2026-09-13 18:58:23 -04:00
Michael A. Cojocari ef374faf21 Merge remote-tracking branch 'refs/remotes/pr/501' into integration/all-open-prs-20260913 2026-09-13 18:58:23 -04:00
Michael A. Cojocari ea8583ead7 Merge remote-tracking branch 'refs/remotes/pr/498' into integration/all-open-prs-20260913 2026-09-13 18:58:22 -04:00
Michael A. Cojocari fdde0dd0cc Merge remote-tracking branch 'refs/remotes/pr/497' into integration/all-open-prs-20260913 2026-09-13 18:58:22 -04:00
Michael A. Cojocari 478a0030e3 Merge remote-tracking branch 'refs/remotes/pr/496' into integration/all-open-prs-20260913 2026-09-13 18:58:22 -04:00
Michael A. Cojocari b77b236d42 Merge remote-tracking branch 'refs/remotes/pr/495' into integration/all-open-prs-20260913 2026-09-13 18:58:22 -04:00
Michael A. Cojocari 8e5775dc34 Merge remote-tracking branch 'refs/remotes/pr/494' into integration/all-open-prs-20260913
# Conflicts:
#	src/ui-touch/UITask.cpp
2026-09-13 18:58:12 -04:00
Michael A. Cojocari 31394f8f1e Merge remote-tracking branch 'refs/remotes/pr/493' into integration/all-open-prs-20260913 2026-09-13 18:57:49 -04:00
Michael A. Cojocari f060bbee09 Merge remote-tracking branch 'refs/remotes/pr/492' into integration/all-open-prs-20260913
# Conflicts:
#	src/ui-touch/UITask.cpp
2026-09-13 18:57:44 -04:00
Michael A. Cojocari 7639363c78 Merge remote-tracking branch 'refs/remotes/pr/489' into integration/all-open-prs-20260913 2026-09-13 18:56:58 -04:00
Michael A. Cojocari 2dd4dc24d5 Merge remote-tracking branch 'refs/remotes/pr/488' into integration/all-open-prs-20260913 2026-09-13 18:56:58 -04:00
Michael A. Cojocari 85e5a28be2 Merge remote-tracking branch 'refs/remotes/pr/487' into integration/all-open-prs-20260913 2026-09-13 18:56:58 -04:00
Michael A. Cojocari 240d455f9c Merge remote-tracking branch 'refs/remotes/pr/486' into integration/all-open-prs-20260913 2026-09-13 18:56:57 -04:00
Michael A. Cojocari 07c09c7b33 Merge remote-tracking branch 'refs/remotes/pr/479' into integration/all-open-prs-20260913 2026-09-13 18:56:57 -04:00
Michael A. Cojocari e95f6ef9c7 Merge remote-tracking branch 'refs/remotes/pr/478' into integration/all-open-prs-20260913 2026-09-13 18:56:57 -04:00
Michael A. Cojocari d3cd12c257 Merge remote-tracking branch 'refs/remotes/pr/477' into integration/all-open-prs-20260913 2026-09-13 18:56:57 -04:00
Michael A. Cojocari e5eb3f9f2d Merge remote-tracking branch 'refs/remotes/pr/476' into integration/all-open-prs-20260913 2026-09-13 18:56:57 -04:00
Michael A. Cojocari a6fdbfcf36 Merge remote-tracking branch 'refs/remotes/pr/469' into integration/all-open-prs-20260913 2026-09-13 18:56:57 -04:00
Michael A. Cojocari db11fcf2c5 feat: add universal microSD diagnostics 2026-09-13 18:40:11 -04:00
Michael A. Cojocari 238d77e849 fix: invalidate map views on UI clear (#511) 2026-09-13 16:49:44 -04:00
Michael A. Cojocari 20477ee7b6 fix: focus new M9 channel composer 2026-09-12 20:16:58 -04:00
Michael A. Cojocari f632b5ea0e Allow 100-character quick replies 2026-09-11 09:20:01 -04:00
Michael A. Cojocari 1ac874cb84 Fix SD_MMC settings backups 2026-09-11 09:10:20 -04:00
Michael A. Cojocari 3f59a6f9d9 Fix battery estimate after clock changes 2026-09-10 20:21:42 -04:00
Michael A. Cojocari 2a481ef64c Add M9 lock-home-to-drawer option 2026-09-10 20:04:57 -04:00
aigarslv 141e7b0bdf Add Latvian (LV) keyboard layout
Same QWERTY deck as English (no letters removed, so loanwords/names still type normally) with the three most common extra letters - s-caron, c-caron, z-caron - promoted directly onto the on-screen deck, matching how Romanian's a-breve/s-cedilla/t-cedilla were added. The remaining eight - a-macron, e-macron, g-cedilla, i-macron, k-cedilla, l-cedilla, n-cedilla, u-macron - reach the physical T-Deck keyboard via the number row (same trick as Romanian's digit row) and the touch keyboard's existing accent popups on their base letter.

Also fixes kbLayoutCode()'s k_codes[] table, which was missing an "RO" entry (so the on-screen language-cycle button mislabeled Romanian as "EN"); LV is appended alongside the fix.

All 22 upper/lower Latvian glyphs sit in Latin Extended-A (U+0100-017F), already covered by the bundled extras_* fallback fonts, so no font changes are needed.
2026-09-10 22:42:10 +03:00
Michael A. Cojocari 1d24205341 Show M9 file timestamps directly 2026-09-10 10:47:57 -04:00
Michael A. Cojocari 294abcb99a Fix M9 admin log scrolling 2026-09-10 10:36:29 -04:00
Michael A. Cojocari bafe905773 Make M9 navigation shortcuts global 2026-09-10 10:30:49 -04:00
Michael A. Cojocari bd46b798eb Improve M9 chat navigation 2026-09-10 09:18:40 -04:00
Michael A. Cojocari 1e79ad044f Fix At-a-glance zero-hop count 2026-09-09 17:47:22 -04:00
Michael A. Cojocari cfb6cc7feb Fix M9 message info scrolling 2026-09-09 17:44:16 -04:00
Michael A. Cojocari 80b9f13da3 Fix M9 discovered contacts scrolling 2026-09-09 17:36:30 -04:00
Michael A. Cojocari 68dea386d3 Wio Tracker L2 login and keyboard tweaks 2026-09-09 17:17:33 -04:00
Michael A. Cojocari fdaa3d22b7 Tweaks and suggested changes. 2026-09-09 14:23:25 -04:00
Michael A. Cojocari 8062d7a077 M9: keep caret in composer through text end 2026-09-09 13:46:05 -04:00
Michael A. Cojocari 994c155149 Work 2026-09-09 11:58:51 -04:00
Michael A. Cojocari 1c36025932 M9: refine navigation cursor highlights (#434) 2026-09-09 11:29:22 -04:00
Michael A. Cojocari 229ef986e6 M9: limit purge confirmation focus (#432) 2026-09-09 10:44:08 -04:00
Michael A. Cojocari bc3229d27e M9: fix settings detail navigation (#427) 2026-09-09 10:37:26 -04:00
Kaj SchittecatandClaude Opus 5 b6440d01cd touch: charging icon on every board, not just two (#473)
Two Discord reports a day apart on different boards: museifu696 (M9, beta_78)
had no charging symbol at all, and thesupergeek (V4-R8) found charge state not
being detected after comparing against a T-Deck.

For the M9 this was structural. batteryIsCharging lived inside

  #if defined(HAS_TDECK_GT911) || defined(HELTEC_LORA_V4_R8)

whose #else returned a flat false, so on the M9 -- and the Pager, RAK Tap, Wio
L2, Attaky, P4 and Tanmatsu -- no voltage could ever produce a charging icon.

That split was a real, evidence-based decision, but it was about the Heltec V4
alone: its noisier ADC path made the EMA drag the average down so the threshold
never tripped (the note above the block explains it). The #else then answered
the question for every OTHER board too, purely by falling through, and nobody
had evaluated those.

So share only the verdict, not the sampler. The EMA stays gated exactly as
before, which means battery PERCENTAGE on the direct-read boards is untouched
and the V4's original complaint cannot recur: the direct read is what it keeps,
and its plugged-in reading already sat high.

Sharing is sound rather than assumed: the same mv feeds batteryPercentFromMv(),
so a board reporting the USB rail instead of the battery would already show a
permanent 100% and someone would have said so.

Kept deliberately PURE. batteryMvSmoothed()'s charge_flip calls this twice with
different arguments to compare the old and new verdicts, so a latching Schmitt
trigger would corrupt itself; flap is bounded by the 20 s publish hold and the
50 mV margin instead. The threshold against each board's uncalibrated ADC still
wants on-device confirmation, as the V4-R8 note already says.

Two follow-ons: kBattChargingMv (4250) is removed, dead and misleading since the
test actually uses batteryFullMv() + 50; and the idle-power-save comment that
reasoned from "the M9 is in batteryIsCharging's #else branch, so the USB-powered
gate can never block" is corrected, because it now can, which is the point of
that gate.

Reported-by: museifu696, thesupergeek
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 11:59:21 +02:00
Kaj SchittecatandClaude Opus 5 565fd883ae touch: a Lua app error must not reset the device (crash dump, T-Deck)
Kaj's T-Deck coredump: abort() on core 1, decoding to luaG_callerror ->
abort() reached from luaAppPress(). luaG_callerror is "attempt to call a ...
value", and the abort is Lua's DEFAULT panic function, because lua_atpanic was
never installed anywhere in this file. So any error reaching Lua with no
protected frame resets the device.

The callback itself was never the problem: guardedCall wraps it in pcall with a
traceback handler and turns a fault into a toast plus a clean close, which is
the host's whole contract. The hole is everything that runs BEFORE that pcall
is armed:

  - pushCallback() used lua_getfield, which honours __index. An app table
    carrying a metatable whose __index is not callable raises exactly
    luaG_callerror, unprotected. It is now a raw lookup, which is also the
    correct semantics: callbacks are plain fields on the table the chunk
    returned, and no shipped app uses setmetatable.
  - the argument marshalling in sendInput/sendKey pushes a table and several
    values before the pcall exists, and those raise on stack growth or OOM.
    lua_checkstack appeared ZERO times in this file; pushCallback now reserves
    the room up front, and checkstack reports failure rather than raising.

lua_atpanic is installed as well. It cannot prevent the abort -- Lua aborts once
a panic function returns and there is no safe frame to unwind to -- but the
error text now reaches the serial log and a toast instead of vanishing, which is
the difference between a reproducible report and a mystery reset.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 11:47:12 +02:00