Browse Source

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

Sebastien 5 years ago
parent
commit
4369614bb4

+ 51 - 10
components/cmd_system/cmd_system.c

@@ -6,14 +6,13 @@
    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    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 <string.h>
 #include <ctype.h>
 #include "esp_log.h"
 #include "esp_console.h"
 #include "esp_system.h"
-#include "esp_sleep.h"
 #include "esp_spi_flash.h"
 #include "driver/rtc_io.h"
 #include "driver/uart.h"
@@ -28,13 +27,15 @@
 #include "esp_ota_ops.h"
 #include "platform_esp32.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
 #define WITH_TASKS_INFO 1
 #endif
 
 
-static const char * TAG = "platform_esp32";
+static const char * TAG = "cmd_system";
 
 static void register_free();
 static void register_heap();
@@ -43,6 +44,7 @@ static void register_restart();
 static void register_deep_sleep();
 static void register_light_sleep();
 static void register_factory_boot();
+static void register_restart_ota();
 #if WITH_TASKS_INFO
 static void register_tasks();
 #endif
@@ -56,6 +58,7 @@ void register_system()
     register_deep_sleep();
     register_light_sleep();
     register_factory_boot();
+    register_restart_ota();
 #if WITH_TASKS_INFO
     register_tasks();
 #endif
@@ -99,6 +102,17 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
 #if RECOVERY_APPLICATION
 	if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
 		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;
 	}
 #endif
@@ -115,30 +129,36 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
 	else
 	{
 		partition = (esp_partition_t *) esp_partition_get(it);
+		ESP_LOGD(TAG, "Releasing partition iterator");
+		esp_partition_iterator_release(it);
 		if(partition != NULL){
 			ESP_LOGI(TAG, "Found application partition %s sub type %u", partition->label,partition_subtype);
 			err=esp_ota_set_boot_partition(partition);
 			if(err!=ESP_OK){
 				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.");
 			}
 			else{
+				ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
 				bFound=true;
 				set_status_message(WARNING, "Rebooting!");
 			}
-
 		}
 		else
 		{
 			ESP_LOGE(TAG,"partition type %u not found!  Unable to reboot to recovery.",partition_subtype);
 			set_status_message(ERROR, "Partition not found.");
 		}
-		esp_partition_iterator_release(it);
+		ESP_LOGD(TAG, "Yielding to other processes");
+		taskYIELD();
 		if(bFound) {
+			ESP_LOGW(TAG,"Configuration %s changes. ",config_has_changes()?"has":"does not have");
 			if(!wait_for_commit()){
 				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();
 		}
 	}
@@ -148,39 +168,50 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
 
 static int restart(int argc, char **argv)
 {
+	ESP_LOGW(TAG, "\n\nPerforming a simple restart to the currently active partition.");
 	if(!wait_for_commit()){
 		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();
     return 0;
 }
 
 void simple_restart()
 {
+	ESP_LOGW(TAG,"\n\n Called to perform a simple system reboot.");
 	if(!wait_for_commit()){
 		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_err_t guided_restart_ota(){
+	ESP_LOGW(TAG,"\n\nCalled for a reboot to OTA Application");
     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!
 }
 esp_err_t guided_factory(){
+	ESP_LOGW(TAG,"\n\nCalled for a reboot to recovery application");
 	guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
 	return ESP_FAIL; // return fail.  This should never return... we're rebooting!
 }
 static int restart_factory(int argc, char **argv)
 {
+	ESP_LOGW(TAG, "Executing guided boot into recovery");
 	guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
 	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()
 {
     const esp_console_cmd_t cmd = {
@@ -191,6 +222,16 @@ static void register_restart()
     };
     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()
 {

+ 3 - 1
components/squeezelite-ota/squeezelite-ota.c

@@ -6,7 +6,7 @@
    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    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/task.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;
 				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();
+
 				ota_status.lastpct=ota_status.newpct;
 			}
+			taskYIELD();
         }
         break;
     case HTTP_EVENT_ON_FINISH:

+ 6 - 9
components/wifi-manager/http_server.c

@@ -474,11 +474,8 @@ void http_server_netconn_serve(struct netconn *conn) {
 							ESP_LOGW(TAG,   "Starting process OTA for url %s",otaURL);
 #else
 							ESP_LOGW(TAG,   "Restarting system to process OTA for url %s",otaURL);
-							// close the connection cleanly
-							netconn_close(conn);
-							netconn_delete(conn);
 #endif
-							start_ota(otaURL,false);
+							wifi_manager_reboot_ota(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_close(conn);
 					netconn_delete(conn);
-					guided_restart_ota();
+					wifi_manager_reboot(OTA);
 					ESP_LOGI(TAG,   "http_server_netconn_serve: done serving 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_close(conn);
 					netconn_delete(conn);
-					simple_restart();
-					ESP_LOGI(TAG,   "http_server_netconn_serve: done serving POST restart.json");
+					wifi_manager_reboot(RESTART);
+					ESP_LOGI(TAG,   "http_server_netconn_serve: done serving POST reboot.json");
 				}
 				else if(strstr(line, "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_close(conn);
 					netconn_delete(conn);
-					guided_factory();
+					wifi_manager_reboot(RECOVERY);
 					ESP_LOGI(TAG,   "http_server_netconn_serve: done serving POST recovery.json");
 				}
 				else if(strstr(line, "GET /status.json ")) {

+ 44 - 0
components/wifi-manager/wifi_manager.c

@@ -61,6 +61,7 @@ Contains the freeRTOS task and all necessary support
 #include "driver/adc.h"
 #include "cJSON.h"
 #include "nvs_utilities.h"
+#include "cmd_system.h"
 
 #ifndef RECOVERY_APPLICATION
 #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
 }
 
+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(){
 	/* event handler and event group for the wifi driver */
 	ESP_LOGD(TAG,   "Initializing wifi.  Creating event group");
@@ -1432,6 +1462,20 @@ void wifi_manager( void * pvParameters ){
 				/* callback */
 				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;
 			default:
 				break;

+ 15 - 1
components/wifi-manager/wifi_manager.h

@@ -200,10 +200,24 @@ typedef enum message_code_t {
 	EVENT_SCAN_DONE = 13,
 	EVENT_STA_GOT_IP = 14,
 	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;
 
+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.
  *

+ 2 - 3
main/config.c

@@ -18,7 +18,7 @@
  * 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 "nvs_utilities.h"
 
@@ -565,7 +565,7 @@ void config_delete_key(const char *key){
 		ESP_LOGV(TAG, "Structure before delete \n%s", struc_str);
 		free(struc_str);
 	}
-	cJSON * entry = cJSON_GetObjectItemCaseSensitive(nvs_json, key);
+	cJSON * entry = cJSON_DetachItemFromObjectCaseSensitive(nvs_json, key);
 	if(entry !=NULL){
 		ESP_LOGI(TAG, "Removing config key [%s]", entry->string);
 		cJSON_Delete(entry);
@@ -574,7 +574,6 @@ void config_delete_key(const char *key){
 			ESP_LOGV(TAG, "Structure after delete \n%s", struc_str);
 			free(struc_str);
 		}
-
 	}
 	else {
 		ESP_LOGW(TAG, "Unable to remove config key [%s]: not found.", key);

+ 1 - 1
main/config.h

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

+ 1 - 1
main/esp_app_main.c

@@ -18,7 +18,7 @@
  * 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 "led.h"
 #include <stdio.h>