Go Down

Topic: Arduino ESP8266 and NTP (Read 35272 times) previous topic - next topic

pixelk

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                    ..........



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



pixelk

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

phaseform

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;
}

atheec

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 !!!!!!!!!!!!!!

adminarduinocc

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.

Mark Bramwell

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.

adminarduinocc

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?

adminarduinocc

#22
Oct 25, 2015, 12:26 am Last Edit: Oct 25, 2015, 12:30 am by adminarduinocc
Working code with this library:


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");
  }

}

Mark Bramwell

#23
Oct 26, 2015, 02:14 am Last Edit: Oct 26, 2015, 02:31 am by Mark Bramwell
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)

adminarduinocc

#24
Oct 26, 2015, 09:29 am Last Edit: Oct 26, 2015, 09:30 am by adminarduinocc
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

Mark Bramwell

#25
Oct 26, 2015, 04:30 pm Last Edit: Oct 26, 2015, 04:32 pm by Mark Bramwell
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



adminarduinocc

#26
Oct 31, 2015, 06:17 pm Last Edit: Oct 31, 2015, 06:18 pm by adminarduinocc
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");
   }

twim

Check out this: UdpNTPClient
It is basically the same example of the standard Arduino WiFi library adapted for the WiFiEsp library that works with ESP8266 module.

adminarduinocc

#28
Feb 03, 2016, 08:41 am Last Edit: Feb 04, 2016, 08:55 am by adminarduinocc
Check out this: UdpNTPClient
It is basically the same example of the standard Arduino WiFi library adapted for the WiFiEsp library that works with ESP8266 module.
Good job! Thanks!
Will this code work without Arduino board? For example, if you connect Esp8266 and tm1637?

torquato

Check out this: UdpNTPClient
It is basically the same example of the standard Arduino WiFi library adapted for the WiFiEsp library 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

Go Up