Added Updater to automatically perform OTA updates without user interaction.

This commit is contained in:
2019-11-28 06:42:30 +01:00
parent 3b0410f560
commit 07b1ea3a5c
9 changed files with 192 additions and 4 deletions

View File

@ -3,6 +3,7 @@
#include "config.h"
#include "playlist.h"
#include "http_server.h"
#include "updater.h"
#include <ArduinoJson.h>
Controller::Controller(Player* p, PlaylistManager* playlist_manager) {
@ -50,6 +51,14 @@ void Controller::loop() {
process_message(_cmd_queue);
_cmd_queue = "";
}
#ifdef OTA_UPDATE_URL
if (!player->is_playing() && _last_update_check_at<millis() && _last_update_check_at + OTA_CHECK_INTERVAL < millis()) {
Updater::run();
} else {
_last_update_check_at = millis();
}
#endif
TRACE("Controller::loop() done.\n");
}

View File

@ -10,6 +10,7 @@
#include "spi_master.h"
#include "http_server.h"
#include "playlist_manager.h"
#include "updater.h"
Controller* controller;
Player* player;
@ -38,9 +39,9 @@ void setup() {
Serial.println("Started.");
INFO("Starting.\n");
#ifdef VERSION
INFO("ESMP3 version %s\n", VERSION);
INFO("ESMP3 version %s (OTA_VERSION %d)\n", VERSION, OTA_VERSION);
#else
INFO("ESMP3, version unknown\n");
INFO("ESMP3, version unknown (OTA_VERSION %d)\n", OTA_VERSION);
#endif
INFO("Initializing...\n");
@ -61,7 +62,16 @@ void setup() {
spi->select_sd(false);
DEBUG("Starting SPIFFS...\n");
uint16_t spiffs_version = 0;
SPIFFS.begin(true);
if (SPIFFS.exists("/_version.txt")) {
File f = SPIFFS.open("/_version.txt", "r");
spiffs_version = f.readString().toInt();
f.close();
DEBUG("SPIFFS filesystem version is %d.\n", spiffs_version);
} else {
DEBUG("No SPIFFS filesystem version found - setting spiffs_version to 0.\n");
}
DEBUG("Initializing PlaylistManager...\n");
pm = new PlaylistManager();
@ -93,9 +103,15 @@ void setup() {
f.close();
}
SPIMaster::select_sd(false);
if (!connected) {
#if defined(WIFI_SSID) and defined(WIFI_PASS)
DEBUG("Trying hardcoded WiFi data...\n");
connected = connect_to_wifi(WIFI_SSID, WIFI_PASS);
#else
DEBUG("No hardcoded WiFi data set.\n");
#endif
}
if (!connected) {
INFO("No WiFi connection!\n");
@ -118,6 +134,12 @@ void setup() {
} else {
INFO("Could not fetch current time via NTP.\n");
}
#ifdef OTA_UPDATE_URL
if (spiffs_version < OTA_VERSION) {
Updater::run();
}
#endif
INFO("Initialization completed.\n");
}

127
src/updater.cpp Normal file
View File

@ -0,0 +1,127 @@
#include <Arduino.h>
#include <Update.h>
#include "config.h"
#include "updater.h"
#include "http_client_wrapper.h"
void Updater::run() {
DEBUG("Updater is running...\n");
HTTPClientWrapper* http = new HTTPClientWrapper();
DEBUG("Requesting update info...\n");
bool result = http->get(OTA_UPDATE_URL);
if (!result) {
ERROR("Updater failed requesting %s.\n", OTA_UPDATE_URL);
return;
}
String line = http->readUntil("\n");
if (!line.startsWith("VERSION=")) {
ERROR("Expected first line to be VERSION.\n");
return;
}
uint16_t version = line.substring(8).toInt();
if (version==0) {
ERROR("Could not parse version number.\n");
return;
}
DEBUG("Found version %d. My version is %d.\n", version, OTA_VERSION);
if (version <= OTA_VERSION) {
return;
}
line = http->readUntil("\n");
if (!line.startsWith("IMAGE_PATH=")) {
ERROR("Expected second line to be IMAGE_PATH.\n");
return;
}
String image_path = line.substring(11);
image_path.trim();
line = http->readUntil("\n");
if (!line.startsWith("SPIFFS_PATH=")) {
ERROR("Expected third line to be SPIFFS_PATH.\n");
return;
}
String spiffs_path = line.substring(12);
spiffs_path.trim();
http->close();
delete http;
result = do_update(U_FLASH, image_path);
if (result) {
do_update(U_SPIFFS, spiffs_path);
}
DEBUG("Done. Rebooting...\n");
ESP.restart();
}
bool Updater::do_update(int command, String url) {
HTTPClientWrapper* http = new HTTPClientWrapper();
bool result = http->get(url);
if (!result) {
ERROR("Updater failed requesting %s.\n", url.c_str());
return false;
}
result = Update.begin(http->getSize(), command);
if (!result) {
ERROR("Update could not be started.\n");
return false;
}
uint8_t buf[512];
uint16_t len;
while((len = http->read(buf, 512))) {
Update.write(buf, 512);
}
http->close();
delete http;
result = Update.end();
if (!result) {
ERROR("Writing the update failed somewhere. Aborted.\n");
return false;
}
return true;
}
void Updater::update_spiffs() {
HTTPClientWrapper* http = new HTTPClientWrapper();
DEBUG("Requesting update info...\n");
bool result = http->get(OTA_UPDATE_URL);
if (!result) {
ERROR("Updater failed requesting %s.\n", OTA_UPDATE_URL);
return;
}
String line = http->readUntil("\n");
if (!line.startsWith("VERSION=")) {
ERROR("Expected first line to be VERSION.\n");
return;
}
uint16_t version = line.substring(8).toInt();
if (version==0) {
ERROR("Could not parse version number.\n");
return;
} else if (version > OTA_VERSION) {
DEBUG("Found newer version %d. My version is %d. Starting full update!\n", version, OTA_VERSION);
run();
} else {
DEBUG("Loading SPIFFS image.\n");
line = http->readUntil("\n");
if (!line.startsWith("IMAGE_PATH=")) {
ERROR("Expected second line to be IMAGE_PATH.\n");
return;
}
line = http->readUntil("\n");
if (!line.startsWith("SPIFFS_PATH=")) {
ERROR("Expected third line to be SPIFFS_PATH.\n");
return;
}
String spiffs_path = line.substring(12);
spiffs_path.trim();
do_update(U_SPIFFS, spiffs_path);
DEBUG("Done. Rebooting...\n");
delay(500);
ESP.restart();
}
http->close();
delete http;
}