Partage de technologie

Un problème lors de l'utilisation de Delphi pour le développement Bluetooth BLE

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

concept

Pour le développement BLE dans Delphi, faites glisser un TBlueToothLe sur l'interface et utilisez ce contrôle pour développer BLE, par exemple en connectant un bracelet Bluetooth.

Il existe un programme BLEScanner dans la démo fournie avec Delphi, qui peut être utilisé comme point de départ pour le développement.

question

Si le programme ci-dessus est exécuté sous Windows, après l'analyse du périphérique, si la souris clique sur un périphérique, l'interface peut se bloquer et le programme ne répondra pas. En regardant la zone de gestion des tâches, il est vrai que le programme ne répond pas et est tombé en panne.

Analyse des causes

Cliquez sur la souris pour analyser les services de l'appareil sélectionné. Ensuite, lorsque les services du périphérique sont découverts, l'événement OnServicesDiscovered de TBluetoothLE est déclenché. Dans ce cas, plusieurs services de l'appareil sont lus en boucle, puis pour un certain service, son nom de personnage est lu en boucle. Le crash est l'endroit où la boucle lit Character.

Pourquoi il s'est écrasé, je ne sais pas. Mais j'ai trouvé une solution, le code est le suivant :

  1. procedure TForm6.BluetoothLE1ServicesDiscovered(const Sender: TObject; const AServiceList: TBluetoothGattServiceList);
  2. var
  3. ServiceIndex: Integer;
  4. Service: TBluetoothGattService;
  5. CharacteristicIndex: Integer;
  6. Characteristic: TBluetoothGattCharacteristic;
  7. begin
  8. //以下代码如果不包到 TTask.Run 里面(原本的代码没有),在 WINDOWS 底下,执行到 for
  9. //CharacteristicIndex := 0 to Service.Characteristics.Count 会界面冻结,而且单步跟踪也停止
  10. //了,没有往下执行。
  11. TTask.Run(
  12. procedure
  13. var
  14. ServiceIndex: Integer;
  15. CharacteristicIndex: Integer;
  16. begin
  17. if AServiceList.Count > 0 then
  18. begin
  19. for ServiceIndex := 0 to AServiceList.Count - 1 do
  20. begin
  21. Service := AServiceList[ServiceIndex];
  22. TThread.Synchronize(nil,
  23. procedure
  24. begin
  25. Listbox2.Items.Add((ServiceIndex + 1).ToString + ' - ' + Service.UUIDName + ' - ' + Service.UUID.ToString);
  26. end
  27. );
  28. //以下代码会导致死机,如果断点跟踪,直接就是停在 for 这一行,不会继续往下执行。
  29. for CharacteristicIndex := 0 to Service.Characteristics.Count - 1 do
  30. begin
  31. Characteristic := Service.Characteristics[CharacteristicIndex];
  32. TThread.Synchronize(nil,
  33. procedure
  34. begin
  35. Listbox2.Items.Add(' - ' + Characteristic.UUIDName + ' - ' + Characteristic.UUID.ToString);
  36. end
  37. );
  38. end;
  39. end;
  40. end
  41. else
  42. TThread.Synchronize(nil,
  43. procedure
  44. begin
  45. Listbox2.Items.Add('- Access not allowed or no service available');
  46. end
  47. );
  48. end
  49. );
  50. //Listbox1.Enabled := True;
  51. end;

Explication du code

Dans le code ci-dessus, TTask.Run a été ajouté par moi. TThread.Synchronize a également été ajouté par moi. Supprimez TTask.Run et TThread.Synchronize et le code restant est le code original de la démo fournie avec Delphi.

Tout d’abord, placez le code original dans TTask.Run, ce qui signifie placer ces codes dans un thread pour exécution. Au lieu de laisser le thread qui a initialement déclenché l'événement OnServicesDiscovered s'exécuter. Raison possible : le thread qui a déclenché OnServicesDiscovered ne peut pas effectuer trop de tâches fastidieuses.

Le code est exécuté dans le thread. Lorsque vous devez écrire des données dans le contrôle d'interface, telles que du code Listbox2.Items.Add, vous devez effectuer une synchronisation des threads. Ajoutez donc TThread.Synchronize.

mon environnement de développement

Dans différents environnements, les phénomènes peuvent être différents. Voici donc mon environnement de développement :

Édition communautaire Delphi 11 ;

Windows 11 Édition Familiale ;

Le programme cible à compiler et à exécuter est la version Win32.

Il n'y a aucun test pour savoir si cette démo aura les problèmes ci-dessus sous Android. Mais je crois que sous Android, il vaudra mieux ajouter TTask.Run.

Emplacement du programme de démonstration

La Démo mentionnée ici, après avoir installé Delphi, s'il est installé par défaut, le programme Démo est :

C:UsersPublicDocumentsEmbarcaderoStudio22.0SamplesObject PascalExemples multi-appareilsCapteurs et services d'appareilsBluetoothBLEScanner

en conclusion

Il n'y a aucun problème à utiliser Delphi pour développer des programmes BLE, comme créer une application de bracelet. Il convient toutefois de noter que dans de nombreux événements du contrôle TBluetoothLE, il est préférable de ne pas exécuter trop de code. S'il existe une logique métier complexe, il est préférable de l'exécuter dans un thread séparé. Dans la méthode événementielle, démarrez simplement le thread correspondant.

Pour Delphi, le nouveau TTask.Run nous permet de lancer beaucoup de code dans l'exécution du thread. La méthode d'écriture de code est beaucoup plus simple qu'auparavant lorsque nous devions créer une classe de thread.