-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatic DST support #3072
Automatic DST support #3072
Conversation
@@ -51,6 +52,7 @@ PG_REGISTER_WITH_RESET_TEMPLATE(timeConfig_t, timeConfig, PG_TIME_CONFIG, 0); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're adding fields to the parameter group. Please also increase version number in the declaration PG_REGISTER_WITH_RESET_TEMPLATE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rookie mistake, my bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries, I keep forgetting to do this myself 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any more work left to be done on this? Sorry to be bothering, it seems that I cannot manually mark this request as solved.
Unfortunately this won't get into 1.9.1, but we'll merge it as soon as we get 1.9.1 out of the door. Can you please amend this or prepare a new PR with documentation? |
CLI docs done! Should these options also be described elsewhere? |
Very welcome addition! I think we either need a few more options or a smarter algorithm which takes the GPS location into account. DST change doesn't happen on same day in all places. You can see the full list here https://en.wikipedia.org/wiki/Daylight_saving_time_by_country, but the biggest problem we need to account for is the difference between US and EU. |
That's true, different offsets should be handled. Messing with GPS data is too much in my opinion, tracking nations & states could quickly turn into an absurd chore... What about a list of special cases?
Another option could be letting users set a specific start/end time and date in a subset of ISO 8601 formats, such as If nobody has better ideas I'll try to implement this last solution as a P.S.: could anybody help me in figuring out why the |
Why not just do this in the configurator (set /clear) the extant dst variable. The desktop OS already knows about the global DST rules. |
@stronnag Could you elaborate? This way you'd depend on the configurator (that is to say: you'll need a PC) to enable/disable DST, or did I get it wrong? It looks a bit too much tight coupling to me, I'd rather keep this feature not configurator-dependant. |
Well the user, or at least the majority of them, have a pretty strong dependency on / coupling to the configurator anyway. So my though process was along the lines that either we end up with a perhaps large amount of code to maintain (and sometimes update) to provide global coverage, or we put a burden on the user to set up some rules which the FC has to parse. The time switch does not happen on the same calendar day each year, so perhaps you end up with something as arcane as the old POSIX TZ rules, for example So it occurred to me that the configurator could be updated to manage the existing mechanism. After all, the host already knows the rules and the configurator could be programmed to compare the current TZ offset with that in the FC and ask the user if she'd like to adjust the setting for the clocks changing. If it's anything like my household, it would just be another device to adjust. But I really have no strong views either way. |
That would be clever, and as you said the user would simply have another device to adjust the time of - not too much of a chore. That could also be compatible with the EU/USA presets that I'm working on, and if a user lives outside these two areas he/she will disable automatic adjustments and (eventually) use the configurator to update the absolute offset. |
I think we could add a couple of variables which indicate the offset in hours from the start of the year when DST starts/stops (max value is 24*366, so it fits in 16 bits). When connecting from the configurator, we could retrieve those and check them against the host computer. If they match, nothing else needs to be done. If they don’t, we can present a dialog to the user asking if they should be updated. This just needs one connection from the configurator until the user switches time zones/DST points, etc... While we're at it, we could also do the same for the timezone, since right now users have to set it manually. This will have very minimal impact on firmware size, but the configurator needs a non-trivial amount of work. I'm only a bit wary of storing the offset in hours and then some country starts switching at xx:30, so maybe we should consider storing minutes like we do for the timezone, but that needs 32 bits. Thoughts? |
as the changeover typically takes place in the early hours of the morning, we probably don't need to worry about the possibility of 1/2 hours. |
I've implemented @fiam's first suggestion before seeing this last idea. Leaving the configurator aside for the moment and assuming that everything is done via CLI, what's an easy way for the user to calculate hours since the start of the year and up to the nth weekday of a given month? Sounds like an easy task for a script but difficult for an human, but I could be missing something evident. |
@nmaggioni Storing the hours would be only useful for "machine assisted" usage. Calculating the hours manually would be a pain. With that said, I also like this approach that you've submitted right now. I think it could be merged with a few changes, I'll post a review in a few minutes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, guard all the new code and settings with #if defined(RTC_AUTOMATIC_DST)
and define it for targets with flash size > 128 in src/main/target/common.h
. F3 targets are very close to their size limit, so we'll need to start disabling features for them soon.
src/main/common/time.h
Outdated
typedef enum { | ||
DST_EU, | ||
DST_USA, | ||
} tz_dst_country_e; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name this tz_automatic_dst_e
with the following values: TZ_AUTO_DST_OFF
, TZ_AUTO_DST_EU
, TZ_AUTO_DST_USA
. Adjust settings.yaml accordingly.
src/main/common/time.h
Outdated
typedef struct timeConfig_s { | ||
int16_t tz_offset; // Offset from UTC in minutes, might be positive or negative | ||
bool tz_automatic_dst; // Automatically handle DST or ignore it | ||
tz_dst_country_e tz_dst_country; | ||
} timeConfig_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than 2 variables, use just one uint8_t named tz_automatic_dst
which can take the values OFF
(default), US
,EU
, etc... That way we use a single byte for storage and users just need to change one setting to make it work. Put a comment at the right indicating that the value comes from tz_automatic_dst_e
.
src/main/common/time.c
Outdated
dateTime_t dateTime; | ||
rtcTimeToDateTime(&dateTime, t); | ||
int lastSunday; | ||
switch (timeConfig()->tz_dst_country) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once you make tz_automatic_dst
an uint8_t, cast it here to tz_automatic_dst_e
, so the compiler will make sure the checks are exhaustive. i.e.
switch ((tz_automatic_dst_e)timeConfig()-> tz_automatic_dst) {
@fiam Done! Thanks for the very helpful pointers. |
Includes `tz_dst_country` removal and docs update
a523616
to
6ad6cc3
Compare
Add probot.stale for automatically managing inactive issues
@digitalentity Are any other corrections needed or can this be set to mergeable in 2.0? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not reviewing these changes sooner. We've all been pretty busy getting a lot of stuff ready for 2.0.
src/main/common/time.c
Outdated
{ | ||
rtcTime_t initialTime = dateTimeToRtcTime(dateTimeInitial); | ||
rtcTime_t offsetTime = rtcTimeMake(rtcTimeGetSeconds(&initialTime) + minutes * 60, rtcTimeGetMillis(&initialTime)); | ||
#if defined(RTC_AUTOMATIC_DST) | ||
if (automatic_dst && isDST(offsetTime)) { offsetTime += 3600; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, align the #if
at the start of the line. Don't put the code inside the if
in the same line. We use:
if (condition) {
do_foo();
}
(this applies to more places in the diff, but no reason to repeat the same comment in all of them)
src/main/common/time.c
Outdated
@@ -120,14 +121,84 @@ static bool rtcIsDateTimeValid(dateTime_t *dateTime) | |||
(dateTime->millis <= 999); | |||
} | |||
|
|||
static void dateTimeWithOffset(dateTime_t *dateTimeOffset, dateTime_t *dateTimeInitial, int16_t minutes) | |||
#if defined(RTC_AUTOMATIC_DST) | |||
static int lastSundayOfMonth(int currentYear, int wantedMonth) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation and formatting need some work in all this function. Opening brace for functions should be in the next line. Indent using 4 spaces and add a space before and after ,
as well as arithmetic operators.
src/main/common/time.c
Outdated
#if defined(RTC_AUTOMATIC_DST) | ||
static int lastSundayOfMonth(int currentYear, int wantedMonth) { | ||
int days[] = {31,29,31,30,31,30,31,31,30,31,30,31}; | ||
int m, y = currentYear, w; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line seems very hairy. m
should be declared in the for
, since it's initialised and used only there. y
is assigned to w
(where is that variable coming from?), but it looks like you could just use currentYear
a few lines down without any extra variables.
src/main/common/time.c
Outdated
days[1] -= (y % 4) || (!(y % 100) && (y % 400)); | ||
w = y * 365 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + 6; | ||
|
||
for(m = 0; m < 12; m++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space between for
and (
@fiam Everything should be okay now, did I miss anything? You should really publish an official styleguide in the developer docs, btw. |
@nmaggioni It looks good to me. Thanks! |
@nmaggioni I spoke too fast, it's not compiling. You need to handle
And it should be good to go |
Whoops, my bad... Forgot about that, it's now fixed. |
Rebase on 'development' required.
@nmaggioni new features should be done on top of |
Sorry, I must have fudged up something while branching locally - it's now fixed! |
@nmaggioni I'm not sure this is working as intended? or has it not been fully implemented? Entering CLI Mode, type 'exit' to return, or 'help' get tztz_offset = -240 tz_automatic_dst = 0 |
@MRC3742 Can reproduce, I'm investigating. |
This PR covers the automatic handling of Daylight Saving Time, based on NIST's specs.
Calculations were inspired by 1 and 2.
This behavior can be toggled ON and OFF via a new CLI setting:
tz_automatic_dst
. If set to OFF/False, DST is simply ignored.Documentation is planned to be added in a separate PR alongside some lines aboutDocs included.tz_offset
(currently not mentioned at all in the docs, only in release notes).