Compartir tecnología

Un problema al utilizar Delphi para el desarrollo de Bluetooth BLE

2024-07-12

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

concepto

Para el desarrollo de BLE en Delphi, arrastre un TBlueToothLe a la interfaz y use este control para desarrollar BLE, como conectar una pulsera Bluetooth.

Hay un programa BLEScanner en la demostración que viene con Delphi, que puede usarse como punto de partida para el desarrollo.

pregunta

Si el programa anterior se ejecuta en Windows, después de escanear el dispositivo, si el mouse hace clic en un dispositivo, la interfaz puede congelarse y el programa no responderá. Si observamos el área de gestión de tareas, es cierto que el programa no responde y se ha bloqueado.

Análisis de causa

Haga clic con el mouse para escanear los servicios del dispositivo seleccionado. Luego, cuando se descubren los servicios del dispositivo, se activa el evento OnServicesDiscovered de TBluetoothLE. En este caso, se leen en un bucle varios servicios del dispositivo y luego, para un determinado servicio, se lee en un bucle su nombre de carácter. El bloqueo es donde el bucle dice Carácter.

Por qué se estrelló, no lo sé. Pero encontré una solución, el código es el siguiente:

  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;

Explicación del código

En el código anterior, agregué TTask.Run. TThread.Synchronize también fue añadido por mí. Elimine TTask.Run y ​​TThread.Synchronize y el código restante es el código original de la demostración que viene con Delphi.

Primero, coloque el código original en TTask.Run, lo que significa colocar estos códigos en un hilo para su ejecución. En lugar de dejar que se ejecute el hilo que originalmente generó el evento OnServicesDiscovered. Posible motivo: el subproceso que activó OnServicesDiscovered no puede realizar demasiadas tareas que requieren mucho tiempo.

El código se ejecuta en el hilo. Cuando necesita escribir datos en el control de la interfaz, como el código Listbox2.Items.Add, debe realizar una sincronización del hilo. Entonces agregue TThread.Synchronize.

mi entorno de desarrollo

En diferentes entornos, los fenómenos pueden ser diferentes. Por lo tanto, aquí está mi entorno de desarrollo:

Edición comunitaria de Delphi 11;

Edición para el hogar de Windows 11;

El programa de destino que se compilará y ejecutará es la versión Win32.

No hay pruebas de si esta demostración tendrá los problemas anteriores en Android. Pero creo que en Android será mejor agregar TTask.Run.

Ubicación del programa de demostración

La demostración mencionada aquí, después de instalar Delphi, si se instala de forma predeterminada, el programa de demostración es:

C:UsuariosPúblicoDocumentosEmbarcaderoStudio22.0MuestrasObject PascalMuestras de dispositivos múltiplesSensores y servicios de dispositivosBluetoothBLEScanner

en conclusión

No hay ningún problema en utilizar Delphi para desarrollar programas BLE, como crear una aplicación de pulsera. Sin embargo, cabe destacar que en muchos eventos del control TBluetoothLE lo mejor es no ejecutar demasiado código. Si existe una lógica empresarial compleja, es mejor ejecutarla en un hilo separado. En el método del evento, simplemente inicie el hilo correspondiente.

Para Delphi, el TTask.Run recién agregado nos permite incluir una gran cantidad de código en la ejecución de subprocesos. El método de escritura de código es mucho más simple que antes, cuando teníamos que crear una clase de subproceso.