Update: 2021-06-08

Download Sketch

Achtung! EspCore Version 2.6.0 oder höher.

NtpTime.ino

// ****************************************************************
// Sketch Esp8266 WiFi NTP Kalenderzeit
// created: Jens Fleischer, 2020-02-22
// last mod: Jens Fleischer, 2021-06-08
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.6.0 - 3.0.0
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Switch, Sonoff Dual
/******************************************************************
  Copyright (c) 2020 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Automatische Umstellung zwischen Sommer- und Normalzeit.
// Inclusive Abfrage ob die Zeit vom NTP Server geholt werden konnte.
/**************************************************************************************/

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

struct tm tm;         // http://www.cplusplus.com/reference/ctime/tm/

const char* ssid = "Netzwerkname";              // << kann bis zu 32 Zeichen haben
const char* password = "PasswortvomNetzwerk";   // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen
const uint32_t SYNC_INTERVAL = 24;              // NTP Sync Interval in Stunden

const char* const PROGMEM NTP_SERVER[] = {"fritz.box", "de.pool.ntp.org", "at.pool.ntp.org", "ch.pool.ntp.org", "ptbtime1.ptb.de", "europe.pool.ntp.org"};
const char* const PROGMEM DAY_NAMES[] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
const char* const PROGMEM DAY_SHORT[] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
const char* const PROGMEM MONTH_NAMES[] = {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"};
const char* const PROGMEM MONTH_SHORT[] = {"Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"};

extern "C" uint8_t sntp_getreachability(uint8_t);

bool getNtpServer(bool reply = false) {
  uint32_t timeout {millis()};
  configTime("CET-1CEST,M3.5.0/02,M10.5.0/03", NTP_SERVER[0], NTP_SERVER[1], NTP_SERVER[2]);   // Zeitzone einstellen https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
  do {
    delay(25);
    if (millis() - timeout >= 1e3) {
      Serial.printf("Warten auf NTP-Antwort %02ld sec\n", (millis() - timeout) / 1000);
      delay(975);
    }
    sntp_getreachability(0) ? reply = true : sntp_getreachability(1) ? reply = true : sntp_getreachability(2) ? reply = true : false;
  } while (millis() - timeout <= 16e3 && !reply);
  return reply;
}

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\n\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nVerbunden mit: " + WiFi.SSID());
  Serial.println("IP Addresse: " + WiFi.localIP().toString());
  bool timeSync = getNtpServer();
  Serial.printf("NTP Synchronisation %s!\n", timeSync ? "erfolgreich" : "fehlgeschlagen");
}

void loop() {
  char buff[20];                                                   // je nach Format von "strftime" eventuell anpassen
  static time_t lastsec {0};
  time_t now = time(&now);
  localtime_r(&now, &tm);
  if (tm.tm_sec != lastsec) {
    lastsec = tm.tm_sec;
    strftime (buff, sizeof(buff), "%d.%m.%Y %T", &tm);             // http://www.cplusplus.com/reference/ctime/strftime/
    if (!(time(&now) % (SYNC_INTERVAL * 3600))) {
      getNtpServer(true);
    }
    // Verwendungsbeispiele
    Serial.printf("\nLokalzeit:  %s\n", buff);                     // Ausgabe der Kalenderzeit
    Serial.printf("Unix Zeitstempel: %lld\n", (int64_t)time(&now));// Ausgabe Unix Zeitstempel
    Serial.printf("UTC: %.2d:%.2d:%.2d\n", int(time(&now) % 86400L / 3600), int(time(&now) % 3600 / 60), int(time(&now) % 60));  // Ausgabe Koordinierte Weltzeit
    Serial.print("Stunde: "); Serial.println(tm.tm_hour);          // aktuelle Stunde
    Serial.print("Minute: "); Serial.println(tm.tm_min);           // aktuelle Minute
    Serial.print("Sekunde: "); Serial.println(tm.tm_sec);          // aktuelle Sekunde
    Serial.print("Tag: "); Serial.println(tm.tm_mday);             // Tag als Zahl
    Serial.print("Monat: "); Serial.println(tm.tm_mon + 1);        // Monat als Zahl
    Serial.print("Jahr: "); Serial.println(tm.tm_year + 1900);     // Jahr als Zahl
    strftime (buff, sizeof(buff), "Wochentag: %u\n", &tm);         // http://www.cplusplus.com/reference/ctime/strftime/
    Serial.print(buff);                                            // Tag der Woche
    Serial.print("Tag des Jahr: "); Serial.println(tm.tm_yday + 1);// Tag des Jahres
    strftime (buff, sizeof(buff), "Kalenderwoche: %V\n", &tm);     // http://www.cplusplus.com/reference/ctime/strftime/
    Serial.print(buff);                                            // Kalenderwoche
    Serial.println(DAY_NAMES[tm.tm_wday]);                         // aktueller Wochentag
    Serial.println(MONTH_NAMES[tm.tm_mon]);                        // aktueller Monat
    Serial.println(DAY_SHORT[tm.tm_wday]);                         // aktueller Wochentag (Abk.)
    Serial.println(MONTH_SHORT[tm.tm_mon]);                        // aktueller Monat (Abk.)
    Serial.printf("Name der Zeitzone: %s\n", _tzname[0]);
    Serial.printf("Name der Sommerzeitzone: %s\n", _tzname[1]);
    Serial.println(tm.tm_isdst ? "Sommerzeit" : "Normalzeit");
  }
}
13 Kommentare
Andreas ✪ ✪ ✪ 05.08.2020
Super!
Vielen Dank für den Code.
Ich benutze ihn, um festzustellen, ob die Türen an meiner Garage nach 22:00 Uhr verschlossen sind.

Nur mal eine Frage: Wenn, aus welchem Grund auch immer, der ESP die WLAN-Verbindung verliert,
baut sich diese dann von allein wieder auf?

Oder muss ich da in meinem Code irgendwie abfragen, ob WLAN verfügbar, und wenn nicht, dann neu aufbauen?

Grüße aus Thüringen.
Andreas

Antwort:
Nach meiner Erfahrung klappt das nicht immer!
Nach einem Stromausfall braucht der Router viel länger zum starten als der Esp8266, deswegen habe ich in meinem Heizungssketch eine Routine dafür eingebaut.

Gruß Fips aus Th.
Stefan ❘ 11.06.2020
Funktioniert leider nicht. Das Skript lässt sich nicht kompillieren und es kommt in der Zeile wo die Zeitzone eingegeben wird die Meldung:
"invalid converation from const char to long int" [-fpermisse]
was auch immer das bedeuten mag

Schöne Grüße
Stefan

Antwort:
Es funktioniert bei dir nicht!
Bei mir schon.
Du versuchst den Sketch mit einer EspCoreVersion vor 2.6.0. zu kompillieren.

Wenn es dir nicht möglich ist eine aktuellere CoreVersion zu benutzen dann ersetze die Zeile mit den folgenden beiden.
configTime(0, 0, NTP_SERVER[1]);
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);

Gruß Fips
MarcE206 ✪ ✪ ✪ 07.06.2020
Servus!

Vielen Dank für dein Programm. Funktioniert soweit bis auf:
Als Monat wird mir richtig "6" angezeigt - in Textform aber "Juli". Ist es hier evtl. wie bei den Wochentagen, das die Zuordnungstabelle mit "Dezember"beginnen müsste?

Schöne grüße aus Südhessen!

Antwort:
Da hat sich ein Fehler eingeschlichen.
Danke für deine Aufmerksamkeit.

Gruß Fips
Kommentar eintragen

*