Making a library for a NTP - timeserver request

I would like to synchonize my board with a NTP server and use a library for this. There are some libraries in the web but they have all the same problem: They use a fixed IP and as NTP servers change regularly my project want last for long =(

Therefore I put some code parts thogether I found on differnt places. Now I have a sketch which can resolve the DNS and works fine :slight_smile:

Now comes my problem. I want to put this into a library and failed by far :0 :0 :0. I can built simple libraries and don't require a basic instruction but when the compiler comes where I need to initialize the DNS costructor : Error Error.......

Can some one help me? Here is my sketch:

#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Dns.h>


DNSClient DNS;
char ntpServer[] = "0.ch.pool.ntp.org";
IPAddress timeServer;
EthernetUDP Udp;
const int NTP_PACKET_SIZE= 48;
byte packetBuffer[ NTP_PACKET_SIZE];  

IPAddress ip(192,168,0,205);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xA5 };
IPAddress gateway(192,168,0,2);
IPAddress subnet(255,255,255,0);



void setup() {
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  Serial.begin(9600);

  DNS.begin(gateway);
  Udp.begin(8888);
  
  Serial.println(NTP_server_answer());
}

void loop() {
}


unsigned long NTP_server_answer() {
  unsigned long epoch = 0;
  
  DNS.getHostByName(ntpServer,timeServer);
  sendNTPpacket(timeServer);
  delay(1000);  
  if ( Udp.parsePacket() ) {  
    Udp.read(packetBuffer,NTP_PACKET_SIZE);
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    epoch = secsSince1900 - 2208988800UL;    
  }
  return epoch;
}

unsigned long sendNTPpacket(IPAddress& address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  packetBuffer[0] = 0b11100011;
  packetBuffer[1] = 0;
  packetBuffer[2] = 6;
  packetBuffer[3] = 0xEC;
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  Udp.beginPacket(address, 123);
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

Here is a topic that has NTP using dns to get the ip for the server.
http://arduino.cc/forum/index.php/topic,137789.0.html
Reply #7 is my basic code.

Use pool.ntp.org

"The pool is being used by millions or tens of millions of systems around the world. It's the default "time server" for most of the major Linux distributions and many networked appliances"

I want to put this into a library and failed by far

Sounds like a great idea. What did that library look like? What errors did you get?

How much of the internet stuff did you plan to move into the library? How much did you plan to leave in the sketch? In other words, is the sketch still to be able to use DNS, UDP, etc.?

@makvr, SurferTim: The code or the address isn't the problem.

I aim is to put as much as possible in the library here I struggle. My code looks like this:

ntp.h:

/*
  NTP -  Libary to contact an NTP server and read the NTP signal
*/

// ensure this library description is only included once
#ifndef NTP_h
#define NTP_h

#include "Arduino.h"
#include <SPI.h>
#include <EthernetUdp.h>
#include <Dns.h>



class NTP 

{
  const char ntpServer[];
  const int NTP_PACKET_SIZE;

  public:
    NTP();
    void begin();
    unsigned long NTP_server_answer();

  private:
    byte packetBuffer[ NTP_PACKET_SIZE];
    IPAddress timeServer;
    unsigned long sendNTPpacket(IPAddress& address);
};

#endif

NTP.ccp

/*
  NTP -  Libary to contact an NTP server and read the NTP signal
*/


#include "NTP.h"



// Constructor /////////////////////////////////////////////////////////////////


NTP::NTP():

  char ntpServer[]("0.ch.pool.ntp.org"),
  int NTP_PACKET_SIZE (48);
{
  DNSClient DNS;
  EthernetUDP Udp;
}

// Public Methods //////////////////////////////////////////////////////////////

void NTP::begin(IPAddress gateway)
{
  DNS.begin(gateway);
  Udp.begin(8888); 
}

unsigned long NTP::NTP_server_answer() {
  unsigned long epoch = 0;
  
  DNS.getHostByName(ntpServer,timeServer);
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);  
  if ( Udp.parsePacket() ) {  
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    epoch = secsSince1900 - 2208988800UL;  // Heute    
  }
  return epoch;
}


// Private Methods /////////////////////////////////////////////////////////////

unsigned long NTP::sendNTPpacket(IPAddress& address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  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
   packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

and the test sketch:

#include <SPI.h>
#include <Ethernet.h>
#include <NTP.h>



IPAddress ip(192,168,0,205); // IBoard pro
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xA5 };  // IBoard pro
IPAddress gateway(192,168,0,2);
IPAddress subnet(255,255,255,0);

NTP Zeit;

void setup() {
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  Serial.begin(9600);
  Zeit.begin();
  
  Serial.println(Zeit.NTP_server_answer());
}

void loop() {
}
NTP::NTP():

  char ntpServer[]("0.ch.pool.ntp.org"),
  int NTP_PACKET_SIZE (48);
{
  DNSClient DNS;
  EthernetUDP Udp;
}

Local variables that go out of scope when the constructor ends don't seem all that useful.

Why are they not class members?

Where does timeServer get assigned a value?

The global declaration of NTP_PACKET_SIZE and the class member NTP_PACKET_SIZE are not the same variable. Which one has precedence in a class method? The global declaration of ntpServer and the class member ntpServer are not the same variable.

Declaring an array of size NTP_PACKET_SIZE in the header, when the size is the default value of 0, doesn't seem all that useful. It's probably just as well that you never try to initialize the 0 element class member array ntpServer.