diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 603e1cd..ca73a87 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -423,19 +423,25 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa // Date and time String fmttype = commonData.config->getString(commonData.config->dateFormat); String timesource = commonData.config->getString(commonData.config->timeSource); - int tz = commonData.config->getInt(commonData.config->timeZone); + double tz = commonData.config->getString(commonData.config->timeZone).toDouble(); getdisplay().setTextColor(commonData.fgcolor); getdisplay().setFont(&Ubuntu_Bold8pt7b); getdisplay().setCursor(230, 15); - if (timesource == "RTC") { - time_t tv = mktime(&commonData.data.rtcTime) + tz * 3600; - struct tm *local_tm = localtime(&tv); - getdisplay().print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0)); - getdisplay().print(" "); - getdisplay().print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday)); - getdisplay().print(" "); + if (timesource == "RTC" or timesource == "iRTC") { + // TODO take DST into account + if (commonData.data.rtcValid) { + time_t tv = mktime(&commonData.data.rtcTime) + (int)(tz * 3600); + struct tm *local_tm = localtime(&tv); + getdisplay().print(formatTime('m', local_tm->tm_hour, local_tm->tm_min, 0)); + getdisplay().print(" "); + getdisplay().print(formatDate(fmttype, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday)); + getdisplay().print(" "); + getdisplay().print(tz == 0 ? "UTC" : "LOT"); + } else { + getdisplay().print("RTC invalid"); + } } - else { // timesource == "GPS" + else if (timesource == "GPS") { // Show date and time if date present if(date->valid == true){ String acttime = formatValue(time, commonData).svalue; @@ -445,6 +451,7 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa getdisplay().print(" "); getdisplay().print(actdate); getdisplay().print(" "); + getdisplay().print(tz == 0 ? "UTC" : "LOT"); } else{ if(commonData.config->getBool(commonData.config->useSimuData) == true){ @@ -455,11 +462,8 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa } } } // timesource == "GPS" - if (tz == 0) { - getdisplay().print("UTC"); - } else { - getdisplay().print("LOT"); + getdisplay().print("No time source"); } } } diff --git a/lib/obp60task/OBPSensorTask.cpp b/lib/obp60task/OBPSensorTask.cpp index dcc680e..500389e 100644 --- a/lib/obp60task/OBPSensorTask.cpp +++ b/lib/obp60task/OBPSensorTask.cpp @@ -17,6 +17,8 @@ #include "ObpNmea0183.h" // Check NMEA0183 sentence for uncorrect content #include "OBP60Extensions.h" // Lib for hardware extensions #include "movingAvg.h" // Lib for moving average building +#include "time.h" // For getting NTP time +#include // Internal ESP32 RTC clock // Timer for hardware functions Ticker Timer1(blinkingFlashLED, 500); // Start Timer1 for flash LED all 500ms @@ -150,6 +152,7 @@ void sensorTask(void *param){ // ds1388.adjust(DateTime(__DATE__, __TIME__)); // Set date and time from PC file time } RTC_ready = true; + sensors.rtcValid = true; } } @@ -366,6 +369,28 @@ void sensorTask(void *param){ GwApi::BoatValue *hdop=new GwApi::BoatValue(GwBoatData::_HDOP); GwApi::BoatValue *valueList[]={gpsdays, gpsseconds, hdop}; + // Internal RTC with NTP init + ESP32Time rtc(0); + if (api->getConfig()->getString(api->getConfig()->timeSource) == "iRTC") { + GwApi::Status status; + api->getStatus(status); + if (status.wifiClientConnected) { + const char *ntpServer = api->getConfig()->getCString(api->getConfig()->timeServer); + api->getLogger()->logDebug(GwLog::LOG,"Fetching date and time from NTP server '%s'.", ntpServer); + configTime(0, 0, ntpServer); // get time in UTC + struct tm timeinfo; + if (getLocalTime(&timeinfo)) { + api->getLogger()->logDebug(GwLog::LOG,"NTP time: %04d-%02d-%02d %02d:%02d:%02d UTC", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + rtc.setTimeStruct(timeinfo); + sensors.rtcValid = true; + } else { + api->getLogger()->logDebug(GwLog::LOG,"NTP time fetch failed!"); + } + } else { + api->getLogger()->logDebug(GwLog::LOG,"Wifi client not connected, NTP not available."); + } + } + // Sensor task loop runs with 100ms //#################################################################################### @@ -464,6 +489,9 @@ void sensorTask(void *param){ api->sendN2kMessage(N2kMsg); // } } + } else if (sensors.rtcValid) { + // use internal rtc feature + sensors.rtcTime = rtc.getTimeStruct(); } } diff --git a/lib/obp60task/PageClock.cpp b/lib/obp60task/PageClock.cpp index 6a2ad34..5516356 100644 --- a/lib/obp60task/PageClock.cpp +++ b/lib/obp60task/PageClock.cpp @@ -119,7 +119,7 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. String svalue1 = formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value if(valid1 == true){ - svalue1old = svalue1; // Save old value + svalue1old = svalue1; // Save old value unit1old = unit1; // Save old unit } @@ -132,7 +132,7 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value if(valid2 == true){ - svalue2old = svalue2; // Save old value + svalue2old = svalue2; // Save old value unit2old = unit2; // Save old unit } @@ -145,7 +145,7 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value if(valid3 == true){ - svalue3old = svalue3; // Save old value + svalue3old = svalue3; // Save old value unit3old = unit3; // Save old unit } @@ -177,7 +177,7 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. if (source == 'G') { // GPS value getdisplay().print(svalue2); - } else { + } else if (commonData->data.rtcValid) { // RTC value if (tz == 'L') { getdisplay().print(formatDate(dateformat, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday)); @@ -185,6 +185,8 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. else { getdisplay().print(formatDate(dateformat, commonData->data.rtcTime.tm_year + 1900, commonData->data.rtcTime.tm_mon + 1, commonData->data.rtcTime.tm_mday)); } + } else { + getdisplay().print("---"); } } else { getdisplay().print(svalue2old); @@ -203,13 +205,15 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. if (source == 'G') { getdisplay().print(svalue1); // Value } - else { + else if (commonData->data.rtcValid) { if (tz == 'L') { getdisplay().print(formatTime('s', local_tm->tm_hour, local_tm->tm_min, local_tm->tm_sec)); } else { getdisplay().print(formatTime('s', commonData->data.rtcTime.tm_hour, commonData->data.rtcTime.tm_min, commonData->data.rtcTime.tm_sec)); } + } else { + getdisplay().print("---"); } } else { @@ -329,14 +333,10 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. getdisplay().setFont(&Ubuntu_Bold12pt7b); getdisplay().setCursor(175, 110); if(holdvalues == false){ - if (tz == 'L') { - getdisplay().print(unit2); // Unit - } else { - getdisplay().print("UTC"); - } + getdisplay().print(tz == 'L' ? "LOT" : "UTC"); } else{ - getdisplay().print(unit2old); // Unit + getdisplay().print(unit2old); // date unit } getdisplay().setFont(&Ubuntu_Bold8pt7b); @@ -378,7 +378,7 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. // Draw hour pointer float startwidth = 8; // Start width of pointer - if(valid1 == true || holdvalues == true || simulation == true){ + if(valid1 == true || commonData->data.rtcValid || holdvalues == true || simulation == true){ float sinx=sin(hour * 30.0 * pi / 180); // Hour float cosx=cos(hour * 30.0 * pi / 180); // Normal pointer @@ -404,7 +404,7 @@ double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5. // Draw minute pointer startwidth = 8; // Start width of pointer - if(valid1 == true || holdvalues == true || simulation == true){ + if(valid1 == true || commonData->data.rtcValid || holdvalues == true || simulation == true){ float sinx=sin(minute * 6.0 * pi / 180); // Minute float cosx=cos(minute * 6.0 * pi / 180); // Normal pointer diff --git a/lib/obp60task/Pagedata.h b/lib/obp60task/Pagedata.h index 0988d01..65bdc67 100644 --- a/lib/obp60task/Pagedata.h +++ b/lib/obp60task/Pagedata.h @@ -46,6 +46,7 @@ typedef struct{ double rotationAngle = 0; // Rotation angle in radiant bool validRotAngle = false; // Valid flag magnet present for rotation sensor struct tm rtcTime; // UTC time from internal RTC + bool rtcValid = false; int sunsetHour = 0; int sunsetMinute = 0; int sunriseHour = 0; diff --git a/lib/obp60task/config.json b/lib/obp60task/config.json index eaf0be4..62a10d2 100644 --- a/lib/obp60task/config.json +++ b/lib/obp60task/config.json @@ -697,8 +697,8 @@ "default": "GPS", "description": "Data source for date and time display in status line [RTC|GPS]", "list": [ - {"l":"Internal real time clock (RTC)","v":"RTC"}, - {"l":"External time via bus (GPS)","v":"GPS"} + {"l":"Real time clock (RTC)","v":"RTC"}, + {"l":"Time via bus (GPS)","v":"GPS"} ], "category": "OBP60 Display", "capabilities": { diff --git a/lib/obp60task/config_obp40.json b/lib/obp60task/config_obp40.json index 9522dcb..9ba6da1 100644 --- a/lib/obp60task/config_obp40.json +++ b/lib/obp60task/config_obp40.json @@ -8,6 +8,17 @@ "description": "system name, used for the access point and for services", "category": "system" }, + { + "name": "timeServer", + "label": "time server", + "type": "string", + "default": "pool.ntp.org", + "description": "NTP time server. Use only one hostname or IP address", + "category": "wifi client", + "capabilities": { + "obp40": "true" + } + }, { "name": "timeZone", "label": "Time Zone", @@ -710,9 +721,10 @@ "label": "Status Time Source", "type": "list", "default": "GPS", - "description": "Data source for date and time display in status line [RTC|GPS]", + "description": "Data source for date and time display in status line [RTC|iRTC|GPS]", "list": [ - {"l":"Internal real time clock (RTC)","v":"RTC"}, + {"l":"Internal real time clock (iRTC)","v":"iRTC"}, + {"l":"External real time clock (RTC)","v":"RTC"}, {"l":"External time via bus (GPS)","v":"GPS"} ], "category": "OBP40 Display", diff --git a/lib/obp60task/platformio.ini b/lib/obp60task/platformio.ini index 2259b61..5ea19a0 100644 --- a/lib/obp60task/platformio.ini +++ b/lib/obp60task/platformio.ini @@ -71,6 +71,7 @@ lib_deps = Wire SPI SD + ESP32time esphome/AsyncTCP-esphome@2.0.1 robtillaart/PCF8574@0.3.9 adafruit/Adafruit Unified Sensor @ 1.1.13