Fix crash shutdown + IMU BLE toujours actif pour tests

PS_Win_BLE : crash à la fermeture d'Unreal (assertion Index >= 0 dans
UObjectArray) car RemoveFromRoot() était appelé dans ShutdownModule()
alors que l'UObject array est déjà partiellement détruit. Fix : cleanup
du BLEManager déplacé dans un delegate FCoreDelegates::OnPreExit qui
s'exécute plus tôt, avant la destruction des UObjects.

uproject : désactivation explicite de WinBluetoothLE (les nœuds
Blueprint restaient dans le groupe Bluetooth Low Energy car le plugin
était chargé automatiquement depuis le dossier Plugins/).

Firmware : envoi IMU BLE découplé du debug mode pour pouvoir tester
la caractéristique 6E400002 à distance (TODO_TEST — remettre la
condition debugMode != DEBUG_OFF quand Pico Motion Tracker intégré).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
j.foucher 2026-02-18 19:23:13 +01:00
parent 0573cd9a57
commit d53dd36194
3 changed files with 26 additions and 9 deletions

View File

@ -574,9 +574,10 @@ void loop() {
sendDebugData(accelMag, gyroMag, audioLevel); sendDebugData(accelMag, gyroMag, audioLevel);
printDebugSerial(accelMag, gyroMag, audioLevel); printDebugSerial(accelMag, gyroMag, audioLevel);
// ─── IMU BLE 10 Hz (debug uniquement) ─── // ─── IMU BLE 10 Hz ───
// En production (debugMode OFF), pas d'envoi IMU → charge BLE réduite pour Unreal // TODO_TEST : envoi IMU toujours actif pour test (Pico Motion Tracker en production)
if (debugMode != DEBUG_OFF && now-lastSend>=100) { // REMETTRE : if (debugMode != DEBUG_OFF && now-lastSend>=100) {
if (now-lastSend>=100) {
lastSend=now; lastSend=now;
float dt=(now-lastUpdate)/1000.0f; lastUpdate=now; float dt=(now-lastUpdate)/1000.0f; lastUpdate=now;
roll+=gx*dt; pitch+=gy*dt; yaw+=gz*dt; roll+=gx*dt; pitch+=gy*dt; yaw+=gz*dt;

View File

@ -18,6 +18,10 @@
"Editor" "Editor"
] ]
}, },
{
"Name": "WinBluetoothLE",
"Enabled": false
},
{ {
"Name": "PS_Win_BLE", "Name": "PS_Win_BLE",
"Enabled": true "Enabled": true

View File

@ -5,6 +5,7 @@
#include "PS_BLEDevice.h" #include "PS_BLEDevice.h"
#include "Async/Async.h" #include "Async/Async.h"
#include "Misc/MessageDialog.h" #include "Misc/MessageDialog.h"
#include "Misc/CoreDelegates.h"
#include "Modules/ModuleManager.h" #include "Modules/ModuleManager.h"
// ─── WinRT includes (Windows only) ─────────────────────────────────────────── // ─── WinRT includes (Windows only) ───────────────────────────────────────────
@ -92,6 +93,19 @@ void UPS_BLE_Module::StartupModule()
LocalBLEManager = NewObject<UPS_BLE_Manager>(); LocalBLEManager = NewObject<UPS_BLE_Manager>();
LocalBLEManager->AddToRoot(); // prevent GC LocalBLEManager->AddToRoot(); // prevent GC
LocalBLEManager->AttachModule(this); LocalBLEManager->AttachModule(this);
// Cleanup UObjects before Unreal's UObject array is destroyed.
// ShutdownModule() is called too late (UObjectArray already partially torn down)
// → we do RemoveFromRoot here, during pre-exit, which is still safe.
FCoreDelegates::OnPreExit.AddLambda([this]()
{
if (LocalBLEManager)
{
LocalBLEManager->DisconnectAll();
LocalBLEManager->RemoveFromRoot();
LocalBLEManager = nullptr;
}
});
#else #else
FMessageDialog::Open(EAppMsgType::Ok, FMessageDialog::Open(EAppMsgType::Ok,
LOCTEXT("PS_Win_BLE_Platform", "PS_Win_BLE: BLE is only supported on Windows 64-bit.")); LOCTEXT("PS_Win_BLE_Platform", "PS_Win_BLE: BLE is only supported on Windows 64-bit."));
@ -103,12 +117,10 @@ void UPS_BLE_Module::ShutdownModule()
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
ScannerCleanup(); ScannerCleanup();
if (LocalBLEManager) // NOTE: LocalBLEManager cleanup (DisconnectAll + RemoveFromRoot) is handled
{ // in the OnPreExit delegate registered in StartupModule, because ShutdownModule
LocalBLEManager->DisconnectAll(); // is called after the UObject array has started to be destroyed (causes Index >= 0 crash).
LocalBLEManager->RemoveFromRoot();
LocalBLEManager = nullptr; LocalBLEManager = nullptr;
}
if (bWinRTCoInitialized) if (bWinRTCoInitialized)
{ {