Lightweight WIZnet W5500 NTPClient library. Includes DST and set RTC options.

Dependents:   W5500-SNTPClient-example

SNTPClient.cpp

Committer:
star297
Date:
2019-05-02
Revision:
0:f8cb34a007a4

File content as of revision 0:f8cb34a007a4:

#include "SNTPClient.h"
#include "UDPSocket.h"

#define MAX_TRY_WRITE 10
#define MAX_TRY_READ 10

SNTPClient::SNTPClient()  : socket()
{
    
}

uint32_t SNTPClient::getNTP(char * NTPpool,uint32_t tzoffset, bool dst, uint32_t setRTC)
{
    uint32_t NTP_PACKET_SIZE = 48;
    char packetBuffer[NTP_PACKET_SIZE];
    uint32_t NTP_OFFSET = 2208988800; // UTC time
    memset(packetBuffer, 0x00, NTP_PACKET_SIZE);
    // Initialize values needed to form NTP request
    packetBuffer[0]  = 0b11100011;      // LI, Version, Mode
    packetBuffer[1]  = 0;               // Stratum, or type of clock
    packetBuffer[2]  = 6;               // Polling Interval
    packetBuffer[3]  = 0xEC;            // Peer Clock Precision
    // [4]-[11]: 8 bytes of zero for Root Delay & Root Dispersion
    packetBuffer[12] = 49;
    packetBuffer[13] = 0x4E;
    packetBuffer[14] = 49;
    packetBuffer[15] = 52;    
    uint32_t recv_size = 0;
    uint32_t tries1 = MAX_TRY_WRITE;
    while ((recv_size != NTP_PACKET_SIZE) && (tries1 > 0)){
        tries1--;        
        socket.set_blocking(false, 3000);    // allow 500mS seconds to connect to remote server
        socket.init();
        socket.bind(0);        
        if(sntp_server.set_address(NTPpool, 123) < 0)
            return false; 
        socket.set_blocking(false, 200);    // check for response 200mS intervals       
        socket.sendTo(sntp_server, packetBuffer, NTP_PACKET_SIZE);       
        uint32_t tries2 = MAX_TRY_READ;
        while ((recv_size != NTP_PACKET_SIZE) && (tries2 > 0)){
            tries2--;
            wait_ms(20);
            recv_size = socket.receiveFrom(sntp_server, packetBuffer,  NTP_PACKET_SIZE);
        }
        socket.close();
    }
    if(recv_size==48){
        uint32_t secsSince1970=((packetBuffer[40]<<24)|(packetBuffer[41]<<16)|(packetBuffer[42]<<8)|packetBuffer[43])-NTP_OFFSET;
        uint32_t CETtime=(secsSince1970+(tzoffset*3600));          
            // check for DST time change, only valid for europe!!!
            // see http://www.instructables.com/id/The-Arduino-and-Daylight-Saving-Time-Europe/    
        uint32_t DST=0;
        if(dst){
            uint32_t dow,hour,day,month;             
            char buffer[10];        
            strftime(buffer, 2,"%H", localtime(&CETtime));                                
            hour = atoi(buffer);
            strftime(buffer, 2,"%w", localtime(&CETtime));                                
            dow = atoi(buffer);
            strftime(buffer, 2,"%e", localtime(&CETtime));                
            day = atoi(buffer);
            strftime(buffer, 2,"%m", localtime(&CETtime));
            month = atoi(buffer);                    
            uint32_t previousSunday = day - dow;
            if (month > 2 && month < 9){DST=3600;}            
            if (month == 2 && previousSunday >= 25 && hour >= 2){DST=3600;} // DST starts 2nd Sunday of March;  2am
            if (month == 9 && previousSunday < 25 && hour >= 2){DST=0;}     // DST ends 1st Sunday of November; 2am
        }            
        if (setRTC){set_time(CETtime+DST+1);} // todo: add timer code to addjust fractional second to offset MCU processing delay        
        return (CETtime+DST);
    }
    else{return 0;}
}