ota & screen

This commit is contained in:
marc 2025-05-08 19:55:17 +02:00
parent e963d43a01
commit ce83025eb2
8 changed files with 542 additions and 74 deletions

View File

@ -186,19 +186,24 @@ static void download(void)
void imgdwn(void *pvParameter) {
ESP_LOGE(TAG, "beginning");
for(;;)
{
ESP_LOGE(TAG, "beginning");
// Should be big enough to allocate the JPEG file size, width * height should suffice
source_buf = (uint8_t *)heap_caps_malloc(IMGDWN_HEIGHT * IMGDWN_WIDTH, MALLOC_CAP_SPIRAM);
if (source_buf == NULL) {
ESP_LOGE(TAG, "Initial alloc source_buf failed!");
// Should be big enough to allocate the JPEG file size, width * height should suffice
source_buf = (uint8_t *)heap_caps_malloc(IMGDWN_HEIGHT * IMGDWN_WIDTH, MALLOC_CAP_SPIRAM);
if (source_buf == NULL) {
ESP_LOGE(TAG, "Initial alloc source_buf failed!");
}
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
download();
heap_caps_free(source_buf);
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
vTaskDelay(pdTICKS_TO_MS(60*60*1000));
}
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
download();
heap_caps_free(source_buf);
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
}

View File

@ -399,7 +399,7 @@ void initialise_weather_data_retrieval(unsigned long retreival_period)
// http_client_on_process_chunk(&http_client, process_chunk);
// http_client_on_disconnected(&http_client, disconnected);
TaskHandle_t xHandle = NULL;
BaseType_t ret1 = xTaskCreate(&http_request_task, "http_meteof", 5 * 1024, NULL, 5, &xHandle);
BaseType_t ret1 = xTaskCreate(&http_request_task, "http_meteof", 5 * 1024, NULL, 1, &xHandle);
if(ret1!=pdPASS ){
ESP_LOGE(TAG, "Impossible de creer la tache %i", ret1);
}

View File

@ -80,10 +80,12 @@ static void event_handler(lv_event_t *e)
}
void init_display(){
lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
//lvgl_cfg.task_priority=15;
bsp_display_cfg_t cfg = {
.lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(),
.lvgl_port_cfg = lvgl_cfg,
.buffer_size = BSP_LCD_DRAW_BUFF_SIZE,
.double_buffer = BSP_LCD_DRAW_BUFF_DOUBLE,
.double_buffer = 1,
.flags = {
.buff_dma = true,
.buff_spiram = false,
@ -99,11 +101,49 @@ void init_display(){
mainState.display_init=true;
}
lv_obj_t * otaStatus;
lv_obj_t * arcProgress;
static void value_changed_event_cb(lv_event_t * e)
{
//lv_obj_t * arc = lv_event_get_target_obj(e);
lv_obj_t * label = (lv_obj_t *)lv_event_get_user_data(e);
lv_label_set_text_fmt(label, "%" LV_PRId32 "%%", lv_arc_get_value(arcProgress));
/*Rotate the label to the current position of the arc*/
lv_arc_rotate_obj_to_angle(arcProgress, label, 25);
}
void app_ota_display(){
lv_obj_clean(lv_scr_act());
lv_obj_t * label = lv_label_create(lv_screen_active());
otaStatus=lv_label_create(lv_scr_act());
lv_label_set_text(otaStatus, "Mise à jour OTA en cours");
/*Create an Arc*/
arcProgress = lv_arc_create(lv_screen_active());
lv_obj_set_size(arcProgress, 150, 150);
lv_arc_set_rotation(arcProgress, 135);
lv_arc_set_bg_angles(arcProgress, 0, 270);
lv_arc_set_value(arcProgress, 0);
lv_obj_center(arcProgress);
lv_obj_add_event_cb(arcProgress, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, label);
/*Manually update the label for the first time*/
lv_obj_send_event(arcProgress, LV_EVENT_VALUE_CHANGED, NULL);
}
void setOTAProgress(int value){
lv_arc_set_value(arcProgress, value);
lv_obj_send_event(arcProgress, LV_EVENT_VALUE_CHANGED, NULL);
}
void app_main_display()
{
lv_subject_init_int(&meteoStatus, -1);
if(display_lock("meteoStatus")){
lv_subject_init_int(&meteoStatus, -1);
display_unlock("meteoStatus");
}
struct meteodailyforecast_data d;
@ -222,23 +262,23 @@ void display_unlock(const char* TAG){
// Ce callback est applé lorsque meteoStatus change
void meteo_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{
ESP_LOGI(TAG, "On passe dans le callback de chgt de statut meteo; %li", lv_subject_get_int(subject));
if (display_lock("meteo_obs_cb"))
{
lv_obj_t *meteoSt = observer->target;
switch (lv_subject_get_int(subject))
ESP_LOGI(TAG, "On passe dans le callback de chgt de statut meteo; %li", lv_subject_get_int(subject));
if (display_lock("meteo_obs_cb"))
{
case 0:
lv_obj_set_style_text_color(meteoSt, lv_color_make(0x00, 0xff, 0xff), 0);
break;
case 1:
lv_obj_set_style_text_color(meteoSt, lv_color_make(0xff, 0x00, 0x00), 0);
break;
lv_obj_t *meteoSt = observer->target;
switch (lv_subject_get_int(subject))
{
case 0:
lv_obj_set_style_text_color(meteoSt, lv_color_make(0x00, 0xff, 0xff), 0);
break;
case 1:
lv_obj_set_style_text_color(meteoSt, lv_color_make(0xff, 0x00, 0x00), 0);
break;
}
display_unlock("meteo_obs_cb");
}else{
ESP_LOGE(TAG,"Impossible d'obtenir le mutex dans meteo_obs_cb");
}
display_unlock("meteo_obs_cb");
}else{
ESP_LOGE(TAG,"Impossible d'obtenir le mutex dans meteo_obs_cb");
}
}
LV_IMAGE_DECLARE(plan_rdc);
@ -791,7 +831,7 @@ void draw_ihm()
// lv_obj_set_style_bg_color(tabview, lv_palette_lighten(LV_PALETTE_RED, 2), 0);
lv_obj_t *tab_buttons = lv_tabview_get_tab_bar(tabview);
lv_obj_set_width(tab_buttons, 100);
lv_obj_set_width(tab_buttons, 120);
lv_obj_set_style_text_font(tab_buttons, lv_theme_get_font_large(tab_buttons), 0);
lv_obj_set_style_bg_color(tab_buttons, lv_palette_darken(LV_PALETTE_GREY, 3), 0);
lv_obj_set_style_text_color(tab_buttons, lv_palette_lighten(LV_PALETTE_GREY, 5), 0);
@ -803,6 +843,7 @@ void draw_ihm()
lv_obj_t* tabMeteo = lv_tabview_add_tab(tabview, "Météo");
lv_obj_t* tabCuve = lv_tabview_add_tab(tabview, "\xEF\x95\xB5"
"Cuve");
lv_obj_t* tabMinuteur = lv_tabview_add_tab(tabview, "Minuteur");
lv_obj_t* tabSettings = lv_tabview_add_tab(tabview, "Settings");
// lv_obj_set_style_bg_color(tab2b, lv_palette_lighten(LV_PALETTE_AMBER, 3), 0);

View File

@ -4,6 +4,8 @@
#include "bsp/esp-bsp.h"
void app_main_display();
void app_ota_display();
void setOTAProgress(int value);
void init_display();
bool display_lock(const char *TAG);

View File

@ -247,7 +247,10 @@ void simple_ota_example_task(void *pvParameter)
ESP_LOGE(TAG, "image header verification failed");
goto ota_end;
}
if(bsp_display_lock(100)){
app_ota_display();
bsp_display_unlock();
}
while (1) {
err = esp_https_ota_perform(https_ota_handle);
if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
@ -256,9 +259,14 @@ void simple_ota_example_task(void *pvParameter)
// esp_https_ota_perform returns after every read operation which gives user the ability to
// monitor the status of OTA upgrade by calling esp_https_ota_get_image_len_read, which gives length of image
// data read so far.
ESP_LOGD(TAG, "Image bytes read: %d", esp_https_ota_get_image_len_read(https_ota_handle));
//ESP_LOGE(TAG,"Image size : %i", esp_https_ota_get_image_size(https_ota_handle));
int percent=esp_https_ota_get_image_len_read(https_ota_handle)*100/esp_https_ota_get_image_size(https_ota_handle);
//ESP_LOGE(TAG, "Image bytes read: %d %i%%", esp_https_ota_get_image_len_read(https_ota_handle),percent);
if(bsp_display_lock(100)){
setOTAProgress(percent);
bsp_display_unlock();
}
}
if (esp_https_ota_is_complete_data_received(https_ota_handle) != true) {
// the OTA image was not completely received and user can customise the response to this situation.
ESP_LOGE(TAG, "Complete data was not received.");
@ -326,15 +334,15 @@ static void gpio_task_example(void* arg)
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
ESP_LOGE(TAG,"Got it !");
if(ecranEteint){
if(bsp_display_lock(0)){
for (int i = 0; i < 100; i++)
for (int i = 0; i < 100; i+=2)
{
bsp_display_brightness_set(i);
if(bsp_display_lock(0)){
bsp_display_brightness_set(i);
bsp_display_unlock();
}
vTaskDelay(delay/portTICK_PERIOD_MS);
}
bsp_display_unlock();
ecranEteint=false;
}
}else{
ESP_LOGI(TAG, "Ecran déjà allumé");
}
@ -369,13 +377,13 @@ void initPirSensor(){
static void presence_timer_callback(void* arg)
{
int64_t time_since_boot = esp_timer_get_time();
if(bsp_display_lock(0)){
for (int i = 100; i >= 0; i--)
{
for (int i = 100; i >= 0; i-=2)
{
if(bsp_display_lock(0)){
bsp_display_brightness_set(i);
vTaskDelay(20/portTICK_PERIOD_MS);
bsp_display_unlock();
}
bsp_display_unlock();
vTaskDelay(20/portTICK_PERIOD_MS);
}
ecranEteint=true;
}
@ -475,6 +483,7 @@ static httpd_handle_t start_webserver(void) {
void app_main(void)
{
init_display();
const esp_timer_create_args_t periodic_timer_args = {
.callback = &presence_timer_callback,
/* name is optional, but may help identify the timer when debugging */
@ -554,10 +563,19 @@ void app_main(void)
// On affiche au plus tot l'ecran de démarrage
// ESP_ERROR_CHECK(esp_lcd_panel_mirror(lcd_panel,true,true));
init_display();
/*
display_lock("app_main");
app_main_display();
app_ota_display();
display_unlock("app_main");
for (size_t i = 0; i < 100; i++)
{
display_lock("app_main");
setOTAProgress(i);
display_unlock("app_main");
vTaskDelay(100/portTICK_PERIOD_MS);
}
*/
app_main_display();
printf("7 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
// Initialize NVS
@ -572,13 +590,19 @@ void app_main(void)
printf("8 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
wifi_init_sta();
//start_wifi_logger();
//wifi_log_e("test", "%s %d %f", "hello world wifi logger", 43, 45.341223242); // write log over wifi with log level -> ERROR
start_wifi_logger();
wifi_log_e("test", "%s %d %f", "hello world wifi logger", 43, 45.341223242); // write log over wifi with log level -> ERROR
esp_log_level_set("tcp_handler", ESP_LOG_NONE);
printf("8b - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
printf("9 - Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
/* Ensure to disable any WiFi power save mode, this allows best throughput
* and hence timings for overall OTA operation.
*/
esp_wifi_set_ps(WIFI_PS_NONE);
xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 1, NULL);
time_t now;
struct tm timeinfo;
time(&now);
@ -602,13 +626,13 @@ void app_main(void)
TaskHandle_t xHandle = NULL;
BaseType_t ret1;
ret1 = xTaskCreate(&imgdwn, "imageDownload_task", 3 * 1024, NULL, 5, &xHandle);
ret1 = xTaskCreate(&imgdwn, "imageDownload_task", 3 * 1024, NULL, 1, &xHandle);
if (ret1 != pdPASS)
{
ESP_LOGE(TAG, "Impossiblke de creer la tache imageDownload_task %i", ret1);
}
BaseType_t ret2 = xTaskCreate(&updateTime, "updateTimeTask", 3 * 1024, NULL, 5, NULL);
BaseType_t ret2 = xTaskCreate(&updateTime, "updateTimeTask", 3 * 1024, NULL, 1, NULL);
if (ret2 != pdPASS)
{
ESP_LOGE(TAG, "Impossiblke de creer la tache updateTimeTask %i", ret2);
@ -643,11 +667,6 @@ void app_main(void)
xTaskCreate(&readTempHumid, "read_temp_task", 8192, NULL, 5, NULL);
*/
/* Ensure to disable any WiFi power save mode, this allows best throughput
* and hence timings for overall OTA operation.
*/
esp_wifi_set_ps(WIFI_PS_NONE);
xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
}

View File

@ -515,7 +515,7 @@ CONFIG_IDF_TOOLCHAIN_GCC=y
CONFIG_IDF_TARGET_ARCH_RISCV=y
CONFIG_IDF_TARGET_ARCH="riscv"
CONFIG_IDF_TARGET="esp32p4"
CONFIG_IDF_INIT_VERSION="5.4.0"
CONFIG_IDF_INIT_VERSION="$IDF_INIT_VERSION"
CONFIG_IDF_TARGET_ESP32P4=y
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0012
@ -701,7 +701,32 @@ CONFIG_ENV_GPIO_RANGE_MIN=0
CONFIG_ENV_GPIO_RANGE_MAX=56
CONFIG_ENV_GPIO_IN_RANGE_MAX=56
CONFIG_ENV_GPIO_OUT_RANGE_MAX=56
# CONFIG_EXAMPLE_CONNECT_WIFI is not set
CONFIG_EXAMPLE_CONNECT_WIFI=y
# CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN is not set
CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD=y
CONFIG_EXAMPLE_WIFI_SSID="wifimms3"
CONFIG_EXAMPLE_WIFI_PASSWORD="mmswifi0611"
CONFIG_EXAMPLE_WIFI_CONN_MAX_RETRY=6
# CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST is not set
CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL=y
#
# WiFi Scan threshold
#
CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD=-127
CONFIG_EXAMPLE_WIFI_AUTH_OPEN=y
# CONFIG_EXAMPLE_WIFI_AUTH_WEP is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK is not set
# CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK is not set
# end of WiFi Scan threshold
CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL=y
# CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY is not set
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
CONFIG_EXAMPLE_ETHERNET_EMAC_TASK_STACK_SIZE=2048
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
@ -1042,7 +1067,7 @@ CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000
# ESP HTTPS OTA
#
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y
# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set
CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000
# end of ESP HTTPS OTA
@ -1238,7 +1263,7 @@ CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
@ -1292,10 +1317,10 @@ CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT=y
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584
CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0 is not set
# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
CONFIG_ESP_MAIN_TASK_AFFINITY=0x0
CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY=y
CONFIG_ESP_MAIN_TASK_AFFINITY=0x7FFFFFFF
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set
@ -1369,7 +1394,6 @@ CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
@ -1702,7 +1726,6 @@ CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4
CONFIG_LWIP_TCP_OVERSIZE_MSS=y
# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
# CONFIG_LWIP_WND_SCALE is not set
CONFIG_LWIP_TCP_RTO_TIME=1500
# end of TCP
@ -2186,7 +2209,7 @@ CONFIG_BSP_I2S_NUM=1
CONFIG_TRANSPORT_PROTOCOL_UDP=y
# CONFIG_TRANSPORT_PROTOCOL_TCP is not set
# CONFIG_TRANSPORT_PROTOCOL_WEBSOCKET is not set
# CONFIG_ROUTE_ESP_IDF_API_LOGS_TO_WIFI is not set
CONFIG_ROUTE_ESP_IDF_API_LOGS_TO_WIFI=y
CONFIG_SERVER_IP_ADDRESS="192.168.0.10"
CONFIG_SERVER_PORT=9999
CONFIG_MESSAGE_QUEUE_SIZE=1000
@ -2417,9 +2440,9 @@ CONFIG_ESP_WIFI_REMOTE_LIBRARY_HOSTED=y
CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=10
CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_WIFI_RMT_STATIC_TX_BUFFER=y
# CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER is not set
CONFIG_WIFI_RMT_TX_BUFFER_TYPE=0
CONFIG_WIFI_RMT_STATIC_TX_BUFFER_NUM=16
CONFIG_WIFI_RMT_CACHE_TX_BUFFER_NUM=32
CONFIG_WIFI_RMT_STATIC_RX_MGMT_BUFFER=y
# CONFIG_WIFI_RMT_DYNAMIC_RX_MGMT_BUFFER is not set
CONFIG_WIFI_RMT_DYNAMIC_RX_MGMT_BUF=0
@ -2429,7 +2452,6 @@ CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y
CONFIG_WIFI_RMT_TX_BA_WIN=6
CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y
CONFIG_WIFI_RMT_RX_BA_WIN=6
# CONFIG_WIFI_RMT_AMSDU_TX_ENABLED is not set
CONFIG_WIFI_RMT_NVS_ENABLED=y
CONFIG_WIFI_RMT_SOFTAP_BEACON_MAX_LEN=752
CONFIG_WIFI_RMT_MGMT_SBUF_NUM=32
@ -2552,15 +2574,15 @@ CONFIG_LV_DPI_DEF=130
#
# Operating System (OS)
#
CONFIG_LV_OS_NONE=y
# CONFIG_LV_OS_NONE is not set
# CONFIG_LV_OS_PTHREAD is not set
# CONFIG_LV_OS_FREERTOS is not set
CONFIG_LV_OS_FREERTOS=y
# CONFIG_LV_OS_CMSIS_RTOS2 is not set
# CONFIG_LV_OS_RTTHREAD is not set
# CONFIG_LV_OS_WINDOWS is not set
# CONFIG_LV_OS_MQX is not set
# CONFIG_LV_OS_CUSTOM is not set
CONFIG_LV_USE_OS=0
CONFIG_LV_USE_OS=2
# end of Operating System (OS)
#
@ -2569,6 +2591,7 @@ CONFIG_LV_USE_OS=0
CONFIG_LV_DRAW_BUF_STRIDE_ALIGN=1
CONFIG_LV_DRAW_BUF_ALIGN=4
CONFIG_LV_DRAW_LAYER_SIMPLE_BUF_SIZE=24576
CONFIG_LV_DRAW_THREAD_STACK_SIZE=8192
CONFIG_LV_USE_DRAW_SW=y
CONFIG_LV_DRAW_SW_SUPPORT_RGB565=y
CONFIG_LV_DRAW_SW_SUPPORT_RGB565A8=y
@ -2756,7 +2779,7 @@ CONFIG_LV_TXT_LINE_BREAK_LONG_LEN=0
#
CONFIG_LV_WIDGETS_HAS_DEFAULT_VALUE=y
# CONFIG_LV_USE_ANIMIMG is not set
# CONFIG_LV_USE_ARC is not set
CONFIG_LV_USE_ARC=y
CONFIG_LV_USE_BAR=y
CONFIG_LV_USE_BUTTON=y
CONFIG_LV_USE_BUTTONMATRIX=y
@ -2940,7 +2963,7 @@ CONFIG_STACK_CHECK_NONE=y
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
CONFIG_OTA_ALLOW_HTTP=y
# CONFIG_OTA_ALLOW_HTTP is not set
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_MAIN_TASK_STACK_SIZE=3584
@ -2972,7 +2995,6 @@ CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=6
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
@ -3085,7 +3107,6 @@ CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=6
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y

380
server.py Normal file
View File

@ -0,0 +1,380 @@
#!/usr/bin/python3
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import http.server
import multiprocessing
import os
import ssl
import subprocess
import sys
from typing import Any
from typing import Optional
from typing import Tuple
import pexpect
import pytest
from pytest_embedded import Dut
try:
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
except ModuleNotFoundError:
idf_path = os.environ['IDF_PATH']
sys.path.insert(0, idf_path + '/tools/ci/python_packages')
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
server_cert = '-----BEGIN CERTIFICATE-----\n' \
'MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ\n'\
'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n'\
'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n'\
'b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ\n'\
'TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD\n'\
'VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j\n'\
'b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL\n'\
'SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W\n'\
'ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ\n'\
'S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz\n'\
'YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz\n'\
'3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap\n'\
'rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud\n'\
'IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk\n'\
'B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32\n'\
'3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9\n'\
'RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN\n'\
'lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y=\n'\
'-----END CERTIFICATE-----\n'
server_key = '-----BEGIN PRIVATE KEY-----\n'\
'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP\n'\
'wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu\n'\
'c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m\n'\
'KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO\n'\
'2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv\n'\
'L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO\n'\
'AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH\n'\
'fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj\n'\
'z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF\n'\
'gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z\n'\
'Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q\n'\
'jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz\n'\
'i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw\n'\
'8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N\n'\
'JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq\n'\
'gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv\n'\
'kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN\n'\
'P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al\n'\
'pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG\n'\
'1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU\n'\
'10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ\n'\
'hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O\n'\
'rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G\n'\
'rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ\n'\
'YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG\n'\
'vSXnRLaxQhooWm+IuX9SuBQ=\n'\
'-----END PRIVATE KEY-----\n'
OTA_0_ADDRESS = '0x20000'
OTA_1_ADDRESS = '0x1d0000'
def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, server_file: Optional[str] = None, key_file: Optional[str] = None) -> None:
os.chdir(ota_image_dir)
if server_file is None:
server_file = os.path.join(ota_image_dir, 'server_cert.pem')
cert_file_handle = open(server_file, 'w+', encoding='utf-8')
cert_file_handle.write(server_cert)
cert_file_handle.close()
if key_file is None:
key_file = os.path.join(ota_image_dir, 'server_key.pem')
key_file_handle = open('server_key.pem', 'w+', encoding='utf-8')
key_file_handle.write(server_key)
key_file_handle.close()
httpd = http.server.HTTPServer((server_ip, server_port), http.server.SimpleHTTPRequestHandler)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(certfile=server_file, keyfile=key_file)
httpd.socket = ssl_context.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()
def start_tls1_3_server(ota_image_dir: str, server_port: int) -> subprocess.Popen:
os.chdir(ota_image_dir)
server_file = os.path.join(ota_image_dir, 'server_cert.pem')
cert_file_handle = open(server_file, 'w+', encoding='utf-8')
cert_file_handle.write(server_cert)
cert_file_handle.close()
key_file = os.path.join(ota_image_dir, 'server_key.pem')
key_file_handle = open('server_key.pem', 'w+', encoding='utf-8')
key_file_handle.write(server_key)
key_file_handle.close()
chunked_server = subprocess.Popen(['openssl', 's_server', '-tls1_3', '-WWW', '-key', key_file, '-cert', server_file, '-port', str(server_port)])
return chunked_server
def check_sha256(sha256_expected: str, sha256_reported: str) -> None:
print('sha256_expected: %s' % (sha256_expected))
print('sha256_reported: %s' % (sha256_reported))
if sha256_expected not in sha256_reported:
raise ValueError('SHA256 mismatch')
else:
print('SHA256 expected and reported are the same')
def calc_all_sha256(dut: Dut) -> Tuple[str, str]:
bootloader_path = os.path.join(dut.app.binary_path, 'bootloader', 'bootloader.bin')
sha256_bootloader = dut.app.get_sha256(bootloader_path)
app_path = os.path.join(dut.app.binary_path, 'simple_ota.bin')
sha256_app = dut.app.get_sha256(app_path)
return str(sha256_bootloader), str(sha256_app)
def setting_connection(dut: Dut, env_name: Optional[str] = None) -> Any:
if env_name is not None and dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
try:
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print(f'Connected to AP/Ethernet with IP: {ip_address}')
except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
return get_host_ip4_by_dest_ip(ip_address)
@pytest.mark.esp32
@pytest.mark.esp32c3
@pytest.mark.esp32s3
@pytest.mark.wifi_high_traffic
def test_examples_protocol_simple_ota_example(dut: Dut) -> None:
"""
steps: |
1. join AP/Ethernet
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
sha256_bootloader, sha256_app = calc_all_sha256(dut)
# Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1.daemon = True
thread1.start()
try:
# start test
dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
# Parse IP address of STA
env_name = 'wifi_high_traffic' if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True else None
host_ip = setting_connection(dut, env_name)
dut.expect('Starting OTA example task', timeout=30)
print(f'writing to device: https://{host_ip}:8000/simple_ota.bin')
dut.write(f'https://{host_ip}:8000/simple_ota.bin')
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect(f'Loaded app from partition at offset {OTA_1_ADDRESS}', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally:
thread1.terminate()
@pytest.mark.esp32
@pytest.mark.ethernet_ota
@pytest.mark.parametrize('config', ['spiram',], indirect=True)
def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: Dut) -> None:
"""
steps: |
1. join AP/Ethernet
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
# Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1.daemon = True
thread1.start()
try:
# start test
dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30)
host_ip = setting_connection(dut)
dut.expect('Starting OTA example task', timeout=30)
print(f'writing to device: https://{host_ip}:8000/simple_ota.bin')
dut.write(f'https://{host_ip}:8000/simple_ota.bin')
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect(f'Loaded app from partition at offset {OTA_1_ADDRESS}', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally:
thread1.terminate()
@pytest.mark.esp32
@pytest.mark.esp32c3
@pytest.mark.flash_encryption_wifi_high_traffic
@pytest.mark.nightly_run
@pytest.mark.parametrize('config', ['flash_enc_wifi',], indirect=True)
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Dut) -> None:
"""
steps: |
1. join AP/Ethernet
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
# CONFIG_PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS==y, it includes partitions_two_ota_encr_nvs.csv
FACTORY_ADDRESS = '0x20000'
OTA_0_ADDRESS = '0x120000'
# OTA_1_ADDRESS = '0x220000'
# start test
# Erase flash
dut.serial.erase_flash()
dut.serial.flash()
# Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1.daemon = True
thread1.start()
try:
dut.expect(f'Loaded app from partition at offset {FACTORY_ADDRESS}', timeout=30)
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
# Parse IP address of STA
env_name = 'flash_encryption_wifi_high_traffic' if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True else None
host_ip = setting_connection(dut, env_name)
dut.expect('Starting OTA example task', timeout=30)
print(f'writing to device: https://{host_ip}:8000/simple_ota.bin')
dut.write(f'https://{host_ip}:8000/simple_ota.bin')
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30)
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
dut.expect('OTA example app_main start', timeout=10)
finally:
thread1.terminate()
@pytest.mark.esp32
@pytest.mark.ethernet_ota
@pytest.mark.parametrize('config', ['on_update_no_sb_ecdsa',], indirect=True)
def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_ecdsa(dut: Dut) -> None:
"""
steps: |
1. join AP/Ethernet
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
sha256_bootloader, sha256_app = calc_all_sha256(dut)
# Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1.daemon = True
thread1.start()
try:
# start test
dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
host_ip = setting_connection(dut)
dut.expect('Starting OTA example task', timeout=30)
print(f'writing to device: https://{host_ip}:8000/simple_ota.bin')
dut.write(f'https://{host_ip}:8000/simple_ota.bin')
dut.expect(f'Writing to <ota_1> partition at offset {OTA_1_ADDRESS}', timeout=20)
dut.expect('Verifying image signature...', timeout=60)
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect(f'Loaded app from partition at offset {OTA_1_ADDRESS}', timeout=20)
dut.expect('OTA example app_main start', timeout=10)
finally:
thread1.terminate()
@pytest.mark.esp32
@pytest.mark.ethernet_ota
@pytest.mark.parametrize('config', ['on_update_no_sb_rsa',], indirect=True)
def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_rsa(dut: Dut) -> None:
"""
steps: |
1. join AP/Ethernet
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
sha256_bootloader, sha256_app = calc_all_sha256(dut)
# Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1.daemon = True
thread1.start()
try:
# start test
dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
host_ip = setting_connection(dut)
dut.expect('Starting OTA example task', timeout=30)
print(f'writing to device: https://{host_ip}:8000/simple_ota.bin')
dut.write(f'https://{host_ip}:8000/simple_ota.bin')
dut.expect(f'Writing to <ota_1> partition at offset {OTA_1_ADDRESS}', timeout=20)
dut.expect('Verifying image signature...', timeout=60)
dut.expect('#0 app key digest == #0 trusted key digest', timeout=10)
dut.expect('Verifying with RSA-PSS...', timeout=10)
dut.expect('Signature verified successfully!', timeout=10)
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect(f'Loaded app from partition at offset {OTA_1_ADDRESS}', timeout=20)
dut.expect('OTA example app_main start', timeout=10)
finally:
thread1.terminate()
@pytest.mark.esp32
@pytest.mark.ethernet_ota
@pytest.mark.parametrize('config', ['tls1_3',], indirect=True)
def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None:
"""
steps: |
1. join AP/Ethernet
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
sha256_bootloader, sha256_app = calc_all_sha256(dut)
# Start server
tls1_3_server = start_tls1_3_server(dut.app.binary_path, 8000)
try:
# start test
dut.expect(f'Loaded app from partition at offset {OTA_0_ADDRESS}', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
# Parse IP address of STA
env_name = 'wifi_high_traffic' if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True else None
host_ip = setting_connection(dut, env_name)
dut.expect('Starting OTA example task', timeout=30)
print(f'writing to device: https://{host_ip}:8000/simple_ota.bin')
dut.write(f'https://{host_ip}:8000/simple_ota.bin')
dut.expect('OTA Succeed, Rebooting...', timeout=120)
# after reboot
dut.expect(f'Loaded app from partition at offset {OTA_1_ADDRESS}', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally:
tls1_3_server.kill()
if __name__ == '__main__':
if sys.argv[2:]: # if two or more arguments provided:
# Usage: pytest_simple_ota.py <image_dir> <server_port> [cert_dir]
this_dir = os.path.dirname(os.path.realpath(__file__))
bin_dir = os.path.join(this_dir, sys.argv[1])
port = int(sys.argv[2])
cert_dir = bin_dir if not sys.argv[3:] else os.path.join(this_dir, sys.argv[3]) # optional argument
print(f'Starting HTTPS server at "https://0.0.0.0:{port}"')
start_https_server(bin_dir, '', port,
server_file=os.path.join(cert_dir, 'ca_cert.pem'),
key_file=os.path.join(cert_dir, 'ca_key.pem'))

View File

@ -1 +1 @@
0.2
0.1