Skip to content

Add Extended Wi-Fi Timeout toggle for TRMNL sleep-screen fetch#3

Open
mcmphd wants to merge 4 commits into
yazdipour:developmentfrom
mcmphd:feature/trmnl-extended-wifi-timeout-toggle
Open

Add Extended Wi-Fi Timeout toggle for TRMNL sleep-screen fetch#3
mcmphd wants to merge 4 commits into
yazdipour:developmentfrom
mcmphd:feature/trmnl-extended-wifi-timeout-toggle

Conversation

@mcmphd

@mcmphd mcmphd commented Jul 1, 2026

Copy link
Copy Markdown

Problem

TrmnlSleepClient::connectWifi() allows only 20 retries × 500ms = 10s
for the radio to associate and get a DHCP lease after waking from deep
sleep. On some networks — WPA2/WPA3 mixed-mode APs in particular, where
the WPA handshake can intermittently time out, or marginal signal — 10s
isn't always enough. When it isn't, the TRMNL fetch fails silently for
that cycle and the device falls back to a stale cached image or the
default sleep screen, indistinguishable on-device from any other failure.

Evidence (on-device serial, debug build)

[TRM] Connecting to WiFi:
[TRM] Wi-Fi connect failed after 20 attempts (~10s)
[WIFI] STA event: disconnected reason=204(HANDSHAKE_TIMEOUT)

A warm manual connect to the same AP typically succeeds in under 2s — the
failure is specific to the 10s cold-wake budget, not the network itself.

Fix

Rather than raising the timeout unconditionally for everyone, add a
per-device, opt-in toggle: Settings → System → TRMNL Settings →
Extended Wi-Fi Timeout
. Off by default (unchanged 10s/20-retry
behavior); when enabled, widens the window to 20s/40 retries.

  • CrossPointSettings: new trmnlExtendedWifiTimeout field, registered
    in getSettingsList() so it persists through the existing JSON
    settings loop (same pattern as trmnlOrientation).
  • TrmnlSettingsActivity: new list item, toggled and saved the same way
    as the other TRMNL settings.
  • TrmnlSleepClient: Config gains extendedWifiTimeout;
    connectWifi() picks between WIFI_RETRIES_DEFAULT (20) and
    WIFI_RETRIES_EXTENDED (40) based on it. connectWifi() returns as
    soon as the link is up, so this only costs extra time on wakes that
    would otherwise fail — no cost on the happy path.

Testing

Builds clean in the simulator env (macOS/arm64). Verified on an XTeink
X4: with the toggle off, wakes on a WPA2/WPA3 mixed-mode AP intermittently
hit the 10s HANDSHAKE_TIMEOUT failure above; with the toggle on, the
wider window resolves the connection reliably on the same network.

Summary by Sourcery

Add an optional extended Wi‑Fi timeout for TRMNL sleep-screen fetches, wired through device settings into the TRMNL client configuration and Wi‑Fi connection logic.

New Features:

  • Introduce a TRMNL settings toggle to enable an extended Wi‑Fi timeout for sleep-screen updates.
  • Extend the TRMNL sleep client configuration with a flag controlling the Wi‑Fi connection retry window.

Enhancements:

  • Adjust TRMNL Wi‑Fi connection logic to select between default and extended retry limits and log the effective timeout.
  • Persist the extended Wi‑Fi timeout preference in CrossPoint settings and expose it in the TRMNL settings UI with localization.

yazdipour and others added 3 commits June 27, 2026 21:40
TrmnlSleepClient::connectWifi() allows only 20 retries x 500ms = 10s for
the radio to associate and get a DHCP lease after waking from deep sleep.
On some networks -- WPA2/WPA3 mixed-mode APs in particular, where the WPA
handshake can intermittently time out -- 10s isn't always enough, and the
TRMNL fetch silently falls back to the default sleep screen.

Rather than raising the timeout unconditionally for everyone, add a
per-device toggle: Settings > System > TRMNL Settings > Extended Wi-Fi
Timeout. Off by default (unchanged 10s/20-retry behavior); when on,
widens the window to 20s/40 retries.

- CrossPointSettings: new trmnlExtendedWifiTimeout field, registered in
  getSettingsList() so it persists through the existing JSON settings
  loop (same pattern as trmnlOrientation).
- TrmnlSettingsActivity: new list item, toggled and saved the same way
  as the other TRMNL settings.
- TrmnlSleepClient: Config gains extendedWifiTimeout; connectWifi() picks
  between WIFI_RETRIES_DEFAULT (20) and WIFI_RETRIES_EXTENDED (40) based
  on it. connectWifi() returns as soon as the link is up, so this only
  costs extra time on wakes that would otherwise fail.

Verified: builds clean in the `simulator` env (macOS/arm64), including
the auto-generated StrId string via gen_i18n.py.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds an opt-in 'Extended Wi-Fi Timeout' TRMNL setting and plumbs it through settings, config, and the TRMNL sleep client so TRMNL fetches can use a longer Wi-Fi connection window on problematic networks, while preserving existing behavior by default.

Sequence diagram for TRMNL fetch using Extended Wi-Fi Timeout

sequenceDiagram
    participant SA as SleepActivity
    participant SC as TrmnlSleepClient
    participant WiFi as WiFi

    SA->>SC: fetchLatest(config)
    SC->>SC: connectWifi(config.extendedWifiTimeout)
    alt extendedWifiTimeout is true
        SC->>WiFi: begin(ssid, password)
        SC->>WiFi: retry up to WIFI_RETRIES_EXTENDED
    else extendedWifiTimeout is false
        SC->>WiFi: begin(ssid, password)
        SC->>WiFi: retry up to WIFI_RETRIES_DEFAULT
    end
Loading

File-Level Changes

Change Details Files
Make TRMNL sleep Wi-Fi connection timeout configurable via an extended-timeout flag.
  • Update TrmnlSleepClient::connectWifi to accept a boolean extendedTimeout parameter and choose between default and extended retry counts.
  • Introduce WIFI_RETRIES_DEFAULT and WIFI_RETRIES_EXTENDED constants and compute a per-call maxRetries value.
  • Enhance logging to include the effective Wi-Fi timeout and report failures using maxRetries instead of a fixed constant.
  • Pass the extendedWifiTimeout flag from the TrmnlSleepClient::Config into fetchLatest so the correct timeout is used for TRMNL sleep fetches.
src/trmnl/TrmnlSleepClient.cpp
src/trmnl/TrmnlSleepClient.h
Add a persisted TRMNL Extended Wi-Fi Timeout setting and expose it in the TRMNL settings UI.
  • Add a trmnlExtendedWifiTimeout field to CrossPointSettings with comments documenting behavior and default.
  • Register the new field as a toggle in getSettingsList so it is persisted and appears under TRMNL Settings.
  • Extend TrmnlSettingsActivity menu definitions and handlers to show the new item, toggle the setting on selection, and render it as ON/OFF based on current value.
  • Thread the trmnlExtendedWifiTimeout value into SleepActivity when constructing TrmnlSleepClient::Config, converting the stored uint8_t into a bool.
src/CrossPointSettings.h
src/SettingsList.h
src/activities/settings/TrmnlSettingsActivity.cpp
src/activities/boot_sleep/SleepActivity.cpp
Localize the label for the Extended Wi-Fi Timeout setting.
  • Add STR_TRMNL_EXTENDED_WIFI_TIMEOUT with an appropriate English label to the translations file so it can be used by the settings UI.
lib/I18n/translations/english.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The TRMNL settings UI now relies on the magic index 4 in multiple places (MENU_ITEMS, handleSelection, and render); consider introducing a small enum or named constants for the menu indices so future additions/reordering don’t silently break the toggle wiring.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The TRMNL settings UI now relies on the magic index `4` in multiple places (`MENU_ITEMS`, `handleSelection`, and `render`); consider introducing a small enum or named constants for the menu indices so future additions/reordering don’t silently break the toggle wiring.

## Individual Comments

### Comment 1
<location path="src/activities/settings/TrmnlSettingsActivity.cpp" line_range="14-20" />
<code_context>

 namespace {
-constexpr int MENU_ITEMS = 4;
+constexpr int MENU_ITEMS = 5;
 const StrId menuNames[MENU_ITEMS] = {StrId::STR_TRMNL_SERVER_URL, StrId::STR_TRMNL_API_KEY,
-                                     StrId::STR_TRMNL_DEVICE_ID, StrId::STR_TRMNL_ORIENTATION};
</code_context>
<issue_to_address>
**suggestion:** Avoid hardcoding menu indices now that MENU_ITEMS has increased.

The new item uses the literal `4` in both `handleSelection` and `render`, tying behavior to the current ordering and count. Please introduce a named constant or enum (e.g. `constexpr int MENU_INDEX_EXTENDED_WIFI_TIMEOUT = 4;`) and reuse it in both places, or derive the behavior from `menuNames` instead of raw indices.

Suggested implementation:

```cpp
namespace {
constexpr int MENU_ITEMS = 5;
constexpr int MENU_INDEX_EXTENDED_WIFI_TIMEOUT = 4;
const StrId menuNames[MENU_ITEMS] = {StrId::STR_TRMNL_SERVER_URL, StrId::STR_TRMNL_API_KEY,
                                     StrId::STR_TRMNL_DEVICE_ID, StrId::STR_TRMNL_ORIENTATION,
                                     StrId::STR_TRMNL_EXTENDED_WIFI_TIMEOUT};

```

```cpp
  } else if (selectedIndex == MENU_INDEX_EXTENDED_WIFI_TIMEOUT) {
    SETTINGS.trmnlExtendedWifiTimeout = !SETTINGS.trmnlExtendedWifiTimeout;

```

There is a corresponding use of the hardcoded index in the `render` logic for this menu item (e.g., something like `if (i == 4)` or similar). That code should be updated to compare against `MENU_INDEX_EXTENDED_WIFI_TIMEOUT` instead of the literal `4`, for example:
- Replace any `i == 4` (or similar loop-index comparison) that is specifically for the extended Wi-Fi timeout item with `i == MENU_INDEX_EXTENDED_WIFI_TIMEOUT`.
- Likewise, any other conditions or accessors for `menuNames[4]` that are conceptually about the extended Wi-Fi timeout should use `MENU_INDEX_EXTENDED_WIFI_TIMEOUT` instead of a raw index.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/activities/settings/TrmnlSettingsActivity.cpp
TrmnlSettingsActivity used the literal 4 in both handleSelection() and
render() for the new Extended Wi-Fi Timeout item, tying its wiring to the
current position/count with no compiler-enforced link between the two
call sites. Introduce MENU_INDEX_EXTENDED_WIFI_TIMEOUT and use it in both
places instead, so reordering or inserting a new item before it can't
silently desync selection handling from rendering.

Left the pre-existing 0/1/2/3 literals for Server URL/API Key/Device
ID/Orientation as-is -- out of scope for this change, and not something
this feature touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants