Skip to content

Fix 49.7-day millis() rollover zeroing day/month plots - #1229

Merged
gskjold merged 2 commits into
mainfrom
fix/millis-rollover-plot-clear
Aug 27, 2026
Merged

Fix 49.7-day millis() rollover zeroing day/month plots#1229
gskjold merged 2 commits into
mainfrom
fix/millis-rollover-plot-clear

Conversation

@gskjold

@gskjold gskjold commented Jul 17, 2026

Copy link
Copy Markdown
Member

Fixes #1228

Problem

After 49.7 days of uptime, millis() (32-bit) wraps while AmsData::getLastUpdateMillis() (fed from 64-bit millis64()) keeps growing past 2^32. In the comparison

if(millis() - meterState.getLastUpdateMillis() > 1800000 && !ds.isHappy(time(nullptr))) {

the subtraction promotes to uint64_t and underflows to an enormous value, so the "no meter data for 30 minutes" condition becomes permanently true. From then on, handleClear() fires at minute 0 of every hour, writes a null update that zeroes the hour and stamps the storage as happy, and the real meter update is skipped behind isHappy(). The day plot flatlines to zeros within 24 hours, the month plot loses one day per midnight (or all 31 at once if a real telegram wins the boundary race and hits the "initializing" branch).

Fix

Use millis64() on the left-hand side of every comparison against getLastUpdateMillis():

  • src/AmsToMqttBridge.cpp — the hourly-clear gate (the actual data-loss bug) and the HAN-port read fallback (benign, but same underflow).
  • src/cloud/CloudConnector.cpp — HAN status calculation; after rollover it permanently reported status 3 (error) to the cloud.

AmsWebServer.cpp and errorBlink() already use millis64() for the equivalent checks and needed no change.

Verification

  • pio run -e esp32dev builds successfully (cloud connector included in ESP32 builds).
  • Not directly testable on native — the affected code lives in the main sketch and requires 49.7 days of simulated uptime; the fix restores the exact rollover-safe pattern already used at the other getLastUpdateMillis() call sites.

🤖 Generated with Claude Code

gskjold and others added 2 commits July 17, 2026 09:43
millis() (32-bit) was compared against getLastUpdateMillis() (64-bit,
fed from millis64()). Once uptime passes 2^32 ms, the subtraction
underflows and the "no meter data for 30 minutes" condition becomes
permanently true, so handleClear() wipes the data storage with a null
update at the top of every hour and blocks the real update behind
isHappy(). Use millis64() on the left-hand side of all comparisons
against getLastUpdateMillis(); same fix for the cloud connector HAN
status, which reported error state after rollover.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The vite 8 / vite-plugin-svelte 7 bumps (#1209) require Node >= 20.19;
build.yml already uses 22.x but pr-build-env.yml still pinned 19.x,
breaking the UI build step on every PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🔧 PR Build Artifacts

Version: 542c769

All environments built successfully. Download the zip files:

Artifacts expire after 7 days. View workflow run

@gskjold
gskjold marked this pull request as ready for review August 27, 2026 06:15
@gskjold
gskjold merged commit b233722 into main Aug 27, 2026
8 checks passed
@gskjold
gskjold deleted the fix/millis-rollover-plot-clear branch August 27, 2026 07:16
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.

Day/month plots turn to zeros after 49.7 days uptime (millis() rollover vs millis64 comparison)

1 participant