Compare commits

...

26 Commits

Author SHA1 Message Date
8f60e9c38c publication temp int + etat online 2026-03-14 11:51:44 +01:00
67e6d1cfaa webserver (crashes & dumps) 2026-03-13 18:57:27 +01:00
77e8116d54 bg
(cherry picked from commit a84b935d41b012d8f4349df37f5e37f4e2de47be)
2026-03-06 07:24:23 +01:00
0de95c5386 dump to flash + poisoning 2026-03-06 07:22:00 +01:00
f871b76ca2 fix compat linux 2026-03-01 21:09:32 +01:00
9d31148d21 Merge branch 'OTA' 2026-03-01 20:33:14 +01:00
9293b5fdc6 Merge branch 'chgt_style_dateheure' 2026-03-01 16:56:00 +01:00
bce9f03eb4 format date 2026-03-01 16:50:11 +01:00
9217397d7d OTA: 1ere version 2026-03-01 15:58:43 +01:00
b7552e15ce notif sonore et fin (1ere version) 2026-02-28 21:06:58 +01:00
434ede2480 amélioration ihm (boutons) 2026-02-26 23:56:19 +01:00
8e868da692 linux compat 2026-02-26 23:55:50 +01:00
e1640f4ad9 machine : affichage durée depuis départ 2026-02-26 23:20:05 +01:00
a41945bcef Merge branch 'fix/etat_machine_logs' 2026-02-26 07:54:12 +01:00
7316561482 1ere implem son fin machine 2026-02-26 07:44:35 +01:00
ae99b85932 compat linux 2026-02-24 17:06:30 +01:00
5ac20b78fa adjust dtHToString 2026-02-24 16:46:13 +01:00
fc5f46d3fd ajout heure meteo ecran home 2026-02-24 16:35:19 +01:00
f5419e85aa reactivation volets 2026-02-24 16:30:24 +01:00
4658da4adb ajout temp intérieure 2026-02-24 15:25:10 +01:00
f32cad2987 ajout temp ext 2026-02-24 14:39:36 +01:00
1d91bac9e9 Merge branch 'etat_machine' 2026-02-24 13:26:31 +01:00
c87cc69b9e corrections meteo + timecb 2026-02-24 12:52:45 +01:00
6f338020ab meteo colors 2026-02-23 20:43:39 +01:00
d9ac74a595 fix meteo (images...) 2026-02-23 18:16:34 +01:00
28c5870ca6 meilleure gestion meteo 2026-02-23 13:59:02 +01:00
102 changed files with 1274 additions and 320 deletions

View File

@ -2,7 +2,7 @@
"configurations": [ "configurations": [
{ {
"name": "ESP-IDF", "name": "ESP-IDF",
"compilerPath": "${config:idf.toolsPath}/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc", "compilerPath": "/home/marc/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc",
"compileCommands": "${config:idf.buildPath}/compile_commands.json", "compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [ "includePath": [
"${config:idf.espIdfPath}/components/**", "${config:idf.espIdfPath}/components/**",

2
.vscode/launch.json vendored
View File

@ -37,7 +37,7 @@
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"preLaunchTask": "Build - Build IHM", "preLaunchTask": "Build - Build IHM",
"program": "${workspaceFolder}/components/domotic_display/test_host/build/nvs_host_test.elf", "program": "${workspaceFolder}/components/domotic_display/test_host/build/host_test.elf",
"args": [], "args": [],
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"stopAtEntry": false, "stopAtEntry": false,

View File

@ -1,3 +1,54 @@
# --------------------------------------------------
# 1. Version de base (version.txt)
# --------------------------------------------------
file(READ "${CMAKE_SOURCE_DIR}/version.txt" FW_VERSION)
string(STRIP "${FW_VERSION}" FW_VERSION)
# --------------------------------------------------
# 2. Détection git + branche
# --------------------------------------------------
find_package(Git)
set(GIT_BRANCH "")
set(IS_GIT_REPO OFF)
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(IS_GIT_REPO ON)
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
# --------------------------------------------------
# 3. Mode dev ou release
# --------------------------------------------------
# Convention simple :
# - branche main / master => release
# - le reste => dev
set(IS_DEV_BUILD OFF)
if(IS_GIT_REPO AND NOT GIT_BRANCH STREQUAL "main" AND NOT GIT_BRANCH STREQUAL "master")
set(IS_DEV_BUILD ON)
endif()
# --------------------------------------------------
# 4. Nettoyage nom de branche
# --------------------------------------------------
if(IS_DEV_BUILD)
# remplace / par -
string(REPLACE "/" "-" GIT_BRANCH_CLEAN "${GIT_BRANCH}")
set(FW_VERSION "${FW_VERSION}-${GIT_BRANCH_CLEAN}")
endif()
message(STATUS "Firmware version: ${FW_VERSION}")
# --------------------------------------------------
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
option(SIMULATION_QEMU "Build for QEMU simulation" OFF) option(SIMULATION_QEMU "Build for QEMU simulation" OFF)
message(STATUS "ROOT:: SIMULATION_QEMU = ${SIMULATION_QEMU}") message(STATUS "ROOT:: SIMULATION_QEMU = ${SIMULATION_QEMU}")
@ -33,7 +84,7 @@ endif()
#list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/esp_timer") #list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/esp_timer")
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(rgb_lcd) project(domotic)
# ------------------------------------------------- # -------------------------------------------------
@ -61,3 +112,44 @@ else()
add_link_options(-fsanitize=address) add_link_options(-fsanitize=address)
endif() endif()
# --- Paramètres OTA ---
set(OTA_DIR "${CMAKE_SOURCE_DIR}/../ota/fw")
set(DEVICE "esp32p4")
# --- Nom final du binaire ---
set(OTA_BIN_NAME "${PROJECT_NAME}-v${FW_VERSION}.bin")
set(BUILD_BIN "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin")
set(BUILD_ELF "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.elf")
message(STATUS "Firmware version: ${FW_VERSION}")
# --- Target OTA ---
add_custom_target(ota_push ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${OTA_DIR}
COMMAND ${CMAKE_COMMAND} -E copy
${BUILD_BIN}
${OTA_DIR}/${OTA_BIN_NAME}
COMMAND ${CMAKE_COMMAND} -E copy
${BUILD_ELF}
${OTA_DIR}/latest.elf
COMMENT "📦 Copy firmware to OTA server directory"
DEPENDS app
)
add_custom_target(ota_latest
COMMAND ${CMAKE_COMMAND} -E echo
"{ \"version\":\"${FW_VERSION}\", \
\"bin\":\"${OTA_BIN_NAME}\" }"
> ${OTA_DIR}/latest.json
DEPENDS ota_push
)
add_custom_target(ota_to_mqtt
COMMAND podman run --rm eclipse-mosquitto:alpine
mosquitto_pub
-h 192.168.0.10
-t devices/esp32p4_01/ota/update
-m '{"version":"${FW_VERSION}","url":"https://192.168.0.9:8443/${OTA_BIN_NAME}","sha256":"","force":true}'
)

View File

@ -0,0 +1,3 @@
idf_component_register(SRCS "audio.c"
INCLUDE_DIRS "include"
REQUIRES esp32_p4_function_ev_board)

224
components/audio/audio.c Normal file
View File

@ -0,0 +1,224 @@
#include <stdio.h>
#include "audio.h"
#include <stdio.h>
#include <inttypes.h>
#include <sdkconfig.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "bsp/esp-bsp.h"
/* Buffer for reading/writing to I2S driver. Same length as SPIFFS buffer and I2S buffer, for optimal read/write performance.
External SPI Flash -> SPIFFS buffer -> App buffer (RAM) -> I2S buffer (DMA) -> I2S peripheral.
*/
#define BUFFER_SIZE (1024)
#define DEFAULT_VOLUME (50)
/* Globals */
static const char *TAG = "audio";
TaskHandle_t audio_task_handle;
// Very simple WAV header, ignores most fields
typedef struct __attribute__((packed))
{
uint8_t ignore_0[22];
uint16_t num_channels;
uint32_t sample_rate;
uint8_t ignore_1[6];
uint16_t bits_per_sample;
uint8_t ignore_2[4];
uint32_t data_size;
uint8_t data[];
} dumb_wav_header_t;
typedef struct {
FILE *f;
uint32_t data_offset;
uint32_t data_size;
} wav_ctx_t;
#define AUDIO_CHUNK_SIZE 4096
bool wav_open(wav_ctx_t *ctx, const char *path)
{
ctx->f = fopen(path, "rb");
if (!ctx->f) return false;
/* Skip RIFF header */
fseek(ctx->f, 12, SEEK_SET);
uint32_t chunk_id, chunk_size;
while (fread(&chunk_id, 4, 1, ctx->f))
{
fread(&chunk_size, 4, 1, ctx->f);
if (chunk_id == 0x61746164) { // "data"
ctx->data_offset = ftell(ctx->f);
ctx->data_size = chunk_size;
return true;
}
fseek(ctx->f, chunk_size, SEEK_CUR);
}
fclose(ctx->f);
return false;
}
void rewind_wav(wav_ctx_t *ctx)
{
fseek(ctx->f, ctx->data_offset, SEEK_SET);
}
#define AUDIO_CHUNK_SIZE 4096
static void audio_task(void *arg)
{
ESP_LOGI(TAG,"Audio task");
esp_codec_dev_handle_t spk_codec_dev = bsp_audio_codec_speaker_init();
assert(spk_codec_dev);
esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
esp_codec_dev_set_out_mute(spk_codec_dev, false); // 🔑 CRITIQUE
const char *play_filename = "/littlefs/sounds/mixkit-clear-announce-tones-2861.wav";
uint8_t *wav_bytes = malloc(BUFFER_SIZE);
assert(wav_bytes != NULL);
for (;;)
{
/* ⏸️ Attend PLAY */
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
bool stop_requested = false;
while (!stop_requested) {
ESP_LOGI(TAG,"On joue !");
FILE *play_file = fopen(play_filename, "rb");
if (!play_file) {
ESP_LOGE(TAG,"File not found");
break;
}
dumb_wav_header_t wav_header;
if (fread(&wav_header, 1, sizeof(wav_header), play_file) != sizeof(wav_header)) {
ESP_LOGE(TAG,"Header read failed");
fclose(play_file);
break;
}
esp_codec_dev_sample_info_t fs = {
.sample_rate = wav_header.sample_rate,
.channel = wav_header.num_channels,
.bits_per_sample = wav_header.bits_per_sample,
};
ESP_ERROR_CHECK(esp_codec_dev_open(spk_codec_dev, &fs));
uint32_t bytes_sent = 0;
while (bytes_sent < wav_header.data_size) {
size_t bytes_read = fread(wav_bytes, 1, BUFFER_SIZE, play_file);
if (bytes_read == 0) break;
esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read);
bytes_sent += bytes_read;
vTaskDelay(1); // watchdog + scheduler
}
esp_codec_dev_close(spk_codec_dev);
fclose(play_file);
ESP_LOGI(TAG,"Fin du fichier");
if (ulTaskNotifyTake(pdTRUE, 0) > 0) {
stop_requested = true;
}
}
}
free(wav_bytes);
}
static void audio_task__(void *arg)
{
ESP_LOGE(TAG,"Audio task");
esp_codec_dev_handle_t spk_codec_dev = bsp_audio_codec_speaker_init();
assert(spk_codec_dev);
esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
/* Pointer to a file that is going to be played */
const char music_filename[] = "/littlefs/sounds/mixkit-clear-announce-tones-2861.wav";
const char *play_filename = music_filename;
int16_t *wav_bytes = malloc(BUFFER_SIZE);
assert(wav_bytes != NULL);
bool stop_requested = false;
while (!stop_requested){
ESP_LOGE(TAG,"On joue !");
/* Open WAV file */
ESP_LOGI(TAG, "Playing file %s", play_filename);
FILE *play_file = fopen(play_filename, "rb");
if (play_file == NULL) {
ESP_LOGW(TAG, "%s file does not exist!", play_filename);
break;
}
/* Read WAV header file */
dumb_wav_header_t wav_header;
if (fread((void *)&wav_header, 1, sizeof(wav_header), play_file) != sizeof(wav_header)) {
ESP_LOGW(TAG, "Error in reading file");
break;
}
//ESP_LOGI(TAG, "Number of channels: %" PRIu16 "", wav_header.num_channels);
//ESP_LOGI(TAG, "Bits per sample: %" PRIu16 "", wav_header.bits_per_sample);
//ESP_LOGI(TAG, "Sample rate: %" PRIu32 "", wav_header.sample_rate);
//ESP_LOGI(TAG, "Data size: %" PRIu32 "", wav_header.data_size);
esp_codec_dev_sample_info_t fs = {
.sample_rate = wav_header.sample_rate,
.channel = wav_header.num_channels,
.bits_per_sample = wav_header.bits_per_sample,
};
esp_codec_dev_open(spk_codec_dev, &fs);
uint32_t bytes_send_to_i2s = 0;
while (bytes_send_to_i2s < wav_header.data_size) {
/* Get data from SPIFFS and send it to codec */
size_t bytes_read_from_spiffs = fread(wav_bytes, 1, BUFFER_SIZE, play_file);
esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read_from_spiffs);
bytes_send_to_i2s += bytes_read_from_spiffs;
/* ⭐ LIGNE CRITIQUE ⭐ */
vTaskDelay(1); // laisse respirer IDLE + watchdog
}
ESP_LOGE(TAG,"On a fini le fichier");
fclose(play_file);
esp_codec_dev_close(spk_codec_dev);
if(ulTaskNotifyTake(pdTRUE, 0)>0){
stop_requested=true;
break;
};
}
free(wav_bytes);
vTaskSuspend(NULL);
}
void playSound(void)
{
if(audio_task_handle==NULL){
BaseType_t ret = xTaskCreate(audio_task, "audio_task", 4096, NULL, 6, &audio_task_handle);
assert(ret == pdPASS);
}
xTaskNotifyGive(audio_task_handle);
}
void stopSound(void){
if (audio_task_handle) {
xTaskNotifyGive(audio_task_handle);
}
}

View File

@ -0,0 +1,4 @@
void playSound(void);
void stopSound(void);

View File

@ -32,7 +32,6 @@ if(${IDF_TARGET} STREQUAL "esp32p4" OR ${IDF_TARGET} STREQUAL "esp32s3")
lvgl_port_create_c_image("images/mqtt_ok.png" "images/" "AUTO" "NONE") lvgl_port_create_c_image("images/mqtt_ok.png" "images/" "AUTO" "NONE")
lvgl_port_create_c_image("images/mqtt_ko.png" "images/" "ARGB8888" "NONE") lvgl_port_create_c_image("images/mqtt_ko.png" "images/" "ARGB8888" "NONE")
lvgl_port_add_images(${COMPONENT_LIB} "images/") lvgl_port_add_images(${COMPONENT_LIB} "images/")
#littlefs_create_partition_image(littlefs images_meteo FLASH_IN_PROJECT)
elseif(${IDF_TARGET} STREQUAL "linux") elseif(${IDF_TARGET} STREQUAL "linux")
idf_component_register(SRC_DIRS . fonts images idf_component_register(SRC_DIRS . fonts images
INCLUDE_DIRS "include" INCLUDE_DIRS "include"

View File

@ -36,9 +36,10 @@ LV_IMAGE_DECLARE(mqtt_ok);
LV_IMAGE_DECLARE(mqtt_ko); LV_IMAGE_DECLARE(mqtt_ko);
lv_subject_t dateHeureSubj; lv_subject_t dateHeureSubj;
lv_obj_t *lblTempInt2; lv_obj_t *lblTempInt;
lv_obj_t *lblTempExt;
char tempExtStr[6]; char tempExtStr[6];
char tempIntStr[6]; char tempIntStr[50];
char hauteurCuveStr[9]; char hauteurCuveStr[9];
char hauteurCuveEvolStr[9]; char hauteurCuveEvolStr[9];
lv_subject_t tempIntSubj; lv_subject_t tempIntSubj;
@ -48,7 +49,7 @@ lv_subject_t hauteurCuveEvolSubj;
lv_subject_t forecastD1Subj; lv_subject_t forecastD1Subj;
lv_subject_t forecastD2Subj; lv_subject_t forecastD2Subj;
lv_subject_t forecastD3Subj; lv_subject_t forecastD3Subj;
lv_subject_t *tmpSubj[3] = {&forecastD1Subj, &forecastD2Subj, &forecastD3Subj}; lv_subject_t *tmpDSubj[3] = {&forecastD1Subj, &forecastD2Subj, &forecastD3Subj};
lv_subject_t forecastH1Subj; lv_subject_t forecastH1Subj;
lv_subject_t forecastH2Subj; lv_subject_t forecastH2Subj;
lv_subject_t forecastH3Subj; lv_subject_t forecastH3Subj;
@ -109,12 +110,36 @@ void draw_time(struct tm *dateHeure){
//} //}
} }
void draw_tempExt(char * tempHumid){
//if(display_lock("draw_temp")){
//lv_label_set_text_fmt(lblTempExt,LV_SYMBOL_HOME "\xEF\x8B\x8A : %.1f°C", atof(tempHumid));
lv_subject_copy_string(&tempExtSubj,tempHumid);
// display_unlock("draw_temp");
//}
}
void draw_temp(char * tempHumid){ void draw_temp(char * tempHumid){
if(display_lock("draw_temp")){ //if(display_lock("draw_temp")){
lv_label_set_text(lblTempInt2,tempHumid); ESP_LOGE(TAG, "draw_temp : %s", tempHumid);
display_unlock("draw_temp"); lv_subject_copy_string(&tempIntSubj,tempHumid);
} //lv_label_set_text_fmt(lblTempInt, "\xEE\x86\xB0\xEF\x8B\x8A : %s", tempHumid);
// display_unlock("draw_temp");
//}
}
void draw_meteo(meteo_event_payload_t *meteo){
//if(display_lock("updateTime")){
//lv_label_set_text(jour, dateHeure);
lv_subject_set_pointer(&forecastH1Subj, &meteo->forecast[0]);
lv_subject_set_pointer(&forecastH2Subj, &meteo->forecast[1]);
lv_subject_set_pointer(&forecastH3Subj, &meteo->forecast[2]);
lv_subject_set_pointer(&forecastD1Subj, &meteo->daily[0]);
lv_subject_set_pointer(&forecastD2Subj, &meteo->daily[1]);
lv_subject_set_pointer(&forecastD3Subj, &meteo->daily[2]);
//display_unlock("updateTime");
//}
} }
lv_obj_t* myChart; lv_obj_t* myChart;
@ -124,6 +149,7 @@ lv_obj_t* lblEtatMachine;
static lv_style_t style_lbvValue; static lv_style_t style_lbvValue;
static lv_style_t style_btn; static lv_style_t style_btn;
/*
lv_theme_t *lv_theme_create(void) lv_theme_t *lv_theme_create(void)
{ {
lv_theme_t *theme = lv_zalloc(sizeof(*theme)); lv_theme_t *theme = lv_zalloc(sizeof(*theme));
@ -140,6 +166,7 @@ void lv_theme_copy(lv_theme_t *dst, const lv_theme_t *src)
} }
lv_memcpy(dst, src, sizeof(*src)); lv_memcpy(dst, src, sizeof(*src));
} }
*/
static void create_ui(void*) static void create_ui(void*)
{ {
// Initialisation du thème // Initialisation du thème
@ -152,6 +179,7 @@ static void create_ui(void*)
// Création des écrans / widgets // Création des écrans / widgets
app_main_display(); // ton écran principal app_main_display(); // ton écran principal
initHome(); // écran Home
drawHome(); // écran Home drawHome(); // écran Home
// chart, labels, boutons, etc. // chart, labels, boutons, etc.
// par exemple : lblEtatMachine, lblHauteurCuve, myChart, ser... // par exemple : lblEtatMachine, lblHauteurCuve, myChart, ser...
@ -163,6 +191,13 @@ static void create_ui(void*)
#include <unistd.h> // usleep #include <unistd.h> // usleep
#include "platform_detect.h" #include "platform_detect.h"
bool suspended;
void suspendIHM(){
suspended=true;
#if CONFIG_IDF_TARGET_ESP32P4
lvgl_port_stop();
#endif
}
void drawIhm(void *param) { void drawIhm(void *param) {
// Init display + LVGL // Init display + LVGL
init_display_ihm(); init_display_ihm();
@ -177,8 +212,14 @@ void drawIhm(void *param) {
// Loop unifiée // Loop unifiée
while (1) { while (1) {
ihm_gateway_process_queue(); if(!suspended){
//uint32_t idle_time = lv_timer_handler(); ihm_gateway_process_queue();
#if CONFIG_IDF_TARGET_LINUX
uint32_t idle_time = lv_timer_handler();
#endif
}else{
vTaskDelay(500 / portTICK_PERIOD_MS);
}
// ESP32 : task FreeRTOS // ESP32 : task FreeRTOS
//vTaskDelay(500 / portTICK_PERIOD_MS); //vTaskDelay(500 / portTICK_PERIOD_MS);
@ -218,6 +259,8 @@ static void event_handler(lv_event_t *e)
static lv_indev_t *keyboard; static lv_indev_t *keyboard;
#endif #endif
struct tm timeinfo;
void init_display_ihm(){ void init_display_ihm(){
#if CONFIG_IDF_TARGET_LINUX #if CONFIG_IDF_TARGET_LINUX
@ -229,13 +272,14 @@ void init_display_ihm(){
keyboard = lv_sdl_keyboard_create(); keyboard = lv_sdl_keyboard_create();
#else #else
lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
lvgl_cfg.task_priority=4; lvgl_cfg.task_priority=18;
lvgl_cfg.task_stack=12000;
bsp_display_cfg_t cfg = { bsp_display_cfg_t cfg = {
.lvgl_port_cfg = lvgl_cfg, .lvgl_port_cfg = lvgl_cfg,
.buffer_size = 1024*600,//BSP_LCD_DRAW_BUFF_SIZE, .buffer_size = 1024*600,//BSP_LCD_DRAW_BUFF_SIZE,
.double_buffer = 1, .double_buffer = 1,
.hw_cfg = { .hw_cfg = {
.dsi_bus.lane_bit_rate_mbps= 1000 .dsi_bus.lane_bit_rate_mbps= BSP_LCD_MIPI_DSI_LANE_BITRATE_MBPS
}, },
.flags = { .flags = {
.buff_dma = false, .buff_dma = false,
@ -244,8 +288,8 @@ void init_display_ihm(){
} }
}; };
ESP_LOGE(TAG,"On demarre le display"); ESP_LOGE(TAG,"On demarre le display");
lv_display_t *dsp = bsp_display_start(); //lv_display_t *dsp = bsp_display_start();
//lv_display_t *dsp = bsp_display_start_with_config(&cfg); lv_display_t *dsp = bsp_display_start_with_config(&cfg);
/*bsp_display_lock(0); /*bsp_display_lock(0);
bsp_display_rotate(dsp,LV_DISP_ROTATION_90); bsp_display_rotate(dsp,LV_DISP_ROTATION_90);
@ -260,7 +304,6 @@ void init_display_ihm(){
mainState.display_init=true; mainState.display_init=true;
time_t now; time_t now;
struct tm timeinfo;
time(&now); time(&now);
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
@ -326,10 +369,9 @@ void app_main_display()
struct meteodailyforecast_data d; struct meteodailyforecast_data d;
struct dailyforecast_prev p; struct dailyforecast_prev p={.desc="", .max=31, .min=12};
lv_strcpy(p.desc, "");
d.previsions = p; d.previsions = p;
d.isValid=false; d.isValid=true;
ESP_LOGI(TAG, "Init forecastD1Subj"); ESP_LOGI(TAG, "Init forecastD1Subj");
lv_subject_init_pointer(&forecastD1Subj, &d); lv_subject_init_pointer(&forecastD1Subj, &d);
@ -403,7 +445,8 @@ void app_main_display()
// lv_label_bind_text(mqtt, &mqttStatus, "Mqtt %d"); // lv_label_bind_text(mqtt, &mqttStatus, "Mqtt %d");
lv_obj_t *scr = lv_scr_act(); lv_obj_t *scr = lv_scr_act();
lv_obj_add_style(scr, &style_gradient, 0); //lv_obj_add_style(scr, &style_gradient, 0);
lv_obj_set_style_bg_color(scr,lv_color_darken(lv_color_make(0x9B, 0x18, 0x42), LV_OPA_40),0);
/* Your LVGL objects code here .... */ /* Your LVGL objects code here .... */
@ -480,13 +523,14 @@ static lv_style_t style_container;
// Callback pour mettre à jour une météo journaliere // Callback pour mettre à jour une météo journaliere
// On pointe sur un tableau de meteodailyforecast_data // On pointe sur un tableau de meteodailyforecast_data
static void weatherdata_obs_cb(lv_observer_t *observer, lv_subject_t *subject) static void weatherdataJour_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{ {
// Retrieve weatherdata // Retrieve weatherdata
const struct meteodailyforecast_data *data = subject->value.pointer; const struct meteodailyforecast_data *data = subject->value.pointer;
bool isMinimal = observer->user_data; bool isMinimal = observer->user_data;
ESP_LOGI(TAG, "CB meteo jour declenché. Meteo valide : %b - Mode minimal : %d", data->isValid, isMinimal); ESP_LOGI(TAG, "CB meteo jour declenché. Meteo valide : %d - Mode minimal : %d", data->isValid, isMinimal);
if(!data->isValid){ if(!data->isValid){
ESP_LOGI(TAG,"Données meteo non valides"); ESP_LOGI(TAG,"Données meteo non valides");
return; return;
@ -496,9 +540,9 @@ static void weatherdata_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{ {
char buff[40] = {}; char buff[40] = {};
snprintf(buff,sizeof(buff),"%s %.1f %.1f", data->previsions.desc, data->previsions.min, data->previsions.max); snprintf(buff,sizeof(buff),"%s %.1f %.1f", data->previsions.desc, data->previsions.min, data->previsions.max);
ESP_LOGI(TAG, "CB meteo jour declenché. Meteo valide : %s", buff); ESP_LOGI(TAG, "meteo jour declenché. Meteo valide : %s", buff);
lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer)); lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer));
lv_obj_dump_tree(parent->parent); //lv_obj_dump_tree(parent->parent);
ESP_LOGI(TAG, "On accede au parent %p %s", (void*)parent, lv_obj_get_name(parent)); ESP_LOGI(TAG, "On accede au parent %p %s", (void*)parent, lv_obj_get_name(parent));
if(parent!=NULL){ if(parent!=NULL){
if(isMinimal){ if(isMinimal){
@ -523,34 +567,57 @@ static void weatherdata_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
} }
} }
} }
//free(data);
} }
} }
// Callback pour mettre à jour une météo horaire // Callback pour mettre à jour une météo horaire
// On pointe sur un tableau de meteoforecast_data // On pointe sur un tableau de meteoforecast_data
static void weatherdataH_obs_cb(lv_observer_t *observer, lv_subject_t *subject) static void weatherdataHeure_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{ {
ESP_LOGV("MeteoFrance", "CB meteo horaire declenché");
// Retrieve weatherdata // Retrieve weatherdata
const struct meteoforecast_data *data = subject->value.pointer; const struct meteoforecast_data *data = subject->value.pointer;
bool isMinimal = observer->user_data;
//ESP_LOGE(TAG, "CB meteo horaire declenché. Meteo valide : %d - Mode minimal : %d", data->isValid, isMinimal);
if(data->isValid){ if(data->isValid){
//printffd(data); //printffd(data);
char buff[40] = {}; char buff[40] = {};
snprintf(buff,sizeof(buff),"%.1f", data->previsions.value); snprintf(buff,sizeof(buff),"%.1f", data->previsions.value);
ESP_LOGV(TAG, "On a recu [%s]", buff); //ESP_LOGE(TAG, "On a recu %s - [%s] - %s", data->type, buff, data->previsions.icon);
lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer)); if(isMinimal){
lv_obj_t *datefld = lv_obj_get_child(parent, 0); lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer));
lv_obj_t *temp_desc_icon = lv_obj_get_child(parent, 1); //lv_obj_dump_tree(parent);
showMeteoIcon(data->previsions.icon, temp_desc_icon, 1);
char buffer[80]; lv_obj_t *timefld = lv_obj_get_child(parent, 0);
dtHToString(data->datetime, buffer); char buffer[8];
dtHToString(data->datetime, buffer,8);
lv_label_set_text(timefld, buffer);
showMeteoIcon(data->previsions.icon, parent, 1);
lv_obj_t *descfld = lv_obj_get_child(parent, 2);
lv_label_set_text(descfld, data->previsions.desc);
lv_obj_t *valuefld = lv_obj_get_child(parent, 3);
lv_label_set_text_fmt(valuefld, "%.1f°C", data->previsions.value);
lv_label_set_text(datefld, buffer); }else{
lv_label_set_text(lv_obj_get_child(temp_desc_icon, 2), data->previsions.desc); lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer));
lv_label_set_text_fmt(lv_obj_get_child(temp_desc_icon, 0), "%.1f°C", data->previsions.value); lv_obj_dump_tree(parent);
lv_obj_t *datefld = lv_obj_get_child(parent, 0);
lv_obj_t *temp_desc_icon = lv_obj_get_child(parent, 1);
showMeteoIcon(data->previsions.icon, temp_desc_icon, 1);
char buffer[8];
dtHToString(data->datetime, buffer,8);
lv_label_set_text(datefld, buffer);
lv_label_set_text(lv_obj_get_child(temp_desc_icon, 2), data->previsions.desc);
lv_label_set_text_fmt(lv_obj_get_child(temp_desc_icon, 0), "%.1f°C", data->previsions.value);
}
//free(data);
}else{ }else{
ESP_LOGE(TAG, "Pas de odnnées valides"); ESP_LOGE(TAG, "Pas de odnnées valides");
@ -561,14 +628,17 @@ static void weatherdataH_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
void showMeteoIcon(const char *icon, lv_obj_t *desc_icon, int childNr) void showMeteoIcon(const char *icon, lv_obj_t *desc_icon, int childNr)
{ {
lv_obj_t *img = lv_obj_get_child(desc_icon, childNr); lv_obj_t *img = lv_obj_get_child(desc_icon, childNr);
//char *str1 = "A:/littlefs/"; #if CONFIG_IDF_TARGET_LINUX
char *str1 = "A:/home/marc/domotic/components/domotic_display/images_meteo"; char *str1 = "A:/home/marc/esp/domotic/domotic/components/domotic_display/images_meteo/";
#else
char *str1 = "A:/littlefs/images_meteo/";
#endif
int sizeOfStr; int sizeOfStr;
sizeOfStr = strlen(str1) + strlen(icon) + 6; sizeOfStr = strlen(str1) + strlen(icon) + 6;
char *result = malloc(sizeOfStr); char *result = malloc(sizeOfStr);
snprintf(result,sizeOfStr, "%s%s.png", str1, icon); snprintf(result,sizeOfStr, "%s%s.png", str1, icon);
ESP_LOGV(TAG,"On affiche l'image %s", result); ESP_LOGV(TAG,"On affiche l'image %s", result);
lv_image_set_src(img, "A:/home/marc/esp/domotic/domotic/components/domotic_display/images_meteo/p4j.png"); lv_image_set_src(img, result);
free(result); free(result);
} }
@ -578,7 +648,6 @@ static lv_style_t tempStyle;
static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool minimal) static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool minimal)
{ {
if (minimal) if (minimal)
{ {
//lv_obj_set_flex_flow(sup, LV_FLEX_FLOW_COLUMN); //lv_obj_set_flex_flow(sup, LV_FLEX_FLOW_COLUMN);
@ -587,6 +656,7 @@ static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool min
//lv_obj_set_style_border_width(sup, 1, 0); //lv_obj_set_style_border_width(sup, 1, 0);
//lv_obj_set_style_border_color(sup, lv_color_white(), 0); //lv_obj_set_style_border_color(sup, lv_color_white(), 0);
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_t *container = lv_obj_create(parent); lv_obj_t *container = lv_obj_create(parent);
lv_obj_set_align(container, LV_ALIGN_CENTER); lv_obj_set_align(container, LV_ALIGN_CENTER);
lv_obj_set_name(container, "container_meteo"); lv_obj_set_name(container, "container_meteo");
@ -629,7 +699,7 @@ static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool min
// On positionne un observer sur le subjet correspondant au jour du widget // On positionne un observer sur le subjet correspondant au jour du widget
bool isMinimal = true; bool isMinimal = true;
lv_subject_add_observer_obj(tmpSubj[dayNr], weatherdata_obs_cb, parent, &isMinimal); lv_subject_add_observer_obj(tmpDSubj[dayNr], weatherdataJour_obs_cb, parent, &isMinimal);
} }
else else
{ {
@ -687,15 +757,15 @@ static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool min
lv_label_set_text(max, "--"); lv_label_set_text(max, "--");
lv_obj_add_style(max, &tempStyle, 0); lv_obj_add_style(max, &tempStyle, 0);
lv_obj_set_style_text_font(max, lv_theme_get_font_normal(max), 0); lv_obj_set_style_text_font(max, lv_theme_get_font_normal(max), 0);
lv_obj_set_style_text_color(max, lv_color_hex(0xFF0000), 0); //lv_obj_set_style_text_color(max, lv_color_hex(0xFF0000), 0);
lv_obj_t *min = lv_label_create(container2); lv_obj_t *min = lv_label_create(container2);
lv_label_set_text(min, "--"); lv_label_set_text(min, "--");
lv_obj_add_style(min, &tempStyle, 0); lv_obj_add_style(min, &tempStyle, 0);
lv_obj_set_style_text_font(min, lv_theme_get_font_normal(max), 0); lv_obj_set_style_text_font(min, lv_theme_get_font_normal(max), 0);
lv_obj_set_style_text_color(min, lv_color_hex(0x3000FF), 0); //lv_obj_set_style_text_color(min, lv_color_hex(0x3000FF), 0);
// On positionne un observer sur le subjet correspondant au jour du widget // On positionne un observer sur le subjet correspondant au jour du widget
lv_subject_add_observer_obj(tmpSubj[dayNr], weatherdata_obs_cb, sup, NULL); lv_subject_add_observer_obj(tmpDSubj[dayNr], weatherdataJour_obs_cb, sup, NULL);
} }
//return container; //return container;
@ -704,10 +774,77 @@ static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool min
static lv_style_t tempStyle; static lv_style_t tempStyle;
// Ce fragment affiche une prévision horaire (date,icone, temp moyenne) // Ce fragment affiche une prévision horaire (date,icone, temp moyenne)
static lv_obj_t* weatherH_fragment_create_obj(int horaireNr, lv_obj_t *parent) static lv_obj_t* weatherH_fragment_create_obj(int horaireNr, lv_obj_t *parent, bool minimal)
{ {
lv_obj_t *sup = lv_obj_create(parent); lv_obj_t *container = lv_obj_create(parent);
if (minimal)
{
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_ROW);
//lv_obj_set_flex_flow(sup, LV_FLEX_FLOW_COLUMN);
lv_obj_set_size(parent, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
//lv_obj_set_flex_align(sup, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
//lv_obj_set_style_border_width(sup, 1, 0);
//lv_obj_set_style_border_color(sup, lv_color_white(), 0);
lv_obj_set_align(container, LV_ALIGN_CENTER);
char name[17];
snprintf(name, 17,"%s%d","container_meteo", horaireNr);
lv_obj_set_name(container, name);
// lv_obj_remove_style_all(container);
// lv_obj_set_style_border_width(container, 1, 0);
// lv_obj_set_style_border_color(container, lv_color_make(0, 255, 0), 0);
lv_obj_set_flex_flow(container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_add_style(container, &no_padding, 0);
lv_obj_set_size(container, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_add_flag(container, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_t *heure = lv_label_create(container);
lv_label_set_text(heure, "--");
lv_obj_add_style(heure, &tempStyle, 0);
lv_obj_set_style_text_font(heure,lv_theme_get_font_normal(heure),0);
lv_obj_t *img1 = lv_image_create(container);
lv_obj_set_name(img1, "meteo_img");
lv_obj_add_flag(img1, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_remove_style_all(img1);
//lv_obj_set_style_bg_color(img1, lv_color_white(),0);
//lv_obj_set_style_border_width(img1,1,0);
lv_obj_add_style(img1, &no_padding, 0);
lv_obj_set_style_bg_color(img1, lv_palette_lighten(LV_PALETTE_BLUE_GREY, 4), 0);
lv_image_set_inner_align(img1, LV_IMAGE_ALIGN_TOP_LEFT);
lv_image_set_offset_y(img1, -8);
lv_image_set_offset_x(img1, -5);
lv_obj_set_size(img1, 40, 35);
lv_image_set_src(img1, LV_SYMBOL_DUMMY);
//lv_obj_set_style_image_recolor_opa(img1, 100, 0);
//lv_obj_set_style_image_recolor(img1, lv_color_black(), 0);
// lv_obj_set_style_border_width(img1,2,0);
// lv_obj_set_style_border_color(img1, lv_palette_main(LV_PALETTE_BLUE_GREY), 0);
lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
lv_obj_t *desc = lv_label_create(container);
lv_obj_set_name(desc, "meteo_desc");
lv_label_set_long_mode(desc, LV_LABEL_LONG_MODE_WRAP);
lv_obj_set_size(desc, 130, LV_SIZE_CONTENT);
//lv_obj_set_style_text_color(desc, lv_color_white(), 0);
lv_label_set_text(desc, name);
lv_obj_set_style_text_align(desc, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_t *temp = lv_label_create(container);
lv_label_set_text(temp, "--");
lv_obj_add_style(temp, &tempStyle, 0);
lv_obj_set_style_text_font(temp,lv_theme_get_font_normal(temp),0);
// On positionne un observer sur le subjet correspondant a l'horaire du widget
bool isMinimal = true;
//ESP_LOGE(TAG, "on positionne obs sur horaire %d", horaireNr);
lv_subject_add_observer_obj(tmpHSubj[horaireNr], weatherdataHeure_obs_cb, container, &isMinimal);
}else{
lv_obj_t *sup = lv_obj_create(parent);
lv_obj_t *title = lv_label_create(sup); lv_obj_t *title = lv_label_create(sup);
lv_label_set_text(title, "--"); lv_label_set_text(title, "--");
@ -749,8 +886,9 @@ static lv_obj_t* weatherH_fragment_create_obj(int horaireNr, lv_obj_t *parent)
lv_obj_set_style_text_font(desc, lv_theme_get_font_normal(desc), 0); lv_obj_set_style_text_font(desc, lv_theme_get_font_normal(desc), 0);
// On positionne un observer sur le subjet correspondant a l'horaire du widget // On positionne un observer sur le subjet correspondant a l'horaire du widget
ESP_LOGV(TAG, "on positionne obs sur horaire %d", horaireNr); //ESP_LOGV(TAG, "on positionne obs sur horaire %d", horaireNr);
lv_subject_add_observer_obj(tmpHSubj[horaireNr], weatherdataH_obs_cb, sup, NULL); lv_subject_add_observer_obj(tmpHSubj[horaireNr], weatherdataHeure_obs_cb, sup, NULL);
}
return container; return container;
} }
@ -922,6 +1060,7 @@ static void cuve_click_cb(lv_event_t * e){
lv_tabview_set_active(tabview, 3, false); lv_tabview_set_active(tabview, 3, false);
} }
/*
void draw_tabHome(lv_obj_t* parent){ void draw_tabHome(lv_obj_t* parent){
lv_obj_t *supmain = parent; lv_obj_t *supmain = parent;
lv_obj_set_flex_flow(supmain, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(supmain, LV_FLEX_FLOW_COLUMN);
@ -933,7 +1072,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_set_flex_flow(main, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(main, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_column(main, 1, 0); lv_obj_set_style_pad_column(main, 1, 0);
/*Conteneur Colonne: Températures*/ //Conteneur Colonne: Températures
lv_obj_t *cont_colTemp = lv_obj_create(main); lv_obj_t *cont_colTemp = lv_obj_create(main);
lv_obj_set_style_pad_all(cont_colTemp, 5, 0); lv_obj_set_style_pad_all(cont_colTemp, 5, 0);
lv_obj_set_size(cont_colTemp, lv_pct(40), lv_pct(100)); lv_obj_set_size(cont_colTemp, lv_pct(40), lv_pct(100));
@ -941,7 +1080,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_set_flex_flow(cont_colTemp, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(cont_colTemp, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(cont_colTemp, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(cont_colTemp, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
/*Create a container with COLUMN flex direction*/ //Create a container with COLUMN flex direction
lv_obj_t *cont_colVolets = lv_obj_create(main); lv_obj_t *cont_colVolets = lv_obj_create(main);
lv_obj_set_style_pad_all(cont_colVolets, 5, 0); lv_obj_set_style_pad_all(cont_colVolets, 5, 0);
lv_obj_set_flex_align(cont_colVolets, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(cont_colVolets, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
@ -950,7 +1089,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_set_flex_flow(cont_colVolets, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(cont_colVolets, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(cont_colVolets, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(cont_colVolets, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER);
/*Conteneur Colonne: Meteo*/ // Conteneur Colonne: Meteo
lv_obj_t *cont_col3 = lv_obj_create(main); lv_obj_t *cont_col3 = lv_obj_create(main);
lv_obj_set_style_pad_all(cont_col3, 5, 0); lv_obj_set_style_pad_all(cont_col3, 5, 0);
lv_obj_set_size(cont_col3, lv_pct(40), lv_pct(100)); lv_obj_set_size(cont_col3, lv_pct(40), lv_pct(100));
@ -977,7 +1116,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_label_bind_text(lblTempExt, &tempExtSubj, "%s °C"); lv_label_bind_text(lblTempExt, &tempExtSubj, "%s °C");
//Create a container with COLUMN flex direction //Create a container with COLUMN flex direction
/* //
lv_obj_t *cont_tempInt = lv_obj_create(cont_colTemp); lv_obj_t *cont_tempInt = lv_obj_create(cont_colTemp);
lv_obj_add_style(cont_tempInt, &style_container, 0); lv_obj_add_style(cont_tempInt, &style_container, 0);
// lv_obj_set_height(cont_tempInt,50); // lv_obj_set_height(cont_tempInt,50);
@ -988,7 +1127,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_add_style(lblTempInt, &style_lbvValue, 0); lv_obj_add_style(lblTempInt, &style_lbvValue, 0);
lv_label_set_text(lblTempInt, ""); lv_label_set_text(lblTempInt, "");
lv_label_bind_text(lblTempInt, &tempIntSubj, "%s °C"); lv_label_bind_text(lblTempInt, &tempIntSubj, "%s °C");
*/ //
//Create a container with COLUMN flex direction //Create a container with COLUMN flex direction
lv_obj_t *cont_tempInt2 = lv_obj_create(cont_colTemp); lv_obj_t *cont_tempInt2 = lv_obj_create(cont_colTemp);
@ -997,11 +1136,11 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_set_flex_flow(cont_tempInt2, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(cont_tempInt2, LV_FLEX_FLOW_ROW);
lv_obj_t * lblInt = lv_label_create(cont_tempInt2); lv_obj_t * lblInt = lv_label_create(cont_tempInt2);
lv_label_set_text(lblInt, "int."); lv_label_set_text(lblInt, "int.");
lblTempInt2 = lv_label_create(cont_tempInt2); //lblTempInt2 = lv_label_create(cont_tempInt2);
lv_obj_add_style(lblTempInt2, &style_lbvValue, 0); //lv_obj_add_style(lblTempInt2, &style_lbvValue, 0);
lv_obj_set_style_text_font(lblTempInt2,lv_theme_get_font_large(lblTempInt2),0); //lv_obj_set_style_text_font(lblTempInt2,lv_theme_get_font_large(lblTempInt2),0);
lv_label_set_text(lblTempInt2, ""); //lv_label_set_text(lblTempInt2, "");
//Create a container with COLUMN flex direction //Create a container with COLUMN flex direction
lv_obj_t *cont_Cuve = lv_obj_create(cont_colTemp); lv_obj_t *cont_Cuve = lv_obj_create(cont_colTemp);
@ -1036,9 +1175,9 @@ void draw_tabHome(lv_obj_t* parent){
lv_label_set_text(label, LV_SYMBOL_DOWN); lv_label_set_text(label, LV_SYMBOL_DOWN);
lv_obj_center(label); lv_obj_center(label);
weatherH_fragment_create_obj(0, cont_col3); weatherH_fragment_create_obj(0, cont_col3,false);
weatherH_fragment_create_obj(1, cont_col3); weatherH_fragment_create_obj(1, cont_col3,false);
weatherH_fragment_create_obj(2, cont_col3); weatherH_fragment_create_obj(2, cont_col3,false);
} }
void draw_tabCuve(lv_obj_t* parent) void draw_tabCuve(lv_obj_t* parent)
@ -1047,15 +1186,8 @@ void draw_tabCuve(lv_obj_t* parent)
lv_image_set_src(imgGraf, "A:/sdcard/hello2.png"); lv_image_set_src(imgGraf, "A:/sdcard/hello2.png");
} }
void draw_tabMeteo(lv_obj_t * parent)
{ */
weatherDay_fragment_create_obj(0,parent, false);
weatherDay_fragment_create_obj(1,parent, false);
weatherDay_fragment_create_obj(2,parent, false);
//manager2 = lv_fragment_manager_create(NULL);
//fragment2 = lv_fragment_create(&meteodailyforecast_cls, (void *)1);
//lv_fragment_manager_add(manager2, fragment2, &parent);
}
void draw_tabVolets(lv_obj_t* parent) void draw_tabVolets(lv_obj_t* parent)
{ {
@ -1097,7 +1229,7 @@ void draw_tabVolets(lv_obj_t* parent)
lv_obj_set_size(cont_btn_volets, lv_pct(15), lv_pct(100)); lv_obj_set_size(cont_btn_volets, lv_pct(15), lv_pct(100));
lv_obj_set_layout(cont_btn_volets, LV_LAYOUT_GRID); lv_obj_set_layout(cont_btn_volets, LV_LAYOUT_GRID);
static int32_t column_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; /*2 columns */ static int32_t column_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; //2 columns
static int32_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; static int32_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
lv_obj_set_grid_dsc_array(cont_btn_volets, column_dsc, row_dsc); lv_obj_set_grid_dsc_array(cont_btn_volets, column_dsc, row_dsc);
@ -1141,6 +1273,16 @@ void draw_tabVolets(lv_obj_t* parent)
} }
} }
void draw_tabMeteo(lv_obj_t * parent)
{
weatherDay_fragment_create_obj(0,parent, false);
weatherDay_fragment_create_obj(1,parent, false);
weatherDay_fragment_create_obj(2,parent, false);
//manager2 = lv_fragment_manager_create(NULL);
//fragment2 = lv_fragment_create(&meteodailyforecast_cls, (void *)1);
//lv_fragment_manager_add(manager2, fragment2, &parent);
}
typedef struct { typedef struct {
lv_obj_t *date_group; lv_obj_t *date_group;
lv_span_t *date_day; lv_span_t *date_day;
@ -1164,69 +1306,47 @@ static inline void u8_to_2digits(char *buf, uint8_t v)
} }
// Ce callback est appelé lorsque le pointeur "tempExt"/"tempInt" est modifié
static void temp_observer_cb(lv_observer_t *observer, lv_subject_t *subject){
lv_obj_t *tempObj = lv_observer_get_target_obj(observer);
char *templateValue = lv_observer_get_user_data(observer);
char *temp = lv_subject_get_string(subject);
//ESP_LOGE(TAG,"On passe dans temp_observer_cb pour %s avec %s - %s ",lv_obj_get_name(tempObj), templateValue, temp);
lv_label_set_text_fmt(tempObj,templateValue,temp);
}
static void time_observer_cb(lv_observer_t *observer, lv_subject_t *subject) static void time_observer_cb(lv_observer_t *observer, lv_subject_t *subject)
{ {
LV_UNUSED(observer); LV_UNUSED(observer);
lv_obj_t *dateTimeObj = lv_observer_get_target_obj(observer); lv_obj_t *parent = observer->target;
datetime_ctx_t *ctx = lv_obj_get_user_data(dateTimeObj); struct tm *timeStruct=lv_subject_get_pointer(subject);
if (!ctx) return;
struct tm *t = (struct tm *)lv_subject_get_pointer(subject); lv_obj_t *day = lv_obj_find_by_name(parent, "day");
if (!t) return; lv_obj_t *month = lv_obj_find_by_name(parent, "month");
ESP_LOGE(TAG,"%d %d %d %02d:%02d", t->tm_wday, t->tm_mday, t->tm_mon, t->tm_hour, t->tm_min);
char buf[4]; lv_obj_t *hour = lv_obj_find_by_name(parent, "hour");
bool refresh_date = false; lv_obj_t *minute = lv_obj_find_by_name(parent, "minute");
bool refresh_time = false;
// ---- DATE ----
if (t->tm_mday != ctx->last_day) { int d = timeStruct->tm_mday;
ctx->last_day = t->tm_mday; int monthVal = timeStruct->tm_mon;
u8_to_2digits(buf, t->tm_mday); int h = timeStruct->tm_hour;
buf[2] = '/'; int m = timeStruct->tm_min;
buf[3] = '\0';
ESP_LOGE(TAG,"Jour %s",buf);
lv_span_set_text(ctx->date_day, buf);
refresh_date = true;
}
if ((t->tm_mon + 1) != ctx->last_month) { char buf[12];
ctx->last_month = t->tm_mon + 1;
u8_to_2digits(buf, ctx->last_month);
ESP_LOGE(TAG,"Mois %s",buf);
lv_span_set_text(ctx->date_month, buf);
refresh_date = true;
}
if (refresh_date) { snprintf(buf, sizeof(buf), "%02d", d);
lv_spangroup_refresh(ctx->date_group); lv_label_set_text(day, buf);
}
// ---- TIME ---- snprintf(buf, sizeof(buf), "%02d", monthVal+1);
if (t->tm_hour != ctx->last_hour) { lv_label_set_text(month, buf);
ctx->last_hour = t->tm_hour;
u8_to_2digits(buf, t->tm_hour);
ESP_LOGE(TAG,"Heure %s",buf);
lv_span_set_text(ctx->time_hour, buf);
refresh_time = true;
}
if (t->tm_min != ctx->last_min) { snprintf(buf, sizeof(buf), "%02d", h);
ctx->last_min = t->tm_min; lv_label_set_text(hour, buf);
buf[0] = ':';
buf[1] = '0' + (t->tm_min / 10);
buf[2] = '0' + (t->tm_min % 10);
buf[3] = '\0';
ESP_LOGE(TAG,"Minutes %s",buf);
lv_span_set_text(ctx->time_min, buf);
refresh_time = true;
}
if (refresh_time) {
lv_spangroup_refresh(ctx->time_group);
}
snprintf(buf, sizeof(buf), "%02d", m);
lv_label_set_text(minute, buf);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -1398,6 +1518,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_t *btnUp = lv_button_create(cont_colVolets); lv_obj_t *btnUp = lv_button_create(cont_colVolets);
lv_obj_set_id(btnUp, (void *)"CV_BT_UP"); lv_obj_set_id(btnUp, (void *)"CV_BT_UP");
lv_obj_set_size(btnUp,60,60);
lv_obj_add_style(btnUp, &style_btn, 0); lv_obj_add_style(btnUp, &style_btn, 0);
lv_obj_add_event_cb(btnUp, event_handler, LV_EVENT_ALL, upEvent); lv_obj_add_event_cb(btnUp, event_handler, LV_EVENT_ALL, upEvent);
// lv_obj_align(btnUp, LV_ALIGN_CENTER, 0, -40); // lv_obj_align(btnUp, LV_ALIGN_CENTER, 0, -40);
@ -1412,6 +1533,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_name(btnDwn, "btnDown_#"); lv_obj_set_name(btnDwn, "btnDown_#");
lv_obj_add_style(btnDwn, &style_btn, 0); lv_obj_add_style(btnDwn, &style_btn, 0);
lv_obj_set_size(btnDwn,60,60);
lv_obj_add_event_cb(btnDwn, event_handler, LV_EVENT_ALL, downEvent); lv_obj_add_event_cb(btnDwn, event_handler, LV_EVENT_ALL, downEvent);
// lv_obj_align(btnDwn, LV_ALIGN_CENTER, 0, -40); // lv_obj_align(btnDwn, LV_ALIGN_CENTER, 0, -40);
lv_obj_remove_flag(btnDwn, LV_OBJ_FLAG_PRESS_LOCK); lv_obj_remove_flag(btnDwn, LV_OBJ_FLAG_PRESS_LOCK);
@ -1424,7 +1546,9 @@ void messageCardContent(lv_obj_t *cont_messages)
{ {
// lv_obj_t *txt = lv_label_create(container); // lv_obj_t *txt = lv_label_create(container);
// lv_label_set_text(txt, "Meteo"); // lv_label_set_text(txt, "Meteo");
weatherDay_fragment_create_obj(0, container, true); weatherH_fragment_create_obj(0, container,true);
weatherH_fragment_create_obj(1, container,true);
weatherH_fragment_create_obj(2, container,true);
// lv_subject_add_observer_obj(&forecastD1Subj, weatherdata_obs_cb, container, NULL); // lv_subject_add_observer_obj(&forecastD1Subj, weatherdata_obs_cb, container, NULL);
} }
@ -1437,10 +1561,41 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_width(txtMinuteur, LV_PCT(100)); lv_obj_set_width(txtMinuteur, LV_PCT(100));
} }
void draw_minuteur(char *txt){
lv_label_set_text(txtMinuteur, txt); lv_obj_t *btnStopNotif;
static void minuteur_event_handler(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e);
// lv_obj_t *obj = (lv_obj_t *)lv_event_get_target(e);
char *evtData = (char *)lv_event_get_user_data(e);
switch (code)
{
case LV_EVENT_CLICKED:
send_event(EVT_FIN_MACHINE_STOP_NOTIF,NULL);
lv_obj_delete(btnStopNotif);
break;
default:
break;
}
} }
void draw_minuteur(char *txt){
lv_label_set_text(txtMinuteur, txt);
}
void draw_minuteurStop(char *txt){
lv_obj_t *ctr = lv_obj_get_parent(txtMinuteur);
btnStopNotif = lv_btn_create(ctr);
lv_obj_add_event_cb(btnStopNotif, minuteur_event_handler, LV_EVENT_ALL, NULL);
lv_obj_t * label=lv_label_create(btnStopNotif);
lv_label_set_text(label, "Stop !");
lv_obj_center(label);
}
static void backCb(lv_event_t * e) static void backCb(lv_event_t * e)
{ {
@ -1467,15 +1622,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100)); lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
lv_obj_t *back = lv_label_create(meteoContainer); createBackBtn(meteoContainer);
lv_obj_add_flag(back, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_id(back, "backBtn");
lv_label_set_text(back, LV_SYMBOL_HOME);
//lv_obj_set_style_border_color(back, lv_color_make(255, 0, 0), 0);
//lv_obj_set_style_border_width(back, 1, 0);
lv_obj_set_style_text_font(back, lv_theme_get_font_large(back), 0);
//lv_obj_set_style_text_color(back, lv_color_white(), 0);
lv_obj_add_event_cb(back, backCb, LV_EVENT_CLICKED, NULL);
lv_obj_t *title = lv_label_create(meteoContainer); lv_obj_t *title = lv_label_create(meteoContainer);
lv_obj_set_id(title, "titleMeteoLbl"); lv_obj_set_id(title, "titleMeteoLbl");
@ -1495,15 +1642,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100)); lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
lv_obj_t *back = lv_label_create(meteoContainer); createBackBtn(meteoContainer);
lv_obj_add_flag(back, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_id(back, "backBtn");
lv_label_set_text(back, LV_SYMBOL_HOME);
//lv_obj_set_style_border_color(back, lv_color_make(255, 0, 0), 0);
//lv_obj_set_style_border_width(back, 1, 0);
lv_obj_set_style_text_font(back, lv_theme_get_font_large(back), 0);
lv_obj_set_style_text_color(back, lv_color_white(), 0);
lv_obj_add_event_cb(back, backCb, LV_EVENT_CLICKED, NULL);
lv_obj_t *title = lv_label_create(meteoContainer); lv_obj_t *title = lv_label_create(meteoContainer);
lv_obj_set_id(title, "titleMeteoLbl"); lv_obj_set_id(title, "titleMeteoLbl");
@ -1525,15 +1664,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100)); lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
lv_obj_t *back = lv_label_create(meteoContainer); createBackBtn(meteoContainer);
lv_obj_add_flag(back, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_id(back, "backBtn");
lv_label_set_text(back, LV_SYMBOL_HOME);
//lv_obj_set_style_border_color(back, lv_color_make(255, 0, 0), 0);
//lv_obj_set_style_border_width(back, 1, 0);
lv_obj_set_style_text_font(back, lv_theme_get_font_large(back), 0);
lv_obj_set_style_text_color(back, lv_color_white(), 0);
lv_obj_add_event_cb(back, backCb, LV_EVENT_CLICKED, NULL);
lv_obj_t *title = lv_label_create(meteoContainer); lv_obj_t *title = lv_label_create(meteoContainer);
lv_obj_set_id(title, "titleMeteoLbl"); lv_obj_set_id(title, "titleMeteoLbl");
@ -1556,15 +1687,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100)); lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
lv_obj_t *back = lv_label_create(meteoContainer); createBackBtn(meteoContainer);
lv_obj_add_flag(back, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_id(back, "backBtn");
lv_label_set_text(back, LV_SYMBOL_HOME);
//lv_obj_set_style_border_color(back, lv_color_make(255, 0, 0), 0);
//lv_obj_set_style_border_width(back, 1, 0);
lv_obj_set_style_text_font(back, lv_theme_get_font_large(back), 0);
lv_obj_set_style_text_color(back, lv_color_white(), 0);
lv_obj_add_event_cb(back, backCb, LV_EVENT_CLICKED, NULL);
lv_obj_t *title = lv_label_create(meteoContainer); lv_obj_t *title = lv_label_create(meteoContainer);
lv_obj_set_id(title, "titleMeteoLbl"); lv_obj_set_id(title, "titleMeteoLbl");
@ -1574,7 +1697,24 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_add_event_cb(title, backCb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(title, backCb, LV_EVENT_CLICKED, NULL);
draw_tabMeteo(meteoContainer); draw_tabMeteo(meteoContainer);
}
void createBackBtn(lv_obj_t *meteoContainer)
{
lv_obj_t *backBtn = lv_button_create(meteoContainer);
lv_obj_add_flag(backBtn, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_id(backBtn, "backBtn");
lv_obj_set_style_border_color(backBtn, lv_color_make(0, 0, 0), 0);
lv_obj_set_style_border_width(backBtn, 1, 0);
lv_obj_set_style_bg_opa(backBtn, 50, 0);
lv_obj_set_size(backBtn, 80, 80);
lv_obj_add_event_cb(backBtn, backCb, LV_EVENT_CLICKED, NULL);
lv_obj_t *backBtnLbl = lv_label_create(backBtn);
lv_label_set_text(backBtnLbl, LV_SYMBOL_HOME);
lv_obj_set_align(backBtnLbl, LV_TEXT_ALIGN_CENTER);
lv_obj_set_style_text_font(backBtnLbl, lv_theme_get_font_large(backBtnLbl), 0);
lv_obj_set_style_text_color(backBtnLbl, lv_color_white(), 0);
lv_obj_center(backBtnLbl);
} }
void messagerieCb(lv_obj_t *base_obj) void messagerieCb(lv_obj_t *base_obj)
@ -1583,6 +1723,7 @@ void messageCardContent(lv_obj_t *cont_messages)
} }
void minuteurCb(lv_obj_t *base_obj) void minuteurCb(lv_obj_t *base_obj)
{ {
send_event(EVT_FIN_MACHINE_STOP_NOTIF,NULL);
drawMinuteur(base_obj); drawMinuteur(base_obj);
} }
void voletsCb(lv_obj_t *base_obj) void voletsCb(lv_obj_t *base_obj)
@ -1612,21 +1753,29 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_user_data(dateTimeObj, ctx); lv_obj_set_user_data(dateTimeObj, ctx);
} }
void initHome(){
void drawHome() /*Initialize the styles*/
{
/*Initialize the styles*/
lv_style_init(&style_btn); lv_style_init(&style_btn);
// lv_style_set_bg_color(&style_btn, lv_palette_main(LV_PALETTE_GREEN)); // lv_style_set_bg_color(&style_btn, lv_palette_main(LV_PALETTE_GREEN));
// lv_style_set_border_color(&style_btn, lv_palette_darken(LV_PALETTE_GREEN, 3)); // lv_style_set_border_color(&style_btn, lv_palette_darken(LV_PALETTE_GREEN, 3));
// lv_style_set_border_width(&style_btn, 3); // lv_style_set_border_width(&style_btn, 3);
lv_style_init(&objstyle);
lv_style_set_bg_color(&objstyle, accent);
lv_style_set_outline_color(&objstyle, accent);
lv_subject_init_string(&tempExtSubj, tempExtStr, NULL, 6, "--"); lv_subject_init_string(&tempExtSubj, tempExtStr, NULL, 6, "--");
lv_subject_init_string(&tempIntSubj, tempIntStr, NULL, 6, "--"); lv_subject_init_string(&tempIntSubj, tempIntStr, NULL, 50, "--");
lv_subject_init_string(&hauteurCuveSubj, hauteurCuveStr, NULL, 9, "--"); lv_subject_init_string(&hauteurCuveSubj, hauteurCuveStr, NULL, 9, "--");
lv_subject_init_string(&hauteurCuveEvolSubj, hauteurCuveEvolStr, NULL, 9, "--"); lv_subject_init_string(&hauteurCuveEvolSubj, hauteurCuveEvolStr, NULL, 9, "--");
}
void drawHome()
{
// keys.clear(); // keys.clear();
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
@ -1641,9 +1790,6 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_style_pad_top(bg_cont, 5, 0); lv_obj_set_style_pad_top(bg_cont, 5, 0);
lv_obj_set_style_bg_color(bg_cont, bgColor, 0); lv_obj_set_style_bg_color(bg_cont, bgColor, 0);
lv_style_init(&objstyle);
lv_style_set_bg_color(&objstyle, accent);
lv_style_set_outline_color(&objstyle, accent);
/* info area */ /* info area */
@ -1665,46 +1811,96 @@ void messageCardContent(lv_obj_t *cont_messages)
//lv_obj_remove_style_all(date_and_time); //lv_obj_remove_style_all(date_and_time);
lv_obj_set_size(date_and_time, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_set_size(date_and_time, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_t *date = lv_spangroup_create(date_and_time); lv_obj_t *date = lv_obj_create(date_and_time);
lv_obj_set_name(date, "date"); lv_obj_set_name(date, "date");
lv_obj_set_id(date, "date"); lv_obj_set_id(date, "date");
lv_obj_set_size(date, 250, LV_SIZE_CONTENT);
lv_obj_clear_flag(date, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_opa(date, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(date, 0, 0);
// Layout flex horizontal
lv_obj_set_flex_flow(date, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(
date,
LV_FLEX_ALIGN_SPACE_BETWEEN, // répartit les enfants
LV_FLEX_ALIGN_CENTER, // align vertical
LV_FLEX_ALIGN_CENTER
);
// lv_obj_add_style(date, &c->fonts[FONT_HEADING_MD], 0); // lv_obj_add_style(date, &c->fonts[FONT_HEADING_MD], 0);
// lv_obj_add_style(date, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0); // lv_obj_add_style(date, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
lv_span_t *day = lv_spangroup_add_span(date); lv_obj_t *day = lv_label_create(date);
lv_span_set_text(day, "--"); lv_obj_set_name(day, "day");
lv_style_set_text_font(lv_span_get_style(day), &super_malibu_80); lv_label_set_text(day, "--");
lv_style_set_text_color(lv_span_get_style(day), base); lv_obj_set_style_text_font(day, &super_malibu_80, 0);
lv_style_set_line_color(lv_span_get_style(day), lv_color_black()); lv_obj_set_style_text_color(day, lv_color_white(), 0);
lv_style_set_line_width(lv_span_get_style(day), 2); lv_obj_set_style_line_color(day, lv_color_black(), 0);
lv_span_t *month = lv_spangroup_add_span(date); lv_obj_set_style_line_width(day, 2, 0);
lv_span_set_text(month, "--"); // --- / ---
lv_style_set_text_font(lv_span_get_style(month), &super_malibu_80); lv_obj_t *slash_lbl = lv_label_create(date);
lv_obj_set_name(slash_lbl, "slash");
lv_obj_set_style_text_font(slash_lbl, &super_malibu_80, 0);
lv_obj_set_style_text_color(slash_lbl, base, 0);
lv_label_set_text(slash_lbl, "/");
lv_obj_t *time = lv_spangroup_create(date_and_time); lv_obj_t *month = lv_label_create(date);
lv_obj_set_name(time, "time"); lv_obj_set_name(month, "month");
lv_obj_set_id(time, "time"); lv_label_set_text(month, "--");
// lv_obj_add_style(time, &txtstyle, 0); lv_obj_set_style_text_font(month, &super_malibu_80,0);
lv_span_t *hourSpan = lv_spangroup_add_span(time);
lv_span_set_text(hourSpan, "--");
lv_style_set_text_font(lv_span_get_style(hourSpan), &super_malibu_80);
lv_span_t *minute = lv_spangroup_add_span(time);
lv_span_set_text(minute, ":--");
lv_style_set_text_color(lv_span_get_style(minute), base);
lv_style_set_line_color(lv_span_get_style(minute), accent);
lv_style_set_text_font(lv_span_get_style(minute), &super_malibu_80);
//lv_subject_add_observer_obj(&c->th, theme_observer_accent_span_cb, time, minute);
lv_obj_t *objTime = lv_obj_create(date_and_time);
lv_obj_set_size(objTime, 250, LV_SIZE_CONTENT);
lv_obj_clear_flag(objTime, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_opa(objTime, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(objTime, 0, 0);
// Layout flex horizontal
lv_obj_set_flex_flow(objTime, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(
objTime,
LV_FLEX_ALIGN_SPACE_BETWEEN, // répartit les enfants
LV_FLEX_ALIGN_CENTER, // align vertical
LV_FLEX_ALIGN_CENTER
);
// --- HEURES ---
lv_obj_t *hour_lbl = lv_label_create(objTime);
lv_obj_set_name(hour_lbl, "hour");
lv_obj_set_style_text_font(hour_lbl, &super_malibu_80, 0);
lv_obj_set_style_text_color(hour_lbl, lv_color_white(), 0);
lv_label_set_text(hour_lbl, "--");
// --- DEUX-POINTS ---
lv_obj_t *colon_lbl = lv_label_create(objTime);
lv_obj_set_name(colon_lbl, "colon");
lv_obj_set_style_text_font(colon_lbl, &super_malibu_80, 0);
lv_obj_set_style_text_color(colon_lbl, base, 0);
lv_label_set_text(colon_lbl, ":");
// --- MINUTES ---
lv_obj_t *minute_lbl = lv_label_create(objTime);
lv_obj_set_name(minute_lbl, "minute");
lv_obj_set_style_text_font(minute_lbl, &super_malibu_80, 0);
lv_obj_set_style_text_color(minute_lbl, lv_color_white(), 0);
lv_label_set_text(minute_lbl, "--");
// Init datetime
//datetime_ctx_init(date_and_time);
lv_subject_add_observer_obj(&timeSubj, time_observer_cb, date_and_time, NULL); lv_subject_add_observer_obj(&timeSubj, time_observer_cb, date_and_time, NULL);
datetime_ctx_init(date_and_time);
lv_obj_t * subContent = lv_obj_create(info_area); lv_obj_t * subContent = lv_obj_create(info_area);
lv_obj_set_flex_flow(subContent, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_flow(subContent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_size(subContent, LV_PCT(70), LV_PCT(100)); lv_obj_set_size(subContent, LV_PCT(70), LV_PCT(100));
lv_obj_t *lblTempInt = lv_label_create(subContent); lblTempInt = lv_label_create(subContent);
lv_label_set_text(lblTempInt, "\xEE\x86\xB0\xEF\x8B\x8A : 21°C"); lv_obj_set_name(lblTempInt,"lblTempInt");
char *templateValue="\xEE\x86\xB0\xEF\x8B\x8A : %s";
lv_obj_set_style_text_font(lblTempInt, lv_theme_get_font_large(lblTempInt),0); lv_obj_set_style_text_font(lblTempInt, lv_theme_get_font_large(lblTempInt),0);
lv_obj_t *lblTempExt = lv_label_create(subContent); lv_subject_add_observer_obj(&tempIntSubj, temp_observer_cb, lblTempInt, templateValue);
lv_label_set_text(lblTempExt, LV_SYMBOL_HOME "\xEF\x8B\x8A : 12°C");
lblTempExt = lv_label_create(subContent);
lv_obj_set_name(lblTempExt,"lblTempExt");
char *templateValue2=LV_SYMBOL_HOME "\xEF\x8B\x8A : %s°C";
lv_obj_set_style_text_font(lblTempExt, lv_theme_get_font_large(lblTempExt),0); lv_obj_set_style_text_font(lblTempExt, lv_theme_get_font_large(lblTempExt),0);
lv_subject_add_observer_obj(&tempExtSubj, temp_observer_cb, lblTempExt, templateValue2);
/*for (size_t i = 0; i < 2; i++) /*for (size_t i = 0; i < 2; i++)
{ {
@ -1727,11 +1923,11 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_flex_flow(apps, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(apps, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_column(apps, 6, 0); lv_obj_set_style_pad_column(apps, 6, 0);
create_card(apps, "Météo", meteoCardContent, meteoCb); create_card(apps, "Météo", meteoCardContent, meteoCb,400);
create_card(apps, "Volets", coverCardContent, voletsCb); create_card(apps, "Volets", coverCardContent, voletsCb,150);
create_card(apps, "Minuteur", minuteurCardContent, minuteurCb); create_card(apps, "Minuteur", minuteurCardContent, minuteurCb,300);
create_card(apps, "Messagerie", messageCardContent, messagerieCb); create_card(apps, "Messagerie", messageCardContent, messagerieCb,300);
return; return;
} }
@ -1813,7 +2009,7 @@ static void app_card_click_cb(lv_event_t *e)
app_cb(base_obj); app_cb(base_obj);
} }
void create_card(lv_obj_t *parent, char *lbl, void (*contentFct)(lv_obj_t *), app_cb_t app_cb) void create_card(lv_obj_t *parent, char *lbl, void (*contentFct)(lv_obj_t *), app_cb_t app_cb, int width)
{ {
//lv_style_init(&objstyle); //lv_style_init(&objstyle);
//lv_style_init(&txtstyle); //lv_style_init(&txtstyle);
@ -1828,7 +2024,10 @@ void create_card(lv_obj_t *parent, char *lbl, void (*contentFct)(lv_obj_t *), ap
lv_obj_set_id(app_card, "app_card"); lv_obj_set_id(app_card, "app_card");
lv_obj_set_name(app_card, "app_card"); lv_obj_set_name(app_card, "app_card");
//lv_obj_remove_style_all(app_card); //lv_obj_remove_style_all(app_card);
lv_obj_set_size(app_card, 300, 200); if(width>0)
lv_obj_set_size(app_card, width, 200);
else
lv_obj_set_size(app_card, 300, 200);
//lv_obj_set_size(app_card, 100, 60); //lv_obj_set_size(app_card, 100, 60);
lv_obj_set_style_radius(app_card, 20, 0); lv_obj_set_style_radius(app_card, 20, 0);
lv_obj_set_style_bg_opa(app_card, 50, 0); lv_obj_set_style_bg_opa(app_card, 50, 0);

View File

@ -35,10 +35,11 @@ void ihm_gateway_post_event(xIHMEvent_t *evt) {
extern lv_subject_t wifiStatus; extern lv_subject_t wifiStatus;
static xIHMEvent_t *evt = NULL;
void ihm_gateway_process_queue(void) { void ihm_gateway_process_queue(void) {
if (!xIHMEventQueue) return; if (!xIHMEventQueue) return;
xIHMEvent_t *evt = NULL;
#if CONFIG_IDF_TARGET_LINUX #if CONFIG_IDF_TARGET_LINUX
while (xQueueReceive(xIHMEventQueue, &evt, pdMS_TO_TICKS(0)) == pdTRUE) while (xQueueReceive(xIHMEventQueue, &evt, pdMS_TO_TICKS(0)) == pdTRUE)
@ -49,7 +50,7 @@ void ihm_gateway_process_queue(void) {
if (!evt) return; if (!evt) return;
UBaseType_t pending = uxQueueMessagesWaiting(xIHMEventQueue); UBaseType_t pending = uxQueueMessagesWaiting(xIHMEventQueue);
ESP_LOGE(TAG,"Evt recu %d. La queue comporte %d éléments à traiter", evt->eEventType, pending); ESP_LOGV(TAG,"Evt recu %d. La queue comporte %d éléments à traiter", evt->eEventType, pending);
lv_async_call(traiteEvt, evt); lv_async_call(traiteEvt, evt);
} }
@ -66,7 +67,8 @@ void traiteEvt(void *arg)
case IHM_EVT_TIME_SETTED: case IHM_EVT_TIME_SETTED:
draw_time(evt->pvData); draw_time(evt->pvData);
break; evt->bNeedToFreeData=false;
break;
case IHM_EVT_OTA_STARTED: case IHM_EVT_OTA_STARTED:
app_ota_display(); app_ota_display();
@ -74,6 +76,12 @@ void traiteEvt(void *arg)
case IHM_EVT_HUMID_TEMP: case IHM_EVT_HUMID_TEMP:
draw_temp((char *)evt->pvData); draw_temp((char *)evt->pvData);
evt->bNeedToFreeData=false;
break;
case IHM_EVT_TEMP_RECUE:
draw_tempExt((char *)evt->pvData);
evt->bNeedToFreeData=false;
break; break;
case IHM_EVT_PUISSANCE_EMISE: case IHM_EVT_PUISSANCE_EMISE:
@ -90,12 +98,17 @@ void traiteEvt(void *arg)
WashingMachineState wms = traiteMessage(etatMachine); WashingMachineState wms = traiteMessage(etatMachine);
char etat[80]; char etat[80];
getEtatMachineStr(wms, etat,80); getEtatMachineStr(wms, etat,80);
ESP_LOGE(TAG,"Etat machine : %s", etat); ESP_LOGI(TAG,"Etat machine : %s", etat);
draw_minuteur(etat); draw_minuteur(etat);
// lv_label_set_text(lblEtatMachine, etatFormate); // lv_label_set_text(lblEtatMachine, etatFormate);
break; break;
} }
case IHM_EVT_MACHINE_TERMINEE:
{
draw_minuteurStop();
}
case IHM_EVT_HAUTEUR_CUVE: case IHM_EVT_HAUTEUR_CUVE:
{ {
float hauteur = *(float *)evt->pvData; float hauteur = *(float *)evt->pvData;
@ -103,13 +116,39 @@ void traiteEvt(void *arg)
break; break;
} }
case IHM_EVT_METEO_RECUE:{
//(void *)evt->pvData; // Pointeur sur tableau
//(void *)evt->pvData
ESP_LOGI(TAG, "Reception evt MF");
// On ne veut liberer la memoire que lorsque l'evenement aura été traité!
evt->bNeedToFreeData=false;
meteo_event_payload_t *datas = (meteo_event_payload_t *) evt->pvData;
for (size_t i = 0; i < 3; i++)
{
ESP_LOGI(TAG,"Type: %s - Valide : %d - %s", datas->daily[i].type, datas->daily[i].isValid, datas->daily[i].previsions.desc);
}
for (size_t i = 0; i < 3; i++)
{
ESP_LOGI(TAG,"Type: %s - Valide : %d - %s - %s - %f", datas->forecast[i].type, datas->forecast[i].isValid, datas->forecast[i].previsions.desc, datas->forecast[i].previsions.icon, datas->forecast[i].previsions.value);
}
draw_meteo(datas);
//lv_subject_set_int(&meteoStatus, 0);
//display_unlock("weather_data_retreived");
ESP_LOGI(TAG, "Fin Reception evt MF");
break;
}
default: default:
ESP_LOGE(TAG, "Evt inconnu"); ESP_LOGE(TAG, "Evt inconnu");
break; break;
} }
// Nettoyage mémoire sécurisé // Nettoyage mémoire sécurisé
if (evt->bNeedToFreeData && evt->pvData) if (evt->bNeedToFreeData && evt->pvData){
//ESP_LOGE(TAG, "Libération mémoire");
free(evt->pvData); free(evt->pvData);
}
free(evt); free(evt);
ESP_LOGV(TAG, "Evt traité"); ESP_LOGV(TAG, "Evt traité");
} }

View File

@ -19,17 +19,23 @@ void showMeteoIcon(const char *icon, lv_obj_t *desc_icon, int childNr);
void draw_tabVolets(); void draw_tabVolets();
void meteoCb(lv_obj_t *base_obj); void meteoCb(lv_obj_t *base_obj);
void createBackBtn(lv_obj_t *ontainer);
void initHome();
void drawHome(); void drawHome();
void draw_time(struct tm *dateHeure); void draw_time(struct tm *dateHeure);
void draw_tempExt(char *tempHumid);
void draw_minuteur(char *txt); void draw_minuteur(char *txt);
void draw_minuteurStop();
void draw_temp(char *tempHumid); void draw_temp(char *tempHumid);
void draw_meteo(meteo_event_payload_t *meteo);
void create_card(); void create_card();
void weather_data_retreived_start(); void weather_data_retreived_start();
void weather_data_retreived(meteodailyforecast_data dailyDatas[3], meteoforecast_data datas[3]); void weather_data_retreived(meteo_event_payload_t *datas);
void draw_tabMeteo(lv_obj_t * parent); void draw_tabMeteo(lv_obj_t * parent);
@ -39,4 +45,6 @@ void draw_tabCuve(lv_obj_t * parent);
void draw_tabHome(lv_obj_t * parent); void draw_tabHome(lv_obj_t * parent);
void draw_tabSettings(lv_obj_t * parent); void draw_tabSettings(lv_obj_t * parent);
void suspendIHM();
void drawIhm(void *pvParameter); void drawIhm(void *pvParameter);

View File

@ -10,6 +10,7 @@ list(APPEND EXTRA_COMPONENT_DIRS
../../stateManagement ../../stateManagement
../../eventsManager ../../eventsManager
../../RemindMe ../../RemindMe
../../washingMachineState
) )
idf_build_set_property(COMPILE_DEFINITIONS "NO_DEBUG_STORAGE" APPEND) idf_build_set_property(COMPILE_DEFINITIONS "NO_DEBUG_STORAGE" APPEND)

View File

@ -2,7 +2,7 @@ dependencies:
idf: idf:
source: source:
type: idf type: idf
version: 5.5.2 version: 5.5.0
lvgl/lvgl: lvgl/lvgl:
component_hash: 17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f component_hash: 17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f
dependencies: [] dependencies: []

View File

@ -20,7 +20,7 @@ idf_component_register(SRCS
"../../include" "../../include"
"../mock" "../mock"
WHOLE_ARCHIVE WHOLE_ARCHIVE
REQUIRES lvgl meteofrance RemindMe) REQUIRES lvgl meteofrance RemindMe washingMachineState)
message("Including SDL2 support") message("Including SDL2 support")
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)

View File

@ -1,3 +1,9 @@
if(${IDF_TARGET} STREQUAL "esp32p4")
idf_component_register(SRCS "obtain_time.c" "eventsManager.c" obtain_time.c idf_component_register(SRCS "obtain_time.c" "eventsManager.c" obtain_time.c
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
REQUIRES mqtt esp_netif) REQUIRES mqtt esp_netif meteofrance audio)
else()
idf_component_register(SRCS "obtain_time.c" "eventsManager.c" obtain_time.c
INCLUDE_DIRS "include"
REQUIRES mqtt esp_netif meteofrance)
endif()

View File

@ -5,10 +5,14 @@
#include "mqtt_client.h" #include "mqtt_client.h"
#include "obtain_time.h" #include "obtain_time.h"
#include <time.h> #include <time.h>
#include "meteofrance.h"
#if CONFIG_IDF_TARGET_ESP32P4
#include "audio.h"
#endif
EventGroupHandle_t domotic_event_group; EventGroupHandle_t domotic_event_group;
QueueHandle_t ihm_queue; QueueHandle_t ihm_queue;
//extern esp_mqtt_client_handle_t client; extern esp_mqtt_client_handle_t client;
static const char *TAG = "evtMgr"; static const char *TAG = "evtMgr";
@ -25,8 +29,43 @@ void startEvtManager(){
/* Tache updateTime - FIN*/ /* Tache updateTime - FIN*/
} }
const char * domo_event_to_str(domo_events evt)
{
switch (evt) {
case EVT_WIFI_CONNECTED: return "WIFI_CONNECTED";
case EVT_TIME_SETTED: return "TIME_SETTED";
case EVT_BTN_VOLET: return "BTN_VOLET";
case EVT_PUISSANCE_RECUE: return "PUISSANCE_RECUE";
case EVT_ETAT_MACHINE: return "ETAT_MACHINE";
case EVT_HAUTEUR_CUVE: return "HAUTEUR_CUVE";
case EVT_METEO_RECUE: return "METEO_RECUE";
case EVT_TEMP_EXT: return "TEMP_EXT";
case EVT_TEMP_INT: return "TEMP_INT";
case EVT_FIN_MACHINE: return "FIN_MACHINE";
case EVT_FIN_MACHINE_STOP_NOTIF: return "FIN_MACHINE_STOP_NOTIF";
default: return "EVT_UNKNOWN";
}
}
const char * ihm_event_to_str(eIHMEvent_t evt)
{
switch (evt) {
case IHM_EVT_WIFI_STATUS: return "IHM_WIFI_STATUS";
case IHM_EVT_TIME_SETTED: return "IHM_TIME_SETTED";
case IHM_EVT_OTA_STARTED: return "IHM_OTA_STARTED";
case IHM_EVT_OTA_PROGRESS: return "IHM_OTA_PROGRESS";
case IHM_EVT_HUMID_TEMP: return "IHM_HUMID_TEMP";
case IHM_EVT_PUISSANCE_EMISE: return "IHM_PUISSANCE_EMISE";
case IHM_EVT_ETAT_MACHINE: return "IHM_ETAT_MACHINE";
case IHM_EVT_HAUTEUR_CUVE: return "IHM_HAUTEUR_CUVE";
case IHM_EVT_METEO_RECUE: return "IHM_METEO_RECUE";
case IHM_EVT_TEMP_RECUE: return "IHM_TEMP_RECUE";
default: return "IHM_EVT_UNKNOWN";
}
}
void send_event(domo_events evt, void* pDatas) { void send_event(domo_events evt, void* pDatas) {
ESP_LOGV(TAG,"On est dans l'event handler %i", evt); ESP_LOGI(TAG, "EventManager: On est dans l'event handler %s", domo_event_to_str(evt));
xIHMEvent_t *ihmEvt = malloc(sizeof(xIHMEvent_t)); xIHMEvent_t *ihmEvt = malloc(sizeof(xIHMEvent_t));
if (!ihmEvt) { if (!ihmEvt) {
@ -78,12 +117,13 @@ void send_event(domo_events evt, void* pDatas) {
break; break;
case EVT_BTN_VOLET: case EVT_BTN_VOLET:
//esp_mqtt_client_publish(client, "volets", pDatas, 0, 0, 0); esp_mqtt_client_publish(client, "volets", pDatas, 0, 0, 0);
free(ihmEvt); // rien à envoyer à l'IHM free(ihmEvt); // rien à envoyer à l'IHM
ihmEvt = NULL;
return; return;
case EVT_PUISSANCE_RECUE: case EVT_PUISSANCE_RECUE:
ESP_LOGE(TAG, "Puissance recue %i", *(int*)pDatas); ESP_LOGI(TAG, "Puissance recue %i", *(int*)pDatas);
int *data = malloc(sizeof(int)); int *data = malloc(sizeof(int));
if (!data) { if (!data) {
ESP_LOGE(TAG, "malloc failed for puissance_5mn"); ESP_LOGE(TAG, "malloc failed for puissance_5mn");
@ -110,6 +150,38 @@ void send_event(domo_events evt, void* pDatas) {
ihmEvt->bNeedToFreeData = true; ihmEvt->bNeedToFreeData = true;
break; break;
case EVT_TEMP_EXT:
const char *msg3 = (const char *)pDatas;
char *msg_copy3 = malloc(strlen(msg3) + 1);
if (!msg_copy3) {
ESP_LOGE(TAG, "malloc failed for message string");
free(ihmEvt);
return;
}
strcpy(msg_copy3, msg3);
ihmEvt->eEventType = IHM_EVT_TEMP_RECUE;
ihmEvt->pvData = msg_copy3;
ihmEvt->bNeedToFreeData = true;
break;
case EVT_TEMP_INT:
const char *msg4 = (const char *)pDatas;
char *msg_copy4 = malloc(strlen(msg4) + 1);
if (!msg_copy4) {
ESP_LOGE(TAG, "malloc failed for message string");
free(ihmEvt);
return;
}
strcpy(msg_copy4, msg4);
ihmEvt->eEventType = IHM_EVT_HUMID_TEMP;
ihmEvt->pvData = msg_copy4;
ihmEvt->bNeedToFreeData = true;
//On envoie les données via mqtt
esp_mqtt_client_publish(client, topicTempInt, pDatas, 0, 0, 0);
break;
case EVT_HAUTEUR_CUVE: { case EVT_HAUTEUR_CUVE: {
float *data = malloc(sizeof(float)); float *data = malloc(sizeof(float));
if (!data) { if (!data) {
@ -125,13 +197,49 @@ void send_event(domo_events evt, void* pDatas) {
break; break;
} }
case EVT_METEO_RECUE:{
meteo_event_payload_t *incoming = (meteo_event_payload_t *) pDatas;
meteo_event_payload_t *payload = malloc(sizeof(meteo_event_payload_t));
if (payload == NULL) {
// gérer lerreur
return;
}
memcpy(payload->daily, incoming->daily, sizeof(incoming->daily));
memcpy(payload->forecast, incoming->forecast, sizeof(incoming->forecast));
ihmEvt->eEventType = IHM_EVT_METEO_RECUE;
ihmEvt->pvData = payload;
ihmEvt->bNeedToFreeData = true;
break;
}
case EVT_FIN_MACHINE:{
#if CONFIG_IDF_TARGET_ESP32P4
playSound();
#endif
ihmEvt->eEventType = IHM_EVT_MACHINE_TERMINEE;
ihmEvt->pvData = NULL;
ihmEvt->bNeedToFreeData = false;
break;
}
case EVT_FIN_MACHINE_STOP_NOTIF:{
#if CONFIG_IDF_TARGET_ESP32P4
stopSound();
#endif
free(ihmEvt); // rien à envoyer à l'IHM
ihmEvt = NULL;
break;
}
default: default:
ESP_LOGE(TAG, "Unhandled event type"); ESP_LOGE(TAG, "Unhandled event type");
free(ihmEvt); free(ihmEvt);
ihmEvt = NULL;
return; return;
} }
ESP_LOGE(TAG, "Envoi d'un evt %i a l'IHM", ihmEvt->eEventType);
if( ihm_queue != NULL && ihmEvt){ if( ihm_queue != NULL && ihmEvt){
ESP_LOGI(TAG, "Suite %s : Envoi d'un evt %s (%i) a l'IHM", domo_event_to_str(evt), ihm_event_to_str(ihmEvt->eEventType),ihmEvt->eEventType);
if (xQueueSendToFront(ihm_queue, &ihmEvt, pdMS_TO_TICKS(10)) != pdPASS) if (xQueueSendToFront(ihm_queue, &ihmEvt, pdMS_TO_TICKS(10)) != pdPASS)
{ {
ESP_LOGE(TAG, "La queue est pleine"); ESP_LOGE(TAG, "La queue est pleine");
@ -141,5 +249,8 @@ void send_event(domo_events evt, void* pDatas) {
} }
free(ihmEvt); free(ihmEvt);
} }
}else{
ESP_LOGI(TAG, "Suite %s : on n'envoie rien a l'IHM", domo_event_to_str(evt));
} }
} }

View File

@ -14,6 +14,9 @@ typedef enum eIHMEvent_t{
IHM_EVT_PUISSANCE_EMISE, IHM_EVT_PUISSANCE_EMISE,
IHM_EVT_ETAT_MACHINE, IHM_EVT_ETAT_MACHINE,
IHM_EVT_HAUTEUR_CUVE, IHM_EVT_HAUTEUR_CUVE,
IHM_EVT_METEO_RECUE,
IHM_EVT_TEMP_RECUE,
IHM_EVT_MACHINE_TERMINEE
} eIHMEvent_t; } eIHMEvent_t;
typedef struct IHM_EVENT typedef struct IHM_EVENT
@ -29,8 +32,22 @@ typedef enum domo_events{
EVT_BTN_VOLET, EVT_BTN_VOLET,
EVT_PUISSANCE_RECUE, EVT_PUISSANCE_RECUE,
EVT_ETAT_MACHINE, EVT_ETAT_MACHINE,
EVT_HAUTEUR_CUVE EVT_HAUTEUR_CUVE,
EVT_METEO_RECUE,
EVT_TEMP_EXT,
EVT_TEMP_INT,
EVT_FIN_MACHINE,
EVT_FIN_MACHINE_STOP_NOTIF
} domo_events; } domo_events;
void startEvtManager(); void startEvtManager();
QueueHandle_t getIHMQueueHandle(); QueueHandle_t getIHMQueueHandle();
void send_event(domo_events evt, void *pDatas); void send_event(domo_events evt, void *pDatas);
#define topicTempExt "house/temp/282A802600008059"
#define topicHauteurCuve "house/cuve/hauteur"
#define topicTempInt "house/temp/287DCF1E00008020"
#define topicHauteurCuveEvol "house/cuve/hauteurEvol"
#define topicConsoElec "energy/puissance_5mn"
#define topicEtatMachine "energy/machine_en_route"
#define topicdomoticCommand "domotic/cmd"
#define topicTest "test"

View File

@ -73,8 +73,6 @@ void updateTime(void *pvParameter)
while (1) while (1)
{ {
time(&now); time(&now);
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
tzset();
struct tm timeinfo = {0}; struct tm timeinfo = {0};
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
sprintf(strftime_buf, "%s %d %s %02d:%02d (%lli mn depuis reboot)", days[timeinfo.tm_wday], timeinfo.tm_mday, months[timeinfo.tm_mon], timeinfo.tm_hour, timeinfo.tm_min, (esp_timer_get_time() / 1000 / 1000 / 60)); sprintf(strftime_buf, "%s %d %s %02d:%02d (%lli mn depuis reboot)", days[timeinfo.tm_wday], timeinfo.tm_mday, months[timeinfo.tm_mon], timeinfo.tm_hour, timeinfo.tm_min, (esp_timer_get_time() / 1000 / 1000 / 60));

View File

@ -29,21 +29,28 @@
char icon[9]; char icon[9];
}; };
typedef struct meteodailyforecast_data typedef struct meteodailyforecast_data // Meteo "par jour"
{ {
char *type;
time_t datetime; time_t datetime;
bool isValid; bool isValid;
struct dailyforecast_prev previsions; struct dailyforecast_prev previsions;
} meteodailyforecast_data; } meteodailyforecast_data;
typedef struct meteoforecast_data typedef struct meteoforecast_data // Meteo "par heure"
{ {
char *type;
time_t datetime; time_t datetime;
bool isValid; bool isValid;
struct forecast_prev previsions; struct forecast_prev previsions;
} meteoforecast_data; } meteoforecast_data;
typedef void (*weather_data_callback)(struct meteodailyforecast_data *datas, struct meteoforecast_data *datasf); typedef struct {
meteodailyforecast_data daily[3];
meteoforecast_data forecast[3];
} meteo_event_payload_t;
typedef void (*weather_data_callback)(meteo_event_payload_t *datas);
typedef void (*weather_data_start_callback)(); typedef void (*weather_data_start_callback)();
typedef struct typedef struct
@ -60,7 +67,7 @@
void printftemp(struct forecast_prev * tmp); void printftemp(struct forecast_prev * tmp);
void printfdf(struct meteodailyforecast_data * tmp); void printfdf(struct meteodailyforecast_data * tmp);
void dtToString(time_t, char *buffer); void dtToString(time_t, char *buffer);
void dtHToString(time_t, char *buffer); void dtHToString(time_t, char *buffer, size_t bufSize);
void printff(struct meteoforecast_data * tmp); void printff(struct meteoforecast_data * tmp);
void on_weather_data_retrieval(weather_data_callback data_retreived_cb); void on_weather_data_retrieval(weather_data_callback data_retreived_cb);

View File

@ -21,6 +21,7 @@
#include "esp_http_client.h" #include "esp_http_client.h"
#include "esp_tls.h" #include "esp_tls.h"
#include "stateManagement.h" #include "stateManagement.h"
#include "eventsManager.h"
static const char *TAG = "MeteoFrance"; static const char *TAG = "MeteoFrance";
/* Constants that aren't configurable in menuconfig /* Constants that aren't configurable in menuconfig
@ -39,8 +40,8 @@ static const char *TAG = "MeteoFrance";
#define MAX_HTTP_OUTPUT_BUFFER 32000 #define MAX_HTTP_OUTPUT_BUFFER 32000
static weather_data weather; static weather_data weather;
static struct meteodailyforecast_data dailydatas[5]; static struct meteodailyforecast_data dailydatas[3];
static struct meteoforecast_data forecastdatas[5]; static struct meteoforecast_data forecastdatas[3];
void printdftemp(struct dailyforecast_prev *tmp) void printdftemp(struct dailyforecast_prev *tmp)
{ {
@ -69,10 +70,10 @@ void dtToString(time_t ttt, char* buffer){
//sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1); //sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1);
} }
void dtHToString(time_t ttt, char* buffer){ void dtHToString(time_t ttt, char* buffer, size_t bufSize){
struct tm timeinfo = {0}; struct tm timeinfo = {0};
localtime_r(&ttt, &timeinfo); localtime_r(&ttt, &timeinfo);
strftime(buffer, MAX_SIZE, "%H:%M", &timeinfo); strftime(buffer, bufSize, "%H:%M", &timeinfo);
//char strftime_buf[64]; //char strftime_buf[64];
//sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1); //sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1);
} }
@ -247,6 +248,7 @@ void JSON_Parse(const cJSON *const root)
cJSON *dt = cJSON_GetObjectItem(current_element, "dt"); cJSON *dt = cJSON_GetObjectItem(current_element, "dt");
if (cJSON_IsNumber(dt)) if (cJSON_IsNumber(dt))
{ {
datasT.type="Daily";
datasT.datetime = dt->valueint; datasT.datetime = dt->valueint;
cJSON *temps = cJSON_GetObjectItem(current_element, "T"); cJSON *temps = cJSON_GetObjectItem(current_element, "T");
datasT.previsions.min = cJSON_GetObjectItem(temps, "min")->valuedouble; datasT.previsions.min = cJSON_GetObjectItem(temps, "min")->valuedouble;
@ -278,6 +280,7 @@ void JSON_Parse(const cJSON *const root)
cJSON *dt = cJSON_GetObjectItem(current_element, "dt"); cJSON *dt = cJSON_GetObjectItem(current_element, "dt");
if (cJSON_IsNumber(dt)) if (cJSON_IsNumber(dt))
{ {
datasT.type="Hourly";
datasT.datetime = dt->valueint; datasT.datetime = dt->valueint;
struct tm timeinfo = {0}; struct tm timeinfo = {0};
localtime_r(&(datasT.datetime), &timeinfo); localtime_r(&(datasT.datetime), &timeinfo);
@ -379,8 +382,13 @@ static void meteo_task(void* domotic_event_group)
heap_caps_free(local_response_buffer); heap_caps_free(local_response_buffer);
esp_http_client_cleanup(client); esp_http_client_cleanup(client);
if(dailydatas->isValid){ if(dailydatas->isValid){
ESP_LOGV(TAG, "Données valides on appelle le cb"); ESP_LOGE(TAG, "Données valides on appelle le cb");
weather.data_retreived_cb(dailydatas, forecastdatas); meteo_event_payload_t *payload = malloc(sizeof(*payload));
memcpy(payload->daily, dailydatas, sizeof(payload->daily));
memcpy(payload->forecast, forecastdatas, sizeof(payload->forecast));
send_event(EVT_METEO_RECUE, payload);
//weather.data_retreived_cb(payload);
free(payload);
vTaskDelay(weather.retreival_period / portTICK_PERIOD_MS); vTaskDelay(weather.retreival_period / portTICK_PERIOD_MS);
}else{ }else{
//Ca a échoué on recommence dans 30 secondes //Ca a échoué on recommence dans 30 secondes

View File

@ -1,2 +1,2 @@
idf_component_register(SRCS "washingMachineState.c" PRIV_REQUIRES json idf_component_register(SRCS "washingMachineState.c" PRIV_REQUIRES json eventsManager
INCLUDE_DIRS "include") INCLUDE_DIRS "include")

View File

@ -2,11 +2,13 @@
#include <cJSON.h> #include <cJSON.h>
#include <esp_log.h> #include <esp_log.h>
#include "washingMachineState.h" #include "washingMachineState.h"
#include "eventsManager.h"
#include <time.h> #include <time.h>
#define TAG "WMS" #define TAG "WMS"
WashingMachineState wms; WashingMachineState wms;
bool stateOn; // Indique si la machine est en route
WashingMachineState traiteMessage(char* message){ WashingMachineState traiteMessage(char* message){
@ -25,6 +27,15 @@ WashingMachineState traiteMessage(char* message){
wms.depuis = timestamp; wms.depuis = timestamp;
wms.ack = ack; wms.ack = ack;
if(wms.etat==LAVEUSE_LAVAGE){
stateOn=true;
}
if(wms.etat==LAVEUSE_ARRET && stateOn){
//Fin détectée !
stateOn=false;
send_event(EVT_FIN_MACHINE, NULL);
}
cJSON_Delete(root); cJSON_Delete(root);
return wms; return wms;
@ -43,6 +54,29 @@ WashingMachineState getEtatMachine(){
return wms; return wms;
} }
char *duree_depuis_timestamp_formatee(time_t timestamp)
{
time_t maintenant = time(NULL);
long diff_minutes = (maintenant - timestamp) / 60;
if (diff_minutes < 0)
diff_minutes = 0; // sécurité si timestamp futur
char *resultat = malloc(32);
if (!resultat)
return NULL;
if (diff_minutes < 60) {
snprintf(resultat, 32, "%ldmn", diff_minutes);
} else {
long heures = diff_minutes / 60;
long minutes = diff_minutes % 60;
snprintf(resultat, 32, "%ldh%02ld", heures, minutes);
}
return resultat;
}
void getEtatMachineStr(WashingMachineState wms, char* etat, size_t etatSize) void getEtatMachineStr(WashingMachineState wms, char* etat, size_t etatSize)
{ {
char* etatStr; char* etatStr;
@ -62,10 +96,22 @@ void getEtatMachineStr(WashingMachineState wms, char* etat, size_t etatSize)
etatStr="Etat inconnu"; etatStr="Etat inconnu";
break; break;
} }
char dateStr[30]; char dateStr[30];
timestampToDate(wms.depuis,dateStr,30); timestampToDate(wms.depuis,dateStr,30);
snprintf(etat,etatSize,"%s depuis %s", etatStr, dateStr); //Si la machine est en route on ajoute la durée en heures/minutes depuis le départ
if(wms.etat==LAVEUSE_LAVAGE){
char *duree = duree_depuis_timestamp_formatee(wms.depuis);
if (duree) {
printf("Durée : %s\n", duree);
snprintf(etat,etatSize,"%s depuis %s\n (%s)", etatStr, duree, dateStr);
free(duree);
}
}else{
snprintf(etat,etatSize,"%s depuis %s", etatStr, dateStr);
}
ESP_LOGE(TAG,"%s",etat); ESP_LOGE(TAG,"%s",etat);
} }

View File

@ -129,7 +129,7 @@ dependencies:
type: service type: service
version: 1.0.4 version: 1.0.4
espressif/esp_hosted: espressif/esp_hosted:
component_hash: 5e1f8af8b51b47714eafb30c59bac952d6abc03125c01cb6a970f368d1e1cb83 component_hash: 9eea9ce83444a412b4a02311f787f3639a5d29fe67e6df83863010dd68ab250b
dependencies: dependencies:
- name: idf - name: idf
require: private require: private
@ -137,7 +137,7 @@ dependencies:
source: source:
registry_url: https://components.espressif.com registry_url: https://components.espressif.com
type: service type: service
version: 2.11.7 version: 2.12.0
espressif/esp_ipa: espressif/esp_ipa:
component_hash: 31003e536f0d26158e10d7fcf2448b6377ce1148518287d0f34ed3b6c942c6d8 component_hash: 31003e536f0d26158e10d7fcf2448b6377ce1148518287d0f34ed3b6c942c6d8
dependencies: dependencies:
@ -217,7 +217,7 @@ dependencies:
type: service type: service
version: 1.2.0~1 version: 1.2.0~1
espressif/esp_lvgl_port: espressif/esp_lvgl_port:
component_hash: 88bbda87376ae20fabfbb5d794ed78d23b3b4a186ecfafecf2edbf06223fd6c9 component_hash: b6360960f47b6776462e7092861b3ea66477ffb762a01baa0aecbb3d74cd50f4
dependencies: dependencies:
- name: idf - name: idf
require: private require: private
@ -229,7 +229,7 @@ dependencies:
source: source:
registry_url: https://components.espressif.com/ registry_url: https://components.espressif.com/
type: service type: service
version: 2.7.1 version: 2.7.2
espressif/esp_sccb_intf: espressif/esp_sccb_intf:
component_hash: c071b189e49f40940722aea01a5489f873385cc39cd5b14012341135b85d1a9d component_hash: c071b189e49f40940722aea01a5489f873385cc39cd5b14012341135b85d1a9d
dependencies: dependencies:
@ -351,12 +351,12 @@ dependencies:
type: service type: service
version: 1.20.4 version: 1.20.4
lvgl/lvgl: lvgl/lvgl:
component_hash: 17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f component_hash: 184e532558c1c45fefed631f3e235423d22582aafb4630f3e8885c35281a49ae
dependencies: [] dependencies: []
source: source:
registry_url: https://components.espressif.com registry_url: https://components.espressif.com
type: service type: service
version: 9.4.0 version: 9.5.0
suda-morris/am2302_rmt: suda-morris/am2302_rmt:
component_hash: 890df8ebfec652eb9f8e1d612959f00a951dbe9241335e5e335fc7fb1468ea32 component_hash: 890df8ebfec652eb9f8e1d612959f00a951dbe9241335e5e335fc7fb1468ea32
dependencies: dependencies:

View File

@ -5,12 +5,13 @@ set(comps heap nvs_flash esp_netif image_downloader fatfs protocol_examples_comm
if(${IDF_TARGET} STREQUAL "esp32p4") if(${IDF_TARGET} STREQUAL "esp32p4")
message(STATUS "SIMULATION_QEMU = OOF --> main standard") message(STATUS "SIMULATION_QEMU = OOF --> main standard")
list(APPEND comps esp32_p4_function_ev_board sdmmc vfs littlefs app_update esp_https_ota espcoredump esp_http_server esp_wifi ) list(APPEND comps esp32_p4_function_ev_board sdmmc vfs littlefs app_update esp_https_ota espcoredump esp_http_server esp_wifi)
idf_component_register(SRCS main.c communication.c idf_component_register(SRCS main.c communication.c
INCLUDE_DIRS "./include" INCLUDE_DIRS "./include"
REQUIRES ${comps} REQUIRES ${comps}
EMBED_TXTFILES ${PROJECT_DIR}/main/ca_cert.pem EMBED_TXTFILES ${PROJECT_DIR}/main/ca_cert.pem ${PROJECT_DIR}/../ota/certs/server.crt
EMBED_FILES "index.html") EMBED_FILES "index.html")
littlefs_create_partition_image(littlefs medias FLASH_IN_PROJECT)
elseif(${IDF_TARGET} STREQUAL "linux") elseif(${IDF_TARGET} STREQUAL "linux")
message(STATUS "Linux Mode --> main standard") message(STATUS "Linux Mode --> main standard")
list(APPEND comps vfs esp_http_server) list(APPEND comps vfs esp_http_server)

View File

@ -2,6 +2,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "mqtt_client.h" #include "mqtt_client.h"
#include "stateManagement.h" #include "stateManagement.h"
#include "eventsManager.h"
#if CONFIG_IDF_TARGET_ESP32P4 #if CONFIG_IDF_TARGET_ESP32P4
#include "esp_wifi.h" #include "esp_wifi.h"
#endif #endif
@ -183,8 +184,8 @@ void splitIt(char *payload, unsigned int length, float *datas)
mqtt_callback mqttcb; mqtt_callback mqttcb;
void mqtt_publish(const char *topic, const char *datas){ void mqtt_publish(const char *topic, const char *datas, bool retain){
esp_mqtt_client_publish(client, topic, datas, 0, 1, 0); esp_mqtt_client_publish(client, topic, datas, 0, 1, retain);
} }
/* /*
@ -238,6 +239,10 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
msg_id = esp_mqtt_client_subscribe(client, topicConsoElec, 0); msg_id = esp_mqtt_client_subscribe(client, topicConsoElec, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "devices/esp32p4_01/ota/update", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); //msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
//ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); //ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
@ -285,7 +290,13 @@ void mqtt_app_start(mqtt_callback callback, EventGroupHandle_t domotic_event_gro
mqttcb=callback; mqttcb=callback;
esp_mqtt_client_config_t mqtt_cfg = { esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://192.168.0.10", .broker.address.uri = "mqtt://192.168.0.10",
.network.timeout_ms = 1000}; .network.timeout_ms = 1000,
.session.keepalive=30,
.session.last_will.topic="esp32p4_domotic/binary_sensor/online/state",
.session.last_will.msg = "offline",
.session.last_will.qos = 1,
.session.last_will.retain = 1
};
#if CONFIG_BROKER_URL_FROM_STDIN #if CONFIG_BROKER_URL_FROM_STDIN
char line[128]; char line[128];

View File

@ -16,14 +16,6 @@ typedef void (*wifi_callback)(wifi_evt evt);
typedef void (*mqtt_callback)(mqtt_evt evt, esp_mqtt_event_handle_t evt_data); typedef void (*mqtt_callback)(mqtt_evt evt, esp_mqtt_event_handle_t evt_data);
void wifi_init_sta(wifi_callback cb); void wifi_init_sta(wifi_callback cb);
void mqtt_app_start(mqtt_callback cb, EventGroupHandle_t evtGroup); void mqtt_app_start(mqtt_callback cb, EventGroupHandle_t evtGroup);
void mqtt_publish(const char *topic, const char *datas); void mqtt_publish(const char *topic, const char *datas, bool retain);
#define topicTempExt "house/temp/282A802600008059"
#define topicHauteurCuve "house/cuve/hauteur"
#define topicTempInt "house/temp/287DCF1E00008020"
#define topicHauteurCuveEvol "house/cuve/hauteurEvol"
#define topicConsoElec "energy/puissance_5mn"
#define topicEtatMachine "energy/machine_en_route"
#define topicdomoticCommand "domotic/cmd"
#define topicTest "test"

View File

@ -73,8 +73,8 @@
<h1>Developed by Mark</h1> <h1>Developed by Mark</h1>
<h2>How to save and Download crash dump</h2> <h2>How to save and Download crash dump</h2>
</br></br> </br></br>
<button class="btn success"><a href="http://192.168.4.1/download">Download</a></button></br></br> <button class="btn success"><a href="./download">Download</a></button></br></br>
<button class="btn success"><a href="http://192.168.4.1/crash">Crash</a></button> <button class="btn success"><a href="./crash">Crash</a></button>
</center> </center>
</body> </body>
</html> </html>

View File

@ -20,10 +20,10 @@
#include "ihm_gateway.h" #include "ihm_gateway.h"
// OTA // OTA
/*#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#include "esp_http_client.h"
#include "esp_https_ota.h" #include "esp_https_ota.h"
*/ #include "esp_http_client.h"
// Includes personnels // Includes personnels
//#include "wifi_logger.h" //#include "wifi_logger.h"
#include "obtain_time.h" #include "obtain_time.h"
@ -31,13 +31,16 @@
#include "include/communication.h" #include "include/communication.h"
#include "stateManagement.h" #include "stateManagement.h"
//#include "driver/gpio.h" //#include "driver/gpio.h"
//#include "am2302_rmt.h"
#include "eventsManager.h" #include "eventsManager.h"
#include "esp_timer.h" #include "esp_timer.h"
#include <esp_task_wdt.h> #include <esp_task_wdt.h>
#if CONFIG_IDF_TARGET_ESP32P4
#include "am2302_rmt.h"
#include "esp_wifi.h"
#endif
// GPIO assignment // GPIO assignment
#define AM2302_GPIO 4 #define AM2302_GPIO 4
@ -104,8 +107,128 @@ void bh1750_init(void)
bh1750 = bh1750_create(I2C_MASTER_NUM, BH1750_I2C_ADDRESS_DEFAULT, bus_handle); bh1750 = bh1750_create(I2C_MASTER_NUM, BH1750_I2C_ADDRESS_DEFAULT, bus_handle);
*/ */
} }
TaskHandle_t ihm_task;
typedef struct {
char version[32];
char url[256];
char sha256[65];
bool force;
} ota_msg_t;
static QueueHandle_t ota_queue;
static const char *OTA_TOPIC = "devices/esp32p4_01/ota/update";
#include <cJSON.h>
bool parse_ota_json(const char *json, ota_msg_t *msg)
{
ESP_LOGE("OTA","On demande à parser : %s", json);
cJSON *root = cJSON_Parse(json);
if (!root) return false;
snprintf(msg->version, sizeof(msg->version),
"%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "version")));
snprintf(msg->url, sizeof(msg->url),
"%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "url")));
snprintf(msg->sha256, sizeof(msg->sha256),
"%s", cJSON_GetStringValue(cJSON_GetObjectItem(root, "sha256")));
msg->force = cJSON_IsTrue(cJSON_GetObjectItem(root, "force"));
cJSON_Delete(root);
return true;
}
extern const uint8_t server_cert_pem_start[] asm("_binary_server_crt_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_server_crt_end");
void ota_task(void *arg)
{
ota_msg_t msg;
while (1) {
if (xQueueReceive(ota_queue, &msg, portMAX_DELAY)) {
ESP_LOGI("OTA", "Starting OTA to %s", msg.version);
esp_http_client_config_t http_cfg = {
.url = msg.url,
.cert_pem = (const char *)server_cert_pem_start,
.timeout_ms = 15000,
.skip_cert_common_name_check = true,
};
esp_https_ota_config_t ota_cfg = {
.http_config = &http_cfg,
};
lv_obj_t *ota = lv_msgbox_create(lv_scr_act());
lv_msgbox_add_text(ota,"Mise à jour OTA en cours");
suspendIHM();
esp_err_t ret = esp_https_ota(&ota_cfg);
if (ret == ESP_OK) {
ESP_LOGI("OTA", "OTA successful, rebooting");
esp_restart();
} else {
ESP_LOGE("OTA", "OTA failed (%s)", esp_err_to_name(ret));
}
}
}
}
static bool parse_semver(const char *ver, int *maj, int *min, int *pat)
{
return sscanf(ver, "%d.%d.%d", maj, min, pat) == 3;
}
static bool is_dev_build(void)
{
const esp_app_desc_t *desc = esp_app_get_description();
return strchr(desc->version, '-') != NULL;
}
static const char *get_suffix(const char *ver)
{
const char *dash = strchr(ver, '-');
return dash ? dash + 1 : NULL;
}
bool is_new_version(const char *incoming)
{
int cur_maj, cur_min, cur_pat;
int new_maj, new_min, new_pat;
const esp_app_desc_t *desc = esp_app_get_description();
const char *current = desc->version;
if (!parse_semver(current, &cur_maj, &cur_min, &cur_pat) ||
!parse_semver(incoming, &new_maj, &new_min, &new_pat)) {
ESP_LOGW("OTA", "Invalid version format");
return true; // fail-open
}
// 1⃣ Upgrade semver classique
if (new_maj != cur_maj) return new_maj > cur_maj;
if (new_min != cur_min) return new_min > cur_min;
if (new_pat != cur_pat) return new_pat > cur_pat;
// 2⃣ Même X.Y.Z → comportement dépend du mode
if (is_dev_build()) {
const char *cur_suffix = get_suffix(current);
const char *new_suffix = get_suffix(incoming);
// si une des deux n'a pas de suffixe → contexte différent
if (!cur_suffix || !new_suffix) {
ESP_LOGI("OTA", "Dev mode: context change (suffix missing)");
return true;
}
// suffix différent → OTA
if (strcmp(cur_suffix, new_suffix) != 0) {
ESP_LOGI("OTA", "Dev mode: branch change (%s → %s)",
cur_suffix, new_suffix);
return true;
}
}
ESP_LOGI("OTA", "No OTA needed");
return false;
}
void mqtt_cb(mqtt_evt evt, esp_mqtt_event_handle_t event){ void mqtt_cb(mqtt_evt evt, esp_mqtt_event_handle_t event){
switch (evt) switch (evt)
{ {
@ -126,16 +249,37 @@ void mqtt_cb(mqtt_evt evt, esp_mqtt_event_handle_t event){
break; break;
case MQTT_DATA_RECEIVED: case MQTT_DATA_RECEIVED:
//lv_subject_set_int(&mqttStatus,2); //lv_subject_set_int(&mqttStatus,2);
ESP_LOGD(TAG, "\nMQTT_EVENT_DATA"); ESP_LOGE(TAG, "MQTT_EVENT_DATA");
ESP_LOGD(TAG, "TOPIC=%.*s\n", event->topic_len, event->topic); ESP_LOGE(TAG, "TOPIC=%.*s\n", event->topic_len, event->topic);
ESP_LOGD(TAG, "DATA=%.*s\n", event->data_len, event->data); ESP_LOGE(TAG, "DATA=%.*s\n", event->data_len, event->data);
char *topic = strndup(event->topic, event->topic_len); char *topic = strndup(event->topic, event->topic_len);
if (strcmp(topic, topicTempExt) == 0) if (strncmp(topic, OTA_TOPIC, event->topic_len ) == 0) {
ota_msg_t msg = {0};
// ⚠️ copie safe (topic/data pas null-terminated)
char payload[512] = {0};
memcpy(payload, event->data, event->data_len);
if (!parse_ota_json(payload, &msg)) {
ESP_LOGE("OTA", "Invalid OTA JSON");
return;
}
if (!is_new_version(msg.version) && !msg.force) {
ESP_LOGI("OTA", "Version already installed");
return;
}
ESP_LOGI("OTA", "OTA requested: %s", msg.version);
xQueueSend(ota_queue, &msg, 0); }
else if (strcmp(topic, topicTempExt) == 0)
{ {
//if(lvgl_port_lock(50)){ //if(lvgl_port_lock(50)){
float temp = strtof(event->data, NULL); float temp = strtof(event->data, NULL);
char buff[5]; char buff[5];
sprintf(buff,"%.1f",temp); sprintf(buff,"%.1f",temp);
send_event(EVT_TEMP_EXT, buff);
//lv_subject_copy_string(&tempExtSubj, buff); //lv_subject_copy_string(&tempExtSubj, buff);
//lvgl_port_unlock(); //lvgl_port_unlock();
@ -294,7 +438,7 @@ extern char *days[7];
extern char *months[12]; extern char *months[12];
/* esp_err_t _ota_http_event_handler(esp_http_client_event_t *evt) esp_err_t _ota_http_event_handler(esp_http_client_event_t *evt)
{ {
switch (evt->event_id) { switch (evt->event_id) {
case HTTP_EVENT_ERROR: case HTTP_EVENT_ERROR:
@ -324,11 +468,10 @@ extern char *months[12];
} }
return ESP_OK; return ESP_OK;
} }
*/
extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); 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"); extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
/* static esp_err_t validate_image_header(esp_app_desc_t *new_app_info) static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
{ {
if (new_app_info == NULL) { if (new_app_info == NULL) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
@ -349,12 +492,11 @@ extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
return ESP_OK; return ESP_OK;
} }
*/
void simple_ota_example_task(void *pvParameter) void simple_ota_example_task(void *pvParameter)
{ {
/* ESP_LOGE(TAG,"En attente connexion wifi"); ESP_LOGE(TAG,"En attente connexion wifi");
// Waiting until either the connection is established (WIFI_CONNECTED_BIT). // Waiting until either the connection is established (WIFI_CONNECTED_BIT).
EventBits_t bits = xEventGroupWaitBits(domotic_event_group, EventBits_t bits = xEventGroupWaitBits(domotic_event_group,
BIT0, BIT0,
@ -378,8 +520,8 @@ void simple_ota_example_task(void *pvParameter)
esp_http_client_config_t config = { esp_http_client_config_t config = {
.url = "https://192.168.0.28:8070/rgb_lcd.bin", .url = "https://192.168.0.28:8070/rgb_lcd.bin",
.timeout_ms = 30000, .timeout_ms = 30000,
.buffer_size = 20000, .buffer_size = 6144,
.buffer_size_tx = 20000, //TX Buffer, Main Buffer .buffer_size_tx = 6144, //TX Buffer, Main Buffer
.event_handler = _ota_http_event_handler, .event_handler = _ota_http_event_handler,
.keep_alive_enable = true, .keep_alive_enable = true,
.cert_pem = (char *)server_cert_pem_start, .cert_pem = (char *)server_cert_pem_start,
@ -480,13 +622,14 @@ ota_end:
ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed"); ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed");
vTaskDelete(NULL); vTaskDelete(NULL);
} }
*/} }
//am2302_handle_t sensor = NULL; #if CONFIG_IDF_TARGET_ESP32P4
am2302_handle_t sensor = NULL;
void readTempHumid(void *pvParameter) void readTempHumid(void *pvParameter)
{ {
/* float temperature = 0; float temperature = 0;
float humidity = 0; float humidity = 0;
while (1) while (1)
{ {
@ -494,16 +637,30 @@ void readTempHumid(void *pvParameter)
char buff[40]; char buff[40];
ESP_LOGI(TAG, "Temperature: %.1f °C, Humidity: %.1f %%", temperature, humidity); ESP_LOGI(TAG, "Temperature: %.1f °C, Humidity: %.1f %%", temperature, humidity);
sprintf(buff,"%.1f °C, %.1f %%", temperature, humidity); sprintf(buff,"%.1f °C, %.1f %%", temperature, humidity);
xIHMEvent_t m = { send_event(EVT_TEMP_INT, buff);
.eEventType = IHM_EVT_HUMID_TEMP,
.pvData = buff
};
//xQueueSendToFront(ihm_queue,&m,5);
vTaskDelay(60000 / portTICK_PERIOD_MS); vTaskDelay(60000 / portTICK_PERIOD_MS);
}
}
#include "esp_littlefs.h"
void littlefs_mount(void)
{
esp_vfs_littlefs_conf_t conf = {
.base_path = "/littlefs",
.partition_label = "littlefs", // ← DOIT matcher partitions.csv
.format_if_mount_failed = false
};
esp_err_t ret = esp_vfs_littlefs_register(&conf);
if (ret != ESP_OK) {
printf("LittleFS mount failed: %s\n", esp_err_to_name(ret));
} else {
printf("LittleFS mounted at /littlefs\n");
} }
*/
} }
#endif
void alloc_fail(size_t size, uint32_t caps, const char * function_name){ void alloc_fail(size_t size, uint32_t caps, const char * function_name){
ESP_LOGE(TAG,"fail alloc %u in %" PRIu32 " in %s", size,caps,function_name); ESP_LOGE(TAG,"fail alloc %u in %" PRIu32 " in %s", size,caps,function_name);
@ -711,9 +868,9 @@ extern lv_subject_t forecastH2Subj;
extern lv_subject_t forecastH3Subj; extern lv_subject_t forecastH3Subj;
extern lv_subject_t meteoStatus; extern lv_subject_t meteoStatus;
void weather_data_retreived(struct meteodailyforecast_data dailyDatas[3], struct meteoforecast_data datas[3]) void weather_data_retreived(meteo_event_payload_t *datas)
{ {
send_event(EVT_METEO_RECUE, datas);
/* ESP_LOGE(TAG, "debut debug"); /* ESP_LOGE(TAG, "debut debug");
printf("%lld\n", datas[0].datetime); printf("%lld\n", datas[0].datetime);
printf("%s\n", datas[0].previsions.desc); printf("%s\n", datas[0].previsions.desc);
@ -728,22 +885,6 @@ void weather_data_retreived(struct meteodailyforecast_data dailyDatas[3], struct
*/ */
//if (display_lock("weather_data_retreived")) //if (display_lock("weather_data_retreived"))
//{ //{
ESP_LOGV("MeteoFrance", "------------------------------------- Set des subjects J --------------------------------");
// Prévisions des 3 prochains jours
//lv_subject_set_pointer(&forecastD1Subj, &dailyDatas[0]);
//lv_subject_set_pointer(&forecastD2Subj, &dailyDatas[1]);
//lv_subject_set_pointer(&forecastD3Subj, &dailyDatas[2]);
ESP_LOGV("MeteoFrance", "------------------------------------- Set des subjects H--------------------------------");
// Prévisions des 3 prochains jours
ESP_LOGV("MeteoFrance", "Pointeur %lli", datas[0].datetime);
//lv_subject_set_pointer(&forecastH1Subj, &datas[0]);
//lv_subject_set_pointer(&forecastH2Subj, &datas[1]);
// lv_subject_set_pointer(&forecastH3Subj, &datas[2]);
//lv_subject_set_int(&meteoStatus, 0);
//display_unlock("weather_data_retreived");
ESP_LOGV(TAG, "------------------------------------- Fin Set des subjects --------------------------------");
//}else{ //}else{
//ESP_LOGE(TAG, "Impossible d'obtenir le mutex dans weather_data_retreived"); //ESP_LOGE(TAG, "Impossible d'obtenir le mutex dans weather_data_retreived");
//} //}
@ -870,16 +1011,34 @@ void lightSensorTask(void *pvParameter){
*/ */
} }
static void heartbeat_task(void *arg)
{
const char *topic = "esp32p4_domotic/binary_sensor/online/state";
while (1) {
mqtt_publish(
topic,
"online",
true);
vTaskDelay(pdMS_TO_TICKS(30000)); // 30 s
}
}
#define BUILD_TIME __DATE__ " " __TIME__
//#include "audio.h"
void app_main(void) void app_main(void)
{ {
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
tzset();
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
ihm_gateway_init(); ihm_gateway_init();
startEvtManager(); startEvtManager();
boucleMeteo();
#if CONFIG_IDF_TARGET_LINUX #if CONFIG_IDF_TARGET_LINUX
// en mode linux on simule l'obtention de la connexion wifi // en mode linux on simule l'obtention de la connexion wifi
xEventGroupSetBits(domotic_event_group, WIFI_CONNECTED_BIT); xEventGroupSetBits(domotic_event_group, WIFI_CONNECTED_BIT);
@ -887,13 +1046,25 @@ void app_main(void)
//drawIhm(getIHMQueueHandle()); //drawIhm(getIHMQueueHandle());
#else #else
xTaskCreate(&drawIhm,"ihm_task",10000,getIHMQueueHandle(),10,NULL); littlefs_mount();
xTaskCreate(&drawIhm,"ihm_task",10000,getIHMQueueHandle(),3,&ihm_task);
//et sinon on se connecte //et sinon on se connecte
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
wifi_init_sta(wifi_cb); wifi_init_sta(wifi_cb);
//start_wifi_logger(); //start_wifi_logger();
/* 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);
#endif #endif
boucleMeteo();
ota_queue = xQueueCreate(1, sizeof(ota_msg_t));
xTaskCreate(ota_task,"ota_task",8192,NULL,5,NULL);
mqtt_app_start(mqtt_cb, domotic_event_group); mqtt_app_start(mqtt_cb, domotic_event_group);
TaskHandle_t xHandle = NULL; TaskHandle_t xHandle = NULL;
@ -904,6 +1075,30 @@ void app_main(void)
ESP_LOGE(TAG, "Impossiblke de creer la tache imageDownload_task %i", ret1); ESP_LOGE(TAG, "Impossiblke de creer la tache imageDownload_task %i", ret1);
}*/ }*/
#if CONFIG_IDF_TARGET_ESP32P4
//playSound();
//send_event(EVT_FIN_MACHINE,NULL);
// Configuration de la sonde Temp/Humid.
am2302_config_t am2302_config = {
.gpio_num = AM2302_GPIO,
};
am2302_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT,
};
ESP_ERROR_CHECK(am2302_new_sensor_rmt(&am2302_config, &rmt_config, &sensor));
xTaskCreate(&readTempHumid, "read_temp_task", 8192, NULL, 5, NULL);
#endif
esp_ota_mark_app_valid_cancel_rollback();
esp_app_desc_t *appDesc = esp_app_get_description();
char buff[300];
snprintf(buff,300,"%s %s %s", BUILD_TIME, appDesc->version, appDesc->idf_ver);
mqtt_publish("esp32p4_domotic/sensor/firmware/state",buff, true);
xTaskCreate(heartbeat_task, "heartbeat_task", 4096, NULL, 5, NULL);
start_webserver();
} }
void boucleMeteo() void boucleMeteo()
@ -1030,14 +1225,5 @@ void app_main1(void)
start_webserver(); start_webserver();
/* // Configuration de la sonde Temp/Humid.
am2302_config_t am2302_config = {
.gpio_num = AM2302_GPIO,
};
am2302_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT,
};
ESP_ERROR_CHECK(am2302_new_sensor_rmt(&am2302_config, &rmt_config, &sensor));
xTaskCreate(&readTempHumid, "read_temp_task", 8192, NULL, 5, NULL);
*/
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,10 +1,10 @@
# ESP-IDF Partition Table # ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,,0x6000,, nvs,data,nvs,,0x6000,
otadata,data,ota,,0x2000,, otadata,data,ota,,0x2000,
phy_init,data,phy,,0x1000,, phy_init,data,phy,,0x1000,
factory,app,factory,,3M,, factory,app,factory,,3M,
ota_0,app,ota_0,,3M,, ota_0,app,ota_0,,3M,
ota_1,app,ota_1,,3M,, ota_1,app,ota_1,,3M,
littlefs,data,littlefs,,1M,, littlefs,data,littlefs,,3M,
coredump, data, coredump,,64K,, coredump,data,coredump,,64K,

1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs,data,nvs,,0x6000,, nvs,data,nvs,,0x6000,
4 otadata,data,ota,,0x2000,, otadata,data,ota,,0x2000,
5 phy_init,data,phy,,0x1000,, phy_init,data,phy,,0x1000,
6 factory,app,factory,,3M,, factory,app,factory,,3M,
7 ota_0,app,ota_0,,3M,, ota_0,app,ota_0,,3M,
8 ota_1,app,ota_1,,3M,, ota_1,app,ota_1,,3M,
9 littlefs,data,littlefs,,1M,, littlefs,data,littlefs,,3M,
10 coredump, data, coredump,,64K,, coredump,data,coredump,,64K,

Some files were not shown because too many files have changed in this diff Show More