205 lines
7.4 KiB
C++
205 lines
7.4 KiB
C++
#include <Arduino.h>
|
|
#include "tools.h"
|
|
#include <Elog.h>
|
|
#include "../global_data/defines.h"
|
|
#include <Preferences.h>
|
|
#include <fetchOTA.h>
|
|
#include <AsyncWebSocket.h>
|
|
#include "log.h"
|
|
#include "esp_sntp.h"
|
|
#include <HTTPClient.h>
|
|
|
|
#ifdef USE_INA226
|
|
#define BOARD_VARIANT "INA226REV2"
|
|
#else
|
|
#define BOARD_VARIANT "INA233REV2"
|
|
#endif
|
|
|
|
extern Preferences prefs;
|
|
extern OTAStatus ota_status;
|
|
extern AsyncWebSocket webSocket;
|
|
|
|
extern Version current_spiffs_version;
|
|
|
|
bool is_error(ActiveErrors active_errors) {
|
|
return active_errors.current_high || active_errors.current_low || active_errors.level_high || active_errors.level_low || active_errors.voltage_high || active_errors.voltage_low;
|
|
}
|
|
|
|
String processor(const String& var)
|
|
{
|
|
if (var == level_sensor_range_key) {
|
|
return String(prefs.getFloat(level_sensor_range_key, -1));
|
|
} else if (var == water_level_min_key) {
|
|
return String(prefs.getFloat(water_level_min_key, -1));
|
|
} else if (var == water_level_max_key) {
|
|
return String(prefs.getFloat(water_level_max_key, -1));
|
|
} else if (var == water_volume_key) {
|
|
return String(prefs.getFloat(water_volume_key, -1));
|
|
} else if (var == ssid_key) {
|
|
return String(prefs.getString(ssid_key, ""));
|
|
}
|
|
|
|
return String("");
|
|
}
|
|
|
|
// OTA Callbacks
|
|
void update_started() {
|
|
LOG(ELOG_LEVEL_DEBUG, "OTA Update started");
|
|
ota_status.update_progress = 0;
|
|
}
|
|
|
|
void update_finished() {
|
|
LOG(ELOG_LEVEL_DEBUG, "OTA Update finished");
|
|
ota_status.update_progress = -1;
|
|
webSocket.textAll(String(-1).c_str());
|
|
}
|
|
|
|
void update_progress(int cur, int total) {
|
|
ota_status.update_progress = 0;
|
|
if (cur != 0 ) {
|
|
ota_status.update_progress = int(float(cur)/float(total)*100);
|
|
LOG(ELOG_LEVEL_DEBUG, "OTA Update progress: %d/%d, %i", cur, total, ota_status.update_progress);
|
|
}
|
|
webSocket.textAll(String(ota_status.update_progress).c_str());
|
|
LOG(ELOG_LEVEL_DEBUG, "OTA Update progress: %d/%d", cur, total);
|
|
}
|
|
|
|
void update_error(int err) {
|
|
LOG(ELOG_LEVEL_ERROR, "OTA Update error: %d", err);
|
|
ota_status.update_progress = -2;
|
|
}
|
|
|
|
void check_update_task(void* parameter) {
|
|
LOG(ELOG_LEVEL_DEBUG, "Starting check Update Task");
|
|
ota_status.current_version = current_software_version;
|
|
ota_status.update_progress = -1;
|
|
|
|
OTA ota("https://iot.tobiasmaier.me/firmware/waterlevel", current_software_version, BOARD_VARIANT);
|
|
OTA littlefs_ota("https://iot.tobiasmaier.me/filesystem/waterlevel", REQUIRED_SPIFFS_VERSION, "generic");
|
|
|
|
while (true) {
|
|
// Check if internet connection exists before running update, the web client seems to fail otherwise
|
|
|
|
if (check_for_internet_connection()) {
|
|
LOG(ELOG_LEVEL_DEBUG, "Ping sucessful, starting update checks");
|
|
check_and_update_littleFS(littlefs_ota);
|
|
check_and_update_firmware(ota);
|
|
} else {
|
|
LOG(ELOG_LEVEL_WARNING, "Server did not respond to ping, waiting...");
|
|
}
|
|
delay(1000 * 60 * 1);
|
|
}
|
|
}
|
|
|
|
void check_and_update_littleFS(OTA littlefs) {
|
|
Firmware latest_fs_version = littlefs.getLatestVersionOnServer();
|
|
|
|
LOG(ELOG_LEVEL_DEBUG, "Required SPIFFS Version: %d.%d.%d; Current SPIFFS version: %d.%d.%d; Server SPIFFS Version: %d.%d.%d", REQUIRED_SPIFFS_VERSION.major, REQUIRED_SPIFFS_VERSION.minor, REQUIRED_SPIFFS_VERSION.patch, current_spiffs_version.major, current_spiffs_version.minor, current_spiffs_version.patch, latest_fs_version.version.major, latest_fs_version.version.minor, latest_fs_version.version.patch);
|
|
|
|
if (latest_fs_version.valid) {
|
|
|
|
// If we need new version and the server has a new version
|
|
if (isVersionNewer(current_spiffs_version, REQUIRED_SPIFFS_VERSION) && isVersionNewer(current_spiffs_version, latest_fs_version.version)) {
|
|
LOG(ELOG_LEVEL_DEBUG, "New SPIFFS version, running update now");
|
|
run_ota_spiffs_update(latest_fs_version.url, update_started, update_finished, update_progress, update_error);
|
|
ESP.restart();
|
|
|
|
// If we do not need a new version but one is available on the server
|
|
} else if (isVersionNewer(REQUIRED_SPIFFS_VERSION, latest_fs_version.version)) {
|
|
LOG(ELOG_LEVEL_DEBUG, "New SPIFFS version available: %d.%d.%d, current version: %d.%d.%d but not necessary to update", latest_fs_version.version.major, latest_fs_version.version.minor, latest_fs_version.version.patch, REQUIRED_SPIFFS_VERSION.major, REQUIRED_SPIFFS_VERSION.minor, REQUIRED_SPIFFS_VERSION.patch);
|
|
|
|
// If we need a new version but server has no new version
|
|
} else if (isVersionNewer(current_spiffs_version, REQUIRED_SPIFFS_VERSION)) {
|
|
LOG(ELOG_LEVEL_ERROR, "New LittleFS Version is needed, but not found on server");
|
|
|
|
// Catch case for the rest
|
|
} else {
|
|
LOG(ELOG_LEVEL_DEBUG, "No new SPIFFS version available");
|
|
}
|
|
}
|
|
}
|
|
|
|
void check_and_update_firmware(OTA ota){
|
|
Firmware fw = ota.getLatestVersionOnServer();
|
|
if (fw.valid) {
|
|
LOG(ELOG_LEVEL_DEBUG, "Firmware available on server: %d.%d.%d, current version: %d.%d.%d", fw.version.major, fw.version.minor, fw.version.patch, current_software_version.major, current_software_version.minor, current_software_version.patch);
|
|
ota_status.latest_version = fw.version;
|
|
ota_status.update_url = fw.url;
|
|
if (isVersionNewer(current_software_version, fw.version)) {
|
|
LOG(ELOG_LEVEL_DEBUG, "Remote version is newer than current version");
|
|
ota_status.update_available = true;
|
|
} else {
|
|
ota_status.update_available = false;
|
|
}
|
|
} else {
|
|
if (fw.version.major != 0 && fw.version.minor != 0 && fw.version.patch != 0) {
|
|
ota_status.latest_version = fw.version;
|
|
ota_status.update_available = false;
|
|
}
|
|
|
|
LOG(ELOG_LEVEL_DEBUG, "No new firmware available");
|
|
}
|
|
}
|
|
|
|
bool check_for_internet_connection() {
|
|
HTTPClient http;
|
|
http.begin("https://iot.tobiasmaier.me");
|
|
int code = http.sendRequest("HEAD");
|
|
if (code > 0) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void run_ota_update_task(void* parameter) {
|
|
TaskArgs_t *args = (TaskArgs_t *) parameter;
|
|
LOG(ELOG_LEVEL_DEBUG, "Running OTA upgrade now with URL: %s", args->ota_status.update_url.c_str());
|
|
run_ota_update(args->ota_status.update_url, update_started, update_finished, update_progress, update_error);
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
|
|
void *arg, uint8_t *data, size_t len) {
|
|
if (type == WS_EVT_CONNECT) {
|
|
Serial.println("WebSocket client connected");
|
|
} else if (type == WS_EVT_DISCONNECT) {
|
|
Serial.println("WebSocket client disconnected");
|
|
} else if (type == WS_EVT_DATA) {
|
|
// Optionally process data received from the client
|
|
}
|
|
}
|
|
|
|
void get_time_task(void* parameter) {
|
|
LOG(ELOG_LEVEL_DEBUG, "Starting GetTimeTask");
|
|
LOG(ELOG_LEVEL_DEBUG, "Trying to get time from Internet");
|
|
|
|
sntp_set_time_sync_notification_cb(onTimeSync);
|
|
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
|
|
sntp_set_sync_interval(1000 * 60 * 60); //re-sync every hour
|
|
configTzTime("UTC0", "pool.ntp.org", "1.europe.pool.ntp.org", " time.Windows.com");
|
|
waitForTime();
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
// Time stuff
|
|
|
|
// Handler to handle successful time sync
|
|
void onTimeSync(struct timeval* tv) {
|
|
struct tm timeinfo;
|
|
getLocalTime(&timeinfo);
|
|
LOG(ELOG_LEVEL_DEBUG, "Time synchronized. New Time: %s", asctime(&timeinfo));
|
|
}
|
|
|
|
// wait for succesful time sync
|
|
bool waitForTime() {
|
|
time_t now;
|
|
do {
|
|
time(&now);
|
|
if (now > 8 * 3600) break;
|
|
delay(500);
|
|
LOG(ELOG_LEVEL_WARNING, "No valid time.");
|
|
} while (true);
|
|
LOG(ELOG_LEVEL_DEBUG, "Found valid time.");
|
|
return true;
|
|
} |