ttlappalainen / NMEA0183

Library for handling NMEA0183 messages
73 stars 47 forks source link

NMEA0183SetZDA: New function, to complement the existing ParseZDA #46

Closed Andrei-Errapart closed 1 year ago

ttlappalainen commented 1 year ago

Do you use it and have you tested it? You could also provide alternative with time_t parameter and test it.

Andrei-Errapart commented 1 year ago

We have used it on the field.

If I have time, I will add an overload with time_t parameter.

Would it be a good idea to update the testing library "catch"? Building tests fails and the issue is corrected in newer versions of "catch".

ttlappalainen commented 1 year ago

Just checked - there was once someone adding functions just because they were missing. Unfortunately they were wrong.

Please update catch - I have not used it, so have not noticed the problem.

Andrei-Errapart commented 1 year ago

Long story short: I dropped the idea of supporting time_t for the moment being. If the need arises, I can happily revisit it.

Regarding time_t, I tried the following approach:

bool NMEA0183SetZDA(tNMEA0183Msg& NMEA0183Msg, time_t DateTime, long Timezone, const char* Src)
{
  const long GPSTime = DateTime - (tNMEA0183Msg::elapsedDaysSince1970(DateTime) - 1) * 24*3600;
  tmElements_t tm;
  tNMEA0183Msg::breakTime(DateTime, tm);
  const int T = Timezone / 60;
  return NMEA0183SetZDA(NMEA0183Msg, GPSTime, tNMEA0183Msg::GetDay(tm), tNMEA0183Msg::GetMonth(tm), tNMEA0183Msg::GetYear(tm), T / 60, T % 60);
}

However, the end result differs from the original by 2 hours on my Linux system, which is in the CEST time zone. I didn't check with Arduino or ESP32 at the moment.

In my opinion the time and date things are a bit cumbersome to get right. The time_t can be specified in the local timezone or UTC. In addition, UTC differs from GPS time by 18 seconds at the moment. When a library function has a parameter named "GPSTime", this value has a direct relation to the NMEA message fields. However, when a parameter is of type "time_t", things are more tricky and can lead a library user into thinking that the library is wrong.

If you want to make a clean break with time_t, the C++ standard std::chrono family of time functions seem to be supported by the ESP-IDF framework at least. Given that the latest Arduinos are all 32-bitters and using g++, the chances are there. The nuances of GPS clock and UTC clock are covered, see for example: https://en.cppreference.com/w/cpp/chrono/gps_clock I find the time and date code written with std::chrono difficult to read, but maybe it is just me.