Skip to content

Time Service — ESP3D-X Reference

Guard: ESP3D_TIMESTAMP_FEATURE

The time service manages system clock synchronization. When enabled, it can sync via NTP (internet time) or accept a manually provided timestamp. It belongs to the Network & Web Services group and requires an active WiFi STA connection for NTP operation.


FileRole
main/modules/time/esp3d_time_service.hTimeService class declaration
main/modules/time/esp3d_time_service.cppFull implementation

extern TimeService esp3dTimeService;

A single singleton defined in the .cpp file. All callers use this instance directly.


class TimeService final {
public:
TimeService();
~TimeService();
bool begin();
void end();
void handle();
const char* getCurrentTime();
const char* getTimeZone();
bool updateTimeZone(bool fromsettings = false);
bool setTime(const char* stime);
bool setTimeZone(const char* stime);
bool started();
bool isInternetTime(bool readfromsettings = false);
private:
int _get_time_zone_offset_min();
bool _started;
uint64_t _dispatch_time;
bool _is_internet_time;
std::string _time_zone;
std::string _server_url[CONFIG_LWIP_SNTP_MAX_SERVERS];
uint8_t _server_count;
};

  1. Calls end() unconditionally to reset any prior state.
  2. Applies the current timezone via updateTimeZone(true) regardless of internet-time setting.
  3. If esp3d_use_internet_time is not set, returns true immediately (manual mode — timezone applied, SNTP not started).
  4. Checks the active network mode. NTP is only started in WiFi STA mode (ESP3DNetworkMode::wifi_sta). All other modes — off, AP, AP-config, AP-limited, BT-serial, BT-BLE — return false.
  5. Loads NTP server URLs from NVS keys esp3d_time_server1, esp3d_time_server2, esp3d_time_server3 (up to CONFIG_LWIP_SNTP_MAX_SERVERS servers; empty strings are skipped).
  6. Configures SNTP_OPMODE_POLL and SNTP_SYNC_MODE_IMMED, registers each server, calls esp_sntp_init().
  7. Records the start tick in _dispatch_time to begin the timeout countdown.

Called from the main application loop. Only active when _started is true and _dispatch_time != 0 (waiting for NTP sync).

Poll interval: every TIMEOUT_NTP_REFRESH = 5 000 ms.

On each poll:

  • Calls time(nullptr) and checks whether the result is post-1970 (> 0).
  • On valid time: formats the timestamp and pushes it to ESP3DValuesIndex::status_bar_label (when ESP3D_HAS_STATUS_BAR is defined), then sets _dispatch_time = 0 to stop polling.
  • On timeout (elapsed > TIMEOUT_NTP_REQUEST = 180 000 ms): logs the failure, sets _dispatch_time = 0, and stops without further retry.

Stops SNTP (esp_sntp_stop()) if previously started, resets all private members to defaults, sets _started = false.


ConstantValuePurpose
TIMEOUT_NTP_REQUEST180 000 ms (3 min)Maximum wait for a successful NTP sync after begin()
TIMEOUT_NTP_REFRESH5 000 msInterval between handle() poll checks

NVS setting keyMeaning
esp3d_use_internet_timetrue = NTP sync; false = manual-only
esp3d_time_server1Primary NTP server URL
esp3d_time_server2Secondary NTP server URL
esp3d_time_server3Tertiary NTP server URL

SNTP is configured with:

  • SNTP_OPMODE_POLL — periodic polling
  • SNTP_SYNC_MODE_IMMED — apply received time immediately (not gradual slew)

+HH:MM east of UTC (e.g. "+05:30" for IST)
-HH:MM west of UTC (e.g. "-05:00" for EST)

The POSIX TZ environment variable uses the opposite sign from the UTC-offset convention. updateTimeZone() inverts the sign before calling setenv("TZ", ...) / tzset():

NVS valueResulting TZ string
+05:30GMT-5:30
-05:00GMT+5:00
+00:00GMT-0:00

updateTimeZone(bool fromsettings = false) → bool

Section titled “updateTimeZone(bool fromsettings = false) → bool”
  • fromsettings = true: reads esp3d_timezone from NVS first.
  • fromsettings = false (default): uses the cached _time_zone member.
  • Validates that the string matches [+-]HH:MM format.
  • Calls setenv("TZ", converted, 1) then tzset().
  • Returns false if the format is invalid or setenv fails.

Stores the string into _time_zone and calls updateTimeZone(). Does not persist to NVS — the caller must save to settings if persistence is required.

Returns _time_zone.c_str(). Valid until the next setTimeZone() or end() call.

_get_time_zone_offset_min() → int (private)

Section titled “_get_time_zone_offset_min() → int (private)”

Returns the timezone offset in minutes, with the sign negated for + zones (POSIX convention). Used by setTime() to compute the correct timeval when applying a manually provided timestamp.


Parses an ISO-8601 timestamp string and sets the system clock via settimeofday().

Accepted formats:

  • %Y-%m-%dT%H:%M:%S (with seconds)
  • %Y-%m-%dT%H:%M (without seconds)

Any timezone suffix in the string is ignored; the stored _time_zone offset is applied instead via _get_time_zone_offset_min().

Returns false if parsing fails.


Returns the current local time formatted as:

%Y-%m-%d %H:%M:%S

Example: "2026-09-01 14:32:07"

Warning: the return value points to an internal static buffer. It is overwritten on every call and is not thread-safe across concurrent callers.


When ESP3D_HAS_STATUS_BAR is defined, handle() pushes the formatted time string to the observable system after a successful NTP sync:

esp3dValues.set(ESP3DValuesIndex::status_bar_label,
getCurrentTime(),
ESP3DValuesCbAction::Update);

This update fires once — immediately after the first valid time is received — not on every poll tick.


NTP startup is gated on the network mode at the time begin() is called:

Network modeNTP started
wifi_staYes
wifi_apNo
wifi_ap_configNo
wifi_ap_limitedNo
offNo
bt_serialNo
bt_bleNo

In all non-STA modes begin() returns false. The timezone is still applied unconditionally.


MethodReturns
started()true if begin() succeeded and end() has not yet been called
isInternetTime(bool readfromsettings = false)true if NTP mode is active; reads from NVS when readfromsettings = true

KeyRead by
esp3d_use_internet_timebegin(), isInternetTime()
esp3d_timezoneupdateTimeZone()
esp3d_time_server1begin()
esp3d_time_server2begin()
esp3d_time_server3begin()

All reads go through ESP3DSettings (NVS-backed).


ModuleRelationship
Connection managementProvides the active network mode queried in begin() to gate NTP startup
ESP3DSettingsNVS reads for all five settings keys
ESP3DValuesReceives status_bar_label push after successful NTP sync
mDNSAdvertises time = "ntp" / "manual" in the _device-info._tcp TXT record