fonctionnel

This commit is contained in:
Marc 2024-10-25 21:38:47 +02:00
parent 7f2a5633d5
commit 8c796dbb9d
38 changed files with 3010 additions and 1268 deletions

159
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,159 @@
# Copy paste of https://github.com/espressif/esp-idf/blob/master/tools/docker/Dockerfile
# but with ubuntu image downgraded.
# You must download https://github.com/espressif/esp-idf/blob/master/tools/docker/entrypoint.sh
# and place it in the .devcontainer directory.
#FROM ubuntu:24.04
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN : \
&& apt-get update \
&& apt-get install -y \
apt-utils \
bison \
bzip2 \
ca-certificates \
ccache \
check \
curl \
flex \
git \
git-lfs \
gperf \
lcov \
libbsd-dev \
libffi-dev \
libglib2.0-0 \
libncurses-dev \
libpixman-1-0 \
libsdl2-2.0-0 \
libslirp0 \
libusb-1.0-0-dev \
make \
ninja-build \
python3 \
python3-venv \
ruby \
unzip \
wget \
xz-utils \
zip \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* \
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 10 \
&& :
# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name.
# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id.
# It is possible to combine both, e.g.:
# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y
# IDF_CHECKOUT_REF=<some commit on release/vX.Y branch>.
# Use IDF_CLONE_SHALLOW=1 to perform shallow clone (i.e. --depth=1 --shallow-submodules)
# Use IDF_CLONE_SHALLOW_DEPTH=X to define the depth if IDF_CLONE_SHALLOW is used (i.e. --depth=X)
# Use IDF_INSTALL_TARGETS to install tools only for selected chip targets (CSV)
ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git
ARG IDF_CLONE_BRANCH_OR_TAG=master
ARG IDF_CHECKOUT_REF=
ARG IDF_CLONE_SHALLOW=
ARG IDF_CLONE_SHALLOW_DEPTH=1
ARG IDF_INSTALL_TARGETS=all
ENV IDF_PATH=/opt/esp/idf
ENV IDF_TOOLS_PATH=/opt/esp
# install build essential needed for linux target apps, which is a preview target so it is installed with "all" only
RUN if [ "$IDF_INSTALL_TARGETS" = "all" ]; then \
apt-get update \
&& apt-get install -y build-essential \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* ; \
fi
RUN echo IDF_CHECKOUT_REF=$IDF_CHECKOUT_REF IDF_CLONE_BRANCH_OR_TAG=$IDF_CLONE_BRANCH_OR_TAG && \
git clone --recursive \
${IDF_CLONE_SHALLOW:+--depth=${IDF_CLONE_SHALLOW_DEPTH} --shallow-submodules} \
${IDF_CLONE_BRANCH_OR_TAG:+-b $IDF_CLONE_BRANCH_OR_TAG} \
$IDF_CLONE_URL $IDF_PATH && \
git config --system --add safe.directory $IDF_PATH && \
if [ -n "$IDF_CHECKOUT_REF" ]; then \
cd $IDF_PATH && \
if [ -n "$IDF_CLONE_SHALLOW" ]; then \
git fetch origin --depth=${IDF_CLONE_SHALLOW_DEPTH} --recurse-submodules ${IDF_CHECKOUT_REF}; \
fi && \
git checkout $IDF_CHECKOUT_REF && \
git submodule update --init --recursive; \
fi
# Install all the required tools
RUN : \
&& update-ca-certificates --fresh \
&& $IDF_PATH/tools/idf_tools.py --non-interactive install required --targets=${IDF_INSTALL_TARGETS} \
&& $IDF_PATH/tools/idf_tools.py --non-interactive install qemu* --targets=${IDF_INSTALL_TARGETS} \
&& $IDF_PATH/tools/idf_tools.py --non-interactive install cmake \
&& $IDF_PATH/tools/idf_tools.py --non-interactive install-python-env \
&& rm -rf $IDF_TOOLS_PATH/dist \
&& :
# Add get_idf as alias
RUN echo 'alias get_idf=". /opt/esp/idf/export.sh"' >> /root/.bashrc
# The constraint file has been downloaded and the right Python package versions installed. No need to check and
# download this at every invocation of the container.
ENV IDF_PYTHON_CHECK_CONSTRAINTS=no
# Ccache is installed, enable it by default
ENV IDF_CCACHE_ENABLE=1
COPY entrypoint.sh /opt/esp/entrypoint.sh
RUN chmod +x /opt/esp/entrypoint.sh
#Original file starts here
#FROM espressif/idf
#ARG DEBIAN_FRONTEND=nointeractive
ARG CONTAINER_USER=esp
ARG USER_UID=1050
ARG USER_GID=$USER_UID
RUN apt-get update \
&& apt install -y -q \
cmake \
git \
libglib2.0-0 \
libnuma1 \
libpixman-1-0 \
&& rm -rf /var/lib/apt/lists/*
# QEMU
ENV QEMU_REL=esp_develop_8.2.0_20240122
ENV QEMU_SHA256=e7c72ef5705ad1444d391711088c8717fc89f42e9bf6d1487f9c2a326b8cfa83
ENV QEMU_DIST=qemu-xtensa-softmmu-${QEMU_REL}-x86_64-linux-gnu.tar.xz
ENV QEMU_URL=https://github.com/espressif/qemu/releases/download/esp-develop-8.2.0-20240122/${QEMU_DIST}
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN wget --no-verbose ${QEMU_URL} \
&& echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \
&& tar -xf $QEMU_DIST -C /opt \
&& rm ${QEMU_DIST}
ENV PATH=/opt/qemu/bin:${PATH}
RUN groupadd --gid $USER_GID $CONTAINER_USER \
&& adduser --uid $USER_UID --gid $USER_GID --disabled-password --gecos "" ${CONTAINER_USER} \
&& usermod -a -G root $CONTAINER_USER && usermod -a -G dialout $CONTAINER_USER
RUN chmod -R 775 /opt/esp/python_env/
USER ${CONTAINER_USER}
ENV USER=${CONTAINER_USER}
WORKDIR /home/${CONTAINER_USER}
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,33 @@
{
"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"
]
},
"codespaces": {
"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"]
}

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -e
# IDF_GIT_SAFE_DIR has the same format as system PATH environment variable.
# All path specified in IDF_GIT_SAFE_DIR will be added to user's
# global git config as safe.directory paths. For more information
# see git-config manual page.
if [ -n "${IDF_GIT_SAFE_DIR+x}" ]
then
echo "Adding following directories into git's safe.directory"
echo "$IDF_GIT_SAFE_DIR" | tr ':' '\n' | while read -r dir
do
git config --global --add safe.directory "$dir"
echo " $dir"
done
fi
. $IDF_PATH/export.sh
exec "$@"

View File

@ -1,20 +1,22 @@
{ {
"configurations": [ "configurations": [
{ {
"name": "Win32", "name": "ESP-IDF",
"compilerPath": "${config:idf.toolsPathWin}\\tools\\xtensa-esp-elf\\esp-13.2.0_20230928\\xtensa-esp-elf\\bin\\xtensa-esp32s3-elf-gcc.exe",
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [ "includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**" "${workspaceFolder}/**"
], ],
"defines": [ "browse": {
"_DEBUG", "path": [
"UNICODE", "${config:idf.espIdfPath}/components",
"_UNICODE" "${config:idf.espIdfPathWin}/components",
], "${workspaceFolder}"
"compilerPath": "C:\\msys64\\mingw64\\bin\\gcc.exe", ],
"cStandard": "c17", "limitSymbolsToIncludedHeaders": true
"cppStandard": "gnu++17", }
"intelliSenseMode": "windows-gcc-x64",
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
} }
], ],
"version": 4 "version": 4

15
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
},
{
"type": "espidf",
"name": "Launch",
"request": "launch"
}
]
}

36
.vscode/settings.json vendored
View File

@ -1,34 +1,12 @@
{ {
"idf.adapterTargetName": "esp32s3", "idf.adapterTargetName": "esp32s3",
"idf.openOcdConfigs": [
"board/esp32s3-builtin.cfg"
],
"idf.flashType": "UART", "idf.flashType": "UART",
"idf.portWin": "COM12", "idf.portWin": "COM11",
"files.associations": { "files.associations": {
"string_view": "c", "wifi.h": "c",
"regex": "c", "esp_log.h": "c",
"bitset": "c", "esp_wifi.h": "c",
"chrono": "c", "esp_lvgl_port.h": "c",
"random": "c", "mqtt.h": "c"
"limits": "c", }
"string": "c",
"format": "c",
"*.tcc": "c",
"ctime": "c",
"iomanip": "c",
"task.h": "c",
"semaphore": "c",
"typeinfo": "c",
"freertos.h": "c",
"esp_err.h": "c",
"esp_lcd_panel_rgb.h": "c",
"esp_lcd_touch_gt911.h": "c",
"esp_lcd_panel_io.h": "c",
"esp_check.h": "c",
"compare": "c",
"cstdint": "c",
"esp_sntp.h": "c"
},
"search.useIgnoreFiles": false
} }

View File

@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "ESP-IDF",
"compilerPath": "C:\\espidftools\\tools\\xtensa-esp-elf\\esp-13.2.0_20230928\\xtensa-esp-elf\\bin\\xtensa-esp32s3-elf-gcc.exe",
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**"
],
"browse": {
"path": [
"${config:idf.espIdfPath}/components",
"${config:idf.espIdfPathWin}/components",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
}
],
"version": 4
}

90
.vscode__/launch.json Normal file
View File

@ -0,0 +1,90 @@
{
// 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": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
},
{
"type": "gdb",
"request": "attach",
"name": "NativeDebug",
"target": "extended-remote :3333",
"executable": "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf",
"gdbpath": "${command:espIdf.getToolchainGdb}",
"cwd": "${workspaceRoot}",
"autorun": [
"mon reset halt",
"maintenance flush register-cache",
"thb app_main"
]
},
{
"name": "GDB",
"type": "cppdbg",
"request": "launch",
"MIMode": "gdb",
"miDebuggerPath": "${command:espIdf.getToolchainGdb}",
"requireExactSource": true,
"stopAtEntry": true,
"program": "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf",
"windows": {
"program": "${workspaceFolder}\\build\\${command:espIdf.getProjectName}.elf"
},
"cwd": "${workspaceFolder}",
"setupCommands": [
{ "text": "set remotetimeout 20" },
],
"postRemoteConnectCommands": [
{ "text": "mon reset halt" },
{ "text": "maintenance flush register-cache"},
],
"externalConsole": false,
"logging": {
"engineLogging": true
}
},
{
"type": "espidf",
"name": "Launch",
"request": "launch",
"debugPort": 9998,
"logLevel": 2,
"mode": "manual",
"verifyAppBinBeforeDebug": false,
"tmoScaleFactor": 1,
"initGdbCommands": [
"target remote :3333",
"set remotetimeout 20",
"symbol-file /path/to/program.elf",
"mon reset halt",
"maintenance flush register-cache",
"thb app_main"
],
"env": {
"CUSTOM_ENV_VAR": "SOME_VALUE"
}
},
{
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT Remote",
"program": "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf",
"initCommands": [
"set remotetimeout 20",
"set remote hardware-watchpoint-limit 2",
"mon reset halt",
"maintenance flush register-cache",
"thb app_main",
],
"gdb": "${command:espIdf.getToolchainGdb}",
"target": {
"port": "3333"
},
}
]
}

9
.vscode__/settings.json Normal file
View File

@ -0,0 +1,9 @@
{
"idf.adapterTargetName": "esp32s3",
"idf.flashType": "UART",
"idf.portWin": "COM11",
"files.associations": {
"string.h": "c"
},
"idf.espIdfPathWin": "C:\\espidf\\v5.2.3\\esp-idf"
}

View File

@ -0,0 +1,3 @@
idf_component_register(SRCS "image_downloader.c"
INCLUDE_DIRS "include"
REQUIRES json esp_http_client esp-tls esp_timer fatfs sdmmc vfs)

View File

@ -0,0 +1,209 @@
// Note: Run menuconfig to set the WiFi Credentials -> CALE Configuration
// Requirements: Needs to have an EPD Class defined. Needs PSRAM.
// This example does not use a decoded buffer hence leaves more external RAM free
// At the same time it looses the JPG_DITHER functionality in favour of render speed.
// As default only configured for parallel epapers
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_sleep.h"
// WiFi related
#include "esp_event.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "lwip/err.h"
#include "lwip/sys.h"
// HTTP Client + time
#include "esp_http_client.h"
#include "esp_sntp.h"
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#define EXAMPLE_MAX_CHAR_SIZE 64
// JPG decoder
#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
#include "esp32/rom/tjpgd.h"
#else // ESP32 Before IDF 4.0
#include "rom/tjpgd.h"
#endif
#include "esp_task_wdt.h"
#include <stdio.h>
#include <string.h>
#include <math.h> // round + pow
#include "image_downloader.h"
#define MOUNT_POINT "/sdcard"
static const char *TAG = "ImgDwn";
// Image URL and jpg settings. Make sure to update EPD_WIDTH/HEIGHT if using loremflickr
// Note: Only HTTP protocol supported (Check README to use SSL secure URLs) loremflickr
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define IMGDWN_WIDTH 600
#define IMGDWN_HEIGHT 460
#define IMGDWN_URL2 ("http://vps-edf71efa.vps.ovh.net:3000/render/d-solo/7BtRMrv4k/temperatures?orgId=1&var-emplacement=entree_ECS&var-emplacement=entree_reseauSol&panelId=4&width=650&height=460&scale=1&tz=Europe%2FParis/")
#define IMGDWN_URL ("http://vps-edf71efa.vps.ovh.net:3000/render/d-solo/bOcPeysGz/hauteur-cuve?orgId=1&from=now-2d&refresh=1m&panelId=4&width=650&height=460&scale=1&tz=Europe%2FParis")
// As default is 512 without setting buffer_size property in esp_http_client_config_t
#define HTTP_RECEIVE_BUFFER_SIZE 1938
#define DEBUG_VERBOSE false
// Buffers
uint8_t *fb; // EPD 2bpp buffer
uint8_t *source_buf; // JPG download buffer
uint8_t *decoded_image; // RAW decoded image
uint32_t buffer_pos = 0;
uint32_t time_download = 0;
uint32_t time_decomp = 0;
uint32_t time_render = 0;
uint16_t countDataEventCalls = 0;
uint32_t countDataBytes = 0;
uint32_t img_buf_pos = 0;
uint32_t dataLenTotal = 0;
uint64_t startTime = 0;
void create_file_app(uint8_t *buffer, uint32_t size)
{
ESP_LOGI(TAG, "Opening file");
//ESP_LOGI(TAG, "output buffer to spiffs: %s \n", buffer);
FILE* f = fopen(MOUNT_POINT"/hello2.png", "wb+");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
for(int i=0; i<size;i++){
fprintf(f, "%c", buffer[i]);
}
fclose(f);
ESP_LOGI(TAG, "File written");
}
// Handles Htpp events and is in charge of buffering source_buf (jpg compressed image)
esp_err_t _http_event_handler_id(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGE(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
#if DEBUG_VERBOSE
ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
#endif
break;
case HTTP_EVENT_ON_DATA:
++countDataEventCalls;
#if DEBUG_VERBOSE
if (countDataEventCalls%10==0) {
ESP_LOGI(TAG, "%d len:%d\n", countDataEventCalls, evt->data_len);
}
#endif
dataLenTotal += evt->data_len;
if (countDataEventCalls == 1) startTime = esp_timer_get_time();
// Append received data into source_buf
memcpy(&source_buf[img_buf_pos], evt->data, evt->data_len);
img_buf_pos += evt->data_len;
// Optional hexa dump
//ESP_LOG_BUFFER_HEX(TAG, source_buf, 100);
break;
case HTTP_EVENT_REDIRECT:
break;
case HTTP_EVENT_ON_FINISH:
// Do not draw if it's a redirect (302)
if (esp_http_client_get_status_code(evt->client) == 200) {
printf("%li bytes read from %s\nIMG_BUF size: %li\n", img_buf_pos, IMGDWN_URL, img_buf_pos);
//drawBufJpeg(source_buf, 0, 0);
create_file_app(source_buf,img_buf_pos); //function which opens and records data to spiffs file
time_download = (esp_timer_get_time()-startTime)/1000;
ESP_LOGI("www-dw", "%li ms - download", time_download);
// Refresh display
//display.update();
ESP_LOGI("total", "%li ms - total time spent\n", time_download+time_decomp+time_render);
} else {
printf("HTTP on finish got status code: %d\n", esp_http_client_get_status_code(evt->client));
}
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED\n");
break;
}
return ESP_OK;
}
// Handles http request
static void download(void)
{
esp_http_client_config_t config = {
.url = IMGDWN_URL,
.disable_auto_redirect = false,
.event_handler = _http_event_handler_id,
.buffer_size = HTTP_RECEIVE_BUFFER_SIZE,
.timeout_ms = 50000
};
esp_http_client_handle_t client = esp_http_client_init(&config);
#if DEBUG_VERBOSE
printf("Free heap before HTTP download: %d\n", xPortGetFreeHeapSize());
#endif
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "\nIMAGE URL: %s\n\nHTTP GET Status = %d, content_length = %lli\n",
IMGDWN_URL,
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
}
else
{
ESP_LOGE(TAG, "\nHTTP GET request failed: %s", esp_err_to_name(err));
}
//printf("Go to sleep %d minutes\n", CONFIG_DEEPSLEEP_MINUTES_AFTER_RENDER);
esp_http_client_cleanup(client);
vTaskDelay(3600000 / portTICK_PERIOD_MS);
//deepsleep();
}
void imgdwn(void *pvParameter) {
ESP_LOGE(TAG, "beginning");
// Should be big enough to allocate the JPEG file size, width * height should suffice
source_buf = (uint8_t *)heap_caps_malloc(IMGDWN_HEIGHT * IMGDWN_WIDTH, MALLOC_CAP_SPIRAM);
if (source_buf == NULL) {
ESP_LOGE(TAG, "Initial alloc source_buf failed!");
}
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
download();
heap_caps_free(source_buf);
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
}

View File

@ -0,0 +1,2 @@
void imgdwn();
#pragma once

View File

@ -1,4 +1,5 @@
#include "time.h"
struct node { struct node {
struct node *next; struct node *next;
@ -10,20 +11,32 @@ struct Hashtable {
struct node *Cells; struct node *Cells;
}; };
struct forecast_temp{ struct dailyforecast_prev{
float min; float min;
float max; float max;
char desc[25]; char desc[25];
char icon[9]; char icon[9];
}; };
struct forecast_prev{
float value;
char desc[25];
char icon[9];
};
struct meteodailyforecast_data{
time_t datetime;
bool isValid;
struct dailyforecast_prev previsions;
};
struct meteoforecast_data{ struct meteoforecast_data{
time_t datetime; time_t datetime;
bool isValid; bool isValid;
struct forecast_temp previsions; struct forecast_prev previsions;
}; };
typedef void (*weather_data_callback)(struct meteoforecast_data *datas); typedef void (*weather_data_callback)(struct meteodailyforecast_data *datas, struct meteoforecast_data *datasf);
typedef void (*weather_data_start_callback)(); typedef void (*weather_data_start_callback)();
typedef struct { typedef struct {
@ -35,8 +48,12 @@ typedef struct {
weather_data_start_callback data_retreived_cb_start; weather_data_start_callback data_retreived_cb_start;
} weather_data; } weather_data;
void printftemp(struct forecast_temp *tmp); void printdftemp(struct dailyforecast_prev *tmp);
void printffd(struct meteoforecast_data *tmp); void printftemp(struct forecast_prev *tmp);
void printfdf(struct meteodailyforecast_data *tmp);
void dtToString(time_t, char *buffer);
void dtHToString(time_t, char *buffer);
void printff(struct meteoforecast_data *tmp);
void on_weather_data_retrieval(weather_data_callback data_retreived_cb); void on_weather_data_retrieval(weather_data_callback data_retreived_cb);
void on_weather_data_retrieval_start(weather_data_callback data_retreived_cb); void on_weather_data_retrieval_start(weather_data_callback data_retreived_cb);

View File

@ -22,234 +22,348 @@
#include "esp_http_client.h" #include "esp_http_client.h"
#include "esp_tls.h" #include "esp_tls.h"
static const char* TAG = "MeteoFrance"; static const char *TAG = "MeteoFrance";
/* Constants that aren't configurable in menuconfig /* Constants that aren't configurable in menuconfig
Typically only LOCATION_ID may need to be changed Typically only LOCATION_ID may need to be changed
*/ */
#define WEB_SERVER "webservice.meteofrance.com" //"192.168.0.10" //"www.example.com"// //"webservice.meteofrance.com" #define WEB_SERVER "webservice.meteofrance.com" //"192.168.0.10" //"www.example.com"// //"webservice.meteofrance.com"
#define WEB_PORT 80//5403 //80 #define WEB_PORT 80 // 5403 //80
#define WEB_URL "/forecast" #define WEB_URL "/forecast"
#define TOKEN "__Wj7dVSTjV9YGu1guveLyDq0g7S7TfTjaHBTPTpO0kj8__" #define TOKEN "__Wj7dVSTjV9YGu1guveLyDq0g7S7TfTjaHBTPTpO0kj8__"
// Location ID to get the weather data for // Location ID to get the weather data for
//#define LOCATION_ID "756135" // #define LOCATION_ID "756135"
#define LATITUDE "49.22017054145735" #define LATITUDE "49.22017054145735"
#define LONGITUDE "3.92188756221628" #define LONGITUDE "3.92188756221628"
#define WEB_QUERY "token="TOKEN"&lat="LATITUDE"&lon="LONGITUDE #define WEB_QUERY "token=" TOKEN "&lat=" LATITUDE "&lon=" LONGITUDE
#define MAX_HTTP_OUTPUT_BUFFER 32000 #define MAX_HTTP_OUTPUT_BUFFER 32000
static weather_data weather; static weather_data weather;
static struct meteoforecast_data datas[5]; static struct meteodailyforecast_data dailydatas[5];
static struct meteoforecast_data forecastdatas[5];
inline int MIN(int a, int b) { return a > b ? b : a; } inline int MIN(int a, int b) { return a > b ? b : a; }
void printftemp(struct forecast_temp *tmp){ void printdftemp(struct dailyforecast_prev *tmp)
{
printf(" Temps Min:%f, Max:%f", tmp->min, tmp->max); printf(" Temps Min:%f, Max:%f", tmp->min, tmp->max);
} }
void printftemp(struct forecast_prev *tmp)
{
printf(" Temps Value:%f", tmp->value);
}
#define MAX_SIZE 80 #define MAX_SIZE 80
void printffd(struct meteoforecast_data *tmp){ void printfdf(struct meteodailyforecast_data *tmp)
struct tm timeinfo = { 0 }; {
char buffer[MAX_SIZE];
time_t timeToTransform = tmp->datetime;
dtToString(timeToTransform,buffer);
//ESP_LOGE(TAG, "%s", strftime_buf);
printf("IsValid:%s date:%s, Min:%.1f Max:%.1f Desc:%s Icon: %s\n", tmp->isValid ? "true" : "false", buffer, tmp->previsions.min, tmp->previsions.max, tmp->previsions.desc, tmp->previsions.icon);
}
void dtToString(time_t ttt, char* buffer){
struct tm timeinfo = {0};
localtime_r(&ttt, &timeinfo);
strftime(buffer, MAX_SIZE, "%d/%m", &timeinfo);
//char strftime_buf[64];
//sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1);
}
void dtHToString(time_t ttt, char* buffer){
struct tm timeinfo = {0};
localtime_r(&ttt, &timeinfo);
strftime(buffer, MAX_SIZE, "%H:%M", &timeinfo);
//char strftime_buf[64];
//sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1);
}
void printff(struct meteoforecast_data *tmp)
{
struct tm timeinfo = {0};
localtime_r(&tmp->datetime, &timeinfo); localtime_r(&tmp->datetime, &timeinfo);
char buffer[ MAX_SIZE ]; char buffer[MAX_SIZE];
strftime(buffer, MAX_SIZE, "%c", &timeinfo); strftime(buffer, MAX_SIZE, "%c", &timeinfo);
char strftime_buf[64]; char strftime_buf[64];
sprintf(strftime_buf,"%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon+1); sprintf(strftime_buf, "%d %d %d", timeinfo.tm_wday, timeinfo.tm_mday, timeinfo.tm_mon + 1);
ESP_LOGE(TAG,"%s",strftime_buf); ESP_LOGE(TAG, "%s", strftime_buf);
printf("IsValid:%s date:%s, Min:%.1f Max:%.1f Desc:%s\n", tmp->isValid ?"true":"false", buffer, tmp->previsions.min, tmp->previsions.max, tmp->previsions.desc); printf("IsValid:%s date:%s, Temp:%.1f Desc:%s\n", tmp->isValid ? "true" : "false", buffer, tmp->previsions.value, tmp->previsions.desc);
} }
esp_err_t _http_event_handler(esp_http_client_event_t *evt) esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{ {
static char *output_buffer; // Buffer to store response of http request from event handler static char *output_buffer; // Buffer to store response of http request from event handler
static int output_len; // Stores number of bytes read static int output_len; // Stores number of bytes read
switch(evt->event_id) { switch (evt->event_id)
case HTTP_EVENT_ERROR: {
ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); case HTTP_EVENT_ERROR:
break; ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
case HTTP_EVENT_ON_CONNECTED: break;
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); case HTTP_EVENT_ON_CONNECTED:
break; ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
case HTTP_EVENT_HEADER_SENT: break;
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); case HTTP_EVENT_HEADER_SENT:
break; ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
case HTTP_EVENT_ON_HEADER: break;
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); case HTTP_EVENT_ON_HEADER:
break; ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
case HTTP_EVENT_ON_DATA: break;
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); case HTTP_EVENT_ON_DATA:
// Clean the buffer in case of a new request ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
if (output_len == 0 && evt->user_data) { // Clean the buffer in case of a new request
// we are just starting to copy the output data into the use if (output_len == 0 && evt->user_data)
memset(evt->user_data, 0, MAX_HTTP_OUTPUT_BUFFER); {
// we are just starting to copy the output data into the use
memset(evt->user_data, 0, MAX_HTTP_OUTPUT_BUFFER);
}
/*
* Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
* However, event handler can also be used in case chunked encoding is used.
*/
if (!esp_http_client_is_chunked_response(evt->client))
{
// If user_data buffer is configured, copy the response into the buffer
int copy_len = 0;
if (evt->user_data)
{
// The last byte in evt->user_data is kept for the NULL character in case of out-of-bound access.
copy_len = MIN(evt->data_len, (MAX_HTTP_OUTPUT_BUFFER - output_len));
if (copy_len)
{
memcpy(evt->user_data + output_len, evt->data, copy_len);
}
} }
/* else
* Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data. {
* However, event handler can also be used in case chunked encoding is used. int content_len = esp_http_client_get_content_length(evt->client);
*/ if (output_buffer == NULL)
if (!esp_http_client_is_chunked_response(evt->client)) { {
// If user_data buffer is configured, copy the response into the buffer // We initialize output_buffer with 0 because it is used by strlen() and similar functions therefore should be null terminated.
int copy_len = 0; output_buffer = (char *)calloc(content_len + 1, sizeof(char));
if (evt->user_data) { output_len = 0;
// The last byte in evt->user_data is kept for the NULL character in case of out-of-bound access. if (output_buffer == NULL)
copy_len = MIN(evt->data_len, (MAX_HTTP_OUTPUT_BUFFER - output_len)); {
if (copy_len) { ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
memcpy(evt->user_data + output_len, evt->data, copy_len); return ESP_FAIL;
}
} else {
int content_len = esp_http_client_get_content_length(evt->client);
if (output_buffer == NULL) {
// We initialize output_buffer with 0 because it is used by strlen() and similar functions therefore should be null terminated.
output_buffer = (char *) calloc(content_len + 1, sizeof(char));
output_len = 0;
if (output_buffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
return ESP_FAIL;
}
}
copy_len = MIN(evt->data_len, (content_len - output_len));
if (copy_len) {
memcpy(output_buffer + output_len, evt->data, copy_len);
} }
} }
output_len += copy_len; copy_len = MIN(evt->data_len, (content_len - output_len));
if (copy_len)
{
memcpy(output_buffer + output_len, evt->data, copy_len);
}
} }
output_len += copy_len;
}
break; break;
case HTTP_EVENT_ON_FINISH: case HTTP_EVENT_ON_FINISH:
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
if (output_buffer != NULL) { if (output_buffer != NULL)
// Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response {
// ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len); // Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
free(output_buffer); // ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
output_buffer = NULL; free(output_buffer);
} output_buffer = NULL;
output_len = 0; }
break; output_len = 0;
case HTTP_EVENT_DISCONNECTED: break;
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); case HTTP_EVENT_DISCONNECTED:
int mbedtls_err = 0; ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL); int mbedtls_err = 0;
if (err != 0) { esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL);
ESP_LOGI(TAG, "Last esp error code: 0x%x", err); if (err != 0)
ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); {
} ESP_LOGI(TAG, "Last esp error code: 0x%x", err);
if (output_buffer != NULL) { ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err);
free(output_buffer); }
output_buffer = NULL; if (output_buffer != NULL)
} {
output_len = 0; free(output_buffer);
break; output_buffer = NULL;
case HTTP_EVENT_REDIRECT: }
ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); output_len = 0;
esp_http_client_set_header(evt->client, "From", "user@example.com"); break;
esp_http_client_set_header(evt->client, "Accept", "text/html"); case HTTP_EVENT_REDIRECT:
esp_http_client_set_redirection(evt->client); ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
break; esp_http_client_set_header(evt->client, "From", "user@example.com");
esp_http_client_set_header(evt->client, "Accept", "text/html");
esp_http_client_set_redirection(evt->client);
break;
} }
return ESP_OK; return ESP_OK;
} }
char *JSON_Types(int type) { char *JSON_Types(int type)
if (type == cJSON_Invalid) return ("cJSON_Invalid"); {
if (type == cJSON_False) return ("cJSON_False"); if (type == cJSON_Invalid)
if (type == cJSON_True) return ("cJSON_True"); return ("cJSON_Invalid");
if (type == cJSON_NULL) return ("cJSON_NULL"); if (type == cJSON_False)
if (type == cJSON_Number) return ("cJSON_Number"); return ("cJSON_False");
if (type == cJSON_String) return ("cJSON_String"); if (type == cJSON_True)
if (type == cJSON_Array) return ("cJSON_Array"); return ("cJSON_True");
if (type == cJSON_Object) return ("cJSON_Object"); if (type == cJSON_NULL)
if (type == cJSON_Raw) return ("cJSON_Raw"); return ("cJSON_NULL");
return NULL; if (type == cJSON_Number)
return ("cJSON_Number");
if (type == cJSON_String)
return ("cJSON_String");
if (type == cJSON_Array)
return ("cJSON_Array");
if (type == cJSON_Object)
return ("cJSON_Object");
if (type == cJSON_Raw)
return ("cJSON_Raw");
return NULL;
} }
void JSON_Parse(const cJSON * const root) { void JSON_Parse(const cJSON *const root)
//ESP_LOGI(TAG, "root->type=%s", JSON_Types(root->type)); {
cJSON *current_element = NULL; // ESP_LOGI(TAG, "root->type=%s", JSON_Types(root->type));
//ESP_LOGI(TAG, "roo->child=%p", root->child); cJSON *current_element = NULL;
//ESP_LOGI(TAG, "roo->next =%p", root->next); // ESP_LOGI(TAG, "roo->child=%p", root->child);
int i=0; // ESP_LOGI(TAG, "roo->next =%p", root->next);
cJSON *df = cJSON_GetObjectItem(root,"daily_forecast"); int i = 0;
if(!cJSON_IsArray(df)){
ESP_LOGE(TAG,"Pas de tableau ^^");
}else{
cJSON_ArrayForEach(current_element, df) {
struct meteoforecast_data datasT;
//ESP_LOGI(TAG, "type=%s", JSON_Types(current_element->type));
cJSON *dt = cJSON_GetObjectItem(current_element,"dt");
if(cJSON_IsNumber(dt)){
datasT.datetime=dt->valueint;
cJSON *temps = cJSON_GetObjectItem(current_element,"T");
datasT.previsions.min=cJSON_GetObjectItem(temps,"min")->valuedouble;
datasT.previsions.max=cJSON_GetObjectItem(temps,"max")->valuedouble;
cJSON *weather12=cJSON_GetObjectItem(current_element,"weather12H"); // Récupération previsions journalieres (15j par défaut mais on en récupere 3)
strncpy(datasT.previsions.desc,cJSON_GetObjectItem(weather12,"desc")->valuestring,24); cJSON *df = cJSON_GetObjectItem(root, "daily_forecast");
strncpy(datasT.previsions.icon,cJSON_GetObjectItem(weather12,"icon")->valuestring,8); if (!cJSON_IsArray(df))
datasT.isValid=true; {
//ESP_LOGE(TAG,"Donnees lues"); ESP_LOGE(TAG, "Pas de tableau ^^");
//printffd(&datasT); }
datas[i++]=datasT; else
if(i==3){break;} {
cJSON_ArrayForEach(current_element, df)
{
struct meteodailyforecast_data datasT;
// ESP_LOGI(TAG, "type=%s", JSON_Types(current_element->type));
cJSON *dt = cJSON_GetObjectItem(current_element, "dt");
if (cJSON_IsNumber(dt))
{
datasT.datetime = dt->valueint;
cJSON *temps = cJSON_GetObjectItem(current_element, "T");
datasT.previsions.min = cJSON_GetObjectItem(temps, "min")->valuedouble;
datasT.previsions.max = cJSON_GetObjectItem(temps, "max")->valuedouble;
cJSON *weather12 = cJSON_GetObjectItem(current_element, "weather12H");
strncpy(datasT.previsions.desc, cJSON_GetObjectItem(weather12, "desc")->valuestring, 24);
strncpy(datasT.previsions.icon, cJSON_GetObjectItem(weather12, "icon")->valuestring, 8);
datasT.isValid = true;
// ESP_LOGE(TAG,"Donnees lues");
// printffd(&datasT);
dailydatas[i++] = datasT;
if (i == 3)
{
break;
}
}
} }
} }
} // Récupération previsions du jour ("matin/midi/am/soir")
cJSON *fore = cJSON_GetObjectItem(root, "forecast");
if(!cJSON_IsArray(fore)){
ESP_LOGE(TAG, "Pas de tableau forecast");
}else{
i=0;
//On garde les données de 10h 14h 18h
cJSON_ArrayForEach(current_element, fore){
struct meteoforecast_data datasT;
cJSON *dt = cJSON_GetObjectItem(current_element, "dt");
if (cJSON_IsNumber(dt))
{
datasT.datetime = dt->valueint;
struct tm timeinfo = {0};
localtime_r(&(datasT.datetime), &timeinfo);
if(timeinfo.tm_hour==10 || timeinfo.tm_hour==14 || timeinfo.tm_hour==18){
cJSON *temps = cJSON_GetObjectItem(current_element, "T");
datasT.previsions.value = cJSON_GetObjectItem(temps, "value")->valuedouble;
cJSON *weather = cJSON_GetObjectItem(current_element, "weather");
strncpy(datasT.previsions.desc, cJSON_GetObjectItem(weather, "desc")->valuestring, 24);
strncpy(datasT.previsions.icon, cJSON_GetObjectItem(weather, "icon")->valuestring, 8);
datasT.isValid = true;
// ESP_LOGE(TAG,"Donnees lues");
// printffd(&datasT);
forecastdatas[i++] = datasT;
printff(&datasT);
if (i == 3)
{
break;
}
}else{
//ESP_LOGE(TAG,"heure = %i on ne garde pas...", timeinfo.tm_hour);
//char buffer[MAX_SIZE];
//strftime(buffer, MAX_SIZE, "%c", &timeinfo);
//printf("date:%s %lli", buffer, datasT.datetime);
}
}else{
ESP_LOGI(TAG,"dt n'est pas au format attendu ^^");
}
}
ESP_LOGI(TAG, "Prévisions lues !");
}
} }
static bool process_response_body(const char * body) static bool process_response_body(const char *body)
{ {
cJSON *root = cJSON_Parse(body); cJSON *root = cJSON_Parse(body);
JSON_Parse(root); JSON_Parse(root);
cJSON_Delete(root); cJSON_Delete(root);
return true; return true;
} }
static void http_request_task(void *pvParameter) static void http_request_task(void *pvParameter)
{ {
while(1) { while (1)
ESP_LOGE(TAG,"Début recup méteo --------------------------"); {
weather.data_retreived_cb_start(NULL); ESP_LOGE(TAG, "Début recup méteo --------------------------");
char *local_response_buffer = heap_caps_malloc((MAX_HTTP_OUTPUT_BUFFER + 1)*(sizeof(char)),MALLOC_CAP_SPIRAM); weather.data_retreived_cb_start(NULL);
//char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER + 1] = {0}; char *local_response_buffer = heap_caps_malloc((MAX_HTTP_OUTPUT_BUFFER + 1) * (sizeof(char)), MALLOC_CAP_SPIRAM);
/** // char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER + 1] = {0};
* NOTE: All the configuration parameters for http_client must be spefied either in URL or as host and path parameters. /**
* If host and path parameters are not set, query parameter will be ignored. In such cases, * NOTE: All the configuration parameters for http_client must be spefied either in URL or as host and path parameters.
* query parameter should be specified in URL. * If host and path parameters are not set, query parameter will be ignored. In such cases,
* * query parameter should be specified in URL.
* If URL as well as host and path parameters are specified, values of host and path will be considered. *
*/ * If URL as well as host and path parameters are specified, values of host and path will be considered.
esp_http_client_config_t config = { */
.host = WEB_SERVER, esp_http_client_config_t config = {
.port = WEB_PORT, .host = WEB_SERVER,
.path = WEB_URL, .port = WEB_PORT,
.query = WEB_QUERY, .path = WEB_URL,
.event_handler = _http_event_handler, .query = WEB_QUERY,
.user_data = local_response_buffer, // Pass address of local buffer to get response .event_handler = _http_event_handler,
.disable_auto_redirect = true, .user_data = local_response_buffer, // Pass address of local buffer to get response
}; .disable_auto_redirect = true,
esp_http_client_handle_t client = esp_http_client_init(&config); };
char url[50]; esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_get_url(client,url,50); char url[50];
ESP_LOGE(TAG,"%s",url); esp_http_client_get_url(client, url, 50);
ESP_LOGE(TAG, "%s", url);
// GET // GET
esp_err_t err = esp_http_client_perform(client); esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK) { if (err == ESP_OK)
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRId64, {
esp_http_client_get_status_code(client), ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %" PRId64,
esp_http_client_get_content_length(client)); esp_http_client_get_status_code(client),
} else { esp_http_client_get_content_length(client));
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); }
} else
//ESP_LOGE(TAG, "%s",local_response_buffer); {
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
}
// ESP_LOGE(TAG, "%s",local_response_buffer);
process_response_body(local_response_buffer); process_response_body(local_response_buffer);
weather.data_retreived_cb(datas); weather.data_retreived_cb(dailydatas, forecastdatas);
esp_http_client_cleanup(client); heap_caps_free(local_response_buffer);
esp_http_client_cleanup(client);
//http_client_request(&http_client, WEB_SERVER, get_request); // http_client_request(&http_client, WEB_SERVER, get_request);
vTaskDelay(weather.retreival_period / portTICK_PERIOD_MS); vTaskDelay(weather.retreival_period / portTICK_PERIOD_MS);
} }
} }
@ -268,8 +382,12 @@ void initialise_weather_data_retrieval(unsigned long retreival_period)
{ {
weather.retreival_period = retreival_period; weather.retreival_period = retreival_period;
//http_client_on_process_chunk(&http_client, process_chunk); // http_client_on_process_chunk(&http_client, process_chunk);
//http_client_on_disconnected(&http_client, disconnected); // http_client_on_disconnected(&http_client, disconnected);
xTaskCreate(&http_request_task, "http_request_task", 10 * 2048, NULL, 5, NULL); TaskHandle_t xHandle = NULL;
BaseType_t ret1 = xTaskCreate(&http_request_task, "http_request_task", 8 * 1024, NULL, 5, &xHandle);
if(ret1!=pdPASS ){
ESP_LOGE(TAG, "Impossible de creer la tache %i", ret1);
}
ESP_LOGI(TAG, "HTTP request task started"); ESP_LOGI(TAG, "HTTP request task started");
} }

View File

@ -1,29 +1,59 @@
dependencies: dependencies:
espressif/esp_lcd_touch: espressif/esp_lcd_touch:
component_hash: 779b4ba2464a3ae85681e4b860caa5fdc35801458c23f3039ee761bae7f442a4 component_hash: 779b4ba2464a3ae85681e4b860caa5fdc35801458c23f3039ee761bae7f442a4
dependencies:
- name: idf
require: private
version: '>=4.4.2'
source: source:
registry_url: https://components.espressif.com/
type: service type: service
version: 1.1.2 version: 1.1.2
espressif/esp_lcd_touch_gt911: espressif/esp_lcd_touch_gt911:
component_hash: 664c544533b91497f29b41e045bb4374a0d4d002f9d8c67c7c1bf43fb4179e3f component_hash: f90c3f82f052d1ccdfd71895a062f396ccc1c90ec69d8a99c483180387230bac
dependencies:
- name: espressif/esp_lcd_touch
registry_url: https://components.espressif.com/
require: public
version: ^1.1.0
- name: idf
require: private
version: '>=4.4.2'
source: source:
registry_url: https://components.espressif.com/
type: service type: service
version: 1.1.1 version: 1.1.1~1
espressif/esp_lvgl_port: espressif/esp_lvgl_port:
component_hash: 531c0525b5a5d6c05c45a147baa0626209aea6b6c0e01a7af7e6bf151878d056 component_hash: 8bcec6b1144750343ce7e411a7a1057a75a6348d3edc137bd5792ccba7f6c270
dependencies:
- name: idf
registry_url: https://components.espressif.com
require: private
version: '>=4.4'
- name: lvgl/lvgl
registry_url: https://components.espressif.com
require: public
version: '>=8,<10'
source: source:
registry_url: https://components.espressif.com/
type: service type: service
version: 2.2.2 version: 2.3.2
idf: idf:
component_hash: null
source: source:
type: idf type: idf
version: 5.1.4 version: 5.3.1
lvgl/lvgl: lvgl/lvgl:
component_hash: 2a8f619b5c2b1c7ad116c33d43dae8989c76739068f406a7e8ba9221e1085f17 component_hash: 2409fdc84e9766d2a18afd84b051aef3f838348136cdb1c10ac2e8bcdb012bf6
dependencies: []
source: source:
registry_url: https://components.espressif.com/
type: service type: service
version: 9.1.0 version: 9.2.0
manifest_hash: 00b1178407be665595f229a4c10495a43316f71ef19242ff89f82944e383f982 direct_dependencies:
- espressif/esp_lcd_touch_gt911
- espressif/esp_lvgl_port
- idf
- lvgl/lvgl
manifest_hash: b5600105e7af98260d4afd2580596fd962c4f216e9d70b5059131b98ee207d7d
target: esp32s3 target: esp32s3
version: 1.0.0 version: 2.0.0

6
gdbinit Normal file
View File

@ -0,0 +1,6 @@
target remote :3333
set remote hardware-watchpoint-limit 2
mon reset halt
maintenance flush register-cache
thb app_main
c

18
heaptrace-gdbinit Normal file
View File

@ -0,0 +1,18 @@
set pagination off
target remote :3333
mon reset halt
flushregs
tb heap_trace_start
commands
mon esp sysview start file://c:/marc/Projects/IDF/rgb_lcd/trace/htrace_1729789901521.svdat
c
end
tb heap_trace_stop
commands
mon esp sysview stop
end
c

View File

@ -1,75 +1,76 @@
idf_component_register(SRC_DIRS . fonts idf_component_register(SRC_DIRS . fonts
INCLUDE_DIRS "." INCLUDE_DIRS "."
REQUIRES esp_wifi nvs_flash mqtt meteofrance esp_netif) REQUIRES heap esp_wifi nvs_flash mqtt meteofrance esp_netif image_downloader)
lvgl_port_create_c_image("images/esp_logo.png" "images/" "ARGB8888" "NONE") lvgl_port_create_c_image("images/p13bisj.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p10j.png" "images/" "ARGB8888" "NONE") #lvgl_port_create_c_image("images/esp_logo.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p10n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p10j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p11j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p10n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p11n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p11j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p12j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p11n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p12bisj.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p12j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p12n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p12bisj.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p13j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p12n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p13n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p13j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p14bisj.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p13n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p14j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p14bisj.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p14n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p14j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p15j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p14n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p15n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p15j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p16bisj.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p15n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p16j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p16bisj.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p16n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p16j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p17j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p16n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p17n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p17j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p18j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p17n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p18n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p18j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p19j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p18n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p19n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p19j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p1j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p19n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p1n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p1j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p20j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p1n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p20n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p20j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p21j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p20n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p21n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p21j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p22j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p21n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p22n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p22j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p23j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p22n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p23n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p23j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p24j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p23n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p24n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p24j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p25j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p24n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p25n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p25j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p26j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p25n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p26n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p26j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p27j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p26n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p27n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p27j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p28j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p27n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p28n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p28j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p29j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p28n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p29n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p29j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p2j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p29n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p2n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p2j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p30j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p2n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p30n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p30j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p31j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p30n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p31n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p31j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p32j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p31n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p32n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p32j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p3j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p32n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p3n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p3j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p4j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p3n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p4n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p4j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p5bisj.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p4n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p5j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p5bisj.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p5n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p5j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p6j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p5n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p6n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p6j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p7j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p6n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p7n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p7j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p8j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p7n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p8n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p8j.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p9j.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p8n.png" "images/" "ARGB8888" "NONE")
lvgl_port_create_c_image("images/p9n.png" "images/" "ARGB8888" "NONE") # lvgl_port_create_c_image("images/p9j.png" "images/" "ARGB8888" "NONE")
# lvgl_port_create_c_image("images/p9n.png" "images/" "ARGB8888" "NONE")
lvgl_port_add_images(${COMPONENT_LIB} "images/") lvgl_port_add_images(${COMPONENT_LIB} "images/")

18
main/fatfs.c Normal file
View File

@ -0,0 +1,18 @@
/**
* @file lv_fs_fatfs.c
*
*/
/*********************
* INCLUDES
*********************/
#include "ff.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/

2
main/fatfs.h Normal file
View File

@ -0,0 +1,2 @@
void my_fatfs_init(void);
#pragma once

View File

@ -2,6 +2,8 @@ dependencies:
esp_lcd_touch_gt911: esp_lcd_touch_gt911:
version: ^1 version: ^1
esp_lvgl_port: esp_lvgl_port:
version: '*' version: 2.3.2
idf: idf:
version: '>=5.0' version: '>=5.0'
lvgl/lvgl:
version: 9.2.0

BIN
main/images/p13bisj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

83
main/include/fmeteod.h Normal file
View File

@ -0,0 +1,83 @@
static void weatherdata_obs_cb(lv_observer_t *observer, lv_subject_t *subject)
{
// Retrieve weatherdata
struct meteodailyforecast_data *data = subject->value.pointer;
//printffd(data);
char buff[40] = {};
// sprintf(buff,"%s %.1f %.1f", data->previsions.desc, data->previsions.min, data->previsions.max);
lv_obj_t *parent = (lv_obj_t *)(observer->target);
lv_obj_t *datefld = lv_obj_get_child(parent, 0);
lv_obj_t *desc_icon = lv_obj_get_child(parent, 1);
lv_obj_t *temps = lv_obj_get_child(parent, 2);
if (strcmp(data->previsions.icon, "p1j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p1j);
}else if (strcmp(data->previsions.icon, "p2j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p2j);
}else if (strcmp(data->previsions.icon, "p3j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p3j);
}else if (strcmp(data->previsions.icon, "p5bisj") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p5bisj);
}else if (strcmp(data->previsions.icon, "p12j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p12j);
}else if (strcmp(data->previsions.icon, "p12bisj") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p12bisj);
}else if (strcmp(data->previsions.icon, "p14j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p14j);
}else if (strcmp(data->previsions.icon, "p24j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p24j);
}else if (strcmp(data->previsions.icon, "p25j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p25j);
}else if (strcmp(data->previsions.icon, "p26j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p26j);
}else if (strcmp(data->previsions.icon, "p27j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p27j);
}else if (strcmp(data->previsions.icon, "p28j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p28j);
}else if (strcmp(data->previsions.icon, "p29j") == 0)
{
lv_image_set_src(lv_obj_get_child(desc_icon, 0), &p29j);
}else{
ESP_LOGE(TAG, "Image %s non connue",data->previsions.icon);
}
char buffer[80];
dtToString(data->datetime,buffer);
lv_label_set_text(datefld, buffer);
lv_label_set_text(lv_obj_get_child(desc_icon, 1), data->previsions.desc);
lv_label_set_text_fmt(lv_obj_get_child(temps, 0), "%.1f°C", data->previsions.max);
lv_label_set_text_fmt(lv_obj_get_child(temps, 1), "%.1f°C", data->previsions.min);
}
struct weatherDay_fragment_t
{
/* IMPORTANT: don't miss this part */
lv_fragment_t base;
/* States, object references and data fields for this fragment */
int dayNr;
bool showTitle;
const char *title;
float minTemp;
float maxTemp;
};
static void weatherDay_fragment_ctor(lv_fragment_t *self, void * args)
{
int dayNo = ((int *)args)[0];
bool showDate = ((int*)args)[1];
((struct weatherDay_fragment_t *)self)->dayNr = dayNo;
((struct weatherDay_fragment_t *)self)->showTitle = showDate;
ESP_LOGI(TAG, "Fragment initialisé avec le jour n°%d - Afficher la date %d",dayNo, showDate);
}

File diff suppressed because it is too large Load Diff

3
main/main.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "mqtt_client.h"
static void showMeteoIcon(const char *icon, lv_obj_t *desc_icon, int childNr);

232
main/mqtt.c Normal file
View File

@ -0,0 +1,232 @@
#include "mqtt.h"
#include "esp_log.h"
#include "esp_lvgl_port.h"
#include "mqtt_client.h"
esp_mqtt_client_handle_t client;
extern lv_subject_t mqttStatus;
extern lv_subject_t tempIntSubj;
extern lv_subject_t tempExtSubj;
extern lv_subject_t hauteurCuveSubj;
extern lv_subject_t hauteurCuveEvolSubj;
static const char *TAG = "mqtt";
char *upEvent = "monter";
char *downEvent = "descendre";
char *topicTempExt = "house/temp/282A802600008059";
char *topicHauteurCuve = "house/cuve/hauteur";
char *topicTempInt = "house/temp/287DCF1E00008020";
char *topicHauteurCuveEvol = "house/cuve/hauteurEvol";
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0)
{
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
}
}
void splitIt(char *payload, unsigned int length, float *datas)
{
char *sep = ",";
char *token;
char *saveptr1;
token = strtok_r(payload, sep, &saveptr1);
datas[0] = atoff(token);
ESP_LOGE(TAG,"%f",datas[0]);
token = strtok_r(NULL, sep, &saveptr1);
datas[1] = atoff(token);
ESP_LOGE(TAG,"%f",datas[1]);
token = strtok_r(NULL, sep, &saveptr1);
datas[2] = atoff(token);
ESP_LOGE(TAG,"%f",datas[2]);
token = strtok_r(NULL, sep, &saveptr1);
datas[3] = atoff(token);
ESP_LOGE(TAG,"%f",datas[3]);
}
/*
* @brief Event handler registered to receive MQTT events
*
* This function is called by the MQTT client event loop.
*
* @param handler_args user data registered to the event.
* @param base Event base for the handler(always MQTT Base in this example).
* @param event_id The id for the received event.
* @param event_data The data for the event, esp_mqtt_event_handle_t.
*/
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut mqttStatus 1");
lv_subject_set_int(&mqttStatus,1);
lvgl_port_unlock();
}
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
//msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
//ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTempExt, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicTempInt, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicHauteurCuve, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, topicHauteurCuveEvol, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
//ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
//ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut mqttStatus 0");
lv_subject_set_int(&mqttStatus,0);
lvgl_port_unlock();
}
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
//msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
//ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
if (strncmp(event->topic, topicTempExt, 27) == 0)
{
lvgl_port_lock(0);
// on retransforme en float pour ne garder que la partie entiere de la température
float temp = strtof(event->data, NULL);
char buff[5];
sprintf(buff,"%.1f",temp);
lv_subject_copy_string(&tempExtSubj, buff);
lvgl_port_unlock();
}
else if (strncmp(event->topic, topicTempInt, 27) == 0)
{
lvgl_port_lock(0);
// on retransforme en float pour ne garder que la partie entiere de la température
float temp = strtof(event->data, NULL);
char buff[5];
sprintf(buff,"%.1f",temp);
lv_subject_copy_string(&tempIntSubj, buff);
lvgl_port_unlock();
}
else if (strncmp(event->topic, topicHauteurCuveEvol, 22) == 0)
{
/* float datas[4] = {};
splitIt(event->data, event->data_len, datas);
ser1->y_points[0] = 130 - (int)datas[0];
ser1->y_points[1] = 130 - (int)datas[1];
ser1->y_points[2] = 130 - (int)datas[2];
ser1->y_points[3] = 130 - (int)datas[3];
lvgl_port_lock(0);
lv_chart_refresh(chart);
lvgl_port_unlock();
*/
// lv_subject_copy_string(&hauteurCuveEvolSubj, event->data);
}
else if (strncmp(event->topic, topicHauteurCuve, 18) == 0)
{
lvgl_port_lock(0);
char *datas = NULL;
datas = (char *)malloc(event->data_len * sizeof(char));
stpncpy(datas, event->data, event->data_len);
datas[event->data_len] = '\0';
lv_subject_copy_string(&hauteurCuveSubj, datas);
free(datas);
lvgl_port_unlock();
}
else
{
ESP_LOGE(TAG, "None match :-(");
}
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
{
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
void mqtt_app_start(void)
{
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = "mqtt://192.168.0.10",
.network.timeout_ms = 1000};
#if CONFIG_BROKER_URL_FROM_STDIN
char line[128];
if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0)
{
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128)
{
int c = fgetc(stdin);
if (c == '\n')
{
line[count] = '\0';
break;
}
else if (c > 0 && c < 127)
{
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
}
else
{
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(client);
}

3
main/mqtt.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void mqtt_app_start(void);

32
main/obtain_time.c Normal file
View File

@ -0,0 +1,32 @@
#include "esp_log.h"
#include "esp_netif_sntp.h"
#include "esp_sntp.h"
#include "obtain_time.h"
static const char *TAG = "sntp";
void time_sync_notification_cb(struct timeval *tv)
{
ESP_LOGI(TAG, "Notification of a time synchronization event");
}
void obtain_time(void)
{
ESP_LOGI(TAG, "Initializing and starting SNTP");
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
config.sync_cb = time_sync_notification_cb; // Note: This is only needed if we want
esp_netif_sntp_init(&config);
// wait for time to be set
time_t now = 0;
struct tm timeinfo = { 0 };
int retry = 0;
const int retry_count = 15;
while (esp_netif_sntp_sync_wait(2000 / portTICK_PERIOD_MS) == ESP_ERR_TIMEOUT && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
}
time(&now);
localtime_r(&now, &timeinfo);
esp_netif_sntp_deinit();
}

2
main/obtain_time.h Normal file
View File

@ -0,0 +1,2 @@
void obtain_time(void);
#pragma once

152
main/wifi.c Normal file
View File

@ -0,0 +1,152 @@
#include "wifi.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_lvgl_port.h"
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
#define EXAMPLE_ESP_WIFI_SSID "wifimms3"
#define EXAMPLE_ESP_WIFI_PASS "mmswifi0611"
#define EXAMPLE_ESP_MAXIMUM_RETRY 5
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
static const char *TAG = "wifi";
static int s_retry_num = 0;
extern lv_subject_t wifiStatus;
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
esp_wifi_connect();
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
{
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut Wifi 0");
lv_subject_set_int(&wifiStatus,0);
lvgl_port_unlock();
}
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY)
{
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
}
else
{
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
ESP_LOGI(TAG, "connect to the AP fail");
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut Wifi 1");
lv_subject_set_int(&wifiStatus,1);
lvgl_port_unlock();
}
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&wifi_event_handler,
NULL,
&instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.password = EXAMPLE_ESP_WIFI_PASS,
/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
*/
.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
.sae_pwe_h2e = ESP_WIFI_SAE_MODE,
.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_sta finished.");
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT)
{
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut Wifi 1");
lv_subject_set_int(&wifiStatus,1);
lvgl_port_unlock();
}
}
else if (bits & WIFI_FAIL_BIT)
{
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut Wifi 0");
lv_subject_set_int(&wifiStatus,0);
lvgl_port_unlock();
}
}
else
{
ESP_LOGE(TAG, "UNEXPECTED EVENT");
if(lvgl_port_lock(0)){
ESP_LOGE(TAG,"Statut Wifi 0");
lv_subject_set_int(&wifiStatus,0);
lvgl_port_unlock();
}
}
}

2
main/wifi.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
void wifi_init_sta(void);

Binary file not shown.

View File

@ -0,0 +1,9 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,24K,
otadata,data,ota,0xf000,8K,
phy_init,data,phy,0x11000,4K,
factory,app,factory,0x20000,3M,
ota_0,app,ota_0,0x320000,3M,
ota_1,app,ota_1,0x620000,3M,
datas,data,spiffs,0x920000,1M,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs,data,nvs,0x9000,24K,
4 otadata,data,ota,0xf000,8K,
5 phy_init,data,phy,0x11000,4K,
6 factory,app,factory,0x20000,3M,
7 ota_0,app,ota_0,0x320000,3M,
8 ota_1,app,ota_1,0x620000,3M,
9 datas,data,spiffs,0x920000,1M,

5
partitions copy.csv Normal file
View File

@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 3M,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 3M,

View File

@ -1,5 +1,9 @@
# Name, Type, SubType, Offset, Size, Flags # ESP-IDF Partition Table
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000, nvs,data,nvs,,0x6000,,
phy_init, data, phy, 0xf000, 0x1000, otadata,data,ota,,0x2000,,
factory, app, factory, 0x10000, 3M, phy_init,data,phy,,0x1000,,
factory,app,factory,,3M,,
ota_0,app,ota_0,,3M,,
ota_1,app,ota_1,,3M,,
datas,data,spiffs,,1M,,

1 # Name, Type, SubType, Offset, Size, Flags # ESP-IDF Partition Table
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x6000, nvs,data,nvs,,0x6000,,
4 phy_init, data, phy, 0xf000, 0x1000, otadata,data,ota,,0x2000,,
5 factory, app, factory, 0x10000, 3M, phy_init,data,phy,,0x1000,,
6 factory,app,factory,,3M,,
7 ota_0,app,ota_0,,3M,,
8 ota_1,app,ota_1,,3M,,
9 datas,data,spiffs,,1M,,

507
sdkconfig

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,6 @@ CONFIG_SPIRAM_SPEED_80M=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_HZ=1000
CONFIG_LV_MEM_CUSTOM=y
CONFIG_LV_MEMCPY_MEMSET_STD=y
CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y
CONFIG_LV_FONT_MONTSERRAT_12=y CONFIG_LV_FONT_MONTSERRAT_12=y
CONFIG_LV_FONT_MONTSERRAT_16=y CONFIG_LV_FONT_MONTSERRAT_16=y

File diff suppressed because it is too large Load Diff