Beispiel #1
0
static void ota_example_task(void *pvParameter)
{
    esp_err_t err;
    /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
    esp_ota_handle_t update_handle = 0 ;
    const esp_partition_t *update_partition = NULL;

    ESP_LOGI(TAG, "Starting OTA example...");

    const esp_partition_t *configured = esp_ota_get_boot_partition();
    const esp_partition_t *running = esp_ota_get_running_partition();

    if (configured != running) {
        ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
                 configured->address, running->address);
        ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
    }
    ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
             running->type, running->subtype, running->address);

    /* Wait for the callback to set the CONNECTED_BIT in the
       event group.
    */
    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();
    }

    int res = -1;
    /*send GET request to http server*/
    res = send(socket_id, http_request, strlen(http_request), 0);
    if (res == -1) {
        ESP_LOGE(TAG, "Send GET request to server failed");
        task_fatal_error();
    } else {
        ESP_LOGI(TAG, "Send GET request to server succeeded");
    }

    update_partition = esp_ota_get_next_update_partition(NULL);
    ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
             update_partition->subtype, update_partition->address);
    assert(update_partition != NULL);

    err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "esp_ota_begin failed, error=%d", err);
        task_fatal_error();
    }
    ESP_LOGI(TAG, "esp_ota_begin succeeded");

    bool resp_body_start = false, flag = true;
    /*deal with all receive packet*/
    while (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);
            task_fatal_error();
        } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/
            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);
            if (err != ESP_OK) {
                ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err);
                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*/
            flag = false;
            ESP_LOGI(TAG, "Connection closed, all packets received");
            close(socket_id);
        } else {
            ESP_LOGE(TAG, "Unexpected recv result");
        }
    }

    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!");
        task_fatal_error();
    }
    err = esp_ota_set_boot_partition(update_partition);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%x", err);
        task_fatal_error();
    }
    ESP_LOGI(TAG, "Prepare to restart system!");
    esp_restart();
    return ;
}
Beispiel #2
0
esp_err_t iot_ota_start(const char *server_ip, uint16_t server_port, const char *file_dir, uint32_t ticks_to_wait)
{
    TimerHandle_t ota_timer = NULL;
    int socket_id = -1;
    esp_err_t ret = ESP_FAIL;
    esp_ota_handle_t upgrade_handle = 0;
    POINT_ASSERT(TAG, server_ip, ESP_ERR_INVALID_ARG);
    POINT_ASSERT(TAG, file_dir, ESP_ERR_INVALID_ARG);
    if (g_ota_mux == NULL) {
        g_ota_mux = xSemaphoreCreateMutex();
    }
    if (g_ota_mux == NULL) {
        ret = ESP_ERR_NO_MEM;
        goto OTA_FINISH;
    }
    if (pdTRUE != xSemaphoreTake(g_ota_mux, ticks_to_wait)){
        ret = ESP_ERR_TIMEOUT;
        goto OTA_FINISH;
    }
    g_ota_timeout = false;

    ESP_LOGI(TAG, "ota starting");
    const esp_partition_t *upgrade_part = NULL;
    const esp_partition_t *part_confed = esp_ota_get_boot_partition();
    const esp_partition_t *part_running = esp_ota_get_running_partition();
    if (part_confed != part_running) {
        ESP_LOGI(TAG, "partition error");
        ret = ESP_FAIL;
        goto OTA_FINISH;
    }
    ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
             part_confed->type, part_confed->subtype, part_confed->address);
    socket_id = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_id == -1) {
        ESP_LOGI(TAG, "create socket error!");
        goto OTA_FINISH;
    }
    if (ticks_to_wait != portMAX_DELAY) {
        ota_timer = xTimerCreate("ota_timer", ticks_to_wait, pdFALSE, (void*)socket_id, download_timer_cb);
        if (ota_timer == NULL) {
            ret = ESP_ERR_NO_MEM;
            goto OTA_FINISH;
        }
        //todo: to check the result of RTOS timer APIs.
        xTimerStart(ota_timer, ticks_to_wait / portTICK_PERIOD_MS);
    }
    ret = connect_http_server(server_ip, server_port, socket_id);
    OTA_CHECK(TAG, "connect http server error!", ret, OTA_FINISH);
    char http_request[64];
    sprintf(http_request, "GET %s HTTP/1.1\r\nHost: %s:%d \r\n\r\n", file_dir, server_ip, server_port);
    ret = send(socket_id, http_request, strlen(http_request), 0);
    if (ret == -1) {
        ESP_LOGI(TAG, "send request to server  error!");
        ret = ESP_FAIL;
        goto OTA_FINISH;
    }
    upgrade_part = esp_ota_get_next_update_partition(NULL);
    if (upgrade_part == NULL) {
        ret = ESP_FAIL;
        goto OTA_FINISH;
    }
    ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
                upgrade_part->subtype, upgrade_part->address);
    ret = esp_ota_begin(upgrade_part, OTA_SIZE_UNKNOWN, &upgrade_handle);
    OTA_CHECK(TAG, "ota begin error!", ret, OTA_FINISH);
    ret = ota_download(socket_id, upgrade_handle);
    OTA_CHECK(TAG, "ota data download error!", ret, OTA_FINISH);
    //Stop timer since downloading has finished.
    xTimerStop(ota_timer, ticks_to_wait / portTICK_PERIOD_MS);
    ret = esp_ota_end(upgrade_handle);
    upgrade_handle = 0;
    OTA_CHECK(TAG, "ota end error!", ret, OTA_FINISH);
    ret = esp_ota_set_boot_partition(upgrade_part);
    OTA_CHECK(TAG, "set boot partition error!", ret, OTA_FINISH);
    ESP_LOGI(TAG, "ota succeed");

OTA_FINISH:
    if (upgrade_handle != 0) {
        esp_ota_end(upgrade_handle);
        upgrade_handle = 0;
    }
    if (g_ota_timeout == true) {
        ESP_LOGI(TAG, "ota timeout");
        ret = ESP_ERR_TIMEOUT;
    } else if (socket_id != -1) {
        close(socket_id);
    }
    if (ticks_to_wait != portMAX_DELAY && ota_timer != NULL) {
        xTimerStop(ota_timer, 0);
        xTimerDelete(ota_timer, 0);
        ota_timer = NULL;
    }
    if (g_ota_mux != NULL) {
        xSemaphoreGive(g_ota_mux);
    }
    return ret;
}
static int
ota_file_upload_cb(void *data, const char *name, const char *filename,
	       char *buf, int len, enum lws_spa_fileupload_states state)
{
	struct per_session_data__esplws_ota *pss =
			(struct per_session_data__esplws_ota *)data;

	switch (state) {
	case LWS_UFS_OPEN:
		lwsl_notice("LWS_UFS_OPEN Filename %s\n", filename);
		strncpy(pss->filename, filename, sizeof(pss->filename) - 1);
		if (strcmp(name, "ota"))
			return 1;

		pss->part = ota_choose_part();
		if (!pss->part)
			return 1;

		if (esp_ota_begin(pss->part, (long)-1, &pss->otahandle) != ESP_OK) {
			lwsl_err("OTA: Failed to begin\n");
			return 1;
		}

		pss->file_length = 0;
		break;

	case LWS_UFS_FINAL_CONTENT:
	case LWS_UFS_CONTENT:
		if (pss->file_length + len > pss->part->size) {
			lwsl_err("OTA: incoming file too large\n");
			return 1;
		}

		lwsl_notice("writing 0x%lx... 0x%lx\n",
			   pss->part->address + pss->file_length,
			   pss->part->address + pss->file_length + len);
		if (esp_ota_write(pss->otahandle, buf, len) != ESP_OK) {
			lwsl_err("OTA: Failed to write\n");
			return 1;
		}
		pss->file_length += len;

		if (state == LWS_UFS_CONTENT)
			break;

		lwsl_notice("LWS_UFS_FINAL_CONTENT\n");
		if (esp_ota_end(pss->otahandle) != ESP_OK) {
			lwsl_err("OTA: end failed\n");
			return 1;
		}

		if (esp_ota_set_boot_partition(pss->part) != ESP_OK) {
			lwsl_err("OTA: set boot part failed\n");
			return 1;
		}

		pss->reboot_timer = xTimerCreate("x", pdMS_TO_TICKS(250), 0, NULL,
						 ota_reboot_timer_cb);
		xTimerStart(pss->reboot_timer, 0);
		break;
	}

	return 0;
}
Beispiel #4
0
static void ota_example_task(void *pvParameter)
{
    esp_err_t err;
    /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
    esp_ota_handle_t update_handle = 0 ;
    const esp_partition_t *update_partition = NULL;

    ESP_LOGI(TAG, "Starting OTA example...");

    const esp_partition_t *configured = esp_ota_get_boot_partition();
    const esp_partition_t *running = esp_ota_get_running_partition();

    if (configured != running) {
        ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
                 configured->address, running->address);
        ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
    }
    ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
             running->type, running->subtype, running->address);

    /* Wait for the callback to set the CONNECTED_BIT in the
       event group.
    */
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                        false, true, portMAX_DELAY);
    ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server....");
    
    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();
    }
    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();
    }
    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",
             update_partition->subtype, update_partition->address);
    assert(update_partition != NULL);

    int binary_file_length = 0;
    /*deal with all receive packet*/
    bool image_header_was_checked = false;
    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 (data_read > 0) {
            if (image_header_was_checked == false) {
                esp_app_desc_t new_app_info;
                if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
                    // check current version with downloading
                    memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
                    ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);

                    esp_app_desc_t running_app_info;
                    if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
                        ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version);
                    }

                    const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition();
                    esp_app_desc_t invalid_app_info;
                    if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) {
                        ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
                    }

                    // check current version with last invalid partition
                    if (last_invalid_app != NULL) {
                        if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) {
                            ESP_LOGW(TAG, "New version is the same as invalid version.");
                            ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
                            ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
                            http_cleanup(client);
                            infinite_loop();
                        }
                    }

                    if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) {
                        ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update.");
                        http_cleanup(client);
                        infinite_loop();
                    }

                    image_header_was_checked = true;

                    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");
                } else {
                    ESP_LOGE(TAG, "received package is not fit len");
                    http_cleanup(client);
                    task_fatal_error();
                }
            }
            err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read);
            if (err != ESP_OK) {
                http_cleanup(client);
                task_fatal_error();
            }
            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!");
    esp_restart();
    return ;
}

static bool diagnostic(void)
{
    gpio_config_t io_conf;
    io_conf.intr_type    = GPIO_PIN_INTR_DISABLE;
    io_conf.mode         = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = (1ULL << CONFIG_GPIO_DIAGNOSTIC);
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en   = GPIO_PULLUP_ENABLE;
    gpio_config(&io_conf);

    ESP_LOGI(TAG, "Diagnostics (5 sec)...");
    vTaskDelay(5000 / portTICK_PERIOD_MS);

    bool diagnostic_is_ok = gpio_get_level(CONFIG_GPIO_DIAGNOSTIC);

    gpio_reset_pin(CONFIG_GPIO_DIAGNOSTIC);
    return diagnostic_is_ok;
}