Compare commits

..

45 Commits
main ... qemu

Author SHA1 Message Date
d505c2fa97 nettoyage 2026-02-15 23:26:41 +01:00
c3f0c148ba work on host and device 2026-02-15 17:43:06 +01:00
58378ea2cf omit bad defaults 2026-02-15 17:26:56 +01:00
2464d13196 suppr lvgl comps 2026-02-13 19:15:49 +01:00
a3d0fa3d25 refactor 2026-02-07 08:26:31 +01:00
43b32b8b68 on deplace l'ihm dans domotic_display 2026-02-07 08:24:56 +01:00
689d51b463 plus propre 2026-02-06 19:05:17 +01:00
dfbd28861e menage 2026-02-06 18:41:04 +01:00
ba266479dd work on pc from main ! 2026-02-06 18:39:36 +01:00
93bffe925f ok on host 2026-02-01 16:01:18 +01:00
Marc PASTEUR
c7b46b5bfe chgt ui 2025-12-31 08:48:02 +01:00
Marc PASTEUR
169b8d62b1 add chars and symbols to fonts 2025-12-19 18:09:00 +01:00
Marc PASTEUR
d132f39ff8 move lvgl 2025-12-19 18:08:19 +01:00
Marc PASTEUR
7e24eaa207 fix float 2025-12-16 07:03:37 +01:00
Marc PASTEUR
8b78cb0a25 enable float ? 2025-12-16 07:01:22 +01:00
Marc PASTEUR
7ff8979051 refonte ihm 2025-12-16 07:01:03 +01:00
Marc PASTEUR
77953a3397 test datas 2025-12-16 07:00:36 +01:00
Marc PASTEUR
48aab82046 change tag 2025-12-16 07:00:23 +01:00
Marc PASTEUR
896aefde48 evtManager --> send evt 2025-12-16 06:59:51 +01:00
Marc PASTEUR
84bec90407 degradé et nb couleurs 2025-12-15 11:16:00 +01:00
Marc PASTEUR
bf85c544f5 fonctionne qemu + linux host 2025-12-15 07:05:50 +01:00
Marc PASTEUR
e55b74b0a2 readme 2025-12-11 19:06:14 +01:00
Marc PASTEUR
88c3c93ae8 work in qemu 2025-12-11 18:51:22 +01:00
Marc PASTEUR
c81027e8e8 add bsd 2025-11-18 06:45:38 +01:00
ab2399ce50 heure ! 2025-11-17 22:31:09 +01:00
27c2376717 set display 2025-11-17 20:39:38 +01:00
829dcfc285 cards 2025-11-16 21:03:18 +01:00
4abbf3abea add custom task 2025-11-16 14:56:08 +01:00
3aeeff52eb gitignore 2025-11-16 14:29:14 +01:00
b232a0d8e1 new defaults ! 2025-11-16 14:27:39 +01:00
ad170a8aa7 work with themes 2025-11-16 14:25:08 +01:00
ef55ef2519 path to double run 2025-11-16 11:40:01 +01:00
430f1c90fd work without theme 2025-11-15 19:47:07 +01:00
1fea5e284d ihm test work 2025-11-15 14:10:40 +01:00
1375e82550 ... 2025-10-31 14:42:33 +01:00
2beca08042 add bh1750 2025-09-17 22:24:26 +02:00
a543836df4 nettoyage 2025-09-05 17:48:54 +02:00
4aa0daf463 desctive perf mon 2025-09-05 17:46:38 +02:00
72a58b373d passage meteofrance https 2025-09-05 17:45:15 +02:00
16b277ff99 ajout capteur luminosite 2025-09-05 17:44:59 +02:00
7715f8b153 suppression (temporaire ?) plans volets 2025-09-05 17:43:13 +02:00
20e04e0de2 gdb 2025-08-02 19:56:15 +02:00
dba5b974c8 reconnect mqtt if disconnect 2025-05-23 13:02:37 +02:00
4ad7177c9f mise en place composant 2025-05-21 20:56:47 +02:00
555a6c6b6a lecture etat machine 2025-05-21 12:31:20 +02:00
105 changed files with 547 additions and 1957 deletions

View File

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

2
.vscode/launch.json vendored
View File

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

View File

@ -7,12 +7,13 @@
"idf.customExtraVars": {
"OPENOCD_SCRIPTS": "/home/marc/.espressif/tools/openocd-esp32/v0.12.0-esp32-20251215/openocd-esp32/share/openocd/scripts",
"ESP_ROM_ELF_DIR": "/home/marc/.espressif/tools/esp-rom-elfs/20240305/",
"IDF_TARGET": "esp32p4"
"IDF_TARGET": "linux"
},
"idf.gitPath": "git",
"idf.adapterTargetName": "esp32s3",
"idf.openOcdConfigs": [
"board/esp32p4-builtin.cfg"
"interface/ftdi/esp_ftdi.cfg",
"target/esp32.cfg"
],
"idf.flashType": "UART",
"idf.port": "/dev/ttyUSB0",

View File

@ -1,54 +1,3 @@
# --------------------------------------------------
# 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)
option(SIMULATION_QEMU "Build for QEMU simulation" OFF)
message(STATUS "ROOT:: SIMULATION_QEMU = ${SIMULATION_QEMU}")
@ -84,7 +33,7 @@ endif()
#list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/esp_timer")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(domotic)
project(rgb_lcd)
# -------------------------------------------------
@ -112,44 +61,3 @@ else()
add_link_options(-fsanitize=address)
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

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

View File

@ -1,224 +0,0 @@
#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

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

View File

@ -19,7 +19,7 @@ make_font(Super_Malibu super_malibu 80)
#execute_process(COMMAND podman run -v /home/marc/rgb_lcd/components/domotic_display/fonts:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 72 --no-compress --font Roboto-Medium.ttf --symbols "0123456789.°àéèûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz %,'():ê/-" --format lvgl -o roboto_medium_72.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575)
SET(comps meteofrance eventsManager lvgl RemindMe washingMachineState)
SET(comps meteofrance eventsManager lvgl RemindMe)
if(${IDF_TARGET} STREQUAL "esp32p4" OR ${IDF_TARGET} STREQUAL "esp32s3")
#esp32_p4_function_ev_board
idf_component_register(SRC_DIRS . fonts
@ -32,6 +32,7 @@ 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_ko.png" "images/" "ARGB8888" "NONE")
lvgl_port_add_images(${COMPONENT_LIB} "images/")
#littlefs_create_partition_image(littlefs images_meteo FLASH_IN_PROJECT)
elseif(${IDF_TARGET} STREQUAL "linux")
idf_component_register(SRC_DIRS . fonts images
INCLUDE_DIRS "include"

View File

@ -36,10 +36,9 @@ LV_IMAGE_DECLARE(mqtt_ok);
LV_IMAGE_DECLARE(mqtt_ko);
lv_subject_t dateHeureSubj;
lv_obj_t *lblTempInt;
lv_obj_t *lblTempExt;
lv_obj_t *lblTempInt2;
char tempExtStr[6];
char tempIntStr[50];
char tempIntStr[6];
char hauteurCuveStr[9];
char hauteurCuveEvolStr[9];
lv_subject_t tempIntSubj;
@ -49,7 +48,7 @@ lv_subject_t hauteurCuveEvolSubj;
lv_subject_t forecastD1Subj;
lv_subject_t forecastD2Subj;
lv_subject_t forecastD3Subj;
lv_subject_t *tmpDSubj[3] = {&forecastD1Subj, &forecastD2Subj, &forecastD3Subj};
lv_subject_t *tmpSubj[3] = {&forecastD1Subj, &forecastD2Subj, &forecastD3Subj};
lv_subject_t forecastH1Subj;
lv_subject_t forecastH2Subj;
lv_subject_t forecastH3Subj;
@ -110,36 +109,11 @@ 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){
//if(display_lock("draw_temp")){
ESP_LOGE(TAG, "draw_temp : %s", tempHumid);
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");
//}
if(display_lock("draw_temp")){
lv_label_set_text(lblTempInt2,tempHumid);
display_unlock("draw_temp");
}
}
lv_obj_t* myChart;
@ -149,7 +123,6 @@ lv_obj_t* lblEtatMachine;
static lv_style_t style_lbvValue;
static lv_style_t style_btn;
/*
lv_theme_t *lv_theme_create(void)
{
lv_theme_t *theme = lv_zalloc(sizeof(*theme));
@ -166,7 +139,6 @@ void lv_theme_copy(lv_theme_t *dst, const lv_theme_t *src)
}
lv_memcpy(dst, src, sizeof(*src));
}
*/
static void create_ui(void*)
{
// Initialisation du thème
@ -179,7 +151,6 @@ static void create_ui(void*)
// Création des écrans / widgets
app_main_display(); // ton écran principal
initHome(); // écran Home
drawHome(); // écran Home
// chart, labels, boutons, etc.
// par exemple : lblEtatMachine, lblHauteurCuve, myChart, ser...
@ -191,13 +162,6 @@ static void create_ui(void*)
#include <unistd.h> // usleep
#include "platform_detect.h"
bool suspended;
void suspendIHM(){
suspended=true;
#if CONFIG_IDF_TARGET_ESP32P4
lvgl_port_stop();
#endif
}
void drawIhm(void *param) {
// Init display + LVGL
init_display_ihm();
@ -212,14 +176,8 @@ void drawIhm(void *param) {
// Loop unifiée
while (1) {
if(!suspended){
ihm_gateway_process_queue();
#if CONFIG_IDF_TARGET_LINUX
uint32_t idle_time = lv_timer_handler();
#endif
}else{
vTaskDelay(500 / portTICK_PERIOD_MS);
}
//uint32_t idle_time = lv_timer_handler();
// ESP32 : task FreeRTOS
//vTaskDelay(500 / portTICK_PERIOD_MS);
@ -259,8 +217,6 @@ static void event_handler(lv_event_t *e)
static lv_indev_t *keyboard;
#endif
struct tm timeinfo;
void init_display_ihm(){
#if CONFIG_IDF_TARGET_LINUX
@ -272,14 +228,13 @@ void init_display_ihm(){
keyboard = lv_sdl_keyboard_create();
#else
lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
lvgl_cfg.task_priority=18;
lvgl_cfg.task_stack=12000;
lvgl_cfg.task_priority=4;
bsp_display_cfg_t cfg = {
.lvgl_port_cfg = lvgl_cfg,
.buffer_size = 1024*600,//BSP_LCD_DRAW_BUFF_SIZE,
.double_buffer = 1,
.hw_cfg = {
.dsi_bus.lane_bit_rate_mbps= BSP_LCD_MIPI_DSI_LANE_BITRATE_MBPS
.dsi_bus.lane_bit_rate_mbps= 1000
},
.flags = {
.buff_dma = false,
@ -288,8 +243,8 @@ void init_display_ihm(){
}
};
ESP_LOGE(TAG,"On demarre le display");
//lv_display_t *dsp = bsp_display_start();
lv_display_t *dsp = bsp_display_start_with_config(&cfg);
lv_display_t *dsp = bsp_display_start();
//lv_display_t *dsp = bsp_display_start_with_config(&cfg);
/*bsp_display_lock(0);
bsp_display_rotate(dsp,LV_DISP_ROTATION_90);
@ -304,6 +259,7 @@ void init_display_ihm(){
mainState.display_init=true;
time_t now;
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
@ -369,9 +325,10 @@ void app_main_display()
struct meteodailyforecast_data d;
struct dailyforecast_prev p={.desc="", .max=31, .min=12};
struct dailyforecast_prev p;
lv_strcpy(p.desc, "");
d.previsions = p;
d.isValid=true;
d.isValid=false;
ESP_LOGI(TAG, "Init forecastD1Subj");
lv_subject_init_pointer(&forecastD1Subj, &d);
@ -445,8 +402,7 @@ void app_main_display()
// lv_label_bind_text(mqtt, &mqttStatus, "Mqtt %d");
lv_obj_t *scr = lv_scr_act();
//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);
lv_obj_add_style(scr, &style_gradient, 0);
/* Your LVGL objects code here .... */
@ -523,14 +479,13 @@ static lv_style_t style_container;
// Callback pour mettre à jour une météo journaliere
// On pointe sur un tableau de meteodailyforecast_data
static void weatherdataJour_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
static void weatherdata_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{
// Retrieve weatherdata
const struct meteodailyforecast_data *data = subject->value.pointer;
bool isMinimal = observer->user_data;
ESP_LOGI(TAG, "CB meteo jour declenché. Meteo valide : %d - Mode minimal : %d", data->isValid, isMinimal);
ESP_LOGI(TAG, "CB meteo jour declenché. Meteo valide : %b - Mode minimal : %d", data->isValid, isMinimal);
if(!data->isValid){
ESP_LOGI(TAG,"Données meteo non valides");
return;
@ -540,9 +495,9 @@ static void weatherdataJour_obs_cb(lv_observer_t *observer, lv_subject_t *subjec
{
char buff[40] = {};
snprintf(buff,sizeof(buff),"%s %.1f %.1f", data->previsions.desc, data->previsions.min, data->previsions.max);
ESP_LOGI(TAG, "meteo jour declenché. Meteo valide : %s", buff);
ESP_LOGI(TAG, "CB meteo jour declenché. Meteo valide : %s", buff);
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));
if(parent!=NULL){
if(isMinimal){
@ -567,57 +522,34 @@ static void weatherdataJour_obs_cb(lv_observer_t *observer, lv_subject_t *subjec
}
}
}
//free(data);
}
}
// Callback pour mettre à jour une météo horaire
// On pointe sur un tableau de meteoforecast_data
static void weatherdataHeure_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
static void weatherdataH_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{
ESP_LOGV("MeteoFrance", "CB meteo horaire declenché");
// Retrieve weatherdata
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){
//printffd(data);
char buff[40] = {};
snprintf(buff,sizeof(buff),"%.1f", data->previsions.value);
//ESP_LOGE(TAG, "On a recu %s - [%s] - %s", data->type, buff, data->previsions.icon);
ESP_LOGV(TAG, "On a recu [%s]", buff);
if(isMinimal){
lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer));
//lv_obj_dump_tree(parent);
lv_obj_t *timefld = lv_obj_get_child(parent, 0);
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);
}else{
lv_obj_t *parent = (lv_obj_t *)(lv_observer_get_target(observer));
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);
char buffer[80];
dtHToString(data->datetime, buffer);
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{
ESP_LOGE(TAG, "Pas de odnnées valides");
@ -628,17 +560,14 @@ static void weatherdataHeure_obs_cb(lv_observer_t *observer, lv_subject_t *subje
void showMeteoIcon(const char *icon, lv_obj_t *desc_icon, int childNr)
{
lv_obj_t *img = lv_obj_get_child(desc_icon, childNr);
#if CONFIG_IDF_TARGET_LINUX
char *str1 = "A:/home/marc/esp/domotic/domotic/components/domotic_display/images_meteo/";
#else
char *str1 = "A:/littlefs/images_meteo/";
#endif
//char *str1 = "A:/littlefs/";
char *str1 = "A:/home/marc/domotic/components/domotic_display/images_meteo";
int sizeOfStr;
sizeOfStr = strlen(str1) + strlen(icon) + 6;
char *result = malloc(sizeOfStr);
snprintf(result,sizeOfStr, "%s%s.png", str1, icon);
ESP_LOGV(TAG,"On affiche l'image %s", result);
lv_image_set_src(img, result);
lv_image_set_src(img, "A:/home/marc/esp/domotic/domotic/components/domotic_display/images_meteo/p4j.png");
free(result);
}
@ -648,6 +577,7 @@ static lv_style_t tempStyle;
static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool minimal)
{
if (minimal)
{
//lv_obj_set_flex_flow(sup, LV_FLEX_FLOW_COLUMN);
@ -656,7 +586,6 @@ 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_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_set_align(container, LV_ALIGN_CENTER);
lv_obj_set_name(container, "container_meteo");
@ -699,7 +628,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
bool isMinimal = true;
lv_subject_add_observer_obj(tmpDSubj[dayNr], weatherdataJour_obs_cb, parent, &isMinimal);
lv_subject_add_observer_obj(tmpSubj[dayNr], weatherdata_obs_cb, parent, &isMinimal);
}
else
{
@ -757,15 +686,15 @@ static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool min
lv_label_set_text(max, "--");
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_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_label_set_text(min, "--");
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_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
lv_subject_add_observer_obj(tmpDSubj[dayNr], weatherdataJour_obs_cb, sup, NULL);
lv_subject_add_observer_obj(tmpSubj[dayNr], weatherdata_obs_cb, sup, NULL);
}
//return container;
@ -774,76 +703,9 @@ static void weatherDay_fragment_create_obj(int dayNr, lv_obj_t *parent, bool min
static lv_style_t tempStyle;
// 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, bool minimal)
static lv_obj_t* weatherH_fragment_create_obj(int horaireNr, lv_obj_t *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);
@ -886,9 +748,8 @@ static lv_obj_t* weatherH_fragment_create_obj(int horaireNr, lv_obj_t *parent, b
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
//ESP_LOGV(TAG, "on positionne obs sur horaire %d", horaireNr);
lv_subject_add_observer_obj(tmpHSubj[horaireNr], weatherdataHeure_obs_cb, sup, NULL);
}
ESP_LOGV(TAG, "on positionne obs sur horaire %d", horaireNr);
lv_subject_add_observer_obj(tmpHSubj[horaireNr], weatherdataH_obs_cb, sup, NULL);
return container;
}
@ -1060,7 +921,6 @@ static void cuve_click_cb(lv_event_t * e){
lv_tabview_set_active(tabview, 3, false);
}
/*
void draw_tabHome(lv_obj_t* parent){
lv_obj_t *supmain = parent;
lv_obj_set_flex_flow(supmain, LV_FLEX_FLOW_COLUMN);
@ -1072,7 +932,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_set_flex_flow(main, LV_FLEX_FLOW_ROW);
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_set_style_pad_all(cont_colTemp, 5, 0);
lv_obj_set_size(cont_colTemp, lv_pct(40), lv_pct(100));
@ -1080,7 +940,7 @@ void draw_tabHome(lv_obj_t* parent){
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);
//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_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);
@ -1089,7 +949,7 @@ void draw_tabHome(lv_obj_t* parent){
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);
// Conteneur Colonne: Meteo
/*Conteneur Colonne: Meteo*/
lv_obj_t *cont_col3 = lv_obj_create(main);
lv_obj_set_style_pad_all(cont_col3, 5, 0);
lv_obj_set_size(cont_col3, lv_pct(40), lv_pct(100));
@ -1116,7 +976,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_label_bind_text(lblTempExt, &tempExtSubj, "%s °C");
//Create a container with COLUMN flex direction
//
/*
lv_obj_t *cont_tempInt = lv_obj_create(cont_colTemp);
lv_obj_add_style(cont_tempInt, &style_container, 0);
// lv_obj_set_height(cont_tempInt,50);
@ -1127,7 +987,7 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_add_style(lblTempInt, &style_lbvValue, 0);
lv_label_set_text(lblTempInt, "");
lv_label_bind_text(lblTempInt, &tempIntSubj, "%s °C");
//
*/
//Create a container with COLUMN flex direction
lv_obj_t *cont_tempInt2 = lv_obj_create(cont_colTemp);
@ -1136,11 +996,11 @@ void draw_tabHome(lv_obj_t* parent){
lv_obj_set_flex_flow(cont_tempInt2, LV_FLEX_FLOW_ROW);
lv_obj_t * lblInt = lv_label_create(cont_tempInt2);
lv_label_set_text(lblInt, "int.");
//lblTempInt2 = lv_label_create(cont_tempInt2);
//lv_obj_add_style(lblTempInt2, &style_lbvValue, 0);
//lv_obj_set_style_text_font(lblTempInt2,lv_theme_get_font_large(lblTempInt2),0);
lblTempInt2 = lv_label_create(cont_tempInt2);
lv_obj_add_style(lblTempInt2, &style_lbvValue, 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
lv_obj_t *cont_Cuve = lv_obj_create(cont_colTemp);
@ -1175,9 +1035,9 @@ void draw_tabHome(lv_obj_t* parent){
lv_label_set_text(label, LV_SYMBOL_DOWN);
lv_obj_center(label);
weatherH_fragment_create_obj(0, cont_col3,false);
weatherH_fragment_create_obj(1, cont_col3,false);
weatherH_fragment_create_obj(2, cont_col3,false);
weatherH_fragment_create_obj(0, cont_col3);
weatherH_fragment_create_obj(1, cont_col3);
weatherH_fragment_create_obj(2, cont_col3);
}
void draw_tabCuve(lv_obj_t* parent)
@ -1186,8 +1046,15 @@ void draw_tabCuve(lv_obj_t* parent)
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)
{
@ -1229,7 +1096,7 @@ void draw_tabVolets(lv_obj_t* parent)
lv_obj_set_size(cont_btn_volets, lv_pct(15), lv_pct(100));
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};
lv_obj_set_grid_dsc_array(cont_btn_volets, column_dsc, row_dsc);
@ -1273,16 +1140,6 @@ 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 {
lv_obj_t *date_group;
lv_span_t *date_day;
@ -1306,47 +1163,69 @@ 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)
{
LV_UNUSED(observer);
lv_obj_t *parent = observer->target;
struct tm *timeStruct=lv_subject_get_pointer(subject);
lv_obj_t *dateTimeObj = lv_observer_get_target_obj(observer);
datetime_ctx_t *ctx = lv_obj_get_user_data(dateTimeObj);
if (!ctx) return;
lv_obj_t *day = lv_obj_find_by_name(parent, "day");
lv_obj_t *month = lv_obj_find_by_name(parent, "month");
struct tm *t = (struct tm *)lv_subject_get_pointer(subject);
if (!t) return;
ESP_LOGE(TAG,"%d %d %d %02d:%02d", t->tm_wday, t->tm_mday, t->tm_mon, t->tm_hour, t->tm_min);
lv_obj_t *hour = lv_obj_find_by_name(parent, "hour");
lv_obj_t *minute = lv_obj_find_by_name(parent, "minute");
char buf[4];
bool refresh_date = false;
bool refresh_time = false;
// ---- DATE ----
if (t->tm_mday != ctx->last_day) {
ctx->last_day = t->tm_mday;
u8_to_2digits(buf, t->tm_mday);
buf[2] = '/';
buf[3] = '\0';
ESP_LOGE(TAG,"Jour %s",buf);
lv_span_set_text(ctx->date_day, buf);
refresh_date = true;
}
int d = timeStruct->tm_mday;
int monthVal = timeStruct->tm_mon;
int h = timeStruct->tm_hour;
int m = timeStruct->tm_min;
if ((t->tm_mon + 1) != ctx->last_month) {
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;
}
char buf[12];
if (refresh_date) {
lv_spangroup_refresh(ctx->date_group);
}
snprintf(buf, sizeof(buf), "%02d", d);
lv_label_set_text(day, buf);
// ---- TIME ----
if (t->tm_hour != ctx->last_hour) {
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;
}
snprintf(buf, sizeof(buf), "%02d", monthVal+1);
lv_label_set_text(month, buf);
if (t->tm_min != ctx->last_min) {
ctx->last_min = t->tm_min;
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;
}
snprintf(buf, sizeof(buf), "%02d", h);
lv_label_set_text(hour, buf);
if (refresh_time) {
lv_spangroup_refresh(ctx->time_group);
}
snprintf(buf, sizeof(buf), "%02d", m);
lv_label_set_text(minute, buf);
}
/* ------------------------------------------------------------ */
@ -1518,7 +1397,6 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_t *btnUp = lv_button_create(cont_colVolets);
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_event_cb(btnUp, event_handler, LV_EVENT_ALL, upEvent);
// lv_obj_align(btnUp, LV_ALIGN_CENTER, 0, -40);
@ -1533,7 +1411,6 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_name(btnDwn, "btnDown_#");
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_align(btnDwn, LV_ALIGN_CENTER, 0, -40);
lv_obj_remove_flag(btnDwn, LV_OBJ_FLAG_PRESS_LOCK);
@ -1546,57 +1423,15 @@ void messageCardContent(lv_obj_t *cont_messages)
{
// lv_obj_t *txt = lv_label_create(container);
// lv_label_set_text(txt, "Meteo");
weatherH_fragment_create_obj(0, container,true);
weatherH_fragment_create_obj(1, container,true);
weatherH_fragment_create_obj(2, container,true);
weatherDay_fragment_create_obj(0, container, true);
// lv_subject_add_observer_obj(&forecastD1Subj, weatherdata_obs_cb, container, NULL);
}
lv_obj_t *txtMinuteur;
void minuteurCardContent(lv_obj_t * container)
{
txtMinuteur = lv_label_create(container);
lv_label_set_long_mode(txtMinuteur, LV_LABEL_LONG_MODE_WRAP);
lv_label_set_text(txtMinuteur, "Rien à signaler !");
lv_obj_set_width(txtMinuteur, LV_PCT(100));
lv_obj_t *txt = lv_label_create(container);
lv_label_set_text(txt, "Rien à signaler !");
}
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)
{
ESP_LOGE(TAG, "We're here !!!!!!!!!!!!!!!!!!!!!!");
@ -1622,7 +1457,15 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
createBackBtn(meteoContainer);
lv_obj_t *back = lv_label_create(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_set_id(title, "titleMeteoLbl");
@ -1642,7 +1485,15 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
createBackBtn(meteoContainer);
lv_obj_t *back = lv_label_create(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_set_id(title, "titleMeteoLbl");
@ -1664,7 +1515,15 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
createBackBtn(meteoContainer);
lv_obj_t *back = lv_label_create(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_set_id(title, "titleMeteoLbl");
@ -1687,7 +1546,15 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_size(meteoContainer, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(meteoContainer, LV_FLEX_FLOW_COLUMN);
createBackBtn(meteoContainer);
lv_obj_t *back = lv_label_create(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_set_id(title, "titleMeteoLbl");
@ -1697,24 +1564,7 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_add_event_cb(title, backCb, LV_EVENT_CLICKED, NULL);
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)
@ -1723,7 +1573,6 @@ void messageCardContent(lv_obj_t *cont_messages)
}
void minuteurCb(lv_obj_t *base_obj)
{
send_event(EVT_FIN_MACHINE_STOP_NOTIF,NULL);
drawMinuteur(base_obj);
}
void voletsCb(lv_obj_t *base_obj)
@ -1753,29 +1602,21 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_user_data(dateTimeObj, ctx);
}
void initHome(){
void drawHome()
{
/*Initialize the styles*/
lv_style_init(&style_btn);
// 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_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(&tempIntSubj, tempIntStr, NULL, 50, "--");
lv_subject_init_string(&tempIntSubj, tempIntStr, NULL, 6, "--");
lv_subject_init_string(&hauteurCuveSubj, hauteurCuveStr, NULL, 9, "--");
lv_subject_init_string(&hauteurCuveEvolSubj, hauteurCuveEvolStr, NULL, 9, "--");
}
void drawHome()
{
// keys.clear();
lv_obj_clean(lv_scr_act());
@ -1790,6 +1631,9 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_style_pad_top(bg_cont, 5, 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 */
@ -1811,96 +1655,46 @@ void messageCardContent(lv_obj_t *cont_messages)
//lv_obj_remove_style_all(date_and_time);
lv_obj_set_size(date_and_time, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_t *date = lv_obj_create(date_and_time);
lv_obj_t *date = lv_spangroup_create(date_and_time);
lv_obj_set_name(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->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
lv_obj_t *day = lv_label_create(date);
lv_obj_set_name(day, "day");
lv_label_set_text(day, "--");
lv_obj_set_style_text_font(day, &super_malibu_80, 0);
lv_obj_set_style_text_color(day, lv_color_white(), 0);
lv_obj_set_style_line_color(day, lv_color_black(), 0);
lv_obj_set_style_line_width(day, 2, 0);
// --- / ---
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_span_t *day = lv_spangroup_add_span(date);
lv_span_set_text(day, "--");
lv_style_set_text_font(lv_span_get_style(day), &super_malibu_80);
lv_style_set_text_color(lv_span_get_style(day), base);
lv_style_set_line_color(lv_span_get_style(day), lv_color_black());
lv_style_set_line_width(lv_span_get_style(day), 2);
lv_span_t *month = lv_spangroup_add_span(date);
lv_span_set_text(month, "--");
lv_style_set_text_font(lv_span_get_style(month), &super_malibu_80);
lv_obj_t *month = lv_label_create(date);
lv_obj_set_name(month, "month");
lv_label_set_text(month, "--");
lv_obj_set_style_text_font(month, &super_malibu_80,0);
lv_obj_t *time = lv_spangroup_create(date_and_time);
lv_obj_set_name(time, "time");
lv_obj_set_id(time, "time");
// lv_obj_add_style(time, &txtstyle, 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);
datetime_ctx_init(date_and_time);
lv_obj_t * subContent = lv_obj_create(info_area);
lv_obj_set_flex_flow(subContent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_size(subContent, LV_PCT(70), LV_PCT(100));
lblTempInt = lv_label_create(subContent);
lv_obj_set_name(lblTempInt,"lblTempInt");
char *templateValue="\xEE\x86\xB0\xEF\x8B\x8A : %s";
lv_obj_t *lblTempInt = lv_label_create(subContent);
lv_label_set_text(lblTempInt, "\xEE\x86\xB0\xEF\x8B\x8A : 21°C");
lv_obj_set_style_text_font(lblTempInt, lv_theme_get_font_large(lblTempInt),0);
lv_subject_add_observer_obj(&tempIntSubj, temp_observer_cb, lblTempInt, templateValue);
lblTempExt = lv_label_create(subContent);
lv_obj_set_name(lblTempExt,"lblTempExt");
char *templateValue2=LV_SYMBOL_HOME "\xEF\x8B\x8A : %s°C";
lv_obj_t *lblTempExt = lv_label_create(subContent);
lv_label_set_text(lblTempExt, LV_SYMBOL_HOME "\xEF\x8B\x8A : 12°C");
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++)
{
@ -1923,11 +1717,11 @@ void messageCardContent(lv_obj_t *cont_messages)
lv_obj_set_flex_flow(apps, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_column(apps, 6, 0);
create_card(apps, "Météo", meteoCardContent, meteoCb,400);
create_card(apps, "Météo", meteoCardContent, meteoCb);
create_card(apps, "Volets", coverCardContent, voletsCb,150);
create_card(apps, "Minuteur", minuteurCardContent, minuteurCb,300);
create_card(apps, "Messagerie", messageCardContent, messagerieCb,300);
create_card(apps, "Volets", coverCardContent, voletsCb);
create_card(apps, "Minuteur", minuteurCardContent, minuteurCb);
create_card(apps, "Messagerie", messageCardContent, messagerieCb);
return;
}
@ -2009,7 +1803,7 @@ static void app_card_click_cb(lv_event_t *e)
app_cb(base_obj);
}
void create_card(lv_obj_t *parent, char *lbl, void (*contentFct)(lv_obj_t *), app_cb_t app_cb, int width)
void create_card(lv_obj_t *parent, char *lbl, void (*contentFct)(lv_obj_t *), app_cb_t app_cb)
{
//lv_style_init(&objstyle);
//lv_style_init(&txtstyle);
@ -2024,9 +1818,6 @@ 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_name(app_card, "app_card");
//lv_obj_remove_style_all(app_card);
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_style_radius(app_card, 20, 0);

View File

@ -6,7 +6,6 @@
#include "platform_detect.h"
#include "cJSON.h"
#include "esp_log.h"
#include "washingMachineState.h"
static const char *TAG = "IHM_GW";
@ -35,11 +34,10 @@ void ihm_gateway_post_event(xIHMEvent_t *evt) {
extern lv_subject_t wifiStatus;
static xIHMEvent_t *evt = NULL;
void ihm_gateway_process_queue(void) {
if (!xIHMEventQueue) return;
xIHMEvent_t *evt = NULL;
#if CONFIG_IDF_TARGET_LINUX
while (xQueueReceive(xIHMEventQueue, &evt, pdMS_TO_TICKS(0)) == pdTRUE)
@ -50,7 +48,7 @@ void ihm_gateway_process_queue(void) {
if (!evt) return;
UBaseType_t pending = uxQueueMessagesWaiting(xIHMEventQueue);
ESP_LOGV(TAG,"Evt recu %d. La queue comporte %d éléments à traiter", evt->eEventType, pending);
ESP_LOGE(TAG,"Evt recu %d. La queue comporte %d éléments à traiter", evt->eEventType, pending);
lv_async_call(traiteEvt, evt);
}
@ -67,7 +65,6 @@ void traiteEvt(void *arg)
case IHM_EVT_TIME_SETTED:
draw_time(evt->pvData);
evt->bNeedToFreeData=false;
break;
case IHM_EVT_OTA_STARTED:
@ -76,12 +73,6 @@ void traiteEvt(void *arg)
case IHM_EVT_HUMID_TEMP:
draw_temp((char *)evt->pvData);
evt->bNeedToFreeData=false;
break;
case IHM_EVT_TEMP_RECUE:
draw_tempExt((char *)evt->pvData);
evt->bNeedToFreeData=false;
break;
case IHM_EVT_PUISSANCE_EMISE:
@ -95,18 +86,23 @@ void traiteEvt(void *arg)
case IHM_EVT_ETAT_MACHINE:
{
char *etatMachine = evt->pvData;
WashingMachineState wms = traiteMessage(etatMachine);
char etat[80];
getEtatMachineStr(wms, etat,80);
ESP_LOGI(TAG,"Etat machine : %s", etat);
draw_minuteur(etat);
// lv_label_set_text(lblEtatMachine, etatFormate);
break;
}
cJSON *root = cJSON_Parse(etatMachine);
bool enRoute = cJSON_GetObjectItem(root, "state")->valueint;
int timestamp = cJSON_GetObjectItem(root, "timestamp")->valueint;
case IHM_EVT_MACHINE_TERMINEE:
{
draw_minuteurStop();
time_t rawtime = (time_t)timestamp;
struct tm *heure_locale = localtime(&rawtime);
char heureFormattee[50];
strftime(heureFormattee, sizeof(heureFormattee), "%d/%m/%Y %H:%M:%S", heure_locale);
char etatFormate[90];
snprintf(etatFormate, sizeof(etatFormate),
enRoute ? "Machine en route depuis %s" : "Machine : Arrêt détecté depuis %s",
heureFormattee);
// lv_label_set_text(lblEtatMachine, etatFormate);
cJSON_Delete(root);
break;
}
case IHM_EVT_HAUTEUR_CUVE:
@ -116,39 +112,13 @@ void traiteEvt(void *arg)
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:
ESP_LOGE(TAG, "Evt inconnu");
break;
}
// Nettoyage mémoire sécurisé
if (evt->bNeedToFreeData && evt->pvData){
//ESP_LOGE(TAG, "Libération mémoire");
if (evt->bNeedToFreeData && evt->pvData)
free(evt->pvData);
}
free(evt);
ESP_LOGV(TAG, "Evt traité");
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,3 @@
if(${IDF_TARGET} STREQUAL "esp32p4")
idf_component_register(SRCS "obtain_time.c" "eventsManager.c" obtain_time.c
INCLUDE_DIRS "include"
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()
REQUIRES mqtt esp_netif)

View File

@ -5,14 +5,10 @@
#include "mqtt_client.h"
#include "obtain_time.h"
#include <time.h>
#include "meteofrance.h"
#if CONFIG_IDF_TARGET_ESP32P4
#include "audio.h"
#endif
EventGroupHandle_t domotic_event_group;
QueueHandle_t ihm_queue;
extern esp_mqtt_client_handle_t client;
//extern esp_mqtt_client_handle_t client;
static const char *TAG = "evtMgr";
@ -29,43 +25,8 @@ void startEvtManager(){
/* 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) {
ESP_LOGI(TAG, "EventManager: On est dans l'event handler %s", domo_event_to_str(evt));
ESP_LOGV(TAG,"On est dans l'event handler %i", evt);
xIHMEvent_t *ihmEvt = malloc(sizeof(xIHMEvent_t));
if (!ihmEvt) {
@ -117,13 +78,12 @@ void send_event(domo_events evt, void* pDatas) {
break;
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
ihmEvt = NULL;
return;
case EVT_PUISSANCE_RECUE:
ESP_LOGI(TAG, "Puissance recue %i", *(int*)pDatas);
ESP_LOGE(TAG, "Puissance recue %i", *(int*)pDatas);
int *data = malloc(sizeof(int));
if (!data) {
ESP_LOGE(TAG, "malloc failed for puissance_5mn");
@ -150,38 +110,6 @@ void send_event(domo_events evt, void* pDatas) {
ihmEvt->bNeedToFreeData = true;
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: {
float *data = malloc(sizeof(float));
if (!data) {
@ -197,49 +125,13 @@ void send_event(domo_events evt, void* pDatas) {
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:
ESP_LOGE(TAG, "Unhandled event type");
free(ihmEvt);
ihmEvt = NULL;
return;
}
ESP_LOGE(TAG, "Envoi d'un evt %i a l'IHM", ihmEvt->eEventType);
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)
{
ESP_LOGE(TAG, "La queue est pleine");
@ -249,8 +141,5 @@ void send_event(domo_events evt, void* pDatas) {
}
free(ihmEvt);
}
}else{
ESP_LOGI(TAG, "Suite %s : on n'envoie rien a l'IHM", domo_event_to_str(evt));
}
}

View File

@ -14,9 +14,6 @@ typedef enum eIHMEvent_t{
IHM_EVT_PUISSANCE_EMISE,
IHM_EVT_ETAT_MACHINE,
IHM_EVT_HAUTEUR_CUVE,
IHM_EVT_METEO_RECUE,
IHM_EVT_TEMP_RECUE,
IHM_EVT_MACHINE_TERMINEE
} eIHMEvent_t;
typedef struct IHM_EVENT
@ -32,22 +29,8 @@ typedef enum domo_events{
EVT_BTN_VOLET,
EVT_PUISSANCE_RECUE,
EVT_ETAT_MACHINE,
EVT_HAUTEUR_CUVE,
EVT_METEO_RECUE,
EVT_TEMP_EXT,
EVT_TEMP_INT,
EVT_FIN_MACHINE,
EVT_FIN_MACHINE_STOP_NOTIF
EVT_HAUTEUR_CUVE
} domo_events;
void startEvtManager();
QueueHandle_t getIHMQueueHandle();
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,6 +73,8 @@ void updateTime(void *pvParameter)
while (1)
{
time(&now);
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
tzset();
struct tm timeinfo = {0};
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));

View File

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

View File

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

View File

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

View File

@ -1,5 +0,0 @@
But:
Exposer l'état de la machine à laver
Dans sa plus simple expression c'est un listener MQTT
L'état de la machine est ensuite émise via une interface
Le topic est en retain pour pouvoir garder le dernier état de la machine {etat, timestamp}

View File

@ -1,24 +0,0 @@
typedef enum {
LAVEUSE_ARRET,
LAVEUSE_REMPLISSAGE,
LAVEUSE_LAVAGE,
LAVEUSE_RINCAGE,
LAVEUSE_ESSORAGE,
LAVEUSE_TERMINEE,
LAVEUSE_ERREUR
} WMState;
typedef struct {
WMState etat; // Indique l'état de la machine
double depuis; // timestamp de l'evenement
bool ack; // Evenement acquitté ?
} WashingMachineState;
WashingMachineState traiteMessage(char *message);
void timestampToDate(double timestamp, char* dateStr, size_t dateStrSize);
WashingMachineState getEtatMachine();
void getEtatMachineStr(WashingMachineState wms, char* etat, size_t etatSize);
void acknoledge();

View File

@ -1,121 +0,0 @@
#include <stdio.h>
#include <cJSON.h>
#include <esp_log.h>
#include "washingMachineState.h"
#include "eventsManager.h"
#include <time.h>
#define TAG "WMS"
WashingMachineState wms;
bool stateOn; // Indique si la machine est en route
WashingMachineState traiteMessage(char* message){
cJSON *root = cJSON_Parse(message);
char* json = cJSON_PrintUnformatted(root);
ESP_LOGE(TAG, "%s", json);
bool state = cJSON_IsTrue(cJSON_GetObjectItem(root, "state"));
double timestamp = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "timestamp"));
bool ack = cJSON_HasObjectItem(root,"ack") && cJSON_GetNumberValue(cJSON_GetObjectItem(root,"ack"));
//char dateStr[80] ;
//timestampToDate(timestamp,dateStr,80);
wms.etat = state?LAVEUSE_LAVAGE:LAVEUSE_ARRET;
wms.depuis = timestamp;
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);
return wms;
}
void timestampToDate(double timestamp, char* dateStr, size_t dateStrSize)
{
time_t ts = timestamp;
struct tm *pTime = localtime(&ts);
strftime(dateStr, dateStrSize, "%d/%m/%Y %H:%M:%S", pTime);
//printf("Date and french time : %s\n", dateStr);
}
WashingMachineState getEtatMachine(){
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)
{
char* etatStr;
switch (wms.etat)
{
case LAVEUSE_ARRET:
/* code */
etatStr="Machine arretée";
break;
case LAVEUSE_LAVAGE:
/* code */
etatStr="Machine en route";
break;
default:
etatStr="Etat inconnu";
break;
}
char dateStr[30];
timestampToDate(wms.depuis,dateStr,30);
//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);
}
void acknoledge(){
wms.ack=true;
}

View File

@ -1,223 +1,16 @@
dependencies:
espressif/bh1750:
component_hash: c8cae6dca70fd5fdf5943ae37efbbea6cc41bcb784506e61ea301b3e94dce74b
espressif/esp_lcd_qemu_rgb:
component_hash: e8981dd7399504a5ab647ce28a4876f8467c03b759895f50c24f0cb6095faaa0
dependencies:
- name: idf
require: private
version: '>=4.0'
version: '>=5.3'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.0.3
espressif/cmake_utilities:
component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
dependencies:
- name: idf
require: private
version: '>=4.1'
source:
registry_url: https://components.espressif.com
type: service
version: 0.5.3
espressif/eppp_link:
component_hash: 9472e6825f4bb71eca2b39cf1bc92659c1ac60bfd7416560ad033a7dd8641b17
dependencies:
- name: espressif/esp_serial_slave_link
registry_url: https://components.espressif.com
require: private
version: ^1.1.0
- name: idf
require: private
version: '>=5.2'
source:
registry_url: https://components.espressif.com
type: service
version: 1.1.4
espressif/esp32_p4_function_ev_board:
component_hash: 2d90a5160cd2aa81f1bc90edf90d802bdc15626b9ec6d699aa36a35bad119ed9
dependencies:
- name: espressif/esp_codec_dev
registry_url: https://components.espressif.com
require: public
version: ~1.5
- name: espressif/esp_lcd_ek79007
registry_url: https://components.espressif.com
require: private
version: '>=2.0.1,<3.0.0'
- name: espressif/esp_lcd_ili9881c
registry_url: https://components.espressif.com
require: private
version: '>=1.0.3,<2.0.0'
- name: espressif/esp_lcd_touch_gt911
registry_url: https://components.espressif.com
require: private
version: ^1
- name: espressif/esp_video
registry_url: https://components.espressif.com
require: public
version: ~1.4
- name: espressif/esp_lcd_lt8912b
registry_url: https://components.espressif.com
require: private
version: '>=0.1.3,<1.0.0'
- name: espressif/esp_lvgl_port
registry_url: https://components.espressif.com
require: public
version: ^2
- name: idf
require: private
version: '>=5.4'
- name: lvgl/lvgl
registry_url: https://components.espressif.com
require: private
version: '>=8,<10'
- name: espressif/usb
registry_url: https://components.espressif.com
require: public
rules:
- if: idf_version >=6.0
version: ^1.0.0
source:
registry_url: https://components.espressif.com/
type: service
targets:
- esp32p4
version: 5.2.1
espressif/esp_cam_sensor:
component_hash: db5b1c725799dced61e7b100dc027e1e59558c9973d7e1ed8ce42a5ec89da31c
dependencies:
- name: espressif/cmake_utilities
registry_url: https://components.espressif.com
require: private
version: 0.*
- name: espressif/esp_sccb_intf
registry_url: https://components.espressif.com
require: private
version: '>=0.0.5'
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com
type: service
targets:
- esp32p4
- esp32s3
- esp32c3
- esp32c5
- esp32c6
- esp32c61
version: 1.7.0
espressif/esp_codec_dev:
component_hash: 0d9e9bc288156eb55f79338d312e1ebf8c9dfbd5e7d13ef0f20ccb031b4e15cf
dependencies:
- name: idf
require: private
version: '>=4.0'
source:
registry_url: https://components.espressif.com
type: service
version: 1.5.4
espressif/esp_h264:
component_hash: fa5daaebc8a304f0b79bc57e51aab43e0a03eabc2ba3865bff4063c56b5d4564
dependencies:
- name: idf
require: private
version: '>=4.4'
source:
registry_url: https://components.espressif.com
type: service
version: 1.0.4
espressif/esp_hosted:
component_hash: 9eea9ce83444a412b4a02311f787f3639a5d29fe67e6df83863010dd68ab250b
dependencies:
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com
type: service
version: 2.12.0
espressif/esp_ipa:
component_hash: 31003e536f0d26158e10d7fcf2448b6377ce1148518287d0f34ed3b6c942c6d8
dependencies:
- name: espressif/cmake_utilities
registry_url: https://components.espressif.com
require: private
version: 0.*
- name: idf
require: private
version: '>=5.4'
source:
registry_url: https://components.espressif.com
type: service
targets:
- esp32p4
version: 1.3.1
espressif/esp_lcd_ek79007:
component_hash: 7a0896e167d88b9fc368ac74b2e84774ec5b48cd9baa390896c4be255d900e2e
dependencies:
- name: espressif/cmake_utilities
registry_url: https://components.espressif.com
require: private
version: 0.*
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com
type: service
targets:
- esp32p4
version: 2.0.2
espressif/esp_lcd_ili9881c:
component_hash: 0288df12755c95d406ccea245a427595f314df0b14a61846286d926ea6f3698e
dependencies:
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com
type: service
targets:
- esp32p4
version: 1.1.0
espressif/esp_lcd_lt8912b:
component_hash: f954a3393c8e16159f0c7448c9f4312b58933a53563fe5173db5f63a2b0f7aa7
dependencies:
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com
type: service
version: 0.2.0
espressif/esp_lcd_touch:
component_hash: 3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862
dependencies:
- name: idf
require: private
version: '>=4.4.2'
source:
registry_url: https://components.espressif.com
type: service
version: 1.2.1
espressif/esp_lcd_touch_gt911:
component_hash: be02e243d18b9a661bc13b0d22c0a5cfa3f708cf04d6eb059772276c8c8a4d76
dependencies:
- name: espressif/esp_lcd_touch
registry_url: https://components.espressif.com
require: public
version: ^1.2.0
- name: idf
require: private
version: '>=4.4.2'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.2.0~1
version: 1.0.2
espressif/esp_lvgl_port:
component_hash: b6360960f47b6776462e7092861b3ea66477ffb762a01baa0aecbb3d74cd50f4
component_hash: f872401524cb645ee6ff1c9242d44fb4ddcfd4d37d7be8b9ed3f4e85a404efcd
dependencies:
- name: idf
require: private
@ -229,153 +22,22 @@ dependencies:
source:
registry_url: https://components.espressif.com/
type: service
version: 2.7.2
espressif/esp_sccb_intf:
component_hash: c071b189e49f40940722aea01a5489f873385cc39cd5b14012341135b85d1a9d
dependencies:
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com
type: service
version: 0.0.8
espressif/esp_serial_slave_link:
component_hash: ac1776806de0a6e371c84e87898bb983e19ce62aa7f1e2e5c4a3b0234a575d2c
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com
type: service
version: 1.1.2
espressif/esp_video:
component_hash: 2239aed49fa4eb1efdf3b0c2b95b05c03fc8b363c101bc2cd70f5e3bcd3c7cc4
dependencies:
- name: espressif/cmake_utilities
registry_url: https://components.espressif.com
require: private
version: 0.*
- name: espressif/esp_cam_sensor
registry_url: https://components.espressif.com
require: private
version: 1.7.*
- name: espressif/esp_h264
registry_url: https://components.espressif.com
require: private
rules:
- if: target in [esp32p4]
version: 1.0.4
- name: espressif/esp_ipa
registry_url: https://components.espressif.com
require: private
rules:
- if: target in [esp32p4]
version: 1.3.*
- name: idf
require: private
version: '>=5.4'
- name: espressif/usb_host_uvc
registry_url: https://components.espressif.com
require: private
rules:
- if: target in [esp32p4, esp32s3]
version: 2.4.*
source:
registry_url: https://components.espressif.com
type: service
targets:
- esp32p4
- esp32s3
- esp32c3
- esp32c5
- esp32c6
- esp32c61
version: 1.4.1
espressif/esp_wifi_remote:
component_hash: 20393ed850b2cb40cadcf369b4c852ef5af49e2d89e58774d968c57b0c436fd3
dependencies:
- name: espressif/eppp_link
registry_url: https://components.espressif.com
require: private
version: '>=0.1'
- name: espressif/esp_hosted
registry_url: https://components.espressif.com
require: private
rules:
- if: target in [esp32h2, esp32p4]
version: '>=0.0.6'
- name: idf
require: private
version: '>=5.3'
source:
registry_url: https://components.espressif.com/
type: service
version: 0.14.4
espressif/usb_host_uvc:
component_hash: 197eae0d1dd5ddec773704653e0ff70e81126b8ccdb62e034ed239f755adb48c
dependencies:
- name: idf
require: private
version: '>=5.0'
- name: espressif/usb
registry_url: https://components.espressif.com
require: public
rules:
- if: idf_version >=6.0
- if: target not in ["linux"]
version: ^1.0.0
source:
registry_url: https://components.espressif.com
type: service
targets:
- esp32s2
- esp32s3
- esp32p4
- esp32h4
- linux
version: 2.4.1
version: 2.7.0
idf:
source:
type: idf
version: 5.5.2
joltwallet/littlefs:
component_hash: dcea25bcef2de023f089f5f01e8d8c46ad1b8ffef75861ad5ffb4098555839df
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.20.4
version: 5.5.1
lvgl/lvgl:
component_hash: 184e532558c1c45fefed631f3e235423d22582aafb4630f3e8885c35281a49ae
dependencies: []
source:
registry_url: https://components.espressif.com
type: service
version: 9.5.0
suda-morris/am2302_rmt:
component_hash: 890df8ebfec652eb9f8e1d612959f00a951dbe9241335e5e335fc7fb1468ea32
dependencies:
- name: idf
require: private
version: '>=5.1'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.1.0
path: /home/marc/domotic/components/lvgl__lvgl
type: local
version: 9.4.0
direct_dependencies:
- espressif/bh1750
- espressif/esp32_p4_function_ev_board
- espressif/esp_lcd_touch_gt911
- espressif/esp_lcd_qemu_rgb
- espressif/esp_lvgl_port
- espressif/esp_wifi_remote
- idf
- joltwallet/littlefs
- suda-morris/am2302_rmt
manifest_hash: ff7936466302f0a070f567433bba5708f3bdab0fb5fa4b9941b77ae4ac95532c
target: esp32p4
- lvgl/lvgl
manifest_hash: 6dfd2d16dd4d21f701b251046402dbd6cb442f0c69beab0ba9af1b2ef32c7367
target: esp32s3
version: 2.0.0

View File

@ -5,17 +5,16 @@ set(comps heap nvs_flash esp_netif image_downloader fatfs protocol_examples_comm
if(${IDF_TARGET} STREQUAL "esp32p4")
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
INCLUDE_DIRS "./include"
REQUIRES ${comps}
EMBED_TXTFILES ${PROJECT_DIR}/main/ca_cert.pem ${PROJECT_DIR}/../ota/certs/server.crt
EMBED_TXTFILES ${PROJECT_DIR}/main/ca_cert.pem
EMBED_FILES "index.html")
littlefs_create_partition_image(littlefs medias FLASH_IN_PROJECT)
elseif(${IDF_TARGET} STREQUAL "linux")
message(STATUS "Linux Mode --> main standard")
list(APPEND comps vfs esp_http_server)
idf_component_register(SRCS main.c communication.c
idf_component_register(SRCS main.c
INCLUDE_DIRS "./include"
REQUIRES ${comps}
EMBED_TXTFILES ${PROJECT_DIR}/main/ca_cert.pem

View File

@ -2,22 +2,206 @@
#include "esp_log.h"
#include "mqtt_client.h"
#include "stateManagement.h"
#include "eventsManager.h"
#if CONFIG_IDF_TARGET_ESP32P4
#include "esp_wifi.h"
#endif
#include "esp_log.h"
esp_mqtt_client_handle_t client;
static const char *TAG = "domo_mqtt";
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0)
{
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
}
}
void splitIt(char *payload, unsigned int length, float *datas)
{
char *sep = ",";
char *token;
char *saveptr1;
token = strtok_r(payload, sep, &saveptr1);
datas[0] = atof(token);
ESP_LOGE(TAG,"%f",datas[0]);
token = strtok_r(NULL, sep, &saveptr1);
datas[1] = atof(token);
ESP_LOGE(TAG,"%f",datas[1]);
token = strtok_r(NULL, sep, &saveptr1);
datas[2] = atof(token);
ESP_LOGE(TAG,"%f",datas[2]);
token = strtok_r(NULL, sep, &saveptr1);
datas[3] = atof(token);
ESP_LOGE(TAG,"%f",datas[3]);
}
mqtt_callback mqttcb;
void mqtt_publish(const char *topic, const char *datas){
esp_mqtt_client_publish(client, topic, datas, 0, 1, 0);
}
/*
* @brief Event handler registered to receive MQTT events
*
* This function is called by the MQTT client event loop.
*
* @param handler_args user data registered to the event.
* @param base Event base for the handler(always MQTT Base in this example).
* @param event_id The id for the received event.
* @param event_data The data for the event, esp_mqtt_event_handle_t.
*/
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGV(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
mqttcb(MQTT_CONNECTED,NULL);
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
//msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
//ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTempExt, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTempInt, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicHauteurCuve, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicHauteurCuveEvol, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTest, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicdomoticCommand, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicdomoticCommand, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicEtatMachine, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicConsoElec, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
//ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
//ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
mqttcb(MQTT_DISCONNECTED,NULL);
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
//msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
//ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
mqttcb(MQTT_DATA_RECEIVED, event);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
{
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
void mqtt_app_start(mqtt_callback callback, EventGroupHandle_t domotic_event_group)
{
mqttcb=callback;
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://192.168.0.10",
.network.timeout_ms = 1000};
#if CONFIG_BROKER_URL_FROM_STDIN
char line[128];
if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0)
{
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128)
{
int c = fgetc(stdin);
if (c == '\n')
{
line[count] = '\0';
break;
}
else if (c > 0 && c < 127)
{
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
}
else
{
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
// Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
// number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above)
EventBits_t bits = xEventGroupWaitBits(domotic_event_group,
BIT0,
pdFALSE,
pdFALSE,
portMAX_DELAY);
if (bits & BIT0)
{
esp_mqtt_client_start(client);
}
}
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define BIT0 0x00000001
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
@ -31,8 +215,7 @@ static EventGroupHandle_t s_wifi_event_group;
static int s_retry_num = 0;
wifi_callback cb;
#if CONFIG_IDF_TARGET_ESP32P4
#define BIT0 0x00000001
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
@ -136,213 +319,4 @@ void wifi_init_sta(wifi_callback callback)
}
*/
}
#else
#include <time.h>
int64_t esp_timer_get_time(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
}
#endif
esp_mqtt_client_handle_t client;
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0)
{
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
}
}
void splitIt(char *payload, unsigned int length, float *datas)
{
char *sep = ",";
char *token;
char *saveptr1;
token = strtok_r(payload, sep, &saveptr1);
datas[0] = atof(token);
ESP_LOGE(TAG,"%f",datas[0]);
token = strtok_r(NULL, sep, &saveptr1);
datas[1] = atof(token);
ESP_LOGE(TAG,"%f",datas[1]);
token = strtok_r(NULL, sep, &saveptr1);
datas[2] = atof(token);
ESP_LOGE(TAG,"%f",datas[2]);
token = strtok_r(NULL, sep, &saveptr1);
datas[3] = atof(token);
ESP_LOGE(TAG,"%f",datas[3]);
}
mqtt_callback mqttcb;
void mqtt_publish(const char *topic, const char *datas, bool retain){
esp_mqtt_client_publish(client, topic, datas, 0, 1, retain);
}
/*
* @brief Event handler registered to receive MQTT events
*
* This function is called by the MQTT client event loop.
*
* @param handler_args user data registered to the event.
* @param base Event base for the handler(always MQTT Base in this example).
* @param event_id The id for the received event.
* @param event_data The data for the event, esp_mqtt_event_handle_t.
*/
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGV(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
mqttcb(MQTT_CONNECTED,NULL);
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
//msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
//ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTempExt, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTempInt, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicHauteurCuve, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicHauteurCuveEvol, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTest, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicdomoticCommand, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicdomoticCommand, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicEtatMachine, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicConsoElec, 0);
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);
//ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
//ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
mqttcb(MQTT_DISCONNECTED,NULL);
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
//msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
//ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
mqttcb(MQTT_DATA_RECEIVED, event);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
{
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
void mqtt_app_start(mqtt_callback callback, EventGroupHandle_t domotic_event_group)
{
mqttcb=callback;
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://192.168.0.10",
.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
char line[128];
if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0)
{
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128)
{
int c = fgetc(stdin);
if (c == '\n')
{
line[count] = '\0';
break;
}
else if (c > 0 && c < 127)
{
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
}
else
{
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
// Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
// number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above)
EventBits_t bits = xEventGroupWaitBits(domotic_event_group,
BIT0,
pdFALSE,
pdFALSE,
portMAX_DELAY);
if (bits & BIT0)
{
esp_mqtt_client_start(client);
}
}

View File

@ -16,6 +16,14 @@ typedef void (*wifi_callback)(wifi_evt evt);
typedef void (*mqtt_callback)(mqtt_evt evt, esp_mqtt_event_handle_t evt_data);
void wifi_init_sta(wifi_callback cb);
void mqtt_app_start(mqtt_callback cb, EventGroupHandle_t evtGroup);
void mqtt_publish(const char *topic, const char *datas, bool retain);
void mqtt_publish(const char *topic, const char *datas);
#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>
<h2>How to save and Download crash dump</h2>
</br></br>
<button class="btn success"><a href="./download">Download</a></button></br></br>
<button class="btn success"><a href="./crash">Crash</a></button>
<button class="btn success"><a href="http://192.168.4.1/download">Download</a></button></br></br>
<button class="btn success"><a href="http://192.168.4.1/crash">Crash</a></button>
</center>
</body>
</html>

View File

@ -20,10 +20,10 @@
#include "ihm_gateway.h"
// OTA
#include "esp_ota_ops.h"
#include "esp_https_ota.h"
/*#include "esp_ota_ops.h"
#include "esp_http_client.h"
#include "esp_https_ota.h"
*/
// Includes personnels
//#include "wifi_logger.h"
#include "obtain_time.h"
@ -31,16 +31,13 @@
#include "include/communication.h"
#include "stateManagement.h"
//#include "driver/gpio.h"
//#include "am2302_rmt.h"
#include "eventsManager.h"
#include "esp_timer.h"
#include <esp_task_wdt.h>
#if CONFIG_IDF_TARGET_ESP32P4
#include "am2302_rmt.h"
#include "esp_wifi.h"
#endif
// GPIO assignment
#define AM2302_GPIO 4
@ -107,128 +104,8 @@ void bh1750_init(void)
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){
switch (evt)
{
@ -249,37 +126,16 @@ void mqtt_cb(mqtt_evt evt, esp_mqtt_event_handle_t event){
break;
case MQTT_DATA_RECEIVED:
//lv_subject_set_int(&mqttStatus,2);
ESP_LOGE(TAG, "MQTT_EVENT_DATA");
ESP_LOGE(TAG, "TOPIC=%.*s\n", event->topic_len, event->topic);
ESP_LOGE(TAG, "DATA=%.*s\n", event->data_len, event->data);
ESP_LOGD(TAG, "\nMQTT_EVENT_DATA");
ESP_LOGD(TAG, "TOPIC=%.*s\n", event->topic_len, event->topic);
ESP_LOGD(TAG, "DATA=%.*s\n", event->data_len, event->data);
char *topic = strndup(event->topic, event->topic_len);
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 (strcmp(topic, topicTempExt) == 0)
{
//if(lvgl_port_lock(50)){
float temp = strtof(event->data, NULL);
char buff[5];
sprintf(buff,"%.1f",temp);
send_event(EVT_TEMP_EXT, buff);
//lv_subject_copy_string(&tempExtSubj, buff);
//lvgl_port_unlock();
@ -438,7 +294,7 @@ extern char *days[7];
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) {
case HTTP_EVENT_ERROR:
@ -468,10 +324,11 @@ esp_err_t _ota_http_event_handler(esp_http_client_event_t *evt)
}
return ESP_OK;
}
*/
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");
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) {
return ESP_ERR_INVALID_ARG;
@ -492,11 +349,12 @@ static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
return ESP_OK;
}
*/
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).
EventBits_t bits = xEventGroupWaitBits(domotic_event_group,
BIT0,
@ -520,8 +378,8 @@ void simple_ota_example_task(void *pvParameter)
esp_http_client_config_t config = {
.url = "https://192.168.0.28:8070/rgb_lcd.bin",
.timeout_ms = 30000,
.buffer_size = 6144,
.buffer_size_tx = 6144, //TX Buffer, Main Buffer
.buffer_size = 20000,
.buffer_size_tx = 20000, //TX Buffer, Main Buffer
.event_handler = _ota_http_event_handler,
.keep_alive_enable = true,
.cert_pem = (char *)server_cert_pem_start,
@ -622,14 +480,13 @@ ota_end:
ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed");
vTaskDelete(NULL);
}
}
*/}
#if CONFIG_IDF_TARGET_ESP32P4
am2302_handle_t sensor = NULL;
//am2302_handle_t sensor = NULL;
void readTempHumid(void *pvParameter)
{
float temperature = 0;
/* float temperature = 0;
float humidity = 0;
while (1)
{
@ -637,30 +494,16 @@ void readTempHumid(void *pvParameter)
char buff[40];
ESP_LOGI(TAG, "Temperature: %.1f °C, Humidity: %.1f %%", temperature, humidity);
sprintf(buff,"%.1f °C, %.1f %%", temperature, humidity);
send_event(EVT_TEMP_INT, buff);
xIHMEvent_t m = {
.eEventType = IHM_EVT_HUMID_TEMP,
.pvData = buff
};
//xQueueSendToFront(ihm_queue,&m,5);
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){
ESP_LOGE(TAG,"fail alloc %u in %" PRIu32 " in %s", size,caps,function_name);
@ -868,9 +711,9 @@ extern lv_subject_t forecastH2Subj;
extern lv_subject_t forecastH3Subj;
extern lv_subject_t meteoStatus;
void weather_data_retreived(meteo_event_payload_t *datas)
void weather_data_retreived(struct meteodailyforecast_data dailyDatas[3], struct meteoforecast_data datas[3])
{
send_event(EVT_METEO_RECUE, datas);
/* ESP_LOGE(TAG, "debut debug");
printf("%lld\n", datas[0].datetime);
printf("%s\n", datas[0].previsions.desc);
@ -885,6 +728,22 @@ void weather_data_retreived(meteo_event_payload_t *datas)
*/
//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{
//ESP_LOGE(TAG, "Impossible d'obtenir le mutex dans weather_data_retreived");
//}
@ -1011,34 +870,16 @@ 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)
{
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
tzset();
ESP_ERROR_CHECK(esp_event_loop_create_default());
ihm_gateway_init();
startEvtManager();
boucleMeteo();
#if CONFIG_IDF_TARGET_LINUX
// en mode linux on simule l'obtention de la connexion wifi
xEventGroupSetBits(domotic_event_group, WIFI_CONNECTED_BIT);
@ -1046,27 +887,13 @@ void app_main(void)
//drawIhm(getIHMQueueHandle());
#else
littlefs_mount();
xTaskCreate(&drawIhm,"ihm_task",10000,getIHMQueueHandle(),3,&ihm_task);
xTaskCreate(&drawIhm,"ihm_task",10000,getIHMQueueHandle(),10,NULL);
//et sinon on se connecte
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
wifi_init_sta(wifi_cb);
//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
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);
TaskHandle_t xHandle = NULL;
BaseType_t ret1;
/*ret1 = xTaskCreate(&imgdwn, "imageDownload_task", 3 * 1024, domotic_event_group, 5, &xHandle);
@ -1075,30 +902,6 @@ void app_main(void)
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()
@ -1225,5 +1028,14 @@ void app_main1(void)
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.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

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