Skip to content

Instantly share code, notes, and snippets.

@haeshh
Created May 14, 2021 11:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haeshh/b0c1b0831af7c0d4636878793f57d19d to your computer and use it in GitHub Desktop.
Save haeshh/b0c1b0831af7c0d4636878793f57d19d to your computer and use it in GitHub Desktop.
ESP32: Programmkonfiguration speichern mit der Preferences-Bibliothek (siehe https://unsinnsbasis.de/esp32-preferences/)
/* ------------------------------------------------------------
* Konfigurationsdaten für den WLAN-Zugang aus NVS lesen
*
* Name des NVS-Namespace: wifi
* Daten:
* - ssid: Name des WLANs
* - wifipwd: WLAN-Passwort
* - hostname: "sprechender" Name des Geräts im Netzwerk
* - timeout: max. Zeit (in Sekunden) für Verbindungsaufbau
* - ntpserver: Name des NTP-Servers
* - ntpfreq: Intervall (in Stunden) für Abfrage des NTP-Servers
* - timezone: Zeitzone
*
* 2021-05-09 Heiko / unsinnsbasis.de
* ------------------------------------------------------------ */
/* ------------------------------------------------------------
* Einbinden der benötigten Bibliotheken,
* Defintion von Konstanten,
* Anlegen der Datenobjekte
* ------------------------------------------------------------ */
// Übertragungsrate für Ausgabe zum seriellen Monitor
#define SERIAL_BAUDRATE 115200
#include <Preferences.h>
// Datenobjekt für einen NVS-Namespace
Preferences prefs;
// Name des Namespace für die WiFi-Konfigurstion
const char* wifi_namespace = "wifi";
/* ------------------------------------------------------------
* WiFi (NTP) und Datum/Zeit
* ------------------------------------------------------------ */
#include <WiFi.h>
#include <time.h>
// Default-Werte für einige Einstellungen
// werden genutzt, wenn kein passender Wert im NVS gefunden wid
#define DEFAULT_WIFI_TIMEOUT 60
#define DEFAULT_NTP_SERVER PSTR("de.pool.ntp.org")
#define DEFAULT_TIMEZONE PSTR("CET-1CEST,M3.5.0,M10.5.0/3") // Europa/Berlin
#define DEFAULT_NTP_FREQ 24
int ntp_freq;
/* Timer für verschiedene Aufgaben:
* - alle n Stunden die Uhrzeit per NTP-Abfrage aktualisieren
* - ggf. weitere Timer, z.B. alle n Sekunden Sensoren abfragen,
* eine Anzeige aktualisieren etc.
*/
unsigned long timer_ntp=0, //NTP-Server abfragen
timer_time=0; // Uhrzeit anzeigen
/* ------------------------------------------------------------ */
void setup() {
bool f_error = false; //Fehler-Flag
Serial.begin(SERIAL_BAUDRATE);
delay(500);
// Namespace zum Lesen öffnen
if (!prefs.begin(wifi_namespace, true)) {
Serial.println("Fehler beim Öffnen des NVS-Namespace");
for (;;); // leere Dauerschleife -> Ende
}
// ... Initialisieren von Sensoren etc.
}
void loop() {
unsigned long timer; // Systemtimer in Sekunden
time_t now;
struct tm tdata;
timer = millis() / 1000;
// alle paar Stunden die Zeit von einem NTP-Server holen
// (auch ganz am Anfang, da ist timer_ntp = 0)
if (timer >= timer_ntp) {
if (get_time_from_ntp_server()) { // Zeit einstellen
timer_ntp += 3600 * ntp_freq; // nächste Sync. in x Stunden
} else {
// im Fehlerfall nach einiger Zeit (n Sekunden) nochmal versuchen
timer_ntp += 3600;
}
}
// alle 30 Sekunden die Uhrzeit anzeigen
if (timer >= timer_time) {
now = time(NULL);
localtime_r(&now, &tdata);
Serial.printf("%04d-%02d-%02d %02d:%02d:%02d\n",
tdata.tm_year+1900, tdata.tm_mon+1, tdata.tm_mday,
tdata.tm_hour, tdata.tm_min, tdata.tm_sec);
timer_time += 30;
}
delay(100);
}
/* ------------------------------------------------------------
* Verbindung zum WLAN herstellen
* - SSID und Passwort aus NVS lesen (müssen vorhanden sein)
* - max. Dauer für Verbindungsaufbau aus NVS lesen
* (bei Fehler, z.B. nicht vorhanden) Defaultwert verwenden
*
* Returncode:
* - true: WLAN-Verbindung wurde hergestellt
* - false: Verbindungsaufbau fehlgeschlagen
* ------------------------------------------------------------ */
bool connect_WiFi() {
struct tm tdata;
unsigned long timer;
// Variablen für die Werte aus dem NVS
char ssid[33]; // Maximallänge lt. Standard: 32
char wifipwd[64]; // Maximallänge lt. Standard: 63 (mind. 8)
char hostname[64]; // Maximallänge lt. Standard: 63
int wifi_timeout;
if ((prefs.getString("ssid", ssid, 32) == 0) ||
(prefs.getString("wifipwd", wifipwd, 63) == 0)) {
return false;
}
wifi_timeout = prefs.getInt("timeout", DEFAULT_WIFI_TIMEOUT);
// Hostnamen setzen, wenn im NVS einer angegeben ist
// (muss vor WiFi.begin() erfolgen)
if (prefs.isKey("hostname")) {
prefs.getString("hostname", hostname, 63);
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.setHostname(hostname);
}
// mit dem WLAN verbinden
Serial.printf("Verbindung herstellen mit %s ", ssid);
timer = millis() / 1000;
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, wifipwd);
while (WiFi.status() != WL_CONNECTED && (millis() / 1000) < timer + wifi_timeout) {
delay(500);
Serial.print(".");
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\nTimeout bei Verbindungsaufbau!");
return false;
} else {
Serial.print("\nVerbunden! IP-Adresse: ");
Serial.println(WiFi.localIP());
return true;
}
}
/* ------------------------------------------------------------
* Aktuelle Zeit von einem NTP-Server holen
* - dazu ggf. Wifi aktivieren
* - Returncode false, wenn keine Wifi-Verbindung zustande kommt
* ------------------------------------------------------------ */
bool get_time_from_ntp_server() {
struct tm tdata;
String ntp_server, timezone;
// NTP-Server-Name und Zeitzone aus NVS ermitteln oder
// Defaultwerte verwenden
ntp_server = prefs.getString("ntpserver", DEFAULT_NTP_SERVER);
timezone = prefs.getString("timezone", DEFAULT_TIMEZONE);
if (WiFi.status() != WL_CONNECTED) {
// ggf. mit dem WLAN verbinden (falls noch nicht geschehen)
connect_WiFi();
}
if (WiFi.status() != WL_CONNECTED) {
// keine WLAN-Verbindung -> zurück mit Fehler
return false;
} else {
// Zeit vom NTP-Server holen und Zeitzone einstellen
configTzTime(timezone.c_str(), ntp_server.c_str());
// einmal getLocalTime() aufrufen; sonst wird die Zeit nicht
// übernommen
getLocalTime(&tdata);
return true;
}
}
/* ------------------------------------------------------------
* Ablegen von Konfigurationsdaten für den WLAN-Zugang im NVS
*
* Name des NVS-Namespace: wifi
* Daten:
* - ssid: Name des WLANs
* - wifipwd: WLAN-Passwort
* - hostname: "sprechender" Name des Geräts im Netzwerk
* - timeout: max. Zeit (in Sekunden) für Verbindungsaufbau
* - ntpserver: Name des NTP-Servers
* - ntpfreq: Intervall (in Stunden) für Abfrage des NTP-Servers
* - timezone: Zeitzone
*
* 2021-05-09 Heiko / unsinnsbasis.de
* ------------------------------------------------------------ */
/* ------------------------------------------------------------
* Einbinden der benötigten Bibliotheken,
* Defintion von Konstanten,
* Anlegen der Datenobjekte
* ------------------------------------------------------------ */
// Übertragungsrate für Ausgabe zum seriellen Monitor
#define SERIAL_BAUDRATE 115200
#include <Preferences.h>
// Datenobjekt für einen NVS-Namespace
Preferences prefs;
// Name des Namespace für die WiFi-Konfigurstion
const char* wifi_namespace = "wifi";
/* ------------------------------------------------------------
* Einstellungen für WiFi (NTP) und Datum/Zeit
* ------------------------------------------------------------ */
const char* ssid = "HS Gastzugang";
const char* password = "seizugast17";
const char* hostname = "ESP32-Test-A";
const char* ntpServer = "fritz.box"; // z.B. (de.)pool.ntp.org
// wie lange (in Sekunden) soll Verbindungsaufbau versucht werden
#define WIFI_TIMEOUT 60
// Häufigkeit (in Stunden) der NTP-Server-Abfrage
#define NTP_FREQ 24
// lokale Zeitzone definieren
// s. auch https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
#define TIMEZONE PSTR("CET-1CEST,M3.5.0,M10.5.0/3") // Europa/Berlin
void setup() {
bool f_error = false; //Fehler-Flag
Serial.begin(SERIAL_BAUDRATE);
delay(500);
// Namespace zum Schreiben öffnen (zweiter Parameter "readonly"
// kann entfallen, da per Default auf "false")
if (!prefs.begin(wifi_namespace)) {
Serial.println("Fehler beim Öffnen des NVS-Namespace");
for (;;); // leere Dauerschleife -> Ende
}
Serial.printf("Anzahl freier Einträge: %d\n", prefs.freeEntries());
prefs.clear();
Serial.printf("Anzahl freier Einträge nach dem Init./Löschen: %d\n", prefs.freeEntries());
if (prefs.putString("ssid", ssid) == 0)
f_error = true;
if (prefs.putString("wifipwd", password) == 0)
f_error = true;
if (prefs.putString("hostname", hostname) == 0)
f_error = true;
if (prefs.putInt("timeout", WIFI_TIMEOUT) == 0)
f_error = true;
if (prefs.putString("ntpserver", ntpServer) == 0)
f_error = true;
if (prefs.putInt("ntpfreq", NTP_FREQ) == 0)
f_error = true;
if (prefs.putString("timezone", TIMEZONE) == 0)
f_error = true;
if (f_error)
Serial.println("Fehler beim Speichern mindestens eines Eintrags");
Serial.printf("Anzahl freier Einträge nach dem Speichern: %d\n", prefs.freeEntries());
prefs.end();
}
void loop() {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment