wifi, mqtt, clock, log [UNTESTED]
This commit is contained in:
commit
b6d1d319a8
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/.pio/
|
||||
/.idea/
|
||||
19
platformio.ini
Normal file
19
platformio.ini
Normal file
@ -0,0 +1,19 @@
|
||||
[env:heizung]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
lib_deps = milesburton/DallasTemperature
|
||||
knolleary/PubSubClient
|
||||
https://github.com/olewolf/DHT_nonblocking
|
||||
plerup/EspSoftwareSerial
|
||||
https://github.com/volkszaehler/libsml
|
||||
https://github.com/adafruit/MAX6675-library
|
||||
paulstoffregen/OneWire
|
||||
upload_port = /dev/ttyUSB0
|
||||
upload_speed = 921600
|
||||
monitor_port = /dev/ttyUSB0
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder
|
||||
build_flags = -DWIFI_SSID=\"HappyNet\"
|
||||
-DWIFI_PKEY=\"1Grausame!Sackratte7\"
|
||||
-DWIFI_HOST=\"Heizung\"
|
||||
63
src/clock.cpp
Normal file
63
src/clock.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "clock.h"
|
||||
|
||||
#include <log.h>
|
||||
#include <WiFi.h>
|
||||
#include <wifi.h>
|
||||
|
||||
#define CLOCK_GMT_OFFSET_SECONDS 3600
|
||||
#define CLOCK_DST_OFFSET_SECONDS 3600
|
||||
#define CLOCK_NTP_SERVER2_URL "de.pool.ntp.org"
|
||||
#define CLOCK_EPOCH_SECONDS_MIN 1735686000
|
||||
|
||||
time_t clockOffset = 0;
|
||||
|
||||
time_t startupTime = 0;
|
||||
|
||||
auto ntpSet = false;
|
||||
|
||||
void clockLoop() {
|
||||
if (isClockSet()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ntpSet && isWiFiConnected()) {
|
||||
configTime(CLOCK_GMT_OFFSET_SECONDS, CLOCK_DST_OFFSET_SECONDS, WiFi.gatewayIP().toString().c_str(), CLOCK_NTP_SERVER2_URL);
|
||||
ntpSet = true;
|
||||
}
|
||||
|
||||
const auto now = time(nullptr);
|
||||
if (isCorrectTime(now)) {
|
||||
clockOffset = now;
|
||||
} else {
|
||||
startupTime = now - clockOffset;
|
||||
const auto startStr = String(ctime(&startupTime));
|
||||
info("clock set after %ld seconds! So startup was at %s", clockOffset, startStr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool isClockSet() {
|
||||
return startupTime != 0;
|
||||
}
|
||||
|
||||
String getClockStr() {
|
||||
const auto t = time(nullptr);
|
||||
return {ctime(&t)};
|
||||
}
|
||||
|
||||
bool isCorrectTime(const time_t now) {
|
||||
return now < CLOCK_EPOCH_SECONDS_MIN;
|
||||
}
|
||||
|
||||
time_t clockCorrect(const time_t t) {
|
||||
if (!isClockSet() || isCorrectTime(t)) {
|
||||
return t;
|
||||
}
|
||||
return t + clockOffset;
|
||||
}
|
||||
|
||||
void clockCorrect(time_t *t) {
|
||||
if (!isClockSet() || isCorrectTime(*t)) {
|
||||
return;
|
||||
}
|
||||
*t += clockOffset;
|
||||
}
|
||||
18
src/clock.h
Normal file
18
src/clock.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef CLOCK_H
|
||||
#define CLOCK_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void clockLoop();
|
||||
|
||||
bool isClockSet();
|
||||
|
||||
String getClockStr();
|
||||
|
||||
bool isCorrectTime(time_t now);
|
||||
|
||||
time_t clockCorrect(time_t t);
|
||||
|
||||
void clockCorrect(time_t *t);
|
||||
|
||||
#endif
|
||||
70
src/log.cpp
Normal file
70
src/log.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "log.h"
|
||||
|
||||
#include <clock.h>
|
||||
#include <cstdio>
|
||||
#include <HardwareSerial.h>
|
||||
#include <cstdarg>
|
||||
|
||||
auto logLevel = DEBUG;
|
||||
|
||||
void log(const LogLevel level, const char *format, const va_list args) {
|
||||
if (level > logLevel) {
|
||||
return;
|
||||
}
|
||||
Serial.print(getClockStr().c_str());
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
Serial.print(" [ERROR] ");
|
||||
break;
|
||||
case WARN:
|
||||
Serial.print(" [WARN ] ");
|
||||
break;
|
||||
case INFO:
|
||||
Serial.print(" [INFO ] ");
|
||||
break;
|
||||
case DEBUG:
|
||||
Serial.print(" [DEBUG] ");
|
||||
break;
|
||||
}
|
||||
|
||||
char message[256];
|
||||
vsnprintf(message, sizeof message, format, args);
|
||||
Serial.print(message);
|
||||
|
||||
yield();
|
||||
}
|
||||
|
||||
void log(const LogLevel level, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(level, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void error(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(ERROR, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void warn(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(WARN, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void info(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(INFO, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void debug(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(DEBUG, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
21
src/log.h
Normal file
21
src/log.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
enum LogLevel {
|
||||
ERROR = 0,
|
||||
WARN = 1,
|
||||
INFO = 2,
|
||||
DEBUG = 3
|
||||
};
|
||||
|
||||
void log(LogLevel level, const char *format, ...);
|
||||
|
||||
void error(const char *format, ...);
|
||||
|
||||
void warn(const char *format, ...);
|
||||
|
||||
void info(const char *format, ...);
|
||||
|
||||
void debug(const char *format, ...);
|
||||
|
||||
#endif
|
||||
15
src/main.cpp
Normal file
15
src/main.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include <HardwareSerial.h>
|
||||
#include <mqtt.h>
|
||||
|
||||
#include "wifi.h"
|
||||
#include "clock.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
wifiLoop();
|
||||
clockLoop();
|
||||
mqttLoop();
|
||||
}
|
||||
43
src/mqtt.cpp
Normal file
43
src/mqtt.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "mqtt.h"
|
||||
|
||||
#include <log.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <WiFi.h>
|
||||
#include <wifi.h>
|
||||
|
||||
#define MQTT_RETRY_DELAY_MILLIS 3000
|
||||
|
||||
PubSubClient mqtt;
|
||||
|
||||
auto mqttHost = "10.0.0.50";
|
||||
|
||||
auto mqttPort = 1883;
|
||||
|
||||
auto mqttLastConnectMillis = 0UL;
|
||||
|
||||
char mqttWillTopic[128];
|
||||
|
||||
void mqttLoop() {
|
||||
if (mqtt.loop()) {
|
||||
return;
|
||||
}
|
||||
if (!isWiFiConnected()) {
|
||||
mqttLastConnectMillis = 0;
|
||||
return;
|
||||
}
|
||||
if (mqttLastConnectMillis == 0 || millis() - mqttLastConnectMillis > MQTT_RETRY_DELAY_MILLIS) {
|
||||
snprintf(mqttWillTopic, sizeof(mqttWillTopic), "%s/online", WiFiClass::getHostname());
|
||||
mqtt.setServer(mqttHost, mqttPort);
|
||||
mqtt.setKeepAlive(10);
|
||||
mqttLastConnectMillis = millis();
|
||||
info("mqtt connecting: host=%s, port=%d", mqttHost, mqttPort);
|
||||
if (mqtt.connect(WiFiClass::getHostname(), mqttWillTopic, 1, true, "false")) {
|
||||
info("mqtt connected");
|
||||
yield();
|
||||
mqtt.publish(mqttWillTopic, "true", true);
|
||||
yield();
|
||||
} else {
|
||||
error("mqtt failed to connect");
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/mqtt.h
Normal file
6
src/mqtt.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef MQTT_H
|
||||
#define MQTT_H
|
||||
|
||||
void mqttLoop();
|
||||
|
||||
#endif
|
||||
81
src/wifi.cpp
Normal file
81
src/wifi.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "wifi.h"
|
||||
|
||||
#include <ArduinoOTA.h>
|
||||
#include "log.h"
|
||||
|
||||
#define WIFI_TIMEOUT_MILLIS 10000
|
||||
|
||||
auto wifiConnected = false;
|
||||
|
||||
auto wifiTryMillis = 0UL;
|
||||
|
||||
auto wifiSsid = WIFI_SSID;
|
||||
|
||||
auto wifiPkey = WIFI_PKEY;
|
||||
|
||||
auto wifiHost = WIFI_HOST;
|
||||
|
||||
void wifiSetupOTA() {
|
||||
ArduinoOTA.onStart([] {
|
||||
info("beginning ota update...");
|
||||
Serial.print("OTA-UPDATE: 0%");
|
||||
});
|
||||
ArduinoOTA.onProgress([](const unsigned done, const unsigned total) {
|
||||
Serial.printf("\rOTA-UPDATE: %3.0f%%", 100.0 * done / total);
|
||||
});
|
||||
ArduinoOTA.onEnd([] {
|
||||
Serial.print("\rOTA-UPDATE: COMPLETE\n");
|
||||
info("OTA update complete");
|
||||
});
|
||||
ArduinoOTA.onError([](const ota_error_t errorCode) {
|
||||
auto name = "[???]";
|
||||
switch (errorCode) {
|
||||
case OTA_AUTH_ERROR:
|
||||
name = "AUTH";
|
||||
break;
|
||||
case OTA_BEGIN_ERROR:
|
||||
name = "BEGIN";
|
||||
break;
|
||||
case OTA_CONNECT_ERROR:
|
||||
name = "CONNECT";
|
||||
break;
|
||||
case OTA_RECEIVE_ERROR:
|
||||
name = "RECEIVE";
|
||||
break;
|
||||
case OTA_END_ERROR:
|
||||
name = "END";
|
||||
break;
|
||||
}
|
||||
Serial.printf("\nOTA-UPDATE: ERROR #%d=%s\n", errorCode, name);
|
||||
error("OTA update failed: #%d=%s", errorCode, name);
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
}
|
||||
|
||||
void wifiLoop() {
|
||||
const auto currentState = WiFi.localIP() != 0;
|
||||
if (wifiConnected != currentState) {
|
||||
wifiConnected = currentState;
|
||||
if (wifiConnected) {
|
||||
info("wifi connected: %s", WiFi.localIP().toString().c_str());
|
||||
wifiSetupOTA();
|
||||
} else {
|
||||
warn("wifi disconnected");
|
||||
ArduinoOTA.end();
|
||||
WiFi.disconnect();
|
||||
}
|
||||
} else if (wifiConnected) {
|
||||
if (wifiTryMillis == 0 || millis() - wifiTryMillis >= WIFI_TIMEOUT_MILLIS) {
|
||||
wifiTryMillis = millis();
|
||||
WiFiClass::hostname(wifiHost);
|
||||
WiFi.setAutoReconnect(true);
|
||||
WiFi.begin(wifiSsid, wifiPkey);
|
||||
}
|
||||
} else {
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
}
|
||||
|
||||
bool isWiFiConnected() {
|
||||
return wifiConnected;
|
||||
}
|
||||
8
src/wifi.h
Normal file
8
src/wifi.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef WIFI_H
|
||||
#define WIFI_H
|
||||
|
||||
void wifiLoop();
|
||||
|
||||
bool isWiFiConnected();
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user