Skip to content

Fix: Theme change during sleep causes mixed theme on wake-up#49

Merged
edwardtfn merged 17 commits intomainfrom
v9999.99.9
Mar 15, 2026
Merged

Fix: Theme change during sleep causes mixed theme on wake-up#49
edwardtfn merged 17 commits intomainfrom
v9999.99.9

Conversation

@edwardtfn
Copy link
Copy Markdown
Owner

@edwardtfn edwardtfn commented Mar 14, 2026

Theme changes applied while the panel was sleeping resulted in a partially updated display — some components reflected the new theme while others retained the previous one. This is now correctly handled by ensuring the full theme is applied on wake-up.

Summary by CodeRabbit

  • New Features

    • Weather display and handling added.
    • New NSPanel Easy landscape UI with boot and home screens.
  • Documentation

    • Added "Where to Buy" purchasing guide with regional retailers and affiliate disclosure.
  • Changes

    • TFT model options renamed to "Legacy" variants; added "NSPanel Easy EU (under construction)".
    • Theme application updated so themes are applied on the screensaver page.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 14, 2026

Warning

Rate limit exceeded

@edwardtfn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 30 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7cecda1e-3e4b-45bb-871b-daa6bc4e696c

📥 Commits

Reviewing files that changed from the base of the PR and between 6d02dfd and f863a78.

📒 Files selected for processing (23)
  • components/nspanel_easy/weather.h
  • docs/where_to_buy.md
  • hmi/dev/nspanel_CJK_eu_code/boot.txt
  • hmi/dev/nspanel_CJK_us_code/boot.txt
  • hmi/dev/nspanel_CJK_us_land_code/boot.txt
  • hmi/dev/nspanel_easy_landscape/boot.txt
  • hmi/dev/nspanel_eu_code/boot.txt
  • hmi/dev/nspanel_us_code/boot.txt
  • hmi/dev/nspanel_us_land_code/boot.txt
  • hmi/nspanel_CJK_eu.HMI
  • hmi/nspanel_CJK_eu.tft
  • hmi/nspanel_CJK_us.HMI
  • hmi/nspanel_CJK_us.tft
  • hmi/nspanel_CJK_us_land.HMI
  • hmi/nspanel_CJK_us_land.tft
  • hmi/nspanel_easy_landscape.hmi
  • hmi/nspanel_easy_landscape.tft
  • hmi/nspanel_eu.HMI
  • hmi/nspanel_eu.tft
  • hmi/nspanel_us.HMI
  • hmi/nspanel_us.tft
  • hmi/nspanel_us_land.HMI
  • hmi/nspanel_us_land.tft
📝 Walkthrough

Walkthrough

Adds NSPanel Easy weather support (C++ state, condition lookup, picture selection), integrates weather handling into ESPHome pages, introduces "Where to Buy" docs, renames TFT model options toward "Legacy"/"Easy", and adds complete landscape HMI (boot/home) assets and logic.

Changes

Cohort / File(s) Summary
Documentation
README.md, docs/where_to_buy.md
Reorders TOC, inserts "🛒 Where to Buy" section in README and adds new docs/where_to_buy.md with regional retailers, affiliate notes, and model guidance.
Weather Component
components/nspanel_easy/weather.h, components/nspanel_easy/weather.cpp
New weather module gated by NSPANEL_EASY_USE_WEATHER: defines SunInfo, WEATHER_CONDITIONS table, picture variant types, normalization/get-index/get-pics/select-variant helpers, and global sun_info & weather_condition_index.
ESPHome Integration
esphome/nspanel_esphome_page_home.yaml, esphome/nspanel_esphome_addon_upload_tft.yaml, esphome/nspanel_esphome_hw_display.yaml
Adds build flag NSPANEL_EASY_USE_WEATHER, new page_home_weather_update script and action handler for weather_state; updates TFT model option names (Legacy vs Easy) and adjusts theme application early-return logic.
HMI — Landscape UI
hmi/dev/nspanel_easy_landscape/Program.s.txt, hmi/dev/nspanel_easy_landscape/boot.txt, hmi/dev/nspanel_easy_landscape/home.txt
Adds full landscape HMI program and pages: boot diagnostics with timers/logging and reboot, and a detailed home page with time/date, weather picture, entity slots, buttons/chips, and layout draw/init logic.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/API
    participant ESPHome
    participant Component as nspanel_easy (C++)
    participant HMI as HMI Display

    User->>ESPHome: Send weather_state text
    ESPHome->>Component: normalise_weather_condition(cond)
    Component->>Component: get_weather_index(cond)
    Component->>Component: get_weather_pics(index)
    ESPHome->>Component: select_weather_variant(is_new_device, is_dark_theme)
    Component-->>ESPHome: picture_id
    ESPHome->>HMI: update home_weather_pic(picture_id)
    HMI->>HMI: render weather icon
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped in code through day and night,

mapped sky to icons, picked the right light.
Legacy names and Easy new,
A buying guide and UI view.
Hop—weather paints the panel bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title references fixing theme changes during sleep, but the changeset includes substantial additions (weather feature files, HMI landscape UI, documentation), which are not directly related to the stated theme fix issue. Either scope this PR to only the theme fix (esphome/nspanel_esphome_hw_display.yaml and related changes) and create separate PRs for weather and HMI features, or revise the title to accurately reflect all major changes included.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch v9999.99.9
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@edwardtfn edwardtfn changed the title New design Fix: Theme change during sleep causes mixed theme on wake-up Mar 15, 2026
@edwardtfn edwardtfn marked this pull request as ready for review March 15, 2026 09:36
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
esphome/nspanel_esphome_addon_upload_tft.yaml (1)

351-351: Option label should match the resolved TFT artifact.

Line 351 says “NSPanel Easy EU (under construction)”, but this selection resolves to nspanel_easy_landscape.tft (Line 213). Please align the label to avoid selecting an unintended layout.

Proposed text alignment
-      - "NSPanel Easy EU (under construction)"
+      - "NSPanel Easy Landscape (under construction)"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@esphome/nspanel_esphome_addon_upload_tft.yaml` at line 351, The option label
"NSPanel Easy EU (under construction)" is inconsistent with the artifact it
resolves to (nspanel_easy_landscape.tft); update the option label in the
selection mapping so it clearly matches the artifact (for example "NSPanel Easy
EU (Landscape)" or "NSPanel Easy EU - Landscape") where the choice that
references nspanel_easy_landscape.tft is defined (look for the option string
currently set to "NSPanel Easy EU (under construction)" and change it to the new
label).
docs/where_to_buy.md (1)

67-67: Missing newline at end of file.

Most style guides and many tools expect a trailing newline at the end of text files.

Proposed fix
 consider [buying me an ice cream](https://www.buymeacoffee.com/edwardfirmo) 🍦
+
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/where_to_buy.md` at line 67, The file ends without a trailing newline;
add a single newline character at the end of the file so the final line
"consider [buying me an ice cream](https://www.buymeacoffee.com/edwardfirmo) 🍦"
is followed by a newline (ensure your editor or commit adds the EOF newline).
components/nspanel_easy/weather.h (1)

185-186: strncpy may not null-terminate if input fills the buffer.

If condition is exactly 31 characters, strncpy won't null-terminate buf, causing strcmp at line 192 to read past the buffer. The buffer is zero-initialized, so this is safe in practice, but explicitly setting the last byte guards against future refactors.

Defensive fix
     char buf[32] = {};
     strncpy(buf, condition, sizeof(buf) - 1);
+    buf[sizeof(buf) - 1] = '\0';  // Ensure null-termination
     normalise_weather_condition(buf, sizeof(buf));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/nspanel_easy/weather.h` around lines 185 - 186, The current use of
strncpy to copy condition into buf (char buf[32]) can leave buf
non-null-terminated when condition is exactly 31 chars; update the copy so the
final byte is always NUL-terminated (e.g., after strncpy assign
buf[sizeof(buf)-1] = '\0' or replace strncpy with a bounded-copy that guarantees
termination such as strlcpy), ensuring subsequent strcmp or other string ops on
buf are safe; locate the buffer and copy site around the buf/condition usage to
apply the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/where_to_buy.md`:
- Line 45: The markdownlint directive on the line currently reads "<!--
markdownlint-disable MD013 MD033 -->" but should re-enable the rules; replace
that duplicate disable directive with the enable directive "<!--
markdownlint-enable MD013 MD033 -->" so the rules disabled earlier (MD013,
MD033) are properly re-enabled; locate the duplicate directive string in the
document and update it to "enable".

In `@hmi/dev/nspanel_easy_landscape/boot.txt`:
- Line 542: The substr call is trimming the first log line with an incorrect +2
/ -2 offset, causing one extra character from the next line to be dropped;
update the substr invocation that references log_body.txt (the call with
log_start_pos.val and log_len.val) to use +1 and -1 (or otherwise use the actual
newline length) instead of +2/-2 so the slice starts at log_start_pos.val+1 and
length is log_len.val-log_start_pos.val-1, ensuring you only remove the single
newline character.

---

Nitpick comments:
In `@components/nspanel_easy/weather.h`:
- Around line 185-186: The current use of strncpy to copy condition into buf
(char buf[32]) can leave buf non-null-terminated when condition is exactly 31
chars; update the copy so the final byte is always NUL-terminated (e.g., after
strncpy assign buf[sizeof(buf)-1] = '\0' or replace strncpy with a bounded-copy
that guarantees termination such as strlcpy), ensuring subsequent strcmp or
other string ops on buf are safe; locate the buffer and copy site around the
buf/condition usage to apply the change.

In `@docs/where_to_buy.md`:
- Line 67: The file ends without a trailing newline; add a single newline
character at the end of the file so the final line "consider [buying me an ice
cream](https://www.buymeacoffee.com/edwardfirmo) 🍦" is followed by a newline
(ensure your editor or commit adds the EOF newline).

In `@esphome/nspanel_esphome_addon_upload_tft.yaml`:
- Line 351: The option label "NSPanel Easy EU (under construction)" is
inconsistent with the artifact it resolves to (nspanel_easy_landscape.tft);
update the option label in the selection mapping so it clearly matches the
artifact (for example "NSPanel Easy EU (Landscape)" or "NSPanel Easy EU -
Landscape") where the choice that references nspanel_easy_landscape.tft is
defined (look for the option string currently set to "NSPanel Easy EU (under
construction)" and change it to the new label).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: db8222dd-f96c-47f0-8dd3-9624ad761cd8

📥 Commits

Reviewing files that changed from the base of the PR and between d6f26a8 and a535552.

⛔ Files ignored due to path filters (59)
  • hmi/dev/ui/Easy/weather-icons_dark-theme/clear-night.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/clear-night.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/cloudy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/cloudy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/fog.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/fog.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/hail.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/hail.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/lightning-rainy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/lightning-rainy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/lightning.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/lightning.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/partlycloudy-night.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/partlycloudy-night.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/partlycloudy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/partlycloudy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/pouring.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/pouring.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/rainy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/rainy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/snowy-rainy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/snowy-rainy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/snowy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/snowy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/sunny.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/sunny.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_dark-theme/windy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_dark-theme/windy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/clear-night.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/clear-night.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/cloudy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/cloudy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/fog.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/fog.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/hail.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/hail.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/lightning-rainy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/lightning-rainy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/lightning.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/lightning.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/partlycloudy-night.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/partlycloudy-night.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/partlycloudy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/partlycloudy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/pouring.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/pouring.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/rainy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/rainy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/snowy-rainy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/snowy-rainy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/snowy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/snowy.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/sunny.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/sunny.svg is excluded by !**/*.svg
  • hmi/dev/ui/Easy/weather-icons_light-theme/windy.png is excluded by !**/*.png
  • hmi/dev/ui/Easy/weather-icons_light-theme/windy.svg is excluded by !**/*.svg
  • hmi/dev/ui/fonts/Roboto-Bold.ttf is excluded by !**/*.ttf
  • hmi/dev/ui/fonts/Roboto-Regular.ttf is excluded by !**/*.ttf
  • hmi/dev/ui/fonts/materialdesignicons-webfont.ttf is excluded by !**/*.ttf
📒 Files selected for processing (33)
  • README.md
  • components/nspanel_easy/weather.cpp
  • components/nspanel_easy/weather.h
  • docs/where_to_buy.md
  • esphome/nspanel_esphome_addon_upload_tft.yaml
  • esphome/nspanel_esphome_hw_display.yaml
  • esphome/nspanel_esphome_page_home.yaml
  • hmi/boot_temp.page
  • hmi/dev/nspanel_easy_landscape/Program.s.txt
  • hmi/dev/nspanel_easy_landscape/boot.txt
  • hmi/dev/nspanel_easy_landscape/home.txt
  • hmi/dev/ui/fonts/10.zi
  • hmi/dev/ui/fonts/7.zi
  • hmi/dev/ui/fonts/8.zi
  • hmi/dev/ui/fonts/MDI 15.zi
  • hmi/dev/ui/fonts/MDI 25.zi
  • hmi/dev/ui/fonts/Roboto Bold 12.zi
  • hmi/dev/ui/fonts/Roboto Bold 30.zi
  • hmi/dev/ui/fonts/Roboto Bold 40.zi
  • hmi/dev/ui/fonts/Roboto Bold 42.zi
  • hmi/dev/ui/fonts/Roboto Regular 12.zi
  • hmi/dev/ui/fonts/Roboto-Bold 80 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 10 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 15 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 24 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 25 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 32 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 48 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 6 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 64 (UTF_8).zi
  • hmi/dev/ui/fonts/Roboto-Regular 80 (UTF_8).zi
  • hmi/nspanel_easy_landscape.hmi
  • hmi/nspanel_easy_landscape.tft

Comment thread docs/where_to_buy.md Outdated
Comment thread hmi/dev/nspanel_easy_landscape/boot.txt Outdated
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/where_to_buy.md`:
- Line 38: The table row currently uses the label "🇬🇧 EU (United Kingdom)"
which is incorrect; update that label to "🇬🇧 UK (United Kingdom)" (or "🇬🇧
Europe (United Kingdom)" if you intended shipping geography) by replacing the
"EU (United Kingdom)" text in the row string that starts with "| 🇬🇧 EU (United
Kingdom) |" so the row becomes "| 🇬🇧 UK (United Kingdom) | ..." to reflect the
correct region name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 24fc3f4e-95e7-402f-a240-0ef4700fd91c

📥 Commits

Reviewing files that changed from the base of the PR and between a535552 and 6d02dfd.

📒 Files selected for processing (1)
  • docs/where_to_buy.md

Comment thread docs/where_to_buy.md Outdated
@edwardtfn edwardtfn merged commit 15a8060 into main Mar 15, 2026
32 checks passed
@edwardtfn edwardtfn deleted the v9999.99.9 branch March 15, 2026 10:11
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.

1 participant