A time interface class. This class replicates the normal time functions, but goes a couple of steps further. mbed library 82 and prior has a defective gmtime function. Also, this class enables access to setting the time, and adjusting the accuracy of the RTC.

Dependencies:   CalendarPage

Dependents:   CI-data-logger-server WattEye X10Svr SSDP_Server

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sun Jan 12 19:04:47 2020 +0000
Parent:
26:9ee3fac64626
Child:
28:3fa154ab6ffd
Commit message:
Update working to code-align the OS2 and OS5 variant for the time query.

Changed in this revision

NTPClient/NTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/NTPClient/NTPClient.cpp	Mon Jan 14 03:17:30 2019 +0000
+++ b/NTPClient/NTPClient.cpp	Sun Jan 12 19:04:47 2020 +0000
@@ -87,10 +87,11 @@
     INFO("Time is currently (UTC): %s", ctime(&ctTime));
 #endif
 
+#if MBED_MAJOR_VERSION == 5
+
     //
     // MBED OS 5
     //
-#if MBED_MAJOR_VERSION == 5
 
     struct NTPPacket pkt;
 
@@ -120,42 +121,38 @@
     pkt.refTm_s = 0;
     pkt.origTm_s = 0;
     pkt.rxTm_s = 0;
-    pkt.txTm_s = NTP_TIMESTAMP_DELTA + tQueryTime;
+    pkt.txTm_s = NTP_TIMESTAMP_DELTA + tQueryTime; //WARN: We are in LE format, network byte order is BE
     pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
-    
-    INFO("      ctime:         %s", ctime(&tQueryTime));
+    HexDump("NTP Post", (uint8_t *)&pkt, sizeof(NTPPacket));
+    pkt.txTm_s = htonl(pkt.txTm_s);
 
-    //WARN: We are in LE format, network byte order is BE
-    INFO("  pkt.txTm_s         %08X, %u, time to send to server", pkt.txTm_s, pkt.txTm_s);
-    pkt.txTm_s = htonl(pkt.txTm_s);
-    INFO("  pkt.txTm_s         %08X, %u, time to send to server", pkt.txTm_s, pkt.txTm_s);
-    HexDump("sending", &pkt, sizeof(NTPPacket));
-
+    // Contact the server
     UDPSocket sock;
     nsapi_error_t ret = sock.open(net);
     INFO("sock.open(...) returned %d", ret);
-    
-    sock.set_timeout(timeout);
+    sock.set_timeout(timeout);   //Set timeout, non-blocking and wait using select
 
+    // Send the query
     int ret_send = sock.sendto(nist, (void *)&pkt, sizeof(NTPPacket));
     INFO("sock.sendto(...) returned %d", ret_send);
     
     SocketAddress source;
+    
+    // Set the inEndpoint address property
     source.set_ip_address(nist.get_ip_address());
     const int n = sock.recvfrom(&source, (void *)&pkt, sizeof(NTPPacket));
     uint32_t destTimeStamp = NTP_TIMESTAMP_DELTA + time(NULL);
     INFO("recvfrom(...) returned %d", n);
-    
+
     if (pkt.stratum == 0) { //Kiss of death message : Not good !
         ERR("Kissed to death!");
-        m_sock.close();
+        sock.close();
         return NTP_PRTCL;
     }
-    
-    HexDump("received", &pkt, sizeof(NTPPacket));
-    
+
+    HexDump("NTP Info", (uint8_t *)&pkt, sizeof(NTPPacket));
+
     //Correct Endianness
-    #if 1
     pkt.refTm_s = ntohl( pkt.refTm_s );
     pkt.refTm_f = ntohl( pkt.refTm_f );
     pkt.origTm_s = ntohl( pkt.origTm_s );
@@ -164,7 +161,6 @@
     pkt.rxTm_f = ntohl( pkt.rxTm_f );
     pkt.txTm_s = ntohl( pkt.txTm_s );
     pkt.txTm_f = ntohl( pkt.txTm_f );
-    #endif
 
     #ifdef DEBUG
     const char *ModeList[] = {
@@ -191,28 +187,13 @@
     INFO("sock.close() returned %d", ret);
 
     if (n == sizeof(NTPPacket)) {
-        int64_t t;
-        #ifdef DEBUG
-        uint32_t T1, T2, T3, T4;
-        T1 = pkt.origTm_s;
-        T2 = pkt.rxTm_s;
-        T3 = pkt.txTm_s;
-        T4 = destTimeStamp;
-
-        uint32_t d = (T4 - T1) - (T3 - T2);
-        INFO("d = %d = (%d - %d) - (%d - %d)", d, T4,T1,T3,T2);
-        INFO("d = %d = (  %d   )    -     (  %d  )", d, (T4-T1), (T3-T2));
-        t = ((T2 - T1) + (T3 - T4))/2;
-        INFO("t = %lld = ((%d - %d) + (%d - %d)) / 2;", t, T2,T1,T3,T4);
-        INFO("t = %lld = ((   %d   )  +  (   %d   )) / 2", t, (T2-T1), (T3-T4));
-        #endif
 
         // Modification by David Smart
         // The setTime function was computing the offset incorrectly as the value was promoted to 64-bit.
         // The side effect was that a negative offset ended up as a very large positive (e.g. jump from 
         // 2016 to 2084). This change revises that computation.
-        t = (((int64_t)pkt.rxTm_s - pkt.origTm_s) + ((int64_t)pkt.txTm_s - destTimeStamp))/2;
-        set_time( time(NULL) + t );
+        int64_t offset = (((int64_t)pkt.rxTm_s - pkt.origTm_s) + ((int64_t)pkt.txTm_s - destTimeStamp))/2;
+        set_time( time(NULL) + offset );
     } else {
         ERR("bad return from recvfrom() %d", n);
         if (n < 0) {
@@ -226,49 +207,56 @@
 
 #else   // MBED OS 2
 
-    //Create & bind socket
-    INFO("Binding socket");
-    m_sock.bind(0); //Bind to a random port
-
     //
     // MBED OS 2
     //
-    m_sock.set_blocking(false, timeout); //Set not blocking
 
     struct NTPPacket pkt;
 
-    //Now ping the server and wait for response
-    INFO("Ping");
-    //Prepare NTP Packet:
-    pkt.li = 0; //Leap Indicator : No warning
-    pkt.vn = 4; //Version Number : 4
-    pkt.mode = 3; //Client mode
-    pkt.stratum = 0; //Not relevant here
-    pkt.poll = 0; //Not significant as well
-    pkt.precision = 0; //Neither this one is
+    Endpoint nist;
+    int ret_gethostbyname = nist.set_address(host, port);
+    INFO("gethostbyname(%s) returned %d", host, ret_gethostbyname);
+    if (ret_gethostbyname < 0) {
+        m_sock.close();
+        return NTP_DNS;     // Network error on DNS lookup
+    }
+    INFO("nist: %s:%d", nist.get_address(), nist.get_port());
+
+    //Create & bind socket
+    INFO("Binding socket");
+    m_sock.bind(0); //Bind to a random port
+    m_sock.set_blocking(false, timeout); //Set not blocking
 
-    pkt.rootDelay = 0; //Or this one
+    time_t tQueryTime = time(NULL);
+    //
+    //Prepare NTP Packet for the query:
+    //
+    pkt.li = 0;             //Leap Indicator : No warning
+    pkt.vn = 4;             //Version Number : 4
+    pkt.mode = 3;           //Client mode
+    pkt.stratum = 0;        //Not relevant here
+    pkt.poll = 0;           //Not significant as well
+    pkt.precision = 0;      //Neither this one is
+    pkt.rootDelay = 0;      //Or this one
     pkt.rootDispersion = 0; //Or that one
-    pkt.refId = 0; //...
-
+    pkt.refId = 0;          //...
     pkt.refTm_s = 0;
     pkt.origTm_s = 0;
     pkt.rxTm_s = 0;
-    pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
-    INFO("pkt.txTm_s = %u", ntohl(pkt.txTm_s) );
+    pkt.txTm_s = NTP_TIMESTAMP_DELTA + tQueryTime; //WARN: We are in LE format, network byte order is BE
     pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
-
     HexDump("NTP Post", (uint8_t *)&pkt, sizeof(NTPPacket));
-    
-    Endpoint outEndpoint;
-    INFO("outEndpoint instantiated");
-    if( outEndpoint.set_address(host, port) < 0) {
-        m_sock.close();
-        return NTP_DNS;
-    }
-    INFO("outEndpoint: %s:%d", outEndpoint.get_address(), outEndpoint.get_port());
-    //Set timeout, non-blocking and wait using select
-    int ret = m_sock.sendTo( outEndpoint, (char*)&pkt, sizeof(NTPPacket) );
+    pkt.txTm_s = htonl(pkt.txTm_s);
+
+    // Contact the server
+    // UDPSocket sock;
+    // nsapi_error_t ret = sock.open(net);
+    // INFO("sock.open(...) returned %d", ret);
+    // sock.set_timeout(timeout);   //Set timeout, non-blocking and wait using select
+
+    // Send the query
+    int ret = m_sock.sendTo(nist, (char*)&pkt, sizeof(NTPPacket));
+    INFO("m_sock.sendto(...) returned %d", ret_send);
     if (ret < 0 ) {
         ERR("Could not send packet");
         m_sock.close();
@@ -278,11 +266,10 @@
     //Read response
     Endpoint inEndpoint;
     INFO(" inEndpoint instantiated: %s.", inEndpoint.get_address());
+    
     // Set the inEndpoint address property
-    inEndpoint.set_address(outEndpoint.get_address(), 0);
-    INFO(" inEndpoint: %s", inEndpoint.get_address());
+    inEndpoint.set_address(nist.get_address(), 0);
 
-    INFO("Pong");
     int loopLimit = 20;  // semi-randomly selected so it doesn't hang forever here...
     do {
         ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) );
@@ -293,7 +280,7 @@
         }
         INFO(".");
         loopLimit--;
-    } while( strcmp(outEndpoint.get_address(), inEndpoint.get_address()) != 0 && loopLimit > 0);
+    } while( strcmp(nist.get_address(), inEndpoint.get_address()) != 0 && loopLimit > 0);
 
     if(ret < (int)sizeof(NTPPacket)) { //TODO: Accept chunks
         ERR("Receive packet size does not match");
@@ -301,7 +288,7 @@
         return NTP_PRTCL;
     }
 
-    if( pkt.stratum == 0) { //Kiss of death message : Not good !
+    if (pkt.stratum == 0) { //Kiss of death message : Not good !
         ERR("Kissed to death!");
         m_sock.close();
         return NTP_PRTCL;
@@ -319,30 +306,40 @@
     pkt.txTm_s = ntohl( pkt.txTm_s );
     pkt.txTm_f = ntohl( pkt.txTm_f );
 
+    #ifdef DEBUG
+    const char *ModeList[] = {
+        "reserved", "symmetric active", "symmetric passive", "client",
+        "server", "broadcast", "reserved for NTP ctrl", "reserved for priv use"
+    };
+    INFO("  pkt.li (Leap Ind)  %d", pkt.li);
+    INFO("  pkt.vn (Vers #)    %d", pkt.vn);
+    INFO("  pkt.mode           %d, mode %s", pkt.mode, ModeList[pkt.mode]);
+    INFO("  pkt.stratum        %d, 0=kiss-o'-death, 1=prim, 2=secd", pkt.stratum);
+    INFO("  pkt.poll           %d", pkt.poll);
+    INFO("  pkt.precision      %d", pkt.precision);
+    INFO("  pkt.rootDelay      %d", pkt.rootDelay);
+    INFO("  pkt.rootDispersion %d", pkt.rootDispersion);
+    INFO("  pkt.refId          %08X, %u", pkt.refId, pkt.refId);
+    INFO("  pkt.refTm_s        %08X, %u, ref time (last set)", pkt.refTm_s, pkt.refTm_s);
+    INFO("  pkt.origTm_s       %08X, %u, time sent from client", pkt.origTm_s, pkt.origTm_s);
+    INFO("  pkt.rxTm_s         %08X, %u, time rcvd at server", pkt.rxTm_s, pkt.rxTm_s);
+    INFO("  pkt.txTm_s         %08X, %u, time sent from server", pkt.txTm_s, pkt.txTm_s);
+    INFO("  pkt.refTm_f        %08X, %u, fraction", pkt.refTm_f, pkt.refTm_f);
+    #endif
+
     //Compute offset, see RFC 4330 p.13
     uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
-    INFO("destTm_s = %u", destTm_s);
-    INFO("pkt.txTm_s = %u", pkt.txTm_s );
-    
+
+
     // Modification by David Smart
     // The setTime function was computing the offset incorrectly as the value was promoted to 64-bit.
     // The side effect was that a negative offset ended up as a very large positive (e.g. jump from 
     // 2016 to 2084). This change revises that computation.
     int64_t offset = ( ((int64_t)pkt.rxTm_s - pkt.origTm_s ) + ((int64_t) pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
-    
-    // delay is not needed, this was for diagnostic purposes only.
-    //int64_t delay = ((int64_t) destTm_s - pkt.origTm_s) - ((int64_t) pkt.txTm_s - pkt.rxTm_s);
-    INFO("txTm_s   @%u", pkt.txTm_s);
-    INFO("origTm_s @%u", pkt.origTm_s);
-    INFO("rxTm_s   @%u", pkt.rxTm_s);
-    INFO("destTm_s @%u", destTm_s);
-    INFO("Offset: %lld", offset);
-    //INFO("Delay:  %lld", delay);
-    INFO(" time:    %u", time(NULL));
-    //Set time accordingly
     set_time( time(NULL) + offset );
 
     m_sock.close();
+
 #endif // OS version
 
     #ifdef DEBUG