Skip to content

Release 1.0#1

Draft
Kampi wants to merge 26 commits intomasterfrom
1.0_Dev
Draft

Release 1.0#1
Kampi wants to merge 26 commits intomasterfrom
1.0_Dev

Conversation

@Kampi
Copy link
Contributor

@Kampi Kampi commented Dec 29, 2025

Summary by CodeRabbit

  • New Features

    • Complete thermal firmware: camera capture, UI, HTTP REST API, WebSocket streaming, OTA updates, and VISA/SCPI interface.
  • Networking & Time

    • Wi‑Fi provisioning, STA/AP management, SNTP time sync with RTC backup, and comprehensive network/server controls.
  • Hardware Support

    • I2C/SPI managers, port expander, ADC battery monitoring, SD card support, touchscreen/display and image encoding.
  • Persistence & Settings

    • Persistent settings manager with defaults, NVS storage, and runtime configuration APIs.
  • Documentation

    • Added README, CHANGELOG and protocol docs (WebSocket, VISA).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a complete ESP32 firmware tree: build/CI and repo metadata, many new device drivers and managers (ADC, I2C, SPI, RTC, PortExpander), network stack and servers (HTTP, WebSocket, VISA), tasks (Lepton, GUI, Network, Devices), LVGL UI assets, settings/time/SD managers, and supporting build/config scripts and manifests.

Changes

Cohort / File(s) Summary
Repository metadata & CI
\.coderabbit.yaml, .github/FUNDING.yml, .github/workflows/firmware.yml, .gitmodules, CHANGELOG.md, README.md, platformio.ini, main/idf_component.yml, scripts/astyle.cfg, scripts/clean.py, scripts/format.py
New repo config, funding, CI workflow (build/release), submodule entry, changelog/readme, PlatformIO/idf manifests, style/config scripts and helpers.
Top-level build & config
CMakeLists.txt, main/CMakeLists.txt, main/Kconfig.projbuild, main/idf_component.yml, platformio.ini
Adds CMake registration, component manifest, version macros, Kconfig project options and PlatformIO settings.
Application entry & core headers
main/main.cpp, main/Application/application.h, main/Application/managers.h, main/Application/bitmap.h, main/Application/Tasks/tasks.h
Adds app entry (app_main), central application context/events, manager/task aggregator headers and bitmap types.
Device drivers (sources & headers)
ADC: <...>/ADC/adc.cpp, .../ADC/adc.h; I2C: <...>/I2C/i2c.cpp, .../I2C/i2c.h; SPI: <...>/SPI/spi.cpp, .../SPI/spi.h; PortExpander: <...>/PortExpander/portexpander.cpp, .../PortExpander/portexpander.h; RTC: <...>/RTC/rtc.cpp, .../RTC/rtc.h; devices aggregator: main/Application/Manager/Devices/devices.h
New low-level drivers and public headers for ADC (battery), I2C master, SPI bus manager, PCAL6416A port expander, RV8263 RTC, plus a devices aggregator header.
Devices manager & task
main/Application/Manager/Devices/devicesManager.cpp, .../devicesManager.h, main/Application/Tasks/Devices/devicesTask.cpp, .../devicesTask.h
DevicesManager to coordinate buses and peripherals and a Devices task that polls battery/controls hardware.
Network stack & types
main/Application/Manager/Network/networkManager.cpp, .../networkManager.h, main/Application/Manager/Network/network_types.h
Full network manager, state/events/types for WiFi/servers/provisioning/SNTP.
Provisioning & SNTP
.../Provisioning/provisioning.cpp, .../Provisioning/provisioning.h, .../SNTP/sntp.cpp, .../SNTP/sntp.h
BLE provisioning implementation and SNTP management with public APIs.
HTTP/WebSocket server & encoder
.../Server/http_server.cpp, .../Server/http_server.h, .../Server/websocket_handler.cpp, .../Server/websocket_handler.h, .../Server/image_encoder.cpp, .../Server/image_encoder.h, .../Server/server.h, .../Server/Websocket.md
HTTP REST API, WebSocket handler and broadcaster, image encoder (JPEG/RAW), server integration and docs.
VISA / SCPI server
main/Application/Manager/Network/VISA/visa_server.cpp, .../visa_server.h, .../visa_commands.cpp, .../visa_commands.h, .../README.md, CMakeLists.txt
TCP VISA/SCPI server and command handling with public APIs and README.
SD manager
main/Application/Manager/SD/sdManager.cpp, .../sdManager.h
SD mount/unmount, debounce card-detect, bitmap save and mount task.
Settings manager & types
main/Application/Manager/Settings/settingsManager.cpp, .../settingsManager.h, .../settings_types.h
NVS-backed settings with defaults, per-section setters/getters, events, and commit/reset APIs.
Time manager & types
main/Application/Manager/Time/timeManager.cpp, .../timeManager.h, .../time_types.h
Unified TimeManager combining SNTP and RTC backup with status API and events.
Lepton task
main/Application/Tasks/Lepton/leptonTask.cpp, .../leptonTask.h
Lepton camera capture task: frame acquisition, conversion, ROI, spotmeter, event integration and lifecycle.
GUI subsystem (LVGL) — sources & generated UI
main/Application/Tasks/GUI/Private/guiHelper.cpp, .../guiHelper.h, main/Application/Tasks/GUI/guiTask.cpp, .../guiTask.h, main/Application/Tasks/GUI/Export/* (ui.c, ui.h, ui_helpers., ui_events., screens `ui_*.(c
h), images, fonts), ui/*`
Image assets & bitmap utilities
main/Application/Tasks/GUI/Export/images/*, main/Application/bitmap.h, main/Application/Manager/Network/Server/image_encoder.*
Embedded image assets, bitmap format types, and image encoding pipeline for streaming and storage.
Vast new public APIs / headers added
many *.h across managers, tasks, drivers, servers (see cohort files)
Numerous new public function/type declarations across modules (ADC/I2C/SPI/RTC/PortExpander, DevicesManager, NetworkManager, Provisioning, SNTP, HTTP/WebSocket server, VISA, SD, Settings, TimeManager, GUI, Lepton, Image encoder, etc.).

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Pre-merge checks

✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 1.0_Dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as outdated.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

♻️ Duplicate comments (4)
main/Application/Manager/Devices/SPI/spi.cpp (1)

97-133: The critical use-after-free bug has been resolved.

The previously reported issue where the mutex was deleted before use has been fixed. The current implementation correctly:

  1. Takes the mutex (line 113)
  2. Performs spi_bus_free (line 114)
  3. Releases the mutex (line 120)
  4. Deletes the mutex only after all operations complete (lines 122-125)
main/Application/Manager/SD/sdManager.cpp (1)

102-112: ISR safety issue already flagged.

The TODO on line 108 acknowledges this issue. Please refer to the previous review comment that provides a complete fix using FreeRTOS xTimerResetFromISR() instead of the non-IRAM-safe esp_timer_* functions.

main/Application/Manager/Devices/ADC/adc.cpp (1)

61-63: Redundant condition: _ADC_Calib_Done is always false at line 63.

The variable is set to false on line 61, so the check if (_ADC_Calib_Done == false) on line 63 is always true. Remove the condition or restructure the logic.

🔎 Proposed fix
     Error = ESP_OK;
-    _ADC_Calib_Done = false;
-
-    if (_ADC_Calib_Done == false) {
+    {
         ESP_LOGD(TAG, "calibration scheme version is %s", "Curve Fitting");
main/Application/Tasks/GUI/Export/screens/ui_Menu.c (1)

20-22: Potential null pointer dereference in gesture handling.

lv_indev_active() may return NULL if no input device is active. The code calls it twice and uses the result without null checking, which could crash.

This issue was already flagged in a previous review. The suggested fix is to capture the result once and check for NULL before using it.

🟡 Minor comments (16)
main/Application/Manager/Devices/SPI/spi.cpp-154-166 (1)

154-166: Minor race condition in logging DeviceCount.

Line 165 reads _SPI_State[Host].DeviceCount after the mutex has been released (line 163). Another thread could modify this value between the unlock and the log statement, resulting in an inaccurate log message.

🔎 Proposed fix
+    uint32_t device_count;
+
     xSemaphoreTake(_SPI_State[Host].Mutex, portMAX_DELAY);
     Error = spi_bus_add_device(Host, p_Dev_Config, p_Handle);
     if (Error != ESP_OK) {
         ESP_LOGE(TAG, "Failed to add device to SPI%d: %d!", Host + 1, Error);
         xSemaphoreGive(_SPI_State[Host].Mutex);
         return Error;
     }
 
     _SPI_State[Host].DeviceCount++;
+    device_count = _SPI_State[Host].DeviceCount;
     xSemaphoreGive(_SPI_State[Host].Mutex);
 
-    ESP_LOGI(TAG, "Device added to SPI%d (total: %d devices)", Host + 1, _SPI_State[Host].DeviceCount);
+    ESP_LOGI(TAG, "Device added to SPI%d (total: %d devices)", Host + 1, device_count);
main/Application/Manager/SD/sdManager.cpp-386-397 (1)

386-397: Missing check for already-mounted state.

The function checks CardPresent and MountTaskHandle, but doesn't verify whether the card is already mounted (_SD_Manager_State.Card != NULL). Calling SDManager_Mount() when already mounted could cause issues.

🔎 Proposed fix
 esp_err_t SDManager_Mount(void)
 {
     if (_SD_Manager_State.CardPresent == false) {
         ESP_LOGW(TAG, "No SD card available!");
         return ESP_ERR_NOT_FOUND;
     }

+    /* Check if already mounted */
+    if (_SD_Manager_State.Card != NULL) {
+        ESP_LOGW(TAG, "SD card already mounted");
+        return ESP_OK;
+    }
+
     /* Prevent multiple mount tasks */
     if (_SD_Manager_State.MountTaskHandle != NULL) {
         ESP_LOGW(TAG, "Mount task already running");
         return ESP_ERR_INVALID_STATE;
     }
main/Application/Manager/SD/sdManager.cpp-266-268 (1)

266-268: Incomplete state check: should also verify card is mounted.

Checking CardPresent only confirms the physical presence detected via GPIO, but doesn't guarantee the filesystem is mounted. If the card is present but SDManager_Mount() failed or hasn't completed, file operations will fail with a confusing error.

🔎 Proposed fix
-    if (_SD_Manager_State.CardPresent == false) {
+    if (_SD_Manager_State.CardPresent == false || _SD_Manager_State.Card == NULL) {
         return ESP_ERR_INVALID_STATE;
     }
main/Application/Tasks/Lepton/leptonTask.cpp-1-2 (1)

1-2: File header comment has incorrect extension.

The comment says leptonTask.c but the file is leptonTask.cpp.

🔎 Proposed fix
 /*
- * leptonTask.c
+ * leptonTask.cpp
main/Application/Tasks/GUI/Private/guiHelper.cpp-308-311 (1)

308-311: Format string mismatch in ESP_LOGW.

The format string contains no format specifiers, but two extra arguments (lv_obj_get_width(...) and lv_obj_get_height(...)) are passed. These arguments are evaluated but ignored.

🔎 Proposed fix
-        ESP_LOGW(TAG, "Thermal image not yet initialized, skipping spot update",
-                 lv_obj_get_width(ui_Image_Thermal), lv_obj_get_height(ui_Image_Thermal));
+        ESP_LOGW(TAG, "Thermal image not yet initialized (w=%d, h=%d), skipping spot update",
+                 lv_obj_get_width(ui_Image_Thermal), lv_obj_get_height(ui_Image_Thermal));
main/Application/Tasks/GUI/Private/guiHelper.cpp-236-244 (1)

236-244: Dead code: duplicate LVGL_TickTimer cleanup.

Lines 236-238 already stop, delete, and NULL the timer. The block at lines 240-244 is unreachable since LVGL_TickTimer is always NULL at that point.

🔎 Proposed fix
     esp_timer_stop(p_GUITask_State->LVGL_TickTimer);
     esp_timer_delete(p_GUITask_State->LVGL_TickTimer);
     p_GUITask_State->LVGL_TickTimer = NULL;
-
-    if (p_GUITask_State->LVGL_TickTimer != NULL) {
-        esp_timer_stop(p_GUITask_State->LVGL_TickTimer);
-        esp_timer_delete(p_GUITask_State->LVGL_TickTimer);
-        p_GUITask_State->LVGL_TickTimer = NULL;
-    }
main/Application/Manager/Settings/settingsManager.cpp-201-206 (1)

201-206: Settings version mismatch logs warning but continues with potentially incompatible data.

When a version mismatch is detected, the code logs a warning and continues using the loaded settings. This could cause issues if the struct layout changed between versions. The TODO comment acknowledges this, but until migration is implemented, consider falling back to defaults for safety.

Do you want me to help implement a version migration framework or propose a safer fallback strategy?

main/Application/Manager/Network/Server/websocket_handler.cpp-687-711 (1)

687-711: Telemetry data access without mutex protection.

WebSocket_Handler_BroadcastTelemetry reads _WSHandler_State.ThermalFrame->temp_avg at line 688 without holding the frame's mutex, but WS_BroadcastTask properly acquires ThermalFrame->mutex before accessing frame data. This inconsistency could lead to torn reads if the thermal task is updating the frame concurrently.

main/Application/Manager/Network/Server/websocket_handler.cpp-775-798 (1)

775-798: Task handle not cleared by the task itself, causing potential race.

WS_BroadcastTask deletes itself with vTaskDelete(NULL) at line 648, but WebSocket_Handler_StopTask polls _WSHandler_State.BroadcastTask to check if the task has finished. Since the task never sets BroadcastTask = NULL before deleting itself, the check at line 790 will never see a NULL handle, and the loop will always run until timeout.

🔎 Proposed fix

Have the task clear its handle before exiting:

 static void WS_BroadcastTask(void *p_Param)
 {
     // ... existing code ...
 
     ESP_LOGI(TAG, "WebSocket broadcast task stopped");
+    _WSHandler_State.BroadcastTask = NULL;
     vTaskDelete(NULL);
 }

And update the stop function:

 void WebSocket_Handler_StopTask(uint32_t Timeout_ms)
 {
-    uint32_t Start;
-
     if (_WSHandler_State.BroadcastTask == NULL) {
         return;
     }
 
     ESP_LOGI(TAG, "Stopping WebSocket broadcast task...");
 
     _WSHandler_State.TaskRunning = false;
 
-    /* Wait for task to finish (max 2 seconds) */
-    Start = esp_timer_get_time() / 1000;
+    uint32_t Start = esp_timer_get_time() / 1000;
 
     while (_WSHandler_State.BroadcastTask != NULL &&
            ((esp_timer_get_time() / 1000) - Start) < Timeout_ms) {
         vTaskDelay(10 / portTICK_PERIOD_MS);
     }
 
-    _WSHandler_State.BroadcastTask = NULL;
+    if (_WSHandler_State.BroadcastTask != NULL) {
+        ESP_LOGW(TAG, "Broadcast task did not exit gracefully, forcing cleanup");
+        _WSHandler_State.BroadcastTask = NULL;
+    }
 
     ESP_LOGI(TAG, "WebSocket broadcast task stopped");
 }

Committable suggestion skipped: line range outside the PR's diff.

main/Application/Tasks/GUI/guiTask.cpp-481-497 (1)

481-497: Splash screen wait loop lacks timeout.

The splash screen loop (lines 481-497) waits indefinitely for LEPTON_CAMERA_READY. If the Lepton camera fails to initialize, the task will be stuck. The TODO comment on line 493 acknowledges this.

Would you like me to implement a timeout mechanism for this loop?

main/Application/Tasks/Devices/devicesTask.cpp-117-117 (1)

117-117: Potential double deinitialization of DevicesManager.

DevicesManager_Deinit() is called both when the task loop exits (line 117) and again in DevicesTask_Deinit() (line 167). If the task exits normally and then DevicesTask_Deinit() is called, this could cause issues if DevicesManager_Deinit is not idempotent.

🔎 Suggested fix - remove from task or add guard

Either remove the call from the task loop (letting DevicesTask_Deinit handle cleanup), or ensure DevicesManager_Deinit is idempotent:

 static void Task_Devices(void *p_Parameters)
 {
     // ... loop code ...
 
     ESP_LOGD(TAG, "Devices task shutting down");
-    DevicesManager_Deinit();
 
     _DevicesTask_State.Running = false;

Also applies to: 167-167

main/Application/Tasks/Network/networkTask.cpp-440-448 (1)

440-448: Task stop may leave Running flag in inconsistent state.

If the task doesn't stop within the timeout, _NetworkTask_State.Running is set to false on line 446 even though the task may still be running. This could cause issues if the task later tries to access freed resources.

main/Application/Tasks/GUI/guiTask.cpp-647-647 (1)

647-647: Minor typo: "recieved" should be "received".

-        /* Process the recieved system events */
+        /* Process the received system events */
main/Application/Tasks/Devices/devicesTask.cpp-145-149 (1)

145-149: Event group not cleaned up on DevicesManager_Init failure.

If DevicesManager_Init() fails (line 146), the event group created on line 139 is not deleted before returning.

🔎 Suggested fix
     Error = DevicesManager_Init();
     if (Error != ESP_OK) {
         ESP_LOGE(TAG, "Failed to initialize Devices Manager: %d!", Error);
+        vEventGroupDelete(_DevicesTask_State.EventGroup);
+        _DevicesTask_State.EventGroup = NULL;
         return Error;
     }
main/Application/Manager/Network/Server/image_encoder.cpp-108-108 (1)

108-108: Stray semicolon.

There's a lone semicolon on line 108 which appears to be a typo.

-;
main/Application/Manager/Network/network_types.h-77-78 (1)

77-78: Incomplete documentation comment.

The comment for NETWORK_EVENT_CREDENTIALS_UPDATED is incomplete: "Data is of ...". Please complete the documentation.

🔎 Proposed fix
     NETWORK_EVENT_CREDENTIALS_UPDATED,          /**< New WiFi credentials have been set
-                                                     Data is of ... */
+                                                     Data is of type Network_WiFi_Credentials_t */
🧹 Nitpick comments (36)
main/Application/Tasks/Network/networkTask.h (2)

27-28: Unused include: esp_event.h is not referenced in this header.

The header declares functions returning esp_err_t and taking App_Context_t*, but no event types are used here. Consider removing this include to reduce compilation dependencies.


35-46: Inconsistent documentation across function declarations.

Only Network_Task_Start has a doxygen comment. For API consistency, consider adding brief documentation to Network_Task_Init, Network_Task_Deinit, Network_Task_Stop, and Network_Task_isRunning similar to the existing comment style.

main/Application/Manager/Devices/ADC/adc.cpp (2)

27-30: Unused FreeRTOS includes.

These FreeRTOS headers are included but no FreeRTOS primitives (tasks, semaphores, event groups) are used in this file. Consider removing them.

🔎 Proposed fix
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <freertos/event_groups.h>
-#include <freertos/semphr.h>
-

51-51: TAG should be declared static for internal linkage.

Global const char *TAG without static has external linkage and may conflict with TAG definitions in other translation units.

🔎 Proposed fix
-const char *TAG = "ADC";
+static const char *TAG = "ADC";
main/Application/Manager/Settings/settings_types.h (1)

24-28: Consider adding explicit includes for bool and fixed-width integer types.

The header uses bool (lines 74, 90, 91, 104) and fixed-width types like uint8_t, uint16_t, uint32_t but only includes esp_event.h. While these may be transitively included, explicit includes improve portability and self-documentation.

🔎 Proposed fix
 #ifndef SETTINGS_TYPES_H_
 #define SETTINGS_TYPES_H_

 #include <esp_event.h>
+#include <stdint.h>
+#include <stdbool.h>
main/Application/Manager/Network/Server/websocket_handler.cpp (1)

550-558: Potential data race on ClientCount reads.

WebSocket_Handler_GetClientCount and WebSocket_Handler_HasClients read ClientCount without mutex protection, while it's modified under mutex in WS_AddClient/WS_RemoveClient. On ESP32 (32-bit ARM), single-word reads are typically atomic, but for strict correctness and consistency, consider protecting these reads or documenting the relaxed guarantee.

main/Application/Manager/Settings/settingsManager.cpp (3)

75-78: Empty string copy has no effect; consider documenting intent.

Lines 76-77 use strncpy to copy empty strings "" to SSID and Password, but memset on line 64 already zeroed the entire struct. This is redundant but harmless. If the intent is to explicitly show WiFi defaults are empty, a comment would clarify.


109-109: ESP_ERROR_CHECK on nvs_flash_init may be too aggressive.

If NVS is corrupted, nvs_flash_init returns an error, and ESP_ERROR_CHECK will abort the application. Consider handling ESP_ERR_NVS_NO_FREE_PAGES or ESP_ERR_NVS_NEW_VERSION_FOUND by erasing and reinitializing NVS, which is a common pattern for recovery.

🔎 Proposed fix
-    ESP_ERROR_CHECK(nvs_flash_init());
+    esp_err_t err = nvs_flash_init();
+    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+        ESP_LOGW(TAG, "NVS partition issue, erasing and reinitializing...");
+        ESP_ERROR_CHECK(nvs_flash_erase());
+        err = nvs_flash_init();
+    }
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to initialize NVS: %d", err);
+        return err;
+    }

423-426: SettingsManager_HasPendingChanges reads without mutex.

_State.PendingChanges is read without mutex protection. While bool reads are typically atomic on ESP32, for consistency with other state accesses that use the mutex, consider adding protection or documenting this is intentional.

main/Application/Tasks/GUI/Export/screens/ui_Main.c (1)

1-5: Auto-generated file - consider adding to .gitattributes for merge handling.

This file is generated by SquareLine Studio. Manual modifications will be lost on regeneration. Consider marking generated UI files in .gitattributes with merge=ours or similar strategy to prevent merge conflicts on tool updates.

main/main.cpp (2)

55-59: Queue creation failure should clean up before returning.

If queue creation fails, the function returns without cleaning up the event loop created at line 53. While this is a fatal error scenario, proper cleanup ensures consistent state.

🔎 Proposed fix
     _App_Context.Lepton_FrameEventQueue = xQueueCreate(1, sizeof(App_Lepton_FrameReady_t));
     if (_App_Context.Lepton_FrameEventQueue == NULL) {
         ESP_LOGE(TAG, "Failed to create frame queue!");
+        esp_event_loop_delete_default();
         return;
     }

82-82: Commented-out code should be removed or explained.

SDManager_Init() is commented out without explanation. If SD card support is planned for later, consider adding a TODO comment or removing the line entirely.

main/Application/Manager/Network/SNTP/sntp.cpp (3)

43-51: Missing initialization state tracking.

SNTP_Init doesn't track whether SNTP is already initialized. Calling esp_sntp_init() twice without calling esp_sntp_stop() first may cause issues. Consider adding an initialization flag.

🔎 Proposed fix
+static bool _sntp_initialized = false;
+
 esp_err_t SNTP_Init(void)
 {
+    if (_sntp_initialized) {
+        ESP_LOGW(TAG, "SNTP already initialized");
+        return ESP_OK;
+    }
+
     esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
     esp_sntp_setservername(0, "pool.ntp.org");
     esp_sntp_set_time_sync_notification_cb(on_SNTP_Time_Sync);
     esp_sntp_init();
 
+    _sntp_initialized = true;
     return ESP_OK;
 }
 
 esp_err_t SNTP_Deinit(void)
 {
+    if (!_sntp_initialized) {
+        return ESP_OK;
+    }
+
     esp_sntp_stop();
+    _sntp_initialized = false;
     return ESP_OK;
 }

69-79: Off-by-one in retry logic - first attempt counts as retry.

The ++Retry increment happens before the first delay, meaning the first actual check at iteration start consumes one retry count. If Retries=1, the loop body executes once but logs "1/1" on the first wait, which is slightly misleading. Consider using post-increment or restructuring.

🔎 Proposed fix
-    while ((TimeInfo.tm_year < (2016 - 1900)) && (++Retry < Retries)) {
-        ESP_LOGD(TAG, "Waiting for system time... (%d/%d)", Retry, Retries);
+    while ((TimeInfo.tm_year < (2016 - 1900)) && (Retry < Retries)) {
+        Retry++;
+        ESP_LOGD(TAG, "Waiting for system time... (%d/%d)", Retry, Retries);
         vTaskDelay(2000 / portTICK_PERIOD_MS);
         time(&Now);
         localtime_r(&Now, &TimeInfo);
     }

81-86: Redundant time retrieval after successful sync.

Lines 83-84 retrieve time again after the loop succeeds, but Now and TimeInfo were already populated in the loop. This is harmless but unnecessary.

main/Application/Tasks/Devices/devicesTask.cpp (3)

97-110: Minor inconsistency: Now recalculated unnecessarily.

Line 97 stores esp_timer_get_time() / 1000 in Now, but line 110 recalculates the same value instead of reusing Now. While functionally correct (slight time may have passed), this seems unintentional.

🔎 Suggested fix
-            _DevicesTask_State.LastBatteryUpdate = esp_timer_get_time() / 1000;
+            _DevicesTask_State.LastBatteryUpdate = Now;

40-41: Unused constant DEVICES_TASK_TIME_SYNCED.

DEVICES_TASK_TIME_SYNCED (BIT1) is defined but never used in this file. Consider removing it to avoid confusion, or implement the intended functionality.


194-202: Unused task parameter p_AppContext.

p_AppContext is passed to Task_Devices but the task never uses it. Either use it or remove the parameter and pass NULL instead.

main/Application/Tasks/GUI/Export/ui_events.cpp (2)

35-39: Event posting uses zero timeout.

esp_event_post with timeout 0 means the call won't block if the event queue is full - events could be silently dropped. Consider using portMAX_DELAY for reliability, or handle the return value.


41-194: Large block of commented-out scaffolding code.

This commented-out menu implementation is substantial. If this is intended for future use, consider moving it to a separate file or tracking it in an issue. If not needed, remove it to reduce code clutter.

Would you like me to open an issue to track the menu implementation as a TODO?

main/Application/Tasks/Network/networkTask.cpp (2)

310-310: Duplicate assignment of AppContext.

_NetworkTask_State.AppContext is assigned at line 310 and again at line 363. The second assignment is redundant.

🔎 Suggested fix
-    _NetworkTask_State.AppContext = p_AppContext;
     _NetworkTask_State.State = NETWORK_STATE_IDLE;
     _NetworkTask_State.isInitialized = true;

Also applies to: 363-363


42-42: Unused constant NETWORK_TASK_BROADCAST_FRAME.

NETWORK_TASK_BROADCAST_FRAME (BIT1) is defined but never used. Consider removing it or implementing the intended functionality.

main/Application/Tasks/GUI/guiTask.cpp (1)

535-537: Consider using named constants for image dimensions.

The values 160, 120, 240, and 180 appear multiple times throughout the file. Using named constants would improve maintainability and reduce magic numbers.

main/Application/Tasks/GUI/Private/guiHelper.h (1)

42-55: Event bit definitions have inconsistent ordering.

The event bits are defined out of numerical order (BIT0-BIT3, then BIT7-BIT13, then BIT4-BIT6). While functionally correct, this makes it harder to track which bits are used. Consider reordering for clarity.

main/Application/Manager/Network/Server/image_encoder.cpp (2)

170-179: Missing initialization check in Encode function.

Image_Encoder_Encode doesn't verify _Encoder_State.isInitialized before proceeding. While it may work without initialization (using default quality 0 clamped to 1), this inconsistency with other functions could lead to unexpected behavior.

🔎 Suggested fix
 esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame,
                                Network_ImageFormat_t Format,
                                Server_Palette_t Palette,
                                Network_Encoded_Image_t *p_Encoded)
 {
     esp_err_t Error;
 
     if ((p_Frame == NULL) || (p_Encoded == NULL)) {
         return ESP_ERR_INVALID_ARG;
     }
+
+    if (_Encoder_State.isInitialized == false) {
+        ESP_LOGE(TAG, "Encoder not initialized!");
+        return ESP_ERR_INVALID_STATE;
+    }

240-252: SetQuality doesn't check initialization state.

Image_Encoder_SetQuality allows setting quality even when the encoder isn't initialized. While this may be intentional (pre-configure before init), it's inconsistent with the isInitialized pattern used elsewhere.

main/Application/Manager/Network/Server/http_server.cpp (3)

192-196: Blocking esp_event_post in HTTP handler may stall server.

Using portMAX_DELAY in an HTTP request handler can block indefinitely if the event queue is full, stalling the HTTP server. Consider using a finite timeout.

🔎 Proposed fix
     /* Set timezone if provided */
     if (cJSON_IsString(timezone) && (timezone->valuestring != NULL)) {
-        esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, (void *)timezone->valuestring, strlen(timezone->valuestring) + 1,
-                       portMAX_DELAY);
+        esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, (void *)timezone->valuestring, strlen(timezone->valuestring) + 1,
+                       100 / portTICK_PERIOD_MS);
     }

427-432: Unreachable code after esp_restart().

The return Error; statement on line 431 will never execute since esp_restart() does not return. This is dead code but harmless.

🔎 Proposed fix
     /* Reboot after response is sent */
     vTaskDelay(1000 / portTICK_PERIOD_MS);
     esp_restart();
-
-    return Error;
+
+    /* esp_restart() does not return, but the compiler may warn without this */
+    return ESP_OK;
 }

571-579: Return values of httpd_register_uri_handler are not checked.

If any URI handler registration fails, the server may operate in an inconsistent state with some endpoints missing. Consider checking return values or at minimum logging failures.

🔎 Proposed fix
     /* Register URI handlers */
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time);
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image);
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry);
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update);
+    esp_err_t reg_err;
+    reg_err = httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time);
+    if (reg_err != ESP_OK) ESP_LOGW(TAG, "Failed to register /time: %s", esp_err_to_name(reg_err));
+    reg_err = httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image);
+    if (reg_err != ESP_OK) ESP_LOGW(TAG, "Failed to register /image: %s", esp_err_to_name(reg_err));
+    reg_err = httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry);
+    if (reg_err != ESP_OK) ESP_LOGW(TAG, "Failed to register /telemetry: %s", esp_err_to_name(reg_err));
+    reg_err = httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update);
+    if (reg_err != ESP_OK) ESP_LOGW(TAG, "Failed to register /update: %s", esp_err_to_name(reg_err));

     if (_HTTPServer_State.Config.EnableCORS) {
-        httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Options);
+        reg_err = httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Options);
+        if (reg_err != ESP_OK) ESP_LOGW(TAG, "Failed to register OPTIONS: %s", esp_err_to_name(reg_err));
     }
main/Application/Manager/Network/networkManager.cpp (2)

96-187: Consider refactoring disconnect reason decoding to a lookup table.

The large switch statement for decoding disconnect reasons is functional but verbose. A static lookup table would be more compact and maintainable.


359-373: Inconsistent error handling: ESP_ERROR_CHECK aborts without cleanup.

Earlier in NetworkManager_Init, errors are handled gracefully with cleanup. However, ESP_ERROR_CHECK on lines 359, 365, and 372 will abort the program on failure, potentially leaving resources allocated (netifs, event group). Consider consistent error handling throughout.

🔎 Proposed fix for line 315 and 359-372
     /* Initialize TCP/IP stack */
-    ESP_ERROR_CHECK(esp_netif_init());
+    Error = esp_netif_init();
+    if (Error != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to init netif: %d!", Error);
+        vEventGroupDelete(_Network_Manager_State.EventGroup);
+        _Network_Manager_State.EventGroup = NULL;
+        return Error;
+    }

     ...

-    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
+    Error = esp_event_handler_instance_register(WIFI_EVENT,
                                                         ESP_EVENT_ANY_ID,
                                                         &on_WiFi_Event,
                                                         NULL,
-                                                        NULL));
+                                                        NULL);
+    if (Error != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to register WiFi event handler: %d!", Error);
+        // cleanup previously allocated resources...
+        return Error;
+    }
main/Application/application.h (1)

40-54: Consider using typed enums for event identifiers.

The anonymous enum for Lepton events provides no type safety. If mixed with other event enums, the compiler won't catch misuse. Consider using a typed enum.

🔎 Proposed enhancement
-/** @brief Lepton camera event identifiers.
- */
-enum {
+/** @brief Lepton camera event identifiers.
+ */
+typedef enum {
     LEPTON_EVENT_CAMERA_READY,
     ...
-};
+} Lepton_Event_t;
main/Application/Manager/Network/Provisioning/provisioning.cpp (3)

330-348: Provisioning_isProvisioned initializes and deinitializes manager on each call.

While this follows ESP-IDF's API requirements, it's expensive if called frequently. Consider caching the result after first check if this is called in a hot path.


199-210: Timer creation failure is not logged.

If xTimerCreate returns NULL (memory exhaustion), the provisioning timeout feature will silently fail. Consider logging a warning.

🔎 Proposed enhancement
     _Provisioning_State.timeout_timer = xTimerCreate("prov_timeout",
                                                      (_Provisioning_State.timeout_sec * 1000) / portTICK_PERIOD_MS,
                                                      pdFALSE,
                                                      NULL,
                                                      on_Timeout_Timer_Handler);
+    if (_Provisioning_State.timeout_timer == NULL) {
+        ESP_LOGW(TAG, "Failed to create timeout timer - provisioning timeout disabled");
+    }

     _Provisioning_State.isInitialized = true;

218-222: Consider documenting the purpose of the 200ms delay in Provisioning_Deinit.

The vTaskDelay(200 / portTICK_PERIOD_MS) appears to allow time for Provisioning_Stop to complete. A brief comment would clarify this intent.

main/Application/Manager/Network/network_types.h (1)

199-207: Clarify ownership semantics for API_Key pointer in Server_Config_t.

The API_Key is a const char* pointer. It's unclear whether the configuration takes ownership of this string or expects the caller to maintain its lifetime. Consider documenting this or using a fixed-size array for self-contained storage.

🔎 Proposed documentation or alternative

Option 1 - Document ownership:

 typedef struct {
     uint16_t HTTP_Port;
     uint8_t MaxClients;
     uint16_t WSPingIntervalSec;
     bool EnableCORS;
-    const char *API_Key;
+    const char *API_Key;                /**< API key for authentication (caller must ensure lifetime) */
 } Server_Config_t;

Option 2 - Use fixed buffer:

-    const char *API_Key;
+    char API_Key[65];                   /**< API key for authentication (empty string = disabled) */
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d42ff7 and f697856.

📒 Files selected for processing (36)
  • components/ESP32-Lepton
  • main/Application/Manager/Devices/ADC/adc.cpp
  • main/Application/Manager/Devices/SPI/spi.cpp
  • main/Application/Manager/Network/Provisioning/provisioning.cpp
  • main/Application/Manager/Network/Provisioning/provisioning.h
  • main/Application/Manager/Network/SNTP/sntp.cpp
  • main/Application/Manager/Network/Server/http_server.cpp
  • main/Application/Manager/Network/Server/image_encoder.cpp
  • main/Application/Manager/Network/Server/image_encoder.h
  • main/Application/Manager/Network/Server/websocket_handler.cpp
  • main/Application/Manager/Network/networkManager.cpp
  • main/Application/Manager/Network/networkManager.h
  • main/Application/Manager/Network/network_types.h
  • main/Application/Manager/SD/sdManager.cpp
  • main/Application/Manager/Settings/settingsManager.cpp
  • main/Application/Manager/Settings/settings_types.h
  • main/Application/Tasks/Devices/devicesTask.cpp
  • main/Application/Tasks/GUI/Export/project.info
  • main/Application/Tasks/GUI/Export/screens/ui_Info.c
  • main/Application/Tasks/GUI/Export/screens/ui_Info.h
  • main/Application/Tasks/GUI/Export/screens/ui_Main.c
  • main/Application/Tasks/GUI/Export/screens/ui_Main.h
  • main/Application/Tasks/GUI/Export/screens/ui_Menu.c
  • main/Application/Tasks/GUI/Export/screens/ui_Menu.h
  • main/Application/Tasks/GUI/Export/ui_events.cpp
  • main/Application/Tasks/GUI/Private/guiHelper.cpp
  • main/Application/Tasks/GUI/Private/guiHelper.h
  • main/Application/Tasks/GUI/guiTask.cpp
  • main/Application/Tasks/Lepton/leptonTask.cpp
  • main/Application/Tasks/Network/networkTask.cpp
  • main/Application/Tasks/Network/networkTask.h
  • main/Application/application.h
  • main/main.cpp
  • ui/PyroVision.sll
  • ui/PyroVision.spj
  • ui/project.info
🚧 Files skipped from review as they are similar to previous changes (6)
  • ui/project.info
  • ui/PyroVision.sll
  • main/Application/Tasks/GUI/Export/project.info
  • main/Application/Manager/Network/Provisioning/provisioning.h
  • main/Application/Tasks/GUI/Export/screens/ui_Info.c
  • components/ESP32-Lepton
🧰 Additional context used
🧬 Code graph analysis (15)
main/Application/Manager/Network/networkManager.h (1)
main/Application/Manager/Network/networkManager.cpp (28)
  • NetworkManager_Init (292-379)
  • NetworkManager_Init (292-292)
  • NetworkManager_Deinit (381-409)
  • NetworkManager_Deinit (381-381)
  • NetworkManager_StartSTA (411-442)
  • NetworkManager_StartSTA (411-411)
  • NetworkManager_Stop (452-465)
  • NetworkManager_Stop (452-452)
  • NetworkManager_ConnectWiFi (467-504)
  • NetworkManager_ConnectWiFi (467-467)
  • NetworkManager_DisconnectWiFi (506-515)
  • NetworkManager_DisconnectWiFi (506-506)
  • NetworkManager_isConnected (517-520)
  • NetworkManager_isConnected (517-517)
  • NetworkManager_GetState (522-525)
  • NetworkManager_GetState (522-522)
  • NetworkManager_GetIP (527-536)
  • NetworkManager_GetIP (527-527)
  • NetworkManager_GetRSSI (538-551)
  • NetworkManager_GetRSSI (538-538)
  • NetworkManager_GetMAC (553-560)
  • NetworkManager_GetMAC (553-553)
  • NetworkManager_SetCredentials (562-581)
  • NetworkManager_SetCredentials (562-562)
  • NetworkManager_GetConnectedStations (583-592)
  • NetworkManager_GetConnectedStations (583-583)
  • NetworkManager_StartServer (444-450)
  • NetworkManager_StartServer (444-444)
main/Application/Manager/Network/Server/image_encoder.h (1)
main/Application/Manager/Network/Server/image_encoder.cpp (10)
  • Image_Encoder_Init (136-157)
  • Image_Encoder_Init (136-136)
  • Image_Encoder_Deinit (159-168)
  • Image_Encoder_Deinit (159-159)
  • Image_Encoder_Encode (170-224)
  • Image_Encoder_Encode (170-173)
  • Image_Encoder_Free (226-238)
  • Image_Encoder_Free (226-226)
  • Image_Encoder_SetQuality (240-252)
  • Image_Encoder_SetQuality (240-240)
main/Application/Tasks/Devices/devicesTask.cpp (1)
main/Application/Tasks/Lepton/leptonTask.cpp (2)
  • on_GUI_Event_Handler (71-117)
  • on_GUI_Event_Handler (71-71)
main/Application/Manager/Network/Server/http_server.cpp (1)
main/Application/Manager/Network/Server/image_encoder.cpp (4)
  • Image_Encoder_Encode (170-224)
  • Image_Encoder_Encode (170-173)
  • Image_Encoder_Free (226-238)
  • Image_Encoder_Free (226-226)
main/Application/Manager/Network/networkManager.cpp (2)
main/Application/Manager/Network/Server/server.h (2)
  • Server_Init (35-58)
  • Server_Start (72-95)
main/Application/Manager/Network/SNTP/sntp.cpp (2)
  • SNTP_Deinit (53-57)
  • SNTP_Deinit (53-53)
main/Application/Tasks/Lepton/leptonTask.cpp (1)
main/Application/Tasks/Devices/devicesTask.cpp (2)
  • on_GUI_Event_Handler (66-69)
  • on_GUI_Event_Handler (66-66)
main/Application/Manager/Network/Server/websocket_handler.cpp (1)
main/Application/Manager/Network/Server/image_encoder.cpp (4)
  • Image_Encoder_Encode (170-224)
  • Image_Encoder_Encode (170-173)
  • Image_Encoder_Free (226-238)
  • Image_Encoder_Free (226-226)
main/Application/Tasks/GUI/guiTask.cpp (3)
main/Application/Manager/Network/Server/server.h (2)
  • Server_SetThermalFrame (119-123)
  • Server_isRunning (111-114)
main/Application/Tasks/GUI/Private/guiHelper.cpp (4)
  • GUI_Helper_Init (104-221)
  • GUI_Helper_Init (104-104)
  • GUI_Helper_Deinit (223-284)
  • GUI_Helper_Deinit (223-223)
main/Application/Tasks/GUI/Export/ui.c (2)
  • ui_init (27-39)
  • ui_destroy (41-47)
main/Application/Tasks/GUI/Export/screens/ui_Main.c (2)
main/Application/Tasks/GUI/Export/ui_events.cpp (4)
  • ScreenMainLoaded (12-33)
  • ScreenMainLoaded (12-12)
  • ButtonMainWiFiClicked (196-199)
  • ButtonMainWiFiClicked (196-196)
main/Application/Tasks/GUI/Export/ui_helpers.c (1)
  • _ui_screen_change (52-58)
main/Application/Tasks/GUI/Private/guiHelper.h (1)
main/Application/Tasks/GUI/Private/guiHelper.cpp (12)
  • GUI_Helper_Init (104-221)
  • GUI_Helper_Init (104-104)
  • GUI_Helper_Deinit (223-284)
  • GUI_Helper_Deinit (223-223)
  • GUI_Helper_Timer_ClockUpdate (286-301)
  • GUI_Helper_Timer_ClockUpdate (286-286)
  • GUI_Helper_Timer_SpotUpdate (303-326)
  • GUI_Helper_Timer_SpotUpdate (303-303)
  • GUI_Helper_Timer_SpotmeterUpdate (328-331)
  • GUI_Helper_Timer_SpotmeterUpdate (328-328)
  • GUI_Helper_Timer_SceneStatisticsUpdate (333-336)
  • GUI_Helper_Timer_SceneStatisticsUpdate (333-333)
main/Application/Tasks/Network/networkTask.h (1)
main/Application/Tasks/Network/networkTask.cpp (10)
  • Network_Task_Init (297-370)
  • Network_Task_Init (297-297)
  • Network_Task_Deinit (372-392)
  • Network_Task_Deinit (372-372)
  • Network_Task_Start (394-427)
  • Network_Task_Start (394-394)
  • Network_Task_Stop (429-449)
  • Network_Task_Stop (429-429)
  • Network_Task_isRunning (451-454)
  • Network_Task_isRunning (451-451)
main/Application/Tasks/GUI/Export/screens/ui_Info.h (1)
main/Application/Tasks/GUI/Export/screens/ui_Info.c (4)
  • ui_Info_screen_init (78-753)
  • ui_Info_screen_destroy (755-806)
  • ui_event_Info (54-65)
  • ui_event_Button_Info_Back (67-74)
main/Application/Tasks/GUI/Private/guiHelper.cpp (2)
main/Application/Manager/Network/Server/server.h (1)
  • Server_isRunning (111-114)
main/Application/Manager/Network/Server/websocket_handler.cpp (2)
  • WebSocket_Handler_BroadcastTelemetry (670-714)
  • WebSocket_Handler_BroadcastTelemetry (670-670)
main/Application/Tasks/GUI/Export/screens/ui_Menu.c (3)
main/Application/Tasks/GUI/Export/ui_helpers.c (1)
  • _ui_screen_change (52-58)
main/Application/Tasks/GUI/Export/screens/ui_Main.c (1)
  • ui_Main_screen_init (77-428)
main/Application/Tasks/GUI/Export/ui_events.cpp (2)
  • ScreenMenuLoaded (97-194)
  • ScreenMenuLoaded (97-97)
main/Application/Tasks/GUI/Export/screens/ui_Main.h (1)
main/Application/Tasks/GUI/Export/screens/ui_Main.c (6)
  • ui_Main_screen_init (77-428)
  • ui_Main_screen_destroy (430-466)
  • ui_event_Main (39-46)
  • ui_event_Button_Main_WiFi (48-55)
  • ui_event_Button_Main_Info (57-64)
  • ui_event_Button_Main_Menu (66-73)
🪛 Clang (14.0.6)
main/Application/Tasks/GUI/Export/screens/ui_Info.h

[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 23-23: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 24-24: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 25-25: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 26-26: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 27-27: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 28-28: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 29-29: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 30-30: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 31-31: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 32-32: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 33-33: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 34-34: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

main/Application/Tasks/GUI/Export/screens/ui_Main.h

[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 23-23: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 24-24: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 25-25: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 26-26: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 27-27: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 28-28: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 29-29: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 30-30: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 31-31: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 32-32: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 33-33: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 34-34: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

main/Application/Tasks/GUI/Export/screens/ui_Menu.h

[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 23-23: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 24-24: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

🪛 Cppcheck (2.19.0)
main/Application/Manager/Network/networkManager.cpp

[error] 232-232: There is an unknown macro here somewhere. Configuration is required. If MACSTR is a macro then please configure it.

(unknownMacro)

main/Application/Tasks/GUI/Private/guiHelper.cpp

[error] 216-216: Array 'p_GUITask_State->UpdateTimer[3]' accessed at index 3, which is out of bounds.

(arrayIndexOutOfBounds)

🔇 Additional comments (37)
main/Application/Manager/Devices/SPI/spi.cpp (2)

50-91: LGTM - Initialization is well-structured.

The function provides comprehensive validation, proper resource cleanup on failure (mutex deletion if bus init fails), and clear logging.


200-207: LGTM - Status check is straightforward and correct.

The validation and return logic are appropriate for this query function.

main/Application/Manager/SD/sdManager.cpp (5)

46-56: LGTM!

Good use of preprocessor conditionals with a compile-time error if no SPI host is defined, ensuring misconfiguration is caught early.


65-77: LGTM!

The state structure is well-organized. Good use of volatile for CardPresent since it's accessed from ISR context.


155-169: Previously flagged issue has been addressed.

The Error variable is now properly declared at line 156. The GPIO configuration and error handling look correct.


254-257: LGTM!

Simple accessor function for the volatile card presence state.


419-441: LGTM!

The unmount function properly checks for null card state, performs cleanup, and clears the card pointer.

main/Application/Manager/Network/Server/image_encoder.h (1)

31-61: LGTM!

The API is well-documented with clear doxygen comments for all functions. The header provides a clean interface for thermal frame encoding with proper lifecycle management (Init/Deinit), encoding operations, and quality control.

main/Application/Manager/Settings/settings_types.h (1)

54-105: LGTM: Well-designed settings structures with version field and reserved space.

The structure design follows good embedded practices:

  • Version field enables future migrations
  • Reserved bytes in each sub-structure allow backward-compatible extensions
  • Clear separation of settings by domain (Lepton, WiFi, Display, System)
main/Application/Tasks/Lepton/leptonTask.cpp (2)

296-303: Verify condition logic for RAW14 format check.

The condition checks if frame dimensions are zero AND format is NOT RAW14. This seems inverted - typically you'd want to skip processing if dimensions are invalid OR if the format doesn't support pixel temperature extraction. Consider if this should be:

if ((_LeptonTask_State.RawFrame.Width == 0) || (_LeptonTask_State.RawFrame.Height == 0) ||
    (VideoFormat != LEPTON_FORMAT_RAW14)) {

353-358: Scene statistics values assigned as raw intensities, not temperatures.

Unlike spotmeter handling (lines 336-338) which converts from Kelvin to Celsius, scene statistics assigns MinIntensity, MaxIntensity, and MeanIntensity directly without conversion. Verify this is intentional - the log message at line 357 suggests these should be temperatures in °C.

main/Application/Manager/Network/Server/websocket_handler.cpp (1)

140-169: LGTM - JSON message handling is well-structured.

The WS_SendJSON function properly creates a JSON object, handles memory allocation failures, and cleans up resources. Using cJSON_AddItemReferenceToObject correctly avoids double-free of the data parameter.

main/Application/Manager/Settings/settingsManager.cpp (2)

359-398: LGTM - Reset to defaults implementation is thorough.

SettingsManager_ResetToDefaults properly erases NVS key, commits, reinitializes defaults, and saves. Error handling is appropriate with early returns on failure.


284-285: No action required — esp_event_post safely copies event data.

The concern about posting events with pointers to caller's data is not an issue. The esp_event_post function internally copies the event data (allocates and manages its own copy), ensuring the event handler receives valid data even if the caller reuses or frees the original memory after posting.

main/Application/Tasks/GUI/Export/screens/ui_Main.c (1)

430-466: LGTM - Screen cleanup properly nullifies all pointers.

ui_Main_screen_destroy correctly deletes the root object (which recursively deletes children in LVGL) and nullifies all global pointers to prevent dangling references.

main/Application/Tasks/GUI/Export/screens/ui_Main.h (2)

6-56: Static analysis errors are false positives - header relies on prior LVGL inclusion.

The Clang errors about unknown types lv_obj_t and lv_event_t occur because this header is designed to be included via ui.h (as seen in ui_Main.c line 6: #include "../ui.h"), which includes LVGL headers first. This is a common pattern for generated UI code and works correctly in the actual build.


1-56: LGTM - Generated header structure is correct.

The header properly uses include guards, extern "C" for C++ compatibility, and declares all public symbols that match the implementation in ui_Main.c.

main/Application/Tasks/GUI/Export/screens/ui_Info.h (1)

1-69: LGTM - Consistent with other generated screen headers.

Same pattern as ui_Main.h with proper include guards and extern "C" wrapping. Static analysis errors are false positives due to the header being included via ui.h.

main/main.cpp (2)

84-94: No cleanup on partial initialization failure.

If GUI_Task_Init succeeds but Lepton_Task_Init fails, ESP_ERROR_CHECK will abort without cleaning up the GUI task. Similarly for subsequent initializations. Consider implementing proper cleanup on failure, or document that ESP_ERROR_CHECK abort is the intended behavior for initialization failures.

Is aborting on initialization failure the intended behavior, or should there be graceful degradation/cleanup?


96-97: LGTM - Task self-deletion is appropriate here.

Using vTaskDelete(NULL) after spawning all application tasks is the correct pattern for ESP-IDF applications. The comment correctly notes the watchdog consideration.

main/Application/Manager/Network/SNTP/sntp.cpp (1)

36-41: LGTM - Event-based sync notification is well-designed.

The callback properly posts an event with the synchronized time, allowing other components (like TimeManager) to react to SNTP sync completion.

main/Application/Tasks/GUI/Export/ui_events.cpp (1)

12-33: LGTM - Clean UI initialization.

ScreenMainLoaded correctly sets up firmware version text and assigns icons/glyphs to UI elements. The use of Unicode escape sequences for FontAwesome icons is appropriate for the font configuration.

main/Application/Tasks/Network/networkTask.cpp (1)

138-144: Provisioning_Stop called from event handler context.

The comment on line 141 mentions "Stop provisioning in task context (not timer context)", but this is still in the event handler. If events are dispatched from a timer or ISR context, calling Provisioning_Stop() here could be problematic. Consider setting an event bit and handling the stop in the task loop instead.

main/Application/Tasks/GUI/Export/screens/ui_Menu.c (2)

40-119: LGTM - Standard SquareLine Studio generated screen initialization.

The screen initialization follows the expected LVGL patterns with proper hierarchy setup, styling, and event callback registration.


121-134: LGTM - Proper cleanup in screen destroy.

The destroy function correctly checks for null before deleting and resets all pointers to NULL, preventing use-after-free issues.

main/Application/Tasks/GUI/guiTask.cpp (2)

804-824: LGTM - Robust buffer allocation with proper cleanup.

The buffer allocation sequence correctly handles failures by freeing previously allocated buffers before returning error. Good defensive coding.


613-644: LGTM - Thread-safe network frame update.

The network frame update properly uses mutex protection with non-blocking acquire (xSemaphoreTake(..., 0)), which is appropriate for real-time thermal streaming where dropping a frame is better than blocking.

main/Application/Tasks/GUI/Private/guiHelper.h (1)

57-100: LGTM - Well-structured state management.

The GUI_Task_State_t structure cleanly aggregates all GUI-related state, handles, buffers, and optional debug elements with conditional compilation.

main/Application/Manager/Network/Server/image_encoder.cpp (2)

136-157: LGTM - Proper initialization with quality clamping.

Quality bounds are correctly enforced during initialization, and the function is idempotent (returns OK if already initialized).


197-223: LGTM - Memory management in encoding paths is correct.

The JPEG path allocates its own output buffer and frees rgb_buffer. The RAW path transfers ownership of rgb_buffer to the caller and returns early. The PNG fallback properly warns and uses RAW format.

main/Application/Manager/Network/Server/http_server.cpp (1)

253-291: LGTM - Frame locking and image encoding are properly handled.

The mutex acquisition with timeout, frame encoding, mutex release, and cleanup via Image_Encoder_Free are correctly sequenced. Error paths are handled appropriately.

main/Application/Manager/Network/networkManager.cpp (2)

467-504: LGTM - NetworkManager_ConnectWiFi flow is correct.

The function properly updates credentials, restarts WiFi via Stop/StartSTA (which clears event bits), and waits for connection result with appropriate timeout handling.


232-234: Static analysis false positive: MACSTR is a valid ESP-IDF macro.

The Cppcheck warning about MACSTR being an unknown macro is a false positive. MACSTR and MAC2STR are defined in esp_mac.h (included on line 28) and are standard ESP-IDF macros for formatting MAC addresses.

main/Application/Manager/Network/networkManager.h (1)

36-111: LGTM - Header declarations are well-documented and consistent with implementation.

The function declarations match the implementations in networkManager.cpp. Documentation is clear and follows a consistent style.

main/Application/application.h (1)

127-131: Union aliasing Average and Mean is intentional and clear.

The union provides semantic flexibility for callers to use either Average or Mean interchangeably, which is appropriate since they represent the same value in this context.

main/Application/Manager/Network/Provisioning/provisioning.cpp (1)

150-170: LGTM - Custom endpoint follows ESP provisioning API contract.

The allocated response buffer will be freed by the ESP provisioning framework after the response is sent. This is the expected usage pattern.

main/Application/Manager/Network/network_types.h (1)

134-145: LGTM - Network_Thermal_Frame_t is well-designed for thread-safe frame sharing.

The structure includes a mutex for synchronization, timestamp for frame identification, and all necessary metadata. This aligns well with usage in HTTP_Handler_Image.

Comment on lines +201 to +206
if (_Network_Manager_State.RetryCount < _Network_Manager_State.STA_Config->MaxRetries) {
ESP_LOGD(TAG, "Retry %d/%d", _Network_Manager_State.RetryCount++, _Network_Manager_State.STA_Config->MaxRetries);

vTaskDelay(_Network_Manager_State.STA_Config->RetryInterval / portTICK_PERIOD_MS);
esp_wifi_connect();
_Network_Manager_State.State = NETWORK_STATE_CONNECTING;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Blocking delay in event handler can stall the event loop.

Calling vTaskDelay() inside the WiFi event handler blocks the system event task, potentially causing other events to be delayed or missed. Consider using a timer or posting to a separate task for retry logic.

🔎 Proposed alternative approach

Instead of blocking in the event handler, use a FreeRTOS timer for delayed reconnection:

// In state structure, add:
TimerHandle_t ReconnectTimer;

// Timer callback:
static void on_Reconnect_Timer(TimerHandle_t timer) {
    esp_wifi_connect();
}

// In disconnect handler, replace vTaskDelay with:
if (_Network_Manager_State.RetryCount < _Network_Manager_State.STA_Config->MaxRetries) {
    _Network_Manager_State.RetryCount++;
    ESP_LOGD(TAG, "Retry %d/%d", _Network_Manager_State.RetryCount, _Network_Manager_State.STA_Config->MaxRetries);
    xTimerChangePeriod(_Network_Manager_State.ReconnectTimer, 
                       _Network_Manager_State.STA_Config->RetryInterval / portTICK_PERIOD_MS, 0);
    xTimerStart(_Network_Manager_State.ReconnectTimer, 0);
    _Network_Manager_State.State = NETWORK_STATE_CONNECTING;
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

♻️ Duplicate comments (21)
main/Application/Manager/SD/sdManager.cpp (4)

102-112: ISR safety issue already flagged in previous review.

The TODO at line 108 acknowledges this issue. The esp_timer_stop() and esp_timer_start_once() calls are not IRAM-safe and should be replaced with xTimerResetFromISR() as suggested in the previous review.


239-243: Race condition with fixed delay already flagged in previous review.

The arbitrary 100ms delay doesn't guarantee SDManager_MountTask completion. Use proper task synchronization as suggested previously.


365-376: WDT timeout risk with portMAX_DELAY already flagged in previous review.

Use a bounded timeout for esp_event_post() as previously suggested to prevent watchdog timeouts.


419-441: No guard against unmounting while mount task is still running.

If SDManager_Unmount() is called while SDManager_MountTask is actively mounting, this could cause undefined behavior or filesystem corruption. Consider checking MountTaskHandle before unmounting.

🔎 Proposed fix
 esp_err_t SDManager_Unmount(void)
 {
     esp_err_t Error;

+    /* Don't unmount while mount is in progress */
+    if (_SD_Manager_State.MountTaskHandle != NULL) {
+        ESP_LOGW(TAG, "Cannot unmount: mount task in progress");
+        return ESP_ERR_INVALID_STATE;
+    }
+
     if (_SD_Manager_State.Card == NULL) {
         return ESP_OK;
     }
main/Application/Manager/Devices/ADC/adc.cpp (1)

60-76: Redundant condition: _ADC_Calib_Done is always false at check.

Line 61 sets _ADC_Calib_Done = false, and line 63 immediately checks if (_ADC_Calib_Done == false). This condition is always true, making the check unnecessary.

🔎 Proposed fix
     Error = ESP_OK;
-    _ADC_Calib_Done = false;
 
-    if (_ADC_Calib_Done == false) {
-        ESP_LOGD(TAG, "calibration scheme version is %s", "Curve Fitting");
-        adc_cali_curve_fitting_config_t CaliConfig = {
-            .unit_id = _ADC_Init_Config.unit_id,
-            .chan = ADC_CHANNEL_0,
-            .atten = config.atten,
-            .bitwidth = ADC_BITWIDTH_DEFAULT,
-        };
+    ESP_LOGD(TAG, "calibration scheme version is %s", "Curve Fitting");
+    adc_cali_curve_fitting_config_t CaliConfig = {
+        .unit_id = _ADC_Init_Config.unit_id,
+        .chan = ADC_CHANNEL_0,
+        .atten = config.atten,
+        .bitwidth = ADC_BITWIDTH_DEFAULT,
+    };
 
-        Error = adc_cali_create_scheme_curve_fitting(&CaliConfig, &_ADC_Calib_Handle);
-        if (Error == ESP_OK) {
-            _ADC_Calib_Done = true;
-        }
+    Error = adc_cali_create_scheme_curve_fitting(&CaliConfig, &_ADC_Calib_Handle);
+    if (Error == ESP_OK) {
+        _ADC_Calib_Done = true;
     }
main/Application/Tasks/GUI/Private/guiHelper.cpp (1)

212-216: Array index out of bounds: UpdateTimer[3] exceeds declared array size of 3.

The UpdateTimer array is declared with size 3 in the header, allowing only indices 0–2. Writing to index 3 causes a buffer overflow. Increase the array size to 4 in guiHelper.h.

main/Application/Manager/Devices/PortExpander/portexpander.cpp (1)

264-277: Inverted logic in EnableCamera and EnableBatteryVoltage.

Lines 160-162 document that camera power is active-high ((0x01 << PIN_CAMERA) enables it). However, PortExpander_EnableCamera(true) writes !Enable (LOW), which disables the camera. The same issue affects PortExpander_EnableBatteryVoltage. Note that PortExpander_EnableLED correctly uses Enable without negation.

🔎 Proposed fix
 esp_err_t PortExpander_EnableCamera(bool Enable)
 {
-    return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_CAMERA), (!Enable << PIN_CAMERA));
+    return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_CAMERA), (Enable << PIN_CAMERA));
 }
 
 esp_err_t PortExpander_EnableLED(bool Enable)
 {
     return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_LED), (Enable << PIN_LED));
 }
 
 esp_err_t PortExpander_EnableBatteryVoltage(bool Enable)
 {
-    return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_BATTERY_VOLTAGE_ENABLE), (!Enable << PIN_BATTERY_VOLTAGE_ENABLE));
+    return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_BATTERY_VOLTAGE_ENABLE), (Enable << PIN_BATTERY_VOLTAGE_ENABLE));
 }
main/Application/Tasks/GUI/Private/guiHelper.h (1)

77-77: Buffer overflow — UpdateTimer array sized for 3 but implementation uses 4 timers.

This issue has already been flagged: UpdateTimer is declared with size [3] but the implementation in guiHelper.cpp assigns four timers at indices 0–3 (ClockUpdate, SpotUpdate, SpotmeterUpdate, SceneStatisticsUpdate), causing an out-of-bounds write at index [3].

main/Application/Tasks/GUI/Export/ui.c (1)

41-47: Memory leak concern already flagged.

The missing cleanup of ui____initial_actions0 in ui_destroy() was previously identified. This object is created with a NULL parent at line 37 and requires explicit deletion to prevent a memory leak.

main/Application/Tasks/GUI/Export/screens/ui_Menu.h (1)

6-24: Missing LVGL header include causes compilation errors.

This issue was previously identified - the header uses lv_event_t and lv_obj_t types but doesn't include lvgl.h, causing compilation errors.

main/Application/Tasks/GUI/guiTask.cpp (1)

959-971: Task forcefully deleted without graceful shutdown.

This issue was previously identified. vTaskDelete() is called directly, bypassing the task's cleanup code including esp_task_wdt_delete(NULL). This can leave the watchdog thinking the task is still registered and skip proper resource cleanup.

main/Application/Tasks/Network/networkTask.cpp (1)

93-100: Potential use-after-free: storing pointer to event data.

This issue was previously identified. Line 96 stores a pointer to event data (p_Data) which may become invalid after the event handler returns. Line 271 later uses memcpy with this potentially dangling pointer.

main/Application/Tasks/GUI/Export/screens/ui_Menu.c (1)

16-27: Potential null pointer dereference with lv_indev_active().

This issue was previously identified. lv_indev_active() is called twice (lines 20-21) and may return NULL if no input device is active. Passing NULL to lv_indev_get_gesture_dir() and lv_indev_wait_release() could cause a crash.

main/Application/Manager/Network/Server/http_server.cpp (3)

115-127: Missing null check for cJSON_CreateObject.

This issue was previously identified. If cJSON_CreateObject() returns NULL (memory allocation failure), the subsequent cJSON_AddStringToObject and cJSON_AddNumberToObject calls will dereference a null pointer.


305-335: Missing null check for cJSON_CreateObject.

This issue was previously identified. If cJSON_CreateObject() fails, subsequent operations will dereference a null pointer.


344-370: Enable CONFIG_SECURE_BOOT_V2 for production OTA updates.

This issue was previously identified. The OTA handler has no signature verification without CONFIG_SECURE_BOOT=y enabled in sdkconfig, allowing unsigned firmware to be flashed.

main/Application/Manager/Network/Server/websocket_handler.cpp (2)

68-77: Missing mutex protection in WS_FindClient.

This issue was previously raised - WS_FindClient accesses _WSHandler_State.Clients without holding ClientsMutex, creating a race condition with WS_AddClient/WS_RemoveClient.


602-635: Releasing mutex during iteration can cause use-after-free.

This issue was previously raised - copying the client FD and re-validating after re-acquiring the mutex is needed to prevent operating on stale/reused client slots.

main/Application/Manager/Network/networkManager.cpp (2)

201-206: Blocking delay in event handler can stall the event loop.

This issue was previously raised - using vTaskDelay() inside the WiFi event handler blocks the system event task. Consider using a timer or posting to a separate task for retry logic.


444-450: NetworkManager_StartServer ignores return values from Server_Init and Server_Start.

This issue was previously raised - both functions can fail but their errors are not propagated.

main/Application/Manager/Network/Provisioning/provisioning.cpp (1)

114-116: Password logged in plaintext is a security/compliance risk.

This issue was previously raised - logging WiFi passwords poses a security risk if logs are captured or persisted.

🟡 Minor comments (8)
main/Application/Tasks/Devices/devicesTask.cpp-217-233 (1)

217-233: Fix inconsistent state on stop timeout.

If the task fails to stop within the timeout (line 228–230), the function returns ESP_ERR_TIMEOUT, but line 233 still executes and sets TaskHandle to NULL. This creates inconsistent state where Running is true but TaskHandle is NULL.

🔎 Recommended fix

Move line 233 inside the success path:

     if (_DevicesTask_State.Running) {
         ESP_LOGE(TAG, "Task did not stop in time");
         return ESP_ERR_TIMEOUT;
     }

     _DevicesTask_State.TaskHandle = NULL;

     return ESP_OK;

This ensures TaskHandle is only cleared when the task has actually stopped.

Committable suggestion skipped: line range outside the PR's diff.

main/Application/Tasks/GUI/guiTask.cpp-647-647 (1)

647-647: Minor typo in comment.

"recieved" should be "received".

main/Application/Tasks/GUI/guiTask.cpp-336-340 (1)

336-340: Logic error in minimum size constraint check.

The else if on line 338 means that h is only checked for minimum size when w >= 10. Both dimensions should be independently constrained.

🔎 Proposed fix
     /* Minimum size constraints */
     if (w < 10) {
         w = 10;
-    } else if (h < 10) {
+    }
+    if (h < 10) {
         h = 10;
     }
main/Application/Manager/Network/Server/websocket_handler.cpp-687-688 (1)

687-688: Reading ThermalFrame fields without mutex in WebSocket_Handler_BroadcastTelemetry.

Line 688 accesses _WSHandler_State.ThermalFrame->temp_avg without holding the frame's mutex, while WS_BroadcastTask properly acquires ThermalFrame->mutex before accessing frame data. This inconsistency could lead to reading torn/inconsistent temperature values.

🔎 Proposed fix
     /* Build telemetry data */
     cJSON *data = cJSON_CreateObject();

     if (_WSHandler_State.ThermalFrame != NULL) {
+        if (xSemaphoreTake(_WSHandler_State.ThermalFrame->mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) {
-        cJSON_AddNumberToObject(data, "temp", _WSHandler_State.ThermalFrame->temp_avg);
+            cJSON_AddNumberToObject(data, "temp", _WSHandler_State.ThermalFrame->temp_avg);
+            xSemaphoreGive(_WSHandler_State.ThermalFrame->mutex);
+        }
     }
main/Application/Manager/Network/Server/websocket_handler.cpp-550-558 (1)

550-558: Missing mutex protection for ClientCount access.

WebSocket_Handler_GetClientCount and WebSocket_Handler_HasClients read _WSHandler_State.ClientCount without mutex protection. This creates a data race with WS_AddClient and WS_RemoveClient which modify ClientCount under the mutex.

🔎 Proposed fix
 uint8_t WebSocket_Handler_GetClientCount(void)
 {
-    return _WSHandler_State.ClientCount;
+    uint8_t count;
+    xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY);
+    count = _WSHandler_State.ClientCount;
+    xSemaphoreGive(_WSHandler_State.ClientsMutex);
+    return count;
 }
 
 bool WebSocket_Handler_HasClients(void)
 {
-    return _WSHandler_State.ClientCount > 0;
+    bool hasClients;
+    xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY);
+    hasClients = _WSHandler_State.ClientCount > 0;
+    xSemaphoreGive(_WSHandler_State.ClientsMutex);
+    return hasClients;
 }
main/Application/Manager/Network/Provisioning/provisioning.cpp-172-209 (1)

172-209: Unused p_Config parameter in Provisioning_Init.

The p_Config parameter is declared but never used within the function. All configuration values come from Kconfig macros (CONFIG_NETWORK_PROV_*). This could confuse callers who pass configuration expecting it to be applied.

🔎 Proposed fix

Either remove the parameter:

-esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config)
+esp_err_t Provisioning_Init(void)

Or add a comment explaining why it's reserved:

 esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config)
 {
+    (void)p_Config;  /* Reserved for future use - config from Kconfig */
+
     if (_Provisioning_State.isInitialized) {
main/Application/Manager/Network/Provisioning/provisioning.cpp-125-133 (1)

125-133: Potential double deinitialization of wifi_prov_mgr.

In the WIFI_PROV_END event handler, wifi_prov_mgr_deinit() is called at line 128. However, Provisioning_Deinit() (lines 212-232) also calls wifi_prov_mgr_deinit() at line 222. If WIFI_PROV_END fires before Provisioning_Deinit() is called, the manager will be deinitialized twice.

🔎 Proposed fix

Track deinit state or guard the call in Provisioning_Deinit:

 void Provisioning_Deinit(void)
 {
     if (_Provisioning_State.isInitialized == false) {
         return;
     }

     Provisioning_Stop();

     vTaskDelay(200 / portTICK_PERIOD_MS);

-    wifi_prov_mgr_deinit();
+    /* wifi_prov_mgr_deinit may have been called in WIFI_PROV_END event */
+    if (_Provisioning_State.active) {
+        wifi_prov_mgr_deinit();
+    }

Or remove the deinit call from the event handler since Provisioning_Deinit handles cleanup.

Committable suggestion skipped: line range outside the PR's diff.

main/Application/Manager/Network/network_types.h-77-78 (1)

77-78: Complete the documentation comment.

The documentation for NETWORK_EVENT_CREDENTIALS_UPDATED is incomplete: "Data is of ...". Please specify the data type for this event.

🔎 Suggested completion
-    NETWORK_EVENT_CREDENTIALS_UPDATED,          /**< New WiFi credentials have been set
-                                                     Data is of ... */
+    NETWORK_EVENT_CREDENTIALS_UPDATED,          /**< New WiFi credentials have been set
+                                                     Data is of type Network_WiFi_Credentials_t */
🧹 Nitpick comments (18)
main/Application/Tasks/GUI/Export/project.info (1)

2-2: Consider using a more descriptive project name.

The generic name "SquareLine_Project.spj" could be replaced with a name that reflects the actual project (e.g., "PyroVision_GUI.spj" or similar).

main/Application/Manager/SD/sdManager.cpp (1)

65-77: Consider initializing state structure to prevent undefined behavior.

The static _SD_Manager_State structure relies on BSS zero-initialization, which works but could be more explicit. If this code is ever moved or the struct is made non-static, uninitialized pointers could cause issues.

🔎 Proposed fix
-static SD_Manager_State_t _SD_Manager_State;
+static SD_Manager_State_t _SD_Manager_State = {};
main/Application/Tasks/GUI/Private/guiHelper.cpp (1)

256-256: Missing NULL check before deleting touch handle.

Other resources in the deinit function are guarded with NULL checks, but esp_lcd_touch_del is called unconditionally. This could cause issues if initialization failed partway.

🔎 Proposed fix
-    esp_lcd_touch_del(p_GUITask_State->TouchHandle);
+    if (p_GUITask_State->TouchHandle != NULL) {
+        esp_lcd_touch_del(p_GUITask_State->TouchHandle);
+        p_GUITask_State->TouchHandle = NULL;
+    }
main/Application/Manager/Devices/ADC/adc.cpp (1)

51-51: Missing static qualifier on TAG.

TAG is defined without static, which can cause ODR (One Definition Rule) violations if this translation unit is linked with others that also define a TAG variable.

🔎 Proposed fix
-const char *TAG = "ADC";
+static const char *TAG = "ADC";
main/Application/Manager/Devices/PortExpander/portexpander.cpp (1)

230-247: Unused parameter p_Config in PortExpander_Init.

The p_Config parameter is passed but never used (only the bus handle is needed). Consider removing it from the signature or documenting why it's reserved for future use.

main/Application/Manager/Settings/settings_types.h (1)

54-105: Consider explicit packing for NVS blob storage compatibility.

These structures are stored in NVS and include a Version field for migration. However, implicit compiler padding between members (e.g., after bool fields) may differ across compiler versions or optimization settings, potentially causing settings corruption during firmware upgrades.

Consider adding __attribute__((packed)) or using explicit padding bytes to ensure consistent binary layout.

main/Application/Manager/Devices/RTC/rtc.cpp (1)

103-103: Storing pointer to caller's handle creates lifetime dependency.

_RTC_Dev_Handle stores a pointer to the caller's p_Dev_Handle variable. If the caller's storage is not persistent (e.g., a local variable), this becomes a dangling pointer. The current usage in DevicesManager stores it in a static struct which is safe, but this pattern is fragile.

Consider storing the handle value directly (i2c_master_dev_handle_t) instead of a pointer to it, consistent with how _Expander_Dev_Handle works in portexpander.cpp.

Also applies to: 192-207

main/Application/Tasks/GUI/Export/ui_events.h (1)

1-22: Include LVGL headers for self-contained header.

The header declares functions using lv_event_t* (lines 13–16) but does not include the LVGL headers that define this type. Static analysis correctly flags "unknown type name 'lv_event_t'". While the implementation file likely includes the necessary headers, this header should be self-contained to avoid compilation issues when included in other files.

🔎 Recommended fix

Add the LVGL include after line 7:

 #ifndef _UI_EVENTS_H
 #define _UI_EVENTS_H

+#include <lvgl.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif

This ensures lv_event_t is defined when the header is included.

main/Application/Tasks/GUI/Export/ui_events.cpp (2)

37-38: Consider checking esp_event_post return values.

Both event posts use a timeout of 0, which is non-blocking and can fail silently if the event queue is full. Consider logging or handling failures for debugging purposes.

🔎 Proposed improvement
 void ScreenInfoLoaded(lv_event_t *e)
 {
-    esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_UPTIME, NULL, 0, 0);
-    esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_FPA_AUX_TEMP, NULL, 0, 0);
+    if (esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_UPTIME, NULL, 0, 0) != ESP_OK) {
+        ESP_LOGW("ui_events", "Failed to post uptime request event");
+    }
+    if (esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_FPA_AUX_TEMP, NULL, 0, 0) != ESP_OK) {
+        ESP_LOGW("ui_events", "Failed to post FPA temp request event");
+    }
 }

41-95: Consider removing or tracking commented placeholder code.

This file contains ~150 lines of commented-out menu scaffolding code. If this is planned functionality, consider tracking it in an issue rather than keeping it in the codebase. Commented code can become stale and confusing over time.

main/Application/Tasks/GUI/guiTask.cpp (1)

481-497: Add timeout to splash screen loading loop as noted in TODO.

The loop waiting for LEPTON_CAMERA_READY has no timeout mechanism. If the Lepton camera fails to initialize, this will loop indefinitely (though watchdog resets will occur every 100ms cycle).

Would you like me to help implement a timeout mechanism that shows an error state after a configurable duration?

main/Application/Tasks/Network/networkTask.cpp (1)

169-185: Remove or activate commented auto-connect logic.

This block contains commented-out auto-connect logic. If this is planned functionality, consider tracking it in an issue. If not needed, remove the dead code to improve maintainability.

main/Application/Manager/Network/Server/http_server.cpp (1)

571-579: Consider checking httpd_register_uri_handler return values.

URI handler registrations can fail (e.g., if max handlers exceeded). Consider logging failures for debugging.

🔎 Example improvement
     /* Register URI handlers */
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time);
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image);
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry);
-    httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update);
+    if (httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time) != ESP_OK) {
+        ESP_LOGW(TAG, "Failed to register /time handler");
+    }
+    if (httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image) != ESP_OK) {
+        ESP_LOGW(TAG, "Failed to register /image handler");
+    }
+    if (httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry) != ESP_OK) {
+        ESP_LOGW(TAG, "Failed to register /telemetry handler");
+    }
+    if (httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update) != ESP_OK) {
+        ESP_LOGW(TAG, "Failed to register /update handler");
+    }
main/Application/Manager/Network/networkManager.cpp (1)

314-377: Incomplete cleanup on failure after partial initialization.

ESP_ERROR_CHECK at line 315 (esp_netif_init) will abort the program if it fails, but by that point EventGroup has already been allocated. More critically, lines 359-369 use ESP_ERROR_CHECK for event handler registration without cleanup - if registration fails, previously created resources (netifs, WiFi) are leaked before the abort.

Consider either:

  1. Making all initialization failures recoverable with proper cleanup, or
  2. Ensuring ESP_ERROR_CHECK is only used when partial cleanup is acceptable (typically at boot)
🔎 Proposed fix for recoverable initialization
     /* Initialize TCP/IP stack */
-    ESP_ERROR_CHECK(esp_netif_init());
+    Error = esp_netif_init();
+    if (Error != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to init netif: %d!", Error);
+        vEventGroupDelete(_Network_Manager_State.EventGroup);
+        _Network_Manager_State.EventGroup = NULL;
+        return Error;
+    }
main/Application/Manager/Network/Provisioning/provisioning.h (2)

27-27: Missing FreeRTOS include for TaskHandle_t.

Line 67 uses TaskHandle_t but the header doesn't include <freertos/FreeRTOS.h> or <freertos/task.h>. This relies on transitive includes from network_types.h, which is fragile and may break if that header's includes change.

🔎 Proposed fix
 #include "../network_types.h"
+
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>

29-33: Unused parameter p_Config in Provisioning_Init.

The function signature declares Network_WiFi_STA_Config_t *p_Config, but reviewing the implementation (from relevant snippets), this parameter is never used. The function only configures device name, POP, and timeout from Kconfig options.

Consider either:

  1. Removing the unused parameter if configuration comes solely from Kconfig
  2. Using the parameter to allow runtime configuration override
main/Application/Manager/Settings/settingsManager.cpp (1)

384-390: Redundant PendingChanges = false before calling SettingsManager_Save.

Line 386 sets _State.PendingChanges = false, but SettingsManager_Save (line 390) also sets it to false at line 241. This is harmless but redundant.

🔎 Proposed fix
     _SettingsManager_InitDefaults(&_State.Settings);
-    _State.PendingChanges = false;

     xSemaphoreGive(_State.Mutex);

     SettingsManager_Save(&_State.Settings);
main/Application/Tasks/GUI/Export/ui_helpers.h (1)

68-69: Formatting: semicolon placement.

The semicolon appears on a separate line after the function declaration. While syntactically valid, this is unusual. Since this is a generated file, the formatting is controlled by SquareLine Studio's code generator.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f697856 and ffe5e45.

📒 Files selected for processing (52)
  • components/ESP32-Lepton
  • main/Application/Manager/Devices/ADC/adc.cpp
  • main/Application/Manager/Devices/PortExpander/portexpander.cpp
  • main/Application/Manager/Devices/RTC/rtc.cpp
  • main/Application/Manager/Devices/SPI/spi.cpp
  • main/Application/Manager/Devices/devicesManager.cpp
  • main/Application/Manager/Devices/devicesManager.h
  • main/Application/Manager/Network/Provisioning/provisioning.cpp
  • main/Application/Manager/Network/Provisioning/provisioning.h
  • main/Application/Manager/Network/SNTP/sntp.cpp
  • main/Application/Manager/Network/Server/http_server.cpp
  • main/Application/Manager/Network/Server/image_encoder.cpp
  • main/Application/Manager/Network/Server/image_encoder.h
  • main/Application/Manager/Network/Server/websocket_handler.cpp
  • main/Application/Manager/Network/networkManager.cpp
  • main/Application/Manager/Network/networkManager.h
  • main/Application/Manager/Network/network_types.h
  • main/Application/Manager/SD/sdManager.cpp
  • main/Application/Manager/Settings/settingsManager.cpp
  • main/Application/Manager/Settings/settings_types.h
  • main/Application/Tasks/Devices/devicesTask.cpp
  • main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c
  • main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c
  • main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c
  • main/Application/Tasks/GUI/Export/project.info
  • main/Application/Tasks/GUI/Export/screens/ui_Info.c
  • main/Application/Tasks/GUI/Export/screens/ui_Info.h
  • main/Application/Tasks/GUI/Export/screens/ui_Main.c
  • main/Application/Tasks/GUI/Export/screens/ui_Main.h
  • main/Application/Tasks/GUI/Export/screens/ui_Menu.c
  • main/Application/Tasks/GUI/Export/screens/ui_Menu.h
  • main/Application/Tasks/GUI/Export/screens/ui_Splash.c
  • main/Application/Tasks/GUI/Export/screens/ui_Splash.h
  • main/Application/Tasks/GUI/Export/ui.c
  • main/Application/Tasks/GUI/Export/ui.h
  • main/Application/Tasks/GUI/Export/ui_events.cpp
  • main/Application/Tasks/GUI/Export/ui_events.h
  • main/Application/Tasks/GUI/Export/ui_helpers.c
  • main/Application/Tasks/GUI/Export/ui_helpers.h
  • main/Application/Tasks/GUI/Private/guiHelper.cpp
  • main/Application/Tasks/GUI/Private/guiHelper.h
  • main/Application/Tasks/GUI/guiTask.cpp
  • main/Application/Tasks/GUI/guiTask.h
  • main/Application/Tasks/Lepton/leptonTask.cpp
  • main/Application/Tasks/Lepton/leptonTask.h
  • main/Application/Tasks/Network/networkTask.cpp
  • main/Application/Tasks/Network/networkTask.h
  • main/Application/application.h
  • main/main.cpp
  • ui/PyroVision.sll
  • ui/PyroVision.spj
  • ui/project.info
🚧 Files skipped from review as they are similar to previous changes (12)
  • ui/project.info
  • components/ESP32-Lepton
  • ui/PyroVision.sll
  • main/main.cpp
  • main/Application/Manager/Network/Server/image_encoder.h
  • main/Application/Tasks/Lepton/leptonTask.h
  • main/Application/Manager/Network/Server/image_encoder.cpp
  • main/Application/Manager/Network/SNTP/sntp.cpp
  • main/Application/Tasks/GUI/Export/screens/ui_Splash.c
  • main/Application/Manager/Devices/SPI/spi.cpp
  • main/Application/Tasks/GUI/Export/ui_helpers.c
  • main/Application/Tasks/Lepton/leptonTask.cpp
🧰 Additional context used
🧬 Code graph analysis (14)
main/Application/Tasks/GUI/Export/ui_events.h (1)
main/Application/Tasks/GUI/Export/ui_events.cpp (8)
  • ScreenMainLoaded (12-33)
  • ScreenMainLoaded (12-12)
  • ButtonMainWiFiClicked (196-199)
  • ButtonMainWiFiClicked (196-196)
  • ScreenMenuLoaded (97-194)
  • ScreenMenuLoaded (97-97)
  • ScreenInfoLoaded (35-39)
  • ScreenInfoLoaded (35-35)
main/Application/Tasks/Devices/devicesTask.cpp (1)
main/Application/Manager/Devices/devicesManager.cpp (4)
  • DevicesManager_GetBatteryVoltage (174-209)
  • DevicesManager_GetBatteryVoltage (174-174)
  • DevicesManager_Init (97-139)
  • DevicesManager_Init (97-97)
main/Application/Manager/Network/Provisioning/provisioning.cpp (1)
main/Application/Manager/Network/networkManager.cpp (2)
  • NetworkManager_SetCredentials (562-581)
  • NetworkManager_SetCredentials (562-562)
main/Application/Tasks/GUI/Export/ui.h (1)
main/Application/Tasks/GUI/Export/ui.c (2)
  • ui_init (27-39)
  • ui_destroy (41-47)
main/Application/Tasks/GUI/Export/ui.c (4)
main/Application/Tasks/GUI/Export/screens/ui_Splash.c (2)
  • ui_Splash_screen_init (19-112)
  • ui_Splash_screen_destroy (114-129)
main/Application/Tasks/GUI/Export/screens/ui_Main.c (2)
  • ui_Main_screen_init (77-428)
  • ui_Main_screen_destroy (430-468)
main/Application/Tasks/GUI/Export/screens/ui_Menu.c (2)
  • ui_Menu_screen_init (40-119)
  • ui_Menu_screen_destroy (121-136)
main/Application/Tasks/GUI/Export/screens/ui_Info.c (2)
  • ui_Info_screen_init (78-753)
  • ui_Info_screen_destroy (755-808)
main/Application/Manager/Network/Server/http_server.cpp (1)
main/Application/Manager/Network/Server/image_encoder.cpp (4)
  • Image_Encoder_Encode (170-224)
  • Image_Encoder_Encode (170-173)
  • Image_Encoder_Free (226-238)
  • Image_Encoder_Free (226-226)
main/Application/Manager/Network/Provisioning/provisioning.h (1)
main/Application/Manager/Network/Provisioning/provisioning.cpp (16)
  • Provisioning_Init (172-210)
  • Provisioning_Init (172-172)
  • Provisioning_Deinit (212-232)
  • Provisioning_Deinit (212-212)
  • Provisioning_Start (234-307)
  • Provisioning_Start (234-234)
  • Provisioning_Stop (309-328)
  • Provisioning_Stop (309-309)
  • Provisioning_isProvisioned (330-348)
  • Provisioning_isProvisioned (330-330)
  • Provisioning_Reset (350-357)
  • Provisioning_Reset (350-350)
  • Provisioning_isActive (359-362)
  • Provisioning_isActive (359-359)
  • Provisioning_SetNetworkTaskHandle (364-367)
  • Provisioning_SetNetworkTaskHandle (364-364)
main/Application/Manager/Network/networkManager.cpp (2)
main/Application/Manager/Network/Server/server.h (2)
  • Server_Init (35-58)
  • Server_Start (72-95)
main/Application/Manager/Network/SNTP/sntp.cpp (2)
  • SNTP_Deinit (53-57)
  • SNTP_Deinit (53-53)
main/Application/Tasks/GUI/Private/guiHelper.h (1)
main/Application/Tasks/GUI/Private/guiHelper.cpp (12)
  • GUI_Helper_Init (104-221)
  • GUI_Helper_Init (104-104)
  • GUI_Helper_Deinit (223-284)
  • GUI_Helper_Deinit (223-223)
  • GUI_Helper_Timer_ClockUpdate (286-301)
  • GUI_Helper_Timer_ClockUpdate (286-286)
  • GUI_Helper_Timer_SpotUpdate (303-326)
  • GUI_Helper_Timer_SpotUpdate (303-303)
  • GUI_Helper_Timer_SpotmeterUpdate (328-331)
  • GUI_Helper_Timer_SpotmeterUpdate (328-328)
  • GUI_Helper_Timer_SceneStatisticsUpdate (333-336)
  • GUI_Helper_Timer_SceneStatisticsUpdate (333-333)
main/Application/Tasks/GUI/Private/guiHelper.cpp (2)
main/Application/Manager/Network/Server/server.h (1)
  • Server_isRunning (111-114)
main/Application/Manager/Network/Server/websocket_handler.cpp (2)
  • WebSocket_Handler_BroadcastTelemetry (670-714)
  • WebSocket_Handler_BroadcastTelemetry (670-670)
main/Application/Tasks/Network/networkTask.cpp (4)
main/Application/Manager/Network/Provisioning/provisioning.cpp (12)
  • Provisioning_Stop (309-328)
  • Provisioning_Stop (309-309)
  • Provisioning_isProvisioned (330-348)
  • Provisioning_isProvisioned (330-330)
  • Provisioning_Start (234-307)
  • Provisioning_Start (234-234)
  • Provisioning_Init (172-210)
  • Provisioning_Init (172-172)
  • Provisioning_Deinit (212-232)
  • Provisioning_Deinit (212-212)
  • Provisioning_SetNetworkTaskHandle (364-367)
  • Provisioning_SetNetworkTaskHandle (364-364)
main/Application/Manager/Network/networkManager.cpp (6)
  • NetworkManager_StartSTA (411-442)
  • NetworkManager_StartSTA (411-411)
  • NetworkManager_StartServer (444-450)
  • NetworkManager_StartServer (444-444)
  • NetworkManager_Stop (452-465)
  • NetworkManager_Stop (452-452)
main/Application/Manager/Settings/settingsManager.cpp (2)
  • SettingsManager_Save (215-250)
  • SettingsManager_Save (215-215)
main/Application/Tasks/GUI/guiTask.cpp (2)
  • on_Network_Event_Handler (114-188)
  • on_Network_Event_Handler (114-114)
main/Application/Tasks/GUI/Export/screens/ui_Main.c (2)
main/Application/Tasks/GUI/Export/ui_events.cpp (4)
  • ScreenMainLoaded (12-33)
  • ScreenMainLoaded (12-12)
  • ButtonMainWiFiClicked (196-199)
  • ButtonMainWiFiClicked (196-196)
main/Application/Tasks/GUI/Export/ui_helpers.c (1)
  • _ui_screen_change (78-85)
main/Application/Tasks/GUI/Export/screens/ui_Info.c (2)
main/Application/Tasks/GUI/Export/ui_helpers.c (1)
  • _ui_screen_change (78-85)
main/Application/Tasks/GUI/Export/ui_events.cpp (2)
  • ScreenInfoLoaded (35-39)
  • ScreenInfoLoaded (35-35)
main/Application/Tasks/GUI/Export/screens/ui_Info.h (1)
main/Application/Tasks/GUI/Export/screens/ui_Info.c (4)
  • ui_Info_screen_init (78-753)
  • ui_Info_screen_destroy (755-808)
  • ui_event_Info (54-65)
  • ui_event_Button_Info_Back (67-74)
🪛 Clang (14.0.6)
main/Application/Tasks/GUI/Export/ui_events.h

[error] 13-13: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 14-14: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 15-15: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)

main/Application/Tasks/GUI/Export/screens/ui_Menu.h

[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 23-23: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 24-24: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

main/Application/Tasks/GUI/Export/screens/ui_Main.h

[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 23-23: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 24-24: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 25-25: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 26-26: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 27-27: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 28-28: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 29-29: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 30-30: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 31-31: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 32-32: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 33-33: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 34-34: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

main/Application/Tasks/GUI/Export/screens/ui_Info.h

[error] 16-16: unknown type name 'lv_event_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 23-23: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 24-24: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 25-25: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 26-26: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 27-27: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 28-28: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 29-29: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 30-30: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 31-31: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 32-32: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 33-33: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 34-34: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

main/Application/Tasks/GUI/Export/screens/ui_Splash.h

[error] 16-16: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 17-17: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 18-18: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 19-19: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 20-20: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 21-21: unknown type name 'lv_obj_t'

(clang-diagnostic-error)


[error] 22-22: unknown type name 'lv_obj_t'

(clang-diagnostic-error)

🪛 Cppcheck (2.19.0)
main/Application/Tasks/GUI/Export/ui.c

[error] 18-18: #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings"

(preprocessorErrorDirective)

main/Application/Manager/Network/networkManager.cpp

[error] 232-232: There is an unknown macro here somewhere. Configuration is required. If MACSTR is a macro then please configure it.

(unknownMacro)

main/Application/Tasks/GUI/Private/guiHelper.cpp

[error] 216-216: Array 'p_GUITask_State->UpdateTimer[3]' accessed at index 3, which is out of bounds.

(arrayIndexOutOfBounds)

🔇 Additional comments (33)
main/Application/Manager/SD/sdManager.cpp (4)

46-77: LGTM! Well-structured preprocessor configuration and state management.

The SPI host selection with compile-time error for missing configuration is good defensive programming. The state structure is appropriately organized with volatile correctly applied to CardPresent for ISR access.


254-257: LGTM!

Simple accessor with correct use of volatile for ISR-modified state.


283-293: Consider BMP row order: positive biHeight implies bottom-up storage.

In standard BMP format, a positive biHeight (line 285) means rows are stored bottom-to-top. If p_Buffer contains top-to-bottom pixel data, the saved image will appear vertically flipped. If this is intentional, consider adding a comment; otherwise, use a negative biHeight for top-down storage.


386-417: LGTM! Good defensive checks and task pinning strategy.

The guards against missing card and concurrent mount tasks are appropriate. Pinning to CPU 1 to avoid blocking the GUI task is a good design decision.

Note: The double-mount concern with SDManager_Init (flagged earlier) also applies here.

main/Application/Manager/Devices/ADC/adc.cpp (1)

103-123: LGTM!

The battery read function properly validates the pointer, reads raw ADC data, applies calibration when available, and falls back to raw values otherwise.

main/Application/Manager/Devices/devicesManager.h (1)

1-63: LGTM!

Well-structured header with proper include guards, Doxygen documentation, and a clean public API surface.

main/Application/Manager/Devices/devicesManager.cpp (2)

174-208: Battery voltage reading will fail due to inverted port expander logic.

PortExpander_EnableBatteryVoltage(true) (line 186) uses inverted logic (see portexpander.cpp), meaning the battery measurement circuit is actually disabled when this function is called. The ADC read will return incorrect values. This depends on fixing the inverted logic in portexpander.cpp.


97-139: LGTM!

The initialization sequence is well-structured with proper error handling, single-initialization guard, and appropriate delays for hardware stabilization.

main/Application/Manager/Settings/settings_types.h (1)

1-107: LGTM!

Well-designed settings structure with version field for migration, reserved space for future expansion, and clear Doxygen documentation for the event system.

main/Application/Manager/Devices/RTC/rtc.cpp (2)

266-303: LGTM!

Time conversion logic correctly handles BCD encoding, struct tm field mappings, and century bit for dates beyond 2099.


349-365: LGTM!

Alarm configuration correctly handles the RV8263-C8's inverted AE bit semantics (0 = enabled, 1 = disabled).

main/Application/Tasks/GUI/Export/ui.h (1)

1-48: LGTM! Well-structured generated UI header.

The header follows best practices with proper include guards, extern C linkage, and clear organization of UI entities (screens, assets, API). The SquareLine Studio generation is consistent with the LVGL 9.1.0 target version.

main/Application/Tasks/Network/networkTask.h (1)

1-60: LGTM! Clean task interface design.

The Network task API follows a consistent lifecycle pattern with clear documentation. The function signatures are well-structured, accepting the application context where needed and returning appropriate error codes.

main/Application/Tasks/GUI/guiTask.h (1)

1-67: LGTM! Consistent task API design.

The GUI task interface mirrors the Network task pattern with appropriate lifecycle functions. The addition of GUI_Toggle_ROI_EditMode() provides clear touch interaction functionality for thermal image ROI adjustment, well-documented in the comments.

main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c (1)

1-136: LGTM! Generated image asset properly structured.

The LVGL image descriptor and data array are correctly formatted for an 80×44 PNG with alpha channel. The memory alignment macro and image structure fields (width, height, color format, magic number) are properly initialized.

main/Application/Tasks/GUI/Export/ui_events.cpp (1)

196-199: LGTM!

The WiFi button click handler correctly posts the network event to trigger WiFi provisioning.

main/Application/Tasks/GUI/guiTask.cpp (1)

804-824: LGTM!

Good defensive programming with proper null checks and cascading cleanup on buffer allocation failures.

main/Application/Tasks/Network/networkTask.cpp (2)

241-249: Verify: Provisioning starts on every WiFi disconnection.

When WiFi disconnects, Provisioning_Start() is called immediately. This may not be the desired behavior if the disconnect is temporary (e.g., AP reboot, interference). Consider adding a reconnection attempt or delay before starting provisioning.


429-448: LGTM!

Good graceful shutdown pattern using event group signaling and waiting for the task to exit cleanly, unlike the GUI task which uses direct vTaskDelete().

main/Application/Tasks/GUI/Export/screens/ui_Menu.c (1)

121-135: LGTM!

The destroy function properly checks for null before deletion and cleans up all object pointers.

main/Application/Manager/Network/networkManager.cpp (1)

232-232: Static analysis false positive: MACSTR is a valid ESP-IDF macro.

The Cppcheck warning about MACSTR being an unknown macro is a false positive. MACSTR and MAC2STR are standard ESP-IDF macros defined in esp_mac.h for formatting MAC addresses.

main/Application/Tasks/GUI/Export/screens/ui_Info.c (2)

1-5: Auto-generated UI code from SquareLine Studio.

This file is generated by SquareLine Studio. Manual modifications should be avoided as they will be overwritten on regeneration. The implementation follows LVGL 9.1.0 patterns correctly with proper screen lifecycle management.


455-457: LVGL 9.1 workaround for bar/slider draw crash properly applied.

This code correctly addresses the known LVGL 9.1 bug where Bar/Slider objects crash or render incorrectly when top-padding is non-zero and right-padding is zero. The workaround—adding 1 pixel to right-padding when top-padding exceeds zero—is the standard fix documented in the LVGL community. The inline comment clearly explains the issue.

main/Application/Manager/Settings/settingsManager.cpp (1)

267-288: Event posted with pointer to parameter data after function may return.

In SettingsManager_SetLepton and similar setters, esp_event_post is called with p_Lepton (line 284-285) after the mutex is released. The caller may free or modify this memory before/during event processing. However, esp_event_post copies the data, so this is actually safe.

main/Application/Tasks/GUI/Export/screens/ui_Main.c (2)

1-5: Auto-generated UI code from SquareLine Studio.

This file is generated by SquareLine Studio and implements the main thermal camera screen. The implementation correctly follows LVGL 9.1.0 patterns with proper event wiring and screen lifecycle management.


430-467: Proper cleanup in ui_Main_screen_destroy.

The destroy function correctly deletes the root object (which cascades to children) and nulls all global pointers to prevent dangling references. This is important for the lazy initialization pattern used in _ui_screen_change.

main/Application/Tasks/GUI/Export/ui_helpers.h (1)

1-4: Generated file - avoid manual edits.

This file is auto-generated by SquareLine Studio. Manual changes will be overwritten on regeneration. Any required modifications should be made in the SquareLine Studio project and regenerated.

main/Application/Manager/Network/network_types.h (2)

4-4: Verify copyright year 2026.

The copyright year is 2026, which is in the future. Confirm whether this is intentional (for a planned release) or should be corrected to 2025.


24-219: Well-structured network type definitions.

The header provides a comprehensive and well-organized set of network types, events, and configuration structures. The ESP event integration, enum definitions, and data structures follow ESP-IDF conventions and provide good type safety.

main/Application/Tasks/GUI/Export/screens/ui_Main.h (2)

1-4: Generated file - avoid manual edits.

This file is auto-generated by SquareLine Studio. Manual changes will be overwritten on regeneration. Any required modifications should be made in the SquareLine Studio project and regenerated.


14-49: LVGL types resolved at build time.

Static analysis reports unknown types lv_event_t and lv_obj_t, but this is a false positive. These LVGL types are provided through the component include paths in the ESP-IDF build system. The implementation file that includes this header will have access to the full LVGL headers, resolving all type dependencies correctly.

main/Application/Tasks/GUI/Export/screens/ui_Info.h (2)

1-4: Generated file - avoid manual edits.

This file is auto-generated by SquareLine Studio. Manual changes will be overwritten on regeneration. Any required modifications should be made in the SquareLine Studio project and regenerated.


14-62: LVGL types resolved at build time.

Similar to ui_Main.h, static analysis reports unknown LVGL types, but this is a false positive. The types are provided through ESP-IDF component includes and resolved during the build process.

Comment on lines +203 to +206
cJSON *response = cJSON_CreateObject();
cJSON_AddStringToObject(response, "status", "ok");
Error = HTTP_Server_SendJSON(p_Request, response, 200);
cJSON_Delete(response);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing null check for cJSON_CreateObject in response creation.

Similar to HTTP_Server_SendError, the response JSON object creation doesn't check for allocation failure before adding items.

🔎 Proposed fix
     /* Send response */
     cJSON *response = cJSON_CreateObject();
+    if (response == NULL) {
+        return HTTP_Server_SendError(p_Request, 500, "Memory allocation failed");
+    }
     cJSON_AddStringToObject(response, "status", "ok");
     Error = HTTP_Server_SendJSON(p_Request, response, 200);
     cJSON_Delete(response);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cJSON *response = cJSON_CreateObject();
cJSON_AddStringToObject(response, "status", "ok");
Error = HTTP_Server_SendJSON(p_Request, response, 200);
cJSON_Delete(response);
/* Send response */
cJSON *response = cJSON_CreateObject();
if (response == NULL) {
return HTTP_Server_SendError(p_Request, 500, "Memory allocation failed");
}
cJSON_AddStringToObject(response, "status", "ok");
Error = HTTP_Server_SendJSON(p_Request, response, 200);
cJSON_Delete(response);
🤖 Prompt for AI Agents
In main/Application/Manager/Network/Server/http_server.cpp around lines 203 to
206, the call to cJSON_CreateObject() is not checked for NULL before adding
fields and sending the response; add a null check immediately after
cJSON_CreateObject() and if it returns NULL, call the existing error handling
(e.g., HTTP_Server_SendError with an appropriate 500/internal allocation-failure
message or set Error and return) without attempting cJSON_AddStringToObject or
cJSON_Delete on the NULL pointer; otherwise proceed to add "status":"ok", send
the JSON and delete the object as before.

Comment on lines +420 to +425
/* Send response */
cJSON *response = cJSON_CreateObject();
cJSON_AddStringToObject(response, "status", "updating");
cJSON_AddStringToObject(response, "message", "Firmware upload successful. Device will reboot after update.");
Error = HTTP_Server_SendJSON(p_Request, response, 200);
cJSON_Delete(response);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing null check for cJSON_CreateObject in OTA response.

Consistent with other handlers, this response creation should check for allocation failure.

🔎 Proposed fix
     /* Send response */
     cJSON *response = cJSON_CreateObject();
+    if (response == NULL) {
+        httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "Memory allocation failed");
+        vTaskDelay(1000 / portTICK_PERIOD_MS);
+        esp_restart();
+        return ESP_ERR_NO_MEM;
+    }
     cJSON_AddStringToObject(response, "status", "updating");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* Send response */
cJSON *response = cJSON_CreateObject();
cJSON_AddStringToObject(response, "status", "updating");
cJSON_AddStringToObject(response, "message", "Firmware upload successful. Device will reboot after update.");
Error = HTTP_Server_SendJSON(p_Request, response, 200);
cJSON_Delete(response);
/* Send response */
cJSON *response = cJSON_CreateObject();
if (response == NULL) {
httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "Memory allocation failed");
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart();
return ESP_ERR_NO_MEM;
}
cJSON_AddStringToObject(response, "status", "updating");
cJSON_AddStringToObject(response, "message", "Firmware upload successful. Device will reboot after update.");
Error = HTTP_Server_SendJSON(p_Request, response, 200);
cJSON_Delete(response);
🤖 Prompt for AI Agents
In main/Application/Manager/Network/Server/http_server.cpp around lines 420 to
425, the call to cJSON_CreateObject() for the OTA response lacks a
NULL/allocation check; add a check immediately after cJSON_CreateObject() and
handle allocation failure by logging/sending an HTTP 500 JSON error (or
appropriate error via HTTP_Server_SendJSON) and returning/setting Error
accordingly, avoiding further cJSON calls if response is NULL and ensuring no
cJSON_Delete is called on a NULL pointer.

Comment on lines +147 to +151
if (esp_vfs_fat_sdspi_mount("/sdcard", &_SD_Manager_State.Host, &_SD_Manager_State.SlotConfig,
&_SD_Manager_State.MountConfig, &_SD_Manager_State.Card) != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount SD card filesystem!");
return ESP_FAIL;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Potential double-mount: SDManager_Init mounts the card, but SDManager_Mount also exists.

SDManager_Init immediately mounts the SD card (line 147-151), but there's also a separate SDManager_Mount() function that performs async mounting. If both are called, this could cause resource conflicts or undefined behavior with the FAT filesystem.

Consider either:

  1. Remove the mount from SDManager_Init and require explicit SDManager_Mount() call
  2. Track mount state separately and prevent re-mounting if already mounted
🔎 Proposed fix - track mount state
 typedef struct {
     sdmmc_card_t *Card;
     sdmmc_host_t Host;
     sdspi_device_config_t SlotConfig;
     bool isInitialized;
+    bool isMounted;
     esp_timer_handle_t DebounceTimer;
     ...
 } SD_Manager_State_t;

Then check isMounted before attempting to mount in both SDManager_Init and SDManager_MountTask.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In main/Application/Manager/SD/sdManager.cpp around lines 147-151, the init
function always mounts the SD which can double-mount when SDManager_Mount is
used; add a boolean mount state (e.g., _SD_Manager_State.isMounted) and check it
before calling esp_vfs_fat_sdspi_mount in both SDManager_Init and in the async
SDManager_MountTask, set isMounted = true only on successful mount, and set it
false on unmount/fail; protect reads/writes to isMounted with the existing
manager mutex or a new mutex to avoid race conditions and ensure SDManager_Mount
returns/aborts early if already mounted.

Comment on lines +230 to +237
#if CONFIG_SD_CARD_PIN_CD > 0
/* Stop and delete debounce timer */
if (_SD_Manager_State.DebounceTimer != NULL) {
esp_timer_stop(_SD_Manager_State.DebounceTimer);
esp_timer_delete(_SD_Manager_State.DebounceTimer);
_SD_Manager_State.DebounceTimer = NULL;
}
#endif /* CONFIG_SD_CARD_PIN_CD */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing GPIO ISR handler removal during deinit.

The ISR handler is added via gpio_isr_handler_add() in SDManager_Init, but it's not removed in SDManager_Deinit. This can cause crashes if the ISR fires after deinitialization.

🔎 Proposed fix
 #if CONFIG_SD_CARD_PIN_CD > 0
+    /* Remove ISR handler first to prevent interrupts during cleanup */
+    gpio_isr_handler_remove(static_cast<gpio_num_t>(CONFIG_SD_CARD_PIN_CD));
+
     /* Stop and delete debounce timer */
     if (_SD_Manager_State.DebounceTimer != NULL) {
         esp_timer_stop(_SD_Manager_State.DebounceTimer);
         esp_timer_delete(_SD_Manager_State.DebounceTimer);
         _SD_Manager_State.DebounceTimer = NULL;
     }
 #endif /* CONFIG_SD_CARD_PIN_CD */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#if CONFIG_SD_CARD_PIN_CD > 0
/* Stop and delete debounce timer */
if (_SD_Manager_State.DebounceTimer != NULL) {
esp_timer_stop(_SD_Manager_State.DebounceTimer);
esp_timer_delete(_SD_Manager_State.DebounceTimer);
_SD_Manager_State.DebounceTimer = NULL;
}
#endif /* CONFIG_SD_CARD_PIN_CD */
#if CONFIG_SD_CARD_PIN_CD > 0
/* Remove ISR handler first to prevent interrupts during cleanup */
gpio_isr_handler_remove(static_cast<gpio_num_t>(CONFIG_SD_CARD_PIN_CD));
/* Stop and delete debounce timer */
if (_SD_Manager_State.DebounceTimer != NULL) {
esp_timer_stop(_SD_Manager_State.DebounceTimer);
esp_timer_delete(_SD_Manager_State.DebounceTimer);
_SD_Manager_State.DebounceTimer = NULL;
}
#endif /* CONFIG_SD_CARD_PIN_CD */
🤖 Prompt for AI Agents
In main/Application/Manager/SD/sdManager.cpp around lines 230 to 237, the deinit
path stops and deletes the debounce timer but fails to remove the GPIO ISR
handler added in SDManager_Init; add code inside the same CONFIG_SD_CARD_PIN_CD
> 0 block to call gpio_isr_handler_remove(CONFIG_SD_CARD_PIN_CD) (or the
variable holding the CD pin) before deleting the timer, and ensure the call is
guarded by a valid pin check so the ISR cannot fire after deinitialization.

Kampi added 4 commits January 15, 2026 22:52
Signed-off-by: Daniel Kampert <DanielKampert@kampis-elektroecke.de>
- Add documentation with AsciiDocs
- Change Settings logic to allow loading default settings from JSON
- All settings are handled via the Settings Manager and not with local copies of the settings

Signed-off-by: Daniel Kampert <DanielKampert@kampis-elektroecke.de>
Kampi added 2 commits January 19, 2026 08:58
- Replace touch controller with GT911
- Improve loading of default settings from SD card
- UI improvements and fixes

Signed-off-by: Daniel Kampert <DanielKampert@kampis-elektroecke.de>
@Kampi Kampi force-pushed the 1.0_Dev branch 4 times, most recently from ab732e5 to 687ec6d Compare February 6, 2026 21:17
@Kampi Kampi force-pushed the 1.0_Dev branch 4 times, most recently from 2b68f4a to 1fdf6c9 Compare February 9, 2026 07:15
@Kampi Kampi force-pushed the 1.0_Dev branch 7 times, most recently from 21012b3 to e9ea185 Compare February 10, 2026 14:58
@Kampi
Copy link
Contributor Author

Kampi commented Feb 10, 2026

@copilot review please

Copy link

Copilot AI commented Feb 10, 2026

@Kampi I've opened a new pull request, #10, to work on those changes. Once the pull request is ready, I'll request review from you.

…menu, add coredump functionality, add memory manager to handle the internal flash and the SD card

- Remove the settings file after loading
- Add USB support for mass storage class, add USB and memory manager
- Fix CI/CD
- Format style, update firmware workflow
- Update documentation
- Add version to settings, rework settings structure, clean up code, add task skeleton for the camera
- Image is stored as PNG
- 240x180 pixel is used now
- Move Touch I2C into Device Manager
- Add Skeletons for the new sensors

Signed-off-by: Daniel Kampert <DanielKampert@kampis-elektroecke.de>
@Kampi Kampi force-pushed the 1.0_Dev branch 2 times, most recently from 858b55e to 60c41da Compare February 22, 2026 18:39
Kampi added 7 commits March 1, 2026 13:17
Refactor USB descriptors to include UVC and CDC support with updated endpoint configurations.
- Add Python script for patching

Signed-off-by: Daniel Kampert <DanielKampert@kampis-elektroecke.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants