kopia lustrzana https://github.com/lora-aprs/LoRa_APRS_iGate
commit
f1f42038e7
|
@ -3,7 +3,6 @@ name: Integration Tests
|
||||||
on:
|
on:
|
||||||
merge_group:
|
merge_group:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, reopened]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -45,10 +44,10 @@ jobs:
|
||||||
- 'lib/BoardFinder'
|
- 'lib/BoardFinder'
|
||||||
- 'lib/ConfigurationManagement'
|
- 'lib/ConfigurationManagement'
|
||||||
#- 'lib/Display'
|
#- 'lib/Display'
|
||||||
#- 'lib/NTPClient'
|
- 'lib/NTPClient'
|
||||||
- 'lib/PowerManagement'
|
- 'lib/PowerManagement'
|
||||||
- 'lib/System'
|
- 'lib/System'
|
||||||
#- 'lib/TimeLib'
|
- 'lib/TimeLib'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
@ -61,38 +60,14 @@ jobs:
|
||||||
cppcheck:
|
cppcheck:
|
||||||
name: Run cppcheck
|
name: Run cppcheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
|
||||||
CPPCHECK_ARGS: --enable=all --std=c++14 --inline-suppr -I lib/BoardFinder -I lib/ConfigurationManagement -I lib/Display -I lib/LoRa -I lib/LoRa_APRS -I lib/NTPClient -I lib/PowerManagement -I lib/System -I lib/TimeLib -i lib/Display -i lib/LoRa -i lib/NTPClient -i lib/TimeLib src lib
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout code
|
- uses: actions/cache@v3
|
||||||
uses: actions/checkout@v3
|
|
||||||
- run: docker pull facthunder/cppcheck:latest
|
|
||||||
- name: Run cppcheck and print result
|
|
||||||
run: docker run --rm -v ${PWD}:/src facthunder/cppcheck:latest /bin/bash -c "cppcheck $CPPCHECK_ARGS"
|
|
||||||
- name: Run cppcheck and create html
|
|
||||||
run: docker run --rm -v ${PWD}:/src facthunder/cppcheck:latest /bin/bash -c "cppcheck --xml $CPPCHECK_ARGS 2> report.xml && cppcheck-htmlreport --file=report.xml --report-dir=output"
|
|
||||||
- name: Upload report
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: Cppcheck Report
|
|
||||||
path: output
|
|
||||||
|
|
||||||
|
|
||||||
remote_testing:
|
|
||||||
name: Remote Testing
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
env:
|
|
||||||
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- name: Setup Cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/pip
|
~/.cache/pip
|
||||||
~/.platformio
|
~/.platformio/.cache
|
||||||
key: remote-cache
|
key: check-cache
|
||||||
- name: Setup Python
|
- uses: actions/setup-python@v4
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
with:
|
||||||
python-version: '3.10'
|
python-version: '3.10'
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
|
@ -101,9 +76,37 @@ jobs:
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install --upgrade platformio
|
pip install --upgrade platformio
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Run PlatformIO Check
|
||||||
|
run: pio check --fail-on-defect high -e lora_board
|
||||||
|
|
||||||
|
hw_testing:
|
||||||
|
name: Hardware Testing
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
usb_port: [ttyUSB0]
|
||||||
|
runs-on: [self-hosted, "${{ matrix.usb_port }}"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/pip
|
||||||
|
~/.platformio/.cache
|
||||||
|
key: hw-cache
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Install PlatformIO
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install --upgrade platformio
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: List Devices
|
- name: List Devices
|
||||||
run: pio remote device list
|
run: pio device list
|
||||||
- name: PlatformIO Test
|
- name: PlatformIO Test
|
||||||
run: pio remote test -v -r --upload-port /dev/ttyUSB4 --test-port /dev/ttyUSB4
|
if: always()
|
||||||
|
run: flock -w 600 --verbose /locks/pio-${{ matrix.usb_port }} -c "pio test -vvv --upload-port /dev/${{ matrix.usb_port }} --test-port /dev/${{ matrix.usb_port }}"
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ NTPClient::NTPClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
NTPClient::NTPClient(long timeOffset) {
|
NTPClient::NTPClient(long timeOffset) {
|
||||||
this->_timeOffset = timeOffset;
|
this->_timeOffset = timeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTPClient::NTPClient(const char* poolServerName) {
|
NTPClient::NTPClient(const char *poolServerName) {
|
||||||
this->_poolServerName = poolServerName;
|
this->_poolServerName = poolServerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,18 +37,18 @@ NTPClient::NTPClient(IPAddress poolServerIP) {
|
||||||
this->_poolServerName = NULL;
|
this->_poolServerName = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTPClient::NTPClient(const char* poolServerName, long timeOffset) {
|
NTPClient::NTPClient(const char *poolServerName, long timeOffset) {
|
||||||
this->_timeOffset = timeOffset;
|
this->_timeOffset = timeOffset;
|
||||||
this->_poolServerName = poolServerName;
|
this->_poolServerName = poolServerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTPClient::NTPClient(IPAddress poolServerIP, long timeOffset){
|
NTPClient::NTPClient(IPAddress poolServerIP, long timeOffset) {
|
||||||
this->_timeOffset = timeOffset;
|
this->_timeOffset = timeOffset;
|
||||||
this->_poolServerIP = poolServerIP;
|
this->_poolServerIP = poolServerIP;
|
||||||
this->_poolServerName = NULL;
|
this->_poolServerName = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTPClient::NTPClient(const char* poolServerName, long timeOffset, unsigned long updateInterval) {
|
NTPClient::NTPClient(const char *poolServerName, long timeOffset, unsigned long updateInterval) {
|
||||||
this->_timeOffset = timeOffset;
|
this->_timeOffset = timeOffset;
|
||||||
this->_poolServerName = poolServerName;
|
this->_poolServerName = poolServerName;
|
||||||
this->_updateInterval = updateInterval;
|
this->_updateInterval = updateInterval;
|
||||||
|
@ -74,23 +74,24 @@ void NTPClient::begin(unsigned int port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTPClient::forceUpdate() {
|
bool NTPClient::forceUpdate() {
|
||||||
#ifdef DEBUG_NTPClient
|
#ifdef DEBUG_NTPClient
|
||||||
Serial.println("Update from NTP Server");
|
Serial.println("Update from NTP Server");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// flush any existing packets
|
// flush any existing packets
|
||||||
while(this->_udp.parsePacket() != 0)
|
while (this->_udp.parsePacket() != 0)
|
||||||
this->_udp.flush();
|
this->_udp.flush();
|
||||||
|
|
||||||
this->sendNTPPacket();
|
this->sendNTPPacket();
|
||||||
|
|
||||||
// Wait till data is there or timeout...
|
// Wait till data is there or timeout...
|
||||||
byte timeout = 0;
|
byte timeout = 0;
|
||||||
int cb = 0;
|
int cb = 0;
|
||||||
do {
|
do {
|
||||||
delay ( 10 );
|
delay(10);
|
||||||
cb = this->_udp.parsePacket();
|
cb = this->_udp.parsePacket();
|
||||||
if (timeout > 100) return false; // timeout after 1000 ms
|
if (timeout > 100)
|
||||||
|
return false; // timeout after 1000 ms
|
||||||
timeout++;
|
timeout++;
|
||||||
} while (cb == 0);
|
} while (cb == 0);
|
||||||
|
|
||||||
|
@ -99,36 +100,37 @@ bool NTPClient::forceUpdate() {
|
||||||
this->_udp.read(this->_packetBuffer, NTP_PACKET_SIZE);
|
this->_udp.read(this->_packetBuffer, NTP_PACKET_SIZE);
|
||||||
|
|
||||||
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
|
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
|
||||||
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
|
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
|
||||||
// combine the four bytes (two words) into a long integer
|
// combine the four bytes (two words) into a long integer
|
||||||
// this is NTP time (seconds since Jan 1 1900):
|
// this is NTP time (seconds since Jan 1 1900):
|
||||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
||||||
|
|
||||||
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
|
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
|
||||||
|
|
||||||
return true; // return true after successful update
|
return true; // return true after successful update
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTPClient::update() {
|
bool NTPClient::update() {
|
||||||
if ((millis() - this->_lastUpdate >= this->_updateInterval) // Update after _updateInterval
|
if ((millis() - this->_lastUpdate >= this->_updateInterval) // Update after _updateInterval
|
||||||
|| this->_lastUpdate == 0) { // Update if there was no update yet.
|
|| this->_lastUpdate == 0) { // Update if there was no update yet.
|
||||||
if (!this->_udpSetup || this->_port != NTP_DEFAULT_LOCAL_PORT) this->begin(this->_port); // setup the UDP client if needed
|
if (!this->_udpSetup || this->_port != NTP_DEFAULT_LOCAL_PORT)
|
||||||
|
this->begin(this->_port); // setup the UDP client if needed
|
||||||
return this->forceUpdate();
|
return this->forceUpdate();
|
||||||
}
|
}
|
||||||
return false; // return false if update does not occur
|
return false; // return false if update does not occur
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long NTPClient::getEpochTime() const {
|
unsigned long NTPClient::getEpochTime() const {
|
||||||
return this->_timeOffset + // User offset
|
return this->_timeOffset + // User offset
|
||||||
this->_currentEpoc + // Epoc returned by the NTP server
|
this->_currentEpoc + // Epoc returned by the NTP server
|
||||||
((millis() - this->_lastUpdate) / 1000); // Time since last update
|
((millis() - this->_lastUpdate) / 1000); // Time since last update
|
||||||
}
|
}
|
||||||
|
|
||||||
int NTPClient::getDay() const {
|
int NTPClient::getDay() const {
|
||||||
return (((this->getEpochTime() / 86400L) + 4 ) % 7); //0 is Sunday
|
return (((this->getEpochTime() / 86400L) + 4) % 7); // 0 is Sunday
|
||||||
}
|
}
|
||||||
int NTPClient::getHours() const {
|
int NTPClient::getHours() const {
|
||||||
return ((this->getEpochTime() % 86400L) / 3600);
|
return ((this->getEpochTime() % 86400L) / 3600);
|
||||||
}
|
}
|
||||||
int NTPClient::getMinutes() const {
|
int NTPClient::getMinutes() const {
|
||||||
return ((this->getEpochTime() % 3600) / 60);
|
return ((this->getEpochTime() % 3600) / 60);
|
||||||
|
@ -138,15 +140,15 @@ int NTPClient::getSeconds() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
String NTPClient::getFormattedTime() const {
|
String NTPClient::getFormattedTime() const {
|
||||||
unsigned long rawTime = this->getEpochTime();
|
unsigned long rawTime = this->getEpochTime();
|
||||||
unsigned long hours = (rawTime % 86400L) / 3600;
|
unsigned long hours = (rawTime % 86400L) / 3600;
|
||||||
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);
|
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);
|
||||||
|
|
||||||
unsigned long minutes = (rawTime % 3600) / 60;
|
unsigned long minutes = (rawTime % 3600) / 60;
|
||||||
String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);
|
String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);
|
||||||
|
|
||||||
unsigned long seconds = rawTime % 60;
|
unsigned long seconds = rawTime % 60;
|
||||||
String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);
|
String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);
|
||||||
|
|
||||||
return hoursStr + ":" + minuteStr + ":" + secondStr;
|
return hoursStr + ":" + minuteStr + ":" + secondStr;
|
||||||
}
|
}
|
||||||
|
@ -158,15 +160,15 @@ void NTPClient::end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPClient::setTimeOffset(int timeOffset) {
|
void NTPClient::setTimeOffset(int timeOffset) {
|
||||||
this->_timeOffset = timeOffset;
|
this->_timeOffset = timeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPClient::setUpdateInterval(unsigned long updateInterval) {
|
void NTPClient::setUpdateInterval(unsigned long updateInterval) {
|
||||||
this->_updateInterval = updateInterval;
|
this->_updateInterval = updateInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPClient::setPoolServerName(const char* poolServerName) {
|
void NTPClient::setPoolServerName(const char *poolServerName) {
|
||||||
this->_poolServerName = poolServerName;
|
this->_poolServerName = poolServerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPClient::sendNTPPacket() {
|
void NTPClient::sendNTPPacket() {
|
||||||
|
@ -175,19 +177,19 @@ void NTPClient::sendNTPPacket() {
|
||||||
// Initialize values needed to form NTP request
|
// Initialize values needed to form NTP request
|
||||||
// (see URL above for details on the packets)
|
// (see URL above for details on the packets)
|
||||||
|
|
||||||
this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
||||||
this->_packetBuffer[1] = 0; // Stratum, or type of clock
|
this->_packetBuffer[1] = 0; // Stratum, or type of clock
|
||||||
this->_packetBuffer[2] = 6; // Polling Interval
|
this->_packetBuffer[2] = 6; // Polling Interval
|
||||||
this->_packetBuffer[3] = 0xEC; // Peer Clock Precision
|
this->_packetBuffer[3] = 0xEC; // Peer Clock Precision
|
||||||
// 8 bytes of zero for Root Delay & Root Dispersion
|
// 8 bytes of zero for Root Delay & Root Dispersion
|
||||||
this->_packetBuffer[12] = 49;
|
this->_packetBuffer[12] = 49;
|
||||||
this->_packetBuffer[13] = 0x4E;
|
this->_packetBuffer[13] = 0x4E;
|
||||||
this->_packetBuffer[14] = 49;
|
this->_packetBuffer[14] = 49;
|
||||||
this->_packetBuffer[15] = 52;
|
this->_packetBuffer[15] = 52;
|
||||||
|
|
||||||
// all NTP fields have been given values, now
|
// all NTP fields have been given values, now
|
||||||
// you can send a packet requesting a timestamp:
|
// you can send a packet requesting a timestamp:
|
||||||
if (this->_poolServerName) {
|
if (this->_poolServerName) {
|
||||||
this->_udp.beginPacket(this->_poolServerName, 123);
|
this->_udp.beginPacket(this->_poolServerName, 123);
|
||||||
} else {
|
} else {
|
||||||
this->_udp.beginPacket(this->_poolServerIP, 123);
|
this->_udp.beginPacket(this->_poolServerIP, 123);
|
||||||
|
@ -199,4 +201,4 @@ void NTPClient::sendNTPPacket() {
|
||||||
void NTPClient::setRandomPort(unsigned int minValue, unsigned int maxValue) {
|
void NTPClient::setRandomPort(unsigned int minValue, unsigned int maxValue) {
|
||||||
randomSeed(analogRead(0));
|
randomSeed(analogRead(0));
|
||||||
this->_port = random(minValue, maxValue);
|
this->_port = random(minValue, maxValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,104 +3,104 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
#define SEVENZYYEARS 2208988800UL
|
#define SEVENZYYEARS 2208988800UL
|
||||||
#define NTP_PACKET_SIZE 48
|
#define NTP_PACKET_SIZE 48
|
||||||
#define NTP_DEFAULT_LOCAL_PORT 1337
|
#define NTP_DEFAULT_LOCAL_PORT 1337
|
||||||
|
|
||||||
class NTPClient {
|
class NTPClient {
|
||||||
private:
|
private:
|
||||||
WiFiUDP _udp;
|
WiFiUDP _udp;
|
||||||
bool _udpSetup = false;
|
bool _udpSetup = false;
|
||||||
|
|
||||||
const char* _poolServerName = "pool.ntp.org"; // Default time server
|
const char *_poolServerName = "pool.ntp.org"; // Default time server
|
||||||
IPAddress _poolServerIP;
|
IPAddress _poolServerIP;
|
||||||
unsigned int _port = NTP_DEFAULT_LOCAL_PORT;
|
unsigned int _port = NTP_DEFAULT_LOCAL_PORT;
|
||||||
long _timeOffset = 0;
|
long _timeOffset = 0;
|
||||||
|
|
||||||
unsigned long _updateInterval = 3600000; // In ms
|
unsigned long _updateInterval = 3600000; // In ms
|
||||||
|
|
||||||
unsigned long _currentEpoc = 0; // In s
|
unsigned long _currentEpoc = 0; // In s
|
||||||
unsigned long _lastUpdate = 0; // In ms
|
unsigned long _lastUpdate = 0; // In ms
|
||||||
|
|
||||||
byte _packetBuffer[NTP_PACKET_SIZE];
|
byte _packetBuffer[NTP_PACKET_SIZE];
|
||||||
|
|
||||||
void sendNTPPacket();
|
void sendNTPPacket();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NTPClient();
|
NTPClient();
|
||||||
explicit NTPClient(long timeOffset);
|
explicit NTPClient(long timeOffset);
|
||||||
explicit NTPClient(const char* poolServerName);
|
explicit NTPClient(const char *poolServerName);
|
||||||
NTPClient(const char* poolServerName, long timeOffset);
|
NTPClient(const char *poolServerName, long timeOffset);
|
||||||
NTPClient(const char* poolServerName, long timeOffset, unsigned long updateInterval);
|
NTPClient(const char *poolServerName, long timeOffset, unsigned long updateInterval);
|
||||||
explicit NTPClient(IPAddress poolServerIP);
|
explicit NTPClient(IPAddress poolServerIP);
|
||||||
NTPClient(IPAddress poolServerIP, long timeOffset);
|
NTPClient(IPAddress poolServerIP, long timeOffset);
|
||||||
NTPClient(IPAddress poolServerIP, long timeOffset, unsigned long updateInterval);
|
NTPClient(IPAddress poolServerIP, long timeOffset, unsigned long updateInterval);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set time server name
|
* Set time server name
|
||||||
*
|
*
|
||||||
* @param poolServerName
|
* @param poolServerName
|
||||||
*/
|
*/
|
||||||
void setPoolServerName(const char* poolServerName);
|
void setPoolServerName(const char *poolServerName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set random local port
|
* Set random local port
|
||||||
*/
|
*/
|
||||||
void setRandomPort(unsigned int minValue = 49152, unsigned int maxValue = 65535);
|
void setRandomPort(unsigned int minValue = 49152, unsigned int maxValue = 65535);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the underlying UDP client with the default local port
|
* Starts the underlying UDP client with the default local port
|
||||||
*/
|
*/
|
||||||
void begin();
|
void begin();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the underlying UDP client with the specified local port
|
* Starts the underlying UDP client with the specified local port
|
||||||
*/
|
*/
|
||||||
void begin(unsigned int port);
|
void begin(unsigned int port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should be called in the main loop of your application. By default an update from the NTP Server is only
|
* This should be called in the main loop of your application. By default an update from the NTP Server is only
|
||||||
* made every 60 seconds. This can be configured in the NTPClient constructor.
|
* made every 60 seconds. This can be configured in the NTPClient constructor.
|
||||||
*
|
*
|
||||||
* @return true on success, false on failure
|
* @return true on success, false on failure
|
||||||
*/
|
*/
|
||||||
bool update();
|
bool update();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will force the update from the NTP Server.
|
* This will force the update from the NTP Server.
|
||||||
*
|
*
|
||||||
* @return true on success, false on failure
|
* @return true on success, false on failure
|
||||||
*/
|
*/
|
||||||
bool forceUpdate();
|
bool forceUpdate();
|
||||||
|
|
||||||
int getDay() const;
|
int getDay() const;
|
||||||
int getHours() const;
|
int getHours() const;
|
||||||
int getMinutes() const;
|
int getMinutes() const;
|
||||||
int getSeconds() const;
|
int getSeconds() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the time offset. Useful for changing timezones dynamically
|
* Changes the time offset. Useful for changing timezones dynamically
|
||||||
*/
|
*/
|
||||||
void setTimeOffset(int timeOffset);
|
void setTimeOffset(int timeOffset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the update interval to another frequency. E.g. useful when the
|
* Set the update interval to another frequency. E.g. useful when the
|
||||||
* timeOffset should not be set in the constructor
|
* timeOffset should not be set in the constructor
|
||||||
*/
|
*/
|
||||||
void setUpdateInterval(unsigned long updateInterval);
|
void setUpdateInterval(unsigned long updateInterval);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return time formatted like `hh:mm:ss`
|
* @return time formatted like `hh:mm:ss`
|
||||||
*/
|
*/
|
||||||
String getFormattedTime() const;
|
String getFormattedTime() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return time in seconds since Jan. 1, 1970
|
* @return time in seconds since Jan. 1, 1970
|
||||||
*/
|
*/
|
||||||
unsigned long getEpochTime() const;
|
unsigned long getEpochTime() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the underlying UDP client
|
* Stops the underlying UDP client
|
||||||
*/
|
*/
|
||||||
void end();
|
void end();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,329 +1,326 @@
|
||||||
/*
|
/*
|
||||||
time.c - low level time and date functions
|
time.c - low level time and date functions
|
||||||
Copyright (c) Michael Margolis 2009-2014
|
Copyright (c) Michael Margolis 2009-2014
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
1.0 6 Jan 2010 - initial release
|
1.0 6 Jan 2010 - initial release
|
||||||
1.1 12 Feb 2010 - fixed leap year calculation error
|
1.1 12 Feb 2010 - fixed leap year calculation error
|
||||||
1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this)
|
1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this)
|
||||||
1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update
|
1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update
|
||||||
status, updated examples for Arduino 1.0, fixed ARM
|
status, updated examples for Arduino 1.0, fixed ARM
|
||||||
compatibility issues, added TimeArduinoDue and TimeTeensy3
|
compatibility issues, added TimeArduinoDue and TimeTeensy3
|
||||||
examples, add error checking and messages to RTC examples,
|
examples, add error checking and messages to RTC examples,
|
||||||
add examples to DS1307RTC library.
|
add examples to DS1307RTC library.
|
||||||
1.4 5 Sep 2014 - compatibility with Arduino 1.5.7
|
1.4 5 Sep 2014 - compatibility with Arduino 1.5.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "TimeLib.h"
|
#include "TimeLib.h"
|
||||||
|
|
||||||
static tmElements_t tm; // a cache of time elements
|
static tmElements_t tm; // a cache of time elements
|
||||||
static time_t cacheTime; // the time the cache was updated
|
static time_t cacheTime; // the time the cache was updated
|
||||||
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
|
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
|
||||||
|
|
||||||
void refreshCache(time_t t) {
|
void refreshCache(time_t t) {
|
||||||
if (t != cacheTime) {
|
if (t != cacheTime) {
|
||||||
breakTime(t, tm);
|
breakTime(t, tm);
|
||||||
cacheTime = t;
|
cacheTime = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hour() { // the hour now
|
int hour() { // the hour now
|
||||||
return hour(now());
|
return hour(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int hour(time_t t) { // the hour for the given time
|
int hour(time_t t) { // the hour for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Hour;
|
return tm.Hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hourFormat12() { // the hour now in 12 hour format
|
int hourFormat12() { // the hour now in 12 hour format
|
||||||
return hourFormat12(now());
|
return hourFormat12(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
|
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
if( tm.Hour == 0 )
|
if (tm.Hour == 0)
|
||||||
return 12; // 12 midnight
|
return 12; // 12 midnight
|
||||||
else if( tm.Hour > 12)
|
else if (tm.Hour > 12)
|
||||||
return tm.Hour - 12 ;
|
return tm.Hour - 12;
|
||||||
else
|
else
|
||||||
return tm.Hour ;
|
return tm.Hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isAM() { // returns true if time now is AM
|
uint8_t isAM() { // returns true if time now is AM
|
||||||
return !isPM(now());
|
return !isPM(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isAM(time_t t) { // returns true if given time is AM
|
uint8_t isAM(time_t t) { // returns true if given time is AM
|
||||||
return !isPM(t);
|
return !isPM(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isPM() { // returns true if PM
|
uint8_t isPM() { // returns true if PM
|
||||||
return isPM(now());
|
return isPM(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isPM(time_t t) { // returns true if PM
|
uint8_t isPM(time_t t) { // returns true if PM
|
||||||
return (hour(t) >= 12);
|
return (hour(t) >= 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
int minute() {
|
int minute() {
|
||||||
return minute(now());
|
return minute(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int minute(time_t t) { // the minute for the given time
|
int minute(time_t t) { // the minute for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Minute;
|
return tm.Minute;
|
||||||
}
|
}
|
||||||
|
|
||||||
int second() {
|
int second() {
|
||||||
return second(now());
|
return second(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int second(time_t t) { // the second for the given time
|
int second(time_t t) { // the second for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Second;
|
return tm.Second;
|
||||||
}
|
}
|
||||||
|
|
||||||
int day(){
|
int day() {
|
||||||
return(day(now()));
|
return (day(now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int day(time_t t) { // the day for the given time (0-6)
|
int day(time_t t) { // the day for the given time (0-6)
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Day;
|
return tm.Day;
|
||||||
}
|
}
|
||||||
|
|
||||||
int weekday() { // Sunday is day 1
|
int weekday() { // Sunday is day 1
|
||||||
return weekday(now());
|
return weekday(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int weekday(time_t t) {
|
int weekday(time_t t) {
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Wday;
|
return tm.Wday;
|
||||||
}
|
|
||||||
|
|
||||||
int month(){
|
|
||||||
return month(now());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int month(time_t t) { // the month for the given time
|
int month() {
|
||||||
refreshCache(t);
|
return month(now());
|
||||||
return tm.Month;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
|
int month(time_t t) { // the month for the given time
|
||||||
return year(now());
|
refreshCache(t);
|
||||||
|
return tm.Month;
|
||||||
|
}
|
||||||
|
|
||||||
|
int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
|
||||||
|
return year(now());
|
||||||
}
|
}
|
||||||
|
|
||||||
int year(time_t t) { // the year for the given time
|
int year(time_t t) { // the year for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tmYearToCalendar(tm.Year);
|
return tmYearToCalendar(tm.Year);
|
||||||
}
|
}
|
||||||
|
|
||||||
const String timeString()
|
const String timeString() {
|
||||||
{
|
return timeString(now());
|
||||||
return timeString(now());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const String timeString(time_t t)
|
const String timeString(time_t t) {
|
||||||
{
|
char line[30];
|
||||||
char line[30];
|
sprintf(line, "%02d:%02d:%02d", hour(t), minute(t), second(t));
|
||||||
sprintf(line, "%02d:%02d:%02d", hour(t), minute(t), second(t));
|
return String(line);
|
||||||
return String(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
/* functions to convert to and from system time */
|
/* functions to convert to and from system time */
|
||||||
/* These are for interfacing with time services and are not normally needed in a sketch */
|
/* These are for interfacing with time services and are not normally needed in a sketch */
|
||||||
|
|
||||||
// leap year calculator expects year argument as years offset from 1970
|
// leap year calculator expects year argument as years offset from 1970
|
||||||
#define LEAP_YEAR(Y) ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) )
|
#define LEAP_YEAR(Y) (((1970 + (Y)) > 0) && !((1970 + (Y)) % 4) && (((1970 + (Y)) % 100) || !((1970 + (Y)) % 400)))
|
||||||
|
|
||||||
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
|
static const uint8_t monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // API starts months from 1, this array starts from 0
|
||||||
|
|
||||||
void breakTime(time_t timeInput, tmElements_t &tm){
|
|
||||||
// break the given time_t into time components
|
|
||||||
// this is a more compact version of the C library localtime function
|
|
||||||
// note that year is offset from 1970 !!!
|
|
||||||
|
|
||||||
uint8_t year;
|
void breakTime(time_t timeInput, tmElements_t &tm) {
|
||||||
uint8_t month, monthLength;
|
// break the given time_t into time components
|
||||||
uint32_t time;
|
// this is a more compact version of the C library localtime function
|
||||||
unsigned long days;
|
// note that year is offset from 1970 !!!
|
||||||
|
|
||||||
time = (uint32_t)timeInput;
|
uint8_t year;
|
||||||
tm.Second = time % 60;
|
uint8_t month, monthLength;
|
||||||
time /= 60; // now it is minutes
|
uint32_t time;
|
||||||
tm.Minute = time % 60;
|
unsigned long days;
|
||||||
time /= 60; // now it is hours
|
|
||||||
tm.Hour = time % 24;
|
time = (uint32_t)timeInput;
|
||||||
time /= 24; // now it is days
|
tm.Second = time % 60;
|
||||||
tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
|
time /= 60; // now it is minutes
|
||||||
|
tm.Minute = time % 60;
|
||||||
year = 0;
|
time /= 60; // now it is hours
|
||||||
days = 0;
|
tm.Hour = time % 24;
|
||||||
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
|
time /= 24; // now it is days
|
||||||
year++;
|
tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
|
||||||
}
|
|
||||||
tm.Year = year; // year is offset from 1970
|
year = 0;
|
||||||
|
days = 0;
|
||||||
days -= LEAP_YEAR(year) ? 366 : 365;
|
while ((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
|
||||||
time -= days; // now it is days in this year, starting at 0
|
year++;
|
||||||
|
}
|
||||||
days=0;
|
tm.Year = year; // year is offset from 1970
|
||||||
month=0;
|
|
||||||
monthLength=0;
|
days -= LEAP_YEAR(year) ? 366 : 365;
|
||||||
for (month=0; month<12; month++) {
|
time -= days; // now it is days in this year, starting at 0
|
||||||
if (month==1) { // february
|
|
||||||
if (LEAP_YEAR(year)) {
|
days = 0;
|
||||||
monthLength=29;
|
month = 0;
|
||||||
} else {
|
monthLength = 0;
|
||||||
monthLength=28;
|
for (month = 0; month < 12; month++) {
|
||||||
}
|
if (month == 1) { // february
|
||||||
} else {
|
if (LEAP_YEAR(year)) {
|
||||||
monthLength = monthDays[month];
|
monthLength = 29;
|
||||||
}
|
} else {
|
||||||
|
monthLength = 28;
|
||||||
if (time >= monthLength) {
|
}
|
||||||
time -= monthLength;
|
} else {
|
||||||
} else {
|
monthLength = monthDays[month];
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
if (time >= monthLength) {
|
||||||
tm.Month = month + 1; // jan is month 1
|
time -= monthLength;
|
||||||
tm.Day = time + 1; // day of month
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tm.Month = month + 1; // jan is month 1
|
||||||
|
tm.Day = time + 1; // day of month
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t makeTime(const tmElements_t &tm){
|
time_t makeTime(const tmElements_t &tm) {
|
||||||
// assemble time elements into time_t
|
// assemble time elements into time_t
|
||||||
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
|
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
|
||||||
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
|
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
|
||||||
|
|
||||||
int i;
|
|
||||||
uint32_t seconds;
|
|
||||||
|
|
||||||
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
int i;
|
||||||
seconds= tm.Year*(SECS_PER_DAY * 365);
|
uint32_t seconds;
|
||||||
for (i = 0; i < tm.Year; i++) {
|
|
||||||
if (LEAP_YEAR(i)) {
|
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
||||||
seconds += SECS_PER_DAY; // add extra days for leap years
|
seconds = tm.Year * (SECS_PER_DAY * 365);
|
||||||
}
|
for (i = 0; i < tm.Year; i++) {
|
||||||
}
|
if (LEAP_YEAR(i)) {
|
||||||
|
seconds += SECS_PER_DAY; // add extra days for leap years
|
||||||
// add days for this year, months start from 1
|
}
|
||||||
for (i = 1; i < tm.Month; i++) {
|
}
|
||||||
if ( (i == 2) && LEAP_YEAR(tm.Year)) {
|
|
||||||
seconds += SECS_PER_DAY * 29;
|
// add days for this year, months start from 1
|
||||||
} else {
|
for (i = 1; i < tm.Month; i++) {
|
||||||
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
|
if ((i == 2) && LEAP_YEAR(tm.Year)) {
|
||||||
}
|
seconds += SECS_PER_DAY * 29;
|
||||||
}
|
} else {
|
||||||
seconds+= (tm.Day-1) * SECS_PER_DAY;
|
seconds += SECS_PER_DAY * monthDays[i - 1]; // monthDay array starts from 0
|
||||||
seconds+= tm.Hour * SECS_PER_HOUR;
|
}
|
||||||
seconds+= tm.Minute * SECS_PER_MIN;
|
}
|
||||||
seconds+= tm.Second;
|
seconds += (tm.Day - 1) * SECS_PER_DAY;
|
||||||
return (time_t)seconds;
|
seconds += tm.Hour * SECS_PER_HOUR;
|
||||||
|
seconds += tm.Minute * SECS_PER_MIN;
|
||||||
|
seconds += tm.Second;
|
||||||
|
return (time_t)seconds;
|
||||||
}
|
}
|
||||||
/*=====================================================*/
|
/*=====================================================*/
|
||||||
/* Low level system time functions */
|
/* Low level system time functions */
|
||||||
|
|
||||||
static uint32_t sysTime = 0;
|
static uint32_t sysTime = 0;
|
||||||
static uint32_t prevMillis = 0;
|
static uint32_t prevMillis = 0;
|
||||||
static uint32_t nextSyncTime = 0;
|
static uint32_t nextSyncTime = 0;
|
||||||
static timeStatus_t Status = timeNotSet;
|
static timeStatus_t Status = timeNotSet;
|
||||||
|
|
||||||
getExternalTime getTimePtr; // pointer to external sync function
|
getExternalTime getTimePtr; // pointer to external sync function
|
||||||
//setExternalTime setTimePtr; // not used in this version
|
// setExternalTime setTimePtr; // not used in this version
|
||||||
|
|
||||||
#ifdef TIME_DRIFT_INFO // define this to get drift data
|
#ifdef TIME_DRIFT_INFO // define this to get drift data
|
||||||
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
|
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
time_t now() {
|
time_t now() {
|
||||||
// calculate number of seconds passed since last call to now()
|
// calculate number of seconds passed since last call to now()
|
||||||
while (millis() - prevMillis >= 1000) {
|
while (millis() - prevMillis >= 1000) {
|
||||||
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
|
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
|
||||||
sysTime++;
|
sysTime++;
|
||||||
prevMillis += 1000;
|
prevMillis += 1000;
|
||||||
#ifdef TIME_DRIFT_INFO
|
#ifdef TIME_DRIFT_INFO
|
||||||
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
|
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (nextSyncTime <= sysTime) {
|
if (nextSyncTime <= sysTime) {
|
||||||
if (getTimePtr != 0) {
|
if (getTimePtr != 0) {
|
||||||
time_t t = getTimePtr();
|
time_t t = getTimePtr();
|
||||||
if (t != 0) {
|
if (t != 0) {
|
||||||
setTime(t);
|
setTime(t);
|
||||||
} else {
|
} else {
|
||||||
nextSyncTime = sysTime + syncInterval;
|
nextSyncTime = sysTime + syncInterval;
|
||||||
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
|
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (time_t)sysTime;
|
return (time_t)sysTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTime(time_t t) {
|
void setTime(time_t t) {
|
||||||
#ifdef TIME_DRIFT_INFO
|
#ifdef TIME_DRIFT_INFO
|
||||||
if(sysUnsyncedTime == 0)
|
if (sysUnsyncedTime == 0)
|
||||||
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
|
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sysTime = (uint32_t)t;
|
sysTime = (uint32_t)t;
|
||||||
nextSyncTime = (uint32_t)t + syncInterval;
|
nextSyncTime = (uint32_t)t + syncInterval;
|
||||||
Status = timeSet;
|
Status = timeSet;
|
||||||
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
|
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
void setTime(int hr, int min, int sec, int dy, int mnth, int yr) {
|
||||||
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
||||||
//it is converted to years since 1970
|
// it is converted to years since 1970
|
||||||
if( yr > 99)
|
if (yr > 99)
|
||||||
yr = yr - 1970;
|
yr = yr - 1970;
|
||||||
else
|
else
|
||||||
yr += 30;
|
yr += 30;
|
||||||
tm.Year = yr;
|
tm.Year = yr;
|
||||||
tm.Month = mnth;
|
tm.Month = mnth;
|
||||||
tm.Day = dy;
|
tm.Day = dy;
|
||||||
tm.Hour = hr;
|
tm.Hour = hr;
|
||||||
tm.Minute = min;
|
tm.Minute = min;
|
||||||
tm.Second = sec;
|
tm.Second = sec;
|
||||||
setTime(makeTime(tm));
|
setTime(makeTime(tm));
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustTime(long adjustment) {
|
void adjustTime(long adjustment) {
|
||||||
sysTime += adjustment;
|
sysTime += adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// indicates if time has been set and recently synchronized
|
// indicates if time has been set and recently synchronized
|
||||||
timeStatus_t timeStatus() {
|
timeStatus_t timeStatus() {
|
||||||
now(); // required to actually update the status
|
now(); // required to actually update the status
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSyncProvider( getExternalTime getTimeFunction){
|
void setSyncProvider(getExternalTime getTimeFunction) {
|
||||||
getTimePtr = getTimeFunction;
|
getTimePtr = getTimeFunction;
|
||||||
nextSyncTime = sysTime;
|
nextSyncTime = sysTime;
|
||||||
now(); // this will sync the clock
|
now(); // this will sync the clock
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
|
void setSyncInterval(time_t interval) { // set the number of seconds between re-sync
|
||||||
syncInterval = (uint32_t)interval;
|
syncInterval = (uint32_t)interval;
|
||||||
nextSyncTime = sysTime + syncInterval;
|
nextSyncTime = sysTime + syncInterval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,44 +5,60 @@
|
||||||
/*
|
/*
|
||||||
July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this)
|
July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this)
|
||||||
- fixed daysToTime_t macro (thanks maniacbug)
|
- fixed daysToTime_t macro (thanks maniacbug)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _Time_h
|
#ifndef _Time_h
|
||||||
#define _Time_h
|
#define _Time_h
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <inttypes.h>
|
||||||
typedef enum {timeNotSet, timeNeedsSync, timeSet
|
|
||||||
} timeStatus_t ;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
timeNotSet,
|
||||||
|
timeNeedsSync,
|
||||||
|
timeSet
|
||||||
|
} timeStatus_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
dowInvalid,
|
||||||
|
dowSunday,
|
||||||
|
dowMonday,
|
||||||
|
dowTuesday,
|
||||||
|
dowWednesday,
|
||||||
|
dowThursday,
|
||||||
|
dowFriday,
|
||||||
|
dowSaturday
|
||||||
} timeDayOfWeek_t;
|
} timeDayOfWeek_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields
|
tmSecond,
|
||||||
} tmByteFields;
|
tmMinute,
|
||||||
|
tmHour,
|
||||||
|
tmWday,
|
||||||
|
tmDay,
|
||||||
|
tmMonth,
|
||||||
|
tmYear,
|
||||||
|
tmNbrFields
|
||||||
|
} tmByteFields;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t Second;
|
uint8_t Second;
|
||||||
uint8_t Minute;
|
uint8_t Minute;
|
||||||
uint8_t Hour;
|
uint8_t Hour;
|
||||||
uint8_t Wday; // day of week, sunday is day 1
|
uint8_t Wday; // day of week, sunday is day 1
|
||||||
uint8_t Day;
|
uint8_t Day;
|
||||||
uint8_t Month;
|
uint8_t Month;
|
||||||
uint8_t Year; // offset from 1970;
|
uint8_t Year; // offset from 1970;
|
||||||
} tmElements_t, TimeElements, *tmElementsPtr_t;
|
} tmElements_t, TimeElements, *tmElementsPtr_t;
|
||||||
|
|
||||||
//convenience macros to convert to and from tm years
|
// convenience macros to convert to and from tm years
|
||||||
#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year
|
#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year
|
||||||
#define CalendarYrToTm(Y) ((Y) - 1970)
|
#define CalendarYrToTm(Y) ((Y)-1970)
|
||||||
#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000
|
#define tmYearToY2k(Y) ((Y)-30) // offset is from 2000
|
||||||
#define y2kYearToTm(Y) ((Y) + 30)
|
#define y2kYearToTm(Y) ((Y) + 30)
|
||||||
|
|
||||||
typedef time_t(*getExternalTime)();
|
|
||||||
//typedef void (*setExternalTime)(const time_t); // not used in this version
|
|
||||||
|
|
||||||
|
typedef time_t (*getExternalTime)();
|
||||||
|
// typedef void (*setExternalTime)(const time_t); // not used in this version
|
||||||
|
|
||||||
/*==============================================================================*/
|
/*==============================================================================*/
|
||||||
/* Useful Constants */
|
/* Useful Constants */
|
||||||
|
@ -52,76 +68,74 @@ typedef time_t(*getExternalTime)();
|
||||||
#define DAYS_PER_WEEK ((time_t)(7UL))
|
#define DAYS_PER_WEEK ((time_t)(7UL))
|
||||||
#define SECS_PER_WEEK ((time_t)(SECS_PER_DAY * DAYS_PER_WEEK))
|
#define SECS_PER_WEEK ((time_t)(SECS_PER_DAY * DAYS_PER_WEEK))
|
||||||
#define SECS_PER_YEAR ((time_t)(SECS_PER_DAY * 365UL)) // TODO: ought to handle leap years
|
#define SECS_PER_YEAR ((time_t)(SECS_PER_DAY * 365UL)) // TODO: ought to handle leap years
|
||||||
#define SECS_YR_2000 ((time_t)(946684800UL)) // the time at the start of y2k
|
#define SECS_YR_2000 ((time_t)(946684800UL)) // the time at the start of y2k
|
||||||
|
|
||||||
/* Useful Macros for getting elapsed time */
|
/* Useful Macros for getting elapsed time */
|
||||||
#define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN)
|
#define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN)
|
||||||
#define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN)
|
#define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN)
|
||||||
#define numberOfHours(_time_) (((_time_) % SECS_PER_DAY) / SECS_PER_HOUR)
|
#define numberOfHours(_time_) (((_time_) % SECS_PER_DAY) / SECS_PER_HOUR)
|
||||||
#define dayOfWeek(_time_) ((((_time_) / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday
|
#define dayOfWeek(_time_) ((((_time_) / SECS_PER_DAY + 4) % DAYS_PER_WEEK) + 1) // 1 = Sunday
|
||||||
#define elapsedDays(_time_) ((_time_) / SECS_PER_DAY) // this is number of days since Jan 1 1970
|
#define elapsedDays(_time_) ((_time_) / SECS_PER_DAY) // this is number of days since Jan 1 1970
|
||||||
#define elapsedSecsToday(_time_) ((_time_) % SECS_PER_DAY) // the number of seconds since last midnight
|
#define elapsedSecsToday(_time_) ((_time_) % SECS_PER_DAY) // the number of seconds since last midnight
|
||||||
// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
|
// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
|
||||||
// Always set the correct time before setting alarms
|
// Always set the correct time before setting alarms
|
||||||
#define previousMidnight(_time_) (((_time_) / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day
|
#define previousMidnight(_time_) (((_time_) / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day
|
||||||
#define nextMidnight(_time_) (previousMidnight(_time_) + SECS_PER_DAY) // time at the end of the given day
|
#define nextMidnight(_time_) (previousMidnight(_time_) + SECS_PER_DAY) // time at the end of the given day
|
||||||
#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY)) // note that week starts on day 1
|
#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_) - 1) * SECS_PER_DAY)) // note that week starts on day 1
|
||||||
#define previousSunday(_time_) ((_time_) - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time
|
#define previousSunday(_time_) ((_time_)-elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time
|
||||||
#define nextSunday(_time_) (previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time
|
#define nextSunday(_time_) (previousSunday(_time_) + SECS_PER_WEEK) // time at the end of the week for the given time
|
||||||
|
|
||||||
|
|
||||||
/* Useful Macros for converting elapsed time to a time_t */
|
/* Useful Macros for converting elapsed time to a time_t */
|
||||||
#define minutesToTime_t(M) ((M) * SECS_PER_MIN)
|
#define minutesToTime_t(M) ((M)*SECS_PER_MIN)
|
||||||
#define hoursToTime_t(H) ((H) * SECS_PER_HOUR)
|
#define hoursToTime_t(H) ((H)*SECS_PER_HOUR)
|
||||||
#define daysToTime_t(D) ((D) * SECS_PER_DAY) // fixed on Jul 22 2011
|
#define daysToTime_t(D) ((D)*SECS_PER_DAY) // fixed on Jul 22 2011
|
||||||
#define weeksToTime_t(W) ((W) * SECS_PER_WEEK)
|
#define weeksToTime_t(W) ((W)*SECS_PER_WEEK)
|
||||||
|
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
/* time and date functions */
|
/* time and date functions */
|
||||||
int hour(); // the hour now
|
int hour(); // the hour now
|
||||||
int hour(time_t t); // the hour for the given time
|
int hour(time_t t); // the hour for the given time
|
||||||
int hourFormat12(); // the hour now in 12 hour format
|
int hourFormat12(); // the hour now in 12 hour format
|
||||||
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
|
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
|
||||||
uint8_t isAM(); // returns true if time now is AM
|
uint8_t isAM(); // returns true if time now is AM
|
||||||
uint8_t isAM(time_t t); // returns true the given time is AM
|
uint8_t isAM(time_t t); // returns true the given time is AM
|
||||||
uint8_t isPM(); // returns true if time now is PM
|
uint8_t isPM(); // returns true if time now is PM
|
||||||
uint8_t isPM(time_t t); // returns true the given time is PM
|
uint8_t isPM(time_t t); // returns true the given time is PM
|
||||||
int minute(); // the minute now
|
int minute(); // the minute now
|
||||||
int minute(time_t t); // the minute for the given time
|
int minute(time_t t); // the minute for the given time
|
||||||
int second(); // the second now
|
int second(); // the second now
|
||||||
int second(time_t t); // the second for the given time
|
int second(time_t t); // the second for the given time
|
||||||
int day(); // the day now
|
int day(); // the day now
|
||||||
int day(time_t t); // the day for the given time
|
int day(time_t t); // the day for the given time
|
||||||
int weekday(); // the weekday now (Sunday is day 1)
|
int weekday(); // the weekday now (Sunday is day 1)
|
||||||
int weekday(time_t t); // the weekday for the given time
|
int weekday(time_t t); // the weekday for the given time
|
||||||
int month(); // the month now (Jan is month 1)
|
int month(); // the month now (Jan is month 1)
|
||||||
int month(time_t t); // the month for the given time
|
int month(time_t t); // the month for the given time
|
||||||
int year(); // the full four digit year: (2009, 2010 etc)
|
int year(); // the full four digit year: (2009, 2010 etc)
|
||||||
int year(time_t t); // the year for the given time
|
int year(time_t t); // the year for the given time
|
||||||
|
|
||||||
const String timeString();
|
const String timeString();
|
||||||
const String timeString(time_t t);
|
const String timeString(time_t t);
|
||||||
|
|
||||||
time_t now(); // return the current time as seconds since Jan 1 1970
|
time_t now(); // return the current time as seconds since Jan 1 1970
|
||||||
void setTime(time_t t);
|
void setTime(time_t t);
|
||||||
void setTime(int hr,int min,int sec,int day, int month, int yr);
|
void setTime(int hr, int min, int sec, int day, int month, int yr);
|
||||||
void adjustTime(long adjustment);
|
void adjustTime(long adjustment);
|
||||||
|
|
||||||
/* date strings */
|
/* date strings */
|
||||||
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
||||||
const String monthStr(uint8_t month);
|
const String monthStr(uint8_t month);
|
||||||
const String dayStr(uint8_t day);
|
const String dayStr(uint8_t day);
|
||||||
const String monthShortStr(uint8_t month);
|
const String monthShortStr(uint8_t month);
|
||||||
const String dayShortStr(uint8_t day);
|
const String dayShortStr(uint8_t day);
|
||||||
|
|
||||||
/* time sync functions */
|
/* time sync functions */
|
||||||
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
|
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
|
||||||
void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
|
void setSyncProvider(getExternalTime getTimeFunction); // identify the external time provider
|
||||||
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
|
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
|
||||||
|
|
||||||
/* low level functions to convert to and from system time */
|
/* low level functions to convert to and from system time */
|
||||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||||
time_t makeTime(const tmElements_t &tm); // convert time elements into time_t
|
time_t makeTime(const tmElements_t &tm); // convert time elements into time_t
|
||||||
|
|
||||||
#endif /* _Time_h */
|
#endif /* _Time_h */
|
||||||
|
|
||||||
|
|
|
@ -4,53 +4,34 @@
|
||||||
* Updated for Arduino 1.5.7 18 July 2014
|
* Updated for Arduino 1.5.7 18 July 2014
|
||||||
*
|
*
|
||||||
* No memory is consumed in the sketch if your code does not call any of the string methods
|
* No memory is consumed in the sketch if your code does not call any of the string methods
|
||||||
* You can change the text of the strings, make sure the short strings are each exactly 3 characters
|
* You can change the text of the strings, make sure the short strings are each exactly 3 characters
|
||||||
* the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in TimeLib.h
|
* the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in TimeLib.h
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "TimeLib.h"
|
#include "TimeLib.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
const String monthNames[] =
|
const String monthNames[] = {"Error", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
||||||
{
|
|
||||||
"Error", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
|
|
||||||
};
|
|
||||||
|
|
||||||
const String monthStr(uint8_t month)
|
const String monthStr(uint8_t month) {
|
||||||
{
|
return monthNames[month];
|
||||||
return monthNames[month];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const String monthShortNames[] = {"Err", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
|
|
||||||
const String monthShortNames[] =
|
const String monthShortStr(uint8_t month) {
|
||||||
{
|
return monthShortNames[month];
|
||||||
"Err", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
||||||
};
|
|
||||||
|
|
||||||
const String monthShortStr(uint8_t month)
|
|
||||||
{
|
|
||||||
return monthShortNames[month];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const String dayNames[] = {"Err", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
|
||||||
|
|
||||||
const String dayNames[] =
|
const String dayStr(uint8_t day) {
|
||||||
{
|
return dayNames[day];
|
||||||
"Err", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
|
||||||
};
|
|
||||||
|
|
||||||
const String dayStr(uint8_t day)
|
|
||||||
{
|
|
||||||
return dayNames[day];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const String dayShortNames[] = {"Err", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||||
|
|
||||||
const String dayShortNames[] =
|
const String dayShortStr(uint8_t day) {
|
||||||
{
|
return dayShortNames[day];
|
||||||
"Err", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
|
||||||
};
|
|
||||||
|
|
||||||
const String dayShortStr(uint8_t day)
|
|
||||||
{
|
|
||||||
return dayShortNames[day];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,9 @@ lib_deps =
|
||||||
jgromes/RadioLib @ 5.7.0
|
jgromes/RadioLib @ 5.7.0
|
||||||
check_tool = cppcheck
|
check_tool = cppcheck
|
||||||
check_flags =
|
check_flags =
|
||||||
cppcheck: --suppress=*:*.pio\* --inline-suppr -DCPPCHECK --force lib -ilib/TimeLib -ilib/LoRa -ilib/NTPClient
|
cppcheck: --std=c++14 --suppress=*:*.pio\* --inline-suppr --suppress=unusedFunction -DCPPCHECK --force lib -ilib/TimeLib
|
||||||
check_skip_packages = yes
|
check_skip_packages = yes
|
||||||
test_build_src = yes
|
test_build_src = yes
|
||||||
#monitor_flags = --raw
|
|
||||||
# activate for OTA Update, use the CALLSIGN from is-cfg.json as upload_port:
|
# activate for OTA Update, use the CALLSIGN from is-cfg.json as upload_port:
|
||||||
#upload_protocol = espota
|
#upload_protocol = espota
|
||||||
#upload_port = <CALLSIGN>.local
|
#upload_port = <CALLSIGN>.local
|
||||||
|
@ -35,4 +34,4 @@ build_flags = -Werror -Wall -DUNITY_INCLUDE_PRINT_FORMATTED
|
||||||
board = esp32doit-devkit-v1
|
board = esp32doit-devkit-v1
|
||||||
build_flags = -Werror -Wall -DCORE_DEBUG_LEVEL=5 -DUNITY_INCLUDE_PRINT_FORMATTED
|
build_flags = -Werror -Wall -DCORE_DEBUG_LEVEL=5 -DUNITY_INCLUDE_PRINT_FORMATTED
|
||||||
build_type = debug
|
build_type = debug
|
||||||
monitor_filters = esp32_exception_decoder
|
#monitor_filters = esp32_exception_decoder
|
||||||
|
|
|
@ -37,7 +37,7 @@ System LoRaSystem;
|
||||||
Configuration userConfig;
|
Configuration userConfig;
|
||||||
|
|
||||||
DisplayTask displayTask;
|
DisplayTask displayTask;
|
||||||
// ModemTask modemTask(fromModem, toModem);
|
// ModemTask modemTask(fromModem, toModem);
|
||||||
RadiolibTask modemTask(fromModem, toModem);
|
RadiolibTask modemTask(fromModem, toModem);
|
||||||
EthTask ethTask;
|
EthTask ethTask;
|
||||||
WifiTask wifiTask;
|
WifiTask wifiTask;
|
||||||
|
|
Ładowanie…
Reference in New Issue