Arduino Forum

Using Arduino => Networking, Protocols, and Devices => Topic started by: Joss on Dec 12, 2014, 08:44 am

Title: Arduino ESP8266 and NTP
Post by: Joss on Dec 12, 2014, 08:44 am
I thought it would be a good idea to try and get one of these new ESP8266 WiFi boards and try get it to connect and download the time from an NTP server.  I can see that there are examples in the IDE for Ethernet and WIFI shields but nothing for this new device (which isn't surprising) ;D

I'm using a Pro mini and I've managed to get everything connected and 'talking' but I'm stumped at the next step of how to get the public NTP server to send the information to me!  Ive googled around but the information I'm finding is very opaque to me as I am unfamiliar with network packets and protocols. The code posted below sets up a connection and sends a message to the NTP server.  The server replies with "No IP".  This suggests to me that I am connected to the server but have not provided the correct message.  Does anyone know the correct structure of the message (in an easy to understand way)!

Here is my code below as it might help others to get started but if you have any help you can offer, please do!

Code: [Select]
// // ESP8266 connection

/* Connect ESP8266 as follows
  I used an Arduino 3.3v Pro Mini with a 3.3V USB-FTDI converter
  The ESP8266 was communicating at 9600 when delivered
  Vcc - 3.3v
  gnd - gnd
  rx - pin 11
  tx - pin 10
  ch_PD - pin 6
*/

// Target Access Point
#define ssid         "your ssid"
#define pass         "your password"

int EnablePin = 6;
unsigned long time = 0;

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX


void setup() 
{
 
  pinMode(EnablePin, OUTPUT);
  digitalWrite(EnablePin, LOW);
  delay (500);
  digitalWrite(EnablePin, HIGH);
  delay (500);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  delay (1000);

  connectWiFi();  // Start the WiFi module
 
  setPacket();

}

void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}

void connectWiFi()
{
 
//Rest the module.
Serial.println("AT+RST");
mySerial.println("AT+RST");
time = millis();
  while ((time + 2000) >= millis()){
   if (mySerial.available() > 0) {
   Serial.write(mySerial.read());
   }
  }

delay(20);

//Set the wireless mode
Serial.println("AT+CWMODE=1");
mySerial.println("AT+CWMODE=1");
time = millis();
  while ((time + 500) >= millis()){
   if (mySerial.available() > 0) {
   Serial.write(mySerial.read());
   }
  }
 delay(20);

//disconnect  - it shouldn't be but just to make sure
Serial.println("AT+CWQAP");
mySerial.println("AT+CWQAP");
time = millis();
  while ((time + 1000) >= millis()){
   if (mySerial.available() > 0) {
   Serial.write(mySerial.read());
   }
  }
 
// connect to your wireless router 
String cmd="AT+CWJAP=\"";
cmd+=ssid;
cmd+="\",\"";
cmd+=pass;
cmd+="\"";
Serial.println(cmd);
mySerial.println(cmd);
//delay(2000);
time = millis();
  while ((time + 15000) >= millis()){
   if (mySerial.available() > 0) {
  Serial.write(mySerial.read());
  }
  }

//print the ip addr
  mySerial.println("AT+CIFSR");
  Serial.println("ip address:");
  time = millis();
  while ((time + 5000) >= millis()){
   if (mySerial.available() > 0) {
   Serial.write(mySerial.read());
   }
  }
 
//set the single connection mode
Serial.println("AT+CIPMUX=0");
mySerial.println("AT+CIPMUX=0");
time = millis();
  while ((time + 1000) >= millis()){
   if (mySerial.available() > 0) {
   Serial.write(mySerial.read());
   }
  }

//Connect to the NTP server

String cmd1 = "AT+CIPSTART=\"UDP\",\"";
cmd1 += "129.6.15.28";
cmd1 += "\",123";
mySerial.println(cmd1);
Serial.println(cmd1);
time = millis();
  while ((time + 5000) >= millis()){
   if (mySerial.available() > 0) {
   Serial.write(mySerial.read());
   }
  }
}

void setPacket(){
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
 
  //mySerial.write("192.168.0.13", 123);
  mySerial.write(packetBuffer,NTP_PACKET_SIZE);
 // Serial.println(packetBuffer,NTP_PACKET_SIZE);
  //Udp.endPacket();
}
Title: Re: Arduino ESP8266 and NTP
Post by: westfw on Dec 12, 2014, 12:22 pm
I am pretty sure that the no ip message is from the esp8266, and means that the step where you set up the udp connection did not work.
Title: Re: Arduino ESP8266 and NTP
Post by: Erni on Dec 12, 2014, 02:46 pm
There are some info here:
http://playground.arduino.cc/Code/NTPclient

Maybe it is easyer to use google:
http://www.esp8266.com/viewtopic.php?f=19&t=809
Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 13, 2014, 02:19 pm
I am pretty sure that the no ip message is from the esp8266, and means that the step where you set up the udp connection did not work.

When I ran the code again today I got a different result!!! :smiley-roll:

This time the response to the command

AT+CIPSTART="UDP","129.6.15.28",123

is "OK" suggesting the command was accepted.

However, after I send the packet I only get some garbage returned......as below....

===================================================================

AT+RST
AT+RST


OK
.ªЃÿP2ýPfhLÈ 4¥_PFˆ
[Vendor:www.ai-thinker.com Version:0.9.2.4]

ready
AT+CWMODE=1
AT+CWMODE=1

no change
AT+CWQAP
AT+CWQAP


OK
AT+CWJAP="xxxxxxxxxxxxx","xxxxxxxxxxxxx"
AT+CWJAP="xxxxxxxxxxxxx","xxxxxxxxxxxxx"


OK
ip address:
AT+CIFSR

192.168.0.13

OK
AT+CIPMUX=0
AT+CIPMUX=0


OK
AT+CIPSTART="UDP","129.6.15.28",123
AT+CIPSTART="UDP","129.6.15.28",123


OK
ã   ì        1N14


=================================================================

So I think the connection today was good but I'm still stumped by what the format of the message to the server should be.


Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 13, 2014, 02:26 pm
There are some info here:
http://playground.arduino.cc/Code/NTPclient

Maybe it is easyer to use google:
http://www.esp8266.com/viewtopic.php?f=19&t=809
I looked at these.  The 2nd one may be the simplest and I'll try it in the next few days.  As for the 1st link I couldnt make it work with this ESP8266  (I assume it needs the WIFI or Ethernet shield connected.  Anyway I find the presentation of the page too complicated for my current competance.  I tried extracting this portion of the code and just writing t to the serial port

  // Send an NTP request
  if (! (udp.beginPacket(timeServer, 123) // 123 is the NTP port
    && udp.write((byte *)&ntpFirstFourBytes, 48) == 48
    && udp.endPacket()))

Again I just seem to get garbage back, I wonder if the return info is not ASCII?
Title: Re: Arduino ESP8266 and NTP
Post by: countrypaul on Dec 13, 2014, 04:08 pm
Assuming ASCII return is likely to be wrong.

THis may help you understand: http://www.ntp.org/ntpfaq/NTP-s-algo.htm

Paul
Title: Re: Arduino ESP8266 and NTP
Post by: westfw on Dec 14, 2014, 12:23 am
Not at all ascii: http://www.meinbergglobal.com/english/info/ntp-packet.htm (http://www.meinbergglobal.com/english/info/ntp-packet.htm)

Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 14, 2014, 03:30 am
Not at all ascii: http://www.meinbergglobal.com/english/info/ntp-packet.htm (http://www.meinbergglobal.com/english/info/ntp-packet.htm)


Thanks - I found that page during my searches and it does provice me a bit of information but as I am unfamiliar with the syntax of datagrams and how to handle them it is still only part of the information.  I'm really looking for the c code to drop into my program.
Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 14, 2014, 03:47 am
Assuming ASCII return is likely to be wrong.

THis may help you understand: http://www.ntp.org/ntpfaq/NTP-s-algo.htm

Paul
Sorry, this link is to the main NTP org people who are all about setting up and running servers.  There is no easy to read documentation here that I can find to show how to make a simple request to a server and to receive the appropriate response. 

I am not interested in accuracy yet I thought it would be easy to just get the number of seconds since 1900,1,1 and just perform a simple calculation and hey presto get the correct date and time. 

All I seem to be learning is the detail, ie how server work and how they calculate accuracy yet these websites and documentation assume a level of competancy that I do not have.  I'm all up for doing the hard yards to learn but the sources I'm finding are all diving in way too deep.

I guess I'm remembering back o when I did work with GPS's and for that type of device you send a message and you receive a string back.  I assumed NTP servers would be similar in their operation.  If they simple, I have not yet uncovered the secret!

Maybe I need NTP for dummies!   :smiley-confuse:
Title: Re: Arduino ESP8266 and NTP
Post by: westfw on Dec 14, 2014, 05:10 am
Don't you get a "+ IPD, <len>:" prefix, followed by a bunch of bytes? <len> should be >= 48
typically, you'd search for that prefix, and then do a "serial.readbytes(packetbuffer, 48);" and look at the values in packetbuffer as binary.  (actually, you'd normally make up a nice structure, like:

Code: [Select]
struct ntp_pkt_t {
       u_char li_vn_mode;   /* leap indicator, version and mode */
       u_char stratum;      /* peer stratum */
       u_char ppoll;        /* peer poll interval */
       s_char precision;    /* peer clock precision */
       u_fp   rootdelay;    /* distance to primary clock */
       u_fp   rootdispersion;      /* clock dispersion */
       u_int32       refid;        /* reference clock ID */
       l_fp   reftime;      /* time peer clock was last updated */
       l_fp   org;          /* originate time stamp */
       l_fp   rec;          /* receive time stamp */
       l_fp   xmt;          /* transmit time stamp */
       u_int32       exten[1];     /* misused */
       u_char mac[MAX_MAC_LEN]; /* mac */
} ntppkt;

and use that for both transmit/receive of the packet.
(ie "Serial.write(&ntppkt, sizeof(ntppkt));")

Title: Re: Arduino ESP8266 and NTP
Post by: westfw on Dec 14, 2014, 05:28 am
NTP is not a simple protocol.  It has things in it to synchronize time across networks to within very small times - much less than a network transmission delay.  Which is a really neat trick, if you think about it.
You might want to look into SNTP ("Simple Network Time Protocol"), Time Protocols (port 37), and unix "rdate", which I think are all more of the "tell me what time it is and I won't worry about how much time has passed since I first asked."
(OTOH, I don't know if they are as widely implemented...)
Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 14, 2014, 05:52 am
Thanks for your help westfw.  I've added a command to prepare the port for sending data (and now I get the IPD message)

AT+CIPSEND=48

The result/response is:

===================================================================

OK
AT+CIPSTART="UDP","129.6.15.28",123
AT+CIPSTART="UDP","129.6.15.28",123


OK
AT+CIPSEND=48
AT+CIPSEND=48

> ãì    1N14

SEND OK

+IPD,48:$ãACTSØ7×0Æêä

OK

=================================================================

I tried using your code   "mySerial.readBytes(packetBuffer, 48);"  but it returns a error:

"invalid conversion from 'byte*' to 'char*'"   


sketch_dec14a.ino: In function 'void setPacket()':
sketch_dec14a:177: error: invalid conversion from 'byte*' to 'char*'
sketch_dec14a:177: error: initializing argument 1 of 'size_t Stream::readBytes(char*, size_t)'


the packetBuffer was declared as a byte at the top of the program but is clearly not happy with this way of reading the data

hmmm one step forward.   You may be right about using the SNTP.  maybe i should investigate that option!
Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 14, 2014, 05:56 am
btw  I am using a structure similar to the one you suggested (copied from an arduino example).  It is at the end of my program thus:

Code: [Select]
void setPacket(){
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
 
  //mySerial.write("192.168.0.13", 123);
  mySerial.write(packetBuffer,NTP_PACKET_SIZE);
 
  delay (2000);
 
  mySerial.readBytes(packetBuffer, 48);
 // Serial.println(packetBuffer,NTP_PACKET_SIZE);
  //Udp.endPacket();
}



Title: Re: Arduino ESP8266 and NTP
Post by: Joss on Dec 15, 2014, 11:00 pm
Well I did not get my own code to work :-*

but I did find an update to the firmware which includes a direct call to a SNTP server. 

If anyone is interested it can be found here:

http://www.esp8266.com/viewtopic.php?f=11&t=705&p=4881#p4881 (http://www.esp8266.com/viewtopic.php?f=11&t=705&p=4881#p4881)

Hope this helps somebody!
Title: Re: Arduino ESP8266 and NTP
Post by: tgibbs99 on Mar 23, 2015, 04:08 am
Can someone please show us what an NTP request packet looks like? I see its a 48 byte thing. How can this sent via esp8266? Can it be converted to a string and back to hex bytes?

Thanks.

Tim
Title: Re: Arduino ESP8266 and NTP
Post by: pixelk on May 22, 2015, 10:06 am
I'm working on the same thing, here is my capture of the NTP request and answer, both are valid and captured at the wifi hotspot, I'm working on the receiving part at this moment.

Command sent by my ESP8266 to my NTP server (from 192.168.0.242 to 192.168.0.28)
Code: [Select]
0000   64 66 b3 b0 f1 20 18 fe 34 9f 38 5e 08 00 45 00  df... ..4.8^..E.
0010   00 4c 00 4e 00 00 ff 11 38 f4 c0 a8 00 f2 c0 a8  .L.N....8.......
0020   00 1c 5b 4b 00 7b 00 38 37 6c e3 00 06 ec 00 00  ..[K.{.87l......
0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0040   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0050   00 00 00 00 00 00 00 00 00 00                    ..........

(http://stuff.knackes.com/dld/201505/ScreenCap-20150522-100358_37DA1D40.png)

Command sent back by the NTP server
Code: [Select]
0000   18 fe 34 9f 38 5e 64 66 b3 b0 f1 20 08 00 45 c0  ..4.8^df... ..E.
0010   00 4c 00 00 40 00 40 11 b7 82 c0 a8 00 1c c0 a8  .L..@.@.........
0020   00 f2 00 7b 5b 4b 00 38 36 2a 24 03 06 f0 00 00  ...{[K.86*$.....
0030   0b 34 00 00 16 67 5b 79 a5 92 d9 08 d2 c7 ee d1  .4...g[y........
0040   ff 40 00 00 00 00 00 00 00 00 d9 08 d4 b3 94 c4  .@..............
0050   37 25 d9 08 d4 b3 94 db 47 72                    7%......Gr

(http://stuff.knackes.com/dld/201505/ScreenCap-20150522-100538_A7BC5229.png)
Title: Re: Arduino ESP8266 and NTP
Post by: pixelk on May 23, 2015, 07:13 am
OK, got it working (ESP8266 in AT mode, fully reset and connected to wifi )
Code: [Select]
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

unsigned long GetTime()
{
  String cmd = "AT+CIPSTART=\"UDP\",\"192.168.0.28\",123"; // my own NTP server, synced by GPS
  Serial1.println(cmd);
  delay(2000);
  if(Serial1.find("Error")){
    Serial.print("RECEIVED: Error");
    return 0;
  }
  
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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
  
  Serial1.print("AT+CIPSEND=");
  Serial1.println(NTP_PACKET_SIZE);
  if(Serial1.find(">"))
  {
    for (byte i = 0; i < NTP_PACKET_SIZE; i++)
    {
      Serial1.write(packetBuffer[i]);
      delay(5);
    }
  }else{
    Serial1.println("AT+CIPCLOSE");
    return 0;
  }
  
  //Serial1.find("+IPD,48:");
  
  int acksize = NTP_PACKET_SIZE + 1 + 2 + 8; // ESP8266 adds a space, a CRLF and starts with "+IPD,48:"
  
  Serial.println("ESP2866 ACK : ");
  for (byte i = 0; i < acksize; i++)
  {
    while (Serial1.available() == 0) // you may have to wait for some bytes
    {
      //Serial.print(".");
    }
    byte ch = Serial1.read();
    if (ch < 0x10) Serial.print('0');
    Serial.print(ch,HEX);
    Serial.print(' ');
    if ( (((i+1) % 15) == 0) ) { Serial.println(); }
  }
  Serial.println();
  Serial.println();

  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  
  Serial.println("Server answer : ");

  int i = 0;
  while (Serial1.available() > 0) {
    byte ch = Serial1.read();
    if (i <= NTP_PACKET_SIZE)
    {
      packetBuffer[i] = ch;
    }
    if (ch < 0x10) Serial.print('0');
    Serial.print(ch,HEX);
    Serial.print(' ');
    if ( (((i+1) % 15) == 0) ) { Serial.println(); }
    delay(5);
    i++;
    if ( ( i < NTP_PACKET_SIZE ) && ( Serial1.available() == 0 ) )
    {
      while (Serial1.available() == 0)  // you may have to wait for some bytes
      {
        Serial.print("!");
      }
    }
  }
  
  Serial.println();
  Serial.println();
  Serial.print(i+1);
  Serial.println(" bytes received"); // will be more than 48
  
  Serial.print(packetBuffer[40],HEX);
  Serial.print(" ");
  Serial.print(packetBuffer[41],HEX);
  Serial.print(" ");
  Serial.print(packetBuffer[42],HEX);
  Serial.print(" ");
  Serial.print(packetBuffer[43],HEX);
  Serial.print(" = ");

  unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
  unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
  unsigned long secsSince1900 = highWord << 16 | lowWord;
  
  Serial.print(secsSince1900,DEC);
  
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
  const unsigned long seventyYears  = 2208988800UL;
    // subtract seventy years:
  unsigned long epoch = secsSince1900 - seventyYears;
  
  unsigned long DST = 60*60*2; // adjust to your GMT+DST
  
  unsigned long timestamp = epoch + DST;

  Serial.println();
  Serial.print("Epoch : ");
  Serial.println(epoch,DEC);        

  return timestamp;
}


you can use the output of this function to set the time of the Time library
Title: Re: Arduino ESP8266 and NTP
Post by: phaseform on Sep 29, 2015, 11:55 am
Thanks pixelk, that code is awesome. I modified it slightly so it doesn't get caught in a while loop and just changed the NTP server to one from http://www.pool.ntp.org/en/ :

Code: [Select]
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

unsigned long GetTime()
{

 String cmd = "AT+CIPSTART=\"UDP\",\"130.102.128.23\",123"; // NTP server
 Serial1.println(cmd);
 delay(2000);
 if(Serial1.find("Error")){
   Serial.print("RECEIVED: Error");
   return 0;
 }
 int counta = 0;
 memset(packetBuffer, 0, NTP_PACKET_SIZE);
 // Initialize values needed to form NTP request
 // (see URL above for details on the packets)
 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
 
 Serial1.print("AT+CIPSEND=");
 Serial1.println(NTP_PACKET_SIZE);
 if(Serial1.find(">"))
 {
   for (byte i = 0; i < NTP_PACKET_SIZE; i++)
   {
     Serial1.write(packetBuffer[i]);
     delay(5);
   }
 }else{
   Serial1.println("AT+CIPCLOSE");
   return 0;
 }
 
 //Serial1.find("+IPD,48:");
 
 int acksize = NTP_PACKET_SIZE + 1 + 2 + 8; // ESP8266 adds a space, a CRLF and starts with "+IPD,48:"
 
 Serial.println("ESP2866 ACK : ");
 for (byte i = 0; i < acksize; i++)
 {
     while (Serial1.available() == 0)  // you may have to wait for some bytes
     {
       counta += 1;
       Serial.print(".");
       delay(100);
       if (counta == 15){
         return 0;
       }
     }
   byte ch = Serial1.read();
   if (ch < 0x10) Serial.print('0');
   Serial.print(ch,HEX);
   Serial.print(' ');
   if ( (((i+1) % 15) == 0) ) { Serial.println(); }
 }
 Serial.println();
 Serial.println();

 memset(packetBuffer, 0, NTP_PACKET_SIZE);
 
 Serial.println("Server answer : ");

 int i = 0;
 while (Serial1.available() > 0) {
   byte ch = Serial1.read();
   if (i <= NTP_PACKET_SIZE)
   {
     packetBuffer[i] = ch;
   }
   if (ch < 0x10) Serial.print('0');
   Serial.print(ch,HEX);
   Serial.print(' ');
   if ( (((i+1) % 15) == 0) ) { Serial.println(); }
   delay(5);
   i++;
   if ( ( i < NTP_PACKET_SIZE ) && ( Serial1.available() == 0 ) )
   {
     while (Serial1.available() == 0)  // you may have to wait for some bytes
     {
       counta += 1;
       Serial.print("!");
       delay(100);
       if (counta == 15){
         return 0;
       }
     }
   }
 }
 
 Serial.println();
 Serial.println();
 Serial.print(i+1);
 Serial.println(" bytes received"); // will be more than 48
 
 Serial.print(packetBuffer[40],HEX);
 Serial.print(" ");
 Serial.print(packetBuffer[41],HEX);
 Serial.print(" ");
 Serial.print(packetBuffer[42],HEX);
 Serial.print(" ");
 Serial.print(packetBuffer[43],HEX);
 Serial.print(" = ");

 unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
 unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
   // combine the four bytes (two words) into a long integer
   // this is NTP time (seconds since Jan 1 1900):
 unsigned long secsSince1900 = highWord << 16 | lowWord;
 
 Serial.print(secsSince1900,DEC);
 
   // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
 const unsigned long seventyYears  = 2208988800UL;
   // subtract seventy years:
 unsigned long epoch = secsSince1900 - seventyYears;
 
 unsigned long DST = 60*60*2; // adjust to your GMT+DST
 
 unsigned long timestamp = epoch + DST;

 Serial.println();
 Serial.print("Epoch : ");
 Serial.println(epoch,DEC);
 return epoch;
}
Title: Re: Arduino ESP8266 and NTP
Post by: atheec on Sep 30, 2015, 09:15 am
I used the above code of yours and get server answer. but it does not go above i= 29;

ESP2866 ACK :
FF 0D 0A 52 65 63 76 20 34 38 20 62 79 74 65
73 0D 0A 0D 0A 53 45 4E 44 20 4F 4B 0D 0A .0D
0A 2B 49 50 44 2C 34 38 3A 24 02 06 EC 00 00
2A 9E 00 00 06 5B D8 DA C0 CA D9 B6 07 7E

Server answer :
8A DB C5 A2 00 00 00 00 00 00 00 00 D9 B6 09
A7 3B 25 B3 6C D9 B6 09 A7 3B 27 3C FA !!!!!!!!!!!!!!
Title: Re: Arduino ESP8266 and NTP
Post by: adminarduinocc on Oct 18, 2015, 03:48 pm
I recive Server answer too :
8B 23 06 57 00 00 00 00 00 00 00 00 D9 CE 21
5B 69 B7 58 A0 D9 CE 21 5B 69 B8 C3 9E !!!!!!!!!!!!!!

Please give the working code somebody.
Title: Re: Arduino ESP8266 and NTP
Post by: Mark Bramwell on Oct 23, 2015, 07:39 pm
I am starting to get involved with these mini wifi boards. I am creating a web app that allows me to manage these boards.

Part of the app is a webservice that allows the boards to get certain types of info.


can you perform a http request with your sketch?

If yes, this tells you the time:  http://www.foxhollow.ca/nodemgr/?time
this tells you the date:  http://www.foxhollow.ca/nodemgr/?date

You tell your mini board to retrieve the data from the above URL and you get the date/time in plain ascii.

I have created some interesting functions like 'weekend'. It will tell your board if is the weekend or weekday (for processes that need to act differently on weekdays/weekends)

more info here:  http://www.foxhollow.ca/nodemgr/?info

This is an easy to install php based web app that I have running on a Linux server. I am not sure if it is of use to any other person.
Title: Re: Arduino ESP8266 and NTP
Post by: adminarduinocc on Oct 24, 2015, 09:21 pm
If yes, this tells you the time:  http://www.foxhollow.ca/nodemgr/?time
this tells you the date:  http://www.foxhollow.ca/nodemgr/?date


This is interesting, but how to get a date in 24-hour format?
Title: Re: Arduino ESP8266 and NTP
Post by: adminarduinocc on Oct 25, 2015, 12:26 am
Working code with this library (https://github.com/itead/ITEADLIB_Arduino_WeeESP8266):


Code: [Select]

#include "ESP8266.h"
#include <SoftwareSerial.h>
SoftwareSerial espSerial(10, 11); // RX:D11, TX:D10

#define HOST_NAME   "82.209.243.241"
#define HOST_PORT   (123)

ESP8266 wifi(espSerial);

void setup()
{
  Serial.begin(9600);
  Serial.print("setup begin\r\n");
  Serial.print("Join AP success\r\n");
  Serial.print("IP: ");
  Serial.println(wifi.getLocalIP().c_str());

  if (wifi.disableMUX()) {
    Serial.print("single ok\r\n");
  } else {
    Serial.print("single err\r\n");
  }

  Serial.print("setup end\r\n");
}
void loop()
{
  ntpupdate();
  delay(20000);
}

void ntpupdate()
{
  uint8_t buffer[128] = {0};

  if (wifi.registerUDP(HOST_NAME, HOST_PORT)) {
    Serial.print("register udp ok\r\n");
  } else {
    Serial.print("register udp err\r\n");
  }

  static const char PROGMEM
  timeReqA[] = { 227,  0,  6, 236 },
               timeReqB[] = {  49, 78, 49,  52 };
  // Assemble and issue request packet
  uint8_t       buf[48];
  memset(buf, 0, sizeof(buf));
  memcpy_P( buf    , timeReqA, sizeof(timeReqA));
  memcpy_P(&buf[12], timeReqB, sizeof(timeReqB));


  //    char *buf = "Hello, this is client!";
  wifi.send((const uint8_t*)buf, 48);

  uint32_t len = wifi.recv(buffer, sizeof(buffer), 10000);
  if (len > 0) {
    Serial.print("UNIX TIME IS:");

    // Serial.print(buffer[42]);
    unsigned long t = (((unsigned long)buffer[40] << 24) |
                       ((unsigned long)buffer[41] << 16) |
                       ((unsigned long)buffer[42] <<  8) |
                       (unsigned long)buffer[43]) - 2208988800UL;

    Serial.println(t);
  }

  if (wifi.unregisterUDP()) {
    Serial.print("unregister udp ");
    Serial.println(" ok");
  } else {
    Serial.print("unregister udp ");
    Serial.println(" err");
  }

}
Title: Re: Arduino ESP8266 and NTP
Post by: Mark Bramwell on Oct 26, 2015, 02:14 am
This is interesting, but how to get a date in 24-hour format?
If you pull up the info page you can see that you can ask for any part of the date/time.

However, give me an example of how you would like it to appear and I'll add a new function called  "time24"

I am guessing  17:01:12  for 5:01pm 12secs in the afternoon

-----
Update:   http://www.foxhollow.ca/nodemgr/index.php?info
http://www.foxhollow.ca/nodemgr/index.php?time24    (display in 24hour format)
Title: Re: Arduino ESP8266 and NTP
Post by: adminarduinocc on Oct 26, 2015, 09:29 am
If you pull up the info page you can see that you can ask for any part of the date/time.

However, give me an example of how you would like it to appear and I'll add a new function called  "time24"

I am guessing  17:01:12  for 5:01pm 12secs in the afternoon

-----
Update:   http://www.foxhollow.ca/nodemgr/index.php?info
http://www.foxhollow.ca/nodemgr/index.php?time24    (display in 24hour format)

This is your personal website? As far as it shows the exact time? Can I use it to synchronize the time? Can you add a function to display the time in Unix format? https://en.wikipedia.org/wiki/Unix_time
Title: Re: Arduino ESP8266 and NTP
Post by: Mark Bramwell on Oct 26, 2015, 04:30 pm
This is your personal website? As far as it shows the exact time? Can I use it to synchronize the time? Can you add a function to display the time in Unix format? https://en.wikipedia.org/wiki/Unix_time
Yes. It is my website and I use NTP to keep the time correct. I do not care if you sync against my server.

The plan is to finish a few functions and release the app so you can run it on your own Linux box (but I'll keep my box going). I like the registration and alert features... more on those later.

ps: I added "unixtime" to the webservice.

http://www.foxhollow.ca/nodemgr?unixtime

and updated the command list on the info screen:  http://www.foxhollow.ca/nodemgr?info


Title: Re: Arduino ESP8266 and NTP
Post by: adminarduinocc on Oct 31, 2015, 06:17 pm
Working code with standasrt AT commands:

Code: [Select]


void ntpupdate()
{
  const byte NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
  byte packetBuffer[ NTP_PACKET_SIZE];
 
Serial.println("AT+CIPSTART=\"UDP\",\"91.226.136.136\",123");
  delay(500);
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
 
 // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
 
 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
 
 // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  Serial.print("AT+CIPSEND=");
  Serial.println(NTP_PACKET_SIZE);
  delay(500);
  for (uint32_t i = 0; i < NTP_PACKET_SIZE; i++) {
    Serial.write(packetBuffer[i]);
  }

  int counta = 0;
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  if (Serial.find("+IPD,48:"))
  {
    dbgSerial.println("Server answer : ");

    int i = 0;
    while (Serial.available() > 0) {
      byte ch = Serial.read();
      if (i < NTP_PACKET_SIZE)
      {
        packetBuffer[i] = ch;
      }
      i++;
      if ( ( i < NTP_PACKET_SIZE ) && ( Serial.available() == 0 ) )
      {
        while (Serial.available() == 0) // you may have to wait for some bytes
        {
          counta += 1;
          dbgSerial.print("!");
          delay(100);
          if (counta == 15) {
            exit;
          }
        }
      }
    }
  }
   //the timestamp starts at byte 40 of the received packet and is four bytes,
  // or two words, long. First, esxtract the two words:

  unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
  unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
  // combine the four bytes (two words) into a long integer
  // this is NTP time (seconds since Jan 1 1900):
  unsigned long secsSince1900 = highWord << 16 | lowWord;
  dbgSerial.print("Seconds since Jan 1 1900 = " );
  dbgSerial.println(secsSince1900);

  // now convert NTP time into everyday time:
  dbgSerial.print("Unix time = ");
  // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
  const unsigned long seventyYears = 2208988800UL;
  // subtract seventy years:
  unsigned long epoch = secsSince1900 - seventyYears;
  // print Unix time:
  dbgSerial.println(epoch);

  // print the hour, minute and second:
  dbgSerial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
  dbgSerial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
  dbgSerial.print(':');
  if ( ((epoch % 3600) / 60) < 10 ) {
    // In the first 10 minutes of each hour, we'll want a leading '0'
    dbgSerial.print('0');
  }
  dbgSerial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
  dbgSerial.print(':');
  if ( (epoch % 60) < 10 ) {
    // In the first 10 seconds of each minute, we'll want a leading '0'
    dbgSerial.print('0');
  }
  dbgSerial.println(epoch % 60); // print the second
  dbgSerial.println(" ");
  Serial.println("AT+CIPCLOSE");
   }
Title: Re: Arduino ESP8266 and NTP
Post by: twim on Jan 04, 2016, 12:17 pm
Check out this: UdpNTPClient (https://github.com/bportaluri/WiFiEsp/blob/master/examples/UdpNTPClient/UdpNTPClient.ino)
It is basically the same example of the standard Arduino WiFi library (https://www.arduino.cc/en/Tutorial/UdpNTPClient) adapted for the WiFiEsp library (https://github.com/bportaluri/WiFiEsp) that works with ESP8266 module.
Title: Re: Arduino ESP8266 and NTP
Post by: adminarduinocc on Feb 03, 2016, 08:41 am
Check out this: UdpNTPClient (https://github.com/bportaluri/WiFiEsp/blob/master/examples/UdpNTPClient/UdpNTPClient.ino)
It is basically the same example of the standard Arduino WiFi library (https://www.arduino.cc/en/Tutorial/UdpNTPClient) adapted for the WiFiEsp library (https://github.com/bportaluri/WiFiEsp) that works with ESP8266 module.
Good job! Thanks!
Will this code work without Arduino board? For example, if you connect Esp8266 and tm1637?
Title: Re: Arduino ESP8266 and NTP
Post by: torquato on May 25, 2016, 10:13 am
Check out this: UdpNTPClient (https://github.com/bportaluri/WiFiEsp/blob/master/examples/UdpNTPClient/UdpNTPClient.ino)
It is basically the same example of the standard Arduino WiFi library (https://www.arduino.cc/en/Tutorial/UdpNTPClient) adapted for the WiFiEsp library (https://github.com/bportaluri/WiFiEsp) that works with ESP8266 module.
give me the same Unix time
17
packet received
Seconds since Jan 1 1900 = 0
Unix time = 2085978496
The UTC time is 6:28:16
48
packet received
Seconds since Jan 1 1900 = 0
Unix time = 2085978496
The UTC time is 6:28:16
Title: Re: Arduino ESP8266 and NTP
Post by: virusbk on Sep 29, 2016, 12:59 pm
Code: [Select]

void ntpupdate()
{
  String cmd = "AT+CIPSTART=\"UDP\",\"";
  uint8_t i;
  cmd += ntp;
  cmd += "\",123\r\n";
  sendData(cmd, 5000, DEBUG);
  delay(500);
  memset(buffer, 0, BUFFER_SIZE);
 // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  buffer[0] = 0b11100011; // LI, Version, Mode
  buffer[1] = 0; // Stratum, or type of clock
  buffer[2] = 6; // Polling Interval
  buffer[3] = 0xEC; // Peer Clock Precision
 // 8 bytes of zero for Root Delay & Root Dispersion
  buffer[12] = 49;
  buffer[13] = 0x4E;
  buffer[14] = 49;
  buffer[15] = 52;
  Serial.println("Send request");
  esp8266.print("AT+CIPSEND=");
  esp8266.println(NTP_PACKET_SIZE);
  delay(20);
  if (esp8266.find(">"))
  {
    Serial.println("Read >");
    for (i = 0; i < NTP_PACKET_SIZE; i++)
    {
    esp8266.write(buffer[i]);
    delay(5);
    }
    delay(200);
    memset(buffer, 0, NTP_PACKET_SIZE); 
    Serial.println("Server answer : ");
    i = 0;
    long int time_ = millis();   
    if (esp8266.find("+IPD,48:"))
    {
      Serial.println("Found +IPD,48:");
      while( (time_+4000) > millis())
      {
          while((esp8266.available()) && (i < NTP_PACKET_SIZE))
          {
              byte ch = esp8266.read();
              if (ch < 0x10) Serial.print('0');
              Serial.print(ch,HEX);
              Serial.print(' ');
              if ( (((i+1) % 15) == 0) ) { Serial.println(); }
              buffer[i] = ch; // read the next character.
              i++;           
          }
      }
      Serial.println();
      Serial.print("Read bytes - ");
      Serial.println(i);
      if (i == NTP_PACKET_SIZE) {
       Serial.println();
       Serial.print(buffer[40],HEX);
       Serial.print(" ");
       Serial.print(buffer[41],HEX);
       Serial.print(" ");
       Serial.print(buffer[42],HEX);
       Serial.print(" ");
       Serial.print(buffer[43],HEX);
       Serial.print(" = ");
         
       //the timestamp starts at byte 40 of the received packet and is four bytes,
       // or two words, long. First, esxtract the two words:
       
       unsigned long highWord = word(buffer[40], buffer[41]);
       unsigned long lowWord = word(buffer[42], buffer[43]);
       // combine the four bytes (two words) into a long integer
       // this is NTP time (seconds since Jan 1 1900):
       unsigned long secsSince1900 = highWord << 16 | lowWord;
       Serial.print("Seconds since Jan 1 1900 = " );
       Serial.println(secsSince1900);
       
       // now convert NTP time into everyday time:
       Serial.print("Unix time = ");
       // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
       const unsigned long DST = 3600*timeZone
       const unsigned long seventyYears = 2208988800UL - DST;
       // subtract seventy years:
       unsigned long epoch = secsSince1900 - seventyYears;
       // print Unix time:
       Serial.println(epoch);   
       // print the hour, minute and second:
       Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
       Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
       Serial.print(':');
       if ( ((epoch % 3600) / 60) < 10 ) {
        // In the first 10 minutes of each hour, we'll want a leading '0'
          Serial.print('0');
          }
       Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
       Serial.print(':');
       if ( (epoch % 60) < 10 ) {
          // In the first 10 seconds of each minute, we'll want a leading '0'
            Serial.print('0');
          }
       Serial.println(epoch % 60); // print the second
       Serial.println(" ");
     }     
  } else {
      Serial.println("Not Found +IPD,48:");
      }
  } else {
      Serial.println("No answer to server ");
   }
  esp8266.println("AT+CIPCLOSE");
 
 
}


Often, instead of 48 bytes, only half comes
Title: Re: Arduino ESP8266 and NTP
Post by: mpopgun on Aug 29, 2019, 07:20 am
This is a few years old, and it seems things have changed, i couldn't get this to work. So, this is possibly the least graceful way of getting the time w/ an ESP8266, but after spending days trying to learn how to program Arduino, most everything above was too advance for me to figure out, except that I could tell the time from the NTP server was not always coming back in the same position, and was taking more than just 4 bytes. I have no idea why, but I can copy and paste hex into an online converter:)

Here is my solution to getting the current time, hopefully it helps somebody else.

ESP8266 is connected to a Mega2560 via Serial 3
If you have a Mega w/ builtin WiFi, it seems they are also connected to Serial 3

HardwareSerial & dbgTerminal = Serial;
HardwareSerial & espSerial = Serial3;

String sntptime, day, month, daynum, hour, minute, second, year;



// Get the data from the WiFi module and send it to the debug serial port
String GetResponse(String AT_Command, int wait){
  String tmpData;
   
  espSerial.println(AT_Command);
  delay(200);
  while (espSerial.available() >0 )  {
    char c = espSerial.read();
    tmpData += c;
     
    if ( tmpData.indexOf(AT_Command) > -1 )          
      tmpData = "";
    else
      tmpData.trim();        
           
   }
   return tmpData;
}


String GetTime()
{

// Uses the modem's SNTP feature to get the time
//the time always comes back 3 letter day, 3 letter month, 2 digit day number, 2 digit hr, : 2 digit minute, : 2 digit second, 4 digit year
 
       
         sntptime = GetResponse("AT+CIPSNTPTIME?", 100);
         
//          Serial.println(sntptime);
         sntptime.remove(0,13);  // Remove 13 characters starting at index=0
         sntptime.remove(20);
//          Serial.print("removed first 13 letters from sntptime = ");
//          Serial.println(sntptime);
         day=sntptime;
         day.remove(3);  // Remove from from index=3 through the end of the string
//          Serial.print("Day = ");
//         Serial.println(day);
         month=sntptime;
         month.remove(0,3);
         month.remove(3);
//         Serial.print("Month = ");
//         Serial.println(month);
         daynum=sntptime;
         daynum.remove(0,6);
         daynum.remove(2);
//          Serial.print("Day number = ");
//          Serial.println(daynum);
         hour=sntptime;
         hour.remove(0,8);
         hour.remove(2);
//          Serial.print("Hour = ");
//          Serial.println(hour);
         minute=sntptime;
         minute.remove(0,11);
         minute.remove(2);
//          Serial.print("Minutes = ");
//         Serial.println(minute);
         second=sntptime;
         second.remove(0,14);
         second.remove(2);
//          Serial.print("Seconds = ");
//          Serial.println(second);
         year=sntptime;
         year.remove(0,16);
         year.remove(4);
//          Serial.print("Year = ");
//          Serial.println(year);


   return sntptime;

}
Title: Re: Arduino ESP8266 and NTP
Post by: floresta on Aug 29, 2019, 03:44 pm
This is a few years old, and it seems things have changed, . . .
Now that you have resurrected this three year old post you might as well take advantage of the latest changes.  Now that the ESP8266 core has been updated with some of the ESP32 code retrieving the date and time information from an NTP server involves just a few lines of code.

Take a look at this thread (https://forum.arduino.cc/index.php?topic=631472.msg4276004#msg4276004) from a few weeks ago.  

The code I posted in that thread also shows how to use strftime() to display the date and time once you have gotten the raw information from the NTP server.

Don
Title: Re: Arduino ESP8266 and NTP
Post by: mpopgun on Aug 29, 2019, 05:11 pm
Now that you have resurrected this three year old post you might as well take advantage of the latest changes.  Now that the ESP8266 core has been updated with some of the ESP32 code retrieving the date and time information from an NTP server involves just a few lines of code.

Take a look at this thread (https://forum.arduino.cc/index.php?topic=631472.msg4276004#msg4276004) from a few weeks ago. 

The code I posted in that thread also shows how to use strftime() to display the date and time once you have gotten the raw information from the NTP server.

Don
Very cool! TY
I have a mega with an esp connected via serial 3, using AT commands...I don't think i can use those built in functions can I?

That was always my hurdle, everybody had a card with wifi built in and could use built in fuctions, the code above mine is the only example i could find that used AT commands but they were advanced and formatted the UDP packets.  However the packets coming back from the server didn't have data consistently in the same packets.
Title: Re: Arduino ESP8266 and NTP
Post by: floresta on Aug 29, 2019, 06:32 pm
If there is some reason that you must use the Mega along with the ESP8266 (instead of just using the ESP8266 alone) then you could look into the possibility of doing just the NTP stuff on the ESP8266.  Then you could send the resulting UNIX timestamp to the Mega and do the rest there.

Don