Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e4f9a221e | ||
|
|
57f206220d | ||
|
|
756bb9f821 |
No files matched your search
@@ -42,40 +42,54 @@ if os.path.exists(nf):
|
||||
notes = "\n".join(l.strip() for l in open(nf, encoding="utf-8")
|
||||
if l.strip() and not l.strip().startswith("#"))
|
||||
|
||||
# Both touch boards are ESP32-S3, single touch-UI ("gui") role. ota_0 sits at
|
||||
# 0x10000 on both (partitions_t*_touch.csv), so flash-update@0x10000 is correct.
|
||||
# Every wadamesh tile here is ESP32-S3, touch-UI ("gui") role. ota_0 sits at
|
||||
# 0x10000 on every touch env (partitions_t*_touch.csv), so flash-update@0x10000 is correct.
|
||||
# `name` MUST match the official MeshCore device name character-for-character, or Mesh America lists it
|
||||
# as a NEW device instead of folding our firmware into the existing tile (TJ Downes, 2026-06). Canonical
|
||||
# names verified from apps.meshamerica.com/proxy/flasher/config.json. The V4 entry is the Expansion Kit
|
||||
# (Touch) variant only, per Kaj. `slug` still maps to our bin filenames on firmware.wadamesh.com.
|
||||
#
|
||||
# A board may carry `variants` instead of a single `slug`: one "gui" firmware entry is emitted per
|
||||
# variant, all under the one tile. The T-Lora Pager ships with either radio, and Mesh America folds both
|
||||
# under a single "LilyGo T-Lora Pager" tile distinguished by a [RADIO] title prefix — matching how their
|
||||
# own stock pager entries are labelled ([SX1262]/[LR1121]), so ours sit naturally alongside them.
|
||||
BOARDS = [
|
||||
{"name": "Heltec v4 + Expansion Kit (Touch)", "slug": "heltec-v4-tft"},
|
||||
{"name": "LilyGo T-Deck", "slug": "tdeck"},
|
||||
{"name": "LilyGo T-Lora Pager", "variants": [
|
||||
{"title": "[LR1121] Touch UI", "slug": "tlora-pager-lr1121"},
|
||||
{"title": "[SX1262] Touch UI", "slug": "tlora-pager-sx1262"},
|
||||
]},
|
||||
]
|
||||
|
||||
def _firmware(title, slug):
|
||||
merged, appbin = "wadamesh-%s-merged.bin" % slug, "wadamesh-%s.bin" % slug
|
||||
return {
|
||||
"role": "gui",
|
||||
"title": title,
|
||||
"version": {TAG: {
|
||||
"notes": notes,
|
||||
"files": [
|
||||
{"type": "flash-wipe", "name": merged,
|
||||
"url": "%s/%s" % (BASE, merged),
|
||||
"title": "Full install (bootloader + firmware)"},
|
||||
{"type": "flash-update", "name": appbin,
|
||||
"url": "%s/%s" % (BASE, appbin),
|
||||
"title": "Update (app only)"},
|
||||
],
|
||||
}},
|
||||
}
|
||||
|
||||
def device(b):
|
||||
merged, appbin = "wadamesh-%s-merged.bin" % b["slug"], "wadamesh-%s.bin" % b["slug"]
|
||||
# `variants` (per-radio builds) fold under one tile; a plain board is the single default variant.
|
||||
variants = b.get("variants") or [{"title": "Touch UI", "slug": b["slug"]}]
|
||||
return {
|
||||
"maker": "wadamesh",
|
||||
"class": "wadamesh",
|
||||
"name": b["name"],
|
||||
"type": "esp32",
|
||||
"tooltip": "<img class='device' src='%s'>" % ICON,
|
||||
"firmware": [{
|
||||
"role": "gui",
|
||||
"title": "Touch UI",
|
||||
"version": {TAG: {
|
||||
"notes": notes,
|
||||
"files": [
|
||||
{"type": "flash-wipe", "name": merged,
|
||||
"url": "%s/%s" % (BASE, merged),
|
||||
"title": "Full install (bootloader + firmware)"},
|
||||
{"type": "flash-update", "name": appbin,
|
||||
"url": "%s/%s" % (BASE, appbin),
|
||||
"title": "Update (app only)"},
|
||||
],
|
||||
}},
|
||||
}],
|
||||
"firmware": [_firmware(v["title"], v["slug"]) for v in variants],
|
||||
}
|
||||
|
||||
# Optional "what's this?" blurb Mesh America shows on a hover tooltip next to our provider badge
|
||||
|
||||
@@ -69,6 +69,61 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"maker": "wadamesh",
|
||||
"class": "wadamesh",
|
||||
"name": "LilyGo T-Lora Pager",
|
||||
"type": "esp32",
|
||||
"tooltip": "<img class='device' src='https://wadamesh.com/wadamesh-icon-512.png'>",
|
||||
"firmware": [
|
||||
{
|
||||
"role": "gui",
|
||||
"title": "[LR1121] Touch UI",
|
||||
"version": {
|
||||
"beta_46": {
|
||||
"notes": "Redesigned control center: round quick-toggle buttons that spread to fill the panel, a frosted-glass look, real lock/bell icons, and a confirmation popup on every toggle.\nDo Not Disturb: set quiet hours in Settings > Sound to silence the incoming-message chime during a daily window, with a bell in the status bar while it's active. (community contribution by Tesso Codemonkey)\nDo Not Disturb quick-toggle in the control center — a bell that gains a slash while quiet hours are on.\nContacts no longer go missing between reboots on microSD devices: saves are now atomic (written then swapped in) and the card is mounted far more reliably at boot.\nHeltec V4-R8: the microSD card now mounts, and the freeze when waking the device from sleep is fixed.\nLilyGo T-Pager: the map no longer shows a \"storage error\" under the launcher — it caches tiles to the microSD card, like the T-Deck.\nHeltec V4 in portrait: the Bluetooth icon no longer overlaps the clock in the status bar, and the control-center buttons no longer clip when tapped.",
|
||||
"files": [
|
||||
{
|
||||
"type": "flash-wipe",
|
||||
"name": "wadamesh-tlora-pager-lr1121-merged.bin",
|
||||
"url": "https://firmware.wadamesh.com/releases/TOUCH/beta_46/wadamesh-tlora-pager-lr1121-merged.bin",
|
||||
"title": "Full install (bootloader + firmware)"
|
||||
},
|
||||
{
|
||||
"type": "flash-update",
|
||||
"name": "wadamesh-tlora-pager-lr1121.bin",
|
||||
"url": "https://firmware.wadamesh.com/releases/TOUCH/beta_46/wadamesh-tlora-pager-lr1121.bin",
|
||||
"title": "Update (app only)"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "gui",
|
||||
"title": "[SX1262] Touch UI",
|
||||
"version": {
|
||||
"beta_46": {
|
||||
"notes": "Redesigned control center: round quick-toggle buttons that spread to fill the panel, a frosted-glass look, real lock/bell icons, and a confirmation popup on every toggle.\nDo Not Disturb: set quiet hours in Settings > Sound to silence the incoming-message chime during a daily window, with a bell in the status bar while it's active. (community contribution by Tesso Codemonkey)\nDo Not Disturb quick-toggle in the control center — a bell that gains a slash while quiet hours are on.\nContacts no longer go missing between reboots on microSD devices: saves are now atomic (written then swapped in) and the card is mounted far more reliably at boot.\nHeltec V4-R8: the microSD card now mounts, and the freeze when waking the device from sleep is fixed.\nLilyGo T-Pager: the map no longer shows a \"storage error\" under the launcher — it caches tiles to the microSD card, like the T-Deck.\nHeltec V4 in portrait: the Bluetooth icon no longer overlaps the clock in the status bar, and the control-center buttons no longer clip when tapped.",
|
||||
"files": [
|
||||
{
|
||||
"type": "flash-wipe",
|
||||
"name": "wadamesh-tlora-pager-sx1262-merged.bin",
|
||||
"url": "https://firmware.wadamesh.com/releases/TOUCH/beta_46/wadamesh-tlora-pager-sx1262-merged.bin",
|
||||
"title": "Full install (bootloader + firmware)"
|
||||
},
|
||||
{
|
||||
"type": "flash-update",
|
||||
"name": "wadamesh-tlora-pager-sx1262.bin",
|
||||
"url": "https://firmware.wadamesh.com/releases/TOUCH/beta_46/wadamesh-tlora-pager-sx1262.bin",
|
||||
"title": "Update (app only)"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+160
-49
@@ -177,6 +177,28 @@
|
||||
.dl2 .dlver{display:block;font-size:.72rem;color:var(--mut);font-weight:600;margin-top:2px;padding-left:20px;letter-spacing:.03em}
|
||||
.dl2 .dlver:empty{display:none}
|
||||
.hint{max-width:760px;margin:18px auto 0;color:var(--mut);font-size:.86rem;text-align:center}
|
||||
/* device selector — grouped by manufacturer, collapsible, searchable */
|
||||
.devsel{max-width:840px; margin:20px auto 0}
|
||||
.devsearch{position:relative; max-width:460px; margin:0 auto 18px}
|
||||
.devsearch>svg{position:absolute; left:15px; top:50%; transform:translateY(-50%); width:17px; height:17px; color:var(--mut); pointer-events:none}
|
||||
.devsearch input{width:100%; box-sizing:border-box; font:inherit; font-size:.95rem; padding:11px 42px; border:1px solid var(--line); border-radius:11px; background:#fff; color:var(--ink)}
|
||||
.devsearch input::-webkit-search-cancel-button{display:none}
|
||||
.devsearch input:focus{outline:none; border-color:var(--teal); box-shadow:0 0 0 3px rgba(21,182,166,.15)}
|
||||
.devsearch-x{position:absolute; right:8px; top:50%; transform:translateY(-50%); width:26px; height:26px; border:0; border-radius:50%; background:var(--bg2); color:var(--mut); font-size:1.15rem; line-height:1; cursor:pointer; display:flex; align-items:center; justify-content:center}
|
||||
.devsearch-x:hover{color:var(--ink); background:var(--line)}
|
||||
.devsearch-empty{text-align:center; color:var(--mut); font-size:.9rem; margin:12px 0 0}
|
||||
.devsearch-empty button{font:inherit; font-size:.9rem; color:var(--teal-ink); background:none; border:0; padding:0; cursor:pointer; text-decoration:underline}
|
||||
.mfr{border:1px solid var(--line); border-radius:14px; background:var(--bg2); margin:0 auto 12px; overflow:hidden}
|
||||
.mfr[hidden]{display:none}
|
||||
.mfr>summary{list-style:none; cursor:pointer; user-select:none; display:flex; align-items:center; gap:11px; padding:15px 18px; font-weight:700; font-size:1.05rem; color:var(--ink)}
|
||||
.mfr>summary::-webkit-details-marker{display:none}
|
||||
.mfr>summary:hover{color:var(--teal-ink)}
|
||||
.mfr-name{flex:1 1 auto}
|
||||
.mfr-count{font-weight:600; font-size:.78rem; color:var(--mut); letter-spacing:.02em}
|
||||
.mfr .chev{width:18px; height:18px; color:var(--mut); flex:none; transition:transform .18s}
|
||||
.mfr[open]>summary .chev{transform:rotate(180deg)}
|
||||
.mfr-boards{max-width:none; margin:0; padding:2px 16px 18px}
|
||||
.board[hidden]{display:none}
|
||||
/* "install a previous version" picker */
|
||||
.verpick{max-width:760px; margin:16px auto 0; border:1px solid var(--line); border-radius:12px; background:var(--bg2); text-align:left}
|
||||
.verpick summary{cursor:pointer; padding:12px 16px; font-weight:600; font-size:.92rem; color:var(--ink); list-style:none; user-select:none}
|
||||
@@ -367,55 +389,102 @@
|
||||
<div class="step"><div class="num">2</div><div><h4>Pick your board & install</h4><p>Hit <b>Install</b> below, choose the serial port, and let it flash. It does a clean full install.</p></div></div>
|
||||
<div class="step"><div class="num">3</div><div><h4>You're on the mesh</h4><p>The device reboots into WADAMESH. Set your name + region in the first-run wizard.</p></div></div>
|
||||
</div>
|
||||
<div class="boards">
|
||||
<div class="board"><h4>Heltec V4 + TFT</h4><p>ESP32-S3 with CHSC6x touch.</p>
|
||||
<span class="sup full" tabindex="0"><span class="dot"></span>Fully supported<span class="pop"><b>Fully supported</b>Everything wadamesh offers works here — this is one of the two primary development boards, tested on every release.</span></span>
|
||||
<esp-web-install-button id="inst-heltec" manifest="https://firmware.wadamesh.com/latest/manifest-heltec-v4-tft.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="heltec-v4-tft" download href="https://firmware.wadamesh.com/latest/wadamesh-heltec-v4-tft-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a></div>
|
||||
<div class="board"><h4>LilyGo T-Deck / Plus</h4><p>ESP32-S3 keyboard handheld.</p>
|
||||
<span class="sup full" tabindex="0"><span class="dot"></span>Fully supported<span class="pop"><b>Fully supported</b>Everything wadamesh offers works here — this is one of the two primary development boards, tested on every release.</span></span>
|
||||
<esp-web-install-button id="inst-tdeck" manifest="https://firmware.wadamesh.com/latest/manifest-tdeck.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tdeck" download href="https://firmware.wadamesh.com/latest/wadamesh-tdeck-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a></div>
|
||||
<div class="board"><h4>ThinkNode M9</h4><p>ESP32-S3 QWERTY handheld (LR1110).</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. Not every feature has been ported or hardware-verified on this board yet.</span></span>
|
||||
<esp-web-install-button id="inst-m9" manifest="https://firmware.wadamesh.com/latest-beta/manifest-thinknode-m9.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="thinknode-m9" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-thinknode-m9-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
<div class="board"><h4>RAK WisMesh Tap V2</h4><p>ESP32-S3 touch node.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. Not every feature has been ported or hardware-verified on this board yet.</span></span>
|
||||
<esp-web-install-button id="inst-rak" manifest="https://firmware.wadamesh.com/latest-beta/manifest-rak-tap-v2.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="rak-tap-v2" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-rak-tap-v2-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
<div class="board"><h4>Heltec V4-R8 <span style="font-weight:600;color:var(--mut)">(experimental)</span></h4><p>ESP32-S3 · 8 MB PSRAM · SD card.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. This revision is still being hardware-verified — flash with care and report back.</span></span>
|
||||
<esp-web-install-button id="inst-v4r8" manifest="https://firmware.wadamesh.com/latest-beta/manifest-heltec-v4-r8-tft.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="heltec-v4-r8-tft" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-heltec-v4-r8-tft-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board, not yet hardware-tested — beta only. Please flash with care and report back.</p></div>
|
||||
<div class="board"><h4>Attaky Core <span style="font-weight:600;color:var(--mut)">(experimental)</span></h4><p>ESP32-S3 · 16 MB · 8 MB PSRAM.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. This community-contributed board (PR #158) isn't hardware-verified by us yet — flash with care and report back.</span></span>
|
||||
<esp-web-install-button id="inst-attaky" manifest="https://firmware.wadamesh.com/latest-beta/manifest-attaky.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="attaky" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-attaky-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board, not yet hardware-tested — beta only. Please flash with care and report back.</p></div>
|
||||
<div class="board"><h4>Tanmatsu</h4><p>ESP32-P4 keyboard handheld.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link over Wi-Fi/USB. Some features are still settling on this board (Bluetooth pairing has known gaps).</span></span>
|
||||
<p style="color:var(--mut);font-size:.84rem;margin:0;line-height:1.5">Already have one? No USB flashing needed — install WADAMESH straight from the <b>Tanmatsu app store</b> on the device.</p>
|
||||
<a class="dl" href="https://shop.nicolaielectronics.nl/" target="_blank" rel="noopener"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>Get a Tanmatsu</a></div>
|
||||
<div class="board"><h4>LilyGo T-Display P4</h4><p>ESP32-P4 AMOLED touch handheld.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>Early port — it's known that not everything works yet, but the core does: LoRa mesh communication, chat, map, GPS and the phone-app link over Wi-Fi or USB. Bluetooth pairing isn't available on this board (a hardware limitation of its stock radio firmware).</span></span>
|
||||
<esp-web-install-button id="inst-tdp4" manifest="https://firmware.wadamesh.com/latest-beta/manifest-tdisplay-p4.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tdisplay-p4" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-tdisplay-p4-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
<div class="board"><h4>LilyGo T-LoRa Pager</h4><p>ESP32-S3 QWERTY + rotary encoder.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>New community port (thanks @codemonkeybr). The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link, driven entirely by the keyboard and rotary encoder. Pick the build that matches your radio chip.</span></span>
|
||||
<p style="color:var(--mut);font-size:.8rem;margin:0">Radio <b>LR1121</b>:</p>
|
||||
<esp-web-install-button id="inst-pager-lr1121" manifest="https://firmware.wadamesh.com/latest-beta/manifest-tlora-pager-lr1121.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tlora-pager-lr1121" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-tlora-pager-lr1121-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p style="color:var(--mut);font-size:.8rem;margin:8px 0 0">Radio <b>SX1262</b>:</p>
|
||||
<esp-web-install-button id="inst-pager-sx1262" manifest="https://firmware.wadamesh.com/latest-beta/manifest-tlora-pager-sx1262.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tlora-pager-sx1262" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-tlora-pager-sx1262-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
<div class="devsel" id="devsel">
|
||||
<div class="devsearch">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-3.6-3.6"/></svg>
|
||||
<input type="search" id="devSearch" autocomplete="off" placeholder="Search by device or maker — T-Deck, Heltec, P4…" aria-label="Search devices">
|
||||
<button type="button" id="devClearX" class="devsearch-x" data-devclear hidden aria-label="Clear search">×</button>
|
||||
</div>
|
||||
<p class="devsearch-empty" data-devempty hidden>No devices match “<span data-devq></span>”. <button type="button" data-devclear>Clear search</button></p>
|
||||
|
||||
<details class="mfr" open data-mfr="LilyGo">
|
||||
<summary><span class="mfr-name">LilyGo</span><span class="mfr-count"></span><svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></summary>
|
||||
<div class="boards mfr-boards">
|
||||
<div class="board" data-search="lilygo t-deck tdeck plus esp32-s3 keyboard handheld"><h4>LilyGo T-Deck / Plus</h4><p>ESP32-S3 keyboard handheld.</p>
|
||||
<span class="sup full" tabindex="0"><span class="dot"></span>Fully supported<span class="pop"><b>Fully supported</b>Everything wadamesh offers works here — this is one of the two primary development boards, tested on every release.</span></span>
|
||||
<esp-web-install-button id="inst-tdeck" manifest="https://firmware.wadamesh.com/latest/manifest-tdeck.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tdeck" download href="https://firmware.wadamesh.com/latest/wadamesh-tdeck-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a></div>
|
||||
<div class="board" data-search="lilygo t-display p4 tdisplay amoled rm69a10 esp32-p4 touch handheld"><h4>LilyGo T-Display P4 <span style="font-weight:600;color:var(--mut)">(AMOLED)</span></h4><p>ESP32-P4 · AMOLED touch handheld.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>Early port — it's known that not everything works yet, but the core does: LoRa mesh communication, chat, map, GPS and the phone-app link over Wi-Fi or USB. Bluetooth pairing isn't available on this board (a hardware limitation of its stock radio firmware).</span></span>
|
||||
<esp-web-install-button id="inst-tdp4" manifest="https://firmware.wadamesh.com/latest-beta/manifest-tdisplay-p4.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tdisplay-p4" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-tdisplay-p4-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
<div class="board" data-search="lilygo t-display p4 tdisplay lcd tft hi8561 esp32-p4 touch handheld"><h4>LilyGo T-Display P4 <span style="font-weight:600;color:var(--mut)">(LCD)</span></h4><p>ESP32-P4 · TFT-LCD touch handheld.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The LCD-screen model of the T-Display P4 (the AMOLED variant is listed above). Early port — the core works: LoRa mesh, chat, map, GPS and the phone-app link over Wi-Fi or USB. Bluetooth pairing isn't available on this board. Flash with care and report back.</span></span>
|
||||
<esp-web-install-button id="inst-tdp4-lcd"></esp-web-install-button>
|
||||
<a class="dl2" id="dl-tdp4-lcd" download><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" id="dl-tdp4-lcd-ver"></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New screen variant, not yet hardware-tested — beta only. Flash with care and report back.</p></div>
|
||||
<div class="board" data-search="lilygo t-lora pager tlora esp32-s3 qwerty rotary encoder lr1121 sx1262"><h4>LilyGo T-LoRa Pager</h4><p>ESP32-S3 QWERTY + rotary encoder.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>New community port (thanks @codemonkeybr). The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. Pick the build that matches your radio chip.</span></span>
|
||||
<p style="color:var(--mut);font-size:.8rem;margin:0">Radio <b>LR1121</b>:</p>
|
||||
<esp-web-install-button id="inst-pager-lr1121" manifest="https://firmware.wadamesh.com/latest-beta/manifest-tlora-pager-lr1121.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tlora-pager-lr1121" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-tlora-pager-lr1121-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p style="color:var(--mut);font-size:.8rem;margin:8px 0 0">Radio <b>SX1262</b>:</p>
|
||||
<esp-web-install-button id="inst-pager-sx1262" manifest="https://firmware.wadamesh.com/latest-beta/manifest-tlora-pager-sx1262.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="tlora-pager-sx1262" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-tlora-pager-sx1262-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mfr" open data-mfr="Heltec">
|
||||
<summary><span class="mfr-name">Heltec</span><span class="mfr-count"></span><svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></summary>
|
||||
<div class="boards mfr-boards">
|
||||
<div class="board" data-search="heltec v4 tft esp32-s3 chsc6x touch"><h4>Heltec V4 + TFT</h4><p>ESP32-S3 with CHSC6x touch.</p>
|
||||
<span class="sup full" tabindex="0"><span class="dot"></span>Fully supported<span class="pop"><b>Fully supported</b>Everything wadamesh offers works here — this is one of the two primary development boards, tested on every release.</span></span>
|
||||
<esp-web-install-button id="inst-heltec" manifest="https://firmware.wadamesh.com/latest/manifest-heltec-v4-tft.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="heltec-v4-tft" download href="https://firmware.wadamesh.com/latest/wadamesh-heltec-v4-tft-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a></div>
|
||||
<div class="board" data-search="heltec v4-r8 v4 r8 esp32-s3 psram sd card experimental"><h4>Heltec V4-R8 <span style="font-weight:600;color:var(--mut)">(experimental)</span></h4><p>ESP32-S3 · 8 MB PSRAM · SD card.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. This revision is still being hardware-verified — flash with care and report back.</span></span>
|
||||
<esp-web-install-button id="inst-v4r8" manifest="https://firmware.wadamesh.com/latest-beta/manifest-heltec-v4-r8-tft.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="heltec-v4-r8-tft" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-heltec-v4-r8-tft-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board, not yet hardware-tested — beta only. Please flash with care and report back.</p></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mfr" data-mfr="Elecrow">
|
||||
<summary><span class="mfr-name">Elecrow</span><span class="mfr-count"></span><svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></summary>
|
||||
<div class="boards mfr-boards">
|
||||
<div class="board" data-search="elecrow thinknode m9 esp32-s3 qwerty lr1110 handheld"><h4>ThinkNode M9</h4><p>ESP32-S3 QWERTY handheld (LR1110).</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. Not every feature has been ported or hardware-verified on this board yet.</span></span>
|
||||
<esp-web-install-button id="inst-m9" manifest="https://firmware.wadamesh.com/latest-beta/manifest-thinknode-m9.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="thinknode-m9" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-thinknode-m9-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mfr" data-mfr="RAKwireless">
|
||||
<summary><span class="mfr-name">RAKwireless</span><span class="mfr-count"></span><svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></summary>
|
||||
<div class="boards mfr-boards">
|
||||
<div class="board" data-search="rakwireless rak wismesh tap v2 esp32-s3 touch node"><h4>RAK WisMesh Tap V2</h4><p>ESP32-S3 touch node.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. Not every feature has been ported or hardware-verified on this board yet.</span></span>
|
||||
<esp-web-install-button id="inst-rak" manifest="https://firmware.wadamesh.com/latest-beta/manifest-rak-tap-v2.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="rak-tap-v2" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-rak-tap-v2-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board: beta channel only until the next stable.</p></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mfr" data-mfr="Nicolai Electronics">
|
||||
<summary><span class="mfr-name">Nicolai Electronics</span><span class="mfr-count"></span><svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></summary>
|
||||
<div class="boards mfr-boards">
|
||||
<div class="board" data-search="nicolai electronics tanmatsu esp32-p4 keyboard handheld app store"><h4>Tanmatsu</h4><p>ESP32-P4 keyboard handheld.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link over Wi-Fi/USB. Some features are still settling on this board (Bluetooth pairing has known gaps).</span></span>
|
||||
<p style="color:var(--mut);font-size:.84rem;margin:0;line-height:1.5">Already have one? No USB flashing needed — install WADAMESH straight from the <b>Tanmatsu app store</b> on the device.</p>
|
||||
<a class="dl" href="https://shop.nicolaielectronics.nl/" target="_blank" rel="noopener"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>Get a Tanmatsu</a></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="mfr" data-mfr="Attaky">
|
||||
<summary><span class="mfr-name">Attaky</span><span class="mfr-count"></span><svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></summary>
|
||||
<div class="boards mfr-boards">
|
||||
<div class="board" data-search="attaky core esp32-s3 psram experimental"><h4>Attaky Core <span style="font-weight:600;color:var(--mut)">(experimental)</span></h4><p>ESP32-S3 · 16 MB · 8 MB PSRAM.</p>
|
||||
<span class="sup part" tabindex="0"><span class="dot"></span>Partially supported<span class="pop"><b>Partially supported</b>The core works: LoRa mesh communication, chat, contacts, channels and the phone-app link. This community-contributed board (PR #158) isn't hardware-verified by us yet — flash with care and report back.</span></span>
|
||||
<esp-web-install-button id="inst-attaky" manifest="https://firmware.wadamesh.com/latest-beta/manifest-attaky.json"></esp-web-install-button>
|
||||
<a class="dl2" data-dl-board="attaky" data-dl-betaonly download href="https://firmware.wadamesh.com/latest-beta/wadamesh-attaky-merged.bin"><span class="dl2-row"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v12M7 11l5 5 5-5M5 21h14"/></svg>Download .bin</span><span class="dlver" data-dl-ver></span></a>
|
||||
<p data-wm-betaonly style="color:var(--mut);font-size:.78rem;margin:6px 0 0">New board, not yet hardware-tested — beta only. Please flash with care and report back.</p></div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<details class="verpick">
|
||||
<details class="verpick">
|
||||
<summary>Install a previous version</summary>
|
||||
<div class="verpick-body">
|
||||
<div class="verpick-row"><label for="verSel">Version</label><select id="verSel" aria-label="Firmware version"></select></div>
|
||||
@@ -619,6 +688,19 @@ We use no tracking, analytics, or advertising cookies. Our CDN and security prov
|
||||
// toggle (beta-only boards stay pinned to latest-beta) and show the exact version
|
||||
// each feed serves — both channel tags are fetched once so every link is accurate.
|
||||
const WM_VER = {};
|
||||
// The T-Display P4 LCD-screen variant ships only in the per-tag BETA archive (no
|
||||
// rolling-feed bin, no server manifest), so wire its Install button to a manifest
|
||||
// built client-side (same blob trick as the previous-version picker) and point its
|
||||
// download at the immutable archive bin. Called once the beta tag is known.
|
||||
window.wmWireP4Lcd = function(tag){
|
||||
const bin = 'https://firmware.wadamesh.com/releases/BETA/' + tag + '/wadamesh-tdisplay-p4-lcd-merged.bin';
|
||||
const btn = document.getElementById('inst-tdp4-lcd');
|
||||
if (btn){ const m = { name:'wadamesh ' + tag + ' \u2014 T-Display P4 (LCD)', version:tag, new_install_prompt_erase:true,
|
||||
builds:[{ chipFamily:'ESP32-P4', parts:[{ path:bin, offset:0 }] }] };
|
||||
btn.setAttribute('manifest', URL.createObjectURL(new Blob([JSON.stringify(m)], {type:'application/json'}))); }
|
||||
const dl = document.getElementById('dl-tdp4-lcd');
|
||||
if (dl){ dl.href = bin; const v = document.getElementById('dl-tdp4-lcd-ver'); if (v) v.textContent = tag; }
|
||||
};
|
||||
window.wmUpdateDownloads = function(){
|
||||
document.querySelectorAll('[data-dl-board]').forEach(a => {
|
||||
const feed = a.hasAttribute('data-dl-betaonly') ? 'latest-beta' : WM.feed;
|
||||
@@ -627,10 +709,39 @@ We use no tracking, analytics, or advertising cookies. Our CDN and security prov
|
||||
});
|
||||
};
|
||||
['latest','latest-beta'].forEach(feed => fetch('https://firmware.wadamesh.com/' + feed + '/version.json', {cache:'no-store'})
|
||||
.then(r => r.ok ? r.json() : null).then(v => { if (v && v.tag) { WM_VER[feed] = v.tag; wmUpdateDownloads(); } }).catch(()=>{}));
|
||||
.then(r => r.ok ? r.json() : null).then(v => { if (v && v.tag) { WM_VER[feed] = v.tag; wmUpdateDownloads(); if (feed === 'latest-beta' && window.wmWireP4Lcd) wmWireP4Lcd(v.tag); } }).catch(()=>{}));
|
||||
document.querySelectorAll('[data-wm-ch]').forEach(b => b.addEventListener('click', () => wmSetChannel(b.getAttribute('data-wm-ch'))));
|
||||
wmSetChannel('stable');
|
||||
|
||||
// ---- device selector: fill counts, remember default open state, live search ----
|
||||
(function(){
|
||||
const root = document.getElementById('devsel'); if (!root) return;
|
||||
const input = document.getElementById('devSearch');
|
||||
const clearX = document.getElementById('devClearX');
|
||||
const empty = root.querySelector('[data-devempty]'), qout = root.querySelector('[data-devq]');
|
||||
const groups = Array.from(root.querySelectorAll('.mfr'));
|
||||
groups.forEach(g => { g.dataset.defopen = g.open ? '1' : '0';
|
||||
const n = g.querySelectorAll('.board').length, c = g.querySelector('.mfr-count');
|
||||
if (c) c.textContent = n + (n === 1 ? ' device' : ' devices'); });
|
||||
const txt = b => (b.getAttribute('data-search') || b.textContent || '').toLowerCase();
|
||||
function run(q){
|
||||
const terms = q.toLowerCase().split(/\s+/).filter(Boolean);
|
||||
let anyVisible = false;
|
||||
groups.forEach(g => { let vis = 0;
|
||||
g.querySelectorAll('.board').forEach(b => { const ok = !terms.length || terms.every(t => txt(b).includes(t));
|
||||
b.hidden = !ok; if (ok) vis++; });
|
||||
g.hidden = vis === 0;
|
||||
if (!g.hidden){ anyVisible = true; g.open = terms.length ? true : (g.dataset.defopen === '1'); } });
|
||||
if (empty) empty.hidden = !(terms.length && !anyVisible);
|
||||
if (qout) qout.textContent = q;
|
||||
if (clearX) clearX.hidden = !q;
|
||||
}
|
||||
function clr(){ if (input){ input.value = ''; input.focus(); } run(''); }
|
||||
if (input){ input.addEventListener('input', () => run(input.value));
|
||||
input.addEventListener('keydown', e => { if (e.key === 'Escape') clr(); }); }
|
||||
root.querySelectorAll('[data-devclear]').forEach(b => b.addEventListener('click', clr));
|
||||
})();
|
||||
|
||||
// ---- community videos — add an entry here to add a video ----
|
||||
const VIDEOS = [
|
||||
// newest first
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# beta_48 - stability and fixes: crash, boot-stuck, MQTT, message times, keyboard and more
|
||||
# One user-facing note per non-blank, non-# line; # lines are section comments.
|
||||
|
||||
# Fixed
|
||||
Fixed a crash that could reboot the device while you were typing in a chat.
|
||||
Fixed devices getting stuck on the boot screen after an update when a microSD card is fitted. The boot-time copy of your data to the card could hang on a slow or damaged card; it is now guarded and the device always boots.
|
||||
MQTT bridge settings now save and survive a reboot. They were being written to the wrong storage and getting lost.
|
||||
Message times now match the clock at the top of the screen, instead of showing 1910 or other wrong dates.
|
||||
Dutch keyboard: the "1" and "!" keys were typing "ij" and "IJ". Fixed.
|
||||
The message box now stops you at the real send limit instead of quietly dropping the end of a long message when you send.
|
||||
Copy and paste no longer cuts off long text.
|
||||
The quick messages list now scrolls when there are more entries than fit on screen.
|
||||
Room server names that start with an unusual character no longer show an empty box on the Join screen.
|
||||
Tanmatsu: you can now reach every emoji in the picker, not just the first half.
|
||||
@@ -6,7 +6,9 @@
|
||||
MqttBridge mqtt_bridge;
|
||||
|
||||
#if !defined(HAS_TANMATSU) && !defined(HAS_TDISPLAY_P4) // ---- real PubSubClient/WiFiClient implementation; NOT built on the P4 boards ----
|
||||
#include <Preferences.h>
|
||||
#include "SdNvsPrefs.h" // NOT raw NVS Preferences: the touch firmware abandoned NVS (tiny, shared,
|
||||
// doesn't survive Launcher) for a file-backed store. MQTT was the last setting
|
||||
// still on NVS, so its writes silently failed / didn't persist (GH #128).
|
||||
#include <WiFi.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -42,7 +44,7 @@ void MqttBridge::loadConfig() {
|
||||
_host[0] = _user[0] = _pwd[0] = _psk[0] = '\0';
|
||||
_port = 1883;
|
||||
|
||||
Preferences p;
|
||||
SdNvsPrefs p;
|
||||
if (p.begin("mqtt", true)) {
|
||||
_enabled = p.getBool("en", false);
|
||||
_port = (uint16_t)p.getUInt("port", 1883);
|
||||
@@ -223,7 +225,7 @@ void MqttBridge::publishChannel(int channelIdx, const char* channelName,
|
||||
void MqttBridge::saveConfig(const char* host, uint16_t port,
|
||||
const char* user, const char* pwd,
|
||||
bool pubDm, bool pubChannel, const char* psk, bool enable) {
|
||||
Preferences p;
|
||||
SdNvsPrefs p;
|
||||
if (!p.begin("mqtt", false)) return;
|
||||
p.putBool("en", enable);
|
||||
p.putString("host", host);
|
||||
|
||||
+37
-2
@@ -234,15 +234,24 @@ bool meshcomodMigrateSpiffsToSd(bool force) {
|
||||
File s = SPIFFS.open(src, FILE_READ);
|
||||
File d = s ? SD.open(dst, FILE_WRITE) : File(); // FILE_WRITE truncates
|
||||
bool ok = s && d;
|
||||
size_t since_feed = 0;
|
||||
while (ok && s.available()) {
|
||||
const size_t n = s.read(buf, sizeof buf);
|
||||
if (n == 0 || d.write(buf, n) != n) ok = false;
|
||||
// Feed the task-WDT mid-file: a large history file on a slow/cold SD card can take
|
||||
// longer than the 20 s task-WDT to copy in 4 KB chunks, and this runs on loopTask
|
||||
// during setup() — without the feed the dog panics and reboot-loops the boot (GH
|
||||
// #142/#148). The copy still can't tolerate a genuinely wedged FAT layer; the
|
||||
// NVS breadcrumb at the call site handles that.
|
||||
since_feed += n;
|
||||
if (since_feed >= 32768) { esp_task_wdt_reset(); since_feed = 0; }
|
||||
}
|
||||
if (s) s.close();
|
||||
if (d) d.close();
|
||||
if (ok) { ++copied; if (strcmp(src, "/identity/_main.id") == 0) identity_ok = true; }
|
||||
else { ++failed; Serial.printf("[BOOT] SD migrate FAILED: %s\n", src); if (SD.exists(dst)) SD.remove(dst); }
|
||||
f.close();
|
||||
esp_task_wdt_reset();
|
||||
yield();
|
||||
}
|
||||
root.close();
|
||||
@@ -253,6 +262,14 @@ bool meshcomodMigrateSpiffsToSd(bool force) {
|
||||
copied, failed, identity_ok ? "ok" : "MISSING");
|
||||
return identity_ok;
|
||||
}
|
||||
|
||||
// Clear the boot safe-mode latch (see the SPIFFS->SD migration above): called after a
|
||||
// successful manual "Copy internal data to SD" so a deliberate retry re-arms boot-time
|
||||
// auto-adoption. The boot path re-latches on its own if a later migration wedges. GH #142/#148.
|
||||
void meshcomodClearSdMigLatch() {
|
||||
Preferences _mp;
|
||||
if (_mp.begin("touch", false)) { _mp.remove("sd_mig_busy"); _mp.end(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
@@ -518,8 +535,26 @@ void setup() {
|
||||
// rather than adopting a card without the identity on it.
|
||||
bool adopt = true;
|
||||
if (SPIFFS.exists("/identity/_main.id") && !SD.exists("/meshcomod/identity/_main.id")) {
|
||||
adopt = meshcomodMigrateSpiffsToSd(false);
|
||||
if (!adopt) Serial.println("[BOOT] SD migration incomplete -> staying on SPIFFS this boot");
|
||||
// Boot safe-mode (GH #142/#148): a wedged or corrupt SD card can hang / WDT-reboot the
|
||||
// device mid-migration, stranding it on the boot screen EVERY boot (reset can't escape,
|
||||
// only a downgrade could). Drop an NVS breadcrumb before migrating and clear it only if
|
||||
// the copy RETURNS. If it's still set at the next boot, the last migration never finished
|
||||
// -> skip it and boot from SPIFFS (the data is safe there); Settings > "Copy internal data
|
||||
// to SD" re-arms a deliberate retry. A merely-slow (healthy) card completes thanks to the
|
||||
// in-loop WDT feed, so it never latches here.
|
||||
Preferences _mp;
|
||||
const bool mp_ok = _mp.begin("touch", false);
|
||||
const bool mig_busy = mp_ok && _mp.getBool("sd_mig_busy", false);
|
||||
if (mig_busy) {
|
||||
if (mp_ok) _mp.end();
|
||||
adopt = false;
|
||||
Serial.println("[BOOT] prior SD migration did not complete -> skipping (staying on SPIFFS); retry via Settings > Copy internal data to SD");
|
||||
} else {
|
||||
if (mp_ok) { _mp.putBool("sd_mig_busy", true); _mp.end(); }
|
||||
adopt = meshcomodMigrateSpiffsToSd(false);
|
||||
Preferences _mp2; if (_mp2.begin("touch", false)) { _mp2.remove("sd_mig_busy"); _mp2.end(); }
|
||||
if (!adopt) Serial.println("[BOOT] SD migration incomplete -> staying on SPIFFS this boot");
|
||||
}
|
||||
}
|
||||
if (adopt) {
|
||||
sd_storage = store.useSdStorage();
|
||||
|
||||
@@ -626,8 +626,9 @@ static const char* hw_de_upper[26] = {
|
||||
static const char* hw_de_digits[10] = { nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr };
|
||||
static const char* hw_de_digits_shift[10] = { nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr };
|
||||
|
||||
/* Dutch keeps the standard alpha matrix but exposes the common IJ digraph on a
|
||||
* digit slot so compact hardware still gets a language-specific shortcut. */
|
||||
/* Dutch keeps the standard alpha matrix. (The IJ digraph used to sit on a hardware
|
||||
* digit slot, but slot 1 is the "1" key AND the back-mapped "!" key, so it broke both
|
||||
* — GH #144/#164 — and the digraph now lives only on the on-screen keyboard's key.) */
|
||||
static const char* hw_nl_lower[26] = {
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
|
||||
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
|
||||
@@ -638,8 +639,8 @@ static const char* hw_nl_upper[26] = {
|
||||
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
|
||||
"U", "V", "W", "X", "Y", "Z"
|
||||
};
|
||||
static const char* hw_nl_digits[10] = { nullptr, "ij", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
static const char* hw_nl_digits_shift[10] = { nullptr, "IJ", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
static const char* hw_nl_digits[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
static const char* hw_nl_digits_shift[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
|
||||
/* Spanish stays close to US QWERTY; use the number row to expose n-tilde on
|
||||
* compact hardware where the semicolon key is absent. */
|
||||
|
||||
+49
-14
@@ -2871,7 +2871,10 @@ static int s_nav_count = 0; // # focusable widgets collected
|
||||
// Collected focusable widgets this rebuild, in tree order — used for 2D spatial
|
||||
// navigation (W/A/Z/D move to the nearest element in that physical direction, not
|
||||
// just the next/prev in the linear list).
|
||||
static const int kNavMax = 64;
|
||||
static const int kNavMax = 160; // spatial-nav mirror capacity — MUST exceed the largest focusable
|
||||
// grid or its tail is keypad-unreachable on the Tanmatsu: focusables
|
||||
// past this cap land in the LVGL group but not s_nav_objs[], so
|
||||
// navMoveDir() never reaches them (the 122-cell emoji picker — GH #141).
|
||||
static lv_obj_t* s_nav_objs[kNavMax] = { nullptr };
|
||||
static lv_obj_t* s_nav_tabbar = nullptr; // the bottom tab bar (btnmatrix), added last to the group
|
||||
static bool s_nav_want_tabbar = false; // after switching tabs from the bar, refocus the bar
|
||||
@@ -7194,7 +7197,12 @@ static void openQuickReplyPicker(LvChatPanel* p) {
|
||||
lv_obj_set_style_border_color(card, lv_color_hex(0x18191A), LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(card, 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_all(card, pad, LV_PART_MAIN);
|
||||
lv_obj_clear_flag(card, LV_OBJ_FLAG_SCROLLABLE);
|
||||
// The card is clamped to the visible height above, but its rows are absolutely
|
||||
// positioned and can extend past that clamp (small screens + Large/Huge UI scale) —
|
||||
// enable vertical scrolling so the lower quick-replies + hint stay reachable (GH #151).
|
||||
lv_obj_add_flag(card, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_scroll_dir(card, LV_DIR_VER);
|
||||
lv_obj_set_scrollbar_mode(card, LV_SCROLLBAR_MODE_AUTO);
|
||||
addCloseXBadge(card, qrSheetCloseCb);
|
||||
|
||||
lv_obj_t* title = lv_label_create(card);
|
||||
@@ -7607,7 +7615,9 @@ static void tdeckModalAutoFocusAsync(void* root) {
|
||||
// Mirrors MCterm's in-RAM clipboard. Anything the user long-presses to copy
|
||||
// lands here; long-press on a textarea pastes the contents at the cursor.
|
||||
// One global buffer keeps the code simple and avoids heap churn.
|
||||
constexpr size_t CLIPBOARD_MAX = 192;
|
||||
constexpr size_t CLIPBOARD_MAX = 640; // must cover the largest copyable text — a full composer draft
|
||||
// plus the 600-byte label-staging buffer (clipboardSet's callers);
|
||||
// 192 silently truncated long copy/pastes (GH #120).
|
||||
static char s_clipboard[CLIPBOARD_MAX] = {0};
|
||||
|
||||
static void clipboardSet(const char* text, const char* tag) {
|
||||
@@ -10184,6 +10194,7 @@ static void useSdStorageToggleCb(lv_event_t* e) {
|
||||
// empty card (which then minted a fresh identity). Overwrites the card's copies
|
||||
// with EVERYTHING from internal flash, forces the SD pref on, reboots.
|
||||
extern bool meshcomodMigrateSpiffsToSd(bool force); // main.cpp
|
||||
extern void meshcomodClearSdMigLatch(); // main.cpp (GH #142/#148 boot safe-mode)
|
||||
static void sdRestoreApply() {
|
||||
if (!g_lv.task) return;
|
||||
if (!fmSdTryMount()) { g_lv.task->showAlert(TR("No SD card"), 1600); return; }
|
||||
@@ -10193,6 +10204,7 @@ static void sdRestoreApply() {
|
||||
const bool ok = meshcomodMigrateSpiffsToSd(true);
|
||||
enableLoopWDT();
|
||||
if (!ok) { g_lv.task->showAlert(TR("Copy failed (no internal identity)"), 2200); return; }
|
||||
meshcomodClearSdMigLatch(); // manual copy succeeded -> re-arm boot auto-adoption (GH #142/#148)
|
||||
touchPrefsSetUseSdStorage(true); // make sure the reboot adopts the card
|
||||
delay(400); // let the alert render before the restart
|
||||
board.reboot();
|
||||
@@ -13140,7 +13152,7 @@ static void mqttSaveCb(lv_event_t* e) {
|
||||
bool pub_ch = !g_set_modal.mqtt_ch_sw || lv_obj_has_state(g_set_modal.mqtt_ch_sw, LV_STATE_CHECKED);
|
||||
bool pub_dm = g_set_modal.mqtt_dm_sw && lv_obj_has_state(g_set_modal.mqtt_dm_sw, LV_STATE_CHECKED);
|
||||
MqttBridge::saveConfig(host, port, user, pwd, pub_dm, pub_ch, psk, en);
|
||||
{ Preferences p; if (p.begin("mqtt", false)) { p.putBool("consent", consent); p.end(); } }
|
||||
{ SdNvsPrefs p; if (p.begin("mqtt", false)) { p.putBool("consent", consent); p.end(); } } // file-backed, not NVS (GH #128)
|
||||
mqtt_bridge.reloadConfig();
|
||||
closeSettingsModal();
|
||||
}
|
||||
@@ -13293,7 +13305,7 @@ static void buildMqttSettings() {
|
||||
|
||||
// ---- Load current config ----
|
||||
{
|
||||
Preferences p;
|
||||
SdNvsPrefs p; // file-backed, matches MqttBridge (GH #128)
|
||||
bool cur_en = false, cur_dm = false, cur_ch = true, cur_consent = false;
|
||||
char cur_host[64] = {}, cur_port_s[8] = "1883", cur_user[32] = {}, cur_pwd[32] = {}, cur_psk[33] = {};
|
||||
if (p.begin("mqtt", true)) {
|
||||
@@ -14298,8 +14310,13 @@ static void openAdminLoginPrompt(const ContactInfo& c) {
|
||||
});
|
||||
|
||||
const bool is_room = (c.type == ADV_TYPE_ROOM);
|
||||
// Sanitize like every other name-display path: copyUtf8ReplacingMissingGlyphs swaps an
|
||||
// unrenderable codepoint for '*'. This Join title skipped it and drew tofu (▯) for a name's
|
||||
// leading unsupported codepoint, while the contacts list/details showed '*' (GH #116).
|
||||
char safe_name[24];
|
||||
copyUtf8ReplacingMissingGlyphs(&g_font_14, safe_name, sizeof(safe_name), c.name);
|
||||
char hdr_buf[40];
|
||||
snprintf(hdr_buf, sizeof(hdr_buf), "%s %.20s", is_room ? "Join:" : "Login:", c.name);
|
||||
snprintf(hdr_buf, sizeof(hdr_buf), "%s %.20s", is_room ? "Join:" : "Login:", safe_name);
|
||||
lv_obj_t* title = lv_label_create(card);
|
||||
lv_label_set_text(title, hdr_buf);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(COLOR_TEXT), LV_PART_MAIN);
|
||||
@@ -27422,6 +27439,11 @@ static void makeChatDetail(LvChatPanel& p) {
|
||||
// — the physical-keyboard CR and the on-screen OK are handled before any
|
||||
// newline can be inserted, so the composer never actually holds a '\n'.
|
||||
lv_textarea_set_one_line(p.composer_ta, false);
|
||||
// Cap input at the LoRa text limit so the user can't type more than can be sent (GH #119).
|
||||
// (LVGL caps by codepoint; for ASCII that's exactly MAX_MSG_TEXT bytes. The send buffer,
|
||||
// _compose_buf, is sized MAX_MSG_TEXT+1 to match — it used to be 128, silently chopping
|
||||
// messages at 127 bytes, shorter than this limit.)
|
||||
lv_textarea_set_max_length(p.composer_ta, UITask::MAX_MSG_TEXT);
|
||||
lv_obj_set_scrollbar_mode(p.composer_ta, LV_SCROLLBAR_MODE_OFF);
|
||||
lv_textarea_set_placeholder_text(p.composer_ta, TR("Type a message..."));
|
||||
lv_obj_set_style_text_color(p.composer_ta, lv_color_hex(COLOR_TEXT), LV_PART_MAIN);
|
||||
@@ -33851,6 +33873,15 @@ if (g_lv.task && g_lv.task->isManualLock()) {
|
||||
// The on-screen keyboard is never shown on the T-Deck, but a textarea is still
|
||||
// bound to it on focus — that binding is our target.
|
||||
lv_obj_t* ta_focused = lv_keyboard_get_textarea(g_lv.keyboard);
|
||||
// Guard a STALE binding (crash #98, decoded coredump: NULL spec_attr in lv_event_send).
|
||||
// lv_keyboard_get_textarea() returns the last-bound composer; if that textarea was deleted
|
||||
// without the keyboard being re-pointed (a chat-panel teardown that bypassed hideKb()), it's
|
||||
// a dangling pointer and typing into it dereferences freed memory. Validate + self-heal the
|
||||
// binding before anything below can insert into it.
|
||||
if (ta_focused && !lv_obj_is_valid(ta_focused)) {
|
||||
if (g_lv.keyboard) lv_keyboard_set_textarea(g_lv.keyboard, nullptr);
|
||||
ta_focused = nullptr;
|
||||
}
|
||||
#if CAP_KEYPAD_NAV && !defined(TLORA_PAGER)
|
||||
// Edit mode (keyboard-nav ON only): a focused field becomes the typing target after
|
||||
// select/Enter (below) — until then `ta` is null so the nav keys navigate. With
|
||||
@@ -41369,14 +41400,15 @@ int UITask::appendMessage(const char* thread, const char* sender, const char* te
|
||||
int t_idx = findOrCreateThread(thread, channel);
|
||||
if (t_idx < 0) return -1;
|
||||
UIMessage& m = _ui_msgs[_ui_msg_head];
|
||||
// Prefer wall-clock (RTC) over uptime — bubble timestamps want HH:MM, and
|
||||
// last_ts/sort comparisons still work since RTC epoch (~1.7e9) outranks
|
||||
// any plausible uptime-seconds value. If RTC is unset, fall back to
|
||||
// uptime; the Info popup shows "—" when the value isn't an epoch.
|
||||
// Bubble timestamps must match the status-bar clock, which reads the NTP-synced ESP32
|
||||
// system clock (time(nullptr)) — NOT the mesh RTC (getRTCClock()). On boards whose
|
||||
// hardware RTC chip reads BCD/century garbage, getCurrentTime() returned wrong epochs
|
||||
// that rendered as 1910-09-03 / 1994 (GH #100/#152). Use the system clock; the ~1.7e9
|
||||
// epoch still outranks any uptime-seconds value for last_ts/sort, and we fall back to
|
||||
// uptime when the clock is unset (the Info popup shows "—" for non-epoch values).
|
||||
{
|
||||
auto* rtc = the_mesh.getRTCClock();
|
||||
uint32_t now_epoch = rtc ? rtc->getCurrentTime() : 0;
|
||||
m.ts = (now_epoch > 1700000000) ? now_epoch : (uint32_t)(millis() / 1000);
|
||||
time_t sys = time(nullptr);
|
||||
m.ts = (sys > 1700000000) ? (uint32_t)sys : (uint32_t)(millis() / 1000);
|
||||
}
|
||||
m.channel = channel;
|
||||
m.outgoing = outgoing;
|
||||
@@ -43544,7 +43576,10 @@ void UITask::newMsgImpl(uint8_t path_len, const char* from_name, const char* tex
|
||||
// (embedded ts ≈ now) are unaffected. Consume-once so it never leaks to the next.
|
||||
{
|
||||
uint32_t emb_ts = the_mesh.uiConsumeLastSenderTs();
|
||||
if (emb_ts > 1700000000) _ui_msgs[msg_slot].ts = emb_ts;
|
||||
// Sanity WINDOW, not just a lower bound: a peer with a garbage-future clock sends e.g.
|
||||
// ~2.42e9, which as a signed 32-bit time_t wraps to 1910-09-03 06:42:07 (GH #100/#152).
|
||||
// Same window as MyMesh.cpp's advert-time guard (>1.7e9 && <2.0e9).
|
||||
if (emb_ts > 1700000000 && emb_ts < 2000000000) _ui_msgs[msg_slot].ts = emb_ts;
|
||||
}
|
||||
syncThreadMeshSlots(thread, channel);
|
||||
#if defined(HAS_TDECK_GT911)
|
||||
|
||||
@@ -167,7 +167,7 @@ private:
|
||||
bool _composer_mode;
|
||||
int _composer_char_idx;
|
||||
int _composer_action_idx;
|
||||
char _compose_buf[128];
|
||||
char _compose_buf[MAX_MSG_TEXT + 1]; // full LoRa text length; was 128 -> silently chopped sends at 127 bytes (GH #119)
|
||||
unsigned long _next_mesh_thread_refresh;
|
||||
TouchUiScreen _touch_screen;
|
||||
bool _active_dm_contact_set;
|
||||
|
||||
Reference in new issue
Block a user