Timestamp Unix nei sistemi embedded, nelle API e nei database
Progetta timestamp di sensori con RTC, NTP, orologi monotoni, JSON e SQL, con un esempio di sincronizzazione ESP32.
Una misura utile associa valore, riferimento temporale e incertezza. Unix facilita l’interoperabilità senza garantire accuratezza o ordine. Esamina i dati con Convertitore Unix Timestamp / Epoch e consulta i fondamenti in Comprendere i timestamp Unix e il tempo Epoch.
RTC e orologio di sistema
Un RTC mantiene calendario o contatore mentre la CPU dorme, spesso con alimentazione di riserva. Non è necessariamente impostato su UTC o sincronizzato. L’orologio di sistema collega una base hardware all’epoca. Dopo una perdita di alimentazione verifica il RTC: la data predefinita non è una misura.
STM32, ESP32 e Linux embedded
Su STM32, registri subsecondo, dominio di riserva e funzioni RTC dipendono dalla famiglia; consulta il manuale e ST AN4759. Non esiste un registro Unix universale. ESP-IDF combina timer RTC e ad alta risoluzione secondo la configurazione. Linux offre CLOCK_REALTIME e orologi monotoni. Controlla libc e ABI oltre alla larghezza della CPU.
Sincronizzazione NTP e SNTP
NTP stima scostamento e ritardo di rete; SNTP semplifica il client. L’asimmetria dei pacchetti resta una fonte d’errore. Epoca ed ere NTP non sono secondi Unix: lascia la traduzione allo stack. Conserva stato, età e incertezza della sincronizzazione. Un salto cambia l’ora improvvisamente; una correzione graduale modifica temporaneamente la velocità dell’orologio.
Orologio civile e orologio monotono
L’orologio civile indica una data UTC e può saltare durante le correzioni. Il monotono misura durate da un’origine arbitraria, non una data UTC; può azzerarsi al riavvio e il comportamento in sospensione dipende dal tipo. Usalo per scadenze e tentativi, aggiungendo un riferimento UTC per correlare dispositivi.
Timestamp dei sensori
Acquisisci il tempo vicino al campione ADC o all’interrupt che definisce la misura. L’invio comprende code, radio e ritrasmissioni; conserva separatamente la ricezione del server. Per blocchi registra origine, periodo e sequenza considerando la deriva. La guida al campionamento completa il progetto.
Registrazione eventi e telemetria
Includi identità del dispositivo, dell’avvio e numero di sequenza. Una correzione all’indietro può ripetere UTC senza ripetere l’evento. Distingui tempo misurato e ricostruito. Ordinare solo per UTC non garantisce causalità fra dispositivi con intervalli di incertezza sovrapposti.
Unità e bilancio degli errori
| Unità del timestamp | 1 s | 1700000000 s |
|---|---|---|
| Secondi (s) | 1 | 1700000000 |
| Millisecondi (ms) | 1000 | 1700000000000 |
| Microsecondi (µs) | 1000000 | 1700000000000000 |
| Nanosecondi (ns) | 1000000000 | 1700000000000000000 |
Secondi per pianificazioni grossolane, millisecondi per molta telemetria, microsecondi per acquisizioni adatte e nanosecondi per hardware appropriato. Risoluzione, ripetibilità e accuratezza sono proprietà diverse. Un errore libero di 20 ppm accumula circa 1,728 s in 24 ore nominali; temperatura e invecchiamento possono modificarlo.
API REST e JSON
{
"timestamp_ns": "1700000000123456789",
"captured_at": "2023-11-14T22:13:20.123456789Z",
"time_quality": "synced",
"uncertainty_ms": 20,
"boot_id": "device-session-42",
"sequence": 17
}
Documenta epoca, unità, segno e intervallo. Trasmetti valori grandi come stringhe decimali se i client usano binary64. JSON.stringify non accetta direttamente BigInt. timestamp_ns esplicita l’unità. Un tempo sconosciuto deve essere null con qualità, anziché una falsa data prossima al 1970.
ISO 8601 e RFC 3339
Includi Z o scostamento numerico e precisione frazionaria concordata. 2023-11-14T22:13:20Z e 2023-11-14T23:13:20+01:00 sono lo stesso istante. Un’ora senza suffisso non determina UTC. Lo scostamento non preserva le regole future di Europe/Paris.
Database SQL
CREATE TABLE sensor_measurement (
device_id text NOT NULL,
boot_id text NOT NULL,
sequence bigint NOT NULL,
captured_at timestamptz,
monotonic_us bigint NOT NULL,
time_quality text NOT NULL,
temperature_c double precision NOT NULL,
PRIMARY KEY (device_id, boot_id, sequence)
);
INSERT INTO sensor_measurement VALUES ('sensor-1', 'boot-42', 17,
TIMESTAMPTZ '2023-11-14T22:13:20.123456Z', 9812370, 'synced', 23.625);
L’esempio usa PostgreSQL. timestamptz conserva un istante e lo presenta nel fuso della sessione, senza mantenere l’identificatore IANA originale. Memorizzalo separatamente se necessario. La precisione è di microsecondi; nanosecondi esatti richiedono un ulteriore campo intero o decimale. Altri motori SQL hanno regole diverse. Indice temporale e identità dispositivo/avvio/sequenza svolgono compiti distinti.
UTC e pianificazione locale
Memorizza gli eventi in UTC. Una regola quotidiana alle 08:00 a Parigi richiede ora locale e fuso IANA, perché l’UTC varia con l’ora legale. Definisci il comportamento per ore saltate o ripetute. Aggiungere 86400 secondi Unix non garantisce la stessa ora locale il giorno seguente.
Limiti di time_t
Non dedurre time_t da sizeof(void*). Un campo secondi a 32 bit con segno raggiunge il 2038 anche in un sistema parzialmente a 64 bit. ESP-IDF usa time_t a 64 bit con segno da v5.0; firmware e protocolli precedenti possono restare limitati. Verifica printf, colonne SQL, bootloader, driver RTC e migrazioni OTA.
Esempio ESP32: sensore sincronizzato con NTP
Questo codice ESP-IDF 5.x/6.x viene chiamato una volta dopo l’inizializzazione di esp-netif e la connessione Wi-Fi o Ethernet. Il driver della scheda fornisce a log_sensor una temperatura finita. La prima attesa è limitata a 15 secondi e ogni acquisizione emette un record JSON.
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "esp_netif_sntp.h"
#include "esp_timer.h"
#include "esp_random.h"
static bool clock_synced;
static int64_t last_sync_us;
static uint32_t boot_id;
static uint64_t sequence;
void ntp_after_network_ready(void) {
boot_id = esp_random();
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
esp_netif_sntp_init(&config);
clock_synced = esp_netif_sntp_sync_wait(pdMS_TO_TICKS(15000)) == ESP_OK;
if (clock_synced) last_sync_us = esp_timer_get_time();
}
void log_sensor(double temperature_c) {
int64_t monotonic_us = esp_timer_get_time();
struct timeval tv;
bool valid = clock_synced && monotonic_us - last_sync_us < INT64_C(3600000000)
&& gettimeofday(&tv, NULL) == 0;
printf("{\"boot_id\":\"%08" PRIx32 "\",\"sequence\":%" PRIu64
",\"monotonic_us\":\"%" PRId64 "\",\"timestamp_us\":",
boot_id, sequence++, monotonic_us);
if (valid) {
int64_t utc_us = (int64_t)tv.tv_sec * INT64_C(1000000) + tv.tv_usec;
printf("\"%" PRId64 "\"", utc_us);
} else printf("null");
printf(",\"time_quality\":\"%s\",\"temperature_c\":%.3f}\n",
valid ? "synced" : "unsynced", temperature_c);
}
timestamp_us e monotonic_us sono stringhe decimali. Senza sincronizzazione UTC è null e l’ordine rimane disponibile. La finestra di un’ora è una politica illustrativa, non una garanzia di accuratezza. L’esempio non rinnova la fiducia dopo sincronizzazioni automatiche: in produzione aggiorna last_sync_us da una notifica, proteggi lo stato condiviso e gestisci riconnessioni e incertezza. L’identificatore casuale di avvio a 32 bit è illustrativo; usa un contatore persistente o un identificatore robusto se le collisioni sono critiche.
Riavvii, deriva e perdita della sincronizzazione
Un riavvio crea una nuova linea monotona. Conservane l’identità e non collegare contatori di avvii diversi senza verifica. Durante la disconnessione aumenta l’incertezza secondo l’oscillatore e l’ultimo riferimento affidabile. Un RTC con riserva può aiutare, ma richiede qualità esplicita. Rendi osservabili le correzioni importanti senza riscrivere silenziosamente la storia.
Buone pratiche e prove
- Definire epoca, unità e segno a ogni interfaccia.
- UTC per eventi, orologi monotoni per scadenze.
- Conservare sequenza, identità di avvio e qualità temporale.
- Provare avvio senza rete, batteria RTC esaurita, correzioni all’indietro, ora legale e limiti interi.
- Aggiornare i dati dei fusi per pianificazioni future.
FAQ tecniche
NTP garantisce accuratezza al microsecondo?
No. Restano asimmetria di rete, pianificazione e latenza di acquisizione. Misura l’intera catena e indica l’incertezza adeguata.
Basta un contatore monotono per ottenere UTC?
Serve una corrispondenza con UTC, un modello di deriva, età e incertezza. Non resta automaticamente valida dopo il riavvio.
È meglio salvare tutto in ora locale?
Conserva gli istanti in UTC e un fuso separato per regole civili o contesto originale. Converti alla visualizzazione.
Strumenti e riferimenti
Convertitore Unix Timestamp / Epoch · Comprendere i timestamp Unix e il tempo Epoch · Tolleranza degli oscillatori.
- IETF · RFC 3339
- IETF · RFC 5905 (NTP)
- IETF · RFC 8259 (JSON)
- Python · PEP 418
- Espressif · ESP-IDF
- STMicroelectronics · AN4759
- PostgreSQL · SQL
Strumenti e guide correlati
Calcolatore dei condensatori di carico del quarzo · Leggi la guida completa di progetto