Jelajahi Sumber

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

Sebastien 5 tahun lalu
induk
melakukan
4369614bb4

+ 51 - 10
components/cmd_system/cmd_system.c

@@ -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()
 {
 {

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

@@ -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:

+ 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);
 							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();
-					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 ")) {
 				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 ")) {

+ 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 "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;

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

@@ -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.
  *
  *

+ 2 - 3
main/config.c

@@ -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);

+ 1 - 1
main/config.h

@@ -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();

+ 1 - 1
main/esp_app_main.c

@@ -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>