Time Synchronization
Time synchronization is required for accurate scheduling and timeseries data timestamps. On ESP-IDF the node runs an SNTP (Simple Network Time Protocol) client. On POSIX the SDK runs no time client at all: the host OS owns the clock, and initialization only records whether that clock already looks valid.
What “synchronised” means
Throughout the firmware, “time is synced” is a wall-clock validity test, not an SNTP success flag: the clock counts as valid once it reads later than a reference instant baked in at compile time. Consequences:
A clock set by an external SNTP owner, by the host OS, or by the cloud
getTimeSyncresponse counts as synced — the SDK does not have to own SNTP.Any attempt to set the clock to a value at or before the build-time reference is rejected, so garbage values cannot make the clock “valid”.
Synchronization Flows
Startup behavior depends on whether mbedTLS validates the server certificate’s validity dates (CONFIG_MBEDTLS_HAVE_TIME_DATE):
Synchronous flow (
CONFIG_MBEDTLS_HAVE_TIME_DATEset): a valid wall clock is a hard prerequisite for the MQTT TLS handshake, so startup blocks (indefinitely, polling every 2 s) before the MQTT connection until the clock syncs. The cloudgetTimeSynccoarse-set cannot help here — it arrives over MQTT, which cannot connect without a valid clock. Schedules arm inline once time is valid.Decoupled flow (
CONFIG_MBEDTLS_HAVE_TIME_DATEunset): startup never blocks on time. MQTT and all non-wall-clock work proceed immediately. A flat-cadence poll (everyCONFIG_RMNG_TIME_SYNC_POLL_INTERVAL_Sseconds, default 2, no backoff and no jitter) observes synchronization later and arms deferred schedules then; wall-clock-sensitive work (timeseries timestamps, schedule arming) is deferred or dropped until the clock is valid. The poll stops as soon as it observes a valid clock.
Both flows poll regardless of whether this SDK initialized SNTP (enable_time_sync) — that flag only decides SNTP ownership, not whether the clock can become valid.
Coarse Time from Cloud
On the post-connect cloud handshake the node requests
getTimeSynconly when the clock is not yet valid at handshake time. In practice this is the decoupled flow — the synchronous flow already has a valid clock by the time it connects.The response carries server time (epoch ms) and is applied only if the system time is still not valid; SNTP remains authoritative and steps the clock when it eventually syncs.
Accuracy is bounded by cloud-to-node delivery latency. See Cloud Communication.
SNTP Configuration (ESP-IDF)
Default Servers: when no server is supplied, four servers are configured in order:
time.google.com,time.cloudflare.com,pool.ntp.org,time.windows.com. Supplying a server name in the timesync configuration replaces the list with that single server.Operating Mode: polling mode (
SNTP_OPMODE_POLL) with immediate step (SNTP_SYNC_MODE_IMMED) — the clock jumps rather than being slewed.Sync Notification: an SNTP notification callback is invoked whenever time is synchronized. The SDK installs a logging callback unless the application supplies its own.
Timezone Support: the timezone is loaded from NVS (or the configured default) during timesync init, independently of whether the clock is valid — see Timezone Service.
POSIX
No time client is started. osal_timesync_init() records whether the OS clock already reads as valid and initializes the timezone; keeping the clock correct is the host’s responsibility.
Time Sync Failure Handling
Retry: on ESP-IDF, SNTP automatically retries at its configured interval
Synchronous flow: startup blocks until sync succeeds (a valid clock is required for the TLS handshake)
Decoupled flow: startup is never blocked; time-sensitive work waits for a valid clock
Fallback: If time sync is disabled, the node proceeds without synchronized time (may affect schedule accuracy); the clock may still be set by an external SNTP owner or the cloud
getTimeSyncresponse
Relationship to Services
Schedules: require a valid clock. Schedule arming is deferred until the clock is valid; the details themselves are loaded from NVS regardless.
Automation: trigger evaluation is purely value-based and needs no clock.
Timeseries: timestamps are included in timeseries data points, and points stamped before the clock became valid are dropped rather than published.
Timezone Service: setting
TZ/TZ-POSIXworks with or without a valid clock; the timezone only affects how an existing clock reading is interpreted.