Κοινή χρήση τεχνολογίας

Ένα πρόβλημα με τη χρήση των Delphi για την ανάπτυξη Bluetooth BLE

2024-07-12

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

έννοια

Για την ανάπτυξη BLE στους Δελφούς, σύρετε ένα TBlueToothLe στη διεπαφή και χρησιμοποιήστε αυτό το στοιχείο ελέγχου για να αναπτύξετε το BLE, όπως τη σύνδεση ενός βραχιολιού Bluetooth.

Υπάρχει ένα πρόγραμμα BLEScanner στο Demo που συνοδεύει το Delphi, το οποίο μπορεί να χρησιμοποιηθεί ως αφετηρία για ανάπτυξη.

ερώτηση

Εάν το παραπάνω πρόγραμμα εκτελεστεί στα Windows, μετά τη σάρωση της συσκευής, εάν το ποντίκι κάνει κλικ σε μια συσκευή, η διεπαφή μπορεί να παγώσει και το πρόγραμμα να μην ανταποκρίνεται. Κοιτάζοντας την περιοχή διαχείρισης εργασιών, είναι αλήθεια ότι το πρόγραμμα δεν ανταποκρίνεται και έχει διακοπεί.

Ανάλυση αιτίας

Κάντε κλικ με το ποντίκι για να σαρώσετε τις υπηρεσίες της επιλεγμένης συσκευής. Στη συνέχεια, όταν ανακαλυφθούν οι υπηρεσίες της συσκευής, ενεργοποιείται το συμβάν OnServicesDiscovered του TBluetoothLE. Σε αυτήν την περίπτωση, πολλαπλές υπηρεσίες της συσκευής διαβάζονται σε βρόχο και, στη συνέχεια, για μια συγκεκριμένη υπηρεσία, το όνομα του χαρακτήρα της διαβάζεται σε βρόχο. Η συντριβή είναι όπου ο βρόχος διαβάζει Χαρακτήρα.

Γιατί συνετρίβη, δεν ξέρω. Βρήκα όμως μια λύση, ο κώδικας είναι ο εξής:

  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;

Εξήγηση κώδικα

Στον παραπάνω κώδικα, το TTask.Run προστέθηκε από εμένα. Το TThread.Synchronize προστέθηκε επίσης από εμένα. Καταργήστε τα TTask.Run και TThread.Synchronize και ο κωδικός που απομένει είναι ο αρχικός κώδικας του Demo που συνοδεύει τους Delphi.

Πρώτα, βάλτε τον αρχικό κώδικα στο TTask.Run, που σημαίνει ότι τοποθετείτε αυτούς τους κωδικούς σε ένα νήμα για εκτέλεση. Αντί να εκτελεστεί το νήμα που ανέβασε αρχικά το συμβάν OnServicesDiscovered. Πιθανή αιτία: Το νήμα που ενεργοποίησε το OnServicesDiscovered δεν μπορεί να εκτελέσει πάρα πολλές χρονοβόρες εργασίες.

Ο κώδικας εκτελείται στο νήμα Όταν χρειάζεται να γράψετε δεδομένα στο στοιχείο ελέγχου διεπαφής, όπως το Listbox2.Items.Add code, πρέπει να κάνετε συγχρονισμό νήματος. Προσθέστε λοιπόν TThread.Synchronize.

το αναπτυξιακό μου περιβάλλον

Σε διαφορετικά περιβάλλοντα, τα φαινόμενα μπορεί να είναι διαφορετικά. Επομένως, εδώ είναι το περιβάλλον ανάπτυξής μου:

Delphi 11 Community Edition;

Windows 11 Home Edition.

Το πρόγραμμα-στόχος που πρέπει να μεταγλωττιστεί και να εκτελεστεί είναι η έκδοση Win32.

Δεν υπάρχει δοκιμή εάν αυτό το Demo θα έχει τα παραπάνω προβλήματα στο Android. Αλλά πιστεύω ότι στο Android, θα είναι καλύτερο να προσθέσετε το TTask.Run.

Τοποθεσία προγράμματος επίδειξης

Το Demo που αναφέρεται εδώ, μετά την εγκατάσταση του Delphi, εάν είναι εγκατεστημένο από προεπιλογή, το πρόγραμμα επίδειξης είναι:

C:UsersPublicDocumentsEmbarcaderoStudio22.0SamplesObject Pascal Δείγματα πολλαπλών συσκευών Αισθητήρες και υπηρεσίες συσκευήςBluetoothBLEScanner

Συμπερασματικά

Δεν υπάρχει πρόβλημα στη χρήση των Delphi για την ανάπτυξη προγραμμάτων BLE, όπως η κατασκευή μιας εφαρμογής βραχιολιού. Ωστόσο, πρέπει να σημειωθεί ότι σε πολλά συμβάντα του στοιχείου ελέγχου TBluetoothLE, είναι καλύτερο να μην εκτελείτε πάρα πολύ κώδικα. Εάν υπάρχει πολύπλοκη επιχειρηματική λογική, είναι καλύτερο να την εκτελέσετε σε ξεχωριστό νήμα Στη μέθοδο συμβάντος, απλώς ξεκινήστε το αντίστοιχο νήμα.

Για τους Delphi, το TTask.Run που προστέθηκε πρόσφατα μας επιτρέπει να ρίξουμε πολύ κώδικα στην εκτέλεση νήματος Η μέθοδος γραφής κώδικα είναι πολύ πιο απλή από πριν όταν έπρεπε να δημιουργήσουμε μια κλάση νήματος.