#include "HermitCrab.h" #include "TimeManager.h" #include "ConnectWiFi.h" #include #include "Config.h" #define TAG_TIME "Time" TimeManager timeManager; void TimeManager::begin() { setenv("TZ", "UTC", 1); // Set time zone to Asia/Seoul (UTC+9) tzset(); // Apply the timezone setting // Initialize UDP only if WiFi is connected if (isWiFiConnected() && !udpInitialized) { udpInitialized = udp.begin(localPort); } // Send an initial NTP request on startup sendNTPRequest(); lastNTPRequestMillis = millis(); } void TimeManager::Stop() { if (udpInitialized) { udp.stop(); } } bool TimeManager::getTime(unsigned long tickMillis) { // Check WiFi Connection if (!isWiFiConnected()) { //ESP_LOGI(TAG_TIME,"TimeManager - getTime called while not connected"); if (udpInitialized) udpInitialized = false; return false; } // Check if 30 minutes have passed since last NTP request if (udpInitialized && ((tickMillis - lastNTPRequestMillis >= NTP_REQUEST_INTERVAL) || !bHasNTPTime && (tickMillis - lastNTPRequestMillis >= NTP_FAILED_INTERNAL))) { sendNTPRequest(); lastNTPRequestMillis = tickMillis; } // Check if there is an NTP response, and if so, update the system clock return checkNTPResponse(); } MY_IRAM_ATTR void TimeManager::sendNTPRequest() { byte ntpPacket[48] = {0}; ntpPacket[0] = 0b11100011; // LI, Version, Mode ntpPacket[1] = 0; // Stratum, or type of clock ntpPacket[2] = 6; // Polling Interval ntpPacket[3] = 0xEC; // Peer Clock Precision udp.beginPacket(ntpServer, 123); // NTP requests are sent to port 123 udp.write(ntpPacket, 48); udp.endPacket(); } MY_IRAM_ATTR bool TimeManager::checkNTPResponse() { if (udp.parsePacket() == 0) { // No response yet return false; } byte ntpBuffer[48]; udp.read(ntpBuffer, 48); // Extract and set the time if response is valid unsigned long epochTime = (unsigned long)ntpBuffer[40] << 24 | (unsigned long)ntpBuffer[41] << 16 | (unsigned long)ntpBuffer[42] << 8 | (unsigned long)ntpBuffer[43]; epochTime -= 2208988800UL; // Convert from NTP to Unix time // epochTime += (9 * 3600); // GMT+9 if (!bHasNTPTime) { bHasNTPTime = true; firstNTPTime = epochTime; config.m_nEpochTime = epochTime; } setSystemClock(epochTime); // ESP_LOGI(TAG_TIME,printTime()); return true; } void TimeManager::setSystemClock(unsigned long epochTime) { struct timeval now; now.tv_sec = epochTime; now.tv_usec = 0; settimeofday(&now, NULL); }