test unix timestamp fix

This commit is contained in:
Aurélien Gauthier 2022-05-24 10:03:16 +02:00
parent 6105de9f97
commit e21137c10d
18 changed files with 478 additions and 149 deletions

View file

@ -39,6 +39,7 @@
#define ADC_PIN 35 #define ADC_PIN 35
#define CONV_FACTOR 1.7 #define CONV_FACTOR 1.7
#define READS 20 #define READS 20
const long gmtOffset_sec = 3600;
void setupMQTT(const char *address, int port); void setupMQTT(const char *address, int port);
void setupWIFI(const char *wifi_name, const char *password); void setupWIFI(const char *wifi_name, const char *password);

View file

@ -0,0 +1,7 @@
# See: https://github.com/codespell-project/codespell#using-a-config-file
[codespell]
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
ignore-words-list = ,
check-filenames =
check-hidden =
skip = ./.git

View file

@ -0,0 +1,10 @@
# See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file
version: 2
updates:
# Configure check for outdated GitHub Actions actions in workflows.
# See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot
- package-ecosystem: github-actions
directory: / # Check the repository's workflows under /.github/workflows/
schedule:
interval: daily

View file

@ -0,0 +1,28 @@
name: Check Arduino
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
pull_request:
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint.
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Arduino Lint
uses: arduino/arduino-lint-action@v1
with:
compliance: specification
library-manager: update
# Always use this setting for official repositories. Remove for 3rd party projects.
official: true
project-type: library

View file

@ -0,0 +1,70 @@
name: Compile Examples
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/compile-examples.yml"
- "examples/**"
- "**.c"
- "**.cpp"
- "**.h"
- "*.S"
pull_request:
paths:
- ".github/workflows/compile-examples.yml"
- "examples/**"
- "**.c"
- "**.cpp"
- "**.h"
- "*.S"
schedule:
# Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms).
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
build:
name: ${{ matrix.board.fqbn }}
runs-on: ubuntu-latest
env:
SKETCHES_REPORTS_PATH: sketches-reports
strategy:
fail-fast: false
matrix:
board:
- fqbn: esp8266:esp8266:huzzah
platforms: |
- name: esp8266:esp8266
source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Compile examples
uses: arduino/compile-sketches@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fqbn: ${{ matrix.board.fqbn }}
platforms: ${{ matrix.board.platforms }}
libraries: |
# Install the library from the local path.
- source-path: ./
# Additional library dependencies can be listed here.
# See: https://github.com/arduino/compile-sketches#libraries
sketch-paths: |
- examples
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
- name: Save sketches report as workflow artifact
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
path: ${{ env.SKETCHES_REPORTS_PATH }}
name: ${{ env.SKETCHES_REPORTS_PATH }}

View file

@ -0,0 +1,24 @@
name: Report Size Deltas
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/report-size-deltas.yml"
schedule:
# Run at the minimum interval allowed by GitHub Actions.
# Note: GitHub Actions periodically has outages which result in workflow failures.
# In this event, the workflows will start passing again once the service recovers.
- cron: "*/5 * * * *"
workflow_dispatch:
repository_dispatch:
jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Comment size deltas reports to PRs
uses: arduino/report-size-deltas@v1
with:
# The name of the workflow artifact created by the sketch compilation workflow
sketches-reports-source: sketches-reports

View file

@ -0,0 +1,22 @@
name: Spell Check
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
on:
push:
pull_request:
schedule:
# Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates.
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:
jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Spell check
uses: codespell-project/actions-codespell@master

View file

@ -0,0 +1,138 @@
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md
name: Sync Labels
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
on:
push:
paths:
- ".github/workflows/sync-labels.ya?ml"
- ".github/label-configuration-files/*.ya?ml"
pull_request:
paths:
- ".github/workflows/sync-labels.ya?ml"
- ".github/label-configuration-files/*.ya?ml"
schedule:
# Run daily at 8 AM UTC to sync with changes to shared label configurations.
- cron: "0 8 * * *"
workflow_dispatch:
repository_dispatch:
env:
CONFIGURATIONS_FOLDER: .github/label-configuration-files
CONFIGURATIONS_ARTIFACT: label-configuration-files
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Download JSON schema for labels configuration file
id: download-schema
uses: carlosperate/download-file-action@v1
with:
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
location: ${{ runner.temp }}/label-configuration-schema
- name: Install JSON schema validator
run: |
sudo npm install \
--global \
ajv-cli \
ajv-formats
- name: Validate local labels configuration
run: |
# See: https://github.com/ajv-validator/ajv-cli#readme
ajv validate \
--all-errors \
-c ajv-formats \
-s "${{ steps.download-schema.outputs.file-path }}" \
-d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}"
download:
needs: check
runs-on: ubuntu-latest
strategy:
matrix:
filename:
# Filenames of the shared configurations to apply to the repository in addition to the local configuration.
# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels
- universal.yml
steps:
- name: Download
uses: carlosperate/download-file-action@v1
with:
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
- name: Pass configuration files to next job via workflow artifact
uses: actions/upload-artifact@v3
with:
path: |
*.yaml
*.yml
if-no-files-found: error
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
sync:
needs: download
runs-on: ubuntu-latest
steps:
- name: Set environment variables
run: |
# See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV"
- name: Determine whether to dry run
id: dry-run
if: >
github.event_name == 'pull_request' ||
(
(
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch'
) &&
github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
)
run: |
# Use of this flag in the github-label-sync command will cause it to only check the validity of the
# configuration.
echo "::set-output name=flag::--dry-run"
- name: Checkout repository
uses: actions/checkout@v3
- name: Download configuration files artifact
uses: actions/download-artifact@v3
with:
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
path: ${{ env.CONFIGURATIONS_FOLDER }}
- name: Remove unneeded artifact
uses: geekyeggo/delete-artifact@v1
with:
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
- name: Merge label configuration files
run: |
# Merge all configuration files
shopt -s extglob
cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}"
- name: Install github-label-sync
run: sudo npm install --global github-label-sync
- name: Sync labels
env:
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# See: https://github.com/Financial-Times/github-label-sync
github-label-sync \
--labels "${{ env.MERGED_CONFIGURATION_PATH }}" \
${{ steps.dry-run.outputs.flag }} \
${{ github.repository }}

View file

@ -1,10 +0,0 @@
language: c
sudo: false
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
script:
- build_platform esp8266
notifications:
email:
on_success: change
on_failure: change

140
lib/NTPClient-master/NTPClient.cpp Normal file → Executable file
View file

@ -25,7 +25,7 @@ NTPClient::NTPClient(UDP& udp) {
this->_udp = &udp; this->_udp = &udp;
} }
NTPClient::NTPClient(UDP& udp, int timeOffset) { NTPClient::NTPClient(UDP& udp, long timeOffset) {
this->_udp = &udp; this->_udp = &udp;
this->_timeOffset = timeOffset; this->_timeOffset = timeOffset;
} }
@ -35,24 +35,45 @@ NTPClient::NTPClient(UDP& udp, const char* poolServerName) {
this->_poolServerName = poolServerName; this->_poolServerName = poolServerName;
} }
NTPClient::NTPClient(UDP& udp, const char* poolServerName, int timeOffset) { NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP) {
this->_udp = &udp;
this->_poolServerIP = poolServerIP;
this->_poolServerName = NULL;
}
NTPClient::NTPClient(UDP& udp, const char* poolServerName, long timeOffset) {
this->_udp = &udp; this->_udp = &udp;
this->_timeOffset = timeOffset; this->_timeOffset = timeOffset;
this->_poolServerName = poolServerName; this->_poolServerName = poolServerName;
} }
NTPClient::NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval) { NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset){
this->_udp = &udp;
this->_timeOffset = timeOffset;
this->_poolServerIP = poolServerIP;
this->_poolServerName = NULL;
}
NTPClient::NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval) {
this->_udp = &udp; this->_udp = &udp;
this->_timeOffset = timeOffset; this->_timeOffset = timeOffset;
this->_poolServerName = poolServerName; this->_poolServerName = poolServerName;
this->_updateInterval = updateInterval; this->_updateInterval = updateInterval;
} }
NTPClient::NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval) {
this->_udp = &udp;
this->_timeOffset = timeOffset;
this->_poolServerIP = poolServerIP;
this->_poolServerName = NULL;
this->_updateInterval = updateInterval;
}
void NTPClient::begin() { void NTPClient::begin() {
this->begin(NTP_DEFAULT_LOCAL_PORT); this->begin(NTP_DEFAULT_LOCAL_PORT);
} }
void NTPClient::begin(int port) { void NTPClient::begin(unsigned int port) {
this->_port = port; this->_port = port;
this->_udp->begin(this->_port); this->_udp->begin(this->_port);
@ -60,37 +81,15 @@ void NTPClient::begin(int port) {
this->_udpSetup = true; this->_udpSetup = true;
} }
bool NTPClient::isValid(byte * ntpPacket)
{
//Perform a few validity checks on the packet
if((ntpPacket[0] & 0b11000000) == 0b11000000) //Check for LI=UNSYNC
return false;
if((ntpPacket[0] & 0b00111000) >> 3 < 0b100) //Check for Version >= 4
return false;
if((ntpPacket[0] & 0b00000111) != 0b100) //Check for Mode == Server
return false;
if((ntpPacket[1] < 1) || (ntpPacket[1] > 15)) //Check for valid Stratum
return false;
if( ntpPacket[16] == 0 && ntpPacket[17] == 0 &&
ntpPacket[18] == 0 && ntpPacket[19] == 0 &&
ntpPacket[20] == 0 && ntpPacket[21] == 0 &&
ntpPacket[22] == 0 && ntpPacket[22] == 0) //Check for ReferenceTimestamp != 0
return false;
return true;
}
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...
@ -99,20 +98,14 @@ bool NTPClient::forceUpdate() {
do { do {
delay ( 10 ); delay ( 10 );
cb = this->_udp->parsePacket(); cb = this->_udp->parsePacket();
if(cb > 0)
{
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
if(!this->isValid(this->_packetBuffer))
cb = 0;
}
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);
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
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
@ -121,39 +114,43 @@ bool NTPClient::forceUpdate() {
this->_currentEpoc = secsSince1900 - SEVENZYYEARS; this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
return true; 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->begin(); // 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 true; return false; // return false if update does not occur
} }
unsigned long NTPClient::getEpochTime() { bool NTPClient::isTimeSet() const {
return (this->_lastUpdate != 0); // returns true if the time has been set, else false
}
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 + // Epoch returned by the NTP server
((millis() - this->_lastUpdate) / 1000); // Time since last update ((millis() - this->_lastUpdate) / 1000); // Time since last update
} }
int NTPClient::getDay() { 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() { int NTPClient::getHours() const {
return ((this->getEpochTime() % 86400L) / 3600); return ((this->getEpochTime() % 86400L) / 3600);
} }
int NTPClient::getMinutes() { int NTPClient::getMinutes() const {
return ((this->getEpochTime() % 3600) / 60); return ((this->getEpochTime() % 3600) / 60);
} }
int NTPClient::getSeconds() { int NTPClient::getSeconds() const {
return (this->getEpochTime() % 60); return (this->getEpochTime() % 60);
} }
String NTPClient::getFormattedTime(unsigned long secs) { String NTPClient::getFormattedTime() const {
unsigned long rawTime = secs ? secs : 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);
@ -166,33 +163,6 @@ String NTPClient::getFormattedTime(unsigned long secs) {
return hoursStr + ":" + minuteStr + ":" + secondStr; return hoursStr + ":" + minuteStr + ":" + secondStr;
} }
// Based on https://github.com/PaulStoffregen/Time/blob/master/Time.cpp
// currently assumes UTC timezone, instead of using this->_timeOffset
String NTPClient::getFormattedDate(unsigned long secs) {
unsigned long rawTime = (secs ? secs : this->getEpochTime()) / 86400L; // in days
unsigned long days = 0, year = 1970;
uint8_t month;
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31};
while((days += (LEAP_YEAR(year) ? 366 : 365)) <= rawTime)
year++;
rawTime -= days - (LEAP_YEAR(year) ? 366 : 365); // now it is days in this year, starting at 0
days=0;
for (month=0; month<12; month++) {
uint8_t monthLength;
if (month==1) { // february
monthLength = LEAP_YEAR(year) ? 29 : 28;
} else {
monthLength = monthDays[month];
}
if (rawTime < monthLength) break;
rawTime -= monthLength;
}
String monthStr = ++month < 10 ? "0" + String(month) : String(month); // jan is month 1
String dayStr = ++rawTime < 10 ? "0" + String(rawTime) : String(rawTime); // day of month
return String(year) + "-" + monthStr + "-" + dayStr + "T" + this->getFormattedTime(secs ? secs : 0) + "Z";
}
void NTPClient::end() { void NTPClient::end() {
this->_udp->stop(); this->_udp->stop();
@ -207,28 +177,36 @@ void NTPClient::setUpdateInterval(unsigned long updateInterval) {
this->_updateInterval = updateInterval; this->_updateInterval = updateInterval;
} }
void NTPClient::setPoolServerName(const char* poolServerName) {
this->_poolServerName = poolServerName;
}
void NTPClient::sendNTPPacket() { void NTPClient::sendNTPPacket() {
// set all bytes in the buffer to 0 // set all bytes in the buffer to 0
memset(this->_packetBuffer, 0, NTP_PACKET_SIZE); memset(this->_packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request // Initialize values needed to form NTP request
// (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] = 0x49; this->_packetBuffer[12] = 49;
this->_packetBuffer[13] = 0x4E; this->_packetBuffer[13] = 0x4E;
this->_packetBuffer[14] = 0x49; this->_packetBuffer[14] = 49;
this->_packetBuffer[15] = 0x52; 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:
this->_udp->beginPacket(this->_poolServerName, 123); //NTP requests are to port 123 if (this->_poolServerName) {
this->_udp->beginPacket(this->_poolServerName, 123);
} else {
this->_udp->beginPacket(this->_poolServerIP, 123);
}
this->_udp->write(this->_packetBuffer, NTP_PACKET_SIZE); this->_udp->write(this->_packetBuffer, NTP_PACKET_SIZE);
this->_udp->endPacket(); this->_udp->endPacket();
} }
void NTPClient::setEpochTime(unsigned long secs) { void NTPClient::setRandomPort(unsigned int minValue, unsigned int maxValue) {
this->_currentEpoc = secs; randomSeed(analogRead(0));
this->_port = random(minValue, maxValue);
} }

65
lib/NTPClient-master/NTPClient.h Normal file → Executable file
View file

@ -7,8 +7,6 @@
#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
#define LEAP_YEAR(Y) ( (Y>0) && !(Y%4) && ( (Y%100) || !(Y%400) ) )
class NTPClient { class NTPClient {
private: private:
@ -16,8 +14,9 @@ class NTPClient {
bool _udpSetup = false; bool _udpSetup = false;
const char* _poolServerName = "pool.ntp.org"; // Default time server const char* _poolServerName = "pool.ntp.org"; // Default time server
int _port = NTP_DEFAULT_LOCAL_PORT; IPAddress _poolServerIP;
int _timeOffset = 0; unsigned int _port = NTP_DEFAULT_LOCAL_PORT;
long _timeOffset = 0;
unsigned long _updateInterval = 60000; // In ms unsigned long _updateInterval = 60000; // In ms
@ -27,14 +26,28 @@ class NTPClient {
byte _packetBuffer[NTP_PACKET_SIZE]; byte _packetBuffer[NTP_PACKET_SIZE];
void sendNTPPacket(); void sendNTPPacket();
bool isValid(byte * ntpPacket);
public: public:
NTPClient(UDP& udp); NTPClient(UDP& udp);
NTPClient(UDP& udp, int timeOffset); NTPClient(UDP& udp, long timeOffset);
NTPClient(UDP& udp, const char* poolServerName); NTPClient(UDP& udp, const char* poolServerName);
NTPClient(UDP& udp, const char* poolServerName, int timeOffset); NTPClient(UDP& udp, const char* poolServerName, long timeOffset);
NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval); NTPClient(UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval);
NTPClient(UDP& udp, IPAddress poolServerIP);
NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset);
NTPClient(UDP& udp, IPAddress poolServerIP, long timeOffset, unsigned long updateInterval);
/**
* Set time server name
*
* @param poolServerName
*/
void setPoolServerName(const char* poolServerName);
/**
* Set random local port
*/
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
@ -44,7 +57,7 @@ class NTPClient {
/** /**
* Starts the underlying UDP client with the specified local port * Starts the underlying UDP client with the specified local port
*/ */
void begin(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
@ -61,10 +74,17 @@ class NTPClient {
*/ */
bool forceUpdate(); bool forceUpdate();
int getDay(); /**
int getHours(); * This allows to check if the NTPClient successfully received a NTP packet and set the time.
int getMinutes(); *
int getSeconds(); * @return true if time has been set, else false
*/
bool isTimeSet() const;
int getDay() const;
int getHours() const;
int getMinutes() const;
int getSeconds() const;
/** /**
* Changes the time offset. Useful for changing timezones dynamically * Changes the time offset. Useful for changing timezones dynamically
@ -78,28 +98,17 @@ class NTPClient {
void setUpdateInterval(unsigned long updateInterval); void setUpdateInterval(unsigned long updateInterval);
/** /**
* @return secs argument (or 0 for current time) formatted like `hh:mm:ss` * @return time formatted like `hh:mm:ss`
*/ */
String getFormattedTime(unsigned long secs = 0); String getFormattedTime() const;
/** /**
* @return time in seconds since Jan. 1, 1970 * @return time in seconds since Jan. 1, 1970
*/ */
unsigned long getEpochTime(); unsigned long getEpochTime() const;
/**
* @return secs argument (or 0 for current date) formatted to ISO 8601
* like `2004-02-12T15:19:21+00:00`
*/
String getFormattedDate(unsigned long secs = 0);
/** /**
* Stops the underlying UDP client * Stops the underlying UDP client
*/ */
void end(); void end();
/**
* Replace the NTP-fetched time with seconds since Jan. 1, 1970
*/
void setEpochTime(unsigned long secs);
}; };

View file

@ -1,6 +1,8 @@
# NTPClient # NTPClient
[![Build Status](https://travis-ci.org/arduino-libraries/NTPClient.svg?branch=master)](https://travis-ci.org/arduino-libraries/NTPClient) [![Check Arduino status](https://github.com/arduino-libraries/NTPClient/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/NTPClient/actions/workflows/check-arduino.yml)
[![Compile Examples status](https://github.com/arduino-libraries/NTPClient/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/NTPClient/actions/workflows/compile-examples.yml)
[![Spell Check status](https://github.com/arduino-libraries/NTPClient/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/NTPClient/actions/workflows/spell-check.yml)
Connect to a NTP server, here is how: Connect to a NTP server, here is how:
@ -22,7 +24,7 @@ WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP); NTPClient timeClient(ntpUDP);
// You can specify the time server pool and the offset, (in seconds) // You can specify the time server pool and the offset, (in seconds)
// additionaly you can specify the update interval (in milliseconds). // additionally you can specify the update interval (in milliseconds).
// NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); // NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
void setup(){ void setup(){
@ -45,3 +47,6 @@ void loop() {
delay(1000); delay(1000);
} }
``` ```
## Function documentation
`getEpochTime` returns the Unix epoch, which are the seconds elapsed since 00:00:00 UTC on 1 January 1970 (leap seconds are ignored, every day is treated as having 86400 seconds). **Attention**: If you have set a time offset this time offset will be added to your epoch timestamp.

View file

@ -11,7 +11,7 @@ const char *password = "<PASSWORD>";
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
// You can specify the time server pool and the offset (in seconds, can be // You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the // changed later with setTimeOffset() ). Additionally you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ). // update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

View file

@ -0,0 +1,53 @@
#include <NTPClient.h>
// change next line to use with another board/shield
#include <ESP8266WiFi.h>
//#include <WiFi.h> // for WiFi shield
//#include <WiFi101.h> // for WiFi 101 shield or MKR1000
#include <WiFiUdp.h>
const char *ssid = "<SSID>";
const char *password = "<PASSWORD>";
WiFiUDP ntpUDP;
// initialized to a time offset of 10 hours
NTPClient timeClient(ntpUDP,"pool.ntp.org", 36000, 60000);
// HH:MM:SS
// timeClient initializes to 10:00:00 if it does not receive an NTP packet
// before the 100ms timeout.
// without isTimeSet() the LED would be switched on, although the time
// was not yet set correctly.
// blue LED on ESP-12F
const int led = 2;
const int hour = 10;
const int minute = 0;
void setup(){
Serial.begin(115200);
pinMode(led, OUTPUT);
// led is off when pin is high
digitalWrite(led, 1);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay (500);
Serial.print (".");
}
timeClient.begin();
}
void loop() {
timeClient.update();
Serial.println(timeClient.getFormattedTime());
if(timeClient.isTimeSet()) {
if (hour == timeClient.getHours() && minute == timeClient.getMinutes()) {
digitalWrite(led, 0);
}
}
delay(1000);
}

View file

@ -12,9 +12,13 @@ begin KEYWORD2
end KEYWORD2 end KEYWORD2
update KEYWORD2 update KEYWORD2
forceUpdate KEYWORD2 forceUpdate KEYWORD2
isTimeSet KEYWORD2
getDay KEYWORD2 getDay KEYWORD2
getHours KEYWORD2 getHours KEYWORD2
getMinutes KEYWORD2 getMinutes KEYWORD2
getSeconds KEYWORD2 getSeconds KEYWORD2
getFormattedTime KEYWORD2 getFormattedTime KEYWORD2
getEpochTime KEYWORD2 getEpochTime KEYWORD2
setTimeOffset KEYWORD2
setUpdateInterval KEYWORD2
setPoolServerName KEYWORD2

View file

@ -1,24 +0,0 @@
{
"name": "NTPClient",
"keywords": "ntp, client, time",
"description": "A NTPClient to connect to a time server",
"authors":
[
{
"name": "Fabrice Weinberg",
"email": "fabrice@weinberg.me"
},
{
"name": "Sandeep Mistry",
"email": "s.mistry@arduino.cc"
}
],
"repository":
{
"type": "git",
"url": "https://github.com/arduino-libraries/NTPClient.git"
},
"version": "3.1.0",
"frameworks": "arduino",
"platforms": "espressif"
}

View file

@ -1,5 +1,5 @@
name=NTPClient name=NTPClient
version=3.1.0 version=3.2.1
author=Fabrice Weinberg author=Fabrice Weinberg
maintainer=Fabrice Weinberg <fabrice@weinberg.me> maintainer=Fabrice Weinberg <fabrice@weinberg.me>
sentence=An NTPClient to connect to a time server sentence=An NTPClient to connect to a time server

View file

@ -1,8 +1,12 @@
#include "main.h" #include "main.h"
#include "NTPClient.h"
#include <sys/time.h>
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
//extern "C" void f(int); // one way
using namespace std; using namespace std;
DHT sensors[SENSORS_NUMBER] = {DHT(04, DHT22), DHT(18, DHT22), DHT(05, DHT22), DHT(17, DHT22), DHT(16, DHT22)}; DHT sensors[SENSORS_NUMBER] = {DHT(04, DHT22), DHT(18, DHT22), DHT(05, DHT22), DHT(17, DHT22), DHT(16, DHT22)};
@ -88,13 +92,18 @@ void sleep()
//exemple d'une triple utilisation de valeur pour une fonction utilise pour la date //exemple d'une triple utilisation de valeur pour une fonction utilise pour la date
std::tuple<int, int, int> getDate() std::tuple<int, int, int> getDate()
{ {
struct timeval synctime;
TimeClient.forceUpdate();
time_t rawtime = TimeClient.getEpochTime(); time_t rawtime = TimeClient.getEpochTime();
synctime.tv_sec = rawtime;
synctime.tv_usec = 0;
if(settimeofday(&synctime,NULL) != 0) std::cout << "error\n" ;
struct tm *ti; struct tm *ti;
ti = localtime(&rawtime); ti = localtime(&rawtime);
int year = ti->tm_year + 1900; int year = ti->tm_year + 1900;
int month = (ti->tm_mon + 1) < 10 ? 0 + (ti->tm_mon + 1) : (ti->tm_mon + 1); int month = (ti->tm_mon + 1) < 10 ? 0 + (ti->tm_mon + 1) : (ti->tm_mon + 1);
int day = (ti->tm_mday) < 10 ? 0 + (ti->tm_mday) : (ti->tm_mday); int day = (ti->tm_mday) < 10 ? 0 + (ti->tm_mday) : (ti->tm_mday);
return std::make_tuple(year, month, day); return std::make_tuple(year, month, day);
} }
@ -116,6 +125,8 @@ void writeMessage(char *txt, float *temp, float *hum, int number)
int chargelvl = Battery.getBatteryChargeLevel(); int chargelvl = Battery.getBatteryChargeLevel();
//float homeValue = 3.3 * analogRead(ADC_PIN) / 2048; for test measurement //float homeValue = 3.3 * analogRead(ADC_PIN) / 2048; for test measurement
//float homeValue1 = 1.7 * analogRead(ADC_PIN) / 1000; //float homeValue1 = 1.7 * analogRead(ADC_PIN) / 1000;
time_t rawtime = TimeClient.getEpochTime();
switch (number) switch (number)
{ {
case 1: case 1:
@ -131,7 +142,7 @@ void writeMessage(char *txt, float *temp, float *hum, int number)
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], hum[0], hum[1], hum[2], hum[3]); sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], hum[0], hum[1], hum[2], hum[3]);
break; break;
case 5: case 5:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f|%d|%f|%f", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], hum[0], hum[1], hum[2], hum[3], hum[4], chargelvl, homeValue, homeValue1); sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f|%d|%lu|%lu", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], hum[0], hum[1], hum[2], hum[3], hum[4], chargelvl, getTime(), rawtime);
break; break;
case 6: case 6:
sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], hum[0], hum[1], hum[2], hum[3], hum[4], hum[5]); sprintf(txt, "|%s|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f|%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f", CLUSTER, temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], hum[0], hum[1], hum[2], hum[3], hum[4], hum[5]);
@ -151,8 +162,11 @@ void setup()
setupMQTT(MQTT_ADDRESS, MQTT_PORT); setupMQTT(MQTT_ADDRESS, MQTT_PORT);
initSensors(sensors, SENSORS_NUMBER); initSensors(sensors, SENSORS_NUMBER);
TimeClient.begin(); TimeClient.begin();
TimeClient.forceUpdate();
} }
//-------------------- Boucle principale --------------------// //-------------------- Boucle principale --------------------//
void loop() void loop()