heure-serveur.ino
Las redes LPWA suelen filtrar NTP por UDP, así que este sketch obtiene la hora con un GET HTTP en el puerto 80 y la mantiene con millis(). La mayor latencia de NB-IoT se absorbe con una espera explícita antes de leer.
Hardware
Una Arduino MKR NB 1500 (microcontrolador SAMD21, módem u-blox LTE-M/NB-IoT, antena externa, alimentación LiPo en J6 o USB). SIM IoT de datos, antena, salida a Internet permitida por el operador (APN de datos estándar).
Cableado
Sin cableado; prueba primero la unión a la red con el ejemplo de attach.
Funcionamiento
La línea Date: de la respuesta HTTP (RFC 1123) se imprime y, en producción, se convierte a epoch. El epoch base se guarda con millis() para un reloj local entre sincronizaciones.
Ejecución
Instala el paquete Arduino SAMD Boards y la librería MKRNB, selecciona la placa y carga. Prevé una SIM IoT (LTE-M o NB1) activada y buena recepción: la conexión a la red puede tardar varios minutos.
Variantes
Si tu APN permite UDP/123, pasa a NBClientUDP y un paquete NTP de 48 bytes, preciso dentro de decenas de milisegundos.
heure-serveur.ino
// Horloge temps reel via serveur HTTP au-dessus de la data NB-IoT.
// Les operateurs LPWA bloquent souvent UDP/123 : on passe par le port 80.
#include <MKRNB.h>
const char PIN_SIM[] = "0000";
const char APN[] = "iot.1nce.net";
NB nb;
NBClient client;
unsigned long baseMs, heureEpoch;
void setup() {
Serial.begin(9600);
if (nb.begin(PIN_SIM) != NB_READY) while (true);
while (nb.getStatus() != NETWORK_JOINED) delay(2000);
nb.attachGPRS(APN);
if (client.connect("ipv4.api.chronie.fr", 80)) {
client.print("GET / HTTP/1.1\r\nHost: ipv4.api.chronie.fr\r\n\r\n");
String h = "";
delay(2000); // reseau LPWA : latence a 1-3 s
while (client.available() && h.length() < 400)
h += (char)client.read();
client.stop();
int p = h.indexOf("Date: ");
if (p >= 0) Serial.println(h.substring(p, p + 31));
// convertir la date HTTP en epoch ; valeur de demo :
heureEpoch = 1735689600UL;
baseMs = millis();
}
}
void loop() {
Serial.println(String(heureEpoch + (millis() - baseMs) / 1000));
delay(1000);
}