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