Merge branch 'main' into 0_15
This commit is contained in:
@@ -199,6 +199,9 @@ void handleNetworkTime()
|
||||
{
|
||||
if (millis() - ntpPacketSentTime > 10000)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32 // I had problems using udp.flush() on 8266
|
||||
while (ntpUdp.parsePacket() > 0) ntpUdp.flush(); // flush any existing packets
|
||||
#endif
|
||||
sendNTPPacket();
|
||||
ntpPacketSentTime = millis();
|
||||
}
|
||||
@@ -239,16 +242,38 @@ void sendNTPPacket()
|
||||
ntpUdp.endPacket();
|
||||
}
|
||||
|
||||
static bool isValidNtpResponse(byte * ntpPacket) {
|
||||
// Perform a few validity checks on the packet
|
||||
// based on https://github.com/taranais/NTPClient/blob/master/NTPClient.cpp
|
||||
if((ntpPacket[0] & 0b11000000) == 0b11000000) return false; //reject LI=UNSYNC
|
||||
// if((ntpPacket[0] & 0b00111000) >> 3 < 0b100) return false; //reject Version < 4
|
||||
if((ntpPacket[0] & 0b00000111) != 0b100) return false; //reject Mode != Server
|
||||
if((ntpPacket[1] < 1) || (ntpPacket[1] > 15)) return false; //reject invalid Stratum
|
||||
if( ntpPacket[16] == 0 && ntpPacket[17] == 0 &&
|
||||
ntpPacket[18] == 0 && ntpPacket[19] == 0 &&
|
||||
ntpPacket[20] == 0 && ntpPacket[21] == 0 &&
|
||||
ntpPacket[22] == 0 && ntpPacket[23] == 0) //reject ReferenceTimestamp == 0
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkNTPResponse()
|
||||
{
|
||||
int cb = ntpUdp.parsePacket();
|
||||
if (!cb) return false;
|
||||
if (cb < NTP_MIN_PACKET_SIZE) {
|
||||
#ifdef ARDUINO_ARCH_ESP32 // I had problems using udp.flush() on 8266
|
||||
if (cb > 0) ntpUdp.flush(); // this avoids memory leaks on esp32
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ntpPacketReceivedTime = millis();
|
||||
DEBUG_PRINT(F("NTP recv, l="));
|
||||
DEBUG_PRINTLN(cb);
|
||||
byte pbuf[NTP_PACKET_SIZE];
|
||||
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
if (!isValidNtpResponse(pbuf)) return false; // verify we have a valid response to client
|
||||
|
||||
Toki::Time arrived = toki.fromNTP(pbuf + 32);
|
||||
Toki::Time departed = toki.fromNTP(pbuf + 40);
|
||||
@@ -422,8 +447,8 @@ void checkTimers()
|
||||
}
|
||||
|
||||
#define ZENITH -0.83
|
||||
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location
|
||||
int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
|
||||
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location. Returns >= INT16_MAX in case of "no sunset"
|
||||
static int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
|
||||
//1. first calculate the day of the year
|
||||
float N1 = 275 * month / 9;
|
||||
float N2 = (month + 9) / 12;
|
||||
@@ -457,8 +482,8 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
||||
|
||||
//7a. calculate the Sun's local hour angle
|
||||
float cosH = (sinf(DEG_TO_RAD*ZENITH) - (sinDec * sinf(DEG_TO_RAD*lat))) / (cosDec * cosf(DEG_TO_RAD*lat));
|
||||
if ((cosH > 1.0f) && !sunset) return 0; // the sun never rises on this location (on the specified date)
|
||||
if ((cosH < -1.0f) && sunset) return 0; // the sun never sets on this location (on the specified date)
|
||||
if ((cosH > 1.0f) && !sunset) return INT16_MAX; // the sun never rises on this location (on the specified date)
|
||||
if ((cosH < -1.0f) && sunset) return INT16_MAX; // the sun never sets on this location (on the specified date)
|
||||
|
||||
//7b. finish calculating H and convert into hours
|
||||
float H = sunset ? RAD_TO_DEG*acosf(cosH) : 360 - RAD_TO_DEG*acosf(cosH);
|
||||
@@ -474,6 +499,7 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
||||
return UT*60;
|
||||
}
|
||||
|
||||
#define SUNSET_MAX (24*60) // 1day = max expected absolute value for sun offset in minutes
|
||||
// calculate sunrise and sunset (if longitude and latitude are set)
|
||||
void calculateSunriseAndSunset() {
|
||||
if ((int)(longitude*10.) || (int)(latitude*10.)) {
|
||||
@@ -484,8 +510,19 @@ void calculateSunriseAndSunset() {
|
||||
tim_0.tm_sec = 0;
|
||||
tim_0.tm_isdst = 0;
|
||||
|
||||
int minUTC = getSunriseUTC(year(localTime), month(localTime), day(localTime), latitude, longitude);
|
||||
if (minUTC) {
|
||||
// Due to limited accuracy, its possible to get a bad sunrise/sunset displayed as "00:00" (see issue #3601)
|
||||
// So in case of invalid result, we try to use the sunset/sunrise of previous day. Max 3 days back, this worked well in all cases I tried.
|
||||
// When latitude = 66,6 (N or S), the functions sometimes returns 2147483647, so this "unexpected large" is another condition for retry
|
||||
int minUTC = 0;
|
||||
int retryCount = 0;
|
||||
do {
|
||||
time_t theDay = localTime - retryCount * 86400; // one day back = 86400 seconds
|
||||
minUTC = getSunriseUTC(year(theDay), month(theDay), day(theDay), latitude, longitude, false);
|
||||
DEBUG_PRINT(F("* sunrise (minutes from UTC) = ")); DEBUG_PRINTLN(minUTC);
|
||||
retryCount ++;
|
||||
} while ((abs(minUTC) > SUNSET_MAX) && (retryCount <= 3));
|
||||
|
||||
if (abs(minUTC) <= SUNSET_MAX) {
|
||||
// there is a sunrise
|
||||
if (minUTC < 0) minUTC += 24*60; // add a day if negative
|
||||
tim_0.tm_hour = minUTC / 60;
|
||||
@@ -496,8 +533,15 @@ void calculateSunriseAndSunset() {
|
||||
sunrise = 0;
|
||||
}
|
||||
|
||||
minUTC = getSunriseUTC(year(localTime), month(localTime), day(localTime), latitude, longitude, true);
|
||||
if (minUTC) {
|
||||
retryCount = 0;
|
||||
do {
|
||||
time_t theDay = localTime - retryCount * 86400; // one day back = 86400 seconds
|
||||
minUTC = getSunriseUTC(year(theDay), month(theDay), day(theDay), latitude, longitude, true);
|
||||
DEBUG_PRINT(F("* sunset (minutes from UTC) = ")); DEBUG_PRINTLN(minUTC);
|
||||
retryCount ++;
|
||||
} while ((abs(minUTC) > SUNSET_MAX) && (retryCount <= 3));
|
||||
|
||||
if (abs(minUTC) <= SUNSET_MAX) {
|
||||
// there is a sunset
|
||||
if (minUTC < 0) minUTC += 24*60; // add a day if negative
|
||||
tim_0.tm_hour = minUTC / 60;
|
||||
|
||||
Reference in New Issue
Block a user