Compare commits
30 Commits
before_big
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f60e9c38c | |||
| 67e6d1cfaa | |||
| 77e8116d54 | |||
| 0de95c5386 | |||
| f871b76ca2 | |||
| 9d31148d21 | |||
| 9293b5fdc6 | |||
| bce9f03eb4 | |||
| 9217397d7d | |||
| b7552e15ce | |||
| 434ede2480 | |||
| 8e868da692 | |||
| e1640f4ad9 | |||
| a41945bcef | |||
| 7316561482 | |||
| ae99b85932 | |||
| 5ac20b78fa | |||
| fc5f46d3fd | |||
| f5419e85aa | |||
| 4658da4adb | |||
| f32cad2987 | |||
| 1d91bac9e9 | |||
| c87cc69b9e | |||
| 6f338020ab | |||
| d9ac74a595 | |||
| 5bd2ef288a | |||
| 28c5870ca6 | |||
| 2da4a8f94b | |||
| f29fee752f | |||
| 3a791daa47 |
13
.devcontainer/Dockerfile
Normal 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"]
|
||||||
21
.devcontainer/devcontainer.json
Normal 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
@ -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
|
||||||
|
|||||||
2
.vscode/c_cpp_properties.json
vendored
@ -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": "/home/marc/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc",
|
||||||
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
|
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${config:idf.espIdfPath}/components/**",
|
"${config:idf.espIdfPath}/components/**",
|
||||||
|
|||||||
131
.vscode/launch.json
vendored
@ -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/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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
18
.vscode/settings.json
vendored
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"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": "esp32p4"
|
||||||
},
|
},
|
||||||
@ -105,7 +105,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
@ -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",
|
||||||
|
|||||||
169
CMakeLists.txt
@ -1,28 +1,155 @@
|
|||||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
# --------------------------------------------------
|
||||||
# in this exact order for cmake to work correctly
|
# 1. Version de base (version.txt)
|
||||||
cmake_minimum_required(VERSION 3.16)
|
# --------------------------------------------------
|
||||||
|
file(READ "${CMAKE_SOURCE_DIR}/version.txt" FW_VERSION)
|
||||||
|
string(STRIP "${FW_VERSION}" FW_VERSION)
|
||||||
|
|
||||||
# "Trim" the build. Include the minimal set of components, main and anything it depends on.
|
# --------------------------------------------------
|
||||||
set(COMPONENTS main)
|
# 2. Détection git + branche
|
||||||
|
# --------------------------------------------------
|
||||||
|
find_package(Git)
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
set(GIT_BRANCH "")
|
||||||
|
set(IS_GIT_REPO OFF)
|
||||||
|
|
||||||
if(${IDF_TARGET} STREQUAL "esp32p4")
|
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||||
set(EXTRA_COMPONENT_DIRS
|
set(IS_GIT_REPO ON)
|
||||||
/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
|
execute_process(
|
||||||
$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs
|
COMMAND git rev-parse --abbrev-ref HEAD
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/FreeRTOS
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
"/home/marc/esp-protocols/common_components/linux_compat"
|
OUTPUT_VARIABLE GIT_BRANCH
|
||||||
"/home/marc/esp-protocols/components/mdns/tests/host_test/components"
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(rgb_lcd)
|
# --------------------------------------------------
|
||||||
|
# 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}")
|
||||||
|
# -------------------------------------------------
|
||||||
|
# CONFIGURATION AVANT project() : uniquement CMake pur
|
||||||
|
# -------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
project(domotic)
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
# --- 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}'
|
||||||
|
)
|
||||||
|
|||||||
15
FreeRTOSConfig/FreeRTOSConfig.h
Normal 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
@ -0,0 +1,7 @@
|
|||||||
|
menu "Simulation options"
|
||||||
|
|
||||||
|
config SIMULATION_QEMU
|
||||||
|
bool "Build with QEMU simulation stubs"
|
||||||
|
default n
|
||||||
|
|
||||||
|
endmenu
|
||||||
@ -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
5
components/RemindMe/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
idf_component_register(SRCS "RemindMe.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
REQUIRES json spiffs)
|
||||||
216
components/RemindMe/RemindMe.c
Normal 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);
|
||||||
|
}
|
||||||
6
components/RemindMe/idf_component.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
## Required IDF version
|
||||||
|
idf:
|
||||||
|
version: '>=4.1.0'
|
||||||
|
|
||||||
19
components/RemindMe/include/RemindMe.h
Normal 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();
|
||||||
12
components/RemindMe/test/CMakeLists.txt
Normal 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)
|
||||||
10
components/RemindMe/test/dependencies.lock
Normal 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
|
||||||
4
components/RemindMe/test/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(
|
||||||
|
SRCS "main.c"
|
||||||
|
REQUIRES RemindMe
|
||||||
|
)
|
||||||
28
components/RemindMe/test/main/main.c
Normal 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;
|
||||||
|
}
|
||||||
9
components/RemindMe/test/test_RemindMe.c
Normal 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);
|
||||||
|
}
|
||||||
3
components/audio/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS "audio.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
REQUIRES esp32_p4_function_ev_board)
|
||||||
224
components/audio/audio.c
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "audio.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "bsp/esp-bsp.h"
|
||||||
|
|
||||||
|
/* Buffer for reading/writing to I2S driver. Same length as SPIFFS buffer and I2S buffer, for optimal read/write performance.
|
||||||
|
External SPI Flash -> SPIFFS buffer -> App buffer (RAM) -> I2S buffer (DMA) -> I2S peripheral.
|
||||||
|
*/
|
||||||
|
#define BUFFER_SIZE (1024)
|
||||||
|
#define DEFAULT_VOLUME (50)
|
||||||
|
|
||||||
|
/* Globals */
|
||||||
|
static const char *TAG = "audio";
|
||||||
|
TaskHandle_t audio_task_handle;
|
||||||
|
|
||||||
|
|
||||||
|
// Very simple WAV header, ignores most fields
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
uint8_t ignore_0[22];
|
||||||
|
uint16_t num_channels;
|
||||||
|
uint32_t sample_rate;
|
||||||
|
uint8_t ignore_1[6];
|
||||||
|
uint16_t bits_per_sample;
|
||||||
|
uint8_t ignore_2[4];
|
||||||
|
uint32_t data_size;
|
||||||
|
uint8_t data[];
|
||||||
|
} dumb_wav_header_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FILE *f;
|
||||||
|
uint32_t data_offset;
|
||||||
|
uint32_t data_size;
|
||||||
|
} wav_ctx_t;
|
||||||
|
#define AUDIO_CHUNK_SIZE 4096
|
||||||
|
|
||||||
|
bool wav_open(wav_ctx_t *ctx, const char *path)
|
||||||
|
{
|
||||||
|
ctx->f = fopen(path, "rb");
|
||||||
|
if (!ctx->f) return false;
|
||||||
|
|
||||||
|
/* Skip RIFF header */
|
||||||
|
fseek(ctx->f, 12, SEEK_SET);
|
||||||
|
|
||||||
|
uint32_t chunk_id, chunk_size;
|
||||||
|
|
||||||
|
while (fread(&chunk_id, 4, 1, ctx->f))
|
||||||
|
{
|
||||||
|
fread(&chunk_size, 4, 1, ctx->f);
|
||||||
|
|
||||||
|
if (chunk_id == 0x61746164) { // "data"
|
||||||
|
ctx->data_offset = ftell(ctx->f);
|
||||||
|
ctx->data_size = chunk_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(ctx->f, chunk_size, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ctx->f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void rewind_wav(wav_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
fseek(ctx->f, ctx->data_offset, SEEK_SET);
|
||||||
|
}
|
||||||
|
#define AUDIO_CHUNK_SIZE 4096
|
||||||
|
static void audio_task(void *arg)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG,"Audio task");
|
||||||
|
|
||||||
|
esp_codec_dev_handle_t spk_codec_dev = bsp_audio_codec_speaker_init();
|
||||||
|
assert(spk_codec_dev);
|
||||||
|
|
||||||
|
esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
|
||||||
|
esp_codec_dev_set_out_mute(spk_codec_dev, false); // 🔑 CRITIQUE
|
||||||
|
|
||||||
|
const char *play_filename = "/littlefs/sounds/mixkit-clear-announce-tones-2861.wav";
|
||||||
|
|
||||||
|
uint8_t *wav_bytes = malloc(BUFFER_SIZE);
|
||||||
|
assert(wav_bytes != NULL);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* ⏸️ Attend PLAY */
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
bool stop_requested = false;
|
||||||
|
|
||||||
|
while (!stop_requested) {
|
||||||
|
ESP_LOGI(TAG,"On joue !");
|
||||||
|
|
||||||
|
FILE *play_file = fopen(play_filename, "rb");
|
||||||
|
if (!play_file) {
|
||||||
|
ESP_LOGE(TAG,"File not found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dumb_wav_header_t wav_header;
|
||||||
|
if (fread(&wav_header, 1, sizeof(wav_header), play_file) != sizeof(wav_header)) {
|
||||||
|
ESP_LOGE(TAG,"Header read failed");
|
||||||
|
fclose(play_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_codec_dev_sample_info_t fs = {
|
||||||
|
.sample_rate = wav_header.sample_rate,
|
||||||
|
.channel = wav_header.num_channels,
|
||||||
|
.bits_per_sample = wav_header.bits_per_sample,
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_codec_dev_open(spk_codec_dev, &fs));
|
||||||
|
|
||||||
|
uint32_t bytes_sent = 0;
|
||||||
|
while (bytes_sent < wav_header.data_size) {
|
||||||
|
size_t bytes_read = fread(wav_bytes, 1, BUFFER_SIZE, play_file);
|
||||||
|
if (bytes_read == 0) break;
|
||||||
|
|
||||||
|
esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read);
|
||||||
|
bytes_sent += bytes_read;
|
||||||
|
|
||||||
|
vTaskDelay(1); // watchdog + scheduler
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_codec_dev_close(spk_codec_dev);
|
||||||
|
fclose(play_file);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG,"Fin du fichier");
|
||||||
|
|
||||||
|
if (ulTaskNotifyTake(pdTRUE, 0) > 0) {
|
||||||
|
stop_requested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(wav_bytes);
|
||||||
|
}
|
||||||
|
static void audio_task__(void *arg)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG,"Audio task");
|
||||||
|
esp_codec_dev_handle_t spk_codec_dev = bsp_audio_codec_speaker_init();
|
||||||
|
assert(spk_codec_dev);
|
||||||
|
esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
|
||||||
|
|
||||||
|
/* Pointer to a file that is going to be played */
|
||||||
|
const char music_filename[] = "/littlefs/sounds/mixkit-clear-announce-tones-2861.wav";
|
||||||
|
const char *play_filename = music_filename;
|
||||||
|
|
||||||
|
int16_t *wav_bytes = malloc(BUFFER_SIZE);
|
||||||
|
assert(wav_bytes != NULL);
|
||||||
|
|
||||||
|
bool stop_requested = false;
|
||||||
|
|
||||||
|
while (!stop_requested){
|
||||||
|
ESP_LOGE(TAG,"On joue !");
|
||||||
|
/* Open WAV file */
|
||||||
|
ESP_LOGI(TAG, "Playing file %s", play_filename);
|
||||||
|
FILE *play_file = fopen(play_filename, "rb");
|
||||||
|
if (play_file == NULL) {
|
||||||
|
ESP_LOGW(TAG, "%s file does not exist!", play_filename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read WAV header file */
|
||||||
|
dumb_wav_header_t wav_header;
|
||||||
|
if (fread((void *)&wav_header, 1, sizeof(wav_header), play_file) != sizeof(wav_header)) {
|
||||||
|
ESP_LOGW(TAG, "Error in reading file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//ESP_LOGI(TAG, "Number of channels: %" PRIu16 "", wav_header.num_channels);
|
||||||
|
//ESP_LOGI(TAG, "Bits per sample: %" PRIu16 "", wav_header.bits_per_sample);
|
||||||
|
//ESP_LOGI(TAG, "Sample rate: %" PRIu32 "", wav_header.sample_rate);
|
||||||
|
//ESP_LOGI(TAG, "Data size: %" PRIu32 "", wav_header.data_size);
|
||||||
|
|
||||||
|
esp_codec_dev_sample_info_t fs = {
|
||||||
|
.sample_rate = wav_header.sample_rate,
|
||||||
|
.channel = wav_header.num_channels,
|
||||||
|
.bits_per_sample = wav_header.bits_per_sample,
|
||||||
|
};
|
||||||
|
esp_codec_dev_open(spk_codec_dev, &fs);
|
||||||
|
|
||||||
|
uint32_t bytes_send_to_i2s = 0;
|
||||||
|
while (bytes_send_to_i2s < wav_header.data_size) {
|
||||||
|
/* Get data from SPIFFS and send it to codec */
|
||||||
|
size_t bytes_read_from_spiffs = fread(wav_bytes, 1, BUFFER_SIZE, play_file);
|
||||||
|
esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read_from_spiffs);
|
||||||
|
bytes_send_to_i2s += bytes_read_from_spiffs;
|
||||||
|
|
||||||
|
/* ⭐ LIGNE CRITIQUE ⭐ */
|
||||||
|
vTaskDelay(1); // laisse respirer IDLE + watchdog
|
||||||
|
}
|
||||||
|
ESP_LOGE(TAG,"On a fini le fichier");
|
||||||
|
|
||||||
|
fclose(play_file);
|
||||||
|
esp_codec_dev_close(spk_codec_dev);
|
||||||
|
if(ulTaskNotifyTake(pdTRUE, 0)>0){
|
||||||
|
stop_requested=true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
free(wav_bytes);
|
||||||
|
vTaskSuspend(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void playSound(void)
|
||||||
|
{
|
||||||
|
if(audio_task_handle==NULL){
|
||||||
|
BaseType_t ret = xTaskCreate(audio_task, "audio_task", 4096, NULL, 6, &audio_task_handle);
|
||||||
|
assert(ret == pdPASS);
|
||||||
|
}
|
||||||
|
xTaskNotifyGive(audio_task_handle);
|
||||||
|
}
|
||||||
|
void stopSound(void){
|
||||||
|
if (audio_task_handle) {
|
||||||
|
xTaskNotifyGive(audio_task_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
4
components/audio/include/audio.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
void playSound(void);
|
||||||
|
|
||||||
|
void stopSound(void);
|
||||||
37
components/domotic_display/.vscode/c_cpp_properties.json
vendored
Normal 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
|
||||||
|
}
|
||||||
20
components/domotic_display/.vscode/launch.json
vendored
Normal 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"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
}
|
||||||
9
components/domotic_display/.vscode/settings.json
vendored
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
49
components/domotic_display/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
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 washingMachineState)
|
||||||
|
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/")
|
||||||
|
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()
|
||||||
|
|
||||||
7
components/domotic_display/domotic_display.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "domotic_display.h"
|
||||||
|
|
||||||
|
void func(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
BIN
components/domotic_display/fonts/Roboto-Medium.ttf
Normal file
BIN
components/domotic_display/fonts/Super_Malibu.ttf
Normal file
BIN
components/domotic_display/fonts/Vlump.ttf
Normal file
1536
components/domotic_display/fonts/montserrat_medium_12.c
Normal file
2236
components/domotic_display/fonts/montserrat_medium_18.c
Normal file
3140
components/domotic_display/fonts/montserrat_medium_24.c
Normal file
5343
components/domotic_display/fonts/roboto_medium_36.c
Normal file
19194
components/domotic_display/fonts/roboto_medium_72.c
Normal file
26814
components/domotic_display/fonts/super_malibu_80.c
Normal file
22874
components/domotic_display/fonts/super_malibu_96.c
Normal file
60223
components/domotic_display/fonts/vlump_96.c
Normal file
110
components/domotic_display/fonts_symbols.cmake
Normal 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}
|
||||||
|
)
|
||||||
28
components/domotic_display/idf_component.yml
Normal 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
|
||||||
2067
components/domotic_display/ihm.c
Normal file
154
components/domotic_display/ihm_gateway.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// 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"
|
||||||
|
#include "washingMachineState.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;
|
||||||
|
|
||||||
|
static xIHMEvent_t *evt = NULL;
|
||||||
|
|
||||||
|
void ihm_gateway_process_queue(void) {
|
||||||
|
if (!xIHMEventQueue) return;
|
||||||
|
|
||||||
|
|
||||||
|
#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_LOGV(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);
|
||||||
|
evt->bNeedToFreeData=false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IHM_EVT_OTA_STARTED:
|
||||||
|
app_ota_display();
|
||||||
|
break;
|
||||||
|
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IHM_EVT_MACHINE_TERMINEE:
|
||||||
|
{
|
||||||
|
draw_minuteurStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
case IHM_EVT_HAUTEUR_CUVE:
|
||||||
|
{
|
||||||
|
float hauteur = *(float *)evt->pvData;
|
||||||
|
// lv_label_set_text_fmt(lblHauteurCuve, "%.0f cm", hauteur);
|
||||||
|
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");
|
||||||
|
free(evt->pvData);
|
||||||
|
}
|
||||||
|
free(evt);
|
||||||
|
ESP_LOGV(TAG, "Evt traité");
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 654 B After Width: | Height: | Size: 654 B |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 483 B After Width: | Height: | Size: 483 B |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 372 B After Width: | Height: | Size: 372 B |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |