heure-serveur.ino
LPWA networks often filter UDP NTP, so this sketch fetches the time with a plain HTTP GET on port 80, then maintains it with millis(). The higher NB-IoT latency is absorbed by an explicit wait before reading.
Hardware
An Arduino MKR NB 1500 (SAMD21 microcontroller, u-blox LTE-M/NB-IoT modem, external antenna, LiPo power on J6 or USB). IoT data SIM, antenna, outbound Internet allowed by the operator (standard data APN).
Wiring
No wiring; first test network join with the attach example.
How it works
The Date: header of the HTTP reply (RFC 1123) is printed then, in production, converted to epoch. The base epoch is stored with millis() for a local clock between syncs.
Running it
Install the Arduino SAMD Boards package and the MKRNB library, select the board, upload. Plan for an activated IoT SIM (LTE-M or NB1) and good reception: attaching to the network can take several minutes.
Variants
If your APN allows UDP/123, switch to NBClientUDP and a 48-byte NTP packet, accurate to within tens of milliseconds.
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);
}