Last active
December 26, 2015 10:18
-
-
Save fpoto/7135314 to your computer and use it in GitHub Desktop.
Example code for the "WiFiUdp stop() does not release UDP socket" bug reported at https://github.com/arduino/Arduino/issues/1637.
Only thing to change is the name (and possibly password) of your WiFi network. See the bug report for the expected output.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <WiFi.h> | |
#include <WiFiUdp.h> | |
unsigned long inline ntpUnixTime (WiFiUDP&); | |
char ssid[] = "xxxxxxxx"; // your network SSID (name) | |
void setup() | |
{ | |
Serial.begin(115200); | |
Serial.print("Attempting to connect to SSID: "); | |
Serial.print(ssid); | |
if (WiFi.begin(ssid) == WL_CONNECTED) | |
Serial.println(" connected"); | |
else { | |
Serial.println(" failed"); | |
while (true) ; | |
} | |
} | |
void loop() | |
{ | |
WiFiUDP udp; | |
int inited; | |
unsigned long unixTime; | |
# define initonce true // open socket once or every packet sent | |
#if initonce | |
inited = udp.begin(1963); // open socket | |
for (int requests = 0; requests < 5; ++requests) { | |
unixTime = ntpUnixTime(udp); // send NTP request and get response | |
#else | |
for (int requests = 0; requests < 5; ++requests) { | |
inited = udp.begin(1963); // open socket | |
unixTime = ntpUnixTime(udp); // send NTP request and get response | |
udp.stop(); // close socket | |
#endif | |
if (! inited) | |
Serial.println("begin failed"); | |
else if (! unixTime) | |
Serial.println("request failed"); | |
else { | |
Serial.print("UTC time: "); | |
Serial.println(unixTime); | |
} | |
delay(2000); // wait for a while before next request | |
} | |
while (true) ; // stop here | |
} | |
/* | |
* Francesco Potortì, 2013, GPLv3, version 1 | |
* Send an NTP packet and wait for the response, return the Unix time | |
* | |
* To lower the memory footprint, no buffers are allocated for sending | |
* and receiving the NTP packets. Four bytes of memory are allocated | |
* for transmision, the rest is random garbage collected from the data | |
* memory segment, and the received packet is read one byte at a time. | |
* Time returned is the Unix time, that is, seconds from 1970-01-01. | |
*/ | |
unsigned long inline ntpUnixTime (WiFiUDP& udp) | |
{ | |
const char timeServer[] = "pool.ntp.org"; // NTP server | |
const long ntpFirstFourBytes = 0xEC0600E3; // NTP request header | |
unsigned long time = 0; // NTP time | |
// Clear received data | |
udp.flush(); | |
// Send an NTP request | |
if (! (udp.beginPacket(timeServer, 123) // 123 is the NTP port | |
&& udp.write((byte *)&ntpFirstFourBytes, 48) == 48 | |
&& udp.endPacket())) | |
return 0; // sending request failed | |
// Wait for response; check every pollIntv ms up to maxPoll times | |
const int pollIntv = 150; // poll every this many ms | |
const byte maxPoll = 15; // poll up to this many times | |
int pktLen; // received packet length | |
for (byte i=0; i<maxPoll; i++) { | |
if ((pktLen = udp.parsePacket()) == 48) | |
break; | |
delay(pollIntv); | |
} | |
if (pktLen != 48) | |
return 0; // no correct packet received | |
// Read and discard the first useless bytes | |
// We use the server receive time if we want to save 8 udp.read() | |
// else we use the server send time which is closest to the real time. | |
// Set useless to 32 for speed; set to 40 for accuracy. | |
const byte useless = 32; | |
for (byte i = 0; i < useless; ++i) | |
udp.read(); | |
// Read the integer part of sending time | |
for (byte i = 0; i < 4; i++) | |
time = time << 8 | udp.read(); | |
// Round to the nearest second if we want accuracy | |
if (useless == 40) // we want accuracy | |
// The fractionary part is the next byte divided by 256: if it is | |
// greater than 500ms we round to the next second; we also account | |
// for an assumed network delay of 50ms, and (0.5-0.05)*256=115; | |
// additionally, we account for how much we delayed reading the packet | |
// since its arrival, which we assume on average to be pollIntv/2. | |
time += (udp.read() > 115 - pollIntv/8); | |
// Discard the rest of the packet | |
udp.flush(); | |
return time - 2208988800ul; // convert NTP time to Unix time | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment