Important update: Arm Announces End of Life Timeline for Mbed. This site will be archived in July 2026. Read the full announcement.
Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
NTP Client Hello World application.
Nobody ? Why am I not surprised ? Well ... I deed some more digging. Seems that MBED gets stuck in the loop because the received endpoint stays blank
4: Time is set to (UTC): Tue Oct 20 05:23:50 2015 [NTPClient : DBG]Time is set to (UTC): Tue Oct 20 05:23:51 2015 [NTPClient : DBG]Binding socket [NTPClient : DBG]Ping [NTPClient : DBG]Output Endpoint = 87.238.165.168 [NTPClient : DBG]Pong [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint = [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint = [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint = [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint = [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint = [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint = [NTPClient : DBG]. [NTPClient : DBG]Input Endpoint =
I believe this is caused by a lost UDP packet either transmitted or received. If i recall my CCNA or P whatever correctly UDP offers best effort so lost packets are a possibility. Furthermore when reading http://doc.ntp.org/4.1.1/accopt.htm the server may drop requests rather than sending a kiss of death.
The do loop therefor can wait forever for the inEndpoint and outEndpoint IP addresses to match. Without a re-transmission it will *most likely* never happen ;-) I removed the do loop from the NTPClient.cpp file, allowing the process to continue when no packet is received. The first if clause will trap socket binding error the second will trap the event where the number of bytes received doesn't match.
Modified snippet from NTPClient.cpp
ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); if(ret < 0) { ERR("Could not receive packet"); m_sock.close(); return NTP_CONN; } if(ret < sizeof(NTPPacket)) //TODO: Accept chunks { ERR("Receive packet size does not match"); ERR("Received only: %u bytes of %u total", ret, sizeof(NTPPacket)); m_sock.close(); return NTP_PRTCL; } if( pkt.stratum == 0) //Kiss of death message : Not good ! { ERR("Kissed to death!"); m_sock.close(); return NTP_PRTCL; }
Lets see what happens if one takes a closer look at the amount of bytes received ... It must be zero if no packet is received.
70: Time is set to (UTC): Tue Oct 20 12:47:33 2015 [NTPClient : DBG]Time is set to (UTC): Tue Oct 20 12:47:34 2015 [NTPClient : DBG]Binding socket [NTPClient : DBG]Ping [NTPClient : DBG]Pong [NTPClient : ERR]Receive packet size does not match [NTPClient : ERR]Received only: 0 bytes of 48 total
I think this confirms my conjecture. Also the Wireshark capture that was running did not capture a return packet from the NTP Server.
Can somebody proof me wrong or share some other insights?
KK
Hi Koen, I think you are right. I can confirm the problems with NTPClient, hanging or receiving a date like 1 Jan 2066. I made a nice digital clock with date (and temperature using TMP102) on a Adafruit 64x32 RGB LED matrix. It connects to my WiFi and should reliable get the time right from an NTP server. Since that doesn't work, instead of using NTPClient, I started to use a 5-way button to set the date and time. But I would like to see NTPClient working too. :-) I haven't looked at it so deep, as I have a 2.5 year old boy at home who's getting most of my attention. :-) So only some late hours are left, if I'm unwilling to sleep...
Hi Koen,
have you checked this?
Invalid IPAddress for Incoming EndPoint: https://developer.mbed.org/forum/repo-42768-PicoTCP-community/topic/16612/
Regards, Jack.
Jack,
No i didn't, but I just did ... It seems like that is a related topic.
I understand the bugfix Martin suggests. However I do not understand why the loop should stay in place in the first place. I just finished some tests with my test program. It recovers fine from dropped request, keeping the RTC at its original setting and signalling the calling application a error occured.
I've committed my proposal for a bugfix, pending approval.
Koen.
Hi Koen,
thank you very much for your contribution. I'm also interested in your fix.
Jack.
On the other hand ... It might be safer to initialize the inEndpoint's address property on the count of network security. This is what I cooked up:
https://developer.mbed.org/users/KKempeneers/code/NTPClient/
It works fine for me, let me know if this works for you.
Koen.
Hi Koen, it seems not to work for me, it only gets date 1 Jan 2066. I tried several times, after I reverted, it works again. Regards, Jack.
Sure.
most is original.
main.cpp
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include "cc3000.h" #include "main.h" #include "NTPClient.h" #define CC3000_IRQ D3 // (D3) #define CC3000_EN D5 // (D5) #define CC3000_CS D10 // (D10) #define CC3000_MOSI D11 // (D11) #define CC3000_MISO D12 // (D12) #define CC3000_SCLK D13 // (D13) #define SSID "Prakjaroen" #define PHRASE "A4B5C6D7E8F9" #define SECURITY WPA2 #define IP "192.168.2.165" #define MASK "255.255.255.0" #define GW "192.168.2.1" #define DHCP 1 using namespace mbed_cc3000; #if defined TARGET_NUCLEO_F446RE //cc3000 wifi(IRQ, EN, CS, SPI(MOSI, MISO, SCLK), SSID, PHRASE, SECURITY, false); cc3000 wifi(D3, D5, D10, SPI(D11, D12, D13), "Prakjaroen", "A4B5C6D7E8F9", WPA2, false); Serial pc(USBTX, USBRX); #endif /** * \brief NTP client demo * \param none * \return int */ int main() { init(); /* board dependent init */ pc.baud(230400); printf("\r\n--------------------------------------------------------------------------------\r\n"); printf("cc3000 NTP client demo for Nucleo F446RE.\r\n"); #if (DHCP == 1) printf("Initialize the interface using DHCP...\r\n"); printf("wifi.init() "); wifi.init(); #else const char IP_ADDR[4] = {192,168,2,165}; const char IP_MASK[4] = {255,255,255,0}; const char IP_GWAY[4] = {192,168,2,1}; printf("Initialize the interface using a static IP address...\r\n"); printf("wifi.init(IP, MASK, GW) "); wifi.init(IP_ADDR, IP_MASK, IP_GWAY); #endif printf("done.\r\n"); printf("wifi.connect() "); if (wifi.connect() == -1) { printf("failed.\r\n"); printf("Failed to connect. Please verify connection details and try again. \r\n"); } else { printf("done.\r\n"); printf("IP address: %s \r\n", wifi.getIPAddress()); } NTPClient ntp_client; time_t ct_time; char time_buffer[80]; char time_buffer_old[80]; wait(1); strcpy(time_buffer_old, ""); // Parameters char* domain_name = "0.uk.pool.ntp.org"; int port_number = 123; // Read time from server printf("Reading time...\r\n"); ntp_client.setTime(domain_name, port_number, 2); // ct_time = time(NULL); // strftime(time_buffer, 80, "%a %b %d %T %p %z %Z\n", localtime(&ct_time)); // printf("UTC/GMT: %s\n", time_buffer); // printf("UTC %s\n", ctime(&ct_time)); // Choose standard or daylight savings time, comment out other // ct_time= time(NULL) + 3600; // Winter time - Convert to Europe/Amsterdam Time ct_time = time(NULL) + 7200; // Summer time - Convert to Europe/Amsterdam Time set_time(ct_time); // ct_time = time(NULL); // strftime(time_buffer, 80, "%a %d-%b-%Y %T", localtime(&ct_time)); // printf("%s\r\n", time_buffer); strftime(time_buffer, 80, "%Y", localtime(&ct_time)); printf("Year: %s\r\n", time_buffer); while (strcmp(time_buffer, "2066") == 0) { ntp_client.setTime(domain_name, port_number, 2); ct_time = time(NULL); strftime(time_buffer, 80, "%Y", localtime(&ct_time)); printf("Year: %s\r\n", time_buffer); } while (1) { ct_time = time(NULL); strftime(time_buffer, 80, "%S", localtime(&ct_time)); if (strcmp(time_buffer, time_buffer_old) != 0) { strcpy(time_buffer_old, time_buffer); // Sync once a day strftime(time_buffer, 80, "%T", localtime(&ct_time)); if (strcmp(time_buffer, "00:00:00") == 0) { ntp_client.setTime(domain_name, port_number, 2); ct_time = time(NULL) + 7200; } strftime(time_buffer, 80, "%a %d-%b-%Y %T", localtime(&ct_time)); printf("%s\r\n", time_buffer); } wait(0.01); } }
ntpclient.cpp It has only these modifications
- m_sock.bind(123); Bind to a random port)
- MaxLoop in the do/while loop
/* NTPClient.cpp */ /* Copyright (C) 2012 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ //Debug is disabled by defaulta #if 0 //Enable debug #define __DEBUG__ #include <cstdio> #define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__); #define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__); #define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__); #else //Disable debug #define DBG(x, ...) #define WARN(x, ...) #define ERR(x, ...) #endif #include "NTPClient.h" #include "UDPSocket.h" #include "mbed.h" //time() and set_time() #define NTP_PORT 123 #define NTP_CLIENT_PORT 0 //Random port #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900) NTPClient::NTPClient() : m_sock() { } NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout) { #ifdef __DEBUG__ time_t ctTime; ctTime = time(NULL); DBG("Time is set to (UTC): %s", ctime(&ctTime)); #endif //Create & bind socket DBG("Binding socket"); m_sock.bind(123); //Bind to a random port m_sock.set_blocking(false, timeout); //Set not blocking struct NTPPacket pkt; //Now ping the server and wait for response DBG("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 pkt.rootDelay = 0; //Or this one pkt.rootDispersion = 0; //Or that one 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 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0; Endpoint outEndpoint; if( outEndpoint.set_address(host, port) < 0) { m_sock.close(); return NTP_DNS; } //Set timeout, non-blocking and wait using select int ret = m_sock.sendTo( outEndpoint, (char*)&pkt, sizeof(NTPPacket) ); if (ret < 0 ) { ERR("Could not send packet"); m_sock.close(); return NTP_CONN; } //Read response Endpoint inEndpoint; DBG("Pong"); int MaxLoop = 100; do { MaxLoop--; // if (MaxLoop == 0) // printf("Pong\r\n"); DBG("m_sock.receiveFrom() start"); ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name DBG("m_sock.receiveFrom() ended"); if(ret < 0) { ERR("Could not receive packet"); m_sock.close(); return NTP_CONN; } } while( (strcmp(outEndpoint.get_address(), inEndpoint.get_address()) != 0 ) && (MaxLoop > 0)); // printf(" - %d ", MaxLoop); if(ret < sizeof(NTPPacket)) //TODO: Accept chunks { ERR("Receive packet size does not match"); m_sock.close(); return NTP_PRTCL; } if( pkt.stratum == 0) //Kiss of death message : Not good ! { ERR("Kissed to death!"); m_sock.close(); return NTP_PRTCL; } //Correct Endianness pkt.refTm_s = ntohl( pkt.refTm_s ); pkt.refTm_f = ntohl( pkt.refTm_f ); pkt.origTm_s = ntohl( pkt.origTm_s ); pkt.origTm_f = ntohl( pkt.origTm_f ); pkt.rxTm_s = ntohl( pkt.rxTm_s ); pkt.rxTm_f = ntohl( pkt.rxTm_f ); pkt.txTm_s = ntohl( pkt.txTm_s ); pkt.txTm_f = ntohl( pkt.txTm_f ); //Compute offset, see RFC 4330 p.13 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL)); int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow DBG("Sent @%ul", pkt.txTm_s); DBG("Offset: %lld", offset); //Set time accordingly set_time( time(NULL) + offset ); #ifdef __DEBUG__ ctTime = time(NULL); DBG("Time is now (UTC): %s", ctime(&ctTime)); #endif m_sock.close(); return NTP_OK; }
Hi Jack:
the unit of timeout in setTime() is mini-seconds. Setting it at 2 will always result in timeout. Try to change 2 to 7000 and see if it works.
Hi Koen, thank you very much, I changed 2 into 7000. It works, it first got 2066, but then 2015, which would not happen otherwise, I believe. I tried your version of NTPClient above with this setting, but that gets dates in 2066. It's maybe because of the combination with the cc3000.
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include "cc3000.h" #include "main.h" #include "NTPClient.h" #define CC3000_IRQ D3 // (D3) #define CC3000_EN D5 // (D5) #define CC3000_CS D10 // (D10) #define CC3000_MOSI D11 // (D11) #define CC3000_MISO D12 // (D12) #define CC3000_SCLK D13 // (D13) #define SSID "Prakjaroen" #define PHRASE "A4B5C6D7E8F9" #define SECURITY WPA2 #define IP "192.168.2.165" #define MASK "255.255.255.0" #define GW "192.168.2.1" #define DHCP 1 using namespace mbed_cc3000; #if defined TARGET_NUCLEO_F446RE //cc3000 wifi(IRQ, EN, CS, SPI(MOSI, MISO, SCLK), SSID, PHRASE, SECURITY, false); cc3000 wifi(D3, D5, D10, SPI(D11, D12, D13), "Prakjaroen", "A4B5C6D7E8F9", WPA2, false); Serial pc(USBTX, USBRX); #endif /** * \brief NTP client demo * \param none * \return int */ int main() { init(); /* board dependent init */ pc.baud(230400); printf("\r\n--------------------------------------------------------------------------------\r\n"); printf("cc3000 NTP client demo for Nucleo F446RE.\r\n"); #if (DHCP == 1) printf("Initialize the interface using DHCP...\r\n"); printf("wifi.init() "); wifi.init(); #else const char IP_ADDR[4] = {192,168,2,165}; const char IP_MASK[4] = {255,255,255,0}; const char IP_GWAY[4] = {192,168,2,1}; printf("Initialize the interface using a static IP address...\r\n"); printf("wifi.init(IP, MASK, GW) "); wifi.init(IP_ADDR, IP_MASK, IP_GWAY); #endif printf("done.\r\n"); printf("wifi.connect() "); if (wifi.connect() == -1) { printf("failed.\r\n"); printf("Failed to connect. Please verify connection details and try again. \r\n"); } else { printf("done.\r\n"); printf("IP address: %s \r\n", wifi.getIPAddress()); } NTPClient ntp_client; time_t ct_time; char time_buffer[80]; char time_buffer_old[80]; wait(1); strcpy(time_buffer_old, ""); // Parameters char* domain_name = "0.uk.pool.ntp.org"; int port_number = 123; uint32_t ntp_timeout = 7000; // Read time from server printf("Reading time...\r\n"); ntp_client.setTime(domain_name, port_number, ntp_timeout); // ct_time = time(NULL); // strftime(time_buffer, 80, "%a %b %d %T %p %z %Z\n", localtime(&ct_time)); // printf("UTC/GMT: %s\n", time_buffer); // printf("UTC %s\n", ctime(&ct_time)); // Choose standard or daylight savings time, comment out other // ct_time= time(NULL) + 3600; // Winter time - Convert to Europe/Amsterdam Time ct_time = time(NULL) + 7200; // Summer time - Convert to Europe/Amsterdam Time set_time(ct_time); // ct_time = time(NULL); // strftime(time_buffer, 80, "%a %d-%b-%Y %T", localtime(&ct_time)); // printf("%s\r\n", time_buffer); strftime(time_buffer, 80, "%Y", localtime(&ct_time)); printf("Year: %s\r\n", time_buffer); while (strcmp(time_buffer, "2066") == 0) { ntp_client.setTime(domain_name, port_number, ntp_timeout); ct_time = time(NULL); strftime(time_buffer, 80, "%Y", localtime(&ct_time)); printf("Year: %s\r\n", time_buffer); } while (1) { ct_time = time(NULL); strftime(time_buffer, 80, "%S", localtime(&ct_time)); if (strcmp(time_buffer, time_buffer_old) != 0) { strcpy(time_buffer_old, time_buffer); // Sync once a day strftime(time_buffer, 80, "%T", localtime(&ct_time)); if (strcmp(time_buffer, "00:00:00") == 0) { ntp_client.setTime(domain_name, port_number, ntp_timeout); ct_time = time(NULL) + 7200; } strftime(time_buffer, 80, "%a %d-%b-%Y %T", localtime(&ct_time)); printf("%s\r\n", time_buffer); } wait(0.01); } }
I'm glad it works for you ... But the latest post came from Zhiyong, so thanks should go out to him. I myself encountered a new error switching from Daylight Savings Time back to CET. Must be the time of year. :-)
KK
Hi,
This is a new post regarding the https://developer.mbed.org/questions/61217/How-stable-is-lwIP/#answer8809 question.
I narrowed the problems I've been having down to the NTP Client using the code below:
This program tries to set the RTC every second, yeah I know very demanding but in the interest of finding a bug very time saving.
I've set the DBG option in the NTPCLient.cpp source and just waited, it sometimes takes 20 tries sometimes about a 500, but it will hang eventually in the do loop in the snippet from NTPClient.cpp below.
As it turns out ... In the case at hand ... after 279 successful attempts, the NTPClient software is hung in the loop revealing no errors whatsoever.
I need some help to get this solved ...
Thanks,
Koen.