PS_Win_BLE : fix crash shutdown + cache caractéristiques GATT
Crash shutdown (Index >= 0) : - OnPreExit se déclenche encore trop tard (GC déjà en cours). - Remplacé par OnEnginePreExit qui fire avant le shutdown des core modules, donc avant toute destruction d'UObject. RemoveFromRoot() est maintenant appelé au bon moment. Cache caractéristiques GATT : - Bug : Read/Write/Subscribe rappelaient GetCharacteristicsAsync(Cached) à chaque opération, ce qui peut retourner un ordre différent du discovery initial (Uncached) → mauvaise caractéristique ciblée. - Fix : les GattCharacteristic sont maintenant stockées dans FPS_GattServiceHandle::Characteristics (std::vector) lors du ConnectDevice, et réutilisées directement via [CI] dans toutes les opérations ultérieures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d53dd36194
commit
7c2cb387f2
@ -65,6 +65,8 @@ struct FPS_BLEDeviceHandle
|
|||||||
struct FPS_GattServiceHandle
|
struct FPS_GattServiceHandle
|
||||||
{
|
{
|
||||||
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceService Service{ nullptr };
|
winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceService Service{ nullptr };
|
||||||
|
// Characteristics cached at discovery time (same order as ActiveServices[SI].Characteristics)
|
||||||
|
std::vector<winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic> Characteristics;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PLATFORM_WINDOWS
|
#endif // PLATFORM_WINDOWS
|
||||||
@ -95,9 +97,9 @@ void UPS_BLE_Module::StartupModule()
|
|||||||
LocalBLEManager->AttachModule(this);
|
LocalBLEManager->AttachModule(this);
|
||||||
|
|
||||||
// Cleanup UObjects before Unreal's UObject array is destroyed.
|
// Cleanup UObjects before Unreal's UObject array is destroyed.
|
||||||
// ShutdownModule() is called too late (UObjectArray already partially torn down)
|
// Both ShutdownModule() and OnPreExit fire too late (UObjectArray already
|
||||||
// → we do RemoveFromRoot here, during pre-exit, which is still safe.
|
// partially torn down). OnEnginePreExit fires earlier, before GC teardown.
|
||||||
FCoreDelegates::OnPreExit.AddLambda([this]()
|
FCoreDelegates::OnEnginePreExit.AddLambda([this]()
|
||||||
{
|
{
|
||||||
if (LocalBLEManager)
|
if (LocalBLEManager)
|
||||||
{
|
{
|
||||||
@ -390,6 +392,12 @@ bool UPS_BLE_Module::ConnectDevice(UPS_BLE_Device* Device)
|
|||||||
for (uint32_t ci = 0; ci < Chars.Size(); ci++)
|
for (uint32_t ci = 0; ci < Chars.Size(); ci++)
|
||||||
{
|
{
|
||||||
auto Ch = Chars.GetAt(ci);
|
auto Ch = Chars.GetAt(ci);
|
||||||
|
|
||||||
|
// Cache the characteristic object so all subsequent operations
|
||||||
|
// (Read / Write / Subscribe) use the exact same instance and index
|
||||||
|
// as what was discovered here — no re-fetch needed.
|
||||||
|
SvcHandle->Characteristics.push_back(Ch);
|
||||||
|
|
||||||
FPS_CharacteristicItem ChItem;
|
FPS_CharacteristicItem ChItem;
|
||||||
GUID cg = Ch.Uuid();
|
GUID cg = Ch.Uuid();
|
||||||
ChItem.CharacteristicUUID = UPS_BLE_Device::GUIDToString(&cg);
|
ChItem.CharacteristicUUID = UPS_BLE_Device::GUIDToString(&cg);
|
||||||
@ -481,11 +489,9 @@ bool UPS_BLE_Module::ReadCharacteristic(UPS_BLE_Device* Device, uint8 SI, uint8
|
|||||||
PS_BLE_WINRT_NS
|
PS_BLE_WINRT_NS
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
||||||
auto Chars = SvcH->Service.GetCharacteristicsAsync(WinBT::BluetoothCacheMode::Cached).get();
|
if (CI >= SvcH->Characteristics.size()) return;
|
||||||
if (Chars.Status() != WinGAP::GattCommunicationStatus::Success) return;
|
auto Ch = SvcH->Characteristics[CI];
|
||||||
|
|
||||||
auto Ch = Chars.Characteristics().GetAt(CI);
|
|
||||||
auto Result = Ch.ReadValueAsync(WinBT::BluetoothCacheMode::Uncached).get();
|
auto Result = Ch.ReadValueAsync(WinBT::BluetoothCacheMode::Uncached).get();
|
||||||
|
|
||||||
EPS_GATTStatus Status = (Result.Status() == WinGAP::GattCommunicationStatus::Success)
|
EPS_GATTStatus Status = (Result.Status() == WinGAP::GattCommunicationStatus::Success)
|
||||||
@ -520,11 +526,9 @@ bool UPS_BLE_Module::WriteCharacteristic(UPS_BLE_Device* Device, uint8 SI, uint8
|
|||||||
PS_BLE_WINRT_NS
|
PS_BLE_WINRT_NS
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
||||||
auto Chars = SvcH->Service.GetCharacteristicsAsync(WinBT::BluetoothCacheMode::Cached).get();
|
if (CI >= SvcH->Characteristics.size()) return;
|
||||||
if (Chars.Status() != WinGAP::GattCommunicationStatus::Success) return;
|
auto Ch = SvcH->Characteristics[CI];
|
||||||
|
|
||||||
auto Ch = Chars.Characteristics().GetAt(CI);
|
|
||||||
auto Writer = WinStr::DataWriter();
|
auto Writer = WinStr::DataWriter();
|
||||||
for (uint8 B : DataCopy) Writer.WriteByte(B);
|
for (uint8 B : DataCopy) Writer.WriteByte(B);
|
||||||
|
|
||||||
@ -554,11 +558,9 @@ bool UPS_BLE_Module::SubscribeCharacteristic(UPS_BLE_Device* Device, uint8 SI, u
|
|||||||
PS_BLE_WINRT_NS
|
PS_BLE_WINRT_NS
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
||||||
auto Chars = SvcH->Service.GetCharacteristicsAsync(WinBT::BluetoothCacheMode::Cached).get();
|
if (CI >= SvcH->Characteristics.size()) return;
|
||||||
if (Chars.Status() != WinGAP::GattCommunicationStatus::Success) return;
|
auto Ch = SvcH->Characteristics[CI];
|
||||||
|
|
||||||
auto Ch = Chars.Characteristics().GetAt(CI);
|
|
||||||
|
|
||||||
auto WriteStatus = Ch.WriteClientCharacteristicConfigurationDescriptorAsync(
|
auto WriteStatus = Ch.WriteClientCharacteristicConfigurationDescriptorAsync(
|
||||||
WinGAP::GattClientCharacteristicConfigurationDescriptorValue::Notify).get();
|
WinGAP::GattClientCharacteristicConfigurationDescriptorValue::Notify).get();
|
||||||
@ -604,11 +606,9 @@ bool UPS_BLE_Module::UnsubscribeCharacteristic(UPS_BLE_Device* Device, uint8 SI,
|
|||||||
PS_BLE_WINRT_NS
|
PS_BLE_WINRT_NS
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
auto* SvcH = static_cast<FPS_GattServiceHandle*>(Device->NativeGattServices[SI]);
|
||||||
auto Chars = SvcH->Service.GetCharacteristicsAsync(WinBT::BluetoothCacheMode::Cached).get();
|
if (CI >= SvcH->Characteristics.size()) return;
|
||||||
if (Chars.Status() != WinGAP::GattCommunicationStatus::Success) return;
|
auto Ch = SvcH->Characteristics[CI];
|
||||||
|
|
||||||
auto Ch = Chars.Characteristics().GetAt(CI);
|
|
||||||
|
|
||||||
uint64 Key = ((uint64)SI << 8) | CI;
|
uint64 Key = ((uint64)SI << 8) | CI;
|
||||||
if (winrt::event_token** TokenPtr = reinterpret_cast<winrt::event_token**>(Device->NotifyTokens.Find(Key)))
|
if (winrt::event_token** TokenPtr = reinterpret_cast<winrt::event_token**>(Device->NotifyTokens.Find(Key)))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user