{
  "id": "meshcore-lowpower",
  "name": "MeshCore Low-Power",
  "type": "fork",
  "maintainer": "dt267",
  "description": "A power-optimised MeshCore firmware with deep sleep, a full companion display UI with multi-transport connectivity (BLE + USB + WiFi in a single build), advanced radio and network controls, a browser-based configuration portal, and battery-life profiling — built for multi-day off-grid operation.\n",
  "repository": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4",
  "license": "MIT",
  "status": "active",
  "lifecycle": "active",
  "maturity": "beta",
  "distribution": "community",
  "lineage": {
    "kind": "fork",
    "upstreamFirmwareId": "meshcore-official",
    "upstreamRepository": "https://github.com/meshcore-dev/MeshCore"
  },
  "runtime": {
    "framework": "arduino",
    "language": "cpp"
  },
  "roles": [
    "companion",
    "repeater",
    "room-server"
  ],
  "features": [
    "Deep power optimisation with idle current profiling",
    "Unified BLE + USB + WiFi companion build (single binary)",
    "Browser-based configuration portal (backup, restore, flash, reboot)",
    "Companion backup/restore (preferences, WiFi credentials, presets)",
    "Adaptive Rx boosted gain on Heltec V4.2",
    "GPS constellation selection and runtime GPS update interval",
    "Low-battery protection and voltage reading",
    "Native multilingual display on Heltec T096 colour TFT",
    "KCT8103L FEM auto-detection on Heltec V4.3"
  ],
  "capabilities": {
    "protocol": {
      "meshcoreCompatible": true
    },
    "transports": {
      "ble": true,
      "usbSerial": true,
      "nativeTcp": true,
      "wifiAp": true
    },
    "operations": {
      "ota": true,
      "webFlasher": false
    },
    "networking": {
      "repeater": true,
      "roomServer": true,
      "observer": false,
      "kissModem": false
    },
    "hardware": {
      "gps": true,
      "display": true,
      "sensors": true,
      "lowPowerRx": true
    }
  },
  "devices": [
    {
      "id": "heltec-v3",
      "status": "supported"
    },
    {
      "id": "heltec-wsl3",
      "status": "supported"
    },
    {
      "id": "heltec-v4",
      "status": "supported"
    },
    {
      "id": "heltec-v4-exp",
      "status": "supported"
    },
    {
      "id": "heltec-e213",
      "status": "supported"
    },
    {
      "id": "heltec-e290",
      "status": "supported"
    },
    {
      "id": "heltec-paper",
      "status": "supported"
    },
    {
      "id": "heltec-t096",
      "status": "supported"
    },
    {
      "id": "xiao-esp32s3",
      "status": "supported"
    },
    {
      "id": "rak-4631",
      "status": "supported",
      "notes": "Uses RAK19003 base board for power profiling."
    },
    {
      "id": "uart-solar-node-station",
      "status": "supported",
      "notes": "Uses RAK4631 target; same as rak-4631."
    }
  ],
  "source": {
    "path": "data/firmwares/meshcore-lowpower/firmware.yaml",
    "updatedAt": "2026-06-22T21:31:07+02:00"
  },
  "latest_version": "1.16.dev_0621",
  "released": "2026-06-21",
  "releases": [
    {
      "version": "MeshCore-low-power-v1.16.dev_0621",
      "name": "MeshCore low power - v1.16.dev_0621",
      "datetime": "2026-06-21T07:24:05Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.16.dev_0621",
      "prerelease": false,
      "notes": "### v1.16_0621\r\n\r\n- **Configuration portal for Companion, Repeater, and Room Server — configure, back up, restore, and update firmware without the CLI.** *(ESP32 devices only)*\r\n\r\n  Open it the same way as before — `start ota` in the CLI, or **Start OTA** from the companion Settings menu. Previously this landed on a firmware-only upload page; it now opens the full configuration portal where you can configure, back up, restore, flash firmware, and reboot — all from one page in the browser.\r\n\r\n  The companion backup covers custom preferences (Quick Send presets, saved locations, channel hop limits, display settings, WiFi credentials,...) that upstream MeshCore doesn't have — handy when moving to a new device. For the Repeater and Room Server, this is the first time backup and restore are available at all — no more re-entering everything from scratch after a node failure or hardware swap.\r\n\r\n  The portal is password-protected. Companion: set one with `set portal.password` in the CLI. Repeater / Room Server: the existing admin password is used automatically.\r\n\r\n  The backup format is compatible with the official MeshCore app — upstream preferences in the backup can be restored by the app. Passwords are never written to backup files.\r\n\r\n- **Config portal AP: open network, login page, 1-client limit, 10-minute idle auto-shutdown.**\r\n\r\n  The WiFi AP is open (no AP password); access is gated by a browser login page using the portal password described above. Only one device can associate with the AP at a time. If no device connects within 10 minutes of the AP opening, it shuts down automatically.\r\n\r\n  <img alt=\"config-portal\" src=\"https://github.com/user-attachments/assets/92a088b9-49b3-40d1-8caa-fd3da634347b\" />\r\n\r\n\r\n- **Fix: full-flash (`_merged.bin`) images for Vision Master E213 and E290 were built with the wrong flash size.**\r\n\r\n  Both boards have 16 MB of flash, but their merged full-flash images were generated with an 8 MB flash-size header. The pre-merged images are now built with the correct 16 MB size. If you previously flashed an E213 or E290 using a `_merged.bin`, re-flash with the corrected image. OTA (`.bin`) updates were not affected.",
      "notesHtml": "<h3>v1.16_0621</h3>\n<ul>\n<li><p><strong>Configuration portal for Companion, Repeater, and Room Server — configure, back up, restore, and update firmware without the CLI.</strong> <em>(ESP32 devices only)</em></p>\n<p>Open it the same way as before — <code>start ota</code> in the CLI, or <strong>Start OTA</strong> from the companion Settings menu. Previously this landed on a firmware-only upload page; it now opens the full configuration portal where you can configure, back up, restore, flash firmware, and reboot — all from one page in the browser.</p>\n<p>The companion backup covers custom preferences (Quick Send presets, saved locations, channel hop limits, display settings, WiFi credentials,...) that upstream MeshCore doesn't have — handy when moving to a new device. For the Repeater and Room Server, this is the first time backup and restore are available at all — no more re-entering everything from scratch after a node failure or hardware swap.</p>\n<p>The portal is password-protected. Companion: set one with <code>set portal.password</code> in the CLI. Repeater / Room Server: the existing admin password is used automatically.</p>\n<p>The backup format is compatible with the official MeshCore app — upstream preferences in the backup can be restored by the app. Passwords are never written to backup files.</p>\n</li>\n<li><p><strong>Config portal AP: open network, login page, 1-client limit, 10-minute idle auto-shutdown.</strong></p>\n<p>The WiFi AP is open (no AP password); access is gated by a browser login page using the portal password described above. Only one device can associate with the AP at a time. If no device connects within 10 minutes of the AP opening, it shuts down automatically.</p>\n<img alt=\"config-portal\" src=\"https://github.com/user-attachments/assets/92a088b9-49b3-40d1-8caa-fd3da634347b\" /></li>\n<li><p><strong>Fix: full-flash (<code>_merged.bin</code>) images for Vision Master E213 and E290 were built with the wrong flash size.</strong></p>\n<p>Both boards have 16 MB of flash, but their merged full-flash images were generated with an 8 MB flash-size header. The pre-merged images are now built with the correct 16 MB size. If you previously flashed an E213 or E290 using a <code>_merged.bin</code>, re-flash with the corrected image. OTA (<code>.bin</code>) updates were not affected.</p>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.16.dev_0614",
      "name": "MeshCore low power - v1.16.dev_0614",
      "datetime": "2026-06-14T04:15:08Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.16.dev_0614",
      "prerelease": false,
      "notes": "### v1.16_0614\r\n\r\n- **New devices: Heltec Vision Master E213, Wireless Paper, and Vision Master E290 — full e-ink companion support (Companion, Repeater, Room Server).**\r\n\r\n  Three e-ink boards are now fully supported with the complete companion UI — Quick Send, Contacts, Settings, Saved Locations, GPS Trace, and message preview. Repeater and Room Server firmware are provided for all three.\r\n\r\n  - **Heltec Vision Master E213** *(author-tested, v1.1.1)*  — ESP32-S3 with a 2.13\" e-ink display (250×122 px), SX1262 LoRa, and a QuickLink I2C port. Has a second user button (GPIO21): press to scroll up in any list, or to go back — faster than double clicking the main button.\r\n  - **Heltec Wireless Paper** — ESP32-S3 with the same 2.13\" e-ink panel as the E213 in a more compact form factor. Shares the same companion UI and firmware variants as the E213. Single button only.\r\n  - **Heltec Vision Master E290** — ESP32-S3R8 with a larger 2.9\" e-ink display (296×128 px), SX1262 LoRa, and a QuickLink I2C port. Also has a second button (GPIO21) like the E213. The companion UI adapts automatically to the wider panel — more message lines and a larger clock on the Home screen.\r\n\r\n  **Common characteristics across all three e-ink boards:**\r\n  - **Always-on display** — e-ink retains content indefinitely without power; no screen timeout.\r\n  - **Native multilingual text** — Latin, Cyrillic, and Greek scripts render natively.\r\n  - **Font Weight setting** — choose between **Thin** and **Bold** via **Settings → Font Weight**. Preference is saved to flash.\r\n  - **I2C sensor support** — environment sensors can be connected via the QuickLink I2C port.\r\n\r\n- **Companion: unified BLE / USB / WiFi connection mode for all ESP32-S3 boards.**\r\n\r\n  All ESP32-S3 companion builds (Heltec V3, V4, E213, Wireless Paper, E290, XIAO S3) now ship as a single unified firmware image that supports all three connection transports: **BLE**, **USB serial**, and **WiFi TCP**. The active mode is saved to flash and selected at boot — no per-mode build is needed.\r\n\r\n  Switching is done via **Settings → Connection Mode**, which opens a direct selection screen listing all three modes with the current one marked `*`. Navigate to the desired mode and confirm — the device reboots into the new mode.\r\n\r\n  Alternatively, switch via [TerminalCLI](Companion_TerminalCLI_Commands.md): `set conn.mode wifi|ble|usb`. WiFi credentials are configured with `set wifi.ssid` / `set wifi.password`, or from the **OTA update page** which now includes a WiFi credentials form alongside the firmware upload button.\r\n\r\n  In WiFi mode, the node connects as a STA to your router and the Home screen shows the IP address and port. All three modes meet the low-power criteria of this repo.  \r\n\r\n- **Companion UI: Home screen always shows a large clock; message count shown in the header.**\r\n\r\n  The center of the Home screen now always shows the current time (`HH:MM`) in a large font — `MSG: N` is gone. If there are messages stored in memory, their count and a small envelope icon appear in the header (where the small clock used to be); the header is left empty when count is zero. The header clock is visible again on all other pages as before.\r\n\r\n  On e-ink displays (E213, Wireless Paper, E290), the clock is rendered in a large font; pairing pin or connection status appears at the bottom-left, and the date at the bottom-right. On OLED and T096, the layout is: large clock → date → connection status, stacked top to bottom.\r\n\r\n  Before the clock is synchronized with the app or GPS, the display shows uptime counting up from `00:00` since boot, consistent with the small header clock.\r\n\r\n- **Repeater/Room Server: flood hop limits now correctly ignore leading-zero path padding.**\r\n\r\n  Some senders limit how far a packet propagates by pre-filling the path with zero entries — a TTL trick used by custom firmware, and by companions in this firmware via `ch.hops`. Previously, repeaters counted these zeros as real relay hops, causi\n…",
      "notesHtml": "<h3>v1.16_0614</h3>\n<ul>\n<li><p><strong>New devices: Heltec Vision Master E213, Wireless Paper, and Vision Master E290 — full e-ink companion support (Companion, Repeater, Room Server).</strong></p>\n<p>Three e-ink boards are now fully supported with the complete companion UI — Quick Send, Contacts, Settings, Saved Locations, GPS Trace, and message preview. Repeater and Room Server firmware are provided for all three.</p>\n<ul>\n<li><strong>Heltec Vision Master E213</strong> <em>(author-tested, v1.1.1)</em>  — ESP32-S3 with a 2.13\" e-ink display (250×122 px), SX1262 LoRa, and a QuickLink I2C port. Has a second user button (GPIO21): press to scroll up in any list, or to go back — faster than double clicking the main button.</li>\n<li><strong>Heltec Wireless Paper</strong> — ESP32-S3 with the same 2.13\" e-ink panel as the E213 in a more compact form factor. Shares the same companion UI and firmware variants as the E213. Single button only.</li>\n<li><strong>Heltec Vision Master E290</strong> — ESP32-S3R8 with a larger 2.9\" e-ink display (296×128 px), SX1262 LoRa, and a QuickLink I2C port. Also has a second button (GPIO21) like the E213. The companion UI adapts automatically to the wider panel — more message lines and a larger clock on the Home screen.</li>\n</ul>\n<p><strong>Common characteristics across all three e-ink boards:</strong></p>\n<ul>\n<li><strong>Always-on display</strong> — e-ink retains content indefinitely without power; no screen timeout.</li>\n<li><strong>Native multilingual text</strong> — Latin, Cyrillic, and Greek scripts render natively.</li>\n<li><strong>Font Weight setting</strong> — choose between <strong>Thin</strong> and <strong>Bold</strong> via <strong>Settings → Font Weight</strong>. Preference is saved to flash.</li>\n<li><strong>I2C sensor support</strong> — environment sensors can be connected via the QuickLink I2C port.</li>\n</ul>\n</li>\n<li><p><strong>Companion: unified BLE / USB / WiFi connection mode for all ESP32-S3 boards.</strong></p>\n<p>All ESP32-S3 companion builds (Heltec V3, V4, E213, Wireless Paper, E290, XIAO S3) now ship as a single unified firmware image that supports all three connection transports: <strong>BLE</strong>, <strong>USB serial</strong>, and <strong>WiFi TCP</strong>. The active mode is saved to flash and selected at boot — no per-mode build is needed.</p>\n<p>Switching is done via <strong>Settings → Connection Mode</strong>, which opens a direct selection screen listing all three modes with the current one marked <code>*</code>. Navigate to the desired mode and confirm — the device reboots into the new mode.</p>\n<p>Alternatively, switch via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>: <code>set conn.mode wifi|ble|usb</code>. WiFi credentials are configured with <code>set wifi.ssid</code> / <code>set wifi.password</code>, or from the <strong>OTA update page</strong> which now includes a WiFi credentials form alongside the firmware upload button.</p>\n<p>In WiFi mode, the node connects as a STA to your router and the Home screen shows the IP address and port. All three modes meet the low-power criteria of this repo.  </p>\n</li>\n<li><p><strong>Companion UI: Home screen always shows a large clock; message count shown in the header.</strong></p>\n<p>The center of the Home screen now always shows the current time (<code>HH:MM</code>) in a large font — <code>MSG: N</code> is gone. If there are messages stored in memory, their count and a small envelope icon appear in the header (where the small clock used to be); the header is left empty when count is zero. The header clock is visible again on all other pages as before.</p>\n<p>On e-ink displays (E213, Wireless Paper, E290), the clock is rendered in a large font; pairing pin or connection status appears at the bottom-left, and the date at the bottom-right. On OLED and T096, the layout is: large clock → date → connection status, stacked top to bottom.</p>\n<p>Before the clock is synchronized with the app or GPS, the display shows uptime counting up from <code>00:00</code> since boot, consistent with the small header clock.</p>\n</li>\n<li><p><strong>Repeater/Room Server: flood hop limits now correctly ignore leading-zero path padding.</strong></p>\n<p>Some senders limit how far a packet propagates by pre-filling the path with zero entries — a TTL trick used by custom firmware, and by companions in this firmware via <code>ch.hops</code>. Previously, repeaters counted these zeros as real relay hops, causi\n…</p>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.16.dev_0607",
      "name": "MeshCore low power - v1.16.dev_0607",
      "datetime": "2026-06-07T05:01:31Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.16.dev_0607",
      "prerelease": false,
      "notes": "### v1.16_0607\r\n\r\n- **Companion UI: Native multilingual display on Heltec T096 (ST7735S)**\r\n\r\n  Node names and messages now render natively on the T096 color TFT — characters are displayed as-is instead of being converted to ASCII equivalents. Supported languages include all 31 from v1.14 plus additional scripts:\r\n\r\n  **Latin-based:** Catalan, Croatian, Czech, Danish, Dutch, Estonian, Finnish, French, German, Hungarian, Icelandic, Italian, Latvian, Lithuanian, Maltese, Norwegian, Polish, Portuguese, Romanian, Slovak, Slovenian, Spanish, Swedish, Turkish, Vietnamese, Welsh\r\n\r\n  **Cyrillic:** Belarusian, Bulgarian, Macedonian, Russian, Serbian, Ukrainian\r\n\r\n  **Greek:** Greek\r\n\r\n- **Companion UI: Contacts screen now includes room servers; request telemetry from any contact.**\r\n\r\n  Room servers appear in the contact list tagged `[R]`. Selecting any contact — chat node or room server — and long pressing opens an action menu: **Send message** or **Request telemetry**. Requesting telemetry displays the node's battery voltage and GPS coordinates (if present); long press to open the GPS Trace screen for that location.\r\n\r\n  GPS coordinates follow the **Pos. Format** selected in Settings (DD, UTM, or MGRS).\r\n\r\n  The message inbox group list now tags group/channel entries with `[G]` and room server entries with `[R]` for consistent visual distinction. Each room message shows the original author's name. When viewing a room message, long press to open the popup and select **Reply** to post back to the room (visible to all subscribers).\r\n\r\n  > **Private room servers:** messaging requires a prior login. Public rooms (no password) work without any login. For private rooms, log in once via the MeshCore app — if your account has admin rights on that room server, the session persists across reboots. Regular user sessions are not saved to flash and will require re-login after the room server reboots.\r\n\r\n- **Companion: switch the app connection between BLE and USB serial without reflashing.**\r\n\r\n  In USB mode the node behaves like a standard `usb` build — the PC app connects over the USB serial port directly. Toggle via **Settings → Connection Mode** on the display, or via TerminalCLI: `set conn.mode usb` / `set conn.mode ble`. The setting persists across reboots. BLE toggle is hidden in the Settings menu while USB mode is active.\r\n\r\n- **Repeater, Room Sever: hold user button 5 seconds to power off.**\r\n\r\n  Hold the user button for 5 seconds to power off the node — faster than reaching for the CLI when you're standing next to it. The LED blinks 5 times as a warning before shutdown.\r\n\r\n- **Repeater, Room Server: `advert.hops.max` default changed to 8; room server support added; `flood.max.advert` alias.**\r\n\r\n  `advert.hops.max` now defaults to `8` instead of `flood.max` — advert relay limiting is active out of the box without any configuration. Room servers now also enforce this limit (previously repeater-only). The command `flood.max.advert` is accepted as an alias for compatibility with upstream firmware.",
      "notesHtml": "<h3>v1.16_0607</h3>\n<ul>\n<li><p><strong>Companion UI: Native multilingual display on Heltec T096 (ST7735S)</strong></p>\n<p>Node names and messages now render natively on the T096 color TFT — characters are displayed as-is instead of being converted to ASCII equivalents. Supported languages include all 31 from v1.14 plus additional scripts:</p>\n<p><strong>Latin-based:</strong> Catalan, Croatian, Czech, Danish, Dutch, Estonian, Finnish, French, German, Hungarian, Icelandic, Italian, Latvian, Lithuanian, Maltese, Norwegian, Polish, Portuguese, Romanian, Slovak, Slovenian, Spanish, Swedish, Turkish, Vietnamese, Welsh</p>\n<p><strong>Cyrillic:</strong> Belarusian, Bulgarian, Macedonian, Russian, Serbian, Ukrainian</p>\n<p><strong>Greek:</strong> Greek</p>\n</li>\n<li><p><strong>Companion UI: Contacts screen now includes room servers; request telemetry from any contact.</strong></p>\n<p>Room servers appear in the contact list tagged <code>[R]</code>. Selecting any contact — chat node or room server — and long pressing opens an action menu: <strong>Send message</strong> or <strong>Request telemetry</strong>. Requesting telemetry displays the node's battery voltage and GPS coordinates (if present); long press to open the GPS Trace screen for that location.</p>\n<p>GPS coordinates follow the <strong>Pos. Format</strong> selected in Settings (DD, UTM, or MGRS).</p>\n<p>The message inbox group list now tags group/channel entries with <code>[G]</code> and room server entries with <code>[R]</code> for consistent visual distinction. Each room message shows the original author's name. When viewing a room message, long press to open the popup and select <strong>Reply</strong> to post back to the room (visible to all subscribers).</p>\n<blockquote>\n<p><strong>Private room servers:</strong> messaging requires a prior login. Public rooms (no password) work without any login. For private rooms, log in once via the MeshCore app — if your account has admin rights on that room server, the session persists across reboots. Regular user sessions are not saved to flash and will require re-login after the room server reboots.</p>\n</blockquote>\n</li>\n<li><p><strong>Companion: switch the app connection between BLE and USB serial without reflashing.</strong></p>\n<p>In USB mode the node behaves like a standard <code>usb</code> build — the PC app connects over the USB serial port directly. Toggle via <strong>Settings → Connection Mode</strong> on the display, or via TerminalCLI: <code>set conn.mode usb</code> / <code>set conn.mode ble</code>. The setting persists across reboots. BLE toggle is hidden in the Settings menu while USB mode is active.</p>\n</li>\n<li><p><strong>Repeater, Room Sever: hold user button 5 seconds to power off.</strong></p>\n<p>Hold the user button for 5 seconds to power off the node — faster than reaching for the CLI when you're standing next to it. The LED blinks 5 times as a warning before shutdown.</p>\n</li>\n<li><p><strong>Repeater, Room Server: <code>advert.hops.max</code> default changed to 8; room server support added; <code>flood.max.advert</code> alias.</strong></p>\n<p><code>advert.hops.max</code> now defaults to <code>8</code> instead of <code>flood.max</code> — advert relay limiting is active out of the box without any configuration. Room servers now also enforce this limit (previously repeater-only). The command <code>flood.max.advert</code> is accepted as an alias for compatibility with upstream firmware.</p>\n</li>\n</ul>\n"
    },
    {
      "version": "pre-release-Heltec-E213-Wireless-Paper-E290",
      "name": "pre-release Heltec E213, Wireless Paper, E290",
      "datetime": "2026-06-11T11:45:39Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/pre-release-Heltec-E213-Wireless-Paper-E290",
      "prerelease": true,
      "notes": "### v1.16_0611 pre-release for Heltec E213, Wireless Paper and E290\r\n\r\n- **New device: Heltec Vision Master E213 — full support (Companion, Repeater, Room Server).**\r\n\r\n  The Heltec Vision Master E213 is now fully supported. It is an ESP32-S3 based board with a 2.13\" e-ink display, SX1262 LoRa radio, and a USB-C port. The complete companion UI runs on the e-ink display — Quick Send, Contacts, Settings, Saved Locations, GPS Trace, and message preview. Repeater and Room Server firmware are also provided.\r\n\r\n  **Notable characteristics:**\r\n  - **Always-on e-ink display** — no screen timeout; the display retains its content indefinitely without power.\r\n  - **Native multilingual text** — Latin, Cyrillic, and Greek scripts render natively.\r\n  - **I2C sensor support** — environment sensors (temperature, humidity, pressure...) can be connected via the QuickLink I2C port.\r\n  - **Two user buttons** — the second button (GPIO21) makes navigation faster: press it to scroll up in any list, or to go back/exit any menu.\r\n\r\n- **New devices: Heltec Wireless Paper and Heltec Vision Master E290 — full support (Companion, Repeater, Room Server).**\r\n\r\n  Two new e-ink boards are now supported:\r\n\r\n  - **Heltec Wireless Paper** — ESP32-S3 with a 2.13\" e-ink display (same resolution as E213), SX1262 LoRa radio, and a compact form factor. Shares the same companion UI and firmware variants as E213.\r\n\r\n  - **Heltec Vision Master E290** — ESP32-S3R8 with a larger 2.9\" e-ink display (296×128), SX1262 LoRa radio, and a QuickLink I2C port for external sensors. The companion UI adapts automatically to the wider, taller display — showing more message lines and better-spaced layouts compared to the 2.13\" boards.",
      "notesHtml": "<h3>v1.16_0611 pre-release for Heltec E213, Wireless Paper and E290</h3>\n<ul>\n<li><p><strong>New device: Heltec Vision Master E213 — full support (Companion, Repeater, Room Server).</strong></p>\n<p>The Heltec Vision Master E213 is now fully supported. It is an ESP32-S3 based board with a 2.13\" e-ink display, SX1262 LoRa radio, and a USB-C port. The complete companion UI runs on the e-ink display — Quick Send, Contacts, Settings, Saved Locations, GPS Trace, and message preview. Repeater and Room Server firmware are also provided.</p>\n<p><strong>Notable characteristics:</strong></p>\n<ul>\n<li><strong>Always-on e-ink display</strong> — no screen timeout; the display retains its content indefinitely without power.</li>\n<li><strong>Native multilingual text</strong> — Latin, Cyrillic, and Greek scripts render natively.</li>\n<li><strong>I2C sensor support</strong> — environment sensors (temperature, humidity, pressure...) can be connected via the QuickLink I2C port.</li>\n<li><strong>Two user buttons</strong> — the second button (GPIO21) makes navigation faster: press it to scroll up in any list, or to go back/exit any menu.</li>\n</ul>\n</li>\n<li><p><strong>New devices: Heltec Wireless Paper and Heltec Vision Master E290 — full support (Companion, Repeater, Room Server).</strong></p>\n<p>Two new e-ink boards are now supported:</p>\n<ul>\n<li><p><strong>Heltec Wireless Paper</strong> — ESP32-S3 with a 2.13\" e-ink display (same resolution as E213), SX1262 LoRa radio, and a compact form factor. Shares the same companion UI and firmware variants as E213.</p>\n</li>\n<li><p><strong>Heltec Vision Master E290</strong> — ESP32-S3R8 with a larger 2.9\" e-ink display (296×128), SX1262 LoRa radio, and a QuickLink I2C port for external sensors. The companion UI adapts automatically to the wider, taller display — showing more message lines and better-spaced layouts compared to the 2.13\" boards.</p>\n</li>\n</ul>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0531",
      "name": "MeshCore low power - v1.15.dev_0531",
      "datetime": "2026-05-31T02:29:03Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0531",
      "prerelease": false,
      "notes": "### v1.15_0531\r\n\r\n- **Full support for Heltec T096 — companion, repeater, and room server**\r\n\r\n  The Heltec T096 is now fully supported across all node types. The hardware is an nRF52840-based board with an SX1262 radio, KCT8103L FEM, UC6580 GPS, and a 0.96\" 160×80 color TFT display (ST7735S).\r\n\r\n  The complete companion UI — Quick Send, Contacts, Settings, GPS, Saved Locations, GPS Trace, and message preview — runs on the color TFT.\r\n\r\n  **Differences from other supported boards:**\r\n\r\n  - **Color TFT display.** All companion pages render in color on the 160×80 ST7735S — unlike other supported boards which use a monochrome OLED.\r\n\r\n  - **Brightness control.** A **Brightness** item in the Settings page adjusts the TFT backlight intensity: `25` → `50` → `75` → `100`. Setting is saved to flash.\r\n\r\n  - **KCT8103L FEM — same as Heltec V4.3.** `set radio.rxgain on` / `off` works identically.\r\n\r\n  - **UC6580 GPS.** `gps.interval` works the same as on Heltec V4. Constellation selection (`gps.mode`) uses a different set of options:\r\n\r\n    | Value | Constellations |\r\n    |---|---|\r\n    | `1` | GPS L1 only |\r\n    | `2` | All-system L1 (GPS+BDS+GLO+GAL) |\r\n    | `3` | All-system + QZSS dual-band *(default)* |\r\n\r\n- **AGC auto-reset improvements (all node types).**\r\n\r\n  Coordination between AGC auto-reset and channel busy detection has been improved. While the noise floor baseline is being re-established after a reset, channel sensing falls back to hardware CAD only.\r\n\r\n- **Fix: excessive flash writes on nRF52 Companion (T096, RAK4631).**\r\n\r\n  Each received advertisement previously triggered an immediate flash write — both to the advert blob store and to the contact list. In areas with high advert traffic this caused unnecessary flash wear, and a malicious node spamming adverts could wear out ExtraFS in hours. Advert blobs are now buffered in RAM and flushed to flash at most once every 10 minutes. Auto-discovered contacts use the same 10-minute pattern instead of a short debounce timer.",
      "notesHtml": "<h3>v1.15_0531</h3>\n<ul>\n<li><p><strong>Full support for Heltec T096 — companion, repeater, and room server</strong></p>\n<p>The Heltec T096 is now fully supported across all node types. The hardware is an nRF52840-based board with an SX1262 radio, KCT8103L FEM, UC6580 GPS, and a 0.96\" 160×80 color TFT display (ST7735S).</p>\n<p>The complete companion UI — Quick Send, Contacts, Settings, GPS, Saved Locations, GPS Trace, and message preview — runs on the color TFT.</p>\n<p><strong>Differences from other supported boards:</strong></p>\n<ul>\n<li><p><strong>Color TFT display.</strong> All companion pages render in color on the 160×80 ST7735S — unlike other supported boards which use a monochrome OLED.</p>\n</li>\n<li><p><strong>Brightness control.</strong> A <strong>Brightness</strong> item in the Settings page adjusts the TFT backlight intensity: <code>25</code> → <code>50</code> → <code>75</code> → <code>100</code>. Setting is saved to flash.</p>\n</li>\n<li><p><strong>KCT8103L FEM — same as Heltec V4.3.</strong> <code>set radio.rxgain on</code> / <code>off</code> works identically.</p>\n</li>\n<li><p><strong>UC6580 GPS.</strong> <code>gps.interval</code> works the same as on Heltec V4. Constellation selection (<code>gps.mode</code>) uses a different set of options:</p>\n<table>\n<thead>\n<tr>\n<th>Value</th>\n<th>Constellations</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>1</code></td>\n<td>GPS L1 only</td>\n</tr>\n<tr>\n<td><code>2</code></td>\n<td>All-system L1 (GPS+BDS+GLO+GAL)</td>\n</tr>\n<tr>\n<td><code>3</code></td>\n<td>All-system + QZSS dual-band <em>(default)</em></td>\n</tr>\n</tbody></table>\n</li>\n</ul>\n</li>\n<li><p><strong>AGC auto-reset improvements (all node types).</strong></p>\n<p>Coordination between AGC auto-reset and channel busy detection has been improved. While the noise floor baseline is being re-established after a reset, channel sensing falls back to hardware CAD only.</p>\n</li>\n<li><p><strong>Fix: excessive flash writes on nRF52 Companion (T096, RAK4631).</strong></p>\n<p>Each received advertisement previously triggered an immediate flash write — both to the advert blob store and to the contact list. In areas with high advert traffic this caused unnecessary flash wear, and a malicious node spamming adverts could wear out ExtraFS in hours. Advert blobs are now buffered in RAM and flushed to flash at most once every 10 minutes. Auto-discovered contacts use the same 10-minute pattern instead of a short debounce timer.</p>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0524",
      "name": "MeshCore low power - v1.15.dev_0524",
      "datetime": "2026-05-24T01:53:36Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0524",
      "prerelease": false,
      "notes": "### v1.15_0524\r\n\r\n- **Fix: radio deafness recovery in noisy environments (all node types).**\r\n\r\n  When strong in-band interference causes the SX1262 AGC to become overwhelmed, the radio can go deaf — severely degraded in receive sensitivity. The firmware now detects this condition automatically and triggers an immediate hardware recalibration, restoring sensitivity without waiting for the scheduled `agc.reset.interval`. The `agc.reset.interval` setting remains available but is now unnecessary.\r\n\r\n  Two new commands let you monitor and reset the AGC reset counter:\r\n\r\n  | Command | Effect |\r\n  |---------|--------|\r\n  | `get agc.resets` | Show how many times the AGC has been auto-reset since boot or last `clear` |\r\n  | `clear agc.resets` | Reset the counter to zero |\r\n\r\n  **Real-world validation:** A repeater installed near a periodic in-band interference source (confirmed via RTL-SDR) accumulated 918 auto-resets over 8.5 hours (~1.8/min), matching the observed interference sweep cycle. A second repeater at a clean location recorded 0 resets over the same period, confirming no false positives. Without this feature, the first repeater was unreachable remotely due to persistent deafness.\r\n\r\n- **GPS update interval configurable at runtime on Heltec V4 (all node types).**\r\n\r\n  A new `gps.interval` setting controls the sleep time between GPS position updates. After each fix, GPS powers down for the configured interval, then wakes and acquires a new fix. Set it to `0` to keep GPS always on. Default is 10 seconds.\r\n\r\n  Available on **Companion** via [TerminalCLI](Companion_TerminalCLI_Commands.md) and on **Repeater / Room Server** via the Command Line:\r\n\r\n  | Command | Effect |\r\n  |---|---|\r\n  | `get gps.interval` | Show current interval (`always on` if 0) |\r\n  | `set gps.interval 0` | GPS always on — maximum accuracy, highest power draw |\r\n  | `set gps.interval 30` | GPS sleeps 30s after each fix, then re-acquires |\r\n  | `set gps.interval 300` | GPS sleeps 5 minutes after each fix |\r\n\r\n  Setting is saved to flash and takes effect immediately — no reboot needed.\r\n\r\n- **GPS constellation selection for L78K on Heltec V4 (`gps.mode`) (all node types).**\r\n\r\n  Choose which satellite constellations the L78K module tracks. Average current draw is essentially the same across all configurations in duty cycle mode with `gps.interval` greater than 10 (~23 mA mean current measured on Heltec V4.3 Companion with `gps.mode = 4` and `gps.interval = 10`). Leave at the default `4` for the most robust fix; adjust only if you have a specific coverage reason.\r\n\r\n  | Value | Constellations |\r\n  |---|---|\r\n  | `1` | GPS only |\r\n  | `2` | GPS + BeiDou |\r\n  | `3` | GPS + GLONASS |\r\n  | `4` | GPS + BeiDou + GLONASS *(default)* |\r\n\r\n  Available on **Companion** via [TerminalCLI](Companion_TerminalCLI_Commands.md) and on **Repeater / Room Server** via the Command Line:\r\n\r\n  | Command | Effect |\r\n  |---|---|\r\n  | `get gps.mode` | Show current constellation selection |\r\n  | `set gps.mode 4` | GPS + BeiDou + GLONASS (default) |\r\n  | `set gps.mode 1` | GPS only |\r\n\r\n  Setting is saved to flash. Change takes effect on next GPS on.\r\n\r\n- **Companion: GPS screen shows interval and constellation when GPS is off.**\r\n\r\n  When GPS is off, the GPS page now shows the configured update interval (`intv`) and constellation selection (`mode`, Heltec V4 only), so you can verify settings before enabling GPS.",
      "notesHtml": "<h3>v1.15_0524</h3>\n<ul>\n<li><p><strong>Fix: radio deafness recovery in noisy environments (all node types).</strong></p>\n<p>When strong in-band interference causes the SX1262 AGC to become overwhelmed, the radio can go deaf — severely degraded in receive sensitivity. The firmware now detects this condition automatically and triggers an immediate hardware recalibration, restoring sensitivity without waiting for the scheduled <code>agc.reset.interval</code>. The <code>agc.reset.interval</code> setting remains available but is now unnecessary.</p>\n<p>Two new commands let you monitor and reset the AGC reset counter:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>get agc.resets</code></td>\n<td>Show how many times the AGC has been auto-reset since boot or last <code>clear</code></td>\n</tr>\n<tr>\n<td><code>clear agc.resets</code></td>\n<td>Reset the counter to zero</td>\n</tr>\n</tbody></table>\n<p><strong>Real-world validation:</strong> A repeater installed near a periodic in-band interference source (confirmed via RTL-SDR) accumulated 918 auto-resets over 8.5 hours (~1.8/min), matching the observed interference sweep cycle. A second repeater at a clean location recorded 0 resets over the same period, confirming no false positives. Without this feature, the first repeater was unreachable remotely due to persistent deafness.</p>\n</li>\n<li><p><strong>GPS update interval configurable at runtime on Heltec V4 (all node types).</strong></p>\n<p>A new <code>gps.interval</code> setting controls the sleep time between GPS position updates. After each fix, GPS powers down for the configured interval, then wakes and acquires a new fix. Set it to <code>0</code> to keep GPS always on. Default is 10 seconds.</p>\n<p>Available on <strong>Companion</strong> via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a> and on <strong>Repeater / Room Server</strong> via the Command Line:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>get gps.interval</code></td>\n<td>Show current interval (<code>always on</code> if 0)</td>\n</tr>\n<tr>\n<td><code>set gps.interval 0</code></td>\n<td>GPS always on — maximum accuracy, highest power draw</td>\n</tr>\n<tr>\n<td><code>set gps.interval 30</code></td>\n<td>GPS sleeps 30s after each fix, then re-acquires</td>\n</tr>\n<tr>\n<td><code>set gps.interval 300</code></td>\n<td>GPS sleeps 5 minutes after each fix</td>\n</tr>\n</tbody></table>\n<p>Setting is saved to flash and takes effect immediately — no reboot needed.</p>\n</li>\n<li><p><strong>GPS constellation selection for L78K on Heltec V4 (<code>gps.mode</code>) (all node types).</strong></p>\n<p>Choose which satellite constellations the L78K module tracks. Average current draw is essentially the same across all configurations in duty cycle mode with <code>gps.interval</code> greater than 10 (~23 mA mean current measured on Heltec V4.3 Companion with <code>gps.mode = 4</code> and <code>gps.interval = 10</code>). Leave at the default <code>4</code> for the most robust fix; adjust only if you have a specific coverage reason.</p>\n<table>\n<thead>\n<tr>\n<th>Value</th>\n<th>Constellations</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>1</code></td>\n<td>GPS only</td>\n</tr>\n<tr>\n<td><code>2</code></td>\n<td>GPS + BeiDou</td>\n</tr>\n<tr>\n<td><code>3</code></td>\n<td>GPS + GLONASS</td>\n</tr>\n<tr>\n<td><code>4</code></td>\n<td>GPS + BeiDou + GLONASS <em>(default)</em></td>\n</tr>\n</tbody></table>\n<p>Available on <strong>Companion</strong> via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a> and on <strong>Repeater / Room Server</strong> via the Command Line:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>get gps.mode</code></td>\n<td>Show current constellation selection</td>\n</tr>\n<tr>\n<td><code>set gps.mode 4</code></td>\n<td>GPS + BeiDou + GLONASS (default)</td>\n</tr>\n<tr>\n<td><code>set gps.mode 1</code></td>\n<td>GPS only</td>\n</tr>\n</tbody></table>\n<p>Setting is saved to flash. Change takes effect on next GPS on.</p>\n</li>\n<li><p><strong>Companion: GPS screen shows interval and constellation when GPS is off.</strong></p>\n<p>When GPS is off, the GPS page now shows the configured update interval (<code>intv</code>) and constellation selection (<code>mode</code>, Heltec V4 only), so you can verify settings before enabling GPS.</p>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0517",
      "name": "MeshCore low power - v1.15.dev_0517",
      "datetime": "2026-05-17T03:19:48Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0517",
      "prerelease": false,
      "notes": "### v1.15_0517\r\n\r\n- **Companion: per-channel outgoing hop limit (`ch.hops`).**\r\n\r\n  Limit how far your outgoing messages travel on a specific channel, without affecting any other channel or any other node in the network. Useful for keeping a private or local-area channel confined to a small radius — for example, a home-to-nearby-relay link — without touching the rest of the city mesh.\r\n\r\n  Configure via **TerminalCLI**:\r\n\r\n  | Command | Effect |\r\n  |---|---|\r\n  | `set ch.hops <channel> <N>` | Limit outgoing messages on `<channel>` to at most N hops |\r\n  | `set ch.hops <channel> off` | Remove the limit |\r\n  | `get ch.hops <channel>` | Show current limit |\r\n  | `ch.hops status` | List all channels with an active limit |\r\n  | `ch.hops clear` | Remove all limits |\r\n\r\n  ```\r\n  set ch.hops Public 2         # Public channel messages travel at most 2 hops\r\n  set ch.hops My Local Net 3   # My Local Net channel travel at most 3 hops\r\n  set ch.hops Public off       # remove the limit\r\n  ch.hops status\r\n  ```\r\n\r\n\r\n  The limit applies to **your outgoing messages only** — other nodes sending on the same channel are unaffected. No repeater configuration or network coordination required.\r\n\r\n  The repeater's `group.hops.max` algorithm has been updated to correctly account for sender-side pre-fill, so `ch.hops` and `group.hops.max` work together without conflict — update repeater firmware to get full compatibility.\r\n\r\n  Settings are stored in flash and persist after reboot.\r\n\r\n- **Companion: toggle RxGain directly from the Radio screen.**\r\n\r\n  Long press on the **Radio** page cycles through RxGain modes (OFF → ON → Auto) and shows a popup confirming the new mode. The current mode is now also displayed on the Radio page itself (`RxG: OFF` / `RxG: ON` / `RxG: Auto`), so you can check it at a glance without going into Settings. *(`Auto` is available on Heltec V4.2 only.)*\r\n\r\n- **Fix: noise floor stuck at -120 in noisy environments (all node types)**\r\n\r\n  In environments with strong in-band interference, the noise floor could remain at -120 dBm for a long time instead of updating to reflect actual conditions. Fixed.",
      "notesHtml": "<h3>v1.15_0517</h3>\n<ul>\n<li><p><strong>Companion: per-channel outgoing hop limit (<code>ch.hops</code>).</strong></p>\n<p>Limit how far your outgoing messages travel on a specific channel, without affecting any other channel or any other node in the network. Useful for keeping a private or local-area channel confined to a small radius — for example, a home-to-nearby-relay link — without touching the rest of the city mesh.</p>\n<p>Configure via <strong>TerminalCLI</strong>:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>set ch.hops &lt;channel&gt; &lt;N&gt;</code></td>\n<td>Limit outgoing messages on <code>&lt;channel&gt;</code> to at most N hops</td>\n</tr>\n<tr>\n<td><code>set ch.hops &lt;channel&gt; off</code></td>\n<td>Remove the limit</td>\n</tr>\n<tr>\n<td><code>get ch.hops &lt;channel&gt;</code></td>\n<td>Show current limit</td>\n</tr>\n<tr>\n<td><code>ch.hops status</code></td>\n<td>List all channels with an active limit</td>\n</tr>\n<tr>\n<td><code>ch.hops clear</code></td>\n<td>Remove all limits</td>\n</tr>\n</tbody></table>\n<pre><code>set ch.hops Public 2         # Public channel messages travel at most 2 hops\nset ch.hops My Local Net 3   # My Local Net channel travel at most 3 hops\nset ch.hops Public off       # remove the limit\nch.hops status\n</code></pre>\n<p>The limit applies to <strong>your outgoing messages only</strong> — other nodes sending on the same channel are unaffected. No repeater configuration or network coordination required.</p>\n<p>The repeater's <code>group.hops.max</code> algorithm has been updated to correctly account for sender-side pre-fill, so <code>ch.hops</code> and <code>group.hops.max</code> work together without conflict — update repeater firmware to get full compatibility.</p>\n<p>Settings are stored in flash and persist after reboot.</p>\n</li>\n<li><p><strong>Companion: toggle RxGain directly from the Radio screen.</strong></p>\n<p>Long press on the <strong>Radio</strong> page cycles through RxGain modes (OFF → ON → Auto) and shows a popup confirming the new mode. The current mode is now also displayed on the Radio page itself (<code>RxG: OFF</code> / <code>RxG: ON</code> / <code>RxG: Auto</code>), so you can check it at a glance without going into Settings. <em>(<code>Auto</code> is available on Heltec V4.2 only.)</em></p>\n</li>\n<li><p><strong>Fix: noise floor stuck at -120 in noisy environments (all node types)</strong></p>\n<p>In environments with strong in-band interference, the noise floor could remain at -120 dBm for a long time instead of updating to reflect actual conditions. Fixed.</p>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0510",
      "name": "MeshCore low power - v1.15.dev_0510",
      "datetime": "2026-05-10T02:47:22Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0510",
      "prerelease": false,
      "notes": "### v1.15_0510\r\n\r\n- **Repeater: per-type relay hop cap (`advert.hops.max` / `group.hops.max`).**\r\n\r\n  Two new settings let you independently limit how far **advertisement packets** and **group messages** are relayed across the mesh, without affecting direct messages, ACKs, or path discovery.\r\n\r\n  | Setting | Controls | Default |\r\n  |---|---|---|\r\n  | `advert.hops.max` | Max hops to relay node advertisement (ADVERT) packets | = `flood.max` |\r\n  | `group.hops.max` | Max hops to relay group messages (GRP_TXT / GRP_DATA) | = `flood.max` |\r\n\r\n  These are **repeater-only** settings. Configure via the **Command Line** in the MeshCore App:\r\n  ```\r\n  set advert.hops.max 3    # relay adverts at most 3 hops from sender\r\n  set group.hops.max 5     # relay group messages at most 5 hops\r\n  get advert.hops.max\r\n  get group.hops.max\r\n  ```\r\n\r\n  Setting either value to `0` completely suppresses that packet type — no relay at all, while everything else (DM, ACK, path) continues to work normally.\r\n\r\n  **Why this matters — advert storm reduction:**\r\n\r\n  Each repeater periodically broadcasts an advertisement that every other repeater in range relays, up to `flood.max` times (default 64). In a network of 35 repeaters and 35 companions, advert traffic alone consumes roughly 4% of airtime. Limiting to 3 hops brings that down to under 0.5% — a 7× reduction — with no loss of communication capability.  \r\n\r\n  **No coordination required.** Each repeater applies its own cap independently. You do not need all repeaters to agree on the same value — even a partial deployment reduces airtime. No region configuration, no App UI changes needed.\r\n\r\n  **Recommended profiles:**\r\n\r\n  | Profile | `advert.hops.max` | `group.hops.max` | Airtime (35R / 35C) | Use case |\r\n  |---|---|---|---|---|\r\n  | Default | = `flood.max` | = `flood.max` | ~4% | No change |\r\n  | Optimized | 3 | 5 | ~0.5% | Most deployments |\r\n  | DM-focused | 0 | 3 | ~0.2% | Prioritise direct messages |\r\n  | EU compliance | 0 | 3 | ~0.2% | Large EU networks (legal requirement) |\r\n\r\n  > **Relationship with `flood.max` and path hash size:** `flood.max` is the master hop cap for **all** flood payloads. Its default of 64 is calibrated for 1-byte path hash mode. With larger hashes the packet fills up sooner — 2-byte hash caps at 32 hops, 3-byte hash caps at 21 hops — so `flood.max` is typically set to match. `advert.hops.max` and `group.hops.max` are automatically clamped to `flood.max` and work correctly with all hash sizes. If you want to suppress adverts entirely while keeping everything else unrestricted, set `advert.hops.max 0` — leave `flood.max` untouched.\r\n\r\n- **Repeater: combining hop caps with region scope for full community isolation.**\r\n\r\n  `advert.hops.max` and `group.hops.max` work standalone — no coordination needed. For operators who also want to restrict which community's group messages get relayed, combine them with region rules and the companion's scope settings:\r\n\r\n  1. Each companion sets a region scope — either per-channel via the burger menu, or globally via **Settings → Experimental → Default Region Scope**. All outgoing flood packets (including DM path discovery) are tagged with the community name.\r\n  2. Each repeater: `denyf *` + `allowf <community>` — only relay community-tagged traffic.\r\n  3. Add `set advert.hops.max 0` to also suppress advert relay.\r\n\r\n  With a global Default Region Scope, DM path discovery is tagged and passes through `denyf *` repeaters — direct messaging works normally inside the community.\r\n\r\n  > **Default Region Scope** is in the App's Experimental Settings and is opt-in. Per-channel scope (burger menu) only tags group messages for that channel, not advertisements or DM path discovery.\r\n\r\n- **Companion: GPS coordinate display formats — DD / UTM / MGRS.**\r\n\r\n  A new **Pos. Format** item in the Settings page lets you choose how GPS coordinates are shown on the GPS page, GPS Trace screen, and Quick Send status bar.\r\n\r\n  | Format | Example |\r\n  |---|---|\r\n  | D\n…",
      "notesHtml": "<h3>v1.15_0510</h3>\n<ul>\n<li><p><strong>Repeater: per-type relay hop cap (<code>advert.hops.max</code> / <code>group.hops.max</code>).</strong></p>\n<p>Two new settings let you independently limit how far <strong>advertisement packets</strong> and <strong>group messages</strong> are relayed across the mesh, without affecting direct messages, ACKs, or path discovery.</p>\n<table>\n<thead>\n<tr>\n<th>Setting</th>\n<th>Controls</th>\n<th>Default</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>advert.hops.max</code></td>\n<td>Max hops to relay node advertisement (ADVERT) packets</td>\n<td>= <code>flood.max</code></td>\n</tr>\n<tr>\n<td><code>group.hops.max</code></td>\n<td>Max hops to relay group messages (GRP_TXT / GRP_DATA)</td>\n<td>= <code>flood.max</code></td>\n</tr>\n</tbody></table>\n<p>These are <strong>repeater-only</strong> settings. Configure via the <strong>Command Line</strong> in the MeshCore App:</p>\n<pre><code>set advert.hops.max 3    # relay adverts at most 3 hops from sender\nset group.hops.max 5     # relay group messages at most 5 hops\nget advert.hops.max\nget group.hops.max\n</code></pre>\n<p>Setting either value to <code>0</code> completely suppresses that packet type — no relay at all, while everything else (DM, ACK, path) continues to work normally.</p>\n<p><strong>Why this matters — advert storm reduction:</strong></p>\n<p>Each repeater periodically broadcasts an advertisement that every other repeater in range relays, up to <code>flood.max</code> times (default 64). In a network of 35 repeaters and 35 companions, advert traffic alone consumes roughly 4% of airtime. Limiting to 3 hops brings that down to under 0.5% — a 7× reduction — with no loss of communication capability.  </p>\n<p><strong>No coordination required.</strong> Each repeater applies its own cap independently. You do not need all repeaters to agree on the same value — even a partial deployment reduces airtime. No region configuration, no App UI changes needed.</p>\n<p><strong>Recommended profiles:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Profile</th>\n<th><code>advert.hops.max</code></th>\n<th><code>group.hops.max</code></th>\n<th>Airtime (35R / 35C)</th>\n<th>Use case</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Default</td>\n<td>= <code>flood.max</code></td>\n<td>= <code>flood.max</code></td>\n<td>~4%</td>\n<td>No change</td>\n</tr>\n<tr>\n<td>Optimized</td>\n<td>3</td>\n<td>5</td>\n<td>~0.5%</td>\n<td>Most deployments</td>\n</tr>\n<tr>\n<td>DM-focused</td>\n<td>0</td>\n<td>3</td>\n<td>~0.2%</td>\n<td>Prioritise direct messages</td>\n</tr>\n<tr>\n<td>EU compliance</td>\n<td>0</td>\n<td>3</td>\n<td>~0.2%</td>\n<td>Large EU networks (legal requirement)</td>\n</tr>\n</tbody></table>\n<blockquote>\n<p><strong>Relationship with <code>flood.max</code> and path hash size:</strong> <code>flood.max</code> is the master hop cap for <strong>all</strong> flood payloads. Its default of 64 is calibrated for 1-byte path hash mode. With larger hashes the packet fills up sooner — 2-byte hash caps at 32 hops, 3-byte hash caps at 21 hops — so <code>flood.max</code> is typically set to match. <code>advert.hops.max</code> and <code>group.hops.max</code> are automatically clamped to <code>flood.max</code> and work correctly with all hash sizes. If you want to suppress adverts entirely while keeping everything else unrestricted, set <code>advert.hops.max 0</code> — leave <code>flood.max</code> untouched.</p>\n</blockquote>\n</li>\n<li><p><strong>Repeater: combining hop caps with region scope for full community isolation.</strong></p>\n<p><code>advert.hops.max</code> and <code>group.hops.max</code> work standalone — no coordination needed. For operators who also want to restrict which community's group messages get relayed, combine them with region rules and the companion's scope settings:</p>\n<ol>\n<li>Each companion sets a region scope — either per-channel via the burger menu, or globally via <strong>Settings → Experimental → Default Region Scope</strong>. All outgoing flood packets (including DM path discovery) are tagged with the community name.</li>\n<li>Each repeater: <code>denyf *</code> + <code>allowf &lt;community&gt;</code> — only relay community-tagged traffic.</li>\n<li>Add <code>set advert.hops.max 0</code> to also suppress advert relay.</li>\n</ol>\n<p>With a global Default Region Scope, DM path discovery is tagged and passes through <code>denyf *</code> repeaters — direct messaging works normally inside the community.</p>\n<blockquote>\n<p><strong>Default Region Scope</strong> is in the App's Experimental Settings and is opt-in. Per-channel scope (burger menu) only tags group messages for that channel, not advertisements or DM path discovery.</p>\n</blockquote>\n</li>\n<li><p><strong>Companion: GPS coordinate display formats — DD / UTM / MGRS.</strong></p>\n<p>A new <strong>Pos. Format</strong> item in the Settings page lets you choose how GPS coordinates are shown on the GPS page, GPS Trace screen, and Quick Send status bar.</p>\n<table>\n<thead>\n<tr>\n<th>Format</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>D</td>\n<td></td>\n</tr>\n<tr>\n<td>…</td>\n<td></td>\n</tr>\n</tbody></table>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0426",
      "name": "MeshCore low power - v1.15.dev_0426",
      "datetime": "2026-04-26T04:49:25Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0426",
      "prerelease": false,
      "notes": "### v1.15_0426\r\n\r\n- **Companion: redesigned message preview.**\r\n\r\n  Messages are now grouped by sender or channel so you can read a conversation in one place instead of hunting through a mixed list.\r\n\r\n  From the **group list** you can scroll back through older messages from any sender or channel, including ones you've already read. Long press a group to open it.\r\n\r\n  When new messages arrive, you go straight to a **new messages view** that shows only the unread ones — from all senders and channels — one by one. Once you've read them all, a single click takes you home.\r\n\r\n  Long messages scroll one full page at a time with no overlap. Small arrows (`▲` / `▼`) appear at the corner of the screen to let you know there is more content above or below.\r\n\r\n- **Companion: reply directly from message preview.**\r\n\r\n  While reading any message, long press to open the menu. A new **Reply** option lets you send a preset message back without leaving the screen:\r\n\r\n  - If the message came from a contact, the reply goes to that contact as a private direct message.\r\n  - If the message came from a channel (Public, #SOS, or any other), the reply goes back to that same channel.\r\n\r\n  > **Note:** The **Quick Send** page always sends to the Public channel. Use Reply from the message preview when you want to respond to a specific contact or a non-Public channel.\r\n\r\n- **Companion: Contacts page and direct messaging.**\r\n\r\n  A new **Contacts** page sits between Quick Send and Saved Locations. Long press it to open the contact list, only chat-capable nodes are listed (repeaters, room servers and sensors are excluded — they cannot receive direct messages). Select a contact and long press to send them a direct message using your Quick Send presets.\r\n\r\n- **Companion: configurable Screen Off timeout in Settings.**\r\n\r\n  A new **Screen Off** item in the Settings page lets you choose how long the display stays on after the last button press: `15s` → `3min` → `Never`. Setting is saved to flash and persists after reboot.\r\n\r\n- **Companion: Flip Screen setting in Settings.**\r\n\r\n  A new **Flip Screen** toggle in the Settings page rotates the display 180°. Setting is saved to flash and persists after reboot.\r\n- **fix bugs**",
      "notesHtml": "<h3>v1.15_0426</h3>\n<ul>\n<li><p><strong>Companion: redesigned message preview.</strong></p>\n<p>Messages are now grouped by sender or channel so you can read a conversation in one place instead of hunting through a mixed list.</p>\n<p>From the <strong>group list</strong> you can scroll back through older messages from any sender or channel, including ones you've already read. Long press a group to open it.</p>\n<p>When new messages arrive, you go straight to a <strong>new messages view</strong> that shows only the unread ones — from all senders and channels — one by one. Once you've read them all, a single click takes you home.</p>\n<p>Long messages scroll one full page at a time with no overlap. Small arrows (<code>▲</code> / <code>▼</code>) appear at the corner of the screen to let you know there is more content above or below.</p>\n</li>\n<li><p><strong>Companion: reply directly from message preview.</strong></p>\n<p>While reading any message, long press to open the menu. A new <strong>Reply</strong> option lets you send a preset message back without leaving the screen:</p>\n<ul>\n<li>If the message came from a contact, the reply goes to that contact as a private direct message.</li>\n<li>If the message came from a channel (Public, #SOS, or any other), the reply goes back to that same channel.</li>\n</ul>\n<blockquote>\n<p><strong>Note:</strong> The <strong>Quick Send</strong> page always sends to the Public channel. Use Reply from the message preview when you want to respond to a specific contact or a non-Public channel.</p>\n</blockquote>\n</li>\n<li><p><strong>Companion: Contacts page and direct messaging.</strong></p>\n<p>A new <strong>Contacts</strong> page sits between Quick Send and Saved Locations. Long press it to open the contact list, only chat-capable nodes are listed (repeaters, room servers and sensors are excluded — they cannot receive direct messages). Select a contact and long press to send them a direct message using your Quick Send presets.</p>\n</li>\n<li><p><strong>Companion: configurable Screen Off timeout in Settings.</strong></p>\n<p>A new <strong>Screen Off</strong> item in the Settings page lets you choose how long the display stays on after the last button press: <code>15s</code> → <code>3min</code> → <code>Never</code>. Setting is saved to flash and persists after reboot.</p>\n</li>\n<li><p><strong>Companion: Flip Screen setting in Settings.</strong></p>\n<p>A new <strong>Flip Screen</strong> toggle in the Settings page rotates the display 180°. Setting is saved to flash and persists after reboot.</p>\n</li>\n<li><p><strong>fix bugs</strong></p>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0427",
      "name": "Repeater feature: per-type relay hop cap (advert.hops.max, group.hops.max) - v1.15.dev_0427",
      "datetime": "2026-04-27T09:32:36Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0427",
      "prerelease": true,
      "notes": "### v1.15_0427\r\n\r\n- **Repeater: per-type relay hop cap (`advert.hops.max` / `group.hops.max`).**\r\n\r\n  Two new settings let you independently limit how far **advertisement packets** and **group messages** are relayed across the mesh, without affecting direct messages, ACKs, or path discovery.\r\n\r\n  | Setting | Controls | Default |\r\n  |---|---|---|\r\n  | `advert.hops.max` | Max hops to relay node advertisement (ADVERT) packets | 64 (unchanged) |\r\n  | `group.hops.max` | Max hops to relay group messages (GRP_TXT / GRP_DATA) | 64 (unchanged) |\r\n\r\n  These are **repeater-only** settings. Configure via the **Command Line** in the MeshCore App:\r\n  ```\r\n  set advert.hops.max 3    # relay adverts at most 3 hops from sender\r\n  set group.hops.max 5     # relay group messages at most 5 hops\r\n  get advert.hops.max\r\n  get group.hops.max\r\n  ```\r\n\r\n  Setting either value to `0` completely suppresses that packet type — no relay at all, while everything else (DM, ACK, path) continues to work normally.\r\n\r\n  **Why this matters — advert storm reduction:**\r\n\r\n  Each repeater periodically broadcasts an advertisement that every other repeater in range relays, up to `flood.max` times (default 64). In a network of 35 repeaters and 35 companions, advert traffic alone consumes roughly 4% of airtime. Limiting to 3 hops brings that down to under 0.5% — a 7× reduction — with no loss of communication capability.  \r\n\r\n  **No coordination required.** Each repeater applies its own cap independently. You do not need all repeaters to agree on the same value — even a partial deployment reduces airtime. No region configuration, no App UI changes needed.\r\n\r\n  **Recommended profiles:**\r\n\r\n  | Profile | `advert.hops.max` | `group.hops.max` | Airtime (35R / 35C) | Use case |\r\n  |---|---|---|---|---|\r\n  | Default | 64 | 64 | ~4% | No change |\r\n  | Optimized | 3 | 5 | ~0.5% | Most deployments |\r\n  | DM-focused | 0 | 3 | ~0.2% | Prioritise direct messages |\r\n  | EU compliance | 0 | 3 | ~0.2% | Large EU networks (legal requirement) |\r\n\r\n  > **Relationship with `flood.max`:** `flood.max` (long-standing setting, default 64) is the master hop cap for **all** flood payloads — DMs on first send, path discovery, group messages, adverts. It applies regardless of payload type. `advert.hops.max` and `group.hops.max` add finer per-type control on top: they can only be equal to or stricter than `flood.max`, never looser. Setting `flood.max` lower automatically clamps both values to match. If you want to suppress adverts entirely while keeping DMs unrestricted, lower `advert.hops.max` to `0` — leave `flood.max` untouched.",
      "notesHtml": "<h3>v1.15_0427</h3>\n<ul>\n<li><p><strong>Repeater: per-type relay hop cap (<code>advert.hops.max</code> / <code>group.hops.max</code>).</strong></p>\n<p>Two new settings let you independently limit how far <strong>advertisement packets</strong> and <strong>group messages</strong> are relayed across the mesh, without affecting direct messages, ACKs, or path discovery.</p>\n<table>\n<thead>\n<tr>\n<th>Setting</th>\n<th>Controls</th>\n<th>Default</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>advert.hops.max</code></td>\n<td>Max hops to relay node advertisement (ADVERT) packets</td>\n<td>64 (unchanged)</td>\n</tr>\n<tr>\n<td><code>group.hops.max</code></td>\n<td>Max hops to relay group messages (GRP_TXT / GRP_DATA)</td>\n<td>64 (unchanged)</td>\n</tr>\n</tbody></table>\n<p>These are <strong>repeater-only</strong> settings. Configure via the <strong>Command Line</strong> in the MeshCore App:</p>\n<pre><code>set advert.hops.max 3    # relay adverts at most 3 hops from sender\nset group.hops.max 5     # relay group messages at most 5 hops\nget advert.hops.max\nget group.hops.max\n</code></pre>\n<p>Setting either value to <code>0</code> completely suppresses that packet type — no relay at all, while everything else (DM, ACK, path) continues to work normally.</p>\n<p><strong>Why this matters — advert storm reduction:</strong></p>\n<p>Each repeater periodically broadcasts an advertisement that every other repeater in range relays, up to <code>flood.max</code> times (default 64). In a network of 35 repeaters and 35 companions, advert traffic alone consumes roughly 4% of airtime. Limiting to 3 hops brings that down to under 0.5% — a 7× reduction — with no loss of communication capability.  </p>\n<p><strong>No coordination required.</strong> Each repeater applies its own cap independently. You do not need all repeaters to agree on the same value — even a partial deployment reduces airtime. No region configuration, no App UI changes needed.</p>\n<p><strong>Recommended profiles:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Profile</th>\n<th><code>advert.hops.max</code></th>\n<th><code>group.hops.max</code></th>\n<th>Airtime (35R / 35C)</th>\n<th>Use case</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Default</td>\n<td>64</td>\n<td>64</td>\n<td>~4%</td>\n<td>No change</td>\n</tr>\n<tr>\n<td>Optimized</td>\n<td>3</td>\n<td>5</td>\n<td>~0.5%</td>\n<td>Most deployments</td>\n</tr>\n<tr>\n<td>DM-focused</td>\n<td>0</td>\n<td>3</td>\n<td>~0.2%</td>\n<td>Prioritise direct messages</td>\n</tr>\n<tr>\n<td>EU compliance</td>\n<td>0</td>\n<td>3</td>\n<td>~0.2%</td>\n<td>Large EU networks (legal requirement)</td>\n</tr>\n</tbody></table>\n<blockquote>\n<p><strong>Relationship with <code>flood.max</code>:</strong> <code>flood.max</code> (long-standing setting, default 64) is the master hop cap for <strong>all</strong> flood payloads — DMs on first send, path discovery, group messages, adverts. It applies regardless of payload type. <code>advert.hops.max</code> and <code>group.hops.max</code> add finer per-type control on top: they can only be equal to or stricter than <code>flood.max</code>, never looser. Setting <code>flood.max</code> lower automatically clamps both values to match. If you want to suppress adverts entirely while keeping DMs unrestricted, lower <code>advert.hops.max</code> to <code>0</code> — leave <code>flood.max</code> untouched.</p>\n</blockquote>\n</li>\n</ul>\n"
    },
    {
      "version": "MeshCore-low-power-v1.15.dev_0419",
      "name": "MeshCore low power - v1.15.dev_0419",
      "datetime": "2026-04-19T04:50:53Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/MeshCore-low-power-v1.15.dev_0419",
      "prerelease": false,
      "notes": "bump to 1.15.dev",
      "notesHtml": "<p>bump to 1.15.dev</p>\n"
    },
    {
      "version": "XIAO-S3-Wio-low-power-v1.14_0417",
      "name": "XIAO S3 Wio low power - v1.14_0417",
      "datetime": "2026-04-17T13:57:17Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/XIAO-S3-Wio-low-power-v1.14_0417",
      "prerelease": false,
      "notes": "### v1.14_0417\r\n\r\n- **Hybrid RSSI + hardware CAD channel sensing (all node types).**\r\n\r\n  `isChannelActive()` now performs a two-stage check before transmitting:\r\n  1. RSSI check (fast, single SPI register read) — defers if signal is above `noise_floor + int.thresh`.\r\n  2. Hardware CAD (`scanChannel()`) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).\r\n\r\n  RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.\r\n\r\n  `int.thresh=0` disables both RSSI and CAD. `int.thresh=1` enables full hybrid at maximum sensitivity.\r\n\r\n  **On repeaters** (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, **`txdelay=2`**, 100 messages):\r\n\r\n  - **Repeaters close together / strong inter-repeater signal:** RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → **9% collision rate**.\r\n  - **Spread-out repeaters, some pairs below noise floor:** RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD **8%** vs RSSI-only **17%**.\r\n  - **Many hidden node pairs:** neither RSSI nor CAD helps. **Only `txdelay` reduces the floor.** Example: ~20–24% regardless of sensing method.\r\n\r\n  **On companions** (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):\r\n\r\n  - `int.thresh=3`: **53–64%** of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)\r\n  - `int.thresh=0` (no sensing): **0–1%** relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back\r\n\r\n  Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.\r\n\r\n- **Companion: `get/set txdelay`, `get/set direct.txdelay`, `get/set int.thresh` via [TerminalCLI](Companion_TerminalCLI_Commands.md).**\r\n\r\n  Relay timing and interference threshold are now configurable without reflashing.\r\n\r\n- **Companion: \"Heard N Repeats\" alert after Quick Send.**\r\n\r\n  After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.\r\n\r\n- **Companion: local time and date on the display.**\r\n\r\n  All pages now show the current time (`HH:MM`) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. `14 Apr 2026`).\r\n\r\n  Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via [TerminalCLI](Companion_TerminalCLI_Commands.md):\r\n  ```\r\n  set tz.offset 7    # UTC+7\r\n  set tz.offset -5   # UTC-5\r\n  get tz.offset\r\n  ```\r\n  Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.\r\n\r\n- **Companion: Metric / Imperial units.**\r\n\r\n  A new **Units** item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.\r\n\r\n  | Display | Metric | Imperial |\r\n  |---|---|---|\r\n  | GPS Trace distance | `150m` / `1.2km` | `492ft` / `0.7mi` |\r\n  | GPS page altitude | `245m` | `804ft` |\r\n  | Home page date | `14 Apr 2026` | `Apr 14 2026` |\r\n\r\n- **Companion: GPS Privacy mode.**\r\n\r\n  A new **GPS Privacy** item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…",
      "notesHtml": "<h3>v1.14_0417</h3>\n<ul>\n<li><p><strong>Hybrid RSSI + hardware CAD channel sensing (all node types).</strong></p>\n<p><code>isChannelActive()</code> now performs a two-stage check before transmitting:</p>\n<ol>\n<li>RSSI check (fast, single SPI register read) — defers if signal is above <code>noise_floor + int.thresh</code>.</li>\n<li>Hardware CAD (<code>scanChannel()</code>) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).</li>\n</ol>\n<p>RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.</p>\n<p><code>int.thresh=0</code> disables both RSSI and CAD. <code>int.thresh=1</code> enables full hybrid at maximum sensitivity.</p>\n<p><strong>On repeaters</strong> (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, <strong><code>txdelay=2</code></strong>, 100 messages):</p>\n<ul>\n<li><strong>Repeaters close together / strong inter-repeater signal:</strong> RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → <strong>9% collision rate</strong>.</li>\n<li><strong>Spread-out repeaters, some pairs below noise floor:</strong> RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD <strong>8%</strong> vs RSSI-only <strong>17%</strong>.</li>\n<li><strong>Many hidden node pairs:</strong> neither RSSI nor CAD helps. <strong>Only <code>txdelay</code> reduces the floor.</strong> Example: ~20–24% regardless of sensing method.</li>\n</ul>\n<p><strong>On companions</strong> (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):</p>\n<ul>\n<li><code>int.thresh=3</code>: <strong>53–64%</strong> of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)</li>\n<li><code>int.thresh=0</code> (no sensing): <strong>0–1%</strong> relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back</li>\n</ul>\n<p>Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.</p>\n</li>\n<li><p><strong>Companion: <code>get/set txdelay</code>, <code>get/set direct.txdelay</code>, <code>get/set int.thresh</code> via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>.</strong></p>\n<p>Relay timing and interference threshold are now configurable without reflashing.</p>\n</li>\n<li><p><strong>Companion: \"Heard N Repeats\" alert after Quick Send.</strong></p>\n<p>After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.</p>\n</li>\n<li><p><strong>Companion: local time and date on the display.</strong></p>\n<p>All pages now show the current time (<code>HH:MM</code>) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. <code>14 Apr 2026</code>).</p>\n<p>Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>:</p>\n<pre><code>set tz.offset 7    # UTC+7\nset tz.offset -5   # UTC-5\nget tz.offset\n</code></pre>\n<p>Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.</p>\n</li>\n<li><p><strong>Companion: Metric / Imperial units.</strong></p>\n<p>A new <strong>Units</strong> item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.</p>\n<table>\n<thead>\n<tr>\n<th>Display</th>\n<th>Metric</th>\n<th>Imperial</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>GPS Trace distance</td>\n<td><code>150m</code> / <code>1.2km</code></td>\n<td><code>492ft</code> / <code>0.7mi</code></td>\n</tr>\n<tr>\n<td>GPS page altitude</td>\n<td><code>245m</code></td>\n<td><code>804ft</code></td>\n</tr>\n<tr>\n<td>Home page date</td>\n<td><code>14 Apr 2026</code></td>\n<td><code>Apr 14 2026</code></td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>Companion: GPS Privacy mode.</strong></p>\n<p>A new <strong>GPS Privacy</strong> item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…</p>\n</li>\n</ul>\n"
    },
    {
      "version": "RAK4631-low-power-v1.14_0417",
      "name": "RAK4631 low power - v1.14_0417",
      "datetime": "2026-04-17T13:53:55Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/RAK4631-low-power-v1.14_0417",
      "prerelease": false,
      "notes": "### v1.14_0417\r\n\r\n- **Hybrid RSSI + hardware CAD channel sensing (all node types).**\r\n\r\n  `isChannelActive()` now performs a two-stage check before transmitting:\r\n  1. RSSI check (fast, single SPI register read) — defers if signal is above `noise_floor + int.thresh`.\r\n  2. Hardware CAD (`scanChannel()`) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).\r\n\r\n  RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.\r\n\r\n  `int.thresh=0` disables both RSSI and CAD. `int.thresh=1` enables full hybrid at maximum sensitivity.\r\n\r\n  **On repeaters** (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, **`txdelay=2`**, 100 messages):\r\n\r\n  - **Repeaters close together / strong inter-repeater signal:** RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → **9% collision rate**.\r\n  - **Spread-out repeaters, some pairs below noise floor:** RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD **8%** vs RSSI-only **17%**.\r\n  - **Many hidden node pairs:** neither RSSI nor CAD helps. **Only `txdelay` reduces the floor.** Example: ~20–24% regardless of sensing method.\r\n\r\n  **On companions** (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):\r\n\r\n  - `int.thresh=3`: **53–64%** of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)\r\n  - `int.thresh=0` (no sensing): **0–1%** relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back\r\n\r\n  Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.\r\n\r\n- **Companion: `get/set txdelay`, `get/set direct.txdelay`, `get/set int.thresh` via [TerminalCLI](Companion_TerminalCLI_Commands.md).**\r\n\r\n  Relay timing and interference threshold are now configurable without reflashing.\r\n\r\n- **Companion: \"Heard N Repeats\" alert after Quick Send.**\r\n\r\n  After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.\r\n\r\n- **Companion: local time and date on the display.**\r\n\r\n  All pages now show the current time (`HH:MM`) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. `14 Apr 2026`).\r\n\r\n  Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via [TerminalCLI](Companion_TerminalCLI_Commands.md):\r\n  ```\r\n  set tz.offset 7    # UTC+7\r\n  set tz.offset -5   # UTC-5\r\n  get tz.offset\r\n  ```\r\n  Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.\r\n\r\n- **Companion: Metric / Imperial units.**\r\n\r\n  A new **Units** item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.\r\n\r\n  | Display | Metric | Imperial |\r\n  |---|---|---|\r\n  | GPS Trace distance | `150m` / `1.2km` | `492ft` / `0.7mi` |\r\n  | GPS page altitude | `245m` | `804ft` |\r\n  | Home page date | `14 Apr 2026` | `Apr 14 2026` |\r\n\r\n- **Companion: GPS Privacy mode.**\r\n\r\n  A new **GPS Privacy** item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…",
      "notesHtml": "<h3>v1.14_0417</h3>\n<ul>\n<li><p><strong>Hybrid RSSI + hardware CAD channel sensing (all node types).</strong></p>\n<p><code>isChannelActive()</code> now performs a two-stage check before transmitting:</p>\n<ol>\n<li>RSSI check (fast, single SPI register read) — defers if signal is above <code>noise_floor + int.thresh</code>.</li>\n<li>Hardware CAD (<code>scanChannel()</code>) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).</li>\n</ol>\n<p>RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.</p>\n<p><code>int.thresh=0</code> disables both RSSI and CAD. <code>int.thresh=1</code> enables full hybrid at maximum sensitivity.</p>\n<p><strong>On repeaters</strong> (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, <strong><code>txdelay=2</code></strong>, 100 messages):</p>\n<ul>\n<li><strong>Repeaters close together / strong inter-repeater signal:</strong> RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → <strong>9% collision rate</strong>.</li>\n<li><strong>Spread-out repeaters, some pairs below noise floor:</strong> RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD <strong>8%</strong> vs RSSI-only <strong>17%</strong>.</li>\n<li><strong>Many hidden node pairs:</strong> neither RSSI nor CAD helps. <strong>Only <code>txdelay</code> reduces the floor.</strong> Example: ~20–24% regardless of sensing method.</li>\n</ul>\n<p><strong>On companions</strong> (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):</p>\n<ul>\n<li><code>int.thresh=3</code>: <strong>53–64%</strong> of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)</li>\n<li><code>int.thresh=0</code> (no sensing): <strong>0–1%</strong> relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back</li>\n</ul>\n<p>Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.</p>\n</li>\n<li><p><strong>Companion: <code>get/set txdelay</code>, <code>get/set direct.txdelay</code>, <code>get/set int.thresh</code> via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>.</strong></p>\n<p>Relay timing and interference threshold are now configurable without reflashing.</p>\n</li>\n<li><p><strong>Companion: \"Heard N Repeats\" alert after Quick Send.</strong></p>\n<p>After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.</p>\n</li>\n<li><p><strong>Companion: local time and date on the display.</strong></p>\n<p>All pages now show the current time (<code>HH:MM</code>) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. <code>14 Apr 2026</code>).</p>\n<p>Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>:</p>\n<pre><code>set tz.offset 7    # UTC+7\nset tz.offset -5   # UTC-5\nget tz.offset\n</code></pre>\n<p>Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.</p>\n</li>\n<li><p><strong>Companion: Metric / Imperial units.</strong></p>\n<p>A new <strong>Units</strong> item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.</p>\n<table>\n<thead>\n<tr>\n<th>Display</th>\n<th>Metric</th>\n<th>Imperial</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>GPS Trace distance</td>\n<td><code>150m</code> / <code>1.2km</code></td>\n<td><code>492ft</code> / <code>0.7mi</code></td>\n</tr>\n<tr>\n<td>GPS page altitude</td>\n<td><code>245m</code></td>\n<td><code>804ft</code></td>\n</tr>\n<tr>\n<td>Home page date</td>\n<td><code>14 Apr 2026</code></td>\n<td><code>Apr 14 2026</code></td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>Companion: GPS Privacy mode.</strong></p>\n<p>A new <strong>GPS Privacy</strong> item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…</p>\n</li>\n</ul>\n"
    },
    {
      "version": "Heltec-V4-OLED-low-power-v1.14_0417",
      "name": "Heltec V4 OLED low power - v1.14_0417",
      "datetime": "2026-04-17T14:04:26Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/Heltec-V4-OLED-low-power-v1.14_0417",
      "prerelease": false,
      "notes": "### v1.14_0417\r\n\r\n- **Hybrid RSSI + hardware CAD channel sensing (all node types).**\r\n\r\n  `isChannelActive()` now performs a two-stage check before transmitting:\r\n  1. RSSI check (fast, single SPI register read) — defers if signal is above `noise_floor + int.thresh`.\r\n  2. Hardware CAD (`scanChannel()`) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).\r\n\r\n  RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.\r\n\r\n  `int.thresh=0` disables both RSSI and CAD. `int.thresh=1` enables full hybrid at maximum sensitivity.\r\n\r\n  **On repeaters** (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, **`txdelay=2`**, 100 messages):\r\n\r\n  - **Repeaters close together / strong inter-repeater signal:** RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → **9% collision rate**.\r\n  - **Spread-out repeaters, some pairs below noise floor:** RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD **8%** vs RSSI-only **17%**.\r\n  - **Many hidden node pairs:** neither RSSI nor CAD helps. **Only `txdelay` reduces the floor.** Example: ~20–24% regardless of sensing method.\r\n\r\n  **On companions** (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):\r\n\r\n  - `int.thresh=3`: **53–64%** of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)\r\n  - `int.thresh=0` (no sensing): **0–1%** relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back\r\n\r\n  Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.\r\n\r\n- **Companion: `get/set txdelay`, `get/set direct.txdelay`, `get/set int.thresh` via [TerminalCLI](Companion_TerminalCLI_Commands.md).**\r\n\r\n  Relay timing and interference threshold are now configurable without reflashing.\r\n\r\n- **Companion: \"Heard N Repeats\" alert after Quick Send.**\r\n\r\n  After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.\r\n\r\n- **Companion: local time and date on the display.**\r\n\r\n  All pages now show the current time (`HH:MM`) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. `14 Apr 2026`).\r\n\r\n  Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via [TerminalCLI](Companion_TerminalCLI_Commands.md):\r\n  ```\r\n  set tz.offset 7    # UTC+7\r\n  set tz.offset -5   # UTC-5\r\n  get tz.offset\r\n  ```\r\n  Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.\r\n\r\n- **Companion: Metric / Imperial units.**\r\n\r\n  A new **Units** item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.\r\n\r\n  | Display | Metric | Imperial |\r\n  |---|---|---|\r\n  | GPS Trace distance | `150m` / `1.2km` | `492ft` / `0.7mi` |\r\n  | GPS page altitude | `245m` | `804ft` |\r\n  | Home page date | `14 Apr 2026` | `Apr 14 2026` |\r\n\r\n- **Companion: GPS Privacy mode.**\r\n\r\n  A new **GPS Privacy** item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…",
      "notesHtml": "<h3>v1.14_0417</h3>\n<ul>\n<li><p><strong>Hybrid RSSI + hardware CAD channel sensing (all node types).</strong></p>\n<p><code>isChannelActive()</code> now performs a two-stage check before transmitting:</p>\n<ol>\n<li>RSSI check (fast, single SPI register read) — defers if signal is above <code>noise_floor + int.thresh</code>.</li>\n<li>Hardware CAD (<code>scanChannel()</code>) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).</li>\n</ol>\n<p>RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.</p>\n<p><code>int.thresh=0</code> disables both RSSI and CAD. <code>int.thresh=1</code> enables full hybrid at maximum sensitivity.</p>\n<p><strong>On repeaters</strong> (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, <strong><code>txdelay=2</code></strong>, 100 messages):</p>\n<ul>\n<li><strong>Repeaters close together / strong inter-repeater signal:</strong> RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → <strong>9% collision rate</strong>.</li>\n<li><strong>Spread-out repeaters, some pairs below noise floor:</strong> RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD <strong>8%</strong> vs RSSI-only <strong>17%</strong>.</li>\n<li><strong>Many hidden node pairs:</strong> neither RSSI nor CAD helps. <strong>Only <code>txdelay</code> reduces the floor.</strong> Example: ~20–24% regardless of sensing method.</li>\n</ul>\n<p><strong>On companions</strong> (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):</p>\n<ul>\n<li><code>int.thresh=3</code>: <strong>53–64%</strong> of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)</li>\n<li><code>int.thresh=0</code> (no sensing): <strong>0–1%</strong> relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back</li>\n</ul>\n<p>Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.</p>\n</li>\n<li><p><strong>Companion: <code>get/set txdelay</code>, <code>get/set direct.txdelay</code>, <code>get/set int.thresh</code> via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>.</strong></p>\n<p>Relay timing and interference threshold are now configurable without reflashing.</p>\n</li>\n<li><p><strong>Companion: \"Heard N Repeats\" alert after Quick Send.</strong></p>\n<p>After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.</p>\n</li>\n<li><p><strong>Companion: local time and date on the display.</strong></p>\n<p>All pages now show the current time (<code>HH:MM</code>) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. <code>14 Apr 2026</code>).</p>\n<p>Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>:</p>\n<pre><code>set tz.offset 7    # UTC+7\nset tz.offset -5   # UTC-5\nget tz.offset\n</code></pre>\n<p>Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.</p>\n</li>\n<li><p><strong>Companion: Metric / Imperial units.</strong></p>\n<p>A new <strong>Units</strong> item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.</p>\n<table>\n<thead>\n<tr>\n<th>Display</th>\n<th>Metric</th>\n<th>Imperial</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>GPS Trace distance</td>\n<td><code>150m</code> / <code>1.2km</code></td>\n<td><code>492ft</code> / <code>0.7mi</code></td>\n</tr>\n<tr>\n<td>GPS page altitude</td>\n<td><code>245m</code></td>\n<td><code>804ft</code></td>\n</tr>\n<tr>\n<td>Home page date</td>\n<td><code>14 Apr 2026</code></td>\n<td><code>Apr 14 2026</code></td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>Companion: GPS Privacy mode.</strong></p>\n<p>A new <strong>GPS Privacy</strong> item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…</p>\n</li>\n</ul>\n"
    },
    {
      "version": "Heltec-V3-WSL3-low-power-v1.14_0417",
      "name": "Heltec V3 & WSL3 low power - v1.14_0417",
      "datetime": "2026-04-17T14:00:08Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/Heltec-V3-WSL3-low-power-v1.14_0417",
      "prerelease": false,
      "notes": "### v1.14_0417\r\n\r\n- **Hybrid RSSI + hardware CAD channel sensing (all node types).**\r\n\r\n  `isChannelActive()` now performs a two-stage check before transmitting:\r\n  1. RSSI check (fast, single SPI register read) — defers if signal is above `noise_floor + int.thresh`.\r\n  2. Hardware CAD (`scanChannel()`) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).\r\n\r\n  RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.\r\n\r\n  `int.thresh=0` disables both RSSI and CAD. `int.thresh=1` enables full hybrid at maximum sensitivity.\r\n\r\n  **On repeaters** (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, **`txdelay=2`**, 100 messages):\r\n\r\n  - **Repeaters close together / strong inter-repeater signal:** RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → **9% collision rate**.\r\n  - **Spread-out repeaters, some pairs below noise floor:** RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD **8%** vs RSSI-only **17%**.\r\n  - **Many hidden node pairs:** neither RSSI nor CAD helps. **Only `txdelay` reduces the floor.** Example: ~20–24% regardless of sensing method.\r\n\r\n  **On companions** (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):\r\n\r\n  - `int.thresh=3`: **53–64%** of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)\r\n  - `int.thresh=0` (no sensing): **0–1%** relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back\r\n\r\n  Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.\r\n\r\n- **Companion: `get/set txdelay`, `get/set direct.txdelay`, `get/set int.thresh` via [TerminalCLI](Companion_TerminalCLI_Commands.md).**\r\n\r\n  Relay timing and interference threshold are now configurable without reflashing.\r\n\r\n- **Companion: \"Heard N Repeats\" alert after Quick Send.**\r\n\r\n  After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.\r\n\r\n- **Companion: local time and date on the display.**\r\n\r\n  All pages now show the current time (`HH:MM`) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. `14 Apr 2026`).\r\n\r\n  Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via [TerminalCLI](Companion_TerminalCLI_Commands.md):\r\n  ```\r\n  set tz.offset 7    # UTC+7\r\n  set tz.offset -5   # UTC-5\r\n  get tz.offset\r\n  ```\r\n  Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.\r\n\r\n- **Companion: Metric / Imperial units.**\r\n\r\n  A new **Units** item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.\r\n\r\n  | Display | Metric | Imperial |\r\n  |---|---|---|\r\n  | GPS Trace distance | `150m` / `1.2km` | `492ft` / `0.7mi` |\r\n  | GPS page altitude | `245m` | `804ft` |\r\n  | Home page date | `14 Apr 2026` | `Apr 14 2026` |\r\n\r\n- **Companion: GPS Privacy mode.**\r\n\r\n  A new **GPS Privacy** item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…",
      "notesHtml": "<h3>v1.14_0417</h3>\n<ul>\n<li><p><strong>Hybrid RSSI + hardware CAD channel sensing (all node types).</strong></p>\n<p><code>isChannelActive()</code> now performs a two-stage check before transmitting:</p>\n<ol>\n<li>RSSI check (fast, single SPI register read) — defers if signal is above <code>noise_floor + int.thresh</code>.</li>\n<li>Hardware CAD (<code>scanChannel()</code>) — if RSSI misses, performs LoRa chirp correlation to detect signals below the noise floor (~16ms blocking scan on SX126x).</li>\n</ol>\n<p>RSSI also detects any in-band signal (interference, jamming), while CAD only correlates LoRa chirp patterns and ignores non-LoRa noise entirely. With hybrid, RSSI acts as the first guard — CAD only runs when the channel appears clear to RSSI.</p>\n<p><code>int.thresh=0</code> disables both RSSI and CAD. <code>int.thresh=1</code> enables full hybrid at maximum sensitivity.</p>\n<p><strong>On repeaters</strong> (single source sending): results depend on topology. Field tests with 4 repeaters (SF8/BW62.5kHz, <strong><code>txdelay=2</code></strong>, 100 messages):</p>\n<ul>\n<li><strong>Repeaters close together / strong inter-repeater signal:</strong> RSSI handles detection well, CAD rarely fires. Example: int.thresh=1 → <strong>9% collision rate</strong>.</li>\n<li><strong>Spread-out repeaters, some pairs below noise floor:</strong> RSSI misses sub-NF pairs; CAD fills the gap. Example: hybrid/CAD <strong>8%</strong> vs RSSI-only <strong>17%</strong>.</li>\n<li><strong>Many hidden node pairs:</strong> neither RSSI nor CAD helps. <strong>Only <code>txdelay</code> reduces the floor.</strong> Example: ~20–24% regardless of sensing method.</li>\n</ul>\n<p><strong>On companions</strong> (multiple sources sending concurrently): channel sensing still helps, but with diminishing returns. Tested with 2 concurrent companions plus a third node sending long messages every 5s (SF8/BW62.5kHz):</p>\n<ul>\n<li><code>int.thresh=3</code>: <strong>53–64%</strong> of messages successfully relayed by all 4 repeaters (confirmed by hearing each relay back)</li>\n<li><code>int.thresh=0</code> (no sensing): <strong>0–1%</strong> relayed by all 4; most messages are relayed by 0–1 repeaters only — collisions occur at two levels: concurrent companion transmissions corrupt each other at the repeater, and the resulting relay transmissions from multiple repeaters collide on the way back</li>\n</ul>\n<p>Channel sensing — even imperfect — is far better than none. The remaining loss at int.thresh=3 is a fundamental ALOHA-style limitation: uncoordinated LoRa nodes cannot eliminate simultaneous transmission without a shared scheduling mechanism that does not exist in this protocol.</p>\n</li>\n<li><p><strong>Companion: <code>get/set txdelay</code>, <code>get/set direct.txdelay</code>, <code>get/set int.thresh</code> via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>.</strong></p>\n<p>Relay timing and interference threshold are now configurable without reflashing.</p>\n</li>\n<li><p><strong>Companion: \"Heard N Repeats\" alert after Quick Send.</strong></p>\n<p>After sending from the Quick Send screen, the display shows how many repeaters have relayed the message (e.g. \"Heard 3 Repeats\"). The counter updates in real time as each relay is heard.</p>\n</li>\n<li><p><strong>Companion: local time and date on the display.</strong></p>\n<p>All pages now show the current time (<code>HH:MM</code>) in the header, between the page title and the battery icon. The Home page also shows the full date at the bottom (e.g. <code>14 Apr 2026</code>).</p>\n<p>Time is sourced from the device RTC, which is synchronized upon app connection or GPS fix. Configure your local timezone offset once via <a href=\"https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/blob/HEAD/Companion_TerminalCLI_Commands.md\" target=\"_blank\" rel=\"noopener noreferrer\">TerminalCLI</a>:</p>\n<pre><code>set tz.offset 7    # UTC+7\nset tz.offset -5   # UTC-5\nget tz.offset\n</code></pre>\n<p>Offset is saved to flash. All internal timestamps remain UTC — the offset is applied only for display.</p>\n</li>\n<li><p><strong>Companion: Metric / Imperial units.</strong></p>\n<p>A new <strong>Units</strong> item in the Settings page toggles between Metric and Imperial. Setting is saved to flash and persists after reboot.</p>\n<table>\n<thead>\n<tr>\n<th>Display</th>\n<th>Metric</th>\n<th>Imperial</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>GPS Trace distance</td>\n<td><code>150m</code> / <code>1.2km</code></td>\n<td><code>492ft</code> / <code>0.7mi</code></td>\n</tr>\n<tr>\n<td>GPS page altitude</td>\n<td><code>245m</code></td>\n<td><code>804ft</code></td>\n</tr>\n<tr>\n<td>Home page date</td>\n<td><code>14 Apr 2026</code></td>\n<td><code>Apr 14 2026</code></td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>Companion: GPS Privacy mode.</strong></p>\n<p>A new <strong>GPS Privacy</strong> item in the Settings page lets you stop GPS coordinates from being attached to Quick Send me\n…</p>\n</li>\n</ul>\n"
    },
    {
      "version": "Heltec-V4-OLED-low-power-v1.14_0410",
      "name": "Heltec V4 OLED low power - v1.14_0410",
      "datetime": "2026-04-10T04:40:07Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/Heltec-V4-OLED-low-power-v1.14_0410",
      "prerelease": false,
      "notes": "### v1.14_0410\r\n\r\n- **Message preview: scroll long messages & see all 256 buffered messages.**\r\n\r\n  The message preview screen is rebuilt from the ground up. All 256 buffered messages are now navigable — previously capped at 32. Long messages that overflow the screen can be scrolled line by line.\r\n\r\n  #### Button controls in message preview\r\n\r\n  | Action | Effect |\r\n  |---|---|\r\n  | **Single click** | Scroll text down (3 lines); advances to next older message at end of text |\r\n  | **Double click** | Scroll text up (3 lines); goes to next newer message at top; at newest → home |\r\n  | **Long press** | Open menu: **Save location** *(if message has GPS coords)* / **Home** |\r\n\r\n  #### Counter and unread tracking\r\n\r\n  ```\r\n  ┌──────────────────────────────┐\r\n  │ 5/19                    42s  │\r\n  │──────────────────────────────│\r\n  │ (2) Alien:                   │\r\n  │ Hello everyone, just wanted  │\r\n  │ to check in. We made it to   │\r\n  │ base camp safe and sound.    │\r\n  │                           ▼  │\r\n  └──────────────────────────────┘\r\n  ```\r\n\r\n  `5/19` = viewing message 5 (newest = 19, oldest = 1). `▼` = more text below. `42s` = time since received. The counter tracks unread messages — when you close preview and return, only new messages since last session are counted.\r\n\r\n- **Saved Locations: save GPS coordinates from messages to flash.**\r\n\r\n  When viewing a message with GPS coordinates, long press opens a menu. Choose **Save location**, then pick one of 10 slots to save into. Saved locations persist in flash memory — they survive reboot.\r\n\r\n  Navigate to the **SAVED LOCS** page on the home screen to browse your saved locations and open the GPS Trace screen for any of them.\r\n\r\n  ```\r\n  ┌──────────────────────────────┐\r\n  │ SAVED  2/10                  │\r\n  │──────────────────────────────│\r\n  │ > Alien: I need help         │\r\n  │   Big Boy: Heading home      │\r\n  │                              │\r\n  │                              │\r\n  └──────────────────────────────┘\r\n  ```\r\n\r\n  Each entry shows **sender + message snippet** so you can identify entries even when multiple locations from the same person are saved.\r\n\r\n  | Press | Effect |\r\n  |---|---|\r\n  | Single click | Move highlight to next entry |\r\n  | Long press | Open GPS Trace screen for that location |\r\n  | Double click | Return to home |\r\n\r\n- **GPS Trace screen: live distance & bearing to a saved location.**\r\n\r\n  ```\r\n  ┌──────────────────────────────┐\r\n  │ Alien: I need help       5m  │\r\n  │──────────────────────────────│\r\n  │      10.7769  106.7009       │\r\n  │                              │\r\n  │           1.2km              │\r\n  │                              │\r\n  │          247°  WSW           │\r\n  └──────────────────────────────┘\r\n  ```\r\n\r\n  The timer in the top-right corner shows how long you have been on this Trace screen. Requires own GPS fix for distance/bearing. Raw coordinates are always shown. Any button returns to the Saved Locations list.\r\n\r\n- **Saved locations CLI commands (TerminalCLI).**\r\n\r\n  Manage saved locations from the terminal without touching the display:\r\n\r\n  | Command | Effect |\r\n  |---|---|\r\n  | `get loc` | List all occupied slots (`N:lat,lon:name`, N is 0-based) |\r\n  | `set loc.<N> <name> <lat> <lon>` | Save to slot N (0-based; display shows 1–10) |\r\n  | `del loc.<N>` | Clear slot N (0-based) |\r\n  | `del loc.all` | Clear all slots |",
      "notesHtml": "<h3>v1.14_0410</h3>\n<ul>\n<li><p><strong>Message preview: scroll long messages &amp; see all 256 buffered messages.</strong></p>\n<p>The message preview screen is rebuilt from the ground up. All 256 buffered messages are now navigable — previously capped at 32. Long messages that overflow the screen can be scrolled line by line.</p>\n<h4>Button controls in message preview</h4>\n<table>\n<thead>\n<tr>\n<th>Action</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><strong>Single click</strong></td>\n<td>Scroll text down (3 lines); advances to next older message at end of text</td>\n</tr>\n<tr>\n<td><strong>Double click</strong></td>\n<td>Scroll text up (3 lines); goes to next newer message at top; at newest → home</td>\n</tr>\n<tr>\n<td><strong>Long press</strong></td>\n<td>Open menu: <strong>Save location</strong> <em>(if message has GPS coords)</em> / <strong>Home</strong></td>\n</tr>\n</tbody></table>\n<h4>Counter and unread tracking</h4>\n<pre><code>┌──────────────────────────────┐\n│ 5/19                    42s  │\n│──────────────────────────────│\n│ (2) Alien:                   │\n│ Hello everyone, just wanted  │\n│ to check in. We made it to   │\n│ base camp safe and sound.    │\n│                           ▼  │\n└──────────────────────────────┘\n</code></pre>\n<p><code>5/19</code> = viewing message 5 (newest = 19, oldest = 1). <code>▼</code> = more text below. <code>42s</code> = time since received. The counter tracks unread messages — when you close preview and return, only new messages since last session are counted.</p>\n</li>\n<li><p><strong>Saved Locations: save GPS coordinates from messages to flash.</strong></p>\n<p>When viewing a message with GPS coordinates, long press opens a menu. Choose <strong>Save location</strong>, then pick one of 10 slots to save into. Saved locations persist in flash memory — they survive reboot.</p>\n<p>Navigate to the <strong>SAVED LOCS</strong> page on the home screen to browse your saved locations and open the GPS Trace screen for any of them.</p>\n<pre><code>┌──────────────────────────────┐\n│ SAVED  2/10                  │\n│──────────────────────────────│\n│ &gt; Alien: I need help         │\n│   Big Boy: Heading home      │\n│                              │\n│                              │\n└──────────────────────────────┘\n</code></pre>\n<p>Each entry shows <strong>sender + message snippet</strong> so you can identify entries even when multiple locations from the same person are saved.</p>\n<table>\n<thead>\n<tr>\n<th>Press</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Single click</td>\n<td>Move highlight to next entry</td>\n</tr>\n<tr>\n<td>Long press</td>\n<td>Open GPS Trace screen for that location</td>\n</tr>\n<tr>\n<td>Double click</td>\n<td>Return to home</td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>GPS Trace screen: live distance &amp; bearing to a saved location.</strong></p>\n<pre><code>┌──────────────────────────────┐\n│ Alien: I need help       5m  │\n│──────────────────────────────│\n│      10.7769  106.7009       │\n│                              │\n│           1.2km              │\n│                              │\n│          247°  WSW           │\n└──────────────────────────────┘\n</code></pre>\n<p>The timer in the top-right corner shows how long you have been on this Trace screen. Requires own GPS fix for distance/bearing. Raw coordinates are always shown. Any button returns to the Saved Locations list.</p>\n</li>\n<li><p><strong>Saved locations CLI commands (TerminalCLI).</strong></p>\n<p>Manage saved locations from the terminal without touching the display:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>get loc</code></td>\n<td>List all occupied slots (<code>N:lat,lon:name</code>, N is 0-based)</td>\n</tr>\n<tr>\n<td><code>set loc.&lt;N&gt; &lt;name&gt; &lt;lat&gt; &lt;lon&gt;</code></td>\n<td>Save to slot N (0-based; display shows 1–10)</td>\n</tr>\n<tr>\n<td><code>del loc.&lt;N&gt;</code></td>\n<td>Clear slot N (0-based)</td>\n</tr>\n<tr>\n<td><code>del loc.all</code></td>\n<td>Clear all slots</td>\n</tr>\n</tbody></table>\n</li>\n</ul>\n"
    },
    {
      "version": "Heltec-V3-WSL3-low-power-v1.14_0410",
      "name": "Heltec V3 & WSL3 low power - v1.14_0410",
      "datetime": "2026-04-10T04:32:34Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/Heltec-V3-WSL3-low-power-v1.14_0410",
      "prerelease": false,
      "notes": "### v1.14_0410\r\n\r\n- **Message preview: scroll long messages & see all 256 buffered messages.**\r\n\r\n  The message preview screen is rebuilt from the ground up. All 256 buffered messages are now navigable — previously capped at 32. Long messages that overflow the screen can be scrolled line by line.\r\n\r\n  #### Button controls in message preview\r\n\r\n  | Action | Effect |\r\n  |---|---|\r\n  | **Single click** | Scroll text down (3 lines); advances to next older message at end of text |\r\n  | **Double click** | Scroll text up (3 lines); goes to next newer message at top; at newest → home |\r\n  | **Long press** | Open menu: **Save location** *(if message has GPS coords)* / **Home** |\r\n\r\n  #### Counter and unread tracking\r\n\r\n  ```\r\n  ┌──────────────────────────────┐\r\n  │ 5/19                    42s  │\r\n  │──────────────────────────────│\r\n  │ (2) Alien:                   │\r\n  │ Hello everyone, just wanted  │\r\n  │ to check in. We made it to   │\r\n  │ base camp safe and sound.    │\r\n  │                           ▼  │\r\n  └──────────────────────────────┘\r\n  ```\r\n\r\n  `5/19` = viewing message 5 (newest = 19, oldest = 1). `▼` = more text below. `42s` = time since received. The counter tracks unread messages — when you close preview and return, only new messages since last session are counted.\r\n\r\n- **Saved Locations: save GPS coordinates from messages to flash.**\r\n\r\n  When viewing a message with GPS coordinates, long press opens a menu. Choose **Save location**, then pick one of 10 slots to save into. Saved locations persist in flash memory — they survive reboot.\r\n\r\n  Navigate to the **SAVED LOCS** page on the home screen to browse your saved locations and open the GPS Trace screen for any of them.\r\n\r\n  ```\r\n  ┌──────────────────────────────┐\r\n  │ SAVED  2/10                  │\r\n  │──────────────────────────────│\r\n  │ > Alien: I need help         │\r\n  │   Big Boy: Heading home      │\r\n  │                              │\r\n  │                              │\r\n  └──────────────────────────────┘\r\n  ```\r\n\r\n  Each entry shows **sender + message snippet** so you can identify entries even when multiple locations from the same person are saved.\r\n\r\n  | Press | Effect |\r\n  |---|---|\r\n  | Single click | Move highlight to next entry |\r\n  | Long press | Open GPS Trace screen for that location |\r\n  | Double click | Return to home |\r\n\r\n- **GPS Trace screen: live distance & bearing to a saved location.**\r\n\r\n  ```\r\n  ┌──────────────────────────────┐\r\n  │ Alien: I need help       5m  │\r\n  │──────────────────────────────│\r\n  │      10.7769  106.7009       │\r\n  │                              │\r\n  │           1.2km              │\r\n  │                              │\r\n  │          247°  WSW           │\r\n  └──────────────────────────────┘\r\n  ```\r\n\r\n  The timer in the top-right corner shows how long you have been on this Trace screen. Requires own GPS fix for distance/bearing. Raw coordinates are always shown. Any button returns to the Saved Locations list.\r\n\r\n- **Saved locations CLI commands (TerminalCLI).**\r\n\r\n  Manage saved locations from the terminal without touching the display:\r\n\r\n  | Command | Effect |\r\n  |---|---|\r\n  | `get loc` | List all occupied slots (`N:lat,lon:name`, N is 0-based) |\r\n  | `set loc.<N> <name> <lat> <lon>` | Save to slot N (0-based; display shows 1–10) |\r\n  | `del loc.<N>` | Clear slot N (0-based) |\r\n  | `del loc.all` | Clear all slots |",
      "notesHtml": "<h3>v1.14_0410</h3>\n<ul>\n<li><p><strong>Message preview: scroll long messages &amp; see all 256 buffered messages.</strong></p>\n<p>The message preview screen is rebuilt from the ground up. All 256 buffered messages are now navigable — previously capped at 32. Long messages that overflow the screen can be scrolled line by line.</p>\n<h4>Button controls in message preview</h4>\n<table>\n<thead>\n<tr>\n<th>Action</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><strong>Single click</strong></td>\n<td>Scroll text down (3 lines); advances to next older message at end of text</td>\n</tr>\n<tr>\n<td><strong>Double click</strong></td>\n<td>Scroll text up (3 lines); goes to next newer message at top; at newest → home</td>\n</tr>\n<tr>\n<td><strong>Long press</strong></td>\n<td>Open menu: <strong>Save location</strong> <em>(if message has GPS coords)</em> / <strong>Home</strong></td>\n</tr>\n</tbody></table>\n<h4>Counter and unread tracking</h4>\n<pre><code>┌──────────────────────────────┐\n│ 5/19                    42s  │\n│──────────────────────────────│\n│ (2) Alien:                   │\n│ Hello everyone, just wanted  │\n│ to check in. We made it to   │\n│ base camp safe and sound.    │\n│                           ▼  │\n└──────────────────────────────┘\n</code></pre>\n<p><code>5/19</code> = viewing message 5 (newest = 19, oldest = 1). <code>▼</code> = more text below. <code>42s</code> = time since received. The counter tracks unread messages — when you close preview and return, only new messages since last session are counted.</p>\n</li>\n<li><p><strong>Saved Locations: save GPS coordinates from messages to flash.</strong></p>\n<p>When viewing a message with GPS coordinates, long press opens a menu. Choose <strong>Save location</strong>, then pick one of 10 slots to save into. Saved locations persist in flash memory — they survive reboot.</p>\n<p>Navigate to the <strong>SAVED LOCS</strong> page on the home screen to browse your saved locations and open the GPS Trace screen for any of them.</p>\n<pre><code>┌──────────────────────────────┐\n│ SAVED  2/10                  │\n│──────────────────────────────│\n│ &gt; Alien: I need help         │\n│   Big Boy: Heading home      │\n│                              │\n│                              │\n└──────────────────────────────┘\n</code></pre>\n<p>Each entry shows <strong>sender + message snippet</strong> so you can identify entries even when multiple locations from the same person are saved.</p>\n<table>\n<thead>\n<tr>\n<th>Press</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Single click</td>\n<td>Move highlight to next entry</td>\n</tr>\n<tr>\n<td>Long press</td>\n<td>Open GPS Trace screen for that location</td>\n</tr>\n<tr>\n<td>Double click</td>\n<td>Return to home</td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>GPS Trace screen: live distance &amp; bearing to a saved location.</strong></p>\n<pre><code>┌──────────────────────────────┐\n│ Alien: I need help       5m  │\n│──────────────────────────────│\n│      10.7769  106.7009       │\n│                              │\n│           1.2km              │\n│                              │\n│          247°  WSW           │\n└──────────────────────────────┘\n</code></pre>\n<p>The timer in the top-right corner shows how long you have been on this Trace screen. Requires own GPS fix for distance/bearing. Raw coordinates are always shown. Any button returns to the Saved Locations list.</p>\n</li>\n<li><p><strong>Saved locations CLI commands (TerminalCLI).</strong></p>\n<p>Manage saved locations from the terminal without touching the display:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>get loc</code></td>\n<td>List all occupied slots (<code>N:lat,lon:name</code>, N is 0-based)</td>\n</tr>\n<tr>\n<td><code>set loc.&lt;N&gt; &lt;name&gt; &lt;lat&gt; &lt;lon&gt;</code></td>\n<td>Save to slot N (0-based; display shows 1–10)</td>\n</tr>\n<tr>\n<td><code>del loc.&lt;N&gt;</code></td>\n<td>Clear slot N (0-based)</td>\n</tr>\n<tr>\n<td><code>del loc.all</code></td>\n<td>Clear all slots</td>\n</tr>\n</tbody></table>\n</li>\n</ul>\n"
    },
    {
      "version": "RAK4631-low-power-v1.14_0404",
      "name": "RAK4631 low power - v1.14_0404",
      "datetime": "2026-04-04T10:34:37Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/RAK4631-low-power-v1.14_0404",
      "prerelease": false,
      "notes": "Ported the BLE random disconnection fix from ESP32 to nRF52.",
      "notesHtml": "<p>Ported the BLE random disconnection fix from ESP32 to nRF52.</p>\n"
    },
    {
      "version": "Heltec-V4-OLED-low-power-v1.14_0404",
      "name": "Heltec V4 OLED low power - v1.14_0404",
      "datetime": "2026-04-04T10:51:14Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/Heltec-V4-OLED-low-power-v1.14_0404",
      "prerelease": false,
      "notes": "### v1.14_0404\r\n\r\n- **Quick Send and Settings — control your Companion without a phone.**\r\n\r\n  Two new pages are added to the Companion's display, accessible without a phone or app.\r\n\r\n  #### Button controls\r\n\r\n  - **Single click / Double click** — navigate between pages (next / previous)\r\n  - **Long press on FIRST page** — reopen unread message preview (up to 32 messages buffered)\r\n  - **Long press** on Quick Send or Settings — enter the page; active item highlights\r\n    - Single click = next item · Double click = exit · Long press = confirm\r\n\r\n  #### Quick Send\r\n\r\n  Send a short status message directly over LoRa to the public channel — no typing, no phone needed. Useful when your phone is dead or unavailable.\r\n\r\n  GPS coordinates are automatically appended if available (e.g. `I'm OK @10.7769,106.7009`). If GPS has no current fix, last known coordinates are used with a `?` prefix so you know before sending.\r\n\r\n  **10 built-in presets:**\r\n  - I'm OK\r\n  - On my way\r\n  - I need help\r\n  - Everyone OK here\r\n  - Wait for me\r\n  - Heading home\r\n  - Running late\r\n  - Lost contact, call me\r\n  - Battery low, signing off\r\n  - All clear\r\n\r\n  **Customize via TerminalCLI** — changes are saved to flash and persist after reboot:\r\n  ```\r\n  get quick                        list all current presets\r\n  set quick.0 Arrived at camp      set preset at index 0\r\n  set quick.reset                  restore all 10 built-in defaults\r\n  ```\r\n\r\n  #### Settings\r\n\r\n  A scrollable list of device settings, controlled directly from the button:\r\n\r\n  | Item | Action |\r\n  |---|---|\r\n  | BLE | Toggle Bluetooth on/off (shows connection state) |\r\n  | Repeat | Toggle repeat mode on/off |\r\n  | RxGain | Cycle RxGain mode: OFF → ON → AUTO *(AUTO: V4.2 only)* |\r\n  | Buzzer | Toggle buzzer on/muted *(boards with buzzer only)* |\r\n  | Send Advert | Broadcast your presence to nearby nodes |\r\n  | Start OTA | Start OTA update mode — connect to `MeshCore-OTA` WiFi and go to `192.168.4.1/update` |\r\n  | Shutdown | Power off the device |\r\n\r\n- **Heltec V4.3 support (KCT8103L FEM).**\r\n  Firmware automatically detects V4.2 / V4.3 at boot — no configuration required. V4.3 replaces the GC1109 FEM with KCT8103L, which supports explicit LNA/bypass RX mode selection via `radio.rxgain`.\r\n\r\n  | Mode | Description |\r\n  |---|---|\r\n  | `on` *(default)* | FEM LNA active — best sensitivity |\r\n  | `off` | FEM bypass — SX1262 boosted gain compensates, better in high-interference environments near strong transmitters |\r\n\r\n  > V4.3 does **not** support `auto` mode — use `on` or `off`.\r\n\r\n  **TerminalCLI** (Companion app), **Command Line** (Repeater / Room Server):\r\n  ```\r\n  set radio.rxgain on\r\n  set radio.rxgain off\r\n  get radio.rxgain\r\n  ```\r\n  \r\n  Setting is saved and restored after reboot.\r\n\r\n- **Unified firmware for \"No Display\" hardware variants.**\r\n\r\n  A single firmware binary now runs on both OLED and no-display hardware — no separate build required. The display is detected automatically at boot via I2C probe.\r\n\r\n  | Hardware | Detected as |\r\n  |---|---|\r\n  | Heltec V4.2 with OLED | Heltec V4.2 OLED |\r\n  | Heltec V4.2 without OLED | Heltec V4.2 No Display |\r\n  | Heltec V4.3 with OLED | Heltec V4.3 OLED |\r\n  | Heltec V4.3 without OLED | Heltec V4.3 No Display |\r\n\r\n  The device name shown in the MeshCore app reflects the actual hardware detected. On no-display hardware, the user button has no effect (previously it could trigger unintended I2C writes).",
      "notesHtml": "<h3>v1.14_0404</h3>\n<ul>\n<li><p><strong>Quick Send and Settings — control your Companion without a phone.</strong></p>\n<p>Two new pages are added to the Companion's display, accessible without a phone or app.</p>\n<h4>Button controls</h4>\n<ul>\n<li><strong>Single click / Double click</strong> — navigate between pages (next / previous)</li>\n<li><strong>Long press on FIRST page</strong> — reopen unread message preview (up to 32 messages buffered)</li>\n<li><strong>Long press</strong> on Quick Send or Settings — enter the page; active item highlights<ul>\n<li>Single click = next item · Double click = exit · Long press = confirm</li>\n</ul>\n</li>\n</ul>\n<h4>Quick Send</h4>\n<p>Send a short status message directly over LoRa to the public channel — no typing, no phone needed. Useful when your phone is dead or unavailable.</p>\n<p>GPS coordinates are automatically appended if available (e.g. <code>I'm OK @10.7769,106.7009</code>). If GPS has no current fix, last known coordinates are used with a <code>?</code> prefix so you know before sending.</p>\n<p><strong>10 built-in presets:</strong></p>\n<ul>\n<li>I'm OK</li>\n<li>On my way</li>\n<li>I need help</li>\n<li>Everyone OK here</li>\n<li>Wait for me</li>\n<li>Heading home</li>\n<li>Running late</li>\n<li>Lost contact, call me</li>\n<li>Battery low, signing off</li>\n<li>All clear</li>\n</ul>\n<p><strong>Customize via TerminalCLI</strong> — changes are saved to flash and persist after reboot:</p>\n<pre><code>get quick                        list all current presets\nset quick.0 Arrived at camp      set preset at index 0\nset quick.reset                  restore all 10 built-in defaults\n</code></pre>\n<h4>Settings</h4>\n<p>A scrollable list of device settings, controlled directly from the button:</p>\n<table>\n<thead>\n<tr>\n<th>Item</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>BLE</td>\n<td>Toggle Bluetooth on/off (shows connection state)</td>\n</tr>\n<tr>\n<td>Repeat</td>\n<td>Toggle repeat mode on/off</td>\n</tr>\n<tr>\n<td>RxGain</td>\n<td>Cycle RxGain mode: OFF → ON → AUTO <em>(AUTO: V4.2 only)</em></td>\n</tr>\n<tr>\n<td>Buzzer</td>\n<td>Toggle buzzer on/muted <em>(boards with buzzer only)</em></td>\n</tr>\n<tr>\n<td>Send Advert</td>\n<td>Broadcast your presence to nearby nodes</td>\n</tr>\n<tr>\n<td>Start OTA</td>\n<td>Start OTA update mode — connect to <code>MeshCore-OTA</code> WiFi and go to <code>192.168.4.1/update</code></td>\n</tr>\n<tr>\n<td>Shutdown</td>\n<td>Power off the device</td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>Heltec V4.3 support (KCT8103L FEM).</strong>\nFirmware automatically detects V4.2 / V4.3 at boot — no configuration required. V4.3 replaces the GC1109 FEM with KCT8103L, which supports explicit LNA/bypass RX mode selection via <code>radio.rxgain</code>.</p>\n<table>\n<thead>\n<tr>\n<th>Mode</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>on</code> <em>(default)</em></td>\n<td>FEM LNA active — best sensitivity</td>\n</tr>\n<tr>\n<td><code>off</code></td>\n<td>FEM bypass — SX1262 boosted gain compensates, better in high-interference environments near strong transmitters</td>\n</tr>\n</tbody></table>\n<blockquote>\n<p>V4.3 does <strong>not</strong> support <code>auto</code> mode — use <code>on</code> or <code>off</code>.</p>\n</blockquote>\n<p><strong>TerminalCLI</strong> (Companion app), <strong>Command Line</strong> (Repeater / Room Server):</p>\n<pre><code>set radio.rxgain on\nset radio.rxgain off\nget radio.rxgain\n</code></pre>\n<p>Setting is saved and restored after reboot.</p>\n</li>\n<li><p><strong>Unified firmware for \"No Display\" hardware variants.</strong></p>\n<p>A single firmware binary now runs on both OLED and no-display hardware — no separate build required. The display is detected automatically at boot via I2C probe.</p>\n<table>\n<thead>\n<tr>\n<th>Hardware</th>\n<th>Detected as</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Heltec V4.2 with OLED</td>\n<td>Heltec V4.2 OLED</td>\n</tr>\n<tr>\n<td>Heltec V4.2 without OLED</td>\n<td>Heltec V4.2 No Display</td>\n</tr>\n<tr>\n<td>Heltec V4.3 with OLED</td>\n<td>Heltec V4.3 OLED</td>\n</tr>\n<tr>\n<td>Heltec V4.3 without OLED</td>\n<td>Heltec V4.3 No Display</td>\n</tr>\n</tbody></table>\n<p>The device name shown in the MeshCore app reflects the actual hardware detected. On no-display hardware, the user button has no effect (previously it could trigger unintended I2C writes).</p>\n</li>\n</ul>\n"
    },
    {
      "version": "Heltec-V3-WSL3-low-power-v1.14_0404",
      "name": "Heltec V3 & WSL3 low power - v1.14_0404",
      "datetime": "2026-04-04T10:47:33Z",
      "url": "https://github.com/dt267/MeshCore-Low-Power-Firmware-For-Heltec-V3-V4/releases/tag/Heltec-V3-WSL3-low-power-v1.14_0404",
      "prerelease": false,
      "notes": "### v1.14_0404\r\n\r\n- **Quick Send and Settings — control your Companion without a phone.**\r\n\r\n  Two new pages are added to the Companion's display, accessible without a phone or app.\r\n\r\n  #### Button controls\r\n\r\n  - **Single click / Double click** — navigate between pages (next / previous)\r\n  - **Long press on FIRST page** — reopen unread message preview (up to 32 messages buffered)\r\n  - **Long press** on Quick Send or Settings — enter the page; active item highlights\r\n    - Single click = next item · Double click = exit · Long press = confirm\r\n\r\n  #### Quick Send\r\n\r\n  Send a short status message directly over LoRa to the public channel — no typing, no phone needed. Useful when your phone is dead or unavailable.\r\n\r\n  GPS coordinates are automatically appended if available (e.g. `I'm OK @10.7769,106.7009`). If GPS has no current fix, last known coordinates are used with a `?` prefix so you know before sending.\r\n\r\n  **10 built-in presets:**\r\n  - I'm OK\r\n  - On my way\r\n  - I need help\r\n  - Everyone OK here\r\n  - Wait for me\r\n  - Heading home\r\n  - Running late\r\n  - Lost contact, call me\r\n  - Battery low, signing off\r\n  - All clear\r\n\r\n  **Customize via TerminalCLI** — changes are saved to flash and persist after reboot:\r\n  ```\r\n  get quick                        list all current presets\r\n  set quick.0 Arrived at camp      set preset at index 0\r\n  set quick.reset                  restore all 10 built-in defaults\r\n  ```\r\n\r\n  #### Settings\r\n\r\n  A scrollable list of device settings, controlled directly from the button:\r\n\r\n  | Item | Action |\r\n  |---|---|\r\n  | BLE | Toggle Bluetooth on/off (shows connection state) |\r\n  | Repeat | Toggle repeat mode on/off |\r\n  | RxGain | Cycle RxGain mode: OFF → ON → AUTO *(AUTO: V4.2 only)* |\r\n  | Buzzer | Toggle buzzer on/muted *(boards with buzzer only)* |\r\n  | Send Advert | Broadcast your presence to nearby nodes |\r\n  | Start OTA | Start OTA update mode — connect to `MeshCore-OTA` WiFi and go to `192.168.4.1/update` |\r\n  | Shutdown | Power off the device |\r\n\r\n- **Unified firmware for \"No Display\" hardware variants.**\r\n\r\n  A single firmware binary now runs on both OLED and no-display hardware — no separate build required. The display is detected automatically at boot via I2C probe.\r\n\r\n  | Hardware | Detected as |\r\n  |---|---|\r\n  | Heltec V3 with OLED | Heltec V3 |\r\n  | Heltec WSL3 (no OLED) | Heltec WSL3 |\r\n\r\n  The device name shown in the MeshCore app reflects the actual hardware detected. On no-display hardware, the user button has no effect (previously it could trigger unintended I2C writes).",
      "notesHtml": "<h3>v1.14_0404</h3>\n<ul>\n<li><p><strong>Quick Send and Settings — control your Companion without a phone.</strong></p>\n<p>Two new pages are added to the Companion's display, accessible without a phone or app.</p>\n<h4>Button controls</h4>\n<ul>\n<li><strong>Single click / Double click</strong> — navigate between pages (next / previous)</li>\n<li><strong>Long press on FIRST page</strong> — reopen unread message preview (up to 32 messages buffered)</li>\n<li><strong>Long press</strong> on Quick Send or Settings — enter the page; active item highlights<ul>\n<li>Single click = next item · Double click = exit · Long press = confirm</li>\n</ul>\n</li>\n</ul>\n<h4>Quick Send</h4>\n<p>Send a short status message directly over LoRa to the public channel — no typing, no phone needed. Useful when your phone is dead or unavailable.</p>\n<p>GPS coordinates are automatically appended if available (e.g. <code>I'm OK @10.7769,106.7009</code>). If GPS has no current fix, last known coordinates are used with a <code>?</code> prefix so you know before sending.</p>\n<p><strong>10 built-in presets:</strong></p>\n<ul>\n<li>I'm OK</li>\n<li>On my way</li>\n<li>I need help</li>\n<li>Everyone OK here</li>\n<li>Wait for me</li>\n<li>Heading home</li>\n<li>Running late</li>\n<li>Lost contact, call me</li>\n<li>Battery low, signing off</li>\n<li>All clear</li>\n</ul>\n<p><strong>Customize via TerminalCLI</strong> — changes are saved to flash and persist after reboot:</p>\n<pre><code>get quick                        list all current presets\nset quick.0 Arrived at camp      set preset at index 0\nset quick.reset                  restore all 10 built-in defaults\n</code></pre>\n<h4>Settings</h4>\n<p>A scrollable list of device settings, controlled directly from the button:</p>\n<table>\n<thead>\n<tr>\n<th>Item</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>BLE</td>\n<td>Toggle Bluetooth on/off (shows connection state)</td>\n</tr>\n<tr>\n<td>Repeat</td>\n<td>Toggle repeat mode on/off</td>\n</tr>\n<tr>\n<td>RxGain</td>\n<td>Cycle RxGain mode: OFF → ON → AUTO <em>(AUTO: V4.2 only)</em></td>\n</tr>\n<tr>\n<td>Buzzer</td>\n<td>Toggle buzzer on/muted <em>(boards with buzzer only)</em></td>\n</tr>\n<tr>\n<td>Send Advert</td>\n<td>Broadcast your presence to nearby nodes</td>\n</tr>\n<tr>\n<td>Start OTA</td>\n<td>Start OTA update mode — connect to <code>MeshCore-OTA</code> WiFi and go to <code>192.168.4.1/update</code></td>\n</tr>\n<tr>\n<td>Shutdown</td>\n<td>Power off the device</td>\n</tr>\n</tbody></table>\n</li>\n<li><p><strong>Unified firmware for \"No Display\" hardware variants.</strong></p>\n<p>A single firmware binary now runs on both OLED and no-display hardware — no separate build required. The display is detected automatically at boot via I2C probe.</p>\n<table>\n<thead>\n<tr>\n<th>Hardware</th>\n<th>Detected as</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Heltec V3 with OLED</td>\n<td>Heltec V3</td>\n</tr>\n<tr>\n<td>Heltec WSL3 (no OLED)</td>\n<td>Heltec WSL3</td>\n</tr>\n</tbody></table>\n<p>The device name shown in the MeshCore app reflects the actual hardware detected. On no-display hardware, the user button has no effect (previously it could trigger unintended I2C writes).</p>\n</li>\n</ul>\n"
    }
  ],
  "changelogSource": "github",
  "changelogUpdatedAt": "2026-06-21T09:55:33.826Z"
}
