Bug Fix: OTA now works from the Squeezelite app partition - release

This commit is contained in:
Sebastien
2019-11-13 17:16:57 -05:00
parent 2c3df6a8ce
commit 4369614bb4
8 changed files with 123 additions and 26 deletions

View File

@@ -6,14 +6,13 @@
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. CONDITIONS OF ANY KIND, either express or implied.
*/ */
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE //#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "esp_log.h" #include "esp_log.h"
#include "esp_console.h" #include "esp_console.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_sleep.h"
#include "esp_spi_flash.h" #include "esp_spi_flash.h"
#include "driver/rtc_io.h" #include "driver/rtc_io.h"
#include "driver/uart.h" #include "driver/uart.h"
@@ -28,13 +27,15 @@
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#include "platform_esp32.h" #include "platform_esp32.h"
#include "nvs_utilities.h" #include "nvs_utilities.h"
#include "esp_sleep.h"
#include "driver/uart.h" // for the uart driver access
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS #ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
#define WITH_TASKS_INFO 1 #define WITH_TASKS_INFO 1
#endif #endif
static const char * TAG = "platform_esp32"; static const char * TAG = "cmd_system";
static void register_free(); static void register_free();
static void register_heap(); static void register_heap();
@@ -43,6 +44,7 @@ static void register_restart();
static void register_deep_sleep(); static void register_deep_sleep();
static void register_light_sleep(); static void register_light_sleep();
static void register_factory_boot(); static void register_factory_boot();
static void register_restart_ota();
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
static void register_tasks(); static void register_tasks();
#endif #endif
@@ -56,6 +58,7 @@ void register_system()
register_deep_sleep(); register_deep_sleep();
register_light_sleep(); register_light_sleep();
register_factory_boot(); register_factory_boot();
register_restart_ota();
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
register_tasks(); register_tasks();
#endif #endif
@@ -99,6 +102,17 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
#if RECOVERY_APPLICATION #if RECOVERY_APPLICATION
if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){ if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
ESP_LOGW(TAG,"RECOVERY application is already active"); ESP_LOGW(TAG,"RECOVERY application is already active");
ESP_LOGW(TAG, "Restarting after tx complete");
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
esp_restart();
return ESP_OK;
}
#else
if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){
ESP_LOGW(TAG,"SQUEEZELITE application is already active");
ESP_LOGW(TAG, "Restarting after tx complete");
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
esp_restart();
return ESP_OK; return ESP_OK;
} }
#endif #endif
@@ -115,30 +129,36 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
else else
{ {
partition = (esp_partition_t *) esp_partition_get(it); partition = (esp_partition_t *) esp_partition_get(it);
ESP_LOGD(TAG, "Releasing partition iterator");
esp_partition_iterator_release(it);
if(partition != NULL){ if(partition != NULL){
ESP_LOGI(TAG, "Found application partition %s sub type %u", partition->label,partition_subtype); ESP_LOGI(TAG, "Found application partition %s sub type %u", partition->label,partition_subtype);
err=esp_ota_set_boot_partition(partition); err=esp_ota_set_boot_partition(partition);
if(err!=ESP_OK){ if(err!=ESP_OK){
ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err)); ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err));
bFound=false;
set_status_message(ERROR, "Unable to select partition for reboot."); set_status_message(ERROR, "Unable to select partition for reboot.");
} }
else{ else{
ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
bFound=true; bFound=true;
set_status_message(WARNING, "Rebooting!"); set_status_message(WARNING, "Rebooting!");
} }
} }
else else
{ {
ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype); ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
set_status_message(ERROR, "Partition not found."); set_status_message(ERROR, "Partition not found.");
} }
esp_partition_iterator_release(it); ESP_LOGD(TAG, "Yielding to other processes");
taskYIELD();
if(bFound) { if(bFound) {
ESP_LOGW(TAG,"Configuration %s changes. ",config_has_changes()?"has":"does not have");
if(!wait_for_commit()){ if(!wait_for_commit()){
ESP_LOGW(TAG,"Unable to commit configuration. "); ESP_LOGW(TAG,"Unable to commit configuration. ");
} }
ESP_LOGI(TAG, "Restarting!."); ESP_LOGW(TAG, "Restarting after tx complete");
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
esp_restart(); esp_restart();
} }
} }
@@ -148,39 +168,50 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
static int restart(int argc, char **argv) static int restart(int argc, char **argv)
{ {
ESP_LOGW(TAG, "\n\nPerforming a simple restart to the currently active partition.");
if(!wait_for_commit()){ if(!wait_for_commit()){
ESP_LOGW(TAG,"Unable to commit configuration. "); ESP_LOGW(TAG,"Unable to commit configuration. ");
} }
ESP_LOGW(TAG, "Restarting"); ESP_LOGW(TAG, "Restarting after tx complete");
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
esp_restart(); esp_restart();
return 0; return 0;
} }
void simple_restart() void simple_restart()
{ {
ESP_LOGW(TAG,"\n\n Called to perform a simple system reboot.");
if(!wait_for_commit()){ if(!wait_for_commit()){
ESP_LOGW(TAG,"Unable to commit configuration. "); ESP_LOGW(TAG,"Unable to commit configuration. ");
} }
ESP_LOGW(TAG, "Restarting"); ESP_LOGW(TAG, "Restarting after tx complete");
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
esp_restart(); esp_restart();
} }
esp_err_t guided_restart_ota(){ esp_err_t guided_restart_ota(){
ESP_LOGW(TAG,"\n\nCalled for a reboot to OTA Application");
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
// If we're still alive, then there may not be an ota partition to boot from
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
return ESP_FAIL; // return fail. This should never return... we're rebooting! return ESP_FAIL; // return fail. This should never return... we're rebooting!
} }
esp_err_t guided_factory(){ esp_err_t guided_factory(){
ESP_LOGW(TAG,"\n\nCalled for a reboot to recovery application");
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
return ESP_FAIL; // return fail. This should never return... we're rebooting! return ESP_FAIL; // return fail. This should never return... we're rebooting!
} }
static int restart_factory(int argc, char **argv) static int restart_factory(int argc, char **argv)
{ {
ESP_LOGW(TAG, "Executing guided boot into recovery");
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
return 0; // return fail. This should never return... we're rebooting! return 0; // return fail. This should never return... we're rebooting!
} }
static int restart_ota(int argc, char **argv)
{
ESP_LOGW(TAG, "Executing guided boot into ota app 0");
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
return 0; // return fail. This should never return... we're rebooting!
}
static void register_restart() static void register_restart()
{ {
const esp_console_cmd_t cmd = { const esp_console_cmd_t cmd = {
@@ -191,6 +222,16 @@ static void register_restart()
}; };
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
static void register_restart_ota()
{
const esp_console_cmd_t cmd = {
.command = "restart_ota",
.help = "Selects the ota app partition to boot from and performa a software reset of the chip",
.hint = NULL,
.func = &restart_ota,
};
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
static void register_factory_boot() static void register_factory_boot()
{ {

View File

@@ -6,7 +6,7 @@
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. CONDITIONS OF ANY KIND, either express or implied.
*/ */
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE //#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "esp_system.h" #include "esp_system.h"
@@ -175,8 +175,10 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
uint32_t elapsed_ms= (tv.tv_sec-ota_status.OTA_start.tv_sec )*1000+(tv.tv_usec-ota_status.OTA_start.tv_usec)/1000; uint32_t elapsed_ms= (tv.tv_sec-ota_status.OTA_start.tv_sec )*1000+(tv.tv_usec-ota_status.OTA_start.tv_usec)/1000;
ESP_LOGI(TAG,"OTA progress : %d/%d (%d pct), %d KB/s", ota_status.ota_actual_len, ota_status.ota_total_len, ota_status.newpct, elapsed_ms>0?ota_status.ota_actual_len*1000/elapsed_ms/1024:0); ESP_LOGI(TAG,"OTA progress : %d/%d (%d pct), %d KB/s", ota_status.ota_actual_len, ota_status.ota_total_len, ota_status.newpct, elapsed_ms>0?ota_status.ota_actual_len*1000/elapsed_ms/1024:0);
wifi_manager_refresh_ota_json(); wifi_manager_refresh_ota_json();
ota_status.lastpct=ota_status.newpct; ota_status.lastpct=ota_status.newpct;
} }
taskYIELD();
} }
break; break;
case HTTP_EVENT_ON_FINISH: case HTTP_EVENT_ON_FINISH:

View File

@@ -474,11 +474,8 @@ void http_server_netconn_serve(struct netconn *conn) {
ESP_LOGW(TAG, "Starting process OTA for url %s",otaURL); ESP_LOGW(TAG, "Starting process OTA for url %s",otaURL);
#else #else
ESP_LOGW(TAG, "Restarting system to process OTA for url %s",otaURL); ESP_LOGW(TAG, "Restarting system to process OTA for url %s",otaURL);
// close the connection cleanly
netconn_close(conn);
netconn_delete(conn);
#endif #endif
start_ota(otaURL,false); wifi_manager_reboot_ota(otaURL);
free(otaURL); free(otaURL);
} }
} }
@@ -537,23 +534,23 @@ void http_server_netconn_serve(struct netconn *conn) {
netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */ netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */
netconn_close(conn); netconn_close(conn);
netconn_delete(conn); netconn_delete(conn);
guided_restart_ota(); wifi_manager_reboot(OTA);
ESP_LOGI(TAG, "http_server_netconn_serve: done serving POST reboot.json"); ESP_LOGI(TAG, "http_server_netconn_serve: done serving POST reboot.json");
} }
else if(strstr(line, "POST /reboot.json ")) { else if(strstr(line, "POST /reboot.json ")) {
ESP_LOGI(TAG, "http_server_netconn_serve: POST restart.json"); ESP_LOGI(TAG, "http_server_netconn_serve: POST reboot.json");
netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */ netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */
netconn_close(conn); netconn_close(conn);
netconn_delete(conn); netconn_delete(conn);
simple_restart(); wifi_manager_reboot(RESTART);
ESP_LOGI(TAG, "http_server_netconn_serve: done serving POST restart.json"); ESP_LOGI(TAG, "http_server_netconn_serve: done serving POST reboot.json");
} }
else if(strstr(line, "POST /recovery.json ")) { else if(strstr(line, "POST /recovery.json ")) {
ESP_LOGI(TAG, "http_server_netconn_serve: POST recovery.json"); ESP_LOGI(TAG, "http_server_netconn_serve: POST recovery.json");
netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */ netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */
netconn_close(conn); netconn_close(conn);
netconn_delete(conn); netconn_delete(conn);
guided_factory(); wifi_manager_reboot(RECOVERY);
ESP_LOGI(TAG, "http_server_netconn_serve: done serving POST recovery.json"); ESP_LOGI(TAG, "http_server_netconn_serve: done serving POST recovery.json");
} }
else if(strstr(line, "GET /status.json ")) { else if(strstr(line, "GET /status.json ")) {

View File

@@ -61,6 +61,7 @@ Contains the freeRTOS task and all necessary support
#include "driver/adc.h" #include "driver/adc.h"
#include "cJSON.h" #include "cJSON.h"
#include "nvs_utilities.h" #include "nvs_utilities.h"
#include "cmd_system.h"
#ifndef RECOVERY_APPLICATION #ifndef RECOVERY_APPLICATION
#define RECOVERY_APPLICATION 0 #define RECOVERY_APPLICATION 0
@@ -222,6 +223,35 @@ void wifi_manager_disconnect_async(){
//xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete
} }
void wifi_manager_reboot_ota(char * url){
if(url == NULL){
wifi_manager_send_message(ORDER_RESTART_OTA, NULL);
}
else {
wifi_manager_send_message(ORDER_RESTART_OTA_URL,strdup(url) );
}
}
void wifi_manager_reboot(reboot_type_t rtype){
switch (rtype) {
case OTA:
wifi_manager_send_message(ORDER_RESTART_OTA, NULL);
break;
case RECOVERY:
wifi_manager_send_message(ORDER_RESTART_RECOVERY, NULL);
break;
case RESTART:
wifi_manager_send_message(ORDER_RESTART, NULL);
break;
default:
ESP_LOGE(TAG,"Unknown reboot type %d", rtype);
break;
}
wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
//xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete
}
void wifi_manager_init_wifi(){ void wifi_manager_init_wifi(){
/* event handler and event group for the wifi driver */ /* event handler and event group for the wifi driver */
ESP_LOGD(TAG, "Initializing wifi. Creating event group"); ESP_LOGD(TAG, "Initializing wifi. Creating event group");
@@ -1432,6 +1462,20 @@ void wifi_manager( void * pvParameters ){
/* callback */ /* callback */
if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL); if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
break;
case ORDER_RESTART_OTA:
guided_restart_ota();
break;
case ORDER_RESTART_OTA_URL:
start_ota(msg.param,false);
free(msg.param);
break;
case ORDER_RESTART_RECOVERY:
guided_factory();
break;
case ORDER_RESTART:
simple_restart();
break; break;
default: default:
break; break;

View File

@@ -200,10 +200,24 @@ typedef enum message_code_t {
EVENT_SCAN_DONE = 13, EVENT_SCAN_DONE = 13,
EVENT_STA_GOT_IP = 14, EVENT_STA_GOT_IP = 14,
EVENT_REFRESH_OTA = 15, EVENT_REFRESH_OTA = 15,
MESSAGE_CODE_COUNT = 16 /* important for the callback array */ ORDER_RESTART_OTA = 16,
ORDER_RESTART_RECOVERY = 17,
ORDER_RESTART_OTA_URL = 18,
ORDER_RESTART = 19,
MESSAGE_CODE_COUNT = 20 /* important for the callback array */
}message_code_t; }message_code_t;
typedef enum reboot_type_t{
OTA,
RECOVERY,
RESTART,
} reboot_type_t;
void wifi_manager_reboot(reboot_type_t rtype);
void wifi_manager_reboot_ota(char * url);
/** /**
* @brief simplified reason codes for a lost connection. * @brief simplified reason codes for a lost connection.
* *

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE //#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "config.h" #include "config.h"
#include "nvs_utilities.h" #include "nvs_utilities.h"
@@ -565,7 +565,7 @@ void config_delete_key(const char *key){
ESP_LOGV(TAG, "Structure before delete \n%s", struc_str); ESP_LOGV(TAG, "Structure before delete \n%s", struc_str);
free(struc_str); free(struc_str);
} }
cJSON * entry = cJSON_GetObjectItemCaseSensitive(nvs_json, key); cJSON * entry = cJSON_DetachItemFromObjectCaseSensitive(nvs_json, key);
if(entry !=NULL){ if(entry !=NULL){
ESP_LOGI(TAG, "Removing config key [%s]", entry->string); ESP_LOGI(TAG, "Removing config key [%s]", entry->string);
cJSON_Delete(entry); cJSON_Delete(entry);
@@ -574,7 +574,6 @@ void config_delete_key(const char *key){
ESP_LOGV(TAG, "Structure after delete \n%s", struc_str); ESP_LOGV(TAG, "Structure after delete \n%s", struc_str);
free(struc_str); free(struc_str);
} }
} }
else { else {
ESP_LOGW(TAG, "Unable to remove config key [%s]: not found.", key); ESP_LOGW(TAG, "Unable to remove config key [%s]: not found.", key);

View File

@@ -10,7 +10,7 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
bool config_has_uncommitted(); bool config_has_changes();
void config_commit_to_nvs(); void config_commit_to_nvs();
void config_start_timer(); void config_start_timer();
void config_init(); void config_init();

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE //#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "platform_esp32.h" #include "platform_esp32.h"
#include "led.h" #include "led.h"
#include <stdio.h> #include <stdio.h>