Files
waterlevel-software/lib/fetchOTA/fetchOTA.cpp
Tobias Maier 3b1ab2e9e9
All checks were successful
Test compiling project / test (push) Successful in 2m21s
Updated shit
2025-02-17 00:12:50 +01:00

128 lines
3.8 KiB
C++

#ifndef UNIT_TEST
#include <fetchOTA.h>
#include "Arduino.h"
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <vector>
#include <ArduinoLog.h>
#include <HTTPUpdate.h>
OTA::OTA(String server_url, Version currentVersion, String currentDeviceConfiguration) {
_serverUrl = server_url;
_currentVersion = currentVersion;
_current_device_configuration = currentDeviceConfiguration;
}
Firmware OTA::getLatestVersionOnServer() {
HTTPClient http;
http.begin(_serverUrl);
int httpCode = http.GET();
if (httpCode != 200) {
return createErrorResponse("HTTP GET request failed with code " + String(httpCode));
}
String payload = http.getString();
Log.verbose("Payload: %s", payload.c_str());
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(doc, payload);
if (error) {
return createErrorResponse("Failed to deserialize JSON");
}
if (!doc.containsKey("Configurations")) {
return createErrorResponse("JSON response does not contain a 'Configurations' key");
}
std::vector<Configuration> configs;
for (JsonObject config : doc["Configurations"].as<JsonArray>()) {
if (config.containsKey("Version") && config.containsKey("URL") && config.containsKey("Config")) {
String deviceConfig = config["Config"].as<String>();
if (deviceConfig == _current_device_configuration) {
configs.push_back(Configuration{
parseVersion(config["Version"]),
config["URL"],
config["Board"],
deviceConfig
});
} else {
Log.verbose("Configuration %s does not match current device configuration %s", deviceConfig.c_str(), _current_device_configuration.c_str());
}
}
}
if (configs.empty()) {
return createErrorResponse("No valid configuration found in the JSON response");
}
Configuration latest = getLatestConfiguration(configs.data(), configs.size());
if (!isVersionNewer(_currentVersion, latest.version)) {
Log.verbose("No newer version found. Server version: %d.%d.%d", latest.version.major, latest.version.minor, latest.version.patch);
}
return Firmware{
latest.version,
latest.url,
true,
""
};
}
Firmware OTA::createErrorResponse(const String& errorMsg) {
return Firmware{
Version{0, 0, 0},
"",
false,
errorMsg
};
}
void OTA::run_ota_update(String url, std::function<void()> callback_started, std::function<void()> callback_finished, std::function<void(int, int)> callback_progress, std::function<void(int)> callback_error) {
Log.verbose("Starting OTA upgrade");
HTTPUpdate httpUpdate;
httpUpdate.onStart(callback_started);
httpUpdate.onEnd(callback_finished);
httpUpdate.onProgress(callback_progress);
httpUpdate.onError(callback_error);
Log.verbose("Defined callbacks, Starting update now");
t_httpUpdate_return ret;
if (url.startsWith("https")) {
Log.verbose("HTTPS URL");
WiFiClientSecure client;
client.setInsecure();
ret = httpUpdate.update(client, url);
} else if (url.startsWith("http")) {
Log.verbose("HTTP URL");
WiFiClient client;
ret = httpUpdate.update(client, url);
} else {
Log.error("URL is not valid: \n%s", url.c_str());
}
switch (ret) {
case HTTP_UPDATE_FAILED:
Log.error("HTTP_UPDATE_FAILED Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
Log.error("HTTP_UPDATE_NO_UPDATES");
break;
case HTTP_UPDATE_OK:
Log.verbose("Update done");
break;
}
}
#endif