mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ntp Server antwortet nicht


Autor: dost0011 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich benutze den ESP8266. Wenn ich nun den NTP Server de.pool.ntp.org 
anfrage, bekomme ich keine Antwort "no packet yet". Was mache ich falsch 
oder ist der Server komplett überlastet?
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
{
  Serial.println("sending NTP packet...");
  // 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;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  udp.beginPacket(address, 123); //NTP requests are to port 123
  udp.write(packetBuffer, NTP_PACKET_SIZE);
  udp.endPacket();
}

unsigned long Get_NTP_Time()
{
  //get a random server from the pool
  WiFi.hostByName(ntpServerName, timeServerIP); 

  sendNTPpacket(timeServerIP); // send an NTP packet to a time server
  // wait to see if a reply is available
  delay(3000);
  
  int cb = udp.parsePacket();
  if (!cb) {
    Serial.println("no packet yet");
    return(0);
  }
  else {
    Serial.print("packet received, length=");
    Serial.println(cb);
    // We've received a packet, read the data from it
    udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

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

    // now convert NTP time into everyday 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:
    Serial.print("NTP:");
    Serial.println(epoch);
    return(epoch); 
  }
}

[Mod: Code in C-Tags eingeschlossen]

: Bearbeitet durch Moderator
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dost0011 schrieb:
> Wenn ich nun den NTP Server de.pool.ntp.org anfrage, bekomme ich keine
> Antwort

Du machst ja auch kein NTP, sondern nur SNTP (Simple ...). Das kann 
keinen Pool nach der Zeit fragen, sondern nur einzelne Server.

Nimm gezielt einen NTP-Server und es sollte gehen.

Autor: Maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dost0011 schrieb:
>   delay(3000);

Das ist bestenfalls unschön. Pakete sollten verarbeitet werden, wenn sie 
ankommen.
>   int cb = udp.parsePacket();

Was macht denn diese Funktion und was gibt sie zurück?

Laß doch mal zum Testen einen lokalen Server laufen und schaue Dir an, 
was im Netzwerk passiert.

de.pool.ntp.org ist übrigens ein einzelner Server, wenn auch immer ein 
anderer.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dost0011 schrieb:
> sendNTPpacket(timeServerIP); // send an NTP packet to a time server
>   // wait to see if a reply is available
>   delay(3000);
>
>   int cb = udp.parsePacket();

Das ist unschön. UDP ist ein verbindungsloses Protokoll. Du kannst keine 
unmittelbare Antwort erwarten. Diese kommt irgendwann... oder auch gar 
nicht.

Ich mache das beim ESP so, dass ich einmal den Request abfeuere und dann 
in loop() zyklisch frage, ob was über UDP reinkommt.
void
loop() 
{
    ... // some other stuff
    ntp_poll_time ();                
    ... // some other stuff
}

wobei:
void
ntp_poll_time (void)
{
    int packetsize;

    packetsize = ntp_udp.parsePacket();

    if (packetsize)
    {
        ntp_udp.read(ntp_packet_buffer, packetsize);                   // read packet

        if (packetsize == NTP_PACKET_SIZE)
        {
            unsigned long hi = word(ntp_packet_buffer[40], ntp_packet_buffer[41]);
            unsigned long lo = word(ntp_packet_buffer[42], ntp_packet_buffer[43]);
            unsigned long secsSince1900 = hi << 16 | lo;

            Serial.print ("TIME ");
            Serial.println(secsSince1900);
        }
        else
        {
            Serial.println("- wrong packet size");
        }

        Serial.flush ();
    }
}

Den kompletten Source findestg Du unter 
https://www.mikrocontroller.net/svnbrowser/wordclo...

Autor: dost0011 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also mit dem Delay habe ich rumgespielt, ob es besser oder schlechter 
wird. Spielt keine Rolle, ich kann es auch rausnehmen.
Es kommt einfach keine Antwort zurück - egal, ob ich warte oder nicht.
Kennt ihr das Phänomen?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Du machst ja auch kein NTP, sondern nur SNTP (Simple ...). Das kann
> keinen Pool nach der Zeit fragen, sondern nur einzelne Server.

Der DNS-Name de.pool.ntp.org liefert bei Übersetzung in eine IP-Adresse 
eine von mehreren Adressen und ist daher in Programmen, die DNS-Namen 
verstehen, üblicherweise direkt nutzbar. Oder hat die ESP-Lib spezielle 
Probleme damit?

: Bearbeitet durch User
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Oder hat die ESP-Lib spezielle Probleme damit?

Ich hatte es damals beim ESP8266 mit de.pool.ntp.org und SNTP nicht 
hinbekommen. Ich hatte dann als Server 192.53.103.103 (ntp3.ptb.de) 
probiert. Das ging sofort. Deshalb habe ich es dann auf den Pool im 
Zusammenhang mit SNTP geschoben.

Eben habe ich es aber nochmal (unter Linux, habe gerade keinen ESP 
parat) mit einem SNTP-Client probiert:
$ sntp de.pool.ntp.org
sntp 4.2.8p11@1.3728-o (1)
2018-05-18 13:29:31.010213 (-0100) +0.000558 +/- 0.023336 de.pool.ntp.org 212.18.3.19 s2 no-leap

Das funktioniert. Kann sein, dass es damals ein anderes temporäres 
Problem gab. Ich nehme daher meine Behauptung zurück ;-)

Ich werde es heute abend aber trotzdem nochmal auf dem ESP ausprobieren.

: Bearbeitet durch Moderator
Autor: dost0011 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt mal einen festen Server (time.nist.gov NTP server) 
angefragt:

sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet

Bin ratlos...

Autor: dost0011 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
IPAddress timeServerIP(192,53,103,103);

funktioniert auch nicht. Liegt vermutlich nicht an den tausenden Servern 
sondern an meinem Code ;-)

Beitrag #5426364 wurde vom Autor gelöscht.
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dost0011 schrieb:
> IPAddress timeServerIP(192,53,103,103);
>
> funktioniert auch nicht.

Dies wollte ich Dir gerade auch vorschlagen, hätte ja sein können, dass 
die Namensauflösung aus irgendeinem Grund nicht klappt. Obwohl, Du 
könntest Dir ja mal die IP-Adresse ausgeben lassen, die von 
WiFi.hostByName(ntpServerName, timeServerIP) ermittelt wird.

> Liegt vermutlich nicht an den tausenden Servern
> sondern an meinem Code ;-)

Den habe ich schon mit meinem Code

  https://www.mikrocontroller.net/svnbrowser/wordclo...

verglichen. Ich kann keinen größeren Unterschied erkennen, bis auf das 
Delay. Wie gesagt: Schick das Paket einmal ab und führe den Aufruf von 
udp.parsePacket() & Co. zyklich in der Hauptschleife aus, ich hatte das 
oben schon so skizziert.

: Bearbeitet durch Moderator
Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Wie gesagt: Führe den Aufruf von udp.parsePacket() & Co. zyklich
> in der Hauptschleife aus, ich hatte das oben schon so skizziert.

Wobei der ESP eigentlich für ereignisorientiertes Arbeiten ausgelegt 
ist, nicht für sequentielles Arbeiten mit Warterei. Also nicht
   Anfrage senden
   warten
   Antwort auswerten
sondern
   Anfrage senden
und unabhängig davon
   Wenn ein UDP Paket eintrifft, dann
      Paket auswerten

Damit habe ich bessere Erfahrungen gemacht. Allerdings war das in LUA.

: Bearbeitet durch User
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Wobei der ESP eigentlich für ereignisorientiertes Arbeiten ausgelegt
> ist, nicht für sequentielles Arbeiten mit Warterei.

Dann passt das ja zu meinem Vorschlag.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nur am Rande: zu den ESP8266 Extensions, die Bestandteil des SDK sind, 
gehört auch die nahezu vollständige Implemetierung der Posix-Time-Lib.
#include <ESP8266WiFi.h>
#include <time.h>

setup()
{
// Start Time service.
  configTime(timezone * 3600, 0, "pool.ntp.org", "time.nist.gov");
}

Mit
  time_t now = time(nullptr);
  struct tm * timeinfo;
  timeinfo = localtime(&now);
füllt man z.B. die Struktur.
 Serial.printf("%02d:%02d:%02d",timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
  Serial.println();  

Es läuft komplett asyncron im Hintergrund, aktualisiert wird per default 
alle Stunde.

Genaueres kann man sich z.B. hier raussuchen.
https://github.com/esp8266/Arduino/blob/master/too...

Gruß aus Berlin
Michael

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und du bist dir sicher, dass die Pakete auch ins Internet gehen und die 
Antworten auch richtig weitergeleitet werden? Nicht dass ne Firewall 
oder fehlendes NAT dir dazwischenfunken ...

Autor: fchk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dost0011 schrieb:

>   packetBuffer[0] = 0b11100011;   // LI, Version, Mode

Das ist falsch. Lies den Standard RFC4330.

LI: Bit 7-6, hier 3 (unsynchronisiert), ok
Version: Bit 2-0, hier 3, auch nicht falsch. Ich würde hier Version 1 
nehmen.
Mode: Bit 5-3, hier 4, und das ist FALSCH.
Du musst hier als Client eine 3 reinschreiben, der Server muss mit 
Mode=4 antworten. Mode=5 ist für Broadcasts.

fchk

Autor: oszi40 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
foobar schrieb:
> Nicht dass ne Firewall
> oder fehlendes NAT dir dazwischenfunken ...

Bevor man große Sprünge macht, sollte man sich in kleinen Schritten 
vergewisseren, daß die einfachen Sachen schon mal funktionieren?
Ping wird ausgeführt für de.pool.ntp.org [195.201.19.162] mit 32 Bytes 
Daten:
Antwort von 195.201.19.162: Bytes=32 Zeit=76ms TTL=53 usw.

Beitrag #5426617 wurde vom Autor gelöscht.
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fchk schrieb:
> Du musst hier als Client eine 3 reinschreiben, der Server muss mit
> Mode=4 antworten. Mode=5 ist für Broadcasts.

Ich habe das mal unter Linux ausprobiert.

Sowohl
   packetBuffer[0] = 0b11100011;  // vom TO verwendet
als auch
   packetBuffer[0] = 0b00011011;  // findet man in diversen Quellen
                                  // LI = 0, NV = 3, MODE = 3

werden von us.pool.ntp.org, de.pool.ntp.org und ntp3.ptb.de ohne Mucken 
geschluckt. Offenbar interessiert sich keiner für die LI, NV und 
MODE-Bits. Naja, nicht ganz: bei packetBuffer[0] = 0x00 antwortet keiner 
mehr.

Ich habe sonst überhaupt keine Felder im Paket mehr gefüllt, also alles 
bei 0 gelassen (durch memset).

Verwendeter Source:

https://lettier.github.io/posts/2016-04-26-lets-ma...

: Bearbeitet durch Moderator
Autor: dost0011 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, jetzt habe ich folgendes gemacht:
Bei den Arduino Beispiel Sketchen gibt es unter ESP8266Wifi-->NTPClient. 
Diesen Sketch habe ich auf den ESP8266 geladen. Er verbindet sich 
einwandfrei mit dem Internet und dann bekomme ich folgenden Output

sending NTP packet...
no packet yet
sending NTP packet...
packet received, length=48
Seconds since Jan 1 1900 = 3735663005
Unix time = 1526674205
The UTC time is 20:10:05
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet

Das bedeutet, dass es einmal funktioniert hat und dann nicht mehr. Das 
reicht natürlich nicht. Wenn ich einen Reset mache, kann es sein, dass 
er für 10min (dann habe ich abgebrochen) kein einziges Paket empfangen 
habe...

Anpingen kann ich den Server vom Rechner aus.
Was ist da los? Kann mich erinnern, dass das vor einem Jahr sofort und 
zuverlässig funktioniert hat...

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dost0011 schrieb:
> Das bedeutet, dass es einmal funktioniert hat und dann nicht mehr.

Kann es sein, dass der Timeserver dicht macht, wenn Du ihn so zuknallst? 
Wie groß sind die zeitlichen Abstände?

Autor: dost0011 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
alle 2s. Ich würde ja nicht knallen, wenn er mal antworten würde :-)

Autor: Jim Meba (turboj)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum nimmst Du nicht Deinen eigenen Server? Den ntpd gibts notfalls 
auch für Windows, und 'nen Wireshark kann man so auch gleich mit 
ansetzen.

Autor: Stephan Dorenkamp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Gerät, welches ich bauen möchte, kommt in einer Umgebung zum 
Einsatz, wo es keinen weiteren Rechner gibt. Kann doch nicht sein, dass 
man einen eigenen Zeitserver benötigt, weil die vorhandenen nicht 
antworten. Ich habe doch bestimmt ein ganzes anderes Problem...

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den lokalen Server benutzt du zum Testen und Debuggen. Wenn's lokal 
läuft, kannst du mit den öffentlichen weitermachen.

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
foobar schrieb:
> Den lokalen Server benutzt du zum Testen und Debuggen.

Vor allem kannst Du dort problemlos einen Wireshark aktivieren oder 
tcpdump laufen lassen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.