Compare commits
7 Commits
7041a35090
...
70761270e2
| Author | SHA1 | Date | |
|---|---|---|---|
| 70761270e2 | |||
| d03369e7ef | |||
| 0660bb1726 | |||
| a63fb21f38 | |||
| c2de0695c0 | |||
| b4705d5662 | |||
| df5a7b6c4a |
@ -1,12 +1,13 @@
|
||||
[env:Helligkeit]
|
||||
[env:Greenhouse]
|
||||
platform = espressif8266
|
||||
board = esp12e
|
||||
framework = arduino
|
||||
lib_deps = https://github.com/adafruit/Adafruit_TSL2561
|
||||
https://github.com/knolleary/pubsubclient
|
||||
build_flags = -DHOSTNAME=\"Helligkeit\"
|
||||
https://github.com/adafruit/Adafruit_BME680
|
||||
build_flags = -DHOSTNAME=\"Greenhouse\"
|
||||
monitor_speed = 115200
|
||||
upload_protocol = espota
|
||||
upload_port = 10.0.0.160
|
||||
upload_port = 10.0.0.169
|
||||
;upload_port = /dev/ttyUSB0
|
||||
;upload_speed = 460800
|
||||
|
||||
76
src/bme680.h
Normal file
76
src/bme680.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef BME680_H
|
||||
#define BME680_H
|
||||
|
||||
#include <Adafruit_BME680.h>
|
||||
#include <mqtt.h>
|
||||
|
||||
class BME680 {
|
||||
|
||||
Adafruit_BME680 bme; // NOLINT(*-interfaces-global-init)
|
||||
|
||||
unsigned long last = 0UL;
|
||||
|
||||
public:
|
||||
|
||||
const String name;
|
||||
|
||||
unsigned long intervalMs;
|
||||
|
||||
explicit BME680(const String& name, const unsigned long interval_ms = 5000) : name(name), intervalMs(interval_ms) {
|
||||
//
|
||||
}
|
||||
|
||||
void setup() {
|
||||
if (bme.begin()) {
|
||||
Log.printf("BME680 \"%s\": Initialized.\n", name.c_str());
|
||||
} else {
|
||||
Log.printf("BME680 \"%s\": Failed to initialize.\n", name.c_str());
|
||||
}
|
||||
bme.setTemperatureOversampling(BME680_OS_8X);
|
||||
bme.setHumidityOversampling(BME680_OS_2X);
|
||||
bme.setPressureOversampling(BME680_OS_4X);
|
||||
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
|
||||
bme.setGasHeater(320, 150);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
const auto now = max(1UL, millis());
|
||||
if (last == 0 || now - last >= intervalMs) {
|
||||
if (bme.beginReading() == 0) {
|
||||
Log.printf("BME680 \"%s\": Failed to request reading.\n", name.c_str());
|
||||
setup();
|
||||
}
|
||||
last = now;
|
||||
}
|
||||
if (bme.remainingReadingMillis() == 0) {
|
||||
if (bme.endReading()) {
|
||||
const auto humidityAbsolute = calculateHumidityAbsolute(bme.temperature, bme.humidity);
|
||||
mqttPublish(name + "/temperature", bme.temperature, "\xB0""C");
|
||||
mqttPublish(name + "/pressure", bme.pressure / 100.0, "hPa");
|
||||
mqttPublish(name + "/humidity/relative", bme.humidity, "%");
|
||||
mqttPublish(name + "/humidity/absolute", humidityAbsolute, "mg/L");
|
||||
mqttPublish(name + "/gas", bme.gas_resistance / 1000.0, "KOhms");
|
||||
mqttPublish(name + "/altitude", bme.readAltitude(1013.25), "m");
|
||||
} else {
|
||||
Log.printf("BME680 \"%s\": Failed to complete reading\n", name.c_str());
|
||||
setup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static double calculateHumidityAbsolute(const double temperature, const double humidityRelative) {
|
||||
constexpr auto A = 6.112;
|
||||
constexpr auto m = 17.67;
|
||||
constexpr auto Tn = 243.5;
|
||||
constexpr auto Mw = 18.01534;
|
||||
constexpr auto R = 8.314462618;
|
||||
const auto Tk = temperature + 273.15;
|
||||
const auto P_sat = A * exp((m * temperature) / (temperature + Tn));
|
||||
const auto P_act = P_sat * (humidityRelative / 100.0);
|
||||
return (P_act * Mw) / (R * Tk);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
25
src/main.cpp
25
src/main.cpp
@ -1,16 +1,31 @@
|
||||
#include "wifi.h"
|
||||
#include "tsl2561.h"
|
||||
#include <bme680.h>
|
||||
#include "mqtt.h"
|
||||
#include "tsl2561.h"
|
||||
#include "wifi.h"
|
||||
|
||||
TSL2561 gardenTSL("garden");
|
||||
|
||||
BME680 gardenBME("garden");
|
||||
|
||||
BME680 greenhouseBME("greenhouse");
|
||||
|
||||
void setup() {
|
||||
delay(500);
|
||||
MySerial.printf("\n\n\nStartup\n");
|
||||
Log.printf("\n\n\nStartup\n");
|
||||
wifiConnect();
|
||||
sensorSetup();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
wifiLoop();
|
||||
sensorLoop();
|
||||
mqttLoop();
|
||||
if (isSetupTimeAfterBootDelay()) {
|
||||
gardenTSL.setup();
|
||||
gardenBME.setup();
|
||||
greenhouseBME.setup();
|
||||
}
|
||||
if (isAfterBootDelay()) {
|
||||
gardenTSL.loop();
|
||||
gardenBME.loop();
|
||||
greenhouseBME.loop();
|
||||
}
|
||||
}
|
||||
80
src/mqtt.cpp
80
src/mqtt.cpp
@ -1,6 +1,7 @@
|
||||
#include "mqtt.h"
|
||||
#include "wifi.h"
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <WiFiClient.h>
|
||||
|
||||
@ -8,35 +9,90 @@ WiFiClient client;
|
||||
|
||||
PubSubClient mqtt(client);
|
||||
|
||||
MySerialClass MySerial(mqtt);
|
||||
LogClass Log(mqtt);
|
||||
|
||||
unsigned long mqttFailureMillis = 0;
|
||||
|
||||
// ReSharper disable once CppUseAuto
|
||||
const String logTopic = String("log/") + HOSTNAME;
|
||||
|
||||
// ReSharper disable once CppUseAuto
|
||||
const String cmdTopic = String("cmd/") + HOSTNAME;
|
||||
|
||||
void mqttCallback(char *topic, const uint8_t *payload, unsigned int length) {
|
||||
char message[500];
|
||||
length = min(sizeof message - 1, length);
|
||||
memcpy(message, payload, length);
|
||||
*(message + length) = 0;
|
||||
Log.printf("MQTT received: topic=\"%s\", message=\"%s\"\n", topic, message);
|
||||
if (strcmp(message, "help") == 0) {
|
||||
Log.printf("HELP\n");
|
||||
Log.printf(" %s\n", "help");
|
||||
Log.printf(" %s\n", "info");
|
||||
Log.printf(" %s\n", "reboot");
|
||||
} else if (strcmp(message, "info") == 0) {
|
||||
Log.printf("INFO\n");
|
||||
Log.printf(" %-10s %s\n", "SSID:", WiFi.SSID().c_str());
|
||||
Log.printf(" %-10s %s\n", "IP:", WiFi.localIP().toString().c_str());
|
||||
Log.printf(" %-10s %d\n", "RSSI:", WiFi.RSSI());
|
||||
Log.printf(" %-10s %s\n", "uptime:", uptimeString().c_str());
|
||||
} else if (strcmp(message, "reboot") == 0) {
|
||||
Log.printf("rebooting...\n");
|
||||
delay(500);
|
||||
mqtt.disconnect();
|
||||
delay(500);
|
||||
EspClass::restart();
|
||||
}
|
||||
}
|
||||
|
||||
void mqttLoop() {
|
||||
if (!mqtt.loop() && isWifiConnected() && (mqttFailureMillis == 0 || millis() - mqttFailureMillis >= 3000)) {
|
||||
mqtt.setServer("10.0.0.50", 1883);
|
||||
if (mqtt.connect(HOSTNAME, HOSTNAME, 0, false, "disconnected\n")) {
|
||||
if (mqtt.connect(HOSTNAME, logTopic.c_str(), 0, false, "disconnected\n")) {
|
||||
yield();
|
||||
mqttPublish("garten/log", "connected\n");
|
||||
MySerial.printf("MQTT connected as \"%s\"\n", HOSTNAME);
|
||||
mqttPublish(logTopic.c_str(), "connected\n");
|
||||
mqtt.setCallback(mqttCallback);
|
||||
mqtt.subscribe(cmdTopic.c_str());
|
||||
Log.printf("MQTT connected as \"%s\"\n", HOSTNAME);
|
||||
mqttFailureMillis = 0;
|
||||
} else {
|
||||
MySerial.printf("Failed to connect MQTT.\n");
|
||||
Log.printf("Failed to connect MQTT.\n");
|
||||
mqttFailureMillis = max(1UL, millis());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mqttPublish(const char *topic, const float value, const char *unit) {
|
||||
if (!isTimeSet()) {
|
||||
return;
|
||||
}
|
||||
void mqttPublish(const String& topic, const int32_t value, const char *unit) {
|
||||
mqttPublish(topic, String(value), unit);
|
||||
}
|
||||
|
||||
void mqttPublish(const String& topic, const int64_t value, const char *unit) {
|
||||
mqttPublish(topic, String(value), unit);
|
||||
}
|
||||
|
||||
void mqttPublish(const String& topic, const uint32_t value, const char *unit) {
|
||||
mqttPublish(topic, String(value), unit);
|
||||
}
|
||||
|
||||
void mqttPublish(const String& topic, const uint64_t value, const char *unit) {
|
||||
mqttPublish(topic, String(value), unit);
|
||||
}
|
||||
|
||||
void mqttPublish(const String& topic, const float value, const char *unit) {
|
||||
mqttPublish(topic, String(value), unit);
|
||||
}
|
||||
|
||||
void mqttPublish(const String& topic, const double value, const char *unit) {
|
||||
mqttPublish(topic, String(value), unit);
|
||||
}
|
||||
|
||||
void mqttPublish(const String& topic, const String& value, const char *unit) {
|
||||
char buffer[200];
|
||||
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), isnan(value) ? "null" : String(value).c_str(), unit);
|
||||
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), value.c_str(), unit);
|
||||
mqttPublish(topic, buffer);
|
||||
}
|
||||
|
||||
void mqttPublish(const char *topic, const char *payload) {
|
||||
mqtt.publish(topic, payload);
|
||||
void mqttPublish(const String& topic, const String& payload) {
|
||||
mqtt.publish(topic.c_str(), payload.c_str());
|
||||
yield();
|
||||
}
|
||||
|
||||
32
src/mqtt.h
32
src/mqtt.h
@ -5,13 +5,29 @@
|
||||
#include "PubSubClient.h"
|
||||
#include "wifi.h"
|
||||
|
||||
extern const String logTopic;
|
||||
|
||||
extern const String cmdTopic;
|
||||
|
||||
void mqttLoop();
|
||||
|
||||
void mqttPublish(const char *topic, float value, const char *unit);
|
||||
void mqttPublish(const String& topic, int32_t value, const char *unit);
|
||||
|
||||
void mqttPublish(const char *topic, const char *payload);
|
||||
void mqttPublish(const String& topic, int64_t value, const char *unit);
|
||||
|
||||
class MySerialClass : public Stream {
|
||||
void mqttPublish(const String& topic, uint32_t value, const char *unit);
|
||||
|
||||
void mqttPublish(const String& topic, uint64_t value, const char *unit);
|
||||
|
||||
void mqttPublish(const String& topic, float value, const char *unit);
|
||||
|
||||
void mqttPublish(const String& topic, double value, const char *unit);
|
||||
|
||||
void mqttPublish(const String& topic, const String& value, const char *unit);
|
||||
|
||||
void mqttPublish(const String& topic, const String& payload);
|
||||
|
||||
class LogClass final : public Stream {
|
||||
|
||||
PubSubClient& mqtt;
|
||||
|
||||
@ -27,11 +43,11 @@ class MySerialClass : public Stream {
|
||||
|
||||
public:
|
||||
|
||||
explicit MySerialClass(PubSubClient& mqttClient) : mqtt(mqttClient) {
|
||||
explicit LogClass(PubSubClient& mqttClient) : mqtt(mqttClient) {
|
||||
Serial.begin(115200);
|
||||
}
|
||||
|
||||
size_t write(uint8_t data) override {
|
||||
size_t write(const uint8_t data) override {
|
||||
Serial.write(data);
|
||||
if (bufferWrite < bufferLast) {
|
||||
*bufferWrite++ = data;
|
||||
@ -43,10 +59,10 @@ public:
|
||||
due = true;
|
||||
if (mqtt.connected()) {
|
||||
if (overflow > 0) {
|
||||
mqtt.publish(HOSTNAME, "\n### LOG BUFFER OVERFLOW BY %d BYTES ###\n");
|
||||
mqttPublish(logTopic, "\n### LOG BUFFER OVERFLOW BY %d BYTES ###\n");
|
||||
overflow = 0;
|
||||
}
|
||||
mqtt.publish(HOSTNAME, (const char *) buffer);
|
||||
mqttPublish(logTopic, reinterpret_cast<const char *>(buffer));
|
||||
bufferWrite = buffer;
|
||||
*bufferWrite = 0;
|
||||
due = false;
|
||||
@ -68,6 +84,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
extern MySerialClass MySerial;
|
||||
extern LogClass Log;
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
#include "tsl2561.h"
|
||||
#include "mqtt.h"
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <Adafruit_TSL2561_U.h>
|
||||
|
||||
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
|
||||
|
||||
void sensorSetup() {
|
||||
if (tsl.begin()) {
|
||||
MySerial.printf("TSL2561: Initialized.\n");
|
||||
} else {
|
||||
MySerial.printf("TSL2561: Failed to initialize.\n");
|
||||
}
|
||||
tsl.enableAutoRange(true);
|
||||
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);
|
||||
}
|
||||
|
||||
void sensorRead() {
|
||||
sensors_event_t event;
|
||||
if (!tsl.getEvent(&event)) {
|
||||
MySerial.printf("TSL2561: Failed to read.\n");
|
||||
sensorSetup();
|
||||
} else {
|
||||
mqttPublish("garten/helligkeit", event.light, "lux");
|
||||
}
|
||||
}
|
||||
|
||||
void sensorLoop() {
|
||||
unsigned long now = millis();
|
||||
static unsigned long last = 0;
|
||||
if (last == 0 || now - last >= 2000) {
|
||||
last = max(1UL, now);
|
||||
sensorRead();
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,57 @@
|
||||
#ifndef TSL2561_H
|
||||
#define TSL2561_H
|
||||
|
||||
void sensorSetup();
|
||||
#include <Adafruit_TSL2561_U.h>
|
||||
|
||||
void sensorLoop();
|
||||
class TSL2561 {
|
||||
|
||||
Adafruit_TSL2561_Unified tsl;
|
||||
|
||||
unsigned long last = 0UL;
|
||||
|
||||
public:
|
||||
|
||||
const String name;
|
||||
|
||||
unsigned long intervalMs;
|
||||
|
||||
explicit TSL2561(const String& name, const uint8_t address = TSL2561_ADDR_FLOAT, const unsigned long interval_ms = 5000) : tsl(Adafruit_TSL2561_Unified(address)), name(name), intervalMs(interval_ms) {
|
||||
//
|
||||
}
|
||||
|
||||
void setup() {
|
||||
if (tsl.begin()) {
|
||||
Log.printf("TSL2561 \"%s\": Initialized.\n", name.c_str());
|
||||
} else {
|
||||
Log.printf("TSL2561 \"%s\": Failed to initialize.\n", name.c_str());
|
||||
}
|
||||
tsl.enableAutoRange(true);
|
||||
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
const auto now = millis();
|
||||
if (last == 0 || now - last >= intervalMs) {
|
||||
last = max(1UL, now);
|
||||
read();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void read() {
|
||||
uint16_t broadband;
|
||||
uint16_t ir;
|
||||
tsl.getLuminosity(&broadband, &ir);
|
||||
const auto illuminance = tsl.calculateLux(broadband, ir);
|
||||
if (illuminance == 65536) {
|
||||
Log.printf("TSL2561 \"%s\": Failed to read.\n", name.c_str());
|
||||
setup();
|
||||
} else {
|
||||
mqttPublish(name + "/illuminance", illuminance, "lux");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
125
src/wifi.cpp
125
src/wifi.cpp
@ -1,37 +1,111 @@
|
||||
#include <TZ.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include "wifi.h"
|
||||
#include <ArduinoOTA.h>
|
||||
#include <TZ.h>
|
||||
#include "mqtt.h"
|
||||
|
||||
bool wifiConnected = false;
|
||||
#define WIFI_TIMEOUT_MS 10000
|
||||
#define WIFI_SSID "HappyNet"
|
||||
#define WIFI_PASSWORD "1Grausame!Sackratte7"
|
||||
#define NTP_SERVER "107.189.12.98" /* pool.ntp.org */
|
||||
#define BOOT_DELAY_SEC 5
|
||||
|
||||
bool timeSet = false;
|
||||
auto wifiConnected = false;
|
||||
|
||||
unsigned long wifiSince = 0;
|
||||
auto timeSetSince = 0UL;
|
||||
|
||||
unsigned long wifiConnectBeginMillis = 0;
|
||||
|
||||
auto bootDelayOver = false;
|
||||
|
||||
void wifiConnect() {
|
||||
wifiSince = max(1UL, millis());
|
||||
wifiConnectBeginMillis = max(1UL, millis());
|
||||
WiFi.setHostname(HOSTNAME);
|
||||
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
|
||||
configTime(TZ_Europe_Berlin, "107.189.12.98");
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
configTime(TZ_Europe_Berlin, NTP_SERVER);
|
||||
ArduinoOTA.onStart([]() {
|
||||
Log.printf("OTA start...\n");
|
||||
});
|
||||
ArduinoOTA.onError([](const ota_error_t error) {
|
||||
const char *name;
|
||||
switch (error) {
|
||||
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;
|
||||
default:
|
||||
name = "[???]";
|
||||
break;
|
||||
}
|
||||
Log.printf("OTA error #%d: %s\n", error, name);
|
||||
});
|
||||
ArduinoOTA.onEnd([]() {
|
||||
Log.printf("OTA success\n");
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
yield();
|
||||
}
|
||||
|
||||
uint64_t uptimeOffset = 0;
|
||||
|
||||
void uptimeLoop() {
|
||||
const auto now = millis();
|
||||
static auto uptimeLast = 0UL;
|
||||
if (now < uptimeLast) {
|
||||
uptimeOffset += static_cast<uint64_t>(-1);
|
||||
}
|
||||
uptimeLast = now;
|
||||
}
|
||||
|
||||
uint64_t uptimeMillis() {
|
||||
return uptimeOffset + millis();
|
||||
}
|
||||
|
||||
String uptimeString() {
|
||||
const auto ms = uptimeMillis();
|
||||
const auto days = static_cast<int>(ms / (24 * 60 * 60 * 1000));
|
||||
const auto hours = static_cast<int>(ms / (60 * 60 * 1000) % 24);
|
||||
const auto minutes = static_cast<int>(ms / (60 * 1000) % 60);
|
||||
const auto seconds = static_cast<int>(ms / 1000 % 60);
|
||||
char buffer[32];
|
||||
if (days > 0) {
|
||||
snprintf(buffer, sizeof buffer, "%d day%s, %d hour%s", days, days == 1 ? "" : "s", hours, hours == 1 ? "" : "s");
|
||||
} else if (hours > 0) {
|
||||
snprintf(buffer, sizeof buffer, "%d hour%s, %d minute%s", hours, hours == 1 ? "" : "s", minutes, minutes == 1 ? "" : "s");
|
||||
} else if (minutes > 0) {
|
||||
snprintf(buffer, sizeof buffer, "%d minute%s, %d second%s", minutes, minutes == 1 ? "" : "s", seconds, seconds == 1 ? "" : "s");
|
||||
} else {
|
||||
snprintf(buffer, sizeof buffer, "%d second%s", seconds, seconds == 1 ? "" : "s");
|
||||
}
|
||||
return {buffer};
|
||||
}
|
||||
|
||||
void timeLoop() {
|
||||
const time_t now = time(nullptr);
|
||||
const time_t nowHour = now / 3600;
|
||||
const auto now = time(nullptr);
|
||||
const auto nowHour = now / 3600;
|
||||
static unsigned long lastHour = 0;
|
||||
if (!timeSet) {
|
||||
if (timeSetSince == 0) {
|
||||
if (now > 1700000000) {
|
||||
timeSet = true;
|
||||
timeSetSince = now;
|
||||
lastHour = nowHour;
|
||||
MySerial.printf("Got time: %s\n", getTimeString().c_str());
|
||||
Log.printf("Got time: %s\n", getTimeString().c_str());
|
||||
Log.printf("Delaying boot for %d seconds.\n", BOOT_DELAY_SEC);
|
||||
}
|
||||
} else {
|
||||
if (lastHour != nowHour) {
|
||||
lastHour = nowHour;
|
||||
MySerial.printf("%s\n", getTimeString().c_str());
|
||||
Log.printf("%s\n", getTimeString().c_str());
|
||||
}
|
||||
if (!bootDelayOver) {
|
||||
bootDelayOver = time(nullptr) - timeSetSince > BOOT_DELAY_SEC;
|
||||
if (bootDelayOver) {
|
||||
Log.printf("Boot delay complete.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,9 +115,9 @@ void wifiLoop() {
|
||||
if (WiFi.localIP() == 0UL) {
|
||||
if (wifiConnected) {
|
||||
wifiConnected = false;
|
||||
MySerial.printf("WiFi disconnected.\n");
|
||||
Log.printf("WiFi disconnected.\n");
|
||||
wifiConnect();
|
||||
} else if (wifiSince == 0 || millis() - wifiSince >= 10000) {
|
||||
} else if (wifiConnectBeginMillis == 0 || millis() - wifiConnectBeginMillis >= WIFI_TIMEOUT_MS) {
|
||||
WiFi.disconnect();
|
||||
yield();
|
||||
wifiConnect();
|
||||
@ -51,10 +125,12 @@ void wifiLoop() {
|
||||
} else {
|
||||
if (!wifiConnected) {
|
||||
wifiConnected = true;
|
||||
MySerial.printf("WiFi connected as \"%s\" (%s)\n", HOSTNAME, WiFi.localIP().toString().c_str());
|
||||
wifiConnectBeginMillis = 0;
|
||||
Log.printf("WiFi connected as \"%s\" (%s)\n", HOSTNAME, WiFi.localIP().toString().c_str());
|
||||
}
|
||||
timeLoop();
|
||||
}
|
||||
uptimeLoop();
|
||||
timeLoop();
|
||||
}
|
||||
|
||||
String getTimeString() {
|
||||
@ -71,6 +147,15 @@ bool isWifiConnected() {
|
||||
return wifiConnected;
|
||||
}
|
||||
|
||||
bool isTimeSet() {
|
||||
return timeSet;
|
||||
bool isSetupTimeAfterBootDelay() {
|
||||
static auto needed = true;
|
||||
if (needed && bootDelayOver) {
|
||||
needed = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isAfterBootDelay() {
|
||||
return bootDelayOver;
|
||||
}
|
||||
@ -11,6 +11,12 @@ String getTimeString();
|
||||
|
||||
bool isWifiConnected();
|
||||
|
||||
bool isTimeSet();
|
||||
bool isSetupTimeAfterBootDelay();
|
||||
|
||||
bool isAfterBootDelay();
|
||||
|
||||
uint64_t uptimeMillis();
|
||||
|
||||
String uptimeString();
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user