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
207 changed files with 156268 additions and 12473 deletions

13
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,13 @@
ARG DOCKER_TAG=latest
FROM espressif/idf:${DOCKER_TAG}
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN apt-get update -y && apt-get install udev -y
RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
CMD ["/bin/bash", "-c"]

View File

@ -0,0 +1,21 @@
{
"name": "ESP-IDF QEMU",
"build": {
"dockerfile": "Dockerfile"
},
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension",
"espressif.esp-idf-web"
]
}
},
"runArgs": ["--privileged"]
}

7
.gitignore vendored
View File

@ -1,2 +1,9 @@
build/ build/
managed_components/ managed_components/
build_slave/
CMakeFiles/
esp-idf/
gdbinit/
sdkconfig
sdkconfig.old
components/domotic_display/test_host/sdkconfig

View File

@ -2,7 +2,7 @@
"configurations": [ "configurations": [
{ {
"name": "ESP-IDF", "name": "ESP-IDF",
"compilerPath": "${config:idf.toolsPath}/tools/riscv32-esp-elf/esp-14.2.0_20240906/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", "compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [ "includePath": [
"${config:idf.espIdfPath}/components/**", "${config:idf.espIdfPath}/components/**",

131
.vscode/launch.json vendored
View File

@ -16,7 +16,7 @@
"name": "Debug LVGL demo with gdb", "name": "Debug LVGL demo with gdb",
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/bin/rgb_lcd", "program": "${workspaceFolder}/build/rgb_lcd",
"args": [], "args": [],
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"stopAtEntry": false, "stopAtEntry": false,
@ -32,6 +32,133 @@
"miDebuggerPath": "C:\\MinGw\\bin\\gdb.exe" "miDebuggerPath": "C:\\MinGw\\bin\\gdb.exe"
} }
}, },
{
"name": "Debug ihm with gdb",
"type": "cppdbg",
"request": "launch",
"preLaunchTask": "Build - Build IHM",
"program": "${workspaceFolder}/components/domotic_display/test_host/build/nvs_host_test.elf",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
/*
"setupCommands": [
{
"description": "Load LVGL GDB helpers",
"text": "source /home/marc/domotic/components/domotic_display/test_host/managed_components/lvgl__lvgl/scripts/gdb/gdbinit.py"
}
],*/
"linux": {
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb"
},
"osx": {
"MIMode": "lldb"
},
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "C:\\MinGw\\bin\\gdb.exe"
}
},
{
"name": "Debug meteofrance with gdb",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/components/meteofrance/testHost/build/my_custom_app.elf",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
/*
"setupCommands": [
{
"description": "Load LVGL GDB helpers",
"text": "source /home/marc/domotic/components/domotic_display/test_host/managed_components/lvgl__lvgl/scripts/gdb/gdbinit.py"
}
],*/
"linux": {
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb"
},
"osx": {
"MIMode": "lldb"
},
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "C:\\MinGw\\bin\\gdb.exe"
}
},
{
"name": "Debug main with gdb",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/rgb_lcd.elf",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
/*
"setupCommands": [
{
"description": "Load LVGL GDB helpers",
"text": "source /home/marc/domotic/components/domotic_display/test_host/managed_components/lvgl__lvgl/scripts/gdb/gdbinit.py"
}
],*/
"linux": {
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb"
},
"osx": {
"MIMode": "lldb"
},
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "C:\\MinGw\\bin\\gdb.exe"
}
},
{
"name": "Debug remindme with gdb",
"type": "cppdbg",
"request": "launch",
"preLaunchTask": "Build - Build IHM",
"program": "${workspaceFolder}/components/RemindMe/test/build/remindme_host_test.elf",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"setupCommands": [
{
"description": "Load LVGL GDB helpers",
"text": "source /home/marc/domotic/components/domotic_display/test_host/managed_components/lvgl__lvgl/scripts/gdb/gdbinit.py"
}
],
"linux": {
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb"
},
"osx": {
"MIMode": "lldb"
},
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "C:\\MinGw\\bin\\gdb.exe"
}
},
{
"name": "Debug comp2 (Linux)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/components/domotic_display/test_host/build/comp2_test",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "Enable pretty printing",
"text": "-enable-pretty-printing"
}
]
}
] ]
} }

23
.vscode/settings.json vendored
View File

@ -1,18 +1,19 @@
{ {
"C_Cpp.intelliSenseEngine": "default", "C_Cpp.intelliSenseEngine": "default",
"idf.espIdfPath": "/home/marc/esp/master/esp-idf", "idf.espIdfPath": "/home/marc/esp/esp-idf",
"idf.pythonBinPath": "/home/marc/.espressif/python_env/idf5.3_py3.10_env/bin/python", "idf.pythonBinPath": "/home/marc/.espressif/tools/python/v5.5.2/venv/bin/python3",
"idf.toolsPath": "/home/marc/.espressif", "idf.toolsPath": "/home/marc/.espressif",
"idf.customExtraPaths": "/home/marc/.espressif/tools/xtensa-esp-elf-gdb/14.2_20240403/xtensa-esp-elf-gdb/bin:/home/marc/.espressif/tools/riscv32-esp-elf-gdb/14.2_20240403/riscv32-esp-elf-gdb/bin:/home/marc/.espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin:/home/marc/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20240530/riscv32-esp-elf/bin:/home/marc/.espressif/tools/esp32ulp-elf/2.38_20240113/esp32ulp-elf/bin:/home/marc/.espressif/tools/cmake/3.24.0/bin:/home/marc/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240318/openocd-esp32/bin:/home/marc/.espressif/tools/ninja/1.11.1:/home/marc/.espressif/tools/esp-rom-elfs/20240305", "idf.customExtraPaths": "/home/marc/.espressif/tools/xtensa-esp-elf-gdb/14.2_20240403/xtensa-esp-elf-gdb/bin:/home/marc/.espressif/tools/riscv32-esp-elf-gdb/14.2_20240403/riscv32-esp-elf-gdb/bin:/home/marc/.espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin:/home/marc/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20240530/riscv32-esp-elf/bin:/home/marc/.espressif/tools/esp32ulp-elf/2.38_20240113/esp32ulp-elf/bin:/home/marc/.espressif/tools/cmake/3.24.0/bin:/home/marc/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240318/openocd-esp32/bin:/home/marc/.espressif/tools/ninja/1.11.1:/home/marc/.espressif/tools/esp-rom-elfs/20240305",
"idf.customExtraVars": { "idf.customExtraVars": {
"OPENOCD_SCRIPTS": "/home/marc/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240318/openocd-esp32/share/openocd/scripts", "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/", "ESP_ROM_ELF_DIR": "/home/marc/.espressif/tools/esp-rom-elfs/20240305/",
"IDF_TARGET": "esp32p4" "IDF_TARGET": "linux"
}, },
"idf.gitPath": "git", "idf.gitPath": "git",
"idf.adapterTargetName": "esp32s3", "idf.adapterTargetName": "esp32s3",
"idf.openOcdConfigs": [ "idf.openOcdConfigs": [
"board/esp32p4-builtin.cfg" "interface/ftdi/esp_ftdi.cfg",
"target/esp32.cfg"
], ],
"idf.flashType": "UART", "idf.flashType": "UART",
"idf.port": "/dev/ttyUSB0", "idf.port": "/dev/ttyUSB0",
@ -105,7 +106,15 @@
"bsp_board_extra.h": "c", "bsp_board_extra.h": "c",
"display.h": "c", "display.h": "c",
"statemanagement.h": "c", "statemanagement.h": "c",
"communication.h": "c" "communication.h": "c",
"mqtt_client.h": "c"
}, },
"idf.pythonInstallPath": "/usr/bin/python3" "idf.pythonInstallPath": "/usr/bin/python3",
"clangd.path": "/home/marc/.espressif/tools/esp-clang/esp-19.1.2_20250312/esp-clang/bin/clangd",
"clangd.arguments": [
"--background-index",
"--query-driver=/home/marc/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-gcc",
"--compile-commands-dir=/home/marc/domotic/build"
],
"idf.currentSetup": "/home/marc/.espressif/v5.5.2/esp-idf"
} }

43
.vscode/tasks.json vendored
View File

@ -33,7 +33,7 @@
"isDefault": true "isDefault": true
}, },
"dependsOn": "Build" "dependsOn": "Build"
} },
{ {
"label": "Build - Build project", "label": "Build - Build project",
"type": "shell", "type": "shell",
@ -73,6 +73,47 @@
"isDefault": true "isDefault": true
} }
}, },
{
"label": "Build - Build IHM",
"type": "shell",
"command": "${config:idf.pythonBinPath} ${config:idf.espIdfPath}/tools/idf.py build",
"windows": {
"command": "${config:idf.pythonBinPathWin} ${config:idf.espIdfPathWin}\\tools\\idf.py build",
"options": {
"env": {
"PATH": "${env:PATH};${config:idf.customExtraPaths}"
}
}
},
"options": {
"cwd": "${workspaceFolder}/components/domotic_display/test_host/",
"env": {
"IDF_TARGET": "linux",
"PATH": "${env:PATH}:${config:idf.customExtraPaths}"
}
},
"problemMatcher": [
{
"owner": "cpp",
"fileLocation": [
"autoDetect",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
],
"group": {
"kind": "build",
"isDefault": true
}
},
{ {
"label": "Set ESP-IDF Target", "label": "Set ESP-IDF Target",
"type": "shell", "type": "shell",

View File

@ -1,28 +1,63 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
option(SIMULATION_QEMU "Build for QEMU simulation" OFF)
message(STATUS "ROOT:: SIMULATION_QEMU = ${SIMULATION_QEMU}")
# -------------------------------------------------
# CONFIGURATION AVANT project() : uniquement CMake pur
# -------------------------------------------------
# "Trim" the build. Include the minimal set of components, main and anything it depends on.
set(COMPONENTS main)
if(SIMULATION_QEMU)
message(STATUS "SIMULATION_QEMU = ON")
option(SIMULATION_QEMU "Build for QEMU simulation" ON)
set(COMPONENTS
components/meteofrance
components/domotic_display
managed_components/lvgl_lvgl
main
esp-timer
$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs
)
else()
message(STATUS "SIMULATION_QEMU = OFF")
option(SIMULATION_QEMU "Build for QEMU simulation" OFF)
# set(COMPONENTS
# components/meteofrance
# components/domotic_display
# managed_components/lvgl_lvgl
# main
# $ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs
# )
endif()
#list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/esp_timer")
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
if(${IDF_TARGET} STREQUAL "esp32p4")
set(EXTRA_COMPONENT_DIRS
/home/marc/esp-dev-kits/examples/esp32-p4-function-ev-board/examples/common_components
$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs
)
else()
# PROJECT_PLATFORM_LINUX
# PROJECT_PLATFORM_ESP32
add_compile_definitions(PROJECT_PLATFORM_LINUX)
set(EXTRA_COMPONENT_DIRS
$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs
${CMAKE_CURRENT_SOURCE_DIR}/FreeRTOS
"/home/marc/esp-protocols/common_components/linux_compat"
"/home/marc/esp-protocols/components/mdns/tests/host_test/components"
)
endif()
project(rgb_lcd) project(rgb_lcd)
# -------------------------------------------------
# APRÈS project() : maintenant CONFIG_SIMULATION_QEMU existe
# -------------------------------------------------
if(CONFIG_SIMULATION_QEMU)
message(STATUS "Compilation IHM (simulation)")
add_compile_definitions(CONFIG_SIMULATION_QEMU=1)
#add_custom_target(run_ihm
# COMMAND ${CMAKE_COMMAND} -E echo "Building and launching IHM native..."
# COMMAND ${CMAKE_COMMAND} --build ${CMAKE_SOURCE_DIR}/components/ihm --target all
# COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_SOURCE_DIR}/components/ihm ./ihm_simulator
#)
else()
message(STATUS "Compilation standard")
#add_link_options("-Wl,--disable-non-contiguous-regions")
add_compile_options(
-fsanitize=address
-fno-omit-frame-pointer
-O0
-g
)
add_link_options(-fsanitize=address)
endif()

View File

@ -0,0 +1,15 @@
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES 5
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) )
#define configMAX_TASK_NAME_LEN 10
#define configUSE_16_BIT_TICKS 0
#endif /* FREERTOS_CONFIG_H */

7
Kconfig.projbuild Normal file
View File

@ -0,0 +1,7 @@
menu "Simulation options"
config SIMULATION_QEMU
bool "Build with QEMU simulation stubs"
default n
endmenu

View File

@ -1,3 +1,7 @@
docker run -v $PWD:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 24 --no-compress --font Montserrat-Medium.ttf --symbols "0123456789.°èéêûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz :-%," --format lvgl -o montserrat_medium_24.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575 docker run -v $PWD:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 24 --no-compress --font Montserrat-Medium.ttf --symbols "0123456789.°èéêûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz :-%," --format lvgl -o montserrat_medium_24.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575
docker run -v $PWD:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 18 --no-compress --font Montserrat-Medium.ttf --symbols "0123456789.°èéêûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz :-%," --format lvgl -o montserrat_medium_18.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575 docker run -v $PWD:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 18 --no-compress --font Montserrat-Medium.ttf --symbols "0123456789.°èéêûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz :-%," --format lvgl -o montserrat_medium_18.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575
docker run -v $PWD:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 12 --no-compress --font Montserrat-Medium.ttf --symbols "0123456789.°èéêûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz :-%," --format lvgl -o montserrat_medium_12.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575 docker run -v $PWD:/app -w /app lvfontconv lv_font_conv --bpp 4 --size 12 --no-compress --font Montserrat-Medium.ttf --symbols "0123456789.°èéêûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz :-%," --format lvgl -o montserrat_medium_12.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575
Pour lancer avec qemu:
idf.py qemu --graphics --qemu-extra-args "-m 8M -global driver=ssi_psram,property=is_octal,value=true" monitor

8647
compile_commands.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.16)
idf_component_register(SRCS "RemindMe.c"
INCLUDE_DIRS "include"
REQUIRES json spiffs)

View File

@ -0,0 +1,216 @@
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "cJSON.h"
#include "esp_spiffs.h"
#include "RemindMe.h"
#include <time.h>
static const char *TAG = "JSON_READER";
static void copy_json_string(cJSON *item,
const char *key,
char *dst,
size_t dst_size)
{
cJSON *v = cJSON_GetObjectItem(item, key);
if (cJSON_IsString(v) && v->valuestring)
{
strncpy(dst, v->valuestring, dst_size - 1);
dst[dst_size - 1] = '\0';
}
}
static RemindMeEvent *get_events_from_file(const char *filepath, int *count)
{
*count = 0;
FILE *f = fopen(filepath, "r");
if (!f)
{
ESP_LOGE(TAG, "Impossible d'ouvrir le fichier");
return NULL;
}
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
char *json_string = malloc(size + 1);
if (!json_string)
{
fclose(f);
return NULL;
}
fread(json_string, 1, size, f);
fclose(f);
json_string[size] = 0;
cJSON *json = cJSON_Parse(json_string);
free(json_string);
if (!cJSON_IsArray(json))
{
cJSON_Delete(json);
return NULL;
}
int n = cJSON_GetArraySize(json);
if (n == 0)
{
cJSON_Delete(json);
return NULL;
}
RemindMeEvent *events = calloc(n, sizeof(RemindMeEvent));
if (!events)
{
cJSON_Delete(json);
return NULL;
}
for (int i = 0; i < n; i++)
{
cJSON *item = cJSON_GetArrayItem(json, i);
copy_json_string(item, "evenement", events[i].evenement, sizeof(events[i].evenement));
copy_json_string(item, "affichage", events[i].affichage, sizeof(events[i].affichage));
copy_json_string(item, "date", events[i].date, sizeof(events[i].date));
copy_json_string(item, "type", events[i].type, sizeof(events[i].type));
}
cJSON_Delete(json);
*count = n;
return events;
}
static void read_json_file(const char *filepath, cJSON **root)
{
FILE *f = fopen(filepath, "r");
if (!f)
{
ESP_LOGE(TAG, "Impossible d'ouvrir le fichier");
return;
}
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
char *json_string = malloc(size + 1);
if (!json_string)
{
fclose(f);
return;
}
fread(json_string, 1, size, f);
fclose(f);
json_string[size] = 0;
*root = cJSON_Parse(json_string);
free(json_string);
}
/**
* Parse une date au format "YYYY-MM-DD" et retourne le timestamp
*/
time_t parse_date(const char *date_str)
{
struct tm tm = {0};
// Parser la date (format: YYYY-MM-DD)
sscanf(date_str, "%d-%d-%d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday);
tm.tm_year -= 1900; // Années depuis 1900
tm.tm_mon -= 1; // Mois de 0 à 11
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
return mktime(&tm);
}
/**
* Calcule le nombre de jours entre maintenant et la date donnée
* Retourne un nombre négatif si la date est passée
*/
int days_until(const char *date_str)
{
// Obtenir l'heure actuelle
time_t now;
time(&now);
// Parser la date cible
time_t target = parse_date(date_str);
// Calculer la différence en secondes
double diff_seconds = difftime(target, now);
// Convertir en jours (arrondi)
int days = (int)(diff_seconds / (60 * 60 * 24));
return days;
}
RemindMeEvent *get_events(int *count)
{
RemindMeEvent *evts = get_events_from_file(
"/spiffs/events.json",
count);
for (size_t i = 0; i < *count; i++)
{
sprintf(evts[i].affichage, evts[i].affichage, days_until(evts[i].date));
}
return evts;
}
esp_err_t events_save_atomic(char *eventsJson)
{
FILE *f = fopen("/spiffs/events.tmp", "w");
if (!f)
goto error;
fwrite(eventsJson, 1, strlen(eventsJson), f);
fclose(f);
rename("/spiffs/events.json", "/spiffs/events.bak");
rename("/spiffs/events.tmp", "/spiffs/events.json");
//unlink("/spiffs/events.bak");
free(eventsJson);
return ESP_OK;
error:
free(eventsJson);
return ESP_FAIL;
}
void add_event(RemindMeEvent e){
int count=0;
cJSON *root = cJSON_CreateObject();
read_json_file("/spiffs/events.json", &root);
printf("%s","####################### AVANT\n");
//printf("%s\n",cJSON_Print(root));
if (!cJSON_IsArray(root))
{
ESP_LOGE(TAG, "'root' n'est pas un tableau");
return;
}else{
cJSON *new_event = cJSON_CreateObject();
if (!new_event)
return;
cJSON_AddStringToObject(new_event, "evenement", e.evenement);
cJSON_AddStringToObject(new_event, "affichage", e.affichage);
cJSON_AddStringToObject(new_event, "date", e.date);
cJSON_AddStringToObject(new_event, "type", e.type);
cJSON_AddItemToArray(root, new_event);
}
printf("%s", "####################### APRES\n");
//printf("%s\n", cJSON_Print(root));
char *eventsJson=cJSON_Print(root);
events_save_atomic(eventsJson);
}

View File

@ -0,0 +1,6 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: '>=4.1.0'

View File

@ -0,0 +1,19 @@
#pragma once
typedef struct
{
char evenement[64];
char affichage[128];
char date[32];
char type[40];
} RemindMeEvent;
/**
* Charge les événements depuis le fichier JSON
* @param count (out) nombre d'événements chargés
* @return pointeur vers tableau d'événements ou NULL en cas d'erreur
*
* L'appelant doit libérer la mémoire avec free()
*/
RemindMeEvent *get_events(int *count);
void add_event();

View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
list(APPEND EXTRA_COMPONENT_DIRS
../../RemindMe
)
project(remindme_host_test)

View File

@ -0,0 +1,10 @@
dependencies:
idf:
source:
type: idf
version: 5.5.1
direct_dependencies:
- idf
manifest_hash: 2fc18f414627b3fc737adcef5ecbfa3a4f7cff55fd5f96a20734c8d5302b79ed
target: linux
version: 2.0.0

View File

@ -0,0 +1,4 @@
idf_component_register(
SRCS "main.c"
REQUIRES RemindMe
)

View File

@ -0,0 +1,28 @@
#include "RemindMe.h"
#include "esp_log.h"
int app_main(int argc, char *argv[])
{
int count=0;
RemindMeEvent *events= get_events(&count);
if (!events)
{
ESP_LOGE("test", "Aucun événement chargé");
return 0;
} // Parcourir tous les événements
for (int i = 0; i < count; i++)
{
ESP_LOGI("test", "%s", events[i].affichage);
}
RemindMeEvent e = {
.affichage = "Test dans %d jours",
.date="2026-12-31",
.type="remaining_days",
.evenement="test"
};
add_event(e);
return 0;
}

View File

@ -0,0 +1,9 @@
#include "unity.h"
#include "RemindMe.h"
TEST_CASE("Test lecture JSON", "[RemindMe]")
{
Event event = {0};
esp_err_t ret = read_json_file("/spiffs/test.json", &event);
TEST_ASSERT_EQUAL(ESP_OK, ret);
}

View File

@ -0,0 +1,37 @@
{
"configurations": [
{
"name": "ESP-IDF",
"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/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**"
],
"defines": ["LV_CONF_SKIP"],
"browse": {
"path": [
"${config:idf.espIdfPath}/components",
"${config:idf.espIdfPathWin}/components",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
},
{
"name": "linux-host",
"includePath": [
"${workspaceFolder}/**"
],
"defines": ["LV_CONF_SKIP"],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

View File

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "cppdbg",
"request": "launch",
"name": "Eclipse CDT GDB Adapter",
"program": "${workspaceFolder}/test_host/build/nvs_host_test.elf",
"cwd": "${workspaceFolder}/test_host",
"linux": {
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb"
},
}
],
}

View File

@ -0,0 +1,9 @@
{
"idf.pythonInstallPath": "/usr/bin/python3",
"files.associations": {
"model.h": "c",
"lvgl.h": "c",
"lv_init.h": "c",
"lv_conf_internal.h": "c"
}
}

View File

@ -0,0 +1,50 @@
include(${CMAKE_CURRENT_LIST_DIR}/fonts_symbols.cmake)
string(JOIN "," LVGL_SYMBOLS ${LVGL_SYMBOLS_CLASSIQUES})
message(STATUS "LVGL SYMBOL RANGE = ${LVGL_SYMBOLS}")
function (make_font fontName fileName fontSize)
execute_process(COMMAND podman run -v ${PROJECT_DIR}/components/domotic_display/fonts:/app -w /app lvfontconv lv_font_conv --bpp 4 --size ${fontSize} --no-compress --font ${fontName}.ttf --symbols "0123456789.°àéèêëûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz %,'!? ():/-" --format lvgl -o ${fileName}_${fontSize}.c --font fa-solid-900.ttf --range ${LVGL_SYMBOLS})
endfunction()
make_font(Montserrat-Medium montserrat_medium 12 )
make_font(Montserrat-Medium montserrat_medium 18)
make_font(Montserrat-Medium montserrat_medium 24)
make_font(Roboto-Medium roboto_medium 36)
make_font(Roboto-Medium roboto_medium 72)
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 36 --no-compress --font Roboto-Medium.ttf --symbols "0123456789.°àéèûCABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz %,'():ê/-" --format lvgl -o roboto_medium_36.c --font fa-solid-900.ttf --range 61461,0xf0c2,0xf575)
#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)
if(${IDF_TARGET} STREQUAL "esp32p4" OR ${IDF_TARGET} STREQUAL "esp32s3")
#esp32_p4_function_ev_board
idf_component_register(SRC_DIRS . fonts
INCLUDE_DIRS "include"
REQUIRES ${comps} esp_lvgl_port esp32_p4_function_ev_board )
target_compile_options(${COMPONENT_LIB} PUBLIC -DLV_LVGL_H_INCLUDE_SIMPLE)
lvgl_port_create_c_image("images/wifi_ok.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/wifi_ko.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/mqtt_ok.png" "images/" "AUTO" "NONE")
lvgl_port_create_c_image("images/mqtt_ko.png" "images/" "ARGB8888" "NONE")
lvgl_port_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"
REQUIRES ${comps})
message("Including SDL2 support")
find_package(SDL2 REQUIRED)
target_link_libraries(${COMPONENT_LIB} PUBLIC
-Wl,--no-as-needed
SDL2
-Wl,--as-needed
)
target_compile_options(${COMPONENT_LIB} PUBLIC -DLV_LVGL_H_INCLUDE_SIMPLE)
endif()

View File

@ -0,0 +1,7 @@
#include <stdio.h>
#include "domotic_display.h"
void func(void)
{
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
# Symboles perso
# --- Weather ---
set(MY_SYMBOL_CLOUD 0xf0c2) # cloud | UTF-8: "\xEF\x83\x82"
set(MY_SYMBOL_CLOUD_SUN 0xf575) # cloud-sun | UTF-8: "\xEF\x95\xB5"
# --- Navigation ---
set(MY_SYMBOL_UP 0xf077) # chevron-up | UTF-8: "\xEF\x81\xB7"
set(MY_SYMBOL_DOWN 0xf078) # chevron-down | UTF-8: "\xEF\x81\xB8"
# --- Sensors ---
set(MY_SYMBOL_THERMOMETER 0xf2ca) # thermometer | UTF-8: "\xEF\x89\xBA"
set(MY_SYMBOL_MESSAGE 0xf27a) # message | UTF-8: "\xEF\x89\xBA"
# --- Location / House ---
set(MY_THERMOMETER_IN_HOUSE 0xe1b0) # house-user | UTF-8: "\xEE\x86\xB0"
set(MY_THERMOMETER_OUT_HOUSE 0xe1b0) # house-user | UTF-8: "\xEE\x86\xB0"
# ======================================
# LVGL symbols (FontAwesome solid mapped)
# ======================================
# --- Base UI ---
set(LV_SYMBOL_OK 0xf00c) # check
set(LV_SYMBOL_CLOSE 0xf00d) # times
set(LV_SYMBOL_POWER 0xf011) # power-off
set(LV_SYMBOL_SETTINGS 0xf013) # gear
set(LV_SYMBOL_HOME 0xf015) # home
set(LV_SYMBOL_DOWNLOAD 0xf019) # download
set(LV_SYMBOL_REFRESH 0xf021) # refresh
set(LV_SYMBOL_LOCK 0xf023) # lock
set(LV_SYMBOL_WIFI 0xf1eb) # wifi
set(LV_SYMBOL_BELL 0xf0f3) # bell
set(LV_SYMBOL_BATTERY_FULL 0xf240) # battery-full
set(LV_SYMBOL_BATTERY_3 0xf241) # battery-3/4
set(LV_SYMBOL_BATTERY_2 0xf242) # battery-1/2
set(LV_SYMBOL_BATTERY_1 0xf243) # battery-1/4
set(LV_SYMBOL_BATTERY_EMPTY 0xf244) # battery-empty
# --- Navigation ---
set(LV_SYMBOL_LEFT 0xf060) # arrow-left
set(LV_SYMBOL_RIGHT 0xf061) # arrow-right
set(LV_SYMBOL_UP 0xf062) # arrow-up
set(LV_SYMBOL_DOWN 0xf063) # arrow-down
set(LV_SYMBOL_NEXT 0xf061) # alias RIGHT
set(LV_SYMBOL_PREV 0xf060) # alias LEFT
# --- Media / Actions ---
set(LV_SYMBOL_PLAY 0xf04b) # play
set(LV_SYMBOL_PAUSE 0xf04c) # pause
set(LV_SYMBOL_STOP 0xf04d) # stop
set(LV_SYMBOL_EJECT 0xf052) # eject
set(LV_SYMBOL_VOLUME_UP 0xf028)
set(LV_SYMBOL_VOLUME_DOWN 0xf027)
set(LV_SYMBOL_MUTE 0xf026)
# --- Information ---
set(LV_SYMBOL_EYE_OPEN 0xf06e)
set(LV_SYMBOL_EYE_CLOSE 0xf070)
set(LV_SYMBOL_WARNING 0xf071)
set(LV_SYMBOL_INFO 0xf05a)
set(LV_SYMBOL_QUESTION 0xf128)
# --- Time / Status ---
set(LV_SYMBOL_CLOCK 0xf017)
set(LV_SYMBOL_CALENDAR 0xf073)
# --- List of symbols used for font generation ---
set(LVGL_SYMBOLS_CLASSIQUES
${LV_SYMBOL_OK}
${LV_SYMBOL_CLOSE}
${LV_SYMBOL_POWER}
${LV_SYMBOL_SETTINGS}
${LV_SYMBOL_HOME}
${LV_SYMBOL_DOWNLOAD}
${LV_SYMBOL_REFRESH}
${LV_SYMBOL_LOCK}
${LV_SYMBOL_WIFI}
${LV_SYMBOL_BELL}
${LV_SYMBOL_BATTERY_FULL}
${LV_SYMBOL_BATTERY_3}
${LV_SYMBOL_BATTERY_2}
${LV_SYMBOL_BATTERY_1}
${LV_SYMBOL_BATTERY_EMPTY}
${LV_SYMBOL_LEFT}
${LV_SYMBOL_RIGHT}
${LV_SYMBOL_UP}
${LV_SYMBOL_DOWN}
${LV_SYMBOL_PLAY}
${LV_SYMBOL_PAUSE}
${LV_SYMBOL_STOP}
${LV_SYMBOL_VOLUME_UP}
${LV_SYMBOL_VOLUME_DOWN}
${LV_SYMBOL_MUTE}
${LV_SYMBOL_EYE_OPEN}
${LV_SYMBOL_EYE_CLOSE}
${LV_SYMBOL_WARNING}
${LV_SYMBOL_INFO}
${LV_SYMBOL_QUESTION}
${LV_SYMBOL_CLOCK}
${LV_SYMBOL_CALENDAR}
${MY_SYMBOL_CLOUD}
${MY_SYMBOL_CLOUD_SUN}
${MY_SYMBOL_UP}
${MY_SYMBOL_DOWN}
${MY_SYMBOL_THERMOMETER}
${MY_SYMBOL_MESSAGE}
${MY_THERMOMETER_IN_HOUSE}
)

View File

@ -0,0 +1,28 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: '>=4.1.0'
# # Put list of dependencies here
# # For components maintained by Espressif:
# component: "~1.0.0"
# # For 3rd party components:
# username/component: ">=1.0.0,<2.0.0"
# username2/component2:
# version: "~1.0.0"
# # For transient dependencies `public` flag can be set.
# # `public` flag doesn't have an effect dependencies of the `main` component.
# # All dependencies of `main` are public by default.
# public: true
espressif/esp_lvgl_port:
rules:
- if: target in ["esp32p4","esp32, "esp32s3"]
version: ^2.7.0
lvgl/lvgl:
rules:
- if: target in ["linux"]
version: 9.4.0
espressif/esp_lcd_qemu_rgb:
rules:
- if: target in ["esp32, "esp32s3"]
version: ^1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
// ihm_gateway.c
#include "ihm_gateway.h"
#include "ihm.h"
#include <stdio.h>
#include <stdlib.h>
#include "platform_detect.h"
#include "cJSON.h"
#include "esp_log.h"
static const char *TAG = "IHM_GW";
static QueueHandle_t xIHMEventQueue = NULL;
QueueHandle_t getIHMQueueHandle(void) {
return xIHMEventQueue;
}
void ihm_gateway_init(void) {
if (!xIHMEventQueue) {
xIHMEventQueue = xQueueCreate(32, sizeof(xIHMEvent_t *));
}
}
void ihm_gateway_post_event(xIHMEvent_t *evt) {
if (!xIHMEventQueue) return;
if (platform_is_pc()) {
xQueueSend(xIHMEventQueue, &evt, 0); // non bloquant sur PC
} else {
xQueueSend(xIHMEventQueue, &evt, portMAX_DELAY); // bloquant ESP32
}
}
extern lv_subject_t wifiStatus;
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)
#else
while (xQueueReceive(xIHMEventQueue, &evt, pdMS_TO_TICKS(10)) == pdTRUE)
#endif
{
if (!evt) return;
UBaseType_t pending = uxQueueMessagesWaiting(xIHMEventQueue);
ESP_LOGE(TAG,"Evt recu %d. La queue comporte %d éléments à traiter", evt->eEventType, pending);
lv_async_call(traiteEvt, evt);
}
}
void traiteEvt(void *arg)
{
xIHMEvent_t *evt = (xIHMEvent_t *)arg;
switch (evt->eEventType)
{
case IHM_EVT_WIFI_STATUS:
lv_subject_set_int(&wifiStatus, *(bool *)evt->pvData);
break;
case IHM_EVT_TIME_SETTED:
draw_time(evt->pvData);
break;
case IHM_EVT_OTA_STARTED:
app_ota_display();
break;
case IHM_EVT_HUMID_TEMP:
draw_temp((char *)evt->pvData);
break;
case IHM_EVT_PUISSANCE_EMISE:
{
int val = *(int *)evt->pvData;
// if(val == 0) lv_chart_set_next_value(myChart, ser, LV_CHART_POINT_NONE);
// else lv_chart_set_next_value(myChart, ser, val);
break;
}
case IHM_EVT_ETAT_MACHINE:
{
char *etatMachine = evt->pvData;
cJSON *root = cJSON_Parse(etatMachine);
bool enRoute = cJSON_GetObjectItem(root, "state")->valueint;
int timestamp = cJSON_GetObjectItem(root, "timestamp")->valueint;
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:
{
float hauteur = *(float *)evt->pvData;
// lv_label_set_text_fmt(lblHauteurCuve, "%.0f cm", hauteur);
break;
}
default:
ESP_LOGE(TAG, "Evt inconnu");
break;
}
// Nettoyage mémoire sécurisé
if (evt->bNeedToFreeData && evt->pvData)
free(evt->pvData);
free(evt);
ESP_LOGV(TAG, "Evt traité");
}

View File

Before

Width:  |  Height:  |  Size: 654 B

After

Width:  |  Height:  |  Size: 654 B

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 483 B

After

Width:  |  Height:  |  Size: 483 B

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 372 B

After

Width:  |  Height:  |  Size: 372 B

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

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