mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-31 22:21:52 +00:00
Added firmware upload from UI
This commit is contained in:
243
lib/Timezone/src/Timezone.cpp
Normal file
243
lib/Timezone/src/Timezone.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/*----------------------------------------------------------------------*
|
||||
* Arduino Timezone Library *
|
||||
* Jack Christensen Mar 2012 *
|
||||
* *
|
||||
* Arduino Timezone Library Copyright (C) 2018 by Jack Christensen and *
|
||||
* licensed under GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html *
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#include "Timezone.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/eeprom.h>
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Create a Timezone object from the given time change rules. *
|
||||
*----------------------------------------------------------------------*/
|
||||
Timezone::Timezone(TimeChangeRule dstStart, TimeChangeRule stdStart)
|
||||
: m_dst(dstStart), m_std(stdStart)
|
||||
{
|
||||
initTimeChanges();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Create a Timezone object for a zone that does not observe *
|
||||
* daylight time. *
|
||||
*----------------------------------------------------------------------*/
|
||||
Timezone::Timezone(TimeChangeRule stdTime)
|
||||
: m_dst(stdTime), m_std(stdTime)
|
||||
{
|
||||
initTimeChanges();
|
||||
}
|
||||
|
||||
#ifdef __AVR__
|
||||
/*----------------------------------------------------------------------*
|
||||
* Create a Timezone object from time change rules stored in EEPROM *
|
||||
* at the given address. *
|
||||
*----------------------------------------------------------------------*/
|
||||
Timezone::Timezone(int address)
|
||||
{
|
||||
readRules(address);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Convert the given UTC time to local time, standard or *
|
||||
* daylight time, as appropriate. *
|
||||
*----------------------------------------------------------------------*/
|
||||
time_t Timezone::toLocal(time_t utc)
|
||||
{
|
||||
// recalculate the time change points if needed
|
||||
if (year(utc) != year(m_dstUTC)) calcTimeChanges(year(utc));
|
||||
|
||||
if (utcIsDST(utc))
|
||||
return utc + m_dst.offset * SECS_PER_MIN;
|
||||
else
|
||||
return utc + m_std.offset * SECS_PER_MIN;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Convert the given UTC time to local time, standard or *
|
||||
* daylight time, as appropriate, and return a pointer to the time *
|
||||
* change rule used to do the conversion. The caller must take care *
|
||||
* not to alter this rule. *
|
||||
*----------------------------------------------------------------------*/
|
||||
time_t Timezone::toLocal(time_t utc, TimeChangeRule **tcr)
|
||||
{
|
||||
// recalculate the time change points if needed
|
||||
if (year(utc) != year(m_dstUTC)) calcTimeChanges(year(utc));
|
||||
|
||||
if (utcIsDST(utc)) {
|
||||
*tcr = &m_dst;
|
||||
return utc + m_dst.offset * SECS_PER_MIN;
|
||||
}
|
||||
else {
|
||||
*tcr = &m_std;
|
||||
return utc + m_std.offset * SECS_PER_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Convert the given local time to UTC time. *
|
||||
* *
|
||||
* WARNING: *
|
||||
* This function is provided for completeness, but should seldom be *
|
||||
* needed and should be used sparingly and carefully. *
|
||||
* *
|
||||
* Ambiguous situations occur after the Standard-to-DST and the *
|
||||
* DST-to-Standard time transitions. When changing to DST, there is *
|
||||
* one hour of local time that does not exist, since the clock moves *
|
||||
* forward one hour. Similarly, when changing to standard time, there *
|
||||
* is one hour of local times that occur twice since the clock moves *
|
||||
* back one hour. *
|
||||
* *
|
||||
* This function does not test whether it is passed an erroneous time *
|
||||
* value during the Local -> DST transition that does not exist. *
|
||||
* If passed such a time, an incorrect UTC time value will be returned. *
|
||||
* *
|
||||
* If passed a local time value during the DST -> Local transition *
|
||||
* that occurs twice, it will be treated as the earlier time, i.e. *
|
||||
* the time that occurs before the transistion. *
|
||||
* *
|
||||
* Calling this function with local times during a transition interval *
|
||||
* should be avoided! *
|
||||
*----------------------------------------------------------------------*/
|
||||
time_t Timezone::toUTC(time_t local)
|
||||
{
|
||||
// recalculate the time change points if needed
|
||||
if (year(local) != year(m_dstLoc)) calcTimeChanges(year(local));
|
||||
|
||||
if (locIsDST(local))
|
||||
return local - m_dst.offset * SECS_PER_MIN;
|
||||
else
|
||||
return local - m_std.offset * SECS_PER_MIN;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Determine whether the given UTC time_t is within the DST interval *
|
||||
* or the Standard time interval. *
|
||||
*----------------------------------------------------------------------*/
|
||||
bool Timezone::utcIsDST(time_t utc)
|
||||
{
|
||||
// recalculate the time change points if needed
|
||||
if (year(utc) != year(m_dstUTC)) calcTimeChanges(year(utc));
|
||||
|
||||
if (m_stdUTC == m_dstUTC) // daylight time not observed in this tz
|
||||
return false;
|
||||
else if (m_stdUTC > m_dstUTC) // northern hemisphere
|
||||
return (utc >= m_dstUTC && utc < m_stdUTC);
|
||||
else // southern hemisphere
|
||||
return !(utc >= m_stdUTC && utc < m_dstUTC);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Determine whether the given Local time_t is within the DST interval *
|
||||
* or the Standard time interval. *
|
||||
*----------------------------------------------------------------------*/
|
||||
bool Timezone::locIsDST(time_t local)
|
||||
{
|
||||
// recalculate the time change points if needed
|
||||
if (year(local) != year(m_dstLoc)) calcTimeChanges(year(local));
|
||||
|
||||
if (m_stdUTC == m_dstUTC) // daylight time not observed in this tz
|
||||
return false;
|
||||
else if (m_stdLoc > m_dstLoc) // northern hemisphere
|
||||
return (local >= m_dstLoc && local < m_stdLoc);
|
||||
else // southern hemisphere
|
||||
return !(local >= m_stdLoc && local < m_dstLoc);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Calculate the DST and standard time change points for the given *
|
||||
* given year as local and UTC time_t values. *
|
||||
*----------------------------------------------------------------------*/
|
||||
void Timezone::calcTimeChanges(int yr)
|
||||
{
|
||||
m_dstLoc = toTime_t(m_dst, yr);
|
||||
m_stdLoc = toTime_t(m_std, yr);
|
||||
m_dstUTC = m_dstLoc - m_std.offset * SECS_PER_MIN;
|
||||
m_stdUTC = m_stdLoc - m_dst.offset * SECS_PER_MIN;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Initialize the DST and standard time change points. *
|
||||
*----------------------------------------------------------------------*/
|
||||
void Timezone::initTimeChanges()
|
||||
{
|
||||
m_dstLoc = 0;
|
||||
m_stdLoc = 0;
|
||||
m_dstUTC = 0;
|
||||
m_stdUTC = 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Convert the given time change rule to a time_t value *
|
||||
* for the given year. *
|
||||
*----------------------------------------------------------------------*/
|
||||
time_t Timezone::toTime_t(TimeChangeRule r, int yr)
|
||||
{
|
||||
uint8_t m = r.month; // temp copies of r.month and r.week
|
||||
uint8_t w = r.week;
|
||||
if (w == 0) // is this a "Last week" rule?
|
||||
{
|
||||
if (++m > 12) // yes, for "Last", go to the next month
|
||||
{
|
||||
m = 1;
|
||||
++yr;
|
||||
}
|
||||
w = 1; // and treat as first week of next month, subtract 7 days later
|
||||
}
|
||||
|
||||
// calculate first day of the month, or for "Last" rules, first day of the next month
|
||||
tmElements_t tm;
|
||||
tm.Hour = r.hour;
|
||||
tm.Minute = 0;
|
||||
tm.Second = 0;
|
||||
tm.Day = 1;
|
||||
tm.Month = m;
|
||||
tm.Year = yr - 1970;
|
||||
time_t t = makeTime(tm);
|
||||
|
||||
// add offset from the first of the month to r.dow, and offset for the given week
|
||||
t += ( (r.dow - weekday(t) + 7) % 7 + (w - 1) * 7 ) * SECS_PER_DAY;
|
||||
// back up a week if this is a "Last" rule
|
||||
if (r.week == 0) t -= 7 * SECS_PER_DAY;
|
||||
return t;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Read or update the daylight and standard time rules from RAM. *
|
||||
*----------------------------------------------------------------------*/
|
||||
void Timezone::setRules(TimeChangeRule dstStart, TimeChangeRule stdStart)
|
||||
{
|
||||
m_dst = dstStart;
|
||||
m_std = stdStart;
|
||||
initTimeChanges(); // force calcTimeChanges() at next conversion call
|
||||
}
|
||||
|
||||
#ifdef __AVR__
|
||||
/*----------------------------------------------------------------------*
|
||||
* Read the daylight and standard time rules from EEPROM at *
|
||||
* the given address. *
|
||||
*----------------------------------------------------------------------*/
|
||||
void Timezone::readRules(int address)
|
||||
{
|
||||
eeprom_read_block((void *) &m_dst, (void *) address, sizeof(m_dst));
|
||||
address += sizeof(m_dst);
|
||||
eeprom_read_block((void *) &m_std, (void *) address, sizeof(m_std));
|
||||
initTimeChanges(); // force calcTimeChanges() at next conversion call
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Write the daylight and standard time rules to EEPROM at *
|
||||
* the given address. *
|
||||
*----------------------------------------------------------------------*/
|
||||
void Timezone::writeRules(int address)
|
||||
{
|
||||
eeprom_write_block((void *) &m_dst, (void *) address, sizeof(m_dst));
|
||||
address += sizeof(m_dst);
|
||||
eeprom_write_block((void *) &m_std, (void *) address, sizeof(m_std));
|
||||
}
|
||||
|
||||
#endif
|
||||
61
lib/Timezone/src/Timezone.h
Normal file
61
lib/Timezone/src/Timezone.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*----------------------------------------------------------------------*
|
||||
* Arduino Timezone Library *
|
||||
* Jack Christensen Mar 2012 *
|
||||
* *
|
||||
* Arduino Timezone Library Copyright (C) 2018 by Jack Christensen and *
|
||||
* licensed under GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html *
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef TIMEZONE_H_INCLUDED
|
||||
#define TIMEZONE_H_INCLUDED
|
||||
#if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
|
||||
|
||||
// convenient constants for TimeChangeRules
|
||||
enum week_t {Last, First, Second, Third, Fourth};
|
||||
enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat};
|
||||
enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
|
||||
|
||||
// structure to describe rules for when daylight/summer time begins,
|
||||
// or when standard time begins.
|
||||
struct TimeChangeRule
|
||||
{
|
||||
char abbrev[6]; // five chars max
|
||||
uint8_t week; // First, Second, Third, Fourth, or Last week of the month
|
||||
uint8_t dow; // day of week, 1=Sun, 2=Mon, ... 7=Sat
|
||||
uint8_t month; // 1=Jan, 2=Feb, ... 12=Dec
|
||||
uint8_t hour; // 0-23
|
||||
int offset; // offset from UTC in minutes
|
||||
};
|
||||
|
||||
class Timezone
|
||||
{
|
||||
public:
|
||||
Timezone(TimeChangeRule dstStart, TimeChangeRule stdStart);
|
||||
Timezone(TimeChangeRule stdTime);
|
||||
Timezone(int address);
|
||||
time_t toLocal(time_t utc);
|
||||
time_t toLocal(time_t utc, TimeChangeRule **tcr);
|
||||
time_t toUTC(time_t local);
|
||||
bool utcIsDST(time_t utc);
|
||||
bool locIsDST(time_t local);
|
||||
void setRules(TimeChangeRule dstStart, TimeChangeRule stdStart);
|
||||
void readRules(int address);
|
||||
void writeRules(int address);
|
||||
|
||||
private:
|
||||
void calcTimeChanges(int yr);
|
||||
void initTimeChanges();
|
||||
time_t toTime_t(TimeChangeRule r, int yr);
|
||||
TimeChangeRule m_dst; // rule for start of dst or summer time for any year
|
||||
TimeChangeRule m_std; // rule for start of standard time for any year
|
||||
time_t m_dstUTC; // dst start for given/current year, given in UTC
|
||||
time_t m_stdUTC; // std time start for given/current year, given in UTC
|
||||
time_t m_dstLoc; // dst start for given/current year, given in local time
|
||||
time_t m_stdLoc; // std time start for given/current year, given in local time
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user