#include <WiFi.h>
#include <esp_sntp.h>
const char *ssid = "Wokwi-GUEST";
const char *wifiPassword = "";
const char *ntpServer = "fr.pool.ntp.org"; // French one, use "pool.ntp.org" to be generic
bool ntpSyncDone = false;
void ntpSyncCallback(struct timeval *tv) {
ntpSyncDone = true;
Serial.println("NTP synced");
}
void wifiStationGotIp(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("IP address obtained = ");
Serial.println(WiFi.localIP());
}
void wifiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("Disconnected from network, attempting to reconnect");
WiFi.begin(ssid, wifiPassword);
}
// builds and sends a $GPRMC sentence from the current system time
void sendGprmc() {
time_t now = time(NULL);
struct tm *utcTime = gmtime(&now);
char sentence[96];
char body[80];
// position is not available from NTP, so a fixed null position is sent with a valid "A" status
// you can also hard code your actual location here instead of the null one, if you want the sentence to carry it
snprintf(body, sizeof(body),
"GPRMC,%02d%02d%02d.00,A,0000.0000,N,00000.0000,E,0.0,0.0,%02d%02d%02d,,",
utcTime->tm_hour, utcTime->tm_min, utcTime->tm_sec,
utcTime->tm_mday, utcTime->tm_mon + 1, utcTime->tm_year % 100);
uint8_t checksum = 0;
for (size_t i = 0; i < strlen(body); i++) {
checksum ^= body[i];
}
snprintf(sentence, sizeof(sentence), "$%s*%02X\r\n", body, checksum);
Serial.print(sentence);
}
void setup() {
Serial.begin(115200);
WiFi.onEvent(wifiStationGotIp, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.onEvent(wifiStationDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
configTzTime("UTC0", ntpServer); // GPRMC time is UTC, no timezone offset
sntp_set_time_sync_notification_cb(ntpSyncCallback);
WiFi.begin(ssid, wifiPassword, 6); // get rid of the 6 if not on wokwi
Serial.println("NTP to GPRMC demo");
}
void loop() {
static unsigned long lastSend = 0;
if (ntpSyncDone && millis() - lastSend >= 1000) {
sendGprmc();
lastSend = millis();
}
}Loading
esp32-devkit-c-v4
esp32-devkit-c-v4