Andrew Boyson
/
iot
Backing up an unused program in case of future need
ntp.cpp@2:06fa34661f19, 2016-04-22 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Apr 22 09:23:57 2016 +0000
- Revision:
- 2:06fa34661f19
- Parent:
- 0:09f915e6f9f6
- Child:
- 4:e076884ef8bd
Added configuration file.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 0:09f915e6f9f6 | 1 | #include <mbed.h> |
andrewboyson | 0:09f915e6f9f6 | 2 | #include "log.h" |
andrewboyson | 0:09f915e6f9f6 | 3 | #include "esp.h" |
andrewboyson | 0:09f915e6f9f6 | 4 | #include "wifi.h" |
andrewboyson | 0:09f915e6f9f6 | 5 | #include "time.h" |
andrewboyson | 0:09f915e6f9f6 | 6 | #include "io.h" |
andrewboyson | 0:09f915e6f9f6 | 7 | #include "at.h" |
andrewboyson | 2:06fa34661f19 | 8 | #include "cfg.h" |
andrewboyson | 0:09f915e6f9f6 | 9 | |
andrewboyson | 0:09f915e6f9f6 | 10 | #define GET_TIME_INTERVAL 600 |
andrewboyson | 0:09f915e6f9f6 | 11 | #define RETRY_INTERVAL 60 |
andrewboyson | 0:09f915e6f9f6 | 12 | |
andrewboyson | 0:09f915e6f9f6 | 13 | #define ID 0 |
andrewboyson | 0:09f915e6f9f6 | 14 | |
andrewboyson | 0:09f915e6f9f6 | 15 | #define SIXTEENTHS_TO_ADD 1 |
andrewboyson | 0:09f915e6f9f6 | 16 | |
andrewboyson | 0:09f915e6f9f6 | 17 | Timer timer; |
andrewboyson | 0:09f915e6f9f6 | 18 | |
andrewboyson | 0:09f915e6f9f6 | 19 | struct Packet { |
andrewboyson | 0:09f915e6f9f6 | 20 | /* |
andrewboyson | 0:09f915e6f9f6 | 21 | LI: 00 no warning; 01 last minute has 61 seconds; 10 last minute has 59 seconds; 11 alarm condition (clock not synchronized) |
andrewboyson | 0:09f915e6f9f6 | 22 | VN: 3 = 011 |
andrewboyson | 0:09f915e6f9f6 | 23 | Mode: 3 = 011 for client request; 4 = 100 for server reply |
andrewboyson | 0:09f915e6f9f6 | 24 | 0 1 2 3 |
andrewboyson | 0:09f915e6f9f6 | 25 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
andrewboyson | 0:09f915e6f9f6 | 26 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
andrewboyson | 0:09f915e6f9f6 | 27 | |LI | VN |Mode | Stratum | Poll | Precision | |
andrewboyson | 0:09f915e6f9f6 | 28 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
andrewboyson | 0:09f915e6f9f6 | 29 | |0 0 0 1|1 0 1 1| |
andrewboyson | 0:09f915e6f9f6 | 30 | |
andrewboyson | 0:09f915e6f9f6 | 31 | Mode: If the Mode field of the request is 3 (client), the reply is set to 4 (server). |
andrewboyson | 0:09f915e6f9f6 | 32 | If this field is set to 1 (symmetric active), the reply is set to 2 (symmetric passive). |
andrewboyson | 0:09f915e6f9f6 | 33 | This allows clients configured in either client (NTP mode 3) or symmetric active (NTP mode 1) to |
andrewboyson | 0:09f915e6f9f6 | 34 | interoperate successfully, even if configured in possibly suboptimal ways. |
andrewboyson | 0:09f915e6f9f6 | 35 | |
andrewboyson | 0:09f915e6f9f6 | 36 | Poll: signed integer indicating the minimum interval between transmitted messages, in seconds as a power of two. |
andrewboyson | 0:09f915e6f9f6 | 37 | For instance, a value of six indicates a minimum interval of 64 seconds. |
andrewboyson | 0:09f915e6f9f6 | 38 | |
andrewboyson | 0:09f915e6f9f6 | 39 | Precision: signed integer indicating the precision of the various clocks, in seconds to the nearest power of two. |
andrewboyson | 0:09f915e6f9f6 | 40 | The value must be rounded to the next larger power of two; |
andrewboyson | 0:09f915e6f9f6 | 41 | for instance, a 50-Hz (20 ms) or 60-Hz (16.67 ms) power-frequency clock would be assigned the value -5 (31.25 ms), |
andrewboyson | 0:09f915e6f9f6 | 42 | while a 1000-Hz (1 ms) crystal-controlled clock would be assigned the value -9 (1.95 ms). |
andrewboyson | 0:09f915e6f9f6 | 43 | |
andrewboyson | 0:09f915e6f9f6 | 44 | Root Delay (rootdelay): Total round-trip delay to the reference clock, in NTP short format (16bitseconds; 16bit fraction). |
andrewboyson | 0:09f915e6f9f6 | 45 | |
andrewboyson | 0:09f915e6f9f6 | 46 | Root Dispersion (rootdisp): Total dispersion to the reference clock, in NTP short format (16bitseconds; 16bit fraction).. |
andrewboyson | 0:09f915e6f9f6 | 47 | */ |
andrewboyson | 0:09f915e6f9f6 | 48 | union |
andrewboyson | 0:09f915e6f9f6 | 49 | { |
andrewboyson | 0:09f915e6f9f6 | 50 | uint32_t FirstLine; |
andrewboyson | 0:09f915e6f9f6 | 51 | struct |
andrewboyson | 0:09f915e6f9f6 | 52 | { |
andrewboyson | 0:09f915e6f9f6 | 53 | unsigned Mode : 3; |
andrewboyson | 0:09f915e6f9f6 | 54 | unsigned VN : 3; |
andrewboyson | 0:09f915e6f9f6 | 55 | unsigned LI : 2; |
andrewboyson | 0:09f915e6f9f6 | 56 | uint8_t Stratum; |
andrewboyson | 0:09f915e6f9f6 | 57 | int8_t Poll; |
andrewboyson | 0:09f915e6f9f6 | 58 | int8_t Precision; |
andrewboyson | 0:09f915e6f9f6 | 59 | }; |
andrewboyson | 0:09f915e6f9f6 | 60 | }; |
andrewboyson | 0:09f915e6f9f6 | 61 | uint32_t RootDelay; |
andrewboyson | 0:09f915e6f9f6 | 62 | uint32_t Dispersion; |
andrewboyson | 0:09f915e6f9f6 | 63 | uint32_t RefIdentifier; |
andrewboyson | 0:09f915e6f9f6 | 64 | |
andrewboyson | 0:09f915e6f9f6 | 65 | uint64_t RefTimeStamp; |
andrewboyson | 0:09f915e6f9f6 | 66 | uint64_t OriTimeStamp; |
andrewboyson | 0:09f915e6f9f6 | 67 | uint64_t RecTimeStamp; |
andrewboyson | 0:09f915e6f9f6 | 68 | uint64_t TraTimeStamp; |
andrewboyson | 0:09f915e6f9f6 | 69 | }; |
andrewboyson | 0:09f915e6f9f6 | 70 | static struct Packet packet; |
andrewboyson | 0:09f915e6f9f6 | 71 | |
andrewboyson | 0:09f915e6f9f6 | 72 | static uint64_t ntohll(uint64_t n) { |
andrewboyson | 0:09f915e6f9f6 | 73 | int testInt = 0x0001; //Big end contains 0x00; little end contains 0x01 |
andrewboyson | 0:09f915e6f9f6 | 74 | int *pTestInt = &testInt; |
andrewboyson | 0:09f915e6f9f6 | 75 | char *pTestByte = (char*)pTestInt; |
andrewboyson | 0:09f915e6f9f6 | 76 | char testByte = *pTestByte; //fetch the first byte |
andrewboyson | 0:09f915e6f9f6 | 77 | if (testByte == 0x00) return n; //If the first byte is the big end then host and network have same endianess |
andrewboyson | 0:09f915e6f9f6 | 78 | |
andrewboyson | 0:09f915e6f9f6 | 79 | union ull |
andrewboyson | 0:09f915e6f9f6 | 80 | { |
andrewboyson | 0:09f915e6f9f6 | 81 | uint64_t Whole; |
andrewboyson | 0:09f915e6f9f6 | 82 | char Bytes[8]; |
andrewboyson | 0:09f915e6f9f6 | 83 | }; |
andrewboyson | 0:09f915e6f9f6 | 84 | union ull h; |
andrewboyson | 0:09f915e6f9f6 | 85 | h.Whole = n; |
andrewboyson | 0:09f915e6f9f6 | 86 | |
andrewboyson | 0:09f915e6f9f6 | 87 | char t; |
andrewboyson | 0:09f915e6f9f6 | 88 | t = h.Bytes[7]; h.Bytes[7] = h.Bytes[0]; h.Bytes[0] = t; |
andrewboyson | 0:09f915e6f9f6 | 89 | t = h.Bytes[6]; h.Bytes[6] = h.Bytes[1]; h.Bytes[1] = t; |
andrewboyson | 0:09f915e6f9f6 | 90 | t = h.Bytes[5]; h.Bytes[5] = h.Bytes[2]; h.Bytes[2] = t; |
andrewboyson | 0:09f915e6f9f6 | 91 | t = h.Bytes[4]; h.Bytes[4] = h.Bytes[3]; h.Bytes[3] = t; |
andrewboyson | 0:09f915e6f9f6 | 92 | |
andrewboyson | 0:09f915e6f9f6 | 93 | return h.Whole; |
andrewboyson | 0:09f915e6f9f6 | 94 | } |
andrewboyson | 0:09f915e6f9f6 | 95 | uint64_t getTimeAsNtp() |
andrewboyson | 0:09f915e6f9f6 | 96 | { |
andrewboyson | 0:09f915e6f9f6 | 97 | uint64_t ntpTime = 2208988800ULL << 32; |
andrewboyson | 0:09f915e6f9f6 | 98 | ntpTime += TimeGet16ths() << 28; |
andrewboyson | 0:09f915e6f9f6 | 99 | return ntpTime; |
andrewboyson | 0:09f915e6f9f6 | 100 | } |
andrewboyson | 0:09f915e6f9f6 | 101 | void setTimeAsNtp(uint64_t ntpTime) |
andrewboyson | 0:09f915e6f9f6 | 102 | { |
andrewboyson | 0:09f915e6f9f6 | 103 | ntpTime -= 2208988800ULL << 32; |
andrewboyson | 0:09f915e6f9f6 | 104 | uint64_t time16ths = (ntpTime >> 28) + SIXTEENTHS_TO_ADD; |
andrewboyson | 0:09f915e6f9f6 | 105 | TimeSet16ths(time16ths); |
andrewboyson | 0:09f915e6f9f6 | 106 | } |
andrewboyson | 0:09f915e6f9f6 | 107 | void NtpInit() |
andrewboyson | 0:09f915e6f9f6 | 108 | { |
andrewboyson | 0:09f915e6f9f6 | 109 | EspIpdReserved[ID] = true; |
andrewboyson | 0:09f915e6f9f6 | 110 | } |
andrewboyson | 0:09f915e6f9f6 | 111 | int preparePacket() |
andrewboyson | 0:09f915e6f9f6 | 112 | { |
andrewboyson | 0:09f915e6f9f6 | 113 | memset(&packet, 0, sizeof(packet)); |
andrewboyson | 0:09f915e6f9f6 | 114 | packet.LI = 0; |
andrewboyson | 0:09f915e6f9f6 | 115 | packet.VN = 1; |
andrewboyson | 0:09f915e6f9f6 | 116 | packet.Mode = 3; //Client |
andrewboyson | 0:09f915e6f9f6 | 117 | packet.TraTimeStamp = ntohll(getTimeAsNtp()); |
andrewboyson | 0:09f915e6f9f6 | 118 | return 0; |
andrewboyson | 0:09f915e6f9f6 | 119 | } |
andrewboyson | 0:09f915e6f9f6 | 120 | int handlePacket() |
andrewboyson | 0:09f915e6f9f6 | 121 | { |
andrewboyson | 0:09f915e6f9f6 | 122 | |
andrewboyson | 0:09f915e6f9f6 | 123 | //Handle the reply |
andrewboyson | 0:09f915e6f9f6 | 124 | char leap = packet.LI; |
andrewboyson | 0:09f915e6f9f6 | 125 | char version = packet.VN; |
andrewboyson | 0:09f915e6f9f6 | 126 | char mode = packet.Mode; |
andrewboyson | 0:09f915e6f9f6 | 127 | char stratum = packet.Stratum; |
andrewboyson | 0:09f915e6f9f6 | 128 | if (leap == 3) { LogF("Remote clock has a fault\r\n"); return -1; } |
andrewboyson | 0:09f915e6f9f6 | 129 | if (version < 1) { LogF("Version is %d\r\n", version); return -1; } |
andrewboyson | 0:09f915e6f9f6 | 130 | if (mode != 4) { LogF("Mode is %d\r\n", mode); return -1; } |
andrewboyson | 0:09f915e6f9f6 | 131 | if (stratum == 0) { LogF("Received Kiss of Death packet (stratum is 0)\r\n"); return -1; } |
andrewboyson | 0:09f915e6f9f6 | 132 | |
andrewboyson | 0:09f915e6f9f6 | 133 | /* |
andrewboyson | 0:09f915e6f9f6 | 134 | See http://www.eecis.udel.edu/~mills/time.html for timestamp calculations |
andrewboyson | 0:09f915e6f9f6 | 135 | Ori |
andrewboyson | 0:09f915e6f9f6 | 136 | ----t1---------t4---- RTC |
andrewboyson | 0:09f915e6f9f6 | 137 | \ / |
andrewboyson | 0:09f915e6f9f6 | 138 | -------t2---t3------- NTP |
andrewboyson | 0:09f915e6f9f6 | 139 | Rec Tra |
andrewboyson | 0:09f915e6f9f6 | 140 | offset (RTC - NTP) = (t1 + t4)/2 - (t2 + t3)/2 ==> [(t1 - t2) + (t4 - t3)] / 2 |
andrewboyson | 0:09f915e6f9f6 | 141 | delay = (t4 - t1) - (t3 - t2) |
andrewboyson | 0:09f915e6f9f6 | 142 | */ |
andrewboyson | 0:09f915e6f9f6 | 143 | |
andrewboyson | 0:09f915e6f9f6 | 144 | //Set the RTC |
andrewboyson | 0:09f915e6f9f6 | 145 | setTimeAsNtp(ntohll(packet.RecTimeStamp)); |
andrewboyson | 0:09f915e6f9f6 | 146 | |
andrewboyson | 0:09f915e6f9f6 | 147 | return 0; |
andrewboyson | 0:09f915e6f9f6 | 148 | } |
andrewboyson | 0:09f915e6f9f6 | 149 | int NtpIdConnectStatus = AT_NONE; |
andrewboyson | 0:09f915e6f9f6 | 150 | static void outgoingMain() |
andrewboyson | 0:09f915e6f9f6 | 151 | { |
andrewboyson | 0:09f915e6f9f6 | 152 | if (AtBusy()) return; |
andrewboyson | 0:09f915e6f9f6 | 153 | if (!WifiStarted()) return; |
andrewboyson | 0:09f915e6f9f6 | 154 | |
andrewboyson | 0:09f915e6f9f6 | 155 | static int firstAttempt = true; |
andrewboyson | 0:09f915e6f9f6 | 156 | static int result = AT_NONE; |
andrewboyson | 0:09f915e6f9f6 | 157 | |
andrewboyson | 0:09f915e6f9f6 | 158 | if (NtpIdConnectStatus == AT_SUCCESS) |
andrewboyson | 0:09f915e6f9f6 | 159 | { |
andrewboyson | 0:09f915e6f9f6 | 160 | int retryAfterFailure = timer.read() > RETRY_INTERVAL && result != AT_SUCCESS; |
andrewboyson | 0:09f915e6f9f6 | 161 | int repeat = timer.read() > GET_TIME_INTERVAL; |
andrewboyson | 0:09f915e6f9f6 | 162 | |
andrewboyson | 0:09f915e6f9f6 | 163 | if (firstAttempt || retryAfterFailure || repeat) |
andrewboyson | 0:09f915e6f9f6 | 164 | { |
andrewboyson | 0:09f915e6f9f6 | 165 | preparePacket(); |
andrewboyson | 0:09f915e6f9f6 | 166 | AtSendData(ID, sizeof(packet), &packet, &result); |
andrewboyson | 0:09f915e6f9f6 | 167 | firstAttempt = false; |
andrewboyson | 0:09f915e6f9f6 | 168 | timer.reset(); |
andrewboyson | 0:09f915e6f9f6 | 169 | timer.start(); |
andrewboyson | 0:09f915e6f9f6 | 170 | } |
andrewboyson | 0:09f915e6f9f6 | 171 | } |
andrewboyson | 0:09f915e6f9f6 | 172 | else |
andrewboyson | 0:09f915e6f9f6 | 173 | { |
andrewboyson | 2:06fa34661f19 | 174 | AtConnectId(ID, "UDP", CfgNtpIp, 123, &packet, sizeof(packet), &NtpIdConnectStatus); |
andrewboyson | 0:09f915e6f9f6 | 175 | } |
andrewboyson | 0:09f915e6f9f6 | 176 | } |
andrewboyson | 0:09f915e6f9f6 | 177 | static void incomingMain() |
andrewboyson | 0:09f915e6f9f6 | 178 | { |
andrewboyson | 0:09f915e6f9f6 | 179 | if (EspDataAvailable == ESP_AVAILABLE && EspIpdId == ID) |
andrewboyson | 0:09f915e6f9f6 | 180 | { |
andrewboyson | 0:09f915e6f9f6 | 181 | if (EspIpdLength == sizeof(packet)) handlePacket(); |
andrewboyson | 0:09f915e6f9f6 | 182 | else LogF("Incorrect NTP packet length of %d bytes", EspIpdLength); |
andrewboyson | 0:09f915e6f9f6 | 183 | } |
andrewboyson | 0:09f915e6f9f6 | 184 | } |
andrewboyson | 0:09f915e6f9f6 | 185 | int NtpMain() |
andrewboyson | 0:09f915e6f9f6 | 186 | { |
andrewboyson | 0:09f915e6f9f6 | 187 | outgoingMain(); |
andrewboyson | 0:09f915e6f9f6 | 188 | incomingMain(); |
andrewboyson | 0:09f915e6f9f6 | 189 | return 0; |
andrewboyson | 0:09f915e6f9f6 | 190 | } |