Uhrzeit von der Fritz.Box

Hallo.

Ich möchte die Uhrzeit von meiner Fritzbox holen und die als lokale Uhrzeit verwenden.
Dazu habe den folgenden Code im Netz gefunden, welcher auch grundsätzlich funktioniert.

#include <WiFi.h>
#include "time.h"

const char* ssid       = "sdg";
const char* password   = "sdg";

const char* ntpServer = "192.168.114.321";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;


void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Fehler beim Zeit abruf");
    return;
  }
  Serial.println(&timeinfo, "%H:%M:%S");
}

void setup()
{
  //Serial
  Serial.begin(115200);
  
  //WiFi Verbindung Start
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" CONNECTED");





  
  //Uhrzeit holen
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();






  //WiFi Verbindung Snde
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}

void loop()
{
  //jede Sekunde die Uhr ausgeben
  delay(1000);
  printLocalTime();
}

Der WiFi Teil ist mir klar.

So nun zu den Fragen der Uhrzeit :slight_smile:

  1. In void setup wird die Uhrzeit einmalig von der Fritzbox beim Start geholt?
  2. void printLocalTime die Funktion kann ich nicht nachvollziehen, kann jemand erklären was da passiert?
  3. Kann man die Uhrzeit auch in einer globalen Variable speichern, da ich dies nicht nur Serial ausgeben möchte (OK, kann man, aber wie).

Danke für die Hilfe.

hd

  1. Üblicherweise holt sich ein Computer die aktuelle Zeit 1 mal, und zählt sie dann mit seiner eigenen Zeitbasis weiter.

  2. Vermutlich kommt die spezielle println() Ausgabe-Konvertierung für timeinfo aus einer C Standardbibliothek, siehe time.h.

  3. Eine globale timeinfo Struktur kann benutzt werden, muß aber vor jeder Benutzung aktualisiert werden - Muster in printLocalTime().

IMO kommt es drauf an, wofür Du die Uhrzeit brauchst. Für Steuerungszwecke reichen die millis(), wenn man sich ggf. dazu den Offset zur aktuellen Uhrzeit merkt - eben einmal beim Systemstart. So läßt sich leichter mit Zeiten rechnen als mit Stunden, Minuten und Sekunden aus timeinfo.

Hallo und Danke.

Also so geht es. Zahlenformat noch nicht angepaßt.

#include <WiFi.h>
#include "time.h"

const char* ssid       = "dfsa";
const char* password   = "dfsd";

const char* ntpServer = "de.pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;

struct tm timeinfo;

void printLocalTime()
{
  if(!getLocalTime(&timeinfo)){
    Serial.println("Uhrzzeit konnte nicht geladen werden!");
    return;
  }
}

void setup()
{
  Serial.begin(115200);
  
  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println(" CONNECTED");


  
  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();




  //disconnect WiFi as it's no longer needed
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}

void loop()
{
  printLocalTime();                               //Aktuelle Uhrzeit holen
  
  Serial.print("(");
  Serial.print(timeinfo.tm_wday);                 //Wochentag in Zahl
  Serial.print(")   ");
  Serial.print(timeinfo.tm_mday);                 //Tag
  Serial.print(".");
  Serial.print(timeinfo.tm_mon + 1);              //Monat
  Serial.print(".");
  Serial.print(timeinfo.tm_year + 1900);          //Jahr
  Serial.print(" --- ");  
  Serial.print(timeinfo.tm_hour);                 //Stunde
  Serial.print(":");
  Serial.print(timeinfo.tm_min);                  //Minute
  Serial.print(":");
  Serial.println(timeinfo.tm_sec);                //Sekunde

  delay(1000);
}

Aber ich sehe es richtig, das die Uhrzeit nur einmal beim Start aktualisiert wird.
Wollte ich das öfters, müsste ich

  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();

in loop z.B. einmal am Tag aufrufen. Natürlich mit aktiven WiFi.

Oder?

configTime() dürfte einmalig reichen, danach reicht getLocalTime().

Wenn da ntpServer vorkommt, dann hat die Fritz!Box nix mit der Zeit zu tun, die kommt dann von einem Zeitserver aus dem Internet.

Die Fritz!Box hat einen NTP-Server.

Gruß Tommy

DrDiettrich:
configTime() dürfte einmalig reichen, danach reicht getLocalTime().

Bist Du sicher, dass das so ist.

A) Ohne Wifi könnte er die Uhrzeit nicht holen.
B) Dann bräuchte das beim void setup doch auch nicht gemacht werden?!

DrDiettrich:
Wenn da ntpServer vorkommt, dann hat die Fritz!Box nix mit der Zeit zu tun, die kommt dann von einem Zeitserver aus dem Internet.

Aber ich gebe doch die Fritzbox, die einen ntpServer hat, ja an.

const char* ntpServer = "de.pool.ntp.org";

Ups, habe kopiert und den ntpServer nicht geändert :slight_smile: Sollte so sein:

const char* ntpServer = "192.168.134.1";

Ich hole die Zeit einmal am Tag von der Fritzbox. Das reicht bei Raumtemperatur für eine hohe Genauigkeit.

Gruß Fips

Habe es jetzt so gemacht, kann mal jemand schauen ob das in Ordnung ist. Danke.

#include <WiFi.h>
#include "time.h"

const char* ssid       = "ssid";
const char* password   = "pass";

const char*           ntpServer                         = "192.168.134.1";
const long            gmtOffset_sec                     = 3600;
const int             daylightOffset_sec                = 0;                                                      //Sommerzeit / Winterzeit (wird aber nicht gebraucht da die Zeit vom ntpServer kommt)

const uint32_t        ntpServer_TimerCounter            = 60000;                                                  //Zeit festlegen in ms, wann die Uhrzeit und das Datum um ntpServer geholt werden soll
uint32_t              ntpServer_TimerComparison         = 0;                                                      //Vergleichswert für den Zähler(Startwert muss 0 sein)        
  
char                  ntpDate[50];                                                                                //Datum
char                  ntpTime[50];                                                                                //Uhrzeit
struct                tm timeinfo;                                                                                //für time.h 



void setup()
{
  Serial.begin(115200);
  
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println(" CONNECTED");

  ntpServer_TimerComparison = millis() + 50000;                                                          //damit die IF Bedinung das erstmal auch WAHR ist  
}



void loop()
{
  LocalTime();                                                                                          //Aktuelle Uhrzeit und das Datum holen
  Serial.println(ntpDate);
  Serial.println(ntpTime);
  delay(1000);
}



void LocalTime()
{
  //jede Stunde die Uhrzeit und das Datum vom ntpServer holen
  if (millis() - ntpServer_TimerComparison >= ntpServer_TimerCounter)
  {
    Serial.println("Uhrzzeit und Datum wird aktualisiert...");
    ntpServer_TimerComparison = millis();
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);                                           //Verbindung zum ntpServer
  }
  
  if(!getLocalTime(&timeinfo))
  {
    Serial.println("Uhrzzeit und Datum konnte nicht aktualisiert werden!");
    return;
  }

  snprintf (ntpTime, 50, "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec + 1);
  snprintf (ntpDate, 50, "%02d.%02d.%0002d (%1d)", timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year + 1900, timeinfo.tm_wday);  
}

Derfips:
Ich hole die Zeit einmal am Tag von der Fritzbox. Das reicht bei Raumtemperatur für eine hohe Genauigkeit.

Esp8266 & Esp32 Arduino

Gruß Fips

Danke!
Werde ich mir anschauen, aber wenn mein CODE in Ordnung ist würde ich den lassen.
Kopieren wäre zu einfach :slight_smile:

hd458:
Kopieren wäre zu einfach :slight_smile:

Davon war keine Rede!

Gruß Fips

Kannst Du Dir meinen Code mal anschauen?

hd458:
const uint32_t ntpServer_TimerCounter = 60000;
//jede Stunde die Uhrzeit und das Datum vom ntpServer holen

Klar, anschauen kann ich den Sketch!

Mir ist aufgefallen, das du deine Kommentare anpassen solltest!

Gruß Fips

Danke!

Ne den Counter muss ich anpassen. Hatte ich zum testen runter gesetzt.

Sonst in Ordnung?

PS Schöne Projekt die Du auf Deiner Seite hast.

hd458:
Sonst in Ordnung?

Tut er denn nicht was du erwartest?

%0002d

Das ist erstmal falsch.

Ausserdem frage ich mich ob du Jahre erwartest die du mit führenden Nullen aufüllen musst?

Warum verwendest du nicht einfach strftime() ?

Gruß Fips

Hallo,

eigendlich bin ich der Meinung das bei Verwendung von configtime() mit der time.h automatisch eine Syncronisierung mit dem NTP Server stattfindet. die Zeit lässt sich wohl einstellen .

#define SNTP_UPDATE_DELAY 3600000

link

warum mehrfach aufrufen ?

Bei mir sieht das so aus.

void NTPstart() {
  configTime(0, 0, "192.168.178.1"); // locale Fritzbox
  setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);  // locale Zeit einstellen mit Sommerzeit

  Serial.println("Waiting for time");
  while (!time(nullptr)) {
    Serial.print(".");
    delay(1000);

  }
 
}

Das läuft jetz so seit Monaten so und die Zeit stimmt. Probleme scheint es dann zu geben wenn der NTP Server nicht erreichbar ist. Aber bei meiner FritzBox kommt das ehr selten vor. Und wenn dann ist auch das Wlan weg.

Heinz

Guten Abend Heinz und Fips,

ich hoffe es ist okay wenn ich meine Frage hier drunter stelle, wenn es nicht gewünscht ist eröffne ich einen eigenen Thread. Ich nutze bisher die TimeLib.h von Paul Stoffregen, eine Lib für die RTC sowie eine separate für die NTP Abfrage. Zusätzlich prüfe ich die Sommerzeit mit der Funktion von jurs.

Ich hab es jetzt soweit laufen nur mit der Time.h den NTP Abruf zu starten und die Systemzeit zu stellen - inkl Sommerzeit Prüfung.
Auf der verlinkten Seite von Heinz steht in einem Kommentar "/* change system time and/or the update the RTC clock */". Nur leider finde ich gar keine Dokumentation zu der hauseigenen Lib.

Ist es euch bekannt, ob ich mit der Time.h direkt die RTC updaten kann? Es ist in meinem Fall eine DS3231. Über Tipps würde ich mich sehr freuen.

Ich wünsche noch einen schönen Abend :-)!

Liebe Grüße,
Björn

Hallo,

warum willst Du zusätzlich eine RTC verwenden? Kann man sicher machen. Mein Link sollte nur einen Hinweis darauf geben das eine automatische Syncronisierung mit dem NTP Server in bestimmten Zeitabständen stattfindet und wo man das einstellen kann.

Hier mal ein Beispiel das ich so ähnlich häufig findet. Ist nur das Minimum enthalten.

zur time.h lib link

Heinz

#include <ESP8266WiFi.h>
#include <time.h>

const char* ssid = "xxxx";
const char* password = "yyy";

int year;
byte month, day, hour, minute, second;
uint32_t altzeit;

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("\nConnecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  configTime(0, 0, "192.168.178.1"); // locale Fritzbox
  //configTime(0, 0, "pool.ntp.org", "time.nist.gov");
  // setenv("TZ", "GMT0BST,M3.5.0/01,M10.5.0/02",1);

  setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);  // locale Zeit einstellen mit Sommerzeit

  Serial.println("\nWaiting for time");
  while (!time(nullptr)) {
    Serial.print(".");
    delay(1000);
  }



  Serial.println("");
}

void loop() {

  if(millis() - altzeit >= 1000){
    altzeit = millis();
    readtime(); // aktualisieren
    Serial.printf("%02u-%02u-%4u\n", day, month, year);
    Serial.printf("%02u:%02u:%02u\n", hour, minute, second);

  }
}
// Datum und zeit auslesen
void readtime() {
  time_t now = time(nullptr);
  struct tm*timeinfo;
  time(&now);
  timeinfo = localtime(&now);
  year = 1900 + timeinfo->tm_year;
  month = 1 + timeinfo->tm_mon;
  day = timeinfo->tm_mday;
  hour = timeinfo->tm_hour;
  minute = timeinfo->tm_min;
  second = timeinfo->tm_sec;


}

Guten Abend Heinz,

Rentner:
warum willst Du zusätzlich eine RTC verwenden? Kann man sicher machen.

Ich benutze die RTC an meiner WordClock, deshalb wäre es interessant für mich mit der Time.h Lib direkt auch per NTP Abruf die RTC-Zeit zu aktualisieren.

Im Moment ziehe ich 1x im Monat (oder beim Neustart) die NTP Zeit (UTC) und speicher diese auch als UTC Zeit auf der RTC. Die Systemzeit wird alle 15 Minuten von der RTC ausgelesen und entsprechend auf die Lokale Uhrzeit angepasst (inkl. Sommerzeitprüfung). Würde gerne die benötigten Libs ausdünnen - daher kommt mein Interesse :-).

Vielen Dank für Deinen Beispiel-Code ich versuche, dass mal auf meine Bedürfnisse umzubauen.

Sorry an den TO, dass ich meine Frage in deinen Thread gepackt habe!

Liebe Grüße,
Björn