{
  "id": "meshcore-solo",
  "name": "MeshCore Solo",
  "type": "fork",
  "maintainer": "MarekZegare4",
  "maintainers": [
    {
      "name": "MarekZegare4",
      "url": "https://github.com/MarekZegare4"
    }
  ],
  "maintainerUrl": "https://github.com/MarekZegare4",
  "repository": "https://github.com/MarekZegare4/MeshCore-Solo",
  "website": "https://marekzegare4.github.io/Solo-tools/",
  "license": "MIT",
  "description": "A fork of the reference MeshCore companion radio firmware with extended features and UI enhancements. Adds GPS navigation (waypoints, compass, trail recording with GPX export), battery power-saving (hardware RX duty-cycle + adaptive power control), favourite contacts dial, extended language support with native Unicode rendering, message delivery status, screen lock, auto-reply bot, repeater mode with diagnostics, and more — all optimized for joystick-only navigation on small displays.\n",
  "status": "active",
  "scope": "universal",
  "lifecycle": "active",
  "maturity": "stable",
  "distribution": "community",
  "lineage": {
    "kind": "fork",
    "upstreamFirmwareId": "meshcore",
    "upstreamRepository": "https://github.com/meshcore-dev/MeshCore"
  },
  "runtime": {
    "framework": "arduino",
    "language": "cpp"
  },
  "roles": [
    "companion",
    "repeater",
    "standalone-ui"
  ],
  "features": [
    "Extended Unicode support with Lemon font and native input",
    "GPS navigation suite (waypoints, compass, backtrack, trail recording)",
    "GPX export via USB serial",
    "Screenshot capture over USB",
    "Favourites dial for pinned contacts",
    "Message delivery status indicators",
    "DM auto-resend and incoming deduplication",
    "Screen lock with time and sensor display",
    "Auto-reply bot with command responses",
    "Auto-advert for location sharing",
    "Battery power saving (RX duty-cycle + APC)",
    "Companion repeater mode with diagnostics",
    "Ping functionality in Nearby Nodes",
    "SOS broadcast with configurable target",
    "Quiet hours for sound suppression",
    "Mark-all-read at type level",
    "Lock-screen unread count",
    "Channel scanner home page",
    "Contact distance sorting",
    "Signal stats screen",
    "Display test pattern",
    "Power profile presets",
    "Solo Tools web app for screenshot capture and GPX export (https://marekzegare4.github.io/Solo-tools/)"
  ],
  "capabilities": {
    "protocol": {
      "meshcoreCompatible": true,
      "rawPacketSend": true,
      "rawPacketObserve": true
    },
    "transports": {
      "ble": true,
      "usbSerial": true,
      "nativeTcp": false,
      "wifiAp": false
    },
    "operations": {
      "webFlasher": false,
      "ota": false,
      "bleDfu": false,
      "configurationBackup": true
    },
    "networking": {
      "repeater": true,
      "roomServer": false,
      "observer": false,
      "mqtt": false,
      "kissModem": false
    },
    "hardware": {
      "gps": true,
      "display": true,
      "sensors": true,
      "lowPowerRx": true
    }
  },
  "changelog": {
    "source": "github",
    "repo": "MarekZegare4/MeshCore-Solo"
  },
  "devices": [
    {
      "id": "wio-tracker-l1",
      "status": "supported",
      "target": "wio-tracker-l1",
      "platformio_board": "seeed-wio-tracker-l1",
      "notes": "OLED variant (SSD1306/SH1106 128x64)"
    },
    {
      "id": "wio-tracker-l1-pro",
      "status": "supported",
      "target": "wio-tracker-l1",
      "platformio_board": "seeed-wio-tracker-l1",
      "notes": "OLED variant — same firmware target as wio-tracker-l1"
    },
    {
      "id": "wio-tracker-l1-eink",
      "status": "supported",
      "target": "wio-tracker-l1-eink",
      "platformio_board": "seeed-wio-tracker-l1",
      "notes": "E-ink variant (GxEPD2 250x122)"
    },
    {
      "id": "gatiot-gat562-30s",
      "status": "supported",
      "target": "gat562_30s_mesh_kit",
      "platformio_board": "rak4631",
      "notes": "GAT562 30S Mesh Kit"
    }
  ],
  "popularity": {
    "githubStars": 56,
    "githubForks": 5,
    "githubWatchers": 3,
    "githubOpenIssues": 8,
    "githubContributors": 178,
    "releaseDownloads": 924,
    "latestReleaseDownloads": 59,
    "lastChecked": "2026-08-05"
  },
  "verification": {
    "sourceAvailable": true,
    "releasesAvailable": true,
    "ciBuilds": true,
    "lastChecked": "2026-08-05"
  },
  "source": {
    "path": "data/firmwares/meshcore-solo/firmware.yaml",
    "updatedAt": "2026-08-05T14:13:46Z"
  },
  "latest_version": "1.24",
  "released": "2026-07-29",
  "releases": [
    {
      "version": "v1.24",
      "name": "Solo v1.24",
      "datetime": "2026-07-29T20:58:38Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.24",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.24\r\n\r\n### What's new\r\n\r\n- **Auto-Reply Bot is renamed to Remote Bot.** It's grown beyond auto-replies into remote device control (Actions, below), so the Tools screen entry and docs now say \"Remote Bot\" — same screen, same settings, nothing to reconfigure.\r\n- **Remote Bot gains Actions: `!buzz`, `!gps`, `!advert`.** A new **Actions** toggle (per target — Direct/Channel/Room, nested under each target's existing **Commands** toggle) enables three commands that change the device's own behaviour instead of just reporting on it: `!buzz [seconds]` sounds the buzzer as a find-me signal (default 5s, capped at 30s, sounds even if the buzzer is muted), `!gps on`/`!gps off` toggles GPS, and `!advert` sends an immediate advert (0 hop). Off by default; combines with the existing query commands in one message the same way (`!batt !gps on` → `4.10V | GPS: on`).\r\n- **`!gps fix [seconds]` — single-shot GPS location, no need to leave GPS running.** Turns GPS on (if it wasn't already), waits for a stabilised fix (HDOP ≤ 2.0 — falls back to ≥8 satellites on GPS hardware that doesn't report HDOP — then averages for 10s), sends the position, and restores GPS to whatever state it was in before — up to a 90s timeout by default (override with an optional argument, clamped to 15-300s, for a poor sky view where 90s isn't always enough), after which it reports a partial fix (if it got at least some samples) or failure. Replies in two parts: an immediate \"acquiring fix...\" ack, then the actual position as a follow-up message once ready. Only one fix request can be in flight at a time (a second one gets \"fix already pending\"); same Actions toggle as `!buzz`/`!gps`/`!advert`.\r\n- **Bot Trigger fields accept multiple phrases.** Pack several trigger words into one Trigger field, comma-separated (`hi,hello there,yo`) — matching any one of them fires the reply, same as before for a single phrase.\r\n- **Remote Bot Actions gain `!gpio1`..`!gpio4`** (Wio Tracker L1 only — 4 otherwise-unused pins). Each pin is independently set to Off/Input/Output (GPIO1/GPIO2 also offer Analog) from a new **Tools › GPIO** screen; `!gpio1 on`/`!gpio1 off` drives an Output pin remotely, a bare `!gpio1` reports the current mode and reading (including a millivolt value in Analog mode). Gated by the same per-target Actions toggle as `!buzz`/`!gps`/`!advert`.\r\n- **GAT562 30S solo builds now use the same OLED font as the Wio Tracker L1.** The misc-fixed 6x9 font (full Latin, Greek and Cyrillic) had only ever reached the SH1106 and e-ink drivers, so on this board every keyboard alphabet beyond ASCII, and every accented contact name, was still being transliterated (`Łódź` → `Lodz`) or drawn as a filled block. Solo builds only — the font costs ~14 KB of flash and the repeater/companion builds have no keyboard to type those alphabets on; they keep the built-in font and are byte-for-byte unchanged.\r\n\r\n _Work in progress territory_ \r\n- **Optional CardKB support (Wio Tracker L1, Grove I2C) — full keyboard-only navigation.** Plug an M5Stack CardKB into the Grove connector and it's auto-detected at boot — no setting to flip. Typing goes straight into the message/name field instead of navigating the on-screen keyboard grid, always as plain Latin text regardless of the Settings › Keyboard language/type — arrows and Esc work as expected everywhere else too (including inside the placeholder and accent popups). Enter acts like the physical centre button (advances the on-screen grid selection) rather than submitting, so **Fn+Enter** sends the message/confirms the field from anywhere, and **Fn+`<letter>`** opens that letter's accent popup directly (no arrow-hunting needed — handy for Polish/Czech/etc. diacritics — and works no matter what language/keyboard type is configured, since CardKB always types Latin either way). **Tab** is the Hold-Enter equivalent everywhere, including message reply/navigate and the Bot/Admin/Repeater menus — same single shortcut whether or \n…",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.24</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Auto-Reply Bot is renamed to Remote Bot.</strong> It's grown beyond auto-replies into remote device control (Actions, below), so the Tools screen entry and docs now say \"Remote Bot\" — same screen, same settings, nothing to reconfigure.</li>\n<li><strong>Remote Bot gains Actions: <code>!buzz</code>, <code>!gps</code>, <code>!advert</code>.</strong> A new <strong>Actions</strong> toggle (per target — Direct/Channel/Room, nested under each target's existing <strong>Commands</strong> toggle) enables three commands that change the device's own behaviour instead of just reporting on it: <code>!buzz [seconds]</code> sounds the buzzer as a find-me signal (default 5s, capped at 30s, sounds even if the buzzer is muted), <code>!gps on</code>/<code>!gps off</code> toggles GPS, and <code>!advert</code> sends an immediate advert (0 hop). Off by default; combines with the existing query commands in one message the same way (<code>!batt !gps on</code> → <code>4.10V | GPS: on</code>).</li>\n<li><strong><code>!gps fix [seconds]</code> — single-shot GPS location, no need to leave GPS running.</strong> Turns GPS on (if it wasn't already), waits for a stabilised fix (HDOP ≤ 2.0 — falls back to ≥8 satellites on GPS hardware that doesn't report HDOP — then averages for 10s), sends the position, and restores GPS to whatever state it was in before — up to a 90s timeout by default (override with an optional argument, clamped to 15-300s, for a poor sky view where 90s isn't always enough), after which it reports a partial fix (if it got at least some samples) or failure. Replies in two parts: an immediate \"acquiring fix...\" ack, then the actual position as a follow-up message once ready. Only one fix request can be in flight at a time (a second one gets \"fix already pending\"); same Actions toggle as <code>!buzz</code>/<code>!gps</code>/<code>!advert</code>.</li>\n<li><strong>Bot Trigger fields accept multiple phrases.</strong> Pack several trigger words into one Trigger field, comma-separated (<code>hi,hello there,yo</code>) — matching any one of them fires the reply, same as before for a single phrase.</li>\n<li><strong>Remote Bot Actions gain <code>!gpio1</code>..<code>!gpio4</code></strong> (Wio Tracker L1 only — 4 otherwise-unused pins). Each pin is independently set to Off/Input/Output (GPIO1/GPIO2 also offer Analog) from a new <strong>Tools › GPIO</strong> screen; <code>!gpio1 on</code>/<code>!gpio1 off</code> drives an Output pin remotely, a bare <code>!gpio1</code> reports the current mode and reading (including a millivolt value in Analog mode). Gated by the same per-target Actions toggle as <code>!buzz</code>/<code>!gps</code>/<code>!advert</code>.</li>\n<li><strong>GAT562 30S solo builds now use the same OLED font as the Wio Tracker L1.</strong> The misc-fixed 6x9 font (full Latin, Greek and Cyrillic) had only ever reached the SH1106 and e-ink drivers, so on this board every keyboard alphabet beyond ASCII, and every accented contact name, was still being transliterated (<code>Łódź</code> → <code>Lodz</code>) or drawn as a filled block. Solo builds only — the font costs ~14 KB of flash and the repeater/companion builds have no keyboard to type those alphabets on; they keep the built-in font and are byte-for-byte unchanged.</li>\n</ul>\n<p> <em>Work in progress territory</em> </p>\n<ul>\n<li><strong>Optional CardKB support (Wio Tracker L1, Grove I2C) — full keyboard-only navigation.</strong> Plug an M5Stack CardKB into the Grove connector and it's auto-detected at boot — no setting to flip. Typing goes straight into the message/name field instead of navigating the on-screen keyboard grid, always as plain Latin text regardless of the Settings › Keyboard language/type — arrows and Esc work as expected everywhere else too (including inside the placeholder and accent popups). Enter acts like the physical centre button (advances the on-screen grid selection) rather than submitting, so <strong>Fn+Enter</strong> sends the message/confirms the field from anywhere, and <strong>Fn+<code>&lt;letter&gt;</code></strong> opens that letter's accent popup directly (no arrow-hunting needed — handy for Polish/Czech/etc. diacritics — and works no matter what language/keyboard type is configured, since CardKB always types Latin either way). <strong>Tab</strong> is the Hold-Enter equivalent everywhere, including message reply/navigate and the Bot/Admin/Repeater menus — same single shortcut whether or \n…</li>\n</ul>\n"
    },
    {
      "version": "v1.23.1",
      "name": "Solo v1.23.1",
      "datetime": "2026-07-24T19:41:29Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.23.1",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.23.1\r\n\r\n### Fixes\r\n\r\n- **Tools › Admin login could get stuck on \"Logging in...\" forever** if the remote node never sent back a reply — most commonly after its admin/room password was changed, since the on-device UI auto-retries the old saved password with no timeout to fall back on. It now gives up after the same estimated-timeout window the rest of Admin's commands use, forgets the stale saved password, and returns you to the picker to try again with the new one.\r\n- **Changing a remote's admin password from Tools › Admin › System didn't update this device's own saved copy** — the very next login attempt to that node retried the password you'd just replaced, hitting the \"stuck on Logging in…\" case above. The confirmation the remote echoes back is now saved as the new on-device password to match.\r\n- **A slow-to-arrive Admin login reply, after you'd already given up on it (Cancel or the new timeout above), could get delivered to whatever screen you'd since moved to and silently overwrite your saved password for that node with unrelated data.** Giving up on a login now also stops tracking it mesh-side, so a late reply is simply dropped instead of misrouted.\r\n- **Opening Admin on a second, password-less node while an earlier room/repeater login elsewhere was still in flight could wrongly show you as logged in as admin on the new node** — a reply meant for the earlier login was accepted as this node's own since both merely looked like \"a login is pending,\" without checking it actually named this node. Now checked.",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.23.1</h2>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Tools › Admin login could get stuck on \"Logging in...\" forever</strong> if the remote node never sent back a reply — most commonly after its admin/room password was changed, since the on-device UI auto-retries the old saved password with no timeout to fall back on. It now gives up after the same estimated-timeout window the rest of Admin's commands use, forgets the stale saved password, and returns you to the picker to try again with the new one.</li>\n<li><strong>Changing a remote's admin password from Tools › Admin › System didn't update this device's own saved copy</strong> — the very next login attempt to that node retried the password you'd just replaced, hitting the \"stuck on Logging in…\" case above. The confirmation the remote echoes back is now saved as the new on-device password to match.</li>\n<li><strong>A slow-to-arrive Admin login reply, after you'd already given up on it (Cancel or the new timeout above), could get delivered to whatever screen you'd since moved to and silently overwrite your saved password for that node with unrelated data.</strong> Giving up on a login now also stops tracking it mesh-side, so a late reply is simply dropped instead of misrouted.</li>\n<li><strong>Opening Admin on a second, password-less node while an earlier room/repeater login elsewhere was still in flight could wrongly show you as logged in as admin on the new node</strong> — a reply meant for the earlier login was accepted as this node's own since both merely looked like \"a login is pending,\" without checking it actually named this node. Now checked.</li>\n</ul>\n"
    },
    {
      "version": "v1.23",
      "name": "Solo v1.23",
      "datetime": "2026-07-17T20:17:33Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.23",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.23\r\n\r\n### What's new\r\n\r\n- **Nodes is now the single node hub.** \"Nearby Nodes\" is renamed **Nodes** and gains on-device contact management — no phone app needed: **Hold Enter** on a row opens **Add contact** (for a scanned-but-unknown node), **Favourite/Unfavourite** (pins to the first free Favourites Dial slot, shown as a star in the list), and **Delete contact** (confirm first, defaults to Cancel). The filter strip (**LEFT/RIGHT**) is now a visible, wraparound tab carousel instead of a hidden mode. The old read-only **Recent adverts** home page is retired — its passively-heard nodes now simply show up in the Nodes list (All filter) — so there's one list instead of two.\r\n- **On-device channel management.** Messages › Channels gets a **\"+ Add channel\"** row and per-channel **Edit**/**Delete** — no phone app required. Adding a channel now starts with a **type picker**, matching the phone app: **Public** (re-adds the well-known default channel, no typing needed), **Hashtag** (type just a topic name, e.g. `test` — the channel name and secret are both derived from it, same convention as the app's `#topic` channels), or **Private** (manual Name + Secret, typing either a passphrase hashed to the channel secret, or the exact 32-hex-character key from a channel QR code).\r\n- **Tools › Admin — administer a remote repeater/room from the device.** Log into a node you have admin rights on (same self-healing saved-password handshake as room logins) and browse its settings in category tabs — **System** (name, owner info), **Radio** (Frequency/Bandwidth/Spreading factor/Coding rate/TX power), **Routing** (Repeat/Advert interval/Flood advert interval/Max hops), **Actions** (reboot, send advert, sync clock, …) — plus a free-text **Custom command…** escape hatch (with **{}**-key command-name completion) for anything not covered. Radio and Routing fields use a type-appropriate editor instead of raw text — a digit-cursor for Frequency (the same widget Settings' own Radio screen uses locally), discrete-set stepping for Bandwidth/Spreading factor/Coding rate, plain number steppers for the rest, and an ON/OFF toggle for Repeat — adjusting a value costs no mesh traffic until you actually confirm it with **Enter** (**Cancel** sends nothing). Reachable either from **Tools › Admin** (opens the same Nodes list to pick a target) or directly via a repeater/room's own **Hold Enter › Admin** action.\r\n- **Auto-Reply Bot gains a third target: room servers**, alongside DM and Channel, with its own trigger/reply/commands — the screen is redesigned as a circular tab carousel (**Direct/Channel/Room/Other**, **LEFT/RIGHT** to switch, **UP/DOWN** within a tab) instead of one long list. Each target's **Enable** and **Commands** toggle is now fully independent (they used to secretly share the DM tab's setting for Channel/Room too). New `{name}`/`{hops}` reply placeholders, a DM allow-list (all chat contacts or favourites only), and a dedicated stepper for Quiet Hours.\r\n- **Keyboard: accent popup, selectable main script, better editing.** Holding **Enter** on a Latin letter with accented variants (`a c d e i l n o r s t u y z`) now opens a one-row popup of that letter's accents — e.g. holding `a` offers `á à â ã ä å ą` — covering every European Latin-diacritic letter (Polish, Czech, Slovak, German, French, Spanish, Portuguese, Nordic, …) from one popup instead of a separate page per language. **Settings › Keyboard** splits **Alphabet** into **Main** and **Additional**: Main picks which script (Latin/Cyrillic/Greek) the keyboard opens on by default, Additional picks the second one reached via the **#@/abc** cycle key — so a Cyrillic or Greek typist can make their own script the default instead of always landing on Latin first. Shift is now **one-shot** by default (capitalises just the next letter; **Hold Enter** on Shift toggles the old sticky caps-lock back on), **Hold Enter** on Backspace clears the whole field, and **UP** from th\n…",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.23</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Nodes is now the single node hub.</strong> \"Nearby Nodes\" is renamed <strong>Nodes</strong> and gains on-device contact management — no phone app needed: <strong>Hold Enter</strong> on a row opens <strong>Add contact</strong> (for a scanned-but-unknown node), <strong>Favourite/Unfavourite</strong> (pins to the first free Favourites Dial slot, shown as a star in the list), and <strong>Delete contact</strong> (confirm first, defaults to Cancel). The filter strip (<strong>LEFT/RIGHT</strong>) is now a visible, wraparound tab carousel instead of a hidden mode. The old read-only <strong>Recent adverts</strong> home page is retired — its passively-heard nodes now simply show up in the Nodes list (All filter) — so there's one list instead of two.</li>\n<li><strong>On-device channel management.</strong> Messages › Channels gets a <strong>\"+ Add channel\"</strong> row and per-channel <strong>Edit</strong>/<strong>Delete</strong> — no phone app required. Adding a channel now starts with a <strong>type picker</strong>, matching the phone app: <strong>Public</strong> (re-adds the well-known default channel, no typing needed), <strong>Hashtag</strong> (type just a topic name, e.g. <code>test</code> — the channel name and secret are both derived from it, same convention as the app's <code>#topic</code> channels), or <strong>Private</strong> (manual Name + Secret, typing either a passphrase hashed to the channel secret, or the exact 32-hex-character key from a channel QR code).</li>\n<li><strong>Tools › Admin — administer a remote repeater/room from the device.</strong> Log into a node you have admin rights on (same self-healing saved-password handshake as room logins) and browse its settings in category tabs — <strong>System</strong> (name, owner info), <strong>Radio</strong> (Frequency/Bandwidth/Spreading factor/Coding rate/TX power), <strong>Routing</strong> (Repeat/Advert interval/Flood advert interval/Max hops), <strong>Actions</strong> (reboot, send advert, sync clock, …) — plus a free-text <strong>Custom command…</strong> escape hatch (with <strong>{}</strong>-key command-name completion) for anything not covered. Radio and Routing fields use a type-appropriate editor instead of raw text — a digit-cursor for Frequency (the same widget Settings' own Radio screen uses locally), discrete-set stepping for Bandwidth/Spreading factor/Coding rate, plain number steppers for the rest, and an ON/OFF toggle for Repeat — adjusting a value costs no mesh traffic until you actually confirm it with <strong>Enter</strong> (<strong>Cancel</strong> sends nothing). Reachable either from <strong>Tools › Admin</strong> (opens the same Nodes list to pick a target) or directly via a repeater/room's own <strong>Hold Enter › Admin</strong> action.</li>\n<li><strong>Auto-Reply Bot gains a third target: room servers</strong>, alongside DM and Channel, with its own trigger/reply/commands — the screen is redesigned as a circular tab carousel (<strong>Direct/Channel/Room/Other</strong>, <strong>LEFT/RIGHT</strong> to switch, <strong>UP/DOWN</strong> within a tab) instead of one long list. Each target's <strong>Enable</strong> and <strong>Commands</strong> toggle is now fully independent (they used to secretly share the DM tab's setting for Channel/Room too). New <code>{name}</code>/<code>{hops}</code> reply placeholders, a DM allow-list (all chat contacts or favourites only), and a dedicated stepper for Quiet Hours.</li>\n<li><strong>Keyboard: accent popup, selectable main script, better editing.</strong> Holding <strong>Enter</strong> on a Latin letter with accented variants (<code>a c d e i l n o r s t u y z</code>) now opens a one-row popup of that letter's accents — e.g. holding <code>a</code> offers <code>á à â ã ä å ą</code> — covering every European Latin-diacritic letter (Polish, Czech, Slovak, German, French, Spanish, Portuguese, Nordic, …) from one popup instead of a separate page per language. <strong>Settings › Keyboard</strong> splits <strong>Alphabet</strong> into <strong>Main</strong> and <strong>Additional</strong>: Main picks which script (Latin/Cyrillic/Greek) the keyboard opens on by default, Additional picks the second one reached via the <strong>#@/abc</strong> cycle key — so a Cyrillic or Greek typist can make their own script the default instead of always landing on Latin first. Shift is now <strong>one-shot</strong> by default (capitalises just the next letter; <strong>Hold Enter</strong> on Shift toggles the old sticky caps-lock back on), <strong>Hold Enter</strong> on Backspace clears the whole field, and <strong>UP</strong> from th\n…</li>\n</ul>\n"
    },
    {
      "version": "v1.22",
      "name": "Solo v1.22",
      "datetime": "2026-07-06T19:29:14Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.22",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.22\r\n\r\n### What's new\r\n\r\n- **T9 on-screen keyboard** — a new keyboard option under **Settings › Keyboard**. Alongside the existing alphabetical **ABC** grid, pick **T9** for phone-keypad-style entry: each key is labelled with its digit and a letter group (e.g. `2abc`), and repeated **Enter** presses cycle through the letters and then the digit. (The alphabetical grid was previously mislabelled *QWERTY* in Settings — it's always been a-b-c order and is now correctly named **ABC**.)\r\n- **Auto-save GPS trail on shutdown** — a new **Tools › Trail › Settings › Auto-save** toggle (default off). With it on, the live trail is written to flash automatically at power-off, so a **low-battery auto-shutdown** no longer loses the whole route. It only writes when the trail actually has points, so an empty trail can't overwrite a previously saved one. Saves to the same `/trail` file as the manual **Trail › Save**.\r\n- **Clock Tools from the Tools menu** — the Alarm / Timer / Stopwatch screen (reachable by pressing **Enter** on the Clock home page) now also has its own entry under **Tools › System**, so it's discoverable without first finding it on the clock face.\r\n- **Map & Shutdown pages are reorderable** — the **Map** home page shipped with no entry under **Settings › Home Pages**, so it was always shown and couldn't be moved. It's now a first-class page there: **toggle its visibility** and **reorder it** like any other (visible by default; existing users keep it on). Reordering also now covers the **Shutdown** page, which was previously pinned to the end of the carousel.\r\n\r\n### Fixes\r\n\r\n- **Battery reads high and jittery on Wio Tracker L1** — a power-saving change had switched the battery-voltage divider on for only ~10 ms before each reading, too short for the high-impedance divider node to settle, so a full LiPo could report 4.6–5.0 V. The divider is now held on continuously again (a negligible ~2 µA on the 2×1 MΩ divider), giving stable, accurate readings. The CPU-sleep and LED energy savings from the same optimisation pass are untouched.\r\n- **Home page visibility no longer resets on update** — the prefs schema-migration that turned the **Favourites** page on ran on *every* firmware update (any schema-version bump), so a page you'd deliberately hidden kept coming back after each release. It's now gated to the single upgrade that introduced Favourites, so your hidden pages stay hidden.\r\n- a **locked device didn't show the alarm** — it woke the display, then immediately re-blanked, so a ringing alarm played to a dark screen. The lock screen now draws the alert and holds the wake for the whole ring.\r\n- **background-mode status icons vanished when Bluetooth was off** — the auto-advert / live-share / trail / repeater indicators were nested inside the \"BT on\" check and are now always shown while their mode is active.\r\n- a **long alert message** (\"GPS on, tracking started\") spilled past its box on a narrow screen — it now wraps to up to three lines and the box grows to fit.\r\n- a **contact name pushed from the phone app** wasn't guaranteed to be NUL-terminated.\r\n- the **timer / alarm could mis-fire** for a deadline landing past the ~49-day `millis()` rollover.\r\n- toggling a **channel's favourite from its context menu** could retarget the menu onto a different channel once the list re-sorted.\r\n- **A repeater could appear twice** on the discovery scan and in the app — a discover response often arrives more than once (the direct copy plus a re-flooded copy carry different packet hashes, so the mesh's duplicate filter passes both), and each copy was listed. Duplicate copies of the same response are now dropped for a few seconds after the first.\r\n- **Favourites self-heal** — a pinned favourite whose contact no longer exists (e.g. after clearing contacts) now reverts to an empty **+** tile instead of showing **(gone)**, and the stale pin is cleared from prefs.\r\n- **Radio preset names no longer seed `{loc}`/`{time}\n…",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.22</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>T9 on-screen keyboard</strong> — a new keyboard option under <strong>Settings › Keyboard</strong>. Alongside the existing alphabetical <strong>ABC</strong> grid, pick <strong>T9</strong> for phone-keypad-style entry: each key is labelled with its digit and a letter group (e.g. <code>2abc</code>), and repeated <strong>Enter</strong> presses cycle through the letters and then the digit. (The alphabetical grid was previously mislabelled <em>QWERTY</em> in Settings — it's always been a-b-c order and is now correctly named <strong>ABC</strong>.)</li>\n<li><strong>Auto-save GPS trail on shutdown</strong> — a new <strong>Tools › Trail › Settings › Auto-save</strong> toggle (default off). With it on, the live trail is written to flash automatically at power-off, so a <strong>low-battery auto-shutdown</strong> no longer loses the whole route. It only writes when the trail actually has points, so an empty trail can't overwrite a previously saved one. Saves to the same <code>/trail</code> file as the manual <strong>Trail › Save</strong>.</li>\n<li><strong>Clock Tools from the Tools menu</strong> — the Alarm / Timer / Stopwatch screen (reachable by pressing <strong>Enter</strong> on the Clock home page) now also has its own entry under <strong>Tools › System</strong>, so it's discoverable without first finding it on the clock face.</li>\n<li><strong>Map &amp; Shutdown pages are reorderable</strong> — the <strong>Map</strong> home page shipped with no entry under <strong>Settings › Home Pages</strong>, so it was always shown and couldn't be moved. It's now a first-class page there: <strong>toggle its visibility</strong> and <strong>reorder it</strong> like any other (visible by default; existing users keep it on). Reordering also now covers the <strong>Shutdown</strong> page, which was previously pinned to the end of the carousel.</li>\n</ul>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Battery reads high and jittery on Wio Tracker L1</strong> — a power-saving change had switched the battery-voltage divider on for only ~10 ms before each reading, too short for the high-impedance divider node to settle, so a full LiPo could report 4.6–5.0 V. The divider is now held on continuously again (a negligible ~2 µA on the 2×1 MΩ divider), giving stable, accurate readings. The CPU-sleep and LED energy savings from the same optimisation pass are untouched.</li>\n<li><strong>Home page visibility no longer resets on update</strong> — the prefs schema-migration that turned the <strong>Favourites</strong> page on ran on <em>every</em> firmware update (any schema-version bump), so a page you'd deliberately hidden kept coming back after each release. It's now gated to the single upgrade that introduced Favourites, so your hidden pages stay hidden.</li>\n<li>a <strong>locked device didn't show the alarm</strong> — it woke the display, then immediately re-blanked, so a ringing alarm played to a dark screen. The lock screen now draws the alert and holds the wake for the whole ring.</li>\n<li><strong>background-mode status icons vanished when Bluetooth was off</strong> — the auto-advert / live-share / trail / repeater indicators were nested inside the \"BT on\" check and are now always shown while their mode is active.</li>\n<li>a <strong>long alert message</strong> (\"GPS on, tracking started\") spilled past its box on a narrow screen — it now wraps to up to three lines and the box grows to fit.</li>\n<li>a <strong>contact name pushed from the phone app</strong> wasn't guaranteed to be NUL-terminated.</li>\n<li>the <strong>timer / alarm could mis-fire</strong> for a deadline landing past the ~49-day <code>millis()</code> rollover.</li>\n<li>toggling a <strong>channel's favourite from its context menu</strong> could retarget the menu onto a different channel once the list re-sorted.</li>\n<li><strong>A repeater could appear twice</strong> on the discovery scan and in the app — a discover response often arrives more than once (the direct copy plus a re-flooded copy carry different packet hashes, so the mesh's duplicate filter passes both), and each copy was listed. Duplicate copies of the same response are now dropped for a few seconds after the first.</li>\n<li><strong>Favourites self-heal</strong> — a pinned favourite whose contact no longer exists (e.g. after clearing contacts) now reverts to an empty <strong>+</strong> tile instead of showing <strong>(gone)</strong>, and the stale pin is cleared from prefs.</li>\n<li>**Radio preset names no longer seed <code>{loc}</code>/`{time}\n…</li>\n</ul>\n"
    },
    {
      "version": "v1.21",
      "name": "Solo v1.21",
      "datetime": "2026-06-30T20:48:57Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.21",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.21\r\n\r\n### What's new\r\n\r\n- **Live Location Sharing** — broadcast your position over the mesh as `[LOC]` messages, **movement-gated**, to a channel or a single contact. Others who share theirs show up as pins on the map with live **distance/bearing in Nearby Nodes**, and a **status-bar indicator** appears while your own share is active. `[LOC]` is parsed in DMs, channel messages **and room messages**; DM shares name the sender.\r\n- **Locator** (geofence) — arm a geofence around a **target** — a saved waypoint *or* a person (their live `[LOC]` or last-known position) — and get an alert when you **arrive/leave** or they get **near/far**, with an optional **homing beeper** that ticks faster the closer you get (and overrides a muted buzzer). Arm it from **Tools › Locator** or straight from **Nearby Nodes** / **Waypoints**; pick the target from a list (favourites first, then any contact), and clear it via a **\"None\"** entry. The active target is drawn as a **flag** on the map.\r\n- **One active target across Locator / Navigate / Map** — a single **\"Set as target\"** action everywhere, backed by a shared resolver that prefers a live `[LOC]` share over the last-advertised GPS, so the three features always agree on where you're headed.\r\n- **Follow live contacts** — **Navigate** to a contact who is live-sharing and the view **follows them as they move**, adding an **ETA** line. **Quick-share** your own position straight from the Map.\r\n- **Map & status-bar upgrades** — the home mini-map gains a **north marker** and a **scale tick**; the status line shows the tracked-node count and, with a fix, an **arrow + distance to the nearest tracked contact** (e.g. `Track:3 →120m`); a **GPS fix icon** sits in the top status bar (boxed once a fix is valid, plain while searching), shown only on GPS boards while **GPS** is enabled in Settings.\r\n- **Trail auto-pause** — recording **freezes on stops** (banking elapsed time and breaking the map line across the idle gap) and **resumes on movement** without ending the session; the home-screen blink keeps going while paused.\r\n- **Collapsible Tools** — tools are grouped into fold-in-place **Location / Comms / System** sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses **page-indicator icons** instead of dots.\r\n- **Clock tools — alarm, timer, stopwatch** — press **Enter** on the Clock page for three time utilities: a **one-shot wake alarm** (set hour/minute with the digit editor; a **bell** marks it on the clock face and the status bar while armed), a **countdown timer** (full **HH:MM:SS**, single-digit cursor), and a **stopwatch**. The alarm and timer **ring with a melody — overriding mute** — and are silenced by **any key**. They keep running with the display off or locked, and the alarm is scheduled as an **absolute instant** so it survives the clock re-syncs the mesh / app / GPS / CLI can trigger at any time (it can't wake the device from a full Shutdown, where the CPU is off).\r\n- **Waypoint coordinate editor** — add a waypoint by scroll-editing its latitude/longitude digit by digit.\r\n- **On-device room login with saved passwords** — log in to a room server straight from the device (no phone app): pick the room and the password prompt appears automatically (a blank password works for open rooms), or re-login any time via the room's **context-menu \"Login…\"**. The password is **remembered across reboots**, so a room you've used before logs back in without retyping; a failed login (e.g. the server's password changed) forgets the stale password so the next attempt prompts again. Room passwords entered via the **phone app** are saved on the device too, so it can post to that room standalone after a reboot. Saved passwords are written with the same atomic, crash-safe persistence as contacts and channels.\r\n\r\n### Fixes\r\n\r\n- **Critical — low-heap hang and contact loss on RAM-tight builds.** With `MAX_CONTACTS=350` an\n…",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.21</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Live Location Sharing</strong> — broadcast your position over the mesh as <code>[LOC]</code> messages, <strong>movement-gated</strong>, to a channel or a single contact. Others who share theirs show up as pins on the map with live <strong>distance/bearing in Nearby Nodes</strong>, and a <strong>status-bar indicator</strong> appears while your own share is active. <code>[LOC]</code> is parsed in DMs, channel messages <strong>and room messages</strong>; DM shares name the sender.</li>\n<li><strong>Locator</strong> (geofence) — arm a geofence around a <strong>target</strong> — a saved waypoint <em>or</em> a person (their live <code>[LOC]</code> or last-known position) — and get an alert when you <strong>arrive/leave</strong> or they get <strong>near/far</strong>, with an optional <strong>homing beeper</strong> that ticks faster the closer you get (and overrides a muted buzzer). Arm it from <strong>Tools › Locator</strong> or straight from <strong>Nearby Nodes</strong> / <strong>Waypoints</strong>; pick the target from a list (favourites first, then any contact), and clear it via a <strong>\"None\"</strong> entry. The active target is drawn as a <strong>flag</strong> on the map.</li>\n<li><strong>One active target across Locator / Navigate / Map</strong> — a single <strong>\"Set as target\"</strong> action everywhere, backed by a shared resolver that prefers a live <code>[LOC]</code> share over the last-advertised GPS, so the three features always agree on where you're headed.</li>\n<li><strong>Follow live contacts</strong> — <strong>Navigate</strong> to a contact who is live-sharing and the view <strong>follows them as they move</strong>, adding an <strong>ETA</strong> line. <strong>Quick-share</strong> your own position straight from the Map.</li>\n<li><strong>Map &amp; status-bar upgrades</strong> — the home mini-map gains a <strong>north marker</strong> and a <strong>scale tick</strong>; the status line shows the tracked-node count and, with a fix, an <strong>arrow + distance to the nearest tracked contact</strong> (e.g. <code>Track:3 →120m</code>); a <strong>GPS fix icon</strong> sits in the top status bar (boxed once a fix is valid, plain while searching), shown only on GPS boards while <strong>GPS</strong> is enabled in Settings.</li>\n<li><strong>Trail auto-pause</strong> — recording <strong>freezes on stops</strong> (banking elapsed time and breaking the map line across the idle gap) and <strong>resumes on movement</strong> without ending the session; the home-screen blink keeps going while paused.</li>\n<li><strong>Collapsible Tools</strong> — tools are grouped into fold-in-place <strong>Location / Comms / System</strong> sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses <strong>page-indicator icons</strong> instead of dots.</li>\n<li><strong>Clock tools — alarm, timer, stopwatch</strong> — press <strong>Enter</strong> on the Clock page for three time utilities: a <strong>one-shot wake alarm</strong> (set hour/minute with the digit editor; a <strong>bell</strong> marks it on the clock face and the status bar while armed), a <strong>countdown timer</strong> (full <strong>HH:MM:SS</strong>, single-digit cursor), and a <strong>stopwatch</strong>. The alarm and timer <strong>ring with a melody — overriding mute</strong> — and are silenced by <strong>any key</strong>. They keep running with the display off or locked, and the alarm is scheduled as an <strong>absolute instant</strong> so it survives the clock re-syncs the mesh / app / GPS / CLI can trigger at any time (it can't wake the device from a full Shutdown, where the CPU is off).</li>\n<li><strong>Waypoint coordinate editor</strong> — add a waypoint by scroll-editing its latitude/longitude digit by digit.</li>\n<li><strong>On-device room login with saved passwords</strong> — log in to a room server straight from the device (no phone app): pick the room and the password prompt appears automatically (a blank password works for open rooms), or re-login any time via the room's <strong>context-menu \"Login…\"</strong>. The password is <strong>remembered across reboots</strong>, so a room you've used before logs back in without retyping; a failed login (e.g. the server's password changed) forgets the stale password so the next attempt prompts again. Room passwords entered via the <strong>phone app</strong> are saved on the device too, so it can post to that room standalone after a reboot. Saved passwords are written with the same atomic, crash-safe persistence as contacts and channels.</li>\n</ul>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Critical — low-heap hang and contact loss on RAM-tight builds.</strong> With <code>MAX_CONTACTS=350</code> an\n…</li>\n</ul>\n"
    },
    {
      "version": "v1.21-rc2",
      "name": "Solo v1.21-rc2",
      "datetime": "2026-06-26T22:52:12Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.21-rc2",
      "prerelease": true,
      "notes": "## MeshCore Solo Companion Firmware v1.21 Release candidate 2\r\n\r\n### What's new\r\n\r\n- **Live Location Sharing** — broadcast your position over the mesh as `[LOC]` messages, **movement-gated**, to a channel or a single contact. Others who share theirs show up as pins on the map with live **distance/bearing in Nearby Nodes**, and a **status-bar indicator** appears while your own share is active. `[LOC]` is parsed in DMs, channel messages **and room messages**; DM shares name the sender.\r\n- **Locator** (geofence) — arm a geofence around a **target** — a saved waypoint *or* a person (their live `[LOC]` or last-known position) — and get an alert when you **arrive/leave** or they get **near/far**, with an optional **homing beeper** that ticks faster the closer you get (and overrides a muted buzzer). Arm it from **Tools › Locator** or straight from **Nearby Nodes** / **Waypoints**; pick the target from a list (favourites first, then any contact), and clear it via a **\"None\"** entry. The active target is drawn as a **flag** on the map.\r\n- **One active target across Locator / Navigate / Map** — a single **\"Set as target\"** action everywhere, backed by a shared resolver that prefers a live `[LOC]` share over the last-advertised GPS, so the three features always agree on where you're headed.\r\n- **Follow live contacts** — **Navigate** to a contact who is live-sharing and the view **follows them as they move**, adding an **ETA** line. **Quick-share** your own position straight from the Map.\r\n- **Map & status-bar upgrades** — the home mini-map gains a **north marker** and a **scale tick**; the status line shows the tracked-node count and, with a fix, an **arrow + distance to the nearest tracked contact** (e.g. `Track:3 →120m`); a **GPS fix icon** sits in the top status bar (boxed once a fix is valid, plain while searching), shown only on GPS boards while **GPS** is enabled in Settings.\r\n- **Trail auto-pause** — recording **freezes on stops** (banking elapsed time and breaking the map line across the idle gap) and **resumes on movement** without ending the session; the home-screen blink keeps going while paused.\r\n- **Collapsible Tools** — tools are grouped into fold-in-place **Location / Comms / System** sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses **page-indicator icons** instead of dots.\r\n- **Waypoint coordinate editor** — add a waypoint by scroll-editing its latitude/longitude digit by digit.\r\n- **On-device room login with saved passwords** — log in to a room server straight from the device (no phone app): pick the room and the password prompt appears automatically (a blank password works for open rooms), or re-login any time via the room's **context-menu \"Login…\"**. The password is **remembered across reboots**, so a room you've used before logs back in without retyping; a failed login (e.g. the server's password changed) forgets the stale password so the next attempt prompts again. Saved passwords are written with the same atomic, crash-safe persistence as contacts and channels.\r\n\r\n\r\n### Fixes\r\n\r\n- **Critical — low-heap hang and contact loss on RAM-tight builds.** With `MAX_CONTACTS=350` and `OFFLINE_QUEUE_SIZE=256` the device ran with very little free heap; an allocation in the input/menu path could then fail and **hang the UI** (notably when entering Diagnostics), and a crash or reset mid-save could **wipe all contacts**. Fixed by two independent changes:\r\n  - **Right-sized message-history rings** — the on-device scrollback rings were halved (96→48 channel, 64→32 DM), recovering **~14 KB of free heap** (measured 3 → 17 KB). History is RAM-only, so the only cost is shorter on-device scrollback.\r\n  - **Atomic persistence** — contacts, channels and prefs are now written to a temp file and **atomically renamed** into place; an interrupted save (crash, reset, full flash) leaves the previous good file intact instead of truncating it.\r\n- **USB host stall** — `Serial.write\n…",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.21 Release candidate 2</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Live Location Sharing</strong> — broadcast your position over the mesh as <code>[LOC]</code> messages, <strong>movement-gated</strong>, to a channel or a single contact. Others who share theirs show up as pins on the map with live <strong>distance/bearing in Nearby Nodes</strong>, and a <strong>status-bar indicator</strong> appears while your own share is active. <code>[LOC]</code> is parsed in DMs, channel messages <strong>and room messages</strong>; DM shares name the sender.</li>\n<li><strong>Locator</strong> (geofence) — arm a geofence around a <strong>target</strong> — a saved waypoint <em>or</em> a person (their live <code>[LOC]</code> or last-known position) — and get an alert when you <strong>arrive/leave</strong> or they get <strong>near/far</strong>, with an optional <strong>homing beeper</strong> that ticks faster the closer you get (and overrides a muted buzzer). Arm it from <strong>Tools › Locator</strong> or straight from <strong>Nearby Nodes</strong> / <strong>Waypoints</strong>; pick the target from a list (favourites first, then any contact), and clear it via a <strong>\"None\"</strong> entry. The active target is drawn as a <strong>flag</strong> on the map.</li>\n<li><strong>One active target across Locator / Navigate / Map</strong> — a single <strong>\"Set as target\"</strong> action everywhere, backed by a shared resolver that prefers a live <code>[LOC]</code> share over the last-advertised GPS, so the three features always agree on where you're headed.</li>\n<li><strong>Follow live contacts</strong> — <strong>Navigate</strong> to a contact who is live-sharing and the view <strong>follows them as they move</strong>, adding an <strong>ETA</strong> line. <strong>Quick-share</strong> your own position straight from the Map.</li>\n<li><strong>Map &amp; status-bar upgrades</strong> — the home mini-map gains a <strong>north marker</strong> and a <strong>scale tick</strong>; the status line shows the tracked-node count and, with a fix, an <strong>arrow + distance to the nearest tracked contact</strong> (e.g. <code>Track:3 →120m</code>); a <strong>GPS fix icon</strong> sits in the top status bar (boxed once a fix is valid, plain while searching), shown only on GPS boards while <strong>GPS</strong> is enabled in Settings.</li>\n<li><strong>Trail auto-pause</strong> — recording <strong>freezes on stops</strong> (banking elapsed time and breaking the map line across the idle gap) and <strong>resumes on movement</strong> without ending the session; the home-screen blink keeps going while paused.</li>\n<li><strong>Collapsible Tools</strong> — tools are grouped into fold-in-place <strong>Location / Comms / System</strong> sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses <strong>page-indicator icons</strong> instead of dots.</li>\n<li><strong>Waypoint coordinate editor</strong> — add a waypoint by scroll-editing its latitude/longitude digit by digit.</li>\n<li><strong>On-device room login with saved passwords</strong> — log in to a room server straight from the device (no phone app): pick the room and the password prompt appears automatically (a blank password works for open rooms), or re-login any time via the room's <strong>context-menu \"Login…\"</strong>. The password is <strong>remembered across reboots</strong>, so a room you've used before logs back in without retyping; a failed login (e.g. the server's password changed) forgets the stale password so the next attempt prompts again. Saved passwords are written with the same atomic, crash-safe persistence as contacts and channels.</li>\n</ul>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Critical — low-heap hang and contact loss on RAM-tight builds.</strong> With <code>MAX_CONTACTS=350</code> and <code>OFFLINE_QUEUE_SIZE=256</code> the device ran with very little free heap; an allocation in the input/menu path could then fail and <strong>hang the UI</strong> (notably when entering Diagnostics), and a crash or reset mid-save could <strong>wipe all contacts</strong>. Fixed by two independent changes:<ul>\n<li><strong>Right-sized message-history rings</strong> — the on-device scrollback rings were halved (96→48 channel, 64→32 DM), recovering <strong>~14 KB of free heap</strong> (measured 3 → 17 KB). History is RAM-only, so the only cost is shorter on-device scrollback.</li>\n<li><strong>Atomic persistence</strong> — contacts, channels and prefs are now written to a temp file and <strong>atomically renamed</strong> into place; an interrupted save (crash, reset, full flash) leaves the previous good file intact instead of truncating it.</li>\n</ul>\n</li>\n<li><strong>USB host stall</strong> — `Serial.write\n…</li>\n</ul>\n"
    },
    {
      "version": "v1.21-rc1",
      "name": "Solo v1.21-rc1",
      "datetime": "2026-06-25T17:17:12Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.21-rc1",
      "prerelease": true,
      "notes": "## MeshCore Solo Companion Firmware v1.21 Release candidate 1\r\n\r\n### What's new\r\n\r\n- **Live Location Sharing** — broadcast your position over the mesh as `[LOC]` messages, **movement-gated**, to a channel or a single contact. Others who share theirs show up as pins on the map with live **distance/bearing in Nearby Nodes**, and a **status-bar indicator** appears while your own share is active. `[LOC]` is parsed in DMs, channel messages **and room messages**; DM shares name the sender.\r\n- **Locator** (geofence) — arm a geofence around a **target** — a saved waypoint *or* a person (their live `[LOC]` or last-known position) — and get an alert when you **arrive/leave** or they get **near/far**, with an optional **homing beeper** that ticks faster the closer you get (and overrides a muted buzzer). Arm it from **Tools › Locator** or straight from **Nearby Nodes** / **Waypoints**; pick the target from a list (favourites first, then any contact), and clear it via a **\"None\"** entry. The active target is drawn as a **flag** on the map.\r\n- **One active target across Locator / Navigate / Map** — a single **\"Set as target\"** action everywhere, backed by a shared resolver that prefers a live `[LOC]` share over the last-advertised GPS, so the three features always agree on where you're headed.\r\n- **Follow live contacts** — **Navigate** to a contact who is live-sharing and the view **follows them as they move**, adding an **ETA** line. **Quick-share** your own position straight from the Map.\r\n- **Map & status-bar upgrades** — the home mini-map gains a **north marker** and a **scale tick**; the status line shows the tracked-node count and, with a fix, an **arrow + distance to the nearest tracked contact** (e.g. `Track:3 →120m`); a **GPS fix icon** sits in the top status bar (boxed once a fix is valid, plain while searching), shown only on GPS boards while **GPS** is enabled in Settings.\r\n- **Trail auto-pause** — recording **freezes on stops** (banking elapsed time and breaking the map line across the idle gap) and **resumes on movement** without ending the session; the home-screen blink keeps going while paused.\r\n- **Collapsible Tools** — tools are grouped into fold-in-place **Location / Comms / System** sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses **page-indicator icons** instead of dots.\r\n- **Waypoint coordinate editor** — add a waypoint by scroll-editing its latitude/longitude digit by digit.\r\n\r\n### Fixes\r\n\r\n- **Critical — low-heap hang and contact loss on RAM-tight builds.** With `MAX_CONTACTS=350` and `OFFLINE_QUEUE_SIZE=256` the device ran with very little free heap; an allocation in the input/menu path could then fail and **hang the UI** (notably when entering Diagnostics), and a crash or reset mid-save could **wipe all contacts**. Fixed by two independent changes:\r\n  - **Right-sized message-history rings** — the on-device scrollback rings were halved (96→48 channel, 64→32 DM), recovering **~14 KB of free heap** (measured 3 → 17 KB). History is RAM-only, so the only cost is shorter on-device scrollback.\r\n  - **Atomic persistence** — contacts, channels and prefs are now written to a temp file and **atomically renamed** into place; an interrupted save (crash, reset, full flash) leaves the previous good file intact instead of truncating it.\r\n- **USB host stall** — `Serial.write()` is bounded so a stalled USB host can no longer hang the device indefinitely.\r\n\r\n### Under the hood\r\n\r\n- **Streaming trail simplification** — GPS points are simplified as they're recorded via a fixed-corridor (Reumann–Witkam) pass: straight runs collapse to their two endpoints while curves stay bounded to within the **Min dist** tolerance of the real track, so the 512-point buffer covers a far longer route than a flat point budget would suggest.\r\n- A UITask-decoupled active-target resolver (`resolvePersonPos` / `activeTargetPos`) replaces the duplicated target-resolution logic that lived sepa\n…",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.21 Release candidate 1</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Live Location Sharing</strong> — broadcast your position over the mesh as <code>[LOC]</code> messages, <strong>movement-gated</strong>, to a channel or a single contact. Others who share theirs show up as pins on the map with live <strong>distance/bearing in Nearby Nodes</strong>, and a <strong>status-bar indicator</strong> appears while your own share is active. <code>[LOC]</code> is parsed in DMs, channel messages <strong>and room messages</strong>; DM shares name the sender.</li>\n<li><strong>Locator</strong> (geofence) — arm a geofence around a <strong>target</strong> — a saved waypoint <em>or</em> a person (their live <code>[LOC]</code> or last-known position) — and get an alert when you <strong>arrive/leave</strong> or they get <strong>near/far</strong>, with an optional <strong>homing beeper</strong> that ticks faster the closer you get (and overrides a muted buzzer). Arm it from <strong>Tools › Locator</strong> or straight from <strong>Nearby Nodes</strong> / <strong>Waypoints</strong>; pick the target from a list (favourites first, then any contact), and clear it via a <strong>\"None\"</strong> entry. The active target is drawn as a <strong>flag</strong> on the map.</li>\n<li><strong>One active target across Locator / Navigate / Map</strong> — a single <strong>\"Set as target\"</strong> action everywhere, backed by a shared resolver that prefers a live <code>[LOC]</code> share over the last-advertised GPS, so the three features always agree on where you're headed.</li>\n<li><strong>Follow live contacts</strong> — <strong>Navigate</strong> to a contact who is live-sharing and the view <strong>follows them as they move</strong>, adding an <strong>ETA</strong> line. <strong>Quick-share</strong> your own position straight from the Map.</li>\n<li><strong>Map &amp; status-bar upgrades</strong> — the home mini-map gains a <strong>north marker</strong> and a <strong>scale tick</strong>; the status line shows the tracked-node count and, with a fix, an <strong>arrow + distance to the nearest tracked contact</strong> (e.g. <code>Track:3 →120m</code>); a <strong>GPS fix icon</strong> sits in the top status bar (boxed once a fix is valid, plain while searching), shown only on GPS boards while <strong>GPS</strong> is enabled in Settings.</li>\n<li><strong>Trail auto-pause</strong> — recording <strong>freezes on stops</strong> (banking elapsed time and breaking the map line across the idle gap) and <strong>resumes on movement</strong> without ending the session; the home-screen blink keeps going while paused.</li>\n<li><strong>Collapsible Tools</strong> — tools are grouped into fold-in-place <strong>Location / Comms / System</strong> sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses <strong>page-indicator icons</strong> instead of dots.</li>\n<li><strong>Waypoint coordinate editor</strong> — add a waypoint by scroll-editing its latitude/longitude digit by digit.</li>\n</ul>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Critical — low-heap hang and contact loss on RAM-tight builds.</strong> With <code>MAX_CONTACTS=350</code> and <code>OFFLINE_QUEUE_SIZE=256</code> the device ran with very little free heap; an allocation in the input/menu path could then fail and <strong>hang the UI</strong> (notably when entering Diagnostics), and a crash or reset mid-save could <strong>wipe all contacts</strong>. Fixed by two independent changes:<ul>\n<li><strong>Right-sized message-history rings</strong> — the on-device scrollback rings were halved (96→48 channel, 64→32 DM), recovering <strong>~14 KB of free heap</strong> (measured 3 → 17 KB). History is RAM-only, so the only cost is shorter on-device scrollback.</li>\n<li><strong>Atomic persistence</strong> — contacts, channels and prefs are now written to a temp file and <strong>atomically renamed</strong> into place; an interrupted save (crash, reset, full flash) leaves the previous good file intact instead of truncating it.</li>\n</ul>\n</li>\n<li><strong>USB host stall</strong> — <code>Serial.write()</code> is bounded so a stalled USB host can no longer hang the device indefinitely.</li>\n</ul>\n<h3>Under the hood</h3>\n<ul>\n<li><strong>Streaming trail simplification</strong> — GPS points are simplified as they're recorded via a fixed-corridor (Reumann–Witkam) pass: straight runs collapse to their two endpoints while curves stay bounded to within the <strong>Min dist</strong> tolerance of the real track, so the 512-point buffer covers a far longer route than a flat point budget would suggest.</li>\n<li>A UITask-decoupled active-target resolver (<code>resolvePersonPos</code> / <code>activeTargetPos</code>) replaces the duplicated target-resolution logic that lived sepa\n…</li>\n</ul>\n"
    },
    {
      "version": "v1.20",
      "name": "Solo v1.20",
      "datetime": "2026-06-22T08:51:38Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.20",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.20\r\n\r\n### What's new\r\n\r\n- **Repeater mode** — a solo companion can now opt in to relaying mesh traffic, configured from a dedicated **Tools › Repeater** screen that consolidates the toggle, the forwarding filters, live forwarding stats, and a separate radio profile:\r\n  - **Forwarding filters** (all flood-only, off by default) — *skip-advert* (don't re-flood the highest-volume advert traffic), *max-hops* (drop a flood once it has travelled too far), *yield* (extra retransmit-delay so a mobile node defers to better-sited fixed repeaters), and *min-SNR* (don't re-flood marginal fringe packets). Plus **overhear suppression**, which cancels a queued retransmit if a peer relays the same packet first.\r\n  - **Dedicated radio profile** — an optional \"Custom\" Freq/SF/BW/CR used only while relaying, separate from the companion's own network and band-matched to the companion frequency by default. It's applied everywhere a radio change can happen (boot, on-device toggle, app-driven `CMD_SET_RADIO_PARAMS`, Settings edits) so the device never silently relays on the wrong params.\r\n  - While relaying, **Adaptive Power Control is pinned to the ceiling** and **duty-cycle RX is forced off** — a repeater needs to hear and relay at consistent power.\r\n- **Radio settings overhaul** (Settings › Radio) — **16 community-suggested presets** plus manual Freq/SF/BW/CR tuning (digit-by-digit frequency editor), and **4 persisted user preset slots**. Presets and the manual editor are now **shared between Settings and the Repeater screen** — a preset saved from either place shows up in both, and you can **save the current profile as a named preset** or **delete one** from either screen.\r\n- **On-device Diagnostics** (Tools › Diagnostics) — a single scrollable screen showing packet counts by category (RX/TX), radio noise floor / RSSI / SNR, packet-pool free count and outbound queue length, actually-forwarded packet count, uptime, and live heap/stack headroom, with a reset-counters popup.\r\n\r\n### Fixes\r\n\r\n- **Channel storage hardening** — `saveChannels()` skips unused (all-zero) slots, so `/channels2` holds only configured channels instead of always writing ~2.7 KB; and `findChannelIdx()` rejects an all-zero secret so a corrupted/empty channel can't match an unused slot and misroute messages.\r\n- **e-ink UI scaling** — self-sizing popup menu scaled for landscape e-ink (no stray header gap, tighter row tiling); popup menu uses the shared proportional scroll indicator instead of raw `^`/`v` glyphs and stops the selection bar before the scrollbar gutter; compass tape ticks/pointer and trail-map markers scale for e-ink, with wrap-around map navigation.\r\n- **Joystick rotation** is now persisted on e-ink builds.\r\n- **Trail capacity guard** — a `static_assert` fails the build if `TrailStore::CAPACITY` ever outgrows the `uint16_t` save-header count, instead of silently truncating.\r\n\r\n### Under the hood\r\n\r\n- Packet pool bumped 16 → 32 so queued retransmits no longer starve incoming-packet allocation while relaying.\r\n- Shared, UITask-decoupled `RadioPresetPicker` and `RadioParamsEditor` (plus `nearestBwIndex()` in `RadioPresets.h`) replace ~6 duplicated methods and several state fields per screen.\r\n- Mesh `Dispatcher` gains generic per-payload-type RX/TX counters and pool-free / queue-length getters; a new `DeviceDiag` helper reports nRF52 heap (linker-symbol + `sbrk`) and stack (FreeRTOS high-water-mark) headroom.\r\n- `build.sh` tolerates control characters in `pio project config`'s JSON dump.",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.20</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Repeater mode</strong> — a solo companion can now opt in to relaying mesh traffic, configured from a dedicated <strong>Tools › Repeater</strong> screen that consolidates the toggle, the forwarding filters, live forwarding stats, and a separate radio profile:<ul>\n<li><strong>Forwarding filters</strong> (all flood-only, off by default) — <em>skip-advert</em> (don't re-flood the highest-volume advert traffic), <em>max-hops</em> (drop a flood once it has travelled too far), <em>yield</em> (extra retransmit-delay so a mobile node defers to better-sited fixed repeaters), and <em>min-SNR</em> (don't re-flood marginal fringe packets). Plus <strong>overhear suppression</strong>, which cancels a queued retransmit if a peer relays the same packet first.</li>\n<li><strong>Dedicated radio profile</strong> — an optional \"Custom\" Freq/SF/BW/CR used only while relaying, separate from the companion's own network and band-matched to the companion frequency by default. It's applied everywhere a radio change can happen (boot, on-device toggle, app-driven <code>CMD_SET_RADIO_PARAMS</code>, Settings edits) so the device never silently relays on the wrong params.</li>\n<li>While relaying, <strong>Adaptive Power Control is pinned to the ceiling</strong> and <strong>duty-cycle RX is forced off</strong> — a repeater needs to hear and relay at consistent power.</li>\n</ul>\n</li>\n<li><strong>Radio settings overhaul</strong> (Settings › Radio) — <strong>16 community-suggested presets</strong> plus manual Freq/SF/BW/CR tuning (digit-by-digit frequency editor), and <strong>4 persisted user preset slots</strong>. Presets and the manual editor are now <strong>shared between Settings and the Repeater screen</strong> — a preset saved from either place shows up in both, and you can <strong>save the current profile as a named preset</strong> or <strong>delete one</strong> from either screen.</li>\n<li><strong>On-device Diagnostics</strong> (Tools › Diagnostics) — a single scrollable screen showing packet counts by category (RX/TX), radio noise floor / RSSI / SNR, packet-pool free count and outbound queue length, actually-forwarded packet count, uptime, and live heap/stack headroom, with a reset-counters popup.</li>\n</ul>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Channel storage hardening</strong> — <code>saveChannels()</code> skips unused (all-zero) slots, so <code>/channels2</code> holds only configured channels instead of always writing ~2.7 KB; and <code>findChannelIdx()</code> rejects an all-zero secret so a corrupted/empty channel can't match an unused slot and misroute messages.</li>\n<li><strong>e-ink UI scaling</strong> — self-sizing popup menu scaled for landscape e-ink (no stray header gap, tighter row tiling); popup menu uses the shared proportional scroll indicator instead of raw <code>^</code>/<code>v</code> glyphs and stops the selection bar before the scrollbar gutter; compass tape ticks/pointer and trail-map markers scale for e-ink, with wrap-around map navigation.</li>\n<li><strong>Joystick rotation</strong> is now persisted on e-ink builds.</li>\n<li><strong>Trail capacity guard</strong> — a <code>static_assert</code> fails the build if <code>TrailStore::CAPACITY</code> ever outgrows the <code>uint16_t</code> save-header count, instead of silently truncating.</li>\n</ul>\n<h3>Under the hood</h3>\n<ul>\n<li>Packet pool bumped 16 → 32 so queued retransmits no longer starve incoming-packet allocation while relaying.</li>\n<li>Shared, UITask-decoupled <code>RadioPresetPicker</code> and <code>RadioParamsEditor</code> (plus <code>nearestBwIndex()</code> in <code>RadioPresets.h</code>) replace ~6 duplicated methods and several state fields per screen.</li>\n<li>Mesh <code>Dispatcher</code> gains generic per-payload-type RX/TX counters and pool-free / queue-length getters; a new <code>DeviceDiag</code> helper reports nRF52 heap (linker-symbol + <code>sbrk</code>) and stack (FreeRTOS high-water-mark) headroom.</li>\n<li><code>build.sh</code> tolerates control characters in <code>pio project config</code>'s JSON dump.</li>\n</ul>\n"
    },
    {
      "version": "v1.19",
      "name": "Solo v1.19",
      "datetime": "2026-06-16T08:11:43Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.19",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.19\r\n\r\n### What's new\r\n\r\n- **Message delivery status** — outgoing messages now show an end-to-end delivery marker, auto-scaled to the font (legible on landscape e-ink), in both the history list and the fullscreen view:\r\n  - **Direct messages** (and room servers): pending → delivered (✓) → failed (✗), driven by the real end-to-end ACK. While pending, a row of dots shows one per send so auto-resend progress is visible.\r\n  - **Auto-resend** — a pending DM whose ACK times out is re-sent automatically (reusing the original timestamp) until resends run out. Configurable count under Settings › Messages › Resend (0–5, default 2). Runs in the background, independent of which screen is open; incoming duplicates from retries are dropped.\r\n  - **Channels** — ✓ appears only once a repeater echo confirms the message was relayed into the mesh. No echo is normal (flood has no recipient ACK), so no pending/fail is shown.\r\n- **Auto-reply bot overhaul** — the trigger/reply bot grows into a small auto-responder:\r\n  - **Query commands** — a DM or monitored-channel message is scanned for `!` tokens (`!ping !batt !loc !time !temp !hops !status !help`) and answered in one combined reply.\r\n  - **Away / reply-to-all** — a lone `*` trigger replies to every message.\r\n  - **Separate DM and channel triggers**, each with its own reply text.\r\n  - **Quiet hours** — silence push replies during a chosen window (wraps midnight).\r\n  - **Throttling & anti-loop** — per-contact DM throttle so one sender can't starve others; channel echo guard so the bot never answers itself; reply counter shown in the bot screen header.\r\n- **Keyboard overhaul** — one shared keyboard across all screens (reclaims duplicate RAM), icon keys (⇧ caps, ⎵ space, ⌫ delete, ✓ OK), and a second **symbols page** toggled with `#@`/`abc`.\r\n- **UI refresh**\r\n  - Proportional **scrollbar** with up/down triangle caps replaces the old `^`/`v` arrows, scaling with the font (1× OLED, 2× landscape e-ink); used by every scrollable list and the fullscreen message view. The redundant `>` selection marker is gone and rows shifted left to reclaim space.\r\n  - Status-bar single-letter indicators (M/B/A/G) replaced with scalable **mini-icons** (mute, bluetooth, advert, trail).\r\n- **Nearby Nodes reorganized** — one list over two sources (stored contacts + live discover scan) with a unified detail/action menu. Type filter and sort are independent axes and persist across re-entry; the active filter is shown in the title and in empty-list messages.\r\n- **Tools › Trail reorganized** — a short two-level action menu (Hold Enter) replaces the flat ~12-item list; view-aware settings; a fitted **square map grid**; and the waypoint manager split out into its own component. No change to trail recording itself.\r\n- **OTA updates** — each solo release now ships a DFU `.zip` (`solo-<ver>-<device>-ota.zip`) for over-the-air / BLE-DFU updates, alongside the `.uf2` for USB flashing.\r\n\r\n### Fixes\r\n\r\n- **GPS battery drain on shutdown** — GPS is powered off before `SYSTEMOFF`, and uses the correct active-level (`!PIN_GPS_EN_ACTIVE`) instead of a hardcoded level.\r\n- **Buzzer octave 8** — the RTTTL parser now fully accepts octave 8 instead of clamping it away (which could leak a digit into the next note's duration).\r\n- **Trail file robustness** — `Waypoint`/trail readers check every header read, so a truncated file is rejected instead of using a garbage count.\r\n\r\n### Under the hood\r\n\r\n- OTA DFU zip is named and attached to releases by the `_solo_dual` build workflow; the per-build Actions artifact already carried it.\r\n- Large UI consolidation: shared `drawList` / header / key-decode helpers, deduplicated status-bar indicators, reusable scalable mini-icon facility (`icons.h`), and an audit-pass cleanup premoving dead code and redundant scroll-clamp logic.",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.19</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Message delivery status</strong> — outgoing messages now show an end-to-end delivery marker, auto-scaled to the font (legible on landscape e-ink), in both the history list and the fullscreen view:<ul>\n<li><strong>Direct messages</strong> (and room servers): pending → delivered (✓) → failed (✗), driven by the real end-to-end ACK. While pending, a row of dots shows one per send so auto-resend progress is visible.</li>\n<li><strong>Auto-resend</strong> — a pending DM whose ACK times out is re-sent automatically (reusing the original timestamp) until resends run out. Configurable count under Settings › Messages › Resend (0–5, default 2). Runs in the background, independent of which screen is open; incoming duplicates from retries are dropped.</li>\n<li><strong>Channels</strong> — ✓ appears only once a repeater echo confirms the message was relayed into the mesh. No echo is normal (flood has no recipient ACK), so no pending/fail is shown.</li>\n</ul>\n</li>\n<li><strong>Auto-reply bot overhaul</strong> — the trigger/reply bot grows into a small auto-responder:<ul>\n<li><strong>Query commands</strong> — a DM or monitored-channel message is scanned for <code>!</code> tokens (<code>!ping !batt !loc !time !temp !hops !status !help</code>) and answered in one combined reply.</li>\n<li><strong>Away / reply-to-all</strong> — a lone <code>*</code> trigger replies to every message.</li>\n<li><strong>Separate DM and channel triggers</strong>, each with its own reply text.</li>\n<li><strong>Quiet hours</strong> — silence push replies during a chosen window (wraps midnight).</li>\n<li><strong>Throttling &amp; anti-loop</strong> — per-contact DM throttle so one sender can't starve others; channel echo guard so the bot never answers itself; reply counter shown in the bot screen header.</li>\n</ul>\n</li>\n<li><strong>Keyboard overhaul</strong> — one shared keyboard across all screens (reclaims duplicate RAM), icon keys (⇧ caps, ⎵ space, ⌫ delete, ✓ OK), and a second <strong>symbols page</strong> toggled with <code>#@</code>/<code>abc</code>.</li>\n<li><strong>UI refresh</strong><ul>\n<li>Proportional <strong>scrollbar</strong> with up/down triangle caps replaces the old <code>^</code>/<code>v</code> arrows, scaling with the font (1× OLED, 2× landscape e-ink); used by every scrollable list and the fullscreen message view. The redundant <code>&gt;</code> selection marker is gone and rows shifted left to reclaim space.</li>\n<li>Status-bar single-letter indicators (M/B/A/G) replaced with scalable <strong>mini-icons</strong> (mute, bluetooth, advert, trail).</li>\n</ul>\n</li>\n<li><strong>Nearby Nodes reorganized</strong> — one list over two sources (stored contacts + live discover scan) with a unified detail/action menu. Type filter and sort are independent axes and persist across re-entry; the active filter is shown in the title and in empty-list messages.</li>\n<li><strong>Tools › Trail reorganized</strong> — a short two-level action menu (Hold Enter) replaces the flat ~12-item list; view-aware settings; a fitted <strong>square map grid</strong>; and the waypoint manager split out into its own component. No change to trail recording itself.</li>\n<li><strong>OTA updates</strong> — each solo release now ships a DFU <code>.zip</code> (<code>solo-&lt;ver&gt;-&lt;device&gt;-ota.zip</code>) for over-the-air / BLE-DFU updates, alongside the <code>.uf2</code> for USB flashing.</li>\n</ul>\n<h3>Fixes</h3>\n<ul>\n<li><strong>GPS battery drain on shutdown</strong> — GPS is powered off before <code>SYSTEMOFF</code>, and uses the correct active-level (<code>!PIN_GPS_EN_ACTIVE</code>) instead of a hardcoded level.</li>\n<li><strong>Buzzer octave 8</strong> — the RTTTL parser now fully accepts octave 8 instead of clamping it away (which could leak a digit into the next note's duration).</li>\n<li><strong>Trail file robustness</strong> — <code>Waypoint</code>/trail readers check every header read, so a truncated file is rejected instead of using a garbage count.</li>\n</ul>\n<h3>Under the hood</h3>\n<ul>\n<li>OTA DFU zip is named and attached to releases by the <code>_solo_dual</code> build workflow; the per-build Actions artifact already carried it.</li>\n<li>Large UI consolidation: shared <code>drawList</code> / header / key-decode helpers, deduplicated status-bar indicators, reusable scalable mini-icon facility (<code>icons.h</code>), and an audit-pass cleanup premoving dead code and redundant scroll-clamp logic.</li>\n</ul>\n"
    },
    {
      "version": "v1.18",
      "name": "Solo v1.18",
      "datetime": "2026-06-14T08:22:51Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.18",
      "prerelease": false,
      "notes": "## MeshCore Solo Companion Firmware v1.18\r\n\r\n### New device support\r\n\r\n- **GAT562 30S Mesh Kit** — the firmware now supports the GAT562 30S alongside the Wio Tracker L1 family. Pre-built `.uf2` files for all supported devices are published with each release — see the [Supported Devices](https://github.com/MarekZegare4/MeshCore-Solo#supported-devices) table.\r\n\r\n### What's new\r\n\r\n- **GAT562 30S Mesh Kit support** — see above.\r\n- **Battery saving (radio)** — two new independent toggles under Settings › Radio:\r\n  - **Pwr save** — hardware duty-cycle receive (SX126x `SetRxDutyCycle`): the radio cycles RX↔sleep autonomously and wakes on a preamble, cutting average RX current with only a small increase in receive latency\r\n  - **Auto pwr** — Adaptive Power Control: trims TX power on strong links (based on ACK SNR) and ramps back up on weak or lost links; the home screen shows the live transmit power\r\n- **BLE disconnect icon fix** — the BLE status icon now updates immediately when the connection drops (e.g. out of range, supervision timeout). Previously it could stay active until the next UI polling cycle.\r\n- **Bot trigger preserves case** — the auto-reply trigger phrase is now stored exactly as typed. Matching remains case-insensitive, so `Ping`, `ping` and `PING` all trigger the bot, but the trigger no longer gets silently lowercased when saved.\r\n- **Screenshot support in all solo builds** — `ENABLE_SCREENSHOT` is now enabled in every solo firmware build. No need to use a separate `_dev` environment. Use the [Solo Tools](https://marekzegare4.github.io/Solo-tools/) web app to capture screenshots directly from the browser.\r\n\r\n\r\n### Under the hood\r\n\r\n- CI matrix for solo firmware builds is now fully dynamic — new devices are picked up automatically from `platformio.ini` based on the `_solo_dual` env suffix, no workflow changes required.\r\n- `AbstractUITask::onBLEDisconnected()` virtual hook added — called by `setHasConnection()` on transition to disconnected; `UITask` overrides it to set `_next_refresh = 0`.\r\n- `build.sh` gains `build-solo-firmwares` command, backed by `build_all_firmwares_by_suffix \"_solo_dual\"`.",
      "notesHtml": "<h2>MeshCore Solo Companion Firmware v1.18</h2>\n<h3>New device support</h3>\n<ul>\n<li><strong>GAT562 30S Mesh Kit</strong> — the firmware now supports the GAT562 30S alongside the Wio Tracker L1 family. Pre-built <code>.uf2</code> files for all supported devices are published with each release — see the <a href=\"https://github.com/MarekZegare4/MeshCore-Solo#supported-devices\" target=\"_blank\" rel=\"noopener noreferrer\">Supported Devices</a> table.</li>\n</ul>\n<h3>What's new</h3>\n<ul>\n<li><strong>GAT562 30S Mesh Kit support</strong> — see above.</li>\n<li><strong>Battery saving (radio)</strong> — two new independent toggles under Settings › Radio:<ul>\n<li><strong>Pwr save</strong> — hardware duty-cycle receive (SX126x <code>SetRxDutyCycle</code>): the radio cycles RX↔sleep autonomously and wakes on a preamble, cutting average RX current with only a small increase in receive latency</li>\n<li><strong>Auto pwr</strong> — Adaptive Power Control: trims TX power on strong links (based on ACK SNR) and ramps back up on weak or lost links; the home screen shows the live transmit power</li>\n</ul>\n</li>\n<li><strong>BLE disconnect icon fix</strong> — the BLE status icon now updates immediately when the connection drops (e.g. out of range, supervision timeout). Previously it could stay active until the next UI polling cycle.</li>\n<li><strong>Bot trigger preserves case</strong> — the auto-reply trigger phrase is now stored exactly as typed. Matching remains case-insensitive, so <code>Ping</code>, <code>ping</code> and <code>PING</code> all trigger the bot, but the trigger no longer gets silently lowercased when saved.</li>\n<li><strong>Screenshot support in all solo builds</strong> — <code>ENABLE_SCREENSHOT</code> is now enabled in every solo firmware build. No need to use a separate <code>_dev</code> environment. Use the <a href=\"https://marekzegare4.github.io/Solo-tools/\" target=\"_blank\" rel=\"noopener noreferrer\">Solo Tools</a> web app to capture screenshots directly from the browser.</li>\n</ul>\n<h3>Under the hood</h3>\n<ul>\n<li>CI matrix for solo firmware builds is now fully dynamic — new devices are picked up automatically from <code>platformio.ini</code> based on the <code>_solo_dual</code> env suffix, no workflow changes required.</li>\n<li><code>AbstractUITask::onBLEDisconnected()</code> virtual hook added — called by <code>setHasConnection()</code> on transition to disconnected; <code>UITask</code> overrides it to set <code>_next_refresh = 0</code>.</li>\n<li><code>build.sh</code> gains <code>build-solo-firmwares</code> command, backed by <code>build_all_firmwares_by_suffix \"_solo_dual\"</code>.</li>\n</ul>\n"
    },
    {
      "version": "v1.17",
      "name": "Solo v1.17",
      "datetime": "2026-06-09T15:33:39Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.17",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Solo Firmware v1.17\r\n\r\n### What's new\r\n\r\n- **Nearby Nodes — navigate & save waypoints from the list** — the context menu now exposes _Navigate_ and _Save waypoint_ directly from the Nearby list and detail view, so you no longer have to open the separate Tools → Waypoints screen. Long-press Options in the detail view also opens a _Ping_ submenu.\r\n- **Nearby Nodes — TIME sort filter** — a new `[TIME]` filter sorts contacts by last-seen time (most recent first) instead of distance, useful when GPS is unavailable.\r\n- **Battery indicator calibrated** — the 100 % ceiling of the LiPo discharge curve was corrected from 4200 mV to 4170 mV, matching what the board's charger actually delivers.\r\n- **Advert sound scope control** — a new _Sound → Advert_ setting lets you choose whether advert notifications play for all nodes or only direct (zero-hop) neighbours, cutting noise on busy meshes.\r\n- **Sound slot \"None\" option** — DM, channel and advert melody slots can now be set to _None_ to silence that notification category entirely without muting everything.\r\n- **Mark-as-read feedback** — marking messages read (per-contact or per-channel) now shows a brief _\"N marked read\"_ confirmation on screen.\r\n- **[Web tool] GPX Downloader** — a standalone web page for downloading saved GPX trails from the device over the browser's Web Serial API, no desktop app required.\r\n\r\n### Under the hood\r\n\r\n- `SoundNotifier` extracted from `UITask::notify()` — all buzzer/melody logic lives in one place, reducing future merge conflict surface with upstream.\r\n- `KeyboardWidget` is now a single shared instance across screens (saves ~1.5 KB heap).\r\n- `onDiscoveredAdvert` extracted as a separate virtual so upstream `onDiscoveredContact` keeps its original 4-parameter signature.",
      "notesHtml": "<h2>Wio Tracker L1 — Solo Firmware v1.17</h2>\n<h3>What's new</h3>\n<ul>\n<li><strong>Nearby Nodes — navigate &amp; save waypoints from the list</strong> — the context menu now exposes <em>Navigate</em> and <em>Save waypoint</em> directly from the Nearby list and detail view, so you no longer have to open the separate Tools → Waypoints screen. Long-press Options in the detail view also opens a <em>Ping</em> submenu.</li>\n<li><strong>Nearby Nodes — TIME sort filter</strong> — a new <code>[TIME]</code> filter sorts contacts by last-seen time (most recent first) instead of distance, useful when GPS is unavailable.</li>\n<li><strong>Battery indicator calibrated</strong> — the 100 % ceiling of the LiPo discharge curve was corrected from 4200 mV to 4170 mV, matching what the board's charger actually delivers.</li>\n<li><strong>Advert sound scope control</strong> — a new <em>Sound → Advert</em> setting lets you choose whether advert notifications play for all nodes or only direct (zero-hop) neighbours, cutting noise on busy meshes.</li>\n<li><strong>Sound slot \"None\" option</strong> — DM, channel and advert melody slots can now be set to <em>None</em> to silence that notification category entirely without muting everything.</li>\n<li><strong>Mark-as-read feedback</strong> — marking messages read (per-contact or per-channel) now shows a brief <em>\"N marked read\"</em> confirmation on screen.</li>\n<li><strong>[Web tool] GPX Downloader</strong> — a standalone web page for downloading saved GPX trails from the device over the browser's Web Serial API, no desktop app required.</li>\n</ul>\n<h3>Under the hood</h3>\n<ul>\n<li><code>SoundNotifier</code> extracted from <code>UITask::notify()</code> — all buzzer/melody logic lives in one place, reducing future merge conflict surface with upstream.</li>\n<li><code>KeyboardWidget</code> is now a single shared instance across screens (saves ~1.5 KB heap).</li>\n<li><code>onDiscoveredAdvert</code> extracted as a separate virtual so upstream <code>onDiscoveredContact</code> keeps its original 4-parameter signature.</li>\n</ul>\n"
    },
    {
      "version": "v1.16",
      "name": "Solo v1.16",
      "datetime": "2026-06-06T16:35:39Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.16",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Solo Firmware v1.16\r\n\r\nRebases the Solo fork onto upstream MeshCore **v1.16.0** (254 commits)\r\n\r\n### What's new (from upstream)\r\n\r\n- **NRF52 power-saving** — the companion now puts the MCU to sleep whenever there's no pending work, instead of looping continuously between events.\r\n- **Better reception of longer messages at low spreading factors** — the LoRa preamble is now 32 (was 16) for SF below 9, which makes longer frames more reliable on weak links.\r\n- **More robust sensors** — the I²C sensor subsystem was rewritten to probe the bus before touching any device, so an absent or misbehaving sensor can no longer hang or crash the node.\r\n- **Charging-aware shutdown** — the device no longer auto-shuts-down on low battery while it's on external power, and shows a shutdown warning on OLED.\r\n- **New companion command** for sending raw packets, plus assorted CLI additions (`flood.max.advert`, `flood.max.unscoped`, region hierarchy) and bounds-checking fixes that the phone app and repeaters benefit from.\r\n- **Battery-voltage reading fix** carried in from upstream.",
      "notesHtml": "<h2>Wio Tracker L1 — Solo Firmware v1.16</h2>\n<p>Rebases the Solo fork onto upstream MeshCore <strong>v1.16.0</strong> (254 commits)</p>\n<h3>What's new (from upstream)</h3>\n<ul>\n<li><strong>NRF52 power-saving</strong> — the companion now puts the MCU to sleep whenever there's no pending work, instead of looping continuously between events.</li>\n<li><strong>Better reception of longer messages at low spreading factors</strong> — the LoRa preamble is now 32 (was 16) for SF below 9, which makes longer frames more reliable on weak links.</li>\n<li><strong>More robust sensors</strong> — the I²C sensor subsystem was rewritten to probe the bus before touching any device, so an absent or misbehaving sensor can no longer hang or crash the node.</li>\n<li><strong>Charging-aware shutdown</strong> — the device no longer auto-shuts-down on low battery while it's on external power, and shows a shutdown warning on OLED.</li>\n<li><strong>New companion command</strong> for sending raw packets, plus assorted CLI additions (<code>flood.max.advert</code>, <code>flood.max.unscoped</code>, region hierarchy) and bounds-checking fixes that the phone app and repeaters benefit from.</li>\n<li><strong>Battery-voltage reading fix</strong> carried in from upstream.</li>\n</ul>\n"
    },
    {
      "version": "v1.15.1",
      "name": "Solo v1.15.1",
      "datetime": "2026-06-05T11:31:47Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.15.1",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Solo Firmware v1.15.1\r\n\r\nHotfix for Bluetooth pairing and buzzer regressions in v1.15 (introduced by the Advert-sound change). No schema change — upgrade in place from v1.15.\r\n\r\n### Fixes\r\n\r\n- **Bluetooth pairing PIN is shown again** — on the published OLED + e-ink (dual BLE+USB) builds the pairing PIN was never drawn, so the phone asked for a code that wasn't displayed and pairing failed. The PIN now appears on the **Bluetooth** home page while BLE is on and not yet bonded.\r\n- **Auto buzzer mute works again** — in v1.15 \"Auto\" was effectively always muted on dual builds (the connection state was hardcoded true). It now mutes only when a companion app is actually connected — **BLE bonded or a host holding the USB serial port open** — and stays audible on charge-only / no host. (Plain serial monitors that assert DTR count as connected.)\r\n- **Bluetooth status indicator** — the top-bar BT dot again reflects a real BLE connection instead of showing connected permanently.\r\n- **New-message display wake** — the screen wakes for an incoming message again when no app is connected.\r\n\r\n### Background\r\n\r\nv1.15's advert-sound feature broadened the internal \"connected\" flag from BLE-bonded to *any* transport, but the dual interface always reports its send-fallback as connected — so everything keyed off \"connected\" (PIN prompt, Auto mute, BT indicator, message-wake) misbehaved. This release splits the two notions: BLE-specific UI uses the BLE bond state, while Auto mute / message-wake use a new \"app connected over BLE or USB\" check (USB detected via the CDC DTR line).",
      "notesHtml": "<h2>Wio Tracker L1 — Solo Firmware v1.15.1</h2>\n<p>Hotfix for Bluetooth pairing and buzzer regressions in v1.15 (introduced by the Advert-sound change). No schema change — upgrade in place from v1.15.</p>\n<h3>Fixes</h3>\n<ul>\n<li><strong>Bluetooth pairing PIN is shown again</strong> — on the published OLED + e-ink (dual BLE+USB) builds the pairing PIN was never drawn, so the phone asked for a code that wasn't displayed and pairing failed. The PIN now appears on the <strong>Bluetooth</strong> home page while BLE is on and not yet bonded.</li>\n<li><strong>Auto buzzer mute works again</strong> — in v1.15 \"Auto\" was effectively always muted on dual builds (the connection state was hardcoded true). It now mutes only when a companion app is actually connected — <strong>BLE bonded or a host holding the USB serial port open</strong> — and stays audible on charge-only / no host. (Plain serial monitors that assert DTR count as connected.)</li>\n<li><strong>Bluetooth status indicator</strong> — the top-bar BT dot again reflects a real BLE connection instead of showing connected permanently.</li>\n<li><strong>New-message display wake</strong> — the screen wakes for an incoming message again when no app is connected.</li>\n</ul>\n<h3>Background</h3>\n<p>v1.15's advert-sound feature broadened the internal \"connected\" flag from BLE-bonded to <em>any</em> transport, but the dual interface always reports its send-fallback as connected — so everything keyed off \"connected\" (PIN prompt, Auto mute, BT indicator, message-wake) misbehaved. This release splits the two notions: BLE-specific UI uses the BLE bond state, while Auto mute / message-wake use a new \"app connected over BLE or USB\" check (USB detected via the CDC DTR line).</p>\n"
    },
    {
      "version": "v1.15",
      "name": "Solo v1.15",
      "datetime": "2026-06-04T15:35:06Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.15",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Solo Firmware v1.15\r\n\r\nAdds a full **GPS navigation suite** on top of Solo v1.14 — the L1 becomes a standalone off-grid navigator, no phone required.\r\n\r\n### Highlights\r\n\r\n- **Waypoints** — mark your current spot or type coordinates, give it a short label, then get live bearing + distance back to it. Ideal for car / camp / water / a meeting point.\r\n- **GPS compass** — *Tools › Compass*: a heads-up heading tape derived from GPS course-over-ground. No magnetometer needed.\r\n- **Navigate to anything** — a saved waypoint, the start of your trail (backtrack), a node from Nearby Nodes, or a location someone texts you.\r\n- **Share & save locations over the mesh** — send a waypoint in a message; on the other end, navigate to or save any shared location with one menu.\r\n- **Global Units setting** — one Metric / Imperial switch (Settings › System) drives every distance and speed in the UI.\r\n- **Advert sound** — an optional audible \"in range\" heartbeat: the device chirps when it receives an advert from another node — pair it with Auto-Advert to keep tabs on a buddy hands-free.\r\n\r\n### Changes\r\n\r\n**Navigation (new)**\r\n\r\n- **Waypoints** — *Tools › Trail › Hold Enter*: **Mark here** drops one at the current GPS fix; **Waypoints** opens the list, which carries a synthetic **Trail start** backtrack row, a usage counter (`WAYPOINTS 3/16`), and a **+ Add by coords** row to enter a point by lat/lon/label with no fix required (hemisphere chosen with LEFT/RIGHT since the keyboard has no minus key). Per-waypoint **Rename / Delete / Send**, plus **Clear waypoints**. Stored in their own `/waypoints` file (16 max) — independent of the trail and **not** cleared by Reset trail.\r\n- **Navigate-to-point view** — distance plus two *absolute* bearings, **To:** (target) and **Hdg:** (your course over ground), compared by eye. Reused by waypoints, trail backtrack, Nearby-node navigation and message-shared locations.\r\n- **GPS compass** — *Tools › Compass*: a scrolling N..E..S..W heading tape under a fixed travel-direction pointer, with a large degrees + cardinal readout. Works whether or not a trail is recording.\r\n- **Navigate to a node** — Nearby Nodes detail → **Hold Enter** now opens an Options menu (**Navigate** / **Ping**); Navigate opens the bearing/distance view targeting the node's last-known position.\r\n- **Trail map as a live view** — the Map draws your current position and all waypoints continuously, even with no trail recording. While a trail exists it frames the recorded route and clamps far-off waypoints to the nearest edge (a distant mark can't blow up the scale); with no trail it auto-fits to your waypoints and position. Markers show the first two label characters, placed edge-aware so labels stay on-map.\r\n- **Navigate / save a shared location** — any message carrying a `lat,lon` (what `{loc}` inserts) or a `[WAY]lat,lon label` share offers **Navigate** and **Save waypoint** from its **Hold Enter** menu — on the history row or in fullscreen, for DMs and channels. **Send** on a waypoint shares it to a contact or channel, pre-filling the message to confirm.\r\n- **Waypoints in GPX** — the GPX export now includes saved waypoints as `<wpt>` elements (label → `<name>`, plus `<time>`) alongside the track, so they import as pins in OsmAnd / Garmin / GPX Studio.\r\n\r\n**Units**\r\n\r\n- **Global Metric / Imperial** (Settings › System) drives every distance and speed: Nearby Nodes, Trail (Summary, List deltas, waypoint distances), the navigate-to-point view, the trail min-distance gate (5/10/25/100 m ↔ 15/30/75/300 ft) and the map scale bar.\r\n- **Trail readout** — the action menu's old four-way km/h·mph·min/km·min/mi cycle is now a **Speed / Pace** toggle; the unit follows the global setting.\r\n\r\n**Notifications**\r\n\r\n- **Advert sound** — Settings › Sound gains an **AD sound** entry (built-in / Melody 1 / Melody 2). The device plays it whenever it receives an advert from any node; combined with Auto-Advert on both ends it acts as a hands-free \"still i\n…",
      "notesHtml": "<h2>Wio Tracker L1 — Solo Firmware v1.15</h2>\n<p>Adds a full <strong>GPS navigation suite</strong> on top of Solo v1.14 — the L1 becomes a standalone off-grid navigator, no phone required.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>Waypoints</strong> — mark your current spot or type coordinates, give it a short label, then get live bearing + distance back to it. Ideal for car / camp / water / a meeting point.</li>\n<li><strong>GPS compass</strong> — <em>Tools › Compass</em>: a heads-up heading tape derived from GPS course-over-ground. No magnetometer needed.</li>\n<li><strong>Navigate to anything</strong> — a saved waypoint, the start of your trail (backtrack), a node from Nearby Nodes, or a location someone texts you.</li>\n<li><strong>Share &amp; save locations over the mesh</strong> — send a waypoint in a message; on the other end, navigate to or save any shared location with one menu.</li>\n<li><strong>Global Units setting</strong> — one Metric / Imperial switch (Settings › System) drives every distance and speed in the UI.</li>\n<li><strong>Advert sound</strong> — an optional audible \"in range\" heartbeat: the device chirps when it receives an advert from another node — pair it with Auto-Advert to keep tabs on a buddy hands-free.</li>\n</ul>\n<h3>Changes</h3>\n<p><strong>Navigation (new)</strong></p>\n<ul>\n<li><strong>Waypoints</strong> — <em>Tools › Trail › Hold Enter</em>: <strong>Mark here</strong> drops one at the current GPS fix; <strong>Waypoints</strong> opens the list, which carries a synthetic <strong>Trail start</strong> backtrack row, a usage counter (<code>WAYPOINTS 3/16</code>), and a <strong>+ Add by coords</strong> row to enter a point by lat/lon/label with no fix required (hemisphere chosen with LEFT/RIGHT since the keyboard has no minus key). Per-waypoint <strong>Rename / Delete / Send</strong>, plus <strong>Clear waypoints</strong>. Stored in their own <code>/waypoints</code> file (16 max) — independent of the trail and <strong>not</strong> cleared by Reset trail.</li>\n<li><strong>Navigate-to-point view</strong> — distance plus two <em>absolute</em> bearings, <strong>To:</strong> (target) and <strong>Hdg:</strong> (your course over ground), compared by eye. Reused by waypoints, trail backtrack, Nearby-node navigation and message-shared locations.</li>\n<li><strong>GPS compass</strong> — <em>Tools › Compass</em>: a scrolling N..E..S..W heading tape under a fixed travel-direction pointer, with a large degrees + cardinal readout. Works whether or not a trail is recording.</li>\n<li><strong>Navigate to a node</strong> — Nearby Nodes detail → <strong>Hold Enter</strong> now opens an Options menu (<strong>Navigate</strong> / <strong>Ping</strong>); Navigate opens the bearing/distance view targeting the node's last-known position.</li>\n<li><strong>Trail map as a live view</strong> — the Map draws your current position and all waypoints continuously, even with no trail recording. While a trail exists it frames the recorded route and clamps far-off waypoints to the nearest edge (a distant mark can't blow up the scale); with no trail it auto-fits to your waypoints and position. Markers show the first two label characters, placed edge-aware so labels stay on-map.</li>\n<li><strong>Navigate / save a shared location</strong> — any message carrying a <code>lat,lon</code> (what <code>{loc}</code> inserts) or a <code>[WAY]lat,lon label</code> share offers <strong>Navigate</strong> and <strong>Save waypoint</strong> from its <strong>Hold Enter</strong> menu — on the history row or in fullscreen, for DMs and channels. <strong>Send</strong> on a waypoint shares it to a contact or channel, pre-filling the message to confirm.</li>\n<li><strong>Waypoints in GPX</strong> — the GPX export now includes saved waypoints as <code>&lt;wpt&gt;</code> elements (label → <code>&lt;name&gt;</code>, plus <code>&lt;time&gt;</code>) alongside the track, so they import as pins in OsmAnd / Garmin / GPX Studio.</li>\n</ul>\n<p><strong>Units</strong></p>\n<ul>\n<li><strong>Global Metric / Imperial</strong> (Settings › System) drives every distance and speed: Nearby Nodes, Trail (Summary, List deltas, waypoint distances), the navigate-to-point view, the trail min-distance gate (5/10/25/100 m ↔ 15/30/75/300 ft) and the map scale bar.</li>\n<li><strong>Trail readout</strong> — the action menu's old four-way km/h·mph·min/km·min/mi cycle is now a <strong>Speed / Pace</strong> toggle; the unit follows the global setting.</li>\n</ul>\n<p><strong>Notifications</strong></p>\n<ul>\n<li><strong>Advert sound</strong> — Settings › Sound gains an <strong>AD sound</strong> entry (built-in / Melody 1 / Melody 2). The device plays it whenever it receives an advert from any node; combined with Auto-Advert on both ends it acts as a hands-free \"still i\n…</li>\n</ul>\n"
    },
    {
      "version": "v1.14",
      "name": "Solo v1.14",
      "datetime": "2026-05-29T10:59:08Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.14",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Solo Firmware v1.14\r\n\r\nBased on MeshCore upstream v1.15.\r\n\r\n### Highlights\r\n\r\n- **Renamed Plus → Solo** — to better reflect that this firmware is designed for *off-grid, standalone* use without needing a companion app on the phone; release artefacts are now `solo-v1.14-oled.uf2` and `solo-v1.14-eink.uf2`\r\n- **E-ink screenshot support** — `tools/screenshot.py` now works with both OLED and the e-ink panel; auto-detects rotation 0–3 and uses GxEPD2's visible dimensions; build with `-D ENABLE_SCREENSHOT`\r\n- **Battery percentage field** — new `Batt %` option for the Clock page dashboard, now sharing the same LiPo discharge curve and `low_batt_mv` cutoff as the top-bar indicator (so both readings agree)\r\n- **Channel favourites** — mark individual channels as favourites from the channel context menu; new Settings › Contacts filter to hide non-favourite channels\r\n- **Context menu cycling unified** — LEFT/RIGHT now cycles values everywhere (Notif, Melody, Fav, Duration, BPM) without closing the popup; ENTER reserved for one-shot actions\r\n- **Popup menus expand to fit the screen** — on portrait e-ink up to 16 items fit without scrolling; on OLED items are now hard-capped to what physically fits\r\n\r\n### Changes\r\n\r\n**New features**\r\n- **E-ink screenshot** — `WioTrackerL1Eink_companion_dual_dev` env enables capture; protocol header widened to 11 bytes (display type, rotation, uint16 width/height/chunk fields) so it scales to any GxEPD2 panel and rotation\r\n- **Dashboard `Batt %` field** — new Clock-page option computed from the same piecewise LiPo curve used by the top-bar battery indicator\r\n- **Channel favourites** — `ch_fav_bitmask` in prefs; toggle from Channel context menu; Settings › Contacts › Channels filter (all / favourites only)\r\n- **GPS trail — scale grid on map** — toggle from the Trail action menu (Grid row); cycles with LEFT/RIGHT now (previously ENTER only)\r\n- **Ringtone editor migrated to PopupMenu** — Duration and BPM now cycle in-place with LEFT/RIGHT; separate BPM+/BPM- rows removed\r\n\r\n**Fixes**\r\n- **OLED joystick rotation** — enforce reset moved after prefs load, so stale e-ink rotation values no longer reverse joystick mapping on OLED builds (`FEAT_JOYSTICK_ROTATION_SETTING=0`)\r\n- **First melody note duration** — preview-only side effect that shortened the first note in `playMelody()` no longer corrupts the stored sequence\r\n- **Home pages migration** — pages added in this release (Favourites, Trail) are appended to stored `page_order` instead of being hidden; SHUTDOWN is evicted from a full order to make room for required pages\r\n- **Pin picker fallback** — pressing `+` on an empty Favourites tile with no starred contacts and no recent DMs now lists all chat contacts instead of showing \"No fav contacts\"\r\n- **Popup menus on OLED** — height-clamped to what fits on screen (max 4 items at 64 px), so long context menus no longer draw outside the panel\r\n- **Trail action menu** — Grid toggle now also works with LEFT/RIGHT (not just ENTER); Export labels shortened to `Export (live)` / `Export (saved)` to fit\r\n- **E-ink default font** — unknown-character fallback rectangle aligned with the text cell baseline instead of one pixel below\r\n- **Build** — added `DisplayDriver::getBuffer`/`getBufferSize` virtuals so MyMesh no longer needs to know about concrete display types",
      "notesHtml": "<h2>Wio Tracker L1 — Solo Firmware v1.14</h2>\n<p>Based on MeshCore upstream v1.15.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>Renamed Plus → Solo</strong> — to better reflect that this firmware is designed for <em>off-grid, standalone</em> use without needing a companion app on the phone; release artefacts are now <code>solo-v1.14-oled.uf2</code> and <code>solo-v1.14-eink.uf2</code></li>\n<li><strong>E-ink screenshot support</strong> — <code>tools/screenshot.py</code> now works with both OLED and the e-ink panel; auto-detects rotation 0–3 and uses GxEPD2's visible dimensions; build with <code>-D ENABLE_SCREENSHOT</code></li>\n<li><strong>Battery percentage field</strong> — new <code>Batt %</code> option for the Clock page dashboard, now sharing the same LiPo discharge curve and <code>low_batt_mv</code> cutoff as the top-bar indicator (so both readings agree)</li>\n<li><strong>Channel favourites</strong> — mark individual channels as favourites from the channel context menu; new Settings › Contacts filter to hide non-favourite channels</li>\n<li><strong>Context menu cycling unified</strong> — LEFT/RIGHT now cycles values everywhere (Notif, Melody, Fav, Duration, BPM) without closing the popup; ENTER reserved for one-shot actions</li>\n<li><strong>Popup menus expand to fit the screen</strong> — on portrait e-ink up to 16 items fit without scrolling; on OLED items are now hard-capped to what physically fits</li>\n</ul>\n<h3>Changes</h3>\n<p><strong>New features</strong></p>\n<ul>\n<li><strong>E-ink screenshot</strong> — <code>WioTrackerL1Eink_companion_dual_dev</code> env enables capture; protocol header widened to 11 bytes (display type, rotation, uint16 width/height/chunk fields) so it scales to any GxEPD2 panel and rotation</li>\n<li><strong>Dashboard <code>Batt %</code> field</strong> — new Clock-page option computed from the same piecewise LiPo curve used by the top-bar battery indicator</li>\n<li><strong>Channel favourites</strong> — <code>ch_fav_bitmask</code> in prefs; toggle from Channel context menu; Settings › Contacts › Channels filter (all / favourites only)</li>\n<li><strong>GPS trail — scale grid on map</strong> — toggle from the Trail action menu (Grid row); cycles with LEFT/RIGHT now (previously ENTER only)</li>\n<li><strong>Ringtone editor migrated to PopupMenu</strong> — Duration and BPM now cycle in-place with LEFT/RIGHT; separate BPM+/BPM- rows removed</li>\n</ul>\n<p><strong>Fixes</strong></p>\n<ul>\n<li><strong>OLED joystick rotation</strong> — enforce reset moved after prefs load, so stale e-ink rotation values no longer reverse joystick mapping on OLED builds (<code>FEAT_JOYSTICK_ROTATION_SETTING=0</code>)</li>\n<li><strong>First melody note duration</strong> — preview-only side effect that shortened the first note in <code>playMelody()</code> no longer corrupts the stored sequence</li>\n<li><strong>Home pages migration</strong> — pages added in this release (Favourites, Trail) are appended to stored <code>page_order</code> instead of being hidden; SHUTDOWN is evicted from a full order to make room for required pages</li>\n<li><strong>Pin picker fallback</strong> — pressing <code>+</code> on an empty Favourites tile with no starred contacts and no recent DMs now lists all chat contacts instead of showing \"No fav contacts\"</li>\n<li><strong>Popup menus on OLED</strong> — height-clamped to what fits on screen (max 4 items at 64 px), so long context menus no longer draw outside the panel</li>\n<li><strong>Trail action menu</strong> — Grid toggle now also works with LEFT/RIGHT (not just ENTER); Export labels shortened to <code>Export (live)</code> / <code>Export (saved)</code> to fit</li>\n<li><strong>E-ink default font</strong> — unknown-character fallback rectangle aligned with the text cell baseline instead of one pixel below</li>\n<li><strong>Build</strong> — added <code>DisplayDriver::getBuffer</code>/<code>getBufferSize</code> virtuals so MyMesh no longer needs to know about concrete display types</li>\n</ul>\n"
    },
    {
      "version": "v1.13",
      "name": "Wio Tracker L1 Firmware v1.13",
      "datetime": "2026-05-26T14:00:21Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.13",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Plus Firmware v1.13\r\n\r\nBased on MeshCore upstream v1.15.\r\n\r\n### Highlights\r\n\r\n- **Favourites dial** — new home page with a 2×3 grid of pinned contacts; Enter opens the DM directly, pin/unpin from the contact context menu in the DM list\r\n- **GPS trail** — Tools › Trail records your route in a RAM ring (512 points); three views cycle with LEFT/RIGHT: Summary (distance, time, avg speed/pace), Map (auto-fit with segment markers), List (per-point timestamps and deltas); Hold Enter for Start/Stop, Save/Load to flash, GPX export over USB Serial, and settings (min-distance gate, speed units)\r\n- **Mark-all-read** — Hold Enter on the DM / Channels / Rooms mode-select screen to mark everything in that category read at once\r\n- **Unicode messages on both displays** — Cyrillic, Greek, Polish, Czech, Baltic and other Latin Extended scripts now render correctly in messages, keyboard preview and reply prefix on both OLED and e-ink when the Lemon font is enabled\r\n- **E-ink full-refresh interval** — Settings › Display › Full rfsh lets you pick how many partial refreshes happen before a cleansing full refresh (off / 5 / 10 / 20 / 30); reduces visible ghosting on long sessions *(e-ink only)*\r\n- **Faster long-message rendering** — fullscreen message view now wraps text in O(n) instead of O(n²); noticeably snappier on long messages, especially with the Lemon font on e-ink\r\n\r\n### Changes\r\n\r\n**New features**\r\n- **Favourites dial home page** — 2×3 grid of pinned contacts; Enter on a filled tile opens the DM, Enter on an empty tile opens an in-place picker (upstream-favourited contacts first, then recent DMs); LEFT/RIGHT reorders in the Home Pages settings\r\n- **GPS trail** — background sampling with configurable min-distance gate (5 / 10 / 25 / 100 m); segments tracked across start/stop cycles; single flash slot `/trail` (binary, magic-versioned header); GPX 1.1 export streams live ring or saved file straight to USB Serial; `G` indicator in status bar blinks while active\r\n- **Mark-all-read** — Hold Enter on the message-type screen clears unread counters for the highlighted mode (DM / Channels / Rooms)\r\n- **Settings sections collapsible** — all sections start collapsed; Enter on a section header expands/collapses it, making long lists (Home Pages, Messages) much faster to navigate\r\n- E-ink: `Full rfsh` setting in Settings › Display — controls how many partial refreshes occur before a cleansing full panel refresh\r\n- Schema versioning of saved preferences — `/new_prefs` now carries a tail sentinel so older saves are detected and treated safely on load; file self-heals on next save\r\n\r\n**Fixes**\r\n- Sensors home page: Enter no longer accidentally toggles GPS on/off while viewing sensor readings\r\n- Upgrade from v1.11 with trail settings in flash: `trail_units_idx` was silently read from the old sentinel byte (giving \"min/mi\" instead of km/h default) — schema bumped to `0xC0DE0004`, corrupted value reset to 0 on mismatch\r\n- Lemon font now correctly decodes multi-byte UTF-8 on the e-ink display (Cyrillic, Greek, Polish accents, etc.); previously rendered as garbage glyphs\r\n- Keyboard preview translates UTF-8 through the active font path, so non-ASCII input shows correctly while typing\r\n- Reply path: the `@[nick]` prefix is now preserved verbatim — a nickname containing `{loc}` / `{time}` is no longer substituted as a placeholder\r\n- Home page order: validity flag prevents a junk byte in flash from being interpreted as a \"custom order\" state\r\n- E-ink: unknown-character fallback rectangle now aligns to the top of the text cell instead of sitting one pixel below the line\r\n- E-ink: Lemon glyphs at text size 2/3 (splash version, clock) no longer render at size 1 scale",
      "notesHtml": "<h2>Wio Tracker L1 — Plus Firmware v1.13</h2>\n<p>Based on MeshCore upstream v1.15.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>Favourites dial</strong> — new home page with a 2×3 grid of pinned contacts; Enter opens the DM directly, pin/unpin from the contact context menu in the DM list</li>\n<li><strong>GPS trail</strong> — Tools › Trail records your route in a RAM ring (512 points); three views cycle with LEFT/RIGHT: Summary (distance, time, avg speed/pace), Map (auto-fit with segment markers), List (per-point timestamps and deltas); Hold Enter for Start/Stop, Save/Load to flash, GPX export over USB Serial, and settings (min-distance gate, speed units)</li>\n<li><strong>Mark-all-read</strong> — Hold Enter on the DM / Channels / Rooms mode-select screen to mark everything in that category read at once</li>\n<li><strong>Unicode messages on both displays</strong> — Cyrillic, Greek, Polish, Czech, Baltic and other Latin Extended scripts now render correctly in messages, keyboard preview and reply prefix on both OLED and e-ink when the Lemon font is enabled</li>\n<li><strong>E-ink full-refresh interval</strong> — Settings › Display › Full rfsh lets you pick how many partial refreshes happen before a cleansing full refresh (off / 5 / 10 / 20 / 30); reduces visible ghosting on long sessions <em>(e-ink only)</em></li>\n<li><strong>Faster long-message rendering</strong> — fullscreen message view now wraps text in O(n) instead of O(n²); noticeably snappier on long messages, especially with the Lemon font on e-ink</li>\n</ul>\n<h3>Changes</h3>\n<p><strong>New features</strong></p>\n<ul>\n<li><strong>Favourites dial home page</strong> — 2×3 grid of pinned contacts; Enter on a filled tile opens the DM, Enter on an empty tile opens an in-place picker (upstream-favourited contacts first, then recent DMs); LEFT/RIGHT reorders in the Home Pages settings</li>\n<li><strong>GPS trail</strong> — background sampling with configurable min-distance gate (5 / 10 / 25 / 100 m); segments tracked across start/stop cycles; single flash slot <code>/trail</code> (binary, magic-versioned header); GPX 1.1 export streams live ring or saved file straight to USB Serial; <code>G</code> indicator in status bar blinks while active</li>\n<li><strong>Mark-all-read</strong> — Hold Enter on the message-type screen clears unread counters for the highlighted mode (DM / Channels / Rooms)</li>\n<li><strong>Settings sections collapsible</strong> — all sections start collapsed; Enter on a section header expands/collapses it, making long lists (Home Pages, Messages) much faster to navigate</li>\n<li>E-ink: <code>Full rfsh</code> setting in Settings › Display — controls how many partial refreshes occur before a cleansing full panel refresh</li>\n<li>Schema versioning of saved preferences — <code>/new_prefs</code> now carries a tail sentinel so older saves are detected and treated safely on load; file self-heals on next save</li>\n</ul>\n<p><strong>Fixes</strong></p>\n<ul>\n<li>Sensors home page: Enter no longer accidentally toggles GPS on/off while viewing sensor readings</li>\n<li>Upgrade from v1.11 with trail settings in flash: <code>trail_units_idx</code> was silently read from the old sentinel byte (giving \"min/mi\" instead of km/h default) — schema bumped to <code>0xC0DE0004</code>, corrupted value reset to 0 on mismatch</li>\n<li>Lemon font now correctly decodes multi-byte UTF-8 on the e-ink display (Cyrillic, Greek, Polish accents, etc.); previously rendered as garbage glyphs</li>\n<li>Keyboard preview translates UTF-8 through the active font path, so non-ASCII input shows correctly while typing</li>\n<li>Reply path: the <code>@[nick]</code> prefix is now preserved verbatim — a nickname containing <code>{loc}</code> / <code>{time}</code> is no longer substituted as a placeholder</li>\n<li>Home page order: validity flag prevents a junk byte in flash from being interpreted as a \"custom order\" state</li>\n<li>E-ink: unknown-character fallback rectangle now aligns to the top of the text cell instead of sitting one pixel below the line</li>\n<li>E-ink: Lemon glyphs at text size 2/3 (splash version, clock) no longer render at size 1 scale</li>\n</ul>\n"
    },
    {
      "version": "v1.12",
      "name": "Wio Tracker L1 Firmware v1.12",
      "datetime": "2026-05-24T18:55:09Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.12",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Plus Firmware v1.12\r\n\r\nBased on MeshCore upstream v1.15.\r\n\r\n### Highlights\r\n\r\n- **Unicode messages on both displays** — Cyrillic, Greek, Polish, Czech, Baltic and other Latin Extended scripts now render correctly in messages, keyboard preview and reply prefix on both OLED and e-ink when the Lemon font is enabled\r\n- **E-ink full-refresh interval** — Settings › Display › Full rfsh lets you pick how many partial refreshes happen before a cleansing full refresh (off / 5 / 10 / 20 / 30); reduces visible ghosting on long sessions *(e-ink only)*\r\n- **Faster long-message rendering** — fullscreen message view now wraps text in O(n) instead of O(n²); noticeably snappier on long messages, especially with the Lemon font on e-ink\r\n\r\n### Changes\r\n\r\n**New features**\r\n- E-ink: `Full rfsh` setting in Settings › Display — controls how many partial refreshes occur before a cleansing full panel refresh\r\n- Schema versioning of saved preferences — `/new_prefs` now carries a tail sentinel so older saves are detected and treated safely on load; file self-heals on next save\r\n\r\n**Fixes**\r\n- Lemon font now correctly decodes multi-byte UTF-8 on the e-ink display (Cyrillic, Greek, Polish accents, etc.); previously rendered as garbage glyphs\r\n- Keyboard preview translates UTF-8 through the active font path, so non-ASCII input shows correctly while typing\r\n- Reply path: the `@[nick]` prefix is now preserved verbatim — a nickname containing `{loc}` / `{time}` is no longer substituted as a placeholder\r\n- Home page order: validity flag prevents a junk byte in flash from being interpreted as a \"custom order\" state\r\n- E-ink: unknown-character fallback rectangle now aligns to the top of the text cell instead of sitting one pixel below the line\r\n- E-ink: Lemon glyphs at text size 2/3 (splash version, clock) no longer render at size 1 scale\r\n\r\n### Upgrade notes\r\n\r\n- Settings and message history are preserved across upgrades from v1.11\r\n- First boot after upgrade may log `prefs schema sentinel mismatch` over serial — expected, file is rewritten with the new sentinel on the next setting change",
      "notesHtml": "<h2>Wio Tracker L1 — Plus Firmware v1.12</h2>\n<p>Based on MeshCore upstream v1.15.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>Unicode messages on both displays</strong> — Cyrillic, Greek, Polish, Czech, Baltic and other Latin Extended scripts now render correctly in messages, keyboard preview and reply prefix on both OLED and e-ink when the Lemon font is enabled</li>\n<li><strong>E-ink full-refresh interval</strong> — Settings › Display › Full rfsh lets you pick how many partial refreshes happen before a cleansing full refresh (off / 5 / 10 / 20 / 30); reduces visible ghosting on long sessions <em>(e-ink only)</em></li>\n<li><strong>Faster long-message rendering</strong> — fullscreen message view now wraps text in O(n) instead of O(n²); noticeably snappier on long messages, especially with the Lemon font on e-ink</li>\n</ul>\n<h3>Changes</h3>\n<p><strong>New features</strong></p>\n<ul>\n<li>E-ink: <code>Full rfsh</code> setting in Settings › Display — controls how many partial refreshes occur before a cleansing full panel refresh</li>\n<li>Schema versioning of saved preferences — <code>/new_prefs</code> now carries a tail sentinel so older saves are detected and treated safely on load; file self-heals on next save</li>\n</ul>\n<p><strong>Fixes</strong></p>\n<ul>\n<li>Lemon font now correctly decodes multi-byte UTF-8 on the e-ink display (Cyrillic, Greek, Polish accents, etc.); previously rendered as garbage glyphs</li>\n<li>Keyboard preview translates UTF-8 through the active font path, so non-ASCII input shows correctly while typing</li>\n<li>Reply path: the <code>@[nick]</code> prefix is now preserved verbatim — a nickname containing <code>{loc}</code> / <code>{time}</code> is no longer substituted as a placeholder</li>\n<li>Home page order: validity flag prevents a junk byte in flash from being interpreted as a \"custom order\" state</li>\n<li>E-ink: unknown-character fallback rectangle now aligns to the top of the text cell instead of sitting one pixel below the line</li>\n<li>E-ink: Lemon glyphs at text size 2/3 (splash version, clock) no longer render at size 1 scale</li>\n</ul>\n<h3>Upgrade notes</h3>\n<ul>\n<li>Settings and message history are preserved across upgrades from v1.11</li>\n<li>First boot after upgrade may log <code>prefs schema sentinel mismatch</code> over serial — expected, file is rewritten with the new sentinel on the next setting change</li>\n</ul>\n"
    },
    {
      "version": "v1.11",
      "name": "Wio Tracker L1 Firmware v1.11",
      "datetime": "2026-05-23T22:53:09Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/v1.11",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Plus Firmware v1.11\r\n\r\nBased on MeshCore upstream v1.15.\r\n\r\n### Highlights\r\n\r\n- **Joystick rotation** — joystick input mapping can now be rotated independently of the display, useful in custom enclosures *(e-ink only)*\r\n- **Home screen page ordering** — all home pages including Clock can now be reordered and toggled in Settings › Home Pages; position indicators are shown immediately on first render\r\n- **Unified firmware branch** — OLED and e-ink builds are now maintained in a single branch; firmware files renamed to `WioTrackerL1_companion_dual` and `WioTrackerL1Eink_companion_dual`\r\n\r\n### Changes\r\n\r\n**New features**\r\n- E-ink: runtime joystick rotation setting in Settings › Display — rotates directional input 0° / 90° / 180° / 270° independently of display rotation\r\n- Settings › Home Pages: LEFT/RIGHT reorders any page in the navigation sequence; ENTER toggles pages ON/OFF (Settings and Messages are always visible and cannot be disabled)\r\n\r\n**Fixes**\r\n- Home Pages: several visibility and ordering bugs fixed\r\n- Display: unknown-character block rendering unified across OLED and e-ink builds\r\n\r\n**Build / CI**\r\n- Firmware environments renamed: `WioTrackerL1_companion_radio_dual_settings` → `WioTrackerL1_companion_dual`, `WioTrackerL1Eink_companion_radio_dual` → `WioTrackerL1Eink_companion_dual`\r\n- Workflow now triggers on `plus_*` tags and correctly injects firmware version into both build jobs",
      "notesHtml": "<h2>Wio Tracker L1 — Plus Firmware v1.11</h2>\n<p>Based on MeshCore upstream v1.15.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>Joystick rotation</strong> — joystick input mapping can now be rotated independently of the display, useful in custom enclosures <em>(e-ink only)</em></li>\n<li><strong>Home screen page ordering</strong> — all home pages including Clock can now be reordered and toggled in Settings › Home Pages; position indicators are shown immediately on first render</li>\n<li><strong>Unified firmware branch</strong> — OLED and e-ink builds are now maintained in a single branch; firmware files renamed to <code>WioTrackerL1_companion_dual</code> and <code>WioTrackerL1Eink_companion_dual</code></li>\n</ul>\n<h3>Changes</h3>\n<p><strong>New features</strong></p>\n<ul>\n<li>E-ink: runtime joystick rotation setting in Settings › Display — rotates directional input 0° / 90° / 180° / 270° independently of display rotation</li>\n<li>Settings › Home Pages: LEFT/RIGHT reorders any page in the navigation sequence; ENTER toggles pages ON/OFF (Settings and Messages are always visible and cannot be disabled)</li>\n</ul>\n<p><strong>Fixes</strong></p>\n<ul>\n<li>Home Pages: several visibility and ordering bugs fixed</li>\n<li>Display: unknown-character block rendering unified across OLED and e-ink builds</li>\n</ul>\n<p><strong>Build / CI</strong></p>\n<ul>\n<li>Firmware environments renamed: <code>WioTrackerL1_companion_radio_dual_settings</code> → <code>WioTrackerL1_companion_dual</code>, <code>WioTrackerL1Eink_companion_radio_dual</code> → <code>WioTrackerL1Eink_companion_dual</code></li>\n<li>Workflow now triggers on <code>plus_*</code> tags and correctly injects firmware version into both build jobs</li>\n</ul>\n"
    },
    {
      "version": "wio-tracker-v1.15-plus.1.10",
      "name": "Wio Tracker L1 Firmware v1.15-plus.1.10",
      "datetime": "2026-05-22T22:07:08Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/wio-tracker-v1.15-plus.1.10",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Plus Firmware v1.15-plus.1.10\r\n\r\nBased on MeshCore upstream v1.15.\r\n\r\n### Highlights\r\n\r\n- **E-ink display support** — the Wio Tracker L1 now has a dedicated e-ink firmware variant; all screens have been adapted for the 250 × 122 / 122 × 250 panel with full portrait and landscape support\r\n- **Home screen page ordering** — all home pages can now be reordered directly in Settings; Settings and Messages are always present and cannot be disabled\r\n- **Runtime font switcher** — choose between the default Adafruit font and the Lemon Unicode font in Settings › Display\r\n- **Single dual-serial firmware** — one build supports both BLE and USB serial; separate BLE/USB variants are retired\r\n- **Unified firmware** — the previously separate font-switcher build has been merged into the main firmware; there is now a single OLED build and a single e-ink build\r\n\r\n### Changes\r\n\r\n**New features**\r\n- E-ink firmware: new build target `WioTrackerL1Eink_companion_radio_dual` for Wio Tracker L1 with e-ink display\r\n- E-ink: all home screen pages (Clock, Recent, Radio, Bluetooth, Advert, Tools, Settings, Messages, Shutdown) adapted for the e-ink panel\r\n- E-ink: adaptive layout engine — all screens reflow correctly in both portrait (122 × 250) and landscape (250 × 122) orientations\r\n- E-ink: runtime display rotation setting in Settings › Display — applied immediately and persisted across reboots\r\n- E-ink: clock seconds suppressed by default to reduce panel refresh wear\r\n- E-ink: Lemon font support with pixel-accurate glyph scaling\r\n- Settings › Home Pages: LEFT/RIGHT reorders any page in the navigation sequence; ENTER toggles pages ON/OFF (except Settings and Messages, which are always visible)\r\n- Settings › Display: runtime font selection — Default (Adafruit) or Lemon (Unicode, pixel-accurate wrap)\r\n- Settings › Display: 12 h / 24 h clock format toggle (default 24 h)\r\n\r\n**Fixes**\r\n- MeshCore logo on splash screen is centre-cropped rather than overflowing in portrait mode\r\n- Lemon font glyphs now scale correctly with `setTextSize` on the lock screen clock\r\n- `use_lemon_font` preference is now persisted to flash and survives reboots\r\n- Strip `@[nick]` reply prefix from channel and DM history card previews\r\n\r\n**Build / CI**\r\n- Font-switcher firmware variant merged into the main OLED build — no separate download needed",
      "notesHtml": "<h2>Wio Tracker L1 — Plus Firmware v1.15-plus.1.10</h2>\n<p>Based on MeshCore upstream v1.15.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>E-ink display support</strong> — the Wio Tracker L1 now has a dedicated e-ink firmware variant; all screens have been adapted for the 250 × 122 / 122 × 250 panel with full portrait and landscape support</li>\n<li><strong>Home screen page ordering</strong> — all home pages can now be reordered directly in Settings; Settings and Messages are always present and cannot be disabled</li>\n<li><strong>Runtime font switcher</strong> — choose between the default Adafruit font and the Lemon Unicode font in Settings › Display</li>\n<li><strong>Single dual-serial firmware</strong> — one build supports both BLE and USB serial; separate BLE/USB variants are retired</li>\n<li><strong>Unified firmware</strong> — the previously separate font-switcher build has been merged into the main firmware; there is now a single OLED build and a single e-ink build</li>\n</ul>\n<h3>Changes</h3>\n<p><strong>New features</strong></p>\n<ul>\n<li>E-ink firmware: new build target <code>WioTrackerL1Eink_companion_radio_dual</code> for Wio Tracker L1 with e-ink display</li>\n<li>E-ink: all home screen pages (Clock, Recent, Radio, Bluetooth, Advert, Tools, Settings, Messages, Shutdown) adapted for the e-ink panel</li>\n<li>E-ink: adaptive layout engine — all screens reflow correctly in both portrait (122 × 250) and landscape (250 × 122) orientations</li>\n<li>E-ink: runtime display rotation setting in Settings › Display — applied immediately and persisted across reboots</li>\n<li>E-ink: clock seconds suppressed by default to reduce panel refresh wear</li>\n<li>E-ink: Lemon font support with pixel-accurate glyph scaling</li>\n<li>Settings › Home Pages: LEFT/RIGHT reorders any page in the navigation sequence; ENTER toggles pages ON/OFF (except Settings and Messages, which are always visible)</li>\n<li>Settings › Display: runtime font selection — Default (Adafruit) or Lemon (Unicode, pixel-accurate wrap)</li>\n<li>Settings › Display: 12 h / 24 h clock format toggle (default 24 h)</li>\n</ul>\n<p><strong>Fixes</strong></p>\n<ul>\n<li>MeshCore logo on splash screen is centre-cropped rather than overflowing in portrait mode</li>\n<li>Lemon font glyphs now scale correctly with <code>setTextSize</code> on the lock screen clock</li>\n<li><code>use_lemon_font</code> preference is now persisted to flash and survives reboots</li>\n<li>Strip <code>@[nick]</code> reply prefix from channel and DM history card previews</li>\n</ul>\n<p><strong>Build / CI</strong></p>\n<ul>\n<li>Font-switcher firmware variant merged into the main OLED build — no separate download needed</li>\n</ul>\n"
    },
    {
      "version": "wio-tracker-v1.15-plus.1.9",
      "name": "Wio Tracker L1 Firmware v1.15-plus.1.9",
      "datetime": "2026-05-21T07:37:51Z",
      "url": "https://github.com/MarekZegare4/MeshCore-Solo/releases/tag/wio-tracker-v1.15-plus.1.9",
      "prerelease": false,
      "notes": "## Wio Tracker L1 — Plus Firmware v1.15-plus.1.9\r\n\r\nBased on MeshCore upstream v1.15.\r\n\r\n### Highlights\r\n\r\n- **Active node discovery** — the Nearby screen now sends a live discovery ping and displays responding nodes (repeaters, sensors, rooms) with RSSI, SNR and remote SNR. Tap Enter on a node for a full-screen detail view including the public key.\r\n\r\n### Changes\r\n\r\n**New features**\r\n- Nearby screen: active node discovery via `NODE_DISCOVER_REQ` replaces the old passive advert scan; nodes respond with name, type, RSSI and SNR data\r\n- Nearby screen: each discovered node is shown as a 2-line boxed card with RSSI, SNR and remote SNR\r\n- Nearby screen: navigate discovered nodes with UP/DOWN; press Enter to open a full-screen detail view showing name, public key (base64), RSSI, SNR, remote SNR and known/new status",
      "notesHtml": "<h2>Wio Tracker L1 — Plus Firmware v1.15-plus.1.9</h2>\n<p>Based on MeshCore upstream v1.15.</p>\n<h3>Highlights</h3>\n<ul>\n<li><strong>Active node discovery</strong> — the Nearby screen now sends a live discovery ping and displays responding nodes (repeaters, sensors, rooms) with RSSI, SNR and remote SNR. Tap Enter on a node for a full-screen detail view including the public key.</li>\n</ul>\n<h3>Changes</h3>\n<p><strong>New features</strong></p>\n<ul>\n<li>Nearby screen: active node discovery via <code>NODE_DISCOVER_REQ</code> replaces the old passive advert scan; nodes respond with name, type, RSSI and SNR data</li>\n<li>Nearby screen: each discovered node is shown as a 2-line boxed card with RSSI, SNR and remote SNR</li>\n<li>Nearby screen: navigate discovered nodes with UP/DOWN; press Enter to open a full-screen detail view showing name, public key (base64), RSSI, SNR, remote SNR and known/new status</li>\n</ul>\n"
    }
  ],
  "changelogSource": "github",
  "changelogUpdatedAt": "2026-07-29T20:58:56.656Z",
  "deviceFamilies": [
    {
      "id": "seeed-wio-tracker-l1",
      "label": "Wio Tracker L1"
    },
    {
      "id": "gatiot-gat562",
      "label": "GAT-IoT GAT562"
    }
  ],
  "primaryFamily": {
    "id": "seeed-wio-tracker-l1",
    "label": "Wio Tracker L1"
  },
  "scopeGroup": null
}
