|
|
@@ -6,10 +6,6 @@
|
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
|
*/
|
|
|
-#include <string.h>
|
|
|
-#include <sys/socket.h>
|
|
|
-#include <netdb.h>
|
|
|
-
|
|
|
#include "freertos/FreeRTOS.h"
|
|
|
#include "freertos/task.h"
|
|
|
#include "freertos/event_groups.h"
|
|
|
@@ -19,27 +15,21 @@
|
|
|
#include "esp_event_loop.h"
|
|
|
#include "esp_log.h"
|
|
|
#include "esp_ota_ops.h"
|
|
|
+#include "esp_http_client.h"
|
|
|
|
|
|
#include "nvs.h"
|
|
|
#include "nvs_flash.h"
|
|
|
|
|
|
#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
|
|
|
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
|
|
|
-#define EXAMPLE_SERVER_IP CONFIG_SERVER_IP
|
|
|
-#define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT
|
|
|
-#define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME
|
|
|
+#define EXAMPLE_SERVER_URL CONFIG_FIRMWARE_UPG_URL
|
|
|
#define BUFFSIZE 1024
|
|
|
-#define TEXT_BUFFSIZE 1024
|
|
|
|
|
|
-static const char *TAG = "ota";
|
|
|
+static const char *TAG = "native_ota_example";
|
|
|
/*an ota data write buffer ready to write to the flash*/
|
|
|
static char ota_write_data[BUFFSIZE + 1] = { 0 };
|
|
|
-/*an packet receive buffer*/
|
|
|
-static char text[BUFFSIZE + 1] = { 0 };
|
|
|
-/* an image total length*/
|
|
|
-static int binary_file_length = 0;
|
|
|
-/*socket id*/
|
|
|
-static int socket_id = -1;
|
|
|
+extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
|
|
|
+extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
|
|
|
|
|
|
/* FreeRTOS event group to signal when we are connected & ready to make a request */
|
|
|
static EventGroupHandle_t wifi_event_group;
|
|
|
@@ -90,85 +80,15 @@ static void initialise_wifi(void)
|
|
|
ESP_ERROR_CHECK( esp_wifi_start() );
|
|
|
}
|
|
|
|
|
|
-/*read buffer by byte still delim ,return read bytes counts*/
|
|
|
-static int read_until(char *buffer, char delim, int len)
|
|
|
-{
|
|
|
-// /*TODO: delim check,buffer check,further: do an buffer length limited*/
|
|
|
- int i = 0;
|
|
|
- while (buffer[i] != delim && i < len) {
|
|
|
- ++i;
|
|
|
- }
|
|
|
- return i + 1;
|
|
|
-}
|
|
|
-
|
|
|
-/* resolve a packet from http socket
|
|
|
- * return true if packet including \r\n\r\n that means http packet header finished,start to receive packet body
|
|
|
- * otherwise return false
|
|
|
- * */
|
|
|
-static bool read_past_http_header(char text[], int total_len, esp_ota_handle_t update_handle)
|
|
|
+static void http_cleanup(esp_http_client_handle_t client)
|
|
|
{
|
|
|
- /* i means current position */
|
|
|
- int i = 0, i_read_len = 0;
|
|
|
- while (text[i] != 0 && i < total_len) {
|
|
|
- i_read_len = read_until(&text[i], '\n', total_len);
|
|
|
- // if we resolve \r\n line,we think packet header is finished
|
|
|
- if (i_read_len == 2) {
|
|
|
- int i_write_len = total_len - (i + 2);
|
|
|
- memset(ota_write_data, 0, BUFFSIZE);
|
|
|
- /*copy first http packet body to write buffer*/
|
|
|
- memcpy(ota_write_data, &(text[i + 2]), i_write_len);
|
|
|
-
|
|
|
- esp_err_t err = esp_ota_write( update_handle, (const void *)ota_write_data, i_write_len);
|
|
|
- if (err != ESP_OK) {
|
|
|
- ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(err));
|
|
|
- return false;
|
|
|
- } else {
|
|
|
- ESP_LOGI(TAG, "esp_ota_write header OK");
|
|
|
- binary_file_length += i_write_len;
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- i += i_read_len;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-static bool connect_to_http_server()
|
|
|
-{
|
|
|
- ESP_LOGI(TAG, "Server IP: %s Server Port:%s", EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT);
|
|
|
-
|
|
|
- int http_connect_flag = -1;
|
|
|
- struct sockaddr_in sock_info;
|
|
|
-
|
|
|
- socket_id = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
- if (socket_id == -1) {
|
|
|
- ESP_LOGE(TAG, "Create socket failed!");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // set connect info
|
|
|
- memset(&sock_info, 0, sizeof(struct sockaddr_in));
|
|
|
- sock_info.sin_family = AF_INET;
|
|
|
- sock_info.sin_addr.s_addr = inet_addr(EXAMPLE_SERVER_IP);
|
|
|
- sock_info.sin_port = htons(atoi(EXAMPLE_SERVER_PORT));
|
|
|
-
|
|
|
- // connect to http server
|
|
|
- http_connect_flag = connect(socket_id, (struct sockaddr *)&sock_info, sizeof(sock_info));
|
|
|
- if (http_connect_flag == -1) {
|
|
|
- ESP_LOGE(TAG, "Connect to server failed! errno=%d", errno);
|
|
|
- close(socket_id);
|
|
|
- return false;
|
|
|
- } else {
|
|
|
- ESP_LOGI(TAG, "Connected to server");
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ esp_http_client_close(client);
|
|
|
+ esp_http_client_cleanup(client);
|
|
|
}
|
|
|
|
|
|
static void __attribute__((noreturn)) task_fatal_error()
|
|
|
{
|
|
|
ESP_LOGE(TAG, "Exiting task due to fatal error...");
|
|
|
- close(socket_id);
|
|
|
(void)vTaskDelete(NULL);
|
|
|
|
|
|
while (1) {
|
|
|
@@ -202,36 +122,23 @@ static void ota_example_task(void *pvParameter)
|
|
|
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
|
|
|
false, true, portMAX_DELAY);
|
|
|
ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server....");
|
|
|
-
|
|
|
- /*connect to http server*/
|
|
|
- if (connect_to_http_server()) {
|
|
|
- ESP_LOGI(TAG, "Connected to http server");
|
|
|
- } else {
|
|
|
- ESP_LOGE(TAG, "Connect to http server failed!");
|
|
|
- task_fatal_error();
|
|
|
- }
|
|
|
-
|
|
|
- /*send GET request to http server*/
|
|
|
- const char *GET_FORMAT =
|
|
|
- "GET %s HTTP/1.0\r\n"
|
|
|
- "Host: %s:%s\r\n"
|
|
|
- "User-Agent: esp-idf/1.0 esp32\r\n\r\n";
|
|
|
-
|
|
|
- char *http_request = NULL;
|
|
|
- int get_len = asprintf(&http_request, GET_FORMAT, EXAMPLE_FILENAME, EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT);
|
|
|
- if (get_len < 0) {
|
|
|
- ESP_LOGE(TAG, "Failed to allocate memory for GET request buffer");
|
|
|
+
|
|
|
+ esp_http_client_config_t config = {
|
|
|
+ .url = EXAMPLE_SERVER_URL,
|
|
|
+ .cert_pem = (char *)server_cert_pem_start,
|
|
|
+ };
|
|
|
+ esp_http_client_handle_t client = esp_http_client_init(&config);
|
|
|
+ if (client == NULL) {
|
|
|
+ ESP_LOGE(TAG, "Failed to initialise HTTP connection");
|
|
|
task_fatal_error();
|
|
|
}
|
|
|
- int res = send(socket_id, http_request, get_len, 0);
|
|
|
- free(http_request);
|
|
|
-
|
|
|
- if (res < 0) {
|
|
|
- ESP_LOGE(TAG, "Send GET request to server failed");
|
|
|
+ err = esp_http_client_open(client, 0);
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
|
|
+ esp_http_client_cleanup(client);
|
|
|
task_fatal_error();
|
|
|
- } else {
|
|
|
- ESP_LOGI(TAG, "Send GET request to server succeeded");
|
|
|
}
|
|
|
+ esp_http_client_fetch_headers(client);
|
|
|
|
|
|
update_partition = esp_ota_get_next_update_partition(NULL);
|
|
|
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
|
|
|
@@ -241,55 +148,43 @@ static void ota_example_task(void *pvParameter)
|
|
|
err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
|
|
|
if (err != ESP_OK) {
|
|
|
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
|
|
+ http_cleanup(client);
|
|
|
task_fatal_error();
|
|
|
}
|
|
|
ESP_LOGI(TAG, "esp_ota_begin succeeded");
|
|
|
|
|
|
- bool resp_body_start = false, socket_flag = true, http_200_flag = false;
|
|
|
+ int binary_file_length = 0;
|
|
|
/*deal with all receive packet*/
|
|
|
- while (socket_flag) {
|
|
|
- memset(text, 0, TEXT_BUFFSIZE);
|
|
|
- memset(ota_write_data, 0, BUFFSIZE);
|
|
|
- int buff_len = recv(socket_id, text, TEXT_BUFFSIZE, 0);
|
|
|
- if (buff_len < 0) { /*receive error*/
|
|
|
- ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno);
|
|
|
+ while (1) {
|
|
|
+ int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE);
|
|
|
+ if (data_read < 0) {
|
|
|
+ ESP_LOGE(TAG, "Error: SSL data read error");
|
|
|
+ http_cleanup(client);
|
|
|
task_fatal_error();
|
|
|
- } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/
|
|
|
- // only start ota when server response 200 state code
|
|
|
- if (strstr(text, "200") == NULL && !http_200_flag) {
|
|
|
- ESP_LOGE(TAG, "ota url is invalid or bin is not exist");
|
|
|
- task_fatal_error();
|
|
|
- }
|
|
|
- http_200_flag = true;
|
|
|
- memcpy(ota_write_data, text, buff_len);
|
|
|
- resp_body_start = read_past_http_header(text, buff_len, update_handle);
|
|
|
- } else if (buff_len > 0 && resp_body_start) { /*deal with response body*/
|
|
|
- memcpy(ota_write_data, text, buff_len);
|
|
|
- err = esp_ota_write( update_handle, (const void *)ota_write_data, buff_len);
|
|
|
+ } else if (data_read > 0) {
|
|
|
+ err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read);
|
|
|
if (err != ESP_OK) {
|
|
|
- ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(err));
|
|
|
+ http_cleanup(client);
|
|
|
task_fatal_error();
|
|
|
}
|
|
|
- binary_file_length += buff_len;
|
|
|
- ESP_LOGI(TAG, "Have written image length %d", binary_file_length);
|
|
|
- } else if (buff_len == 0) { /*packet over*/
|
|
|
- socket_flag = false;
|
|
|
- ESP_LOGI(TAG, "Connection closed, all packets received");
|
|
|
- close(socket_id);
|
|
|
- } else {
|
|
|
- ESP_LOGE(TAG, "Unexpected recv result");
|
|
|
+ binary_file_length += data_read;
|
|
|
+ ESP_LOGD(TAG, "Written image length %d", binary_file_length);
|
|
|
+ } else if (data_read == 0) {
|
|
|
+ ESP_LOGI(TAG, "Connection closed,all data received");
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length);
|
|
|
|
|
|
if (esp_ota_end(update_handle) != ESP_OK) {
|
|
|
ESP_LOGE(TAG, "esp_ota_end failed!");
|
|
|
+ http_cleanup(client);
|
|
|
task_fatal_error();
|
|
|
}
|
|
|
err = esp_ota_set_boot_partition(update_partition);
|
|
|
if (err != ESP_OK) {
|
|
|
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
|
|
|
+ http_cleanup(client);
|
|
|
task_fatal_error();
|
|
|
}
|
|
|
ESP_LOGI(TAG, "Prepare to restart system!");
|