diff --git a/main/component.mk b/main/component.mk new file mode 100644 index 0000000..1ab23d8 --- /dev/null +++ b/main/component.mk @@ -0,0 +1 @@ +COMPONENT_EMBED_TXTFILES := ${PROJECT_PATH}/server_certs/certs.pem \ No newline at end of file diff --git a/main/main.c b/main/main.c new file mode 100644 index 0000000..d81884f --- /dev/null +++ b/main/main.c @@ -0,0 +1,143 @@ +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "cJSON.h" +#include "driver/gpio.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_http_client.h" +#include "esp_https_ota.h" + +#include "wifi_functions.h" + +#define FIRMWARE_VERSION 0.1 +#define UPDATE_JSON_URL "https://esp32.sk/firmware.json" +#define BLINK_GPIO GPIO_NUM_13 + +// server certificates +extern const char server_cert_pem_start[] asm("_binary_certs_pem_start"); +extern const char server_cert_pem_end[] asm("_binary_certs_pem_end"); + +// receive buffer +char rcv_buffer[200]; + +// esp_http_client event handler +esp_err_t _http_event_handler(esp_http_client_event_t *evt) { + + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + break; + case HTTP_EVENT_ON_CONNECTED: + break; + case HTTP_EVENT_HEADER_SENT: + break; + case HTTP_EVENT_ON_HEADER: + break; + case HTTP_EVENT_ON_DATA: + if (!esp_http_client_is_chunked_response(evt->client)) { + strncpy(rcv_buffer, (char*)evt->data, evt->data_len); + } + break; + case HTTP_EVENT_ON_FINISH: + break; + case HTTP_EVENT_DISCONNECTED: + break; + } + return ESP_OK; +} + +// Blink task +void blink_task(void *pvParameter) { + + gpio_pad_select_gpio(BLINK_GPIO); + gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); + while(1) { + gpio_set_level(BLINK_GPIO, 0); + vTaskDelay(1000 / portTICK_PERIOD_MS); + gpio_set_level(BLINK_GPIO, 1); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + + +// Check update task +// downloads every 30sec the json file with the latest firmware +void check_update_task(void *pvParameter) { + + while(1) { + + printf("Looking for a new firmware...\n"); + + // configure the esp_http_client + esp_http_client_config_t config = { + .url = UPDATE_JSON_URL, + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + + // downloading the json file + esp_err_t err = esp_http_client_perform(client); + if(err == ESP_OK) { + + // parse the json file + cJSON *json = cJSON_Parse(rcv_buffer); + if(json == NULL) printf("downloaded file is not a valid json, aborting...\n"); + else { + cJSON *version = cJSON_GetObjectItemCaseSensitive(json, "version"); + cJSON *file = cJSON_GetObjectItemCaseSensitive(json, "file"); + + // check the version + if(!cJSON_IsNumber(version)) printf("unable to read new version, aborting...\n"); + else { + + double new_version = version->valuedouble; + if(new_version > FIRMWARE_VERSION) { + + printf("current firmware version (%.1f) is lower than the available one (%.1f), upgrading...\n", FIRMWARE_VERSION, new_version); + if(cJSON_IsString(file) && (file->valuestring != NULL)) { + printf("downloading and installing new firmware (%s)...\n", file->valuestring); + + esp_http_client_config_t ota_client_config = { + .url = file->valuestring, + .cert_pem = server_cert_pem_start, + }; + esp_err_t ret = esp_https_ota(&ota_client_config); + if (ret == ESP_OK) { + printf("OTA OK, restarting...\n"); + esp_restart(); + } else { + printf("OTA failed...\n"); + } + } + else printf("unable to read the new file name, aborting...\n"); + } + else printf("current firmware version (%.1f) is greater or equal to the available one (%.1f), nothing to do...\n", FIRMWARE_VERSION, new_version); + } + } + } + else printf("unable to download the json file, aborting...\n"); + + // cleanup + esp_http_client_cleanup(client); + + printf("\n"); + vTaskDelay(30000 / portTICK_PERIOD_MS); + } +} + +void app_main() { + + printf("HTTPS OTA, firmware %.1f\n\n", FIRMWARE_VERSION); + + // start the blink task + xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL); + + // connect to the wifi network + wifi_initialise(); + wifi_wait_connected(); + printf("Connected to wifi network\n"); + + // start the check update task + xTaskCreate(&check_update_task, "check_update_task", 8192, NULL, 5, NULL); +} \ No newline at end of file diff --git a/main/wifi_functions.c b/main/wifi_functions.c new file mode 100644 index 0000000..ef184d5 --- /dev/null +++ b/main/wifi_functions.c @@ -0,0 +1,65 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "nvs_flash.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "esp_wifi.h" + +#include "wifi_functions.h" + + +// Event group for wifi connection +static EventGroupHandle_t wifi_event_group; +const int CONNECTED_BIT = BIT0; + +// Wifi event handler +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: + esp_wifi_connect(); + break; + + default: + break; + } + + return ESP_OK; +} + +void wifi_initialise(void) { + + // initialize NVS, required for wifi + ESP_ERROR_CHECK(nvs_flash_init()); + + // connect to the wifi network + wifi_event_group = xEventGroupCreate(); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + wifi_config_t wifi_config = { + .sta = { + .ssid = WIFI_SSID, + .password = WIFI_PASS, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); +} + +void wifi_wait_connected() +{ + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); +} \ No newline at end of file diff --git a/main/wifi_functions.h b/main/wifi_functions.h new file mode 100644 index 0000000..c92cb1b --- /dev/null +++ b/main/wifi_functions.h @@ -0,0 +1,10 @@ +#ifndef _WIFI_FUNCTIONS_H_ +#define _WIFI_FUNCTIONS_H_ + +#define WIFI_SSID "huawei-2929" +#define WIFI_PASS "chefrolet" + +void wifi_initialise(void); +void wifi_wait_connected(); + +#endif \ No newline at end of file