Print next race time in local time.

This commit is contained in:
bissen21 committed 2026-11-08 19:28:11 -06:00
1 parent b67432ed5d
commit f429f32890
2 files changed
+61 -16

No files matched your search

+55 -12
View File
@@ -5,10 +5,36 @@
#include "secrets.h"
#include "ArduinoJson.h"
#include "config.h"
#include "time.h"
extern "C" char *strptime(const char *__restrict, const char *__restrict, struct tm *__restrict); // Not exposed by headers?
// Portable replacement for missing timegm()
time_t timegm(struct tm *t) {
int year = t->tm_year + 1900;
int mon = t->tm_mon + 1; // 1 to 12
int day = t->tm_mday;
// Shift year/month to make March month 0 (simplifies leap year calculation)
int a = (14 - mon) / 12;
int y = year + 4800 - a;
int m = mon + 12 * a - 3;
// Calculate Julian Day Number
long jdn = day + (153 * m + 2) / 5 + 365L * y + y / 4 - y / 100 + y / 400 - 32045;
// Days since Unix epoch (1970-01-01 is JDN 2440588)
long days = jdn - 2440588;
return (time_t)(days * 86400L +
t->tm_hour * 3600L +
t->tm_min * 60L +
t->tm_sec);
}
struct session_info_t {
char session_name[50];
char date_start[32];
struct tm date_start;
char circuit_short_name[50];
uint16_t session_key;
uint16_t meeting_key;
@@ -118,10 +144,24 @@ int parse_session_json(JsonArray sessions, session_info_t* target, const Semapho
JsonObject nextRaceJson = sessions[0];
session_info_t localData;
strptime();
struct tm utc_tm;
memset(&utc_tm, 0, sizeof(struct tm));
strptime(nextRaceJson[F("date_start")], "%Y-%m-%dT%H:%M:%S", &utc_tm);
// 2. Convert UTC struct tm to time_t Unix timestamp
time_t raw_time = timegm(&utc_tm);
// 3. Convert time_t to local struct tm
struct tm local_tm;
localtime_r(&raw_time, &localData.date_start);
char buffer[64];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M:%S %p %Z", &local_tm);
Serial.print("");
Serial.print("Session local: ");
Serial.println(buffer);
const char* sessionName = nextRaceJson[F("session_name")];
const char* dateStart = nextRaceJson[F("date_start")];
const char* circuitName = nextRaceJson[F("circuit_short_name")];
localData.session_key = nextRaceJson[F("session_key")];
@@ -132,15 +172,12 @@ int parse_session_json(JsonArray sessions, session_info_t* target, const Semapho
localData.circuit_key = nextRaceJson[F("circuit_key")];
if (localData.circuit_key == 0) return -1;
if (localData.date_start.tm_year == 0) return -1;
if (sessionName != NULL) {
strlcpy(localData.session_name, sessionName, sizeof(localData.session_name));
cleanToASCIIInPlace(localData.session_name);
} else return -1;
if (dateStart != NULL) {
strlcpy(localData.date_start, dateStart, sizeof(localData.date_start));
cleanToASCIIInPlace(localData.date_start);
} else return -1;
if (circuitName != NULL) {
strlcpy(localData.circuit_short_name, circuitName, sizeof(localData.circuit_short_name));
cleanToASCIIInPlace(localData.circuit_short_name);
@@ -231,11 +268,14 @@ void get_next_race(void *pvParameters) {
if (err == DeserializationError::Ok) {
JsonArray meetings = json.as<JsonArray>();
if (meetings.size() != 0) {
parse_meeting_json(meetings, &race_data.meeting_info, &dataMutex);
if (parse_meeting_json(meetings, &race_data.meeting_info, &dataMutex) != 0) {
Serial.print("");
Serial.println(F("Failed to parse meeting data."));
}
}
} else {
Serial.print("");
Serial.print("Failed to parse JSON response: ");
Serial.print(F("Failed to parse JSON response: "));
Serial.println(err.c_str());
}
@@ -275,11 +315,14 @@ void get_next_race(void *pvParameters) {
if (err == DeserializationError::Ok) {
JsonArray sessions = json.as<JsonArray>();
if (sessions.size() != 0) {
parse_session_json(sessions, &race_data.session_info, &dataMutex);
if (parse_session_json(sessions, &race_data.session_info, &dataMutex) != 0) {
Serial.print("");
Serial.println(F("Failed to parse session data"));
}
}
} else {
Serial.print("");
Serial.print("Failed to parse JSON response: ");
Serial.print(F("Failed to parse JSON response: "));
Serial.println(err.c_str());
}
@@ -297,7 +340,7 @@ void get_next_race(void *pvParameters) {
} else {
Serial.print("");
Serial.println("WiFi not connecteFormattedd.");
Serial.println(F("WiFi not connected."));
}
vTaskDelay(retryDelay);
}
+6 -4
View File
@@ -56,7 +56,7 @@ void wifi_connect() {
void sync_time() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Skipping NTP synchronization because WiFi is disconnected.");
Serial.println(F("Skipping NTP synchronization because WiFi is disconnected."));
return;
}
@@ -71,7 +71,7 @@ void sync_time() {
Serial.print("Time synchronized: ");
Serial.println(asctime(&timeinfo));
} else {
Serial.println("Failed to synchronize time within 10 seconds.");
Serial.println(F("Failed to synchronize time within 10 seconds."));
}
}
@@ -115,8 +115,10 @@ void display_loop(void *pvParameters) {
Paint_Clear(WHITE);
if (local_data.session_info.date_start[0] != 0) {
Paint_DrawString_EN(10, 22, local_data.session_info.date_start, &Font16, WHITE, BLACK);
if (local_data.session_info.date_start.tm_year != 0) {
char date_buffer[30];
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d %I:%M:%S %p %Z", &local_data.session_info.date_start);
Paint_DrawString_EN(10, 22, date_buffer, &Font16, WHITE, BLACK);
}
Paint_DrawString_EN(10, 0, counterStr, &Font16, WHITE, BLACK);