fix: restore PIO build (3.20014 + JsonV7)

The pinned commit 6129375 accumulated incompatibilities with
the current toolchain (Arduino-ESP32 3.20014, ESP-IDF v5
underneath) and ArduinoJson v7 (which the codebase already
uses via .to<>() / .add<>() syntax). Fresh installs hit five
distinct build errors. This commit fixes them so the firmware
compiles and flashes cleanly on a Freenove ESP32-S3 WROOM
N16R8 board.

Library version:
- platformio.ini: bumped bblanchon/ArduinoJson from 6.21.5
  to ^7.2.0. The codebase uses v7 API patterns
  (doc[..].to<JsonArray>(), arr.add<JsonObject>()) in 7
  files, so v7 is the source of truth. Mixed v6
  createNested* calls remain in 4 files and are forward-
  compatible.

Build excludes:
- platformio.ini build_src_filter: skip
  src/audio/audio_ble_control.cpp. The .cpp was committed
  without its header (audio/audio_ble_control.h) and has
  zero callers — dead code that broke compile.

Header / signature fixes:
- include/npc/npc_engine.h: added <stddef.h> so size_t is
  declared (npc_build_sd_path uses it in the public API).
- src/npc/game_coordinator.cpp: changed
  game_coordinator_phase return type from game_phase_t to
  int to match the extern "C" header declaration. The
  original cast remains (just on the return value).
- src/npc/espnow_master.cpp: on_recv now uses the legacy
  (const uint8_t* mac_addr, ...) callback signature
  matching Arduino-ESP32 3.20014's esp_now.h. The
  esp_now_recv_info_t* form is IDF v5 only and not yet
  surfaced through the Arduino wrapper.

Boot-time crash fix (lwip "Invalid mbox" panic, reset
reason 4):
- src/app/main.cpp: gate voiceWsInit/voiceWsConnect behind
  !g_boot_network_deferred && !kBootEspNowOnlyMode.
  voiceWsConnect() calls into s_ws.begin() -> lwip
  tcpip_send_msg, which panics if the TCP/IP stack is not
  yet initialised. The bug was dormant because earlier
  builds presumably had NET coming up before VOICE; with
  espnow_only_mode + deferred network bringup paths the
  ordering became visible.

Acceptance:
- `pio run` succeeds (RAM 79%, Flash 65%).
- `pio run -t upload` flashes 2.7 MB in 38s, all hashes
  verified.
- Boot stable: SD_MMC mounted, LittleFS ready, reset=1, no
  panic over 30s monitor (90k UI frames).

Out of scope:
- 2 macOS Finder duplicate font sources
  (ui_freenove_allinone/src/ui/fonts/lv_font_*  2.c) were
  removed locally to unblock the linker (multiple
  definition errors). They are untracked Finder artefacts
  and should never have appeared on disk.
This commit is contained in:
L'électron rare
2026-05-03 16:21:38 +02:00
parent 6129375916
commit 1a984b006d
5 changed files with 19 additions and 7 deletions
+2 -1
View File
@@ -23,6 +23,7 @@ board_build.filesystem = littlefs
build_src_filter =
-<*>
+<src/>
-<src/audio/audio_ble_control.cpp>
monitor_speed = 115200
monitor_filters = time, esp32_exception_decoder
monitor_echo = yes
@@ -34,7 +35,7 @@ lib_deps =
lovyan03/LovyanGFX@1.2.7
lvgl/lvgl@8.4.0
esphome/ESP32-audioI2S@2.3.0
bblanchon/ArduinoJson@6.21.5
bblanchon/ArduinoJson@^7.2.0
adafruit/Adafruit NeoPixel@1.12.3
links2004/WebSockets@^2.4.0
build_flags =
@@ -4,6 +4,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
+9 -2
View File
@@ -7783,8 +7783,15 @@ void setup() {
}
g_next_espnow_discovery_ms = millis() + 2000U;
// Voice pipeline — connect to voice bridge server
{
// Voice pipeline — connect to voice bridge server.
// Skip when network boot is deferred: voiceWsConnect() calls into lwip
// (s_ws.begin -> tcpip_send_msg) which panics with "Invalid mbox" if the
// TCP/IP stack is not yet initialised. Same applies to espnow-only mode.
if (g_boot_network_deferred) {
Serial.println("[VOICE] init skipped (network_boot_deferred=1)");
} else if (kBootEspNowOnlyMode) {
Serial.println("[VOICE] init skipped (espnow_only_mode=1)");
} else {
zacus::voice::VoiceWsConfig voice_cfg;
voice_cfg.server_url = "ws://192.168.0.120:8200/voice/ws";
voice_cfg.device_id = g_network_cfg.hostname[0] != '\0'
@@ -42,11 +42,14 @@ struct MasterRecvItem {
// Wi-Fi ISR callbacks
// ---------------------------------------------------------------------------
static void on_recv(const esp_now_recv_info_t *info,
// Note: SDK Arduino-ESP32 3.20014 uses the legacy callback signature
// (const uint8_t* mac_addr, ...). IDF v5 introduced esp_now_recv_info_t.
// Use the legacy form here so the firmware builds with the pinned SDK.
static void on_recv(const uint8_t *mac_addr,
const uint8_t *data, int len)
{
MasterRecvItem item;
memcpy(item.src_mac, info->src_addr, 6);
memcpy(item.src_mac, mac_addr, 6);
int copy = len < (int)sizeof(item.data) ? len : (int)sizeof(item.data);
memcpy(item.data, data, copy);
item.len = copy;
@@ -323,8 +323,8 @@ void game_coordinator_tick(void) {
}
}
game_phase_t game_coordinator_phase(void) {
return (game_phase_t)s_game.phase;
int game_coordinator_phase(void) {
return (int)s_game.phase;
}
uint32_t game_coordinator_score(void) {