Added NTP time (overrules RDS CT)

This commit is contained in:
Sjef Verhoeven PE5PVB
2025-01-09 21:49:11 +01:00
parent 525593d6c4
commit dc69f72951
9 changed files with 158 additions and 132 deletions
+26 -17
View File
@@ -10,6 +10,7 @@
#include <Hash.h> // https://github.com/bbx10/Hash_tng/archive/refs/heads/master.zip #include <Hash.h> // https://github.com/bbx10/Hash_tng/archive/refs/heads/master.zip
#include <WebServer.h> #include <WebServer.h>
#include <SPIFFS.h> #include <SPIFFS.h>
#include "src/NTPupdate.h"
#include "src/WiFiConnect.h" #include "src/WiFiConnect.h"
#include "src/WiFiConnectParam.h" #include "src/WiFiConnectParam.h"
#include "src/FONT16.h" #include "src/FONT16.h"
@@ -99,6 +100,7 @@ bool mwstepsize;
bool airstepsize; bool airstepsize;
#endif #endif
bool nobattery; bool nobattery;
bool NTPupdated;
bool optenc; bool optenc;
bool rdsflagreset; bool rdsflagreset;
bool rdsreset; bool rdsreset;
@@ -200,6 +202,7 @@ byte memstoppos;
byte menuitem; byte menuitem;
byte menupage; byte menupage;
byte MSold; byte MSold;
byte NTPoffset = 1;
byte poweroptions; byte poweroptions;
byte rdsblockold; byte rdsblockold;
byte rdsqualityold; byte rdsqualityold;
@@ -414,6 +417,7 @@ unsigned long lastTouchTime = 0;
unsigned long lowsignaltimer; unsigned long lowsignaltimer;
unsigned long ModulationpreviousMillis; unsigned long ModulationpreviousMillis;
unsigned long ModulationpeakPreviousMillis; unsigned long ModulationpeakPreviousMillis;
unsigned long NTPtimer;
unsigned long peakholdmillis; unsigned long peakholdmillis;
unsigned long pslongticker; unsigned long pslongticker;
unsigned long pslongtickerhold; unsigned long pslongtickerhold;
@@ -931,6 +935,11 @@ void setup() {
void loop() { void loop() {
if (wifi) webserver.handleClient(); if (wifi) webserver.handleClient();
if (wifi && millis() >= NTPtimer + 1800000) {
NTPupdate();
NTPtimer = millis();
}
if (hardwaremodel == PORTABLE_TOUCH_ILI9341 && touch_detect) { if (hardwaremodel == PORTABLE_TOUCH_ILI9341 && touch_detect) {
if (tft.getTouchRawZ() > 100) { // Check if the touch is active if (tft.getTouchRawZ() > 100) { // Check if the touch is active
uint16_t x, y; uint16_t x, y;
@@ -5571,43 +5580,43 @@ bool addRowToCSV() {
} }
String getCurrentDateTime() { String getCurrentDateTime() {
// Check if time has been set // Check if the RTC has been set
if (!rtcset) { if (!rtcset) {
return "-,-"; // Return placeholder when time is not set return "-,-"; // Return placeholder when the RTC is not set
} }
// Use the ESP32's time functions (assuming time is set correctly via RDS) // Use the ESP32's time functions to retrieve the current time
struct tm timeInfo; struct tm timeInfo;
if (!getLocalTime(&timeInfo)) { if (!getLocalTime(&timeInfo)) {
return "-,-"; // Return placeholder if time is not available return "-,-"; // Return placeholder if local time is unavailable
} }
// Adjust timeInfo using the GMT offset // Adjust timeInfo using the GMT offset
time_t currentEpoch = mktime(&timeInfo); // Convert struct tm to time_t time_t currentEpoch = mktime(&timeInfo); // Convert struct tm to time_t format
currentEpoch += radio.rds.offset; // Apply the offset (in seconds) currentEpoch += (NTPupdated ? NTPoffset * 3600 : radio.rds.offset); // Apply GMT offset if NTPupdated, else RDS offset
localtime_r(&currentEpoch, &timeInfo); // Convert back to struct tm localtime_r(&currentEpoch, &timeInfo); // Convert adjusted time back to struct tm format
// Format date-time based on the region // Buffer for formatted date-time string
char buf[20]; // Buffer size for formatted date string char buf[20];
if (radio.rds.region == 1) { if (radio.rds.region == 1) {
// USA format: MM/DD/YYYY, HH:MM AM/PM // USA format: MM/DD/YYYY, HH:MM AM/PM
strftime(buf, sizeof(buf), "%m/%d/%Y", &timeInfo); // MM/DD/YYYY format strftime(buf, sizeof(buf), "%m/%d/%Y", &timeInfo); // Format as MM/DD/YYYY
// Format time in 12-hour format with AM/PM // Format time in 12-hour format with AM/PM
int hour = timeInfo.tm_hour; int hour = timeInfo.tm_hour;
String ampm = (hour >= 12) ? "PM" : "AM"; String ampm = (hour >= 12) ? "PM" : "AM"; // Determine AM or PM
if (hour == 0) hour = 12; // Midnight case if (hour == 0) hour = 12; // Convert 0 hour to 12 AM
else if (hour > 12) hour -= 12; // Convert PM to 12-hour format else if (hour > 12) hour -= 12; // Convert to 12-hour format for PM
String timeWithAMPM = String(hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min) + " " + ampm; String timeWithAMPM = String(hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min) + " " + ampm;
// Return final formatted date-time for USA // Return the final formatted date and time for the USA region
return String(buf) + "," + timeWithAMPM; return String(buf) + "," + timeWithAMPM;
} else { } else {
// European format: DD/MM/YYYY, HH:MM // European format: DD-MM-YYYY, HH:MM
strftime(buf, sizeof(buf), "%d-%m-%Y", &timeInfo); // DD/MM/YYYY format strftime(buf, sizeof(buf), "%d-%m-%Y", &timeInfo); // Format as DD-MM-YYYY
String timeEuropean = String(timeInfo.tm_hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min); // Add leading 0 for minutes if necessary String timeEuropean = String(timeInfo.tm_hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min); // Format time with leading zero if needed
return String(buf) + "," + timeEuropean; return String(buf) + "," + timeEuropean;
} }
} }
+59 -33
View File
@@ -1,58 +1,84 @@
#include "NTPupdate.h" #include "NTPupdate.h"
// send an NTP request to the time server at the given address // Sends an NTP request packet to the specified server address
void sendNTPpacket(IPAddress &address) { void sendNTPpacket(IPAddress &address) {
byte packetBuffer[NTP_PACKET_SIZE]; byte packetBuffer[NTP_PACKET_SIZE] = {0}; // Initialize buffer with zeros
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE); // Set NTP packet header fields as per NTP protocol
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling interval
packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer clock precision
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion // Root Delay & Root Dispersion fields
packetBuffer[12] = 49; packetBuffer[12] = 49;
packetBuffer[13] = 0x4E; packetBuffer[13] = 0x4E;
packetBuffer[14] = 49; packetBuffer[14] = 49;
packetBuffer[15] = 52; packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp: // Send the NTP request to port 123 (NTP standard port)
Udp.beginPacket(address, 123); //NTP requests are to port 123 Udp.beginPacket(address, 123);
Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket(); Udp.endPacket();
} }
// Retrieves the current time from an NTP server
time_t getNtpTime() { time_t getNtpTime() {
IPAddress ntpServerIP; // NTP server's ip address IPAddress ntpServerIP;
byte packetBuffer[NTP_PACKET_SIZE]; byte packetBuffer[NTP_PACKET_SIZE];
while (Udp.parsePacket() > 0) ; // discard any previously received packets // Clear any previously received UDP packets
WiFi.hostByName(ntpServerName, ntpServerIP); while (Udp.parsePacket() > 0);
// Resolve the NTP server's hostname to its IP address
if (!WiFi.hostByName(ntpServerName, ntpServerIP)) {
return 0; // Return 0 if hostname resolution fails
}
// Send an NTP request
sendNTPpacket(ntpServerIP); sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) { // Wait for a response with a 1500ms timeout
int size = Udp.parsePacket(); uint32_t startWait = millis();
if (size >= NTP_PACKET_SIZE) { while (millis() - startWait < 1500) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer if (Udp.parsePacket() >= NTP_PACKET_SIZE) { // Check if a valid packet is received
unsigned long secsSince1900; Udp.read(packetBuffer, NTP_PACKET_SIZE);
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24; // Extract "seconds since 1900" from the packet (bytes 40-43)
secsSince1900 |= (unsigned long)packetBuffer[41] << 16; unsigned long secsSince1900 =
secsSince1900 |= (unsigned long)packetBuffer[42] << 8; ((unsigned long)packetBuffer[40] << 24) |
secsSince1900 |= (unsigned long)packetBuffer[43]; ((unsigned long)packetBuffer[41] << 16) |
((unsigned long)packetBuffer[42] << 8) |
(unsigned long)packetBuffer[43];
// Convert to UNIX epoch time (seconds since 1970)
return secsSince1900 - 2208988800UL; return secsSince1900 - 2208988800UL;
} }
} }
return 0; // return 0 if unable to get the time
// Return 0 if no valid response is received
return 0;
} }
// Updates the RTC with the time from an NTP server
void NTPupdate() { void NTPupdate() {
if (!wifi) { return; } // Abort if Wi-Fi is not connected
time_t time = getNtpTime(); if (!wifi) {
if (time) { NTPupdated = false;
rtc.setTime(time); return;
}
} }
// Retrieve the current time from the NTP server
time_t currentTime = getNtpTime();
if (currentTime) {
// Set the RTC if valid time is received
rtc.setTime(currentTime);
rtcset = true;
NTPupdated = true;
radio.rds.ctupdate = false;
} else {
// Indicate that the update failed
NTPupdated = false;
radio.rds.ctupdate = true;
}
}
+5
View File
@@ -7,6 +7,7 @@
#include <WiFiUdp.h> #include <WiFiUdp.h>
#include <ESP32Time.h> #include <ESP32Time.h>
#include <TimeLib.h> #include <TimeLib.h>
#include "TEF6686.h"
static const char ntpServerName[] = "0.pool.ntp.org"; static const char ntpServerName[] = "0.pool.ntp.org";
static const int localPort = 8944; static const int localPort = 8944;
@@ -15,7 +16,11 @@ const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
extern ESP32Time rtc; extern ESP32Time rtc;
extern WiFiClient RemoteClient; extern WiFiClient RemoteClient;
extern WiFiUDP Udp; extern WiFiUDP Udp;
extern TEF6686 radio;
extern bool wifi; extern bool wifi;
extern bool NTPupdated;
extern bool rtcset;
void sendNTPpacket(IPAddress &address); void sendNTPpacket(IPAddress &address);
void NTPupdate(); void NTPupdate();
+1 -1
View File
@@ -1340,7 +1340,7 @@ void TEF6686::readRDS(byte showrdserrors) {
} break; } break;
case RDS_GROUP_4A: { case RDS_GROUP_4A: {
if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) { if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold && rds.ctupdate) {
// CT // CT
uint32_t mjd; uint32_t mjd;
mjd = (rds.rdsB & 0x03); mjd = (rds.rdsB & 0x03);
+1
View File
@@ -621,6 +621,7 @@ typedef struct _rds_ {
bool filter; bool filter;
bool rdsreset; bool rdsreset;
bool pierrors; bool pierrors;
bool ctupdate = true;
bool sortaf; bool sortaf;
bool rtbuffer = true; bool rtbuffer = true;
bool afreg; bool afreg;
+1
View File
@@ -912,6 +912,7 @@ void tryWiFi() {
Server.begin(); Server.begin();
Udp.begin(9031); Udp.begin(9031);
webserver.begin(); webserver.begin();
NTPupdate();
remoteip = IPAddress (WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], subnetclient); remoteip = IPAddress (WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], subnetclient);
if (!setupmode) tftPrint(0, myLanguage[language][57], 155, 128, InsignificantColor, InsignificantColorSmooth, 28); if (!setupmode) tftPrint(0, myLanguage[language][57], 155, 128, InsignificantColor, InsignificantColorSmooth, 28);
} else { } else {
+1
View File
@@ -149,4 +149,5 @@ extern void ShowStepSize();
extern void startFMDXScan(); extern void startFMDXScan();
extern void cancelDXScan(); extern void cancelDXScan();
extern void printLogbookCSV(); extern void printLogbookCSV();
extern void NTPupdate();
#endif #endif
+33 -52
View File
@@ -787,90 +787,71 @@ void showCT() {
char str[6]; char str[6];
time_t t; time_t t;
// Check if screen is not muted and the clock should be displayed // Determine the current time source
if (!screenmute && showclock) { if (radio.rds.hasCT && !dropout && !NTPupdated) {
// If RDS CT (Clock Time) is available and no dropout, use RDS time
if (radio.rds.hasCT && !dropout) {
t = radio.rds.time + radio.rds.offset; t = radio.rds.time + radio.rds.offset;
} } else {
// If no RDS CT or there is a dropout, fall back to RTC time t = rtc.getEpoch() + (NTPupdated ? 0 : radio.rds.offset);
else {
t = rtc.getEpoch() + radio.rds.offset;
// Update RDS time in case of dropout // Update RDS time during dropout
if (dropout) { if (dropout) {
radio.rds.time = static_cast<time_t>(rtc.getEpoch()); radio.rds.time = static_cast<time_t>(rtc.getEpoch());
} }
} }
// Check if USA region, use 12-hour AM/PM format // Apply the GMT offset only if NTPupdated is true
if (radio.rds.region == 1) { if (NTPupdated) {
// Format time in 24-hour format first t += NTPoffset * 3600; // Convert offset from hours to seconds
}
// Format the time based on region
if (radio.rds.region == 1) { // USA region: 12-hour AM/PM format
strftime(str, sizeof(str), "%I:%M", localtime(&t)); strftime(str, sizeof(str), "%I:%M", localtime(&t));
// Manually determine AM/PM and add it // Determine AM/PM and adjust hour format
int hour = localtime(&t)->tm_hour; int hour = localtime(&t)->tm_hour;
String ampm = (hour >= 12) ? "PM" : "AM"; String ampm = (hour >= 12) ? "PM" : "AM";
// Adjust the hour to 12-hour format, taking care of 12 AM and 12 PM
if (hour == 0) { if (hour == 0) {
hour = 12; // Midnight case hour = 12; // Midnight case
} else if (hour > 12) { } else if (hour > 12) {
hour -= 12; // Convert PM to 12-hour format hour -= 12; // Convert PM hours
} }
// Construct the final time string manually
rds_clock = String(hour) + ":" + String(localtime(&t)->tm_min) + " " + ampm; rds_clock = String(hour) + ":" + String(localtime(&t)->tm_min) + " " + ampm;
} else { } else { // Other regions: 24-hour format
// For other regions, use 24-hour format
strftime(str, sizeof(str), "%H:%M", localtime(&t)); strftime(str, sizeof(str), "%H:%M", localtime(&t));
rds_clock = String(str); rds_clock = String(str);
} }
// If the clock has changed or RDS CT status has changed, update the display // Check if the clock or RDS CT status has changed
if (rds_clock != rds_clockold || hasCTold != radio.rds.hasCT) { if (!screenmute && showclock && (rds_clock != rds_clockold || hasCTold != radio.rds.hasCT)) {
// If RDS CT is available and RDS status is active, set RTC time // Update RTC if RDS CT is available or NTP was updated
if (radio.rds.hasCT && RDSstatus) { if ((radio.rds.hasCT && RDSstatus) || NTPupdated) {
rtcset = true; rtcset = true;
if (!NTPupdated) {
rtc.setTime(radio.rds.time); rtc.setTime(radio.rds.time);
}
// Display the new time with different coordinates based on advancedRDS setting // Display the updated time
if (advancedRDS) { int yCoord = advancedRDS ? 109 : 163;
tftReplace(1, rds_clockold, rds_clock, 208, 109, RDSColor, RDSColorSmooth, BackgroundColor, 16); tftReplace(1, rds_clockold, rds_clock, 208, yCoord, RDSColor, RDSColorSmooth, BackgroundColor, 16);
} else { } else { // Handle dropout scenarios
tftReplace(1, rds_clockold, rds_clock, 208, 163, RDSColor, RDSColorSmooth, BackgroundColor, 16); int yCoord = advancedRDS ? 109 : 163;
}
} if (rtcset) { // Display dropout message if RTC was set
// If no RDS CT available or status is inactive, handle dropout scenarios tftReplace(1, rds_clockold, rds_clock, 208, yCoord, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 16);
else { } else { // Clear and reprint the clock
// If RTC was previously set, show dropout message tftPrint(1, rds_clockold, 208, yCoord, BackgroundColor, BackgroundColor, 16);
if (rtcset) { tftPrint(1, rds_clock, 208, yCoord, BackgroundColor, BackgroundColor, 16);
if (advancedRDS) {
tftReplace(1, rds_clockold, rds_clock, 208, 109, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 16);
} else {
tftReplace(1, rds_clockold, rds_clock, 208, 163, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 16);
}
}
// If RTC is not set, just print the clock with no background (clear the display)
else {
if (advancedRDS) {
tftPrint(1, rds_clockold, 208, 109, BackgroundColor, BackgroundColor, 16);
tftPrint(1, rds_clock, 208, 109, BackgroundColor, BackgroundColor, 16);
} else {
tftPrint(1, rds_clockold, 208, 163, BackgroundColor, BackgroundColor, 16);
tftPrint(1, rds_clock, 208, 163, BackgroundColor, BackgroundColor, 16);
}
} }
} }
} }
// Update the previous clock and RDS CT status to detect future changes // Update previous clock and RDS CT status
rds_clockold = rds_clock; rds_clockold = rds_clock;
hasCTold = radio.rds.hasCT; hasCTold = radio.rds.hasCT;
} }
}
void showRadioText() { void showRadioText() {
String RTString = String(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "") + " "); String RTString = String(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "") + " ");
+2
View File
@@ -26,6 +26,7 @@ extern bool haseonold;
extern bool hasrtplusold; extern bool hasrtplusold;
extern bool hastmcold; extern bool hastmcold;
extern bool memreset; extern bool memreset;
extern bool NTPupdated;
extern bool rdsreset; extern bool rdsreset;
extern bool RDSSPYTCP; extern bool RDSSPYTCP;
extern bool RDSSPYUSB; extern bool RDSSPYUSB;
@@ -51,6 +52,7 @@ extern byte ECCold;
extern byte language; extern byte language;
extern byte licold; extern byte licold;
extern byte MSold; extern byte MSold;
extern byte NTPoffset;
extern byte eonptyold[20]; extern byte eonptyold[20];
extern byte rdsblockold; extern byte rdsblockold;
extern byte rdsqualityold; extern byte rdsqualityold;