v2.5.0 - Fix setenv/tzset Called on Every NMEA Timestamp Conversion (2026-02-24)¶
What Changed?¶
This release fixes gnss_manager.cpp to call setenv("TZ", "UTC0", 1) and tzset() only once at initialization instead of on every NMEA timestamp conversion.
Previously, these calls were inside nmea_to_unix_timestamp_seconds(), which is invoked from the main loop whenever GNSS time is needed.
Moving them to gnss_init() eliminates repeated heap allocation and global state mutation in the hot path.
What's New¶
Main Feature: Move setenv/tzset to gnss_init()¶
What it does:
Moves timezone initialization out of the per-call NMEA conversion helper into the one-time gnss_init() function:
Before:
nmea_to_unix_timestamp_seconds() // called every NMEA parse
setenv("TZ", "UTC0", 1) // heap alloc every call
tzset() // global TZ re-init every call
mktime()
After:
gnss_init() // called once in setup()
setenv("TZ", "UTC0", 1) // heap alloc once
tzset() // global TZ init once
nmea_to_unix_timestamp_seconds() // called every NMEA parse
mktime() // TZ already set
Why it matters:
setenv()allocates heap memory on every call — on ESP32's constrained RAM, repeated calls cause heap fragmentationtzset()re-initializes the global timezone state unnecessarily- TZ is always
"UTC0"and never changes, so setting it once is correct and sufficient
Installation¶
Quick Start¶
# Get the release
git checkout 2.5.0
# Build
task v2:build
# Upload
task v2:upload
# Check it works
task monitor
What's Different from the Last Version?¶
🐛 Fixed¶
src/gnss_manager.cpp:setenv("TZ", "UTC0", 1)andtzset()moved fromnmea_to_unix_timestamp_seconds()tognss_init()
Is It Safe to Upgrade?¶
Backward Compatible: Yes
- No change in behavior; UTC timezone was already set before every
mktime()call - Only affects code path when
ENABLE_GNSS=1
Tests Passed¶
- ✅ Builds without errors
Release Details¶
- Date: 2026-02-24
- Version: v2.5.0
- Files Changed: 1 (
src/gnss_manager.cpp)
Next Steps¶
Continued code quality improvements (see REFACTORING_ROADMAP.md):
- Remove double
discard_input()call (P2, pending real-device verification)