浏览代码

OTA werks... sort of!

Sebastien 5 年之前
父节点
当前提交
46024a358e

+ 19 - 7
components/squeezelite-ota/squeezelite-ota.c

@@ -18,14 +18,15 @@
 #include <stdbool.h>
 #include "nvs.h"
 #include "nvs_flash.h"
-
+#include "cmd_system.h"
 #include "esp_err.h"
 #include "tcpip_adapter.h"
-
+#include "squeezelite-ota.h"
 
 static const char *TAG = "squeezelite-ota";
 extern const uint8_t server_cert_pem_start[] asm("_binary_github_pem_start");
 extern const uint8_t server_cert_pem_end[] asm("_binary_github_pem_end");
+extern bool wait_for_wifi();
 
 #define OTA_URL_SIZE 256
 static char ota_status[31]={0};
@@ -45,7 +46,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
         break;
     case HTTP_EVENT_ON_CONNECTED:
         ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
-       // strncpy(ota_status,"HTTP_EVENT_ON_CONNECTED",sizeof(ota_status)-1);
+       // strncpy(ota_status,"HTTP_EVENT_ON_CONNECTED",sizsffeof(ota_status)-1);
                 break;
     case HTTP_EVENT_HEADER_SENT:
         ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
@@ -53,10 +54,15 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
         break;
     case HTTP_EVENT_ON_HEADER:
         ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, status_code=%d, key=%s, value=%s",esp_http_client_get_status_code(evt->client),evt->header_key, evt->header_value);
+        // check for header Content-Length:2222240
+        // convert to numeric and store in total bin size
+
         //snprintf(ota_status,sizeof(ota_status)-1,"HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
         break;
     case HTTP_EVENT_ON_DATA:
         ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, status_code=%d, len=%d",esp_http_client_get_status_code(evt->client), evt->data_len);
+        //increment the total data received, then divide by the bin size and store as ota_pct
+
         //snprintf(ota_status,sizeof(ota_status)-1, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
         break;
     case HTTP_EVENT_ON_FINISH:
@@ -73,9 +79,8 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
 void ota_task(void *pvParameter)
 {
 	char * bin_url=(char *)pvParameter;
-    ESP_LOGI(TAG, "Starting OTA example");
 
-    esp_http_client_config_t config = {
+     esp_http_client_config_t config = {
         .url = bin_url,
         .cert_pem = (char *)server_cert_pem_start,
         .event_handler = _http_event_handler,
@@ -97,8 +102,10 @@ void ota_task(void *pvParameter)
 
 void start_ota(const char * bin_url)
 {
-    // Initialize NVS.
-    esp_err_t err = nvs_flash_init();
+	ESP_LOGW(TAG, "Called to update the firmware from url: %s",bin_url);
+#if RECOVERY_APPLICATION
+	// Initialize NVS.
+	esp_err_t err = nvs_flash_init();
     if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
     	// todo: If we ever change the size of the nvs partition, we need to figure out a mechanism to enlarge the nvs.
         // 1.OTA app partition table has a smaller NVS partition size than the non-OTA
@@ -114,4 +121,9 @@ void start_ota(const char * bin_url)
 
     ESP_LOGI(TAG, "Starting ota: %s", urlPtr);
     xTaskCreate(&ota_task, "ota_task", 8192*3,(void *) urlPtr, 5, NULL);
+#else
+    ESP_LOGW(TAG, "Rebooting to recovery to complete the installation");
+    guided_factory();
+#endif
+
 }

+ 17 - 0
components/squeezelite-ota/squeezelite-ota.h

@@ -0,0 +1,17 @@
+/*
+ * squeezelite-ota.h
+ *
+ *  Created on: 25 sept. 2019
+ *      Author: sle11
+ */
+
+#ifndef COMPONENTS_SQUEEZELITE_OTA_SQUEEZELITE_OTA_H_
+#define COMPONENTS_SQUEEZELITE_OTA_SQUEEZELITE_OTA_H_
+
+void start_ota(const char * bin_url);
+const char * ota_get_status();
+uint8_t ota_get_pct_complete();
+
+
+
+#endif /* COMPONENTS_SQUEEZELITE_OTA_SQUEEZELITE_OTA_H_ */

+ 19 - 5
components/wifi-manager/http_server.c

@@ -46,6 +46,7 @@ static const char array_separator[]=",";
 static TaskHandle_t task_http_server = NULL;
 extern char current_namespace[];
 
+extern void start_ota(const char * bin_url);
 /**
  * @brief embedded binary data.
  * @see file "component.mk"
@@ -274,8 +275,8 @@ void http_server_netconn_serve(struct netconn *conn) {
 					char autoexec_name[21]={0};
 					char * autoexec_value=NULL;
 					uint8_t autoexec_flag=0;
-					int buflen=MAX_COMMAND_LINE_SIZE+strlen(template)+1;
-					char * buff = malloc(buflen);
+					int locbuflen=MAX_COMMAND_LINE_SIZE+strlen(template)+1;
+					char * buff = malloc(locbuflen);
           			char *s = "\"";
           			char *r = "\\\"";
 					if(!buff)
@@ -290,7 +291,7 @@ void http_server_netconn_serve(struct netconn *conn) {
 						esp_err_t esp_err;
 						netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY);
 						autoexec_flag = wifi_manager_get_flag();
-						snprintf(buff,buflen-1, json_start, RECOVERY_APPLICATION, autoexec_flag);
+						snprintf(buff,locbuflen-1, json_start, RECOVERY_APPLICATION, autoexec_flag);
 						netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY);
 
 						ESP_LOGI(TAG, "About to get config from flash");
@@ -313,7 +314,7 @@ void http_server_netconn_serve(struct netconn *conn) {
 								autoexec_value = wifi_manager_alloc_get_config(info.key, &l);
 								strreplace(autoexec_value, s, r);
 								ESP_LOGI(TAG,"Namespace %s, key=%s, value=%s", info.namespace_name, info.key,autoexec_value );
-								snprintf(buff, buflen-1, template, info.key, autoexec_value);
+								snprintf(buff, locbuflen-1, template, info.key, autoexec_value);
 								netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY);
 								ESP_LOGD(TAG,"Freeing memory for command %s name", autoexec_name);
 								free(autoexec_value );
@@ -336,6 +337,8 @@ void http_server_netconn_serve(struct netconn *conn) {
 					char  last_parm_name[41]={0};
 					uint8_t autoexec_flag=0;
 					bool bErrorFound=false;
+					bool bOTA=false;
+					char * otaURL=NULL;
 
 					while(last_parm!=NULL){
 						// Search will return
@@ -344,6 +347,12 @@ void http_server_netconn_serve(struct netconn *conn) {
 						last_parm = http_server_search_header(next_parm, "X-Custom-", &lenA, last_parm_name, sizeof(last_parm_name)-1,&next_parm);
 						if(last_parm!=NULL){
 							ESP_LOGI(TAG, "http_server_netconn_serve: config.json/ call, found parameter %s=%s, length %i", last_parm_name, last_parm, lenA);
+							if(strcmp(last_parm_name, "fwurl")==0){
+								// we're getting a request to do an OTA from that URL
+								ESP_LOGI(TAG, "OTA parameter found!");
+								otaURL=strdup(last_parm);
+								bOTA=true;
+							}
 							if(strcmp(last_parm_name, "autoexec")==0){
 								autoexec_flag = atoi(last_parm);
 								wifi_manager_save_autoexec_flag(autoexec_flag);
@@ -369,6 +378,10 @@ void http_server_netconn_serve(struct netconn *conn) {
 					}
 					else{
 						netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); //200ok
+						if(bOTA){
+							ESP_LOGI(TAG, "Initiating OTA for url %s",otaURL);
+							start_ota(otaURL);
+						}
 					}
 
 				} 
@@ -440,7 +453,8 @@ void http_server_netconn_serve(struct netconn *conn) {
 			netconn_write(conn, http_404_hdr, sizeof(http_404_hdr) - 1, NETCONN_NOCOPY);
 		}
 	}
-
+	// reset the buffer with nulls
+	memset(buf, 0x00,buflen);
 	/* free the buffer */
 	netbuf_delete(inbuf);
 }

+ 2 - 4
components/wifi-manager/wifi_manager.c

@@ -56,14 +56,12 @@ Contains the freeRTOS task and all necessary support
 #include "lwip/ip4_addr.h"
 #include "esp_ota_ops.h"
 #include "esp_app_format.h"
+#include "squeezelite-ota.h"
 
 #ifndef SQUEEZELITE_ESP32_RELEASE_URL
 #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
 #endif
-#if RECOVERY_APPLICATION
-extern const char * ota_get_status();
-extern uint8_t ota_get_pct_complete();
-#endif
+
 /* objects used to manipulate the main queue of events */
 QueueHandle_t wifi_manager_queue;
 

+ 5 - 0
main/console.c

@@ -282,9 +282,14 @@ void console_start() {
     esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
     cfg.thread_name= "console";
     cfg.inherit_cfg = true;
+#if RECOVERY_APPLICATION
+    // make sure the stack is large enough for http processing with redirects.
+	cfg.stack_size = 1024*100 ;
+#endif
     esp_pthread_set_cfg(&cfg);
 	pthread_attr_t attr;
 	pthread_attr_init(&attr);
+
 	pthread_create(&thread_console, &attr, console_thread, NULL);
 	pthread_attr_destroy(&attr);
 }

+ 19 - 2
main/esp_app_main.c

@@ -38,15 +38,17 @@
 #include "lwip/api.h"
 #include "lwip/err.h"
 #include "lwip/netdb.h"
-
+#include "nvs_utilities.h"
 #include "http_server.h"
 #include "wifi_manager.h"
+#include "squeezelite-ota.h"
+
 static EventGroupHandle_t wifi_event_group;
 const int CONNECTED_BIT = BIT0;
 #define JOIN_TIMEOUT_MS (10000)
 
 static const char TAG[] = "esp_app_main";
-
+char * fwurl = NULL;
 
 #ifdef CONFIG_SQUEEZEAMP
 #define LED_GREEN_GPIO 	12
@@ -55,15 +57,18 @@ static const char TAG[] = "esp_app_main";
 #define LED_GREEN_GPIO 	0
 #define LED_RED_GPIO	0
 #endif
+static bool bWifiConnected=false;
 
 /* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */
 void cb_connection_got_ip(void *pvParameter){
 	ESP_LOGI(TAG, "I have a connection!");
 	xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
+	bWifiConnected=true;
 	led_unpush(LED_GREEN);
 }
 void cb_connection_sta_disconnected(void *pvParameter){
 	led_blink_pushed(LED_GREEN, 250, 250);
+	bWifiConnected=false;
 	xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
 }
 bool wait_for_wifi(){
@@ -88,6 +93,7 @@ void app_main()
 	led_config(LED_GREEN, LED_GREEN_GPIO, 0);
 	led_config(LED_RED, LED_RED_GPIO, 0);
 	wifi_event_group = xEventGroupCreate();
+	xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
 	
 	/* start the wifi manager */
 	led_blink(LED_GREEN, 250, 250);
@@ -95,6 +101,17 @@ void app_main()
 	wifi_manager_set_callback(EVENT_STA_GOT_IP, &cb_connection_got_ip);
 	wifi_manager_set_callback(WIFI_EVENT_STA_DISCONNECTED, &cb_connection_sta_disconnected);
 
+	char * fwurl = get_nvs_value_alloc(NVS_TYPE_STR, "fwurl");
+	if(fwurl){
+		// the first thing we need to do here is to erase the firmware url
+		// to avoid a boot loop
+		erase_nvs("fwurl");
+		while(!bWifiConnected){
+			wait_for_wifi();
+		}
+		ESP_LOGI(TAG,"Updating firmware from link: %s",fwurl);
+		start_ota(fwurl);
+	}
 
 	console_start();
 }

+ 18 - 0
main/nvs_utilities.c

@@ -210,4 +210,22 @@ esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint
 	nvs_close(nvs);
 	return err;
 }
+esp_err_t erase_nvs(const char *key)
+{
+    nvs_handle nvs;
+
+    esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs);
+    if (err == ESP_OK) {
+        err = nvs_erase_key(nvs, key);
+        if (err == ESP_OK) {
+            err = nvs_commit(nvs);
+            if (err == ESP_OK) {
+                ESP_LOGI(TAG, "Value with key '%s' erased", key);
+            }
+        }
+        nvs_close(nvs);
+    }
+
+    return err;
+}
 

+ 1 - 0
main/nvs_utilities.h

@@ -9,6 +9,7 @@ esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data, siz
 esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data);
 esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint8_t buf_size);
 void * get_nvs_value_alloc(nvs_type_t type, const char *key);
+esp_err_t erase_nvs(const char *key);
 #ifdef __cplusplus
 }
 #endif

+ 1 - 1
main/platform_esp32.h

@@ -24,7 +24,7 @@
 #include "esp_pthread.h"
 
 extern void run_command(char * line);
-extern bool wait_for_wifi();
+extern  bool wait_for_wifi();
 extern void console_start();
 extern pthread_cond_t wifi_connect_suspend_cond;
 extern pthread_t wifi_connect_suspend_mutex;