Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* OTA example
- This example code is in the Public Domain (or CC0 licensed, at your option.)
- Unless required by applicable law or agreed to in writing, this
- 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 <stdlib.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/event_groups.h"
- #include "esp_system.h"
- #include "esp_wifi.h"
- #include "esp_event_loop.h"
- #include "esp_log.h"
- #include "esp_ota_ops.h"
- #include "nvs.h"
- #include "nvs_flash.h"
- #include "lwip/err.h"
- #include "lwip/sockets.h"
- #include "lwip/sys.h"
- #include "lwip/netdb.h"
- #include "lwip/dns.h"
- #include "esp_tls.h"
- //#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
- //#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
- #define EXAMPLE_WIFI_SSID "SecureUpdate"
- #define EXAMPLE_WIFI_PASS "EmsecExercise42018"
- #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP
- #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT
- #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME
- #define BUFFSIZE 1024
- #define TEXT_BUFFSIZE 1024
- /*************************************************************************************/
- /* Constants that aren't configurable in menuconfig */
- #define WEB_SERVER "emsec.cispa.saarland"
- #define WEB_PORT "443"
- #define WEB_URL "https://emsec.cispa.saarland/files/image.bin"
- //static const char *TAG = "example";
- static const char *REQUEST = "GET " WEB_URL " HTTP/1.0\r\n"
- "Host: "WEB_SERVER"\r\n"
- "User-Agent: esp-idf/1.0 esp32\r\n"
- "\r\n";
- /* Root cert for howsmyssl.com, taken from server_root_cert.pem
- The PEM file was extracted from the output of this command:
- openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
- The CA root cert is the last cert given in the chain of certs.
- To embed it in the app binary, the PEM file is named
- in the component.mk COMPONENT_EMBED_TXTFILES variable.
- */
- extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start");
- extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end");
- /*************************************************************************************/
- static const char *TAG = "ota";
- /*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;
- /* FreeRTOS event group to signal when we are connected & ready to make a request */
- static EventGroupHandle_t wifi_event_group;
- /* The event group allows multiple bits for each event,
- but we only care about one event - are we connected
- to the AP with an IP? */
- const int CONNECTED_BIT = BIT0;
- static esp_err_t event_handler(void *ctx, system_event_t *event)
- {
- switch (event->event_id) {
- case SYSTEM_EVENT_STA_START:
- esp_wifi_connect();
- break;
- case SYSTEM_EVENT_STA_GOT_IP:
- xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
- break;
- case SYSTEM_EVENT_STA_DISCONNECTED:
- /* This is a workaround as ESP32 WiFi libs don't currently
- auto-reassociate. */
- esp_wifi_connect();
- xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
- break;
- default:
- break;
- }
- return ESP_OK;
- }
- static void initialise_wifi(void)
- {
- tcpip_adapter_init();
- wifi_event_group = xEventGroupCreate();
- ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
- wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
- ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
- ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
- wifi_config_t wifi_config = {
- .sta = {
- .ssid = EXAMPLE_WIFI_SSID,
- .password = EXAMPLE_WIFI_PASS,
- },
- };
- ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
- ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
- ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
- 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)
- {
- /* 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()
- {
- char buf[512];
- int ret, len;
- /*
- 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));
- */
- /*************************************************************************************/
- int cipher_list[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0};
- mbedtls_ssl_conf_ciphersuites(&conf, cipher_list);
- esp_tls_cfg_t cfg = {
- .cacert_pem_buf = server_root_cert_pem_start,
- .cacert_pem_bytes = server_root_cert_pem_end - server_root_cert_pem_start,
- };
- struct esp_tls *tls = esp_tls_conn_http_new(WEB_URL, &cfg);
- if(tls != NULL) {
- ESP_LOGI(TAG, "Connection established...");
- } else {
- ESP_LOGE(TAG, "Connection failed...");
- goto exit;
- }
- size_t written_bytes = 0;
- do {
- ret = esp_tls_conn_write(tls,
- REQUEST + written_bytes,
- strlen(REQUEST) - written_bytes);
- if (ret >= 0) {
- ESP_LOGI(TAG, "%d bytes written", ret);
- written_bytes += ret;
- } else if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
- ESP_LOGE(TAG, "esp_tls_conn_write returned 0x%x", ret);
- goto exit;
- }
- } while(written_bytes < strlen(REQUEST));
- ESP_LOGI(TAG, "Reading HTTP response...");
- do
- {
- len = sizeof(buf) - 1;
- bzero(buf, sizeof(buf));
- ret = esp_tls_conn_read(tls, (char *)buf, len);
- if(ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ)
- continue;
- if(ret < 0)
- {
- ESP_LOGE(TAG, "esp_tls_conn_read returned -0x%x", -ret);
- break;
- }
- if(ret == 0)
- {
- ESP_LOGI(TAG, "connection closed");
- break;
- }
- len = ret;
- ESP_LOGD(TAG, "%d bytes read", len);
- /* Print response directly to stdout as it is read */
- for(int i = 0; i < len; i++) {
- putchar(buf[i]);
- }
- } while(1);
- exit:
- esp_tls_conn_delete(tls);
- putchar('\n'); // JSON output doesn't have a newline at end
- static int request_count;
- ESP_LOGI(TAG, "Completed %d requests", ++request_count);
- for(int countdown = 10; countdown >= 0; countdown--) {
- ESP_LOGI(TAG, "%d...", countdown);
- vTaskDelay(1000 / portTICK_PERIOD_MS);
- }
- ESP_LOGI(TAG, "Starting again!");
- return true;
- }
- /*************************************************************************************/
- /*
- // 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;
- */
- static void __attribute__((noreturn)) task_fatal_error()
- {
- ESP_LOGE(TAG, "Exiting task due to fatal error...");
- close(socket_id);
- (void)vTaskDelete(NULL);
- while (1) {
- ;
- }
- }
- 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();
- }
- /*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");
- 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");
- 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 (%s)", esp_err_to_name(err));
- task_fatal_error();
- }
- ESP_LOGI(TAG, "esp_ota_begin succeeded");
- bool resp_body_start = false, socket_flag = true, http_200_flag = false;
- /*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);
- 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);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(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*/
- socket_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 (%s)!", esp_err_to_name(err));
- task_fatal_error();
- }
- ESP_LOGI(TAG, "Prepare to restart system!");
- esp_restart();
- return ;
- }
- void app_main()
- {
- // Initialize NVS.
- esp_err_t err = nvs_flash_init();
- if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
- // OTA app partition table has a smaller NVS partition size than the non-OTA
- // partition table. This size mismatch may cause NVS initialization to fail.
- // If this happens, we erase NVS partition and initialize NVS again.
- ESP_ERROR_CHECK(nvs_flash_erase());
- err = nvs_flash_init();
- }
- ESP_ERROR_CHECK( err );
- initialise_wifi();
- xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement