Archive for the ‘Bluetooth Basics’ Category

JABWT (JSR-82) Teil 5: Discovery Agent und DiscoveryListener

Sunday, November 11th, 2018

Ausgangspunkt für die Suche von Bluetoothgeräten ist die Klasse DiscoveryAgent. Sie erlaubt die Suche nach Geräten und Diensten. Dabei wird die Suche im Hintergrund ausgeführt und blockiert nicht die Applikation. Wird ein Gerät oder ein Dienst gefunden, dann wird dies über ein Listener, dem DiscoveryListener, mitgeteilt.

Der Entwickler implementiert diesen Listener und übergibt ihn beim Start der Suche. Die JABWT-Implementierung ruft die Methoden dieses Listeners auf und übermittelt gefundene Geräte (Klasse RemoteDevice) bzw. Dienste (Interface ServiceRecord) als Übergabeparameter. Mit Hilfe dieser Objekte erhält man den Connection String (den wir ja nicht mehr hartcodieren möchten )

;)

Im nachfolgenden Beispiel wird zunächst eine Suche nach Geräten mit der major device class “peripheral” ausgeführt. Anschliessend wird auf einem gefundenen Gerät die Suche nach dem RFCOMM-Dienst gestartet.

Beispielcode:

  1. DiscoveryListener listener= new DiscoveryListener() {
  2. public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) {
  3. // Ein Bluetoothgerät wurde gefunden.
  4. // Filterung nach Major Device Class “Peripheral”
  5. if ((deviceClass.getMajorDeviceClass() & 0x500) != 0) {
  6. // Speichern des remoteDevice in eine Liste
  7.     }
  8.     …
  9.   }
  10. public void servicesDiscovered(int i, ServiceRecord[] sr) {
  11. // Ein oder mehrere Dienste wurden gefunden.
  12. int reqSecurity = ServiceRecord.NOAUTHENTICATE_NOENCRYPT;
  13. boolean mustBeMaster = false;
  14. String connectionURL = sr[0].getConnectionURL(reqSecurity, mustBeMaster);
  15.     …
  16.   }
  17.  
  18. public void serviceSearchCompleted(int transactionID, int responseCode) {
  19. // Abschluss der Suche nach Diensten.
  20. if (responseCode == DiscoveryListener.SERVICE_SEARCH_ERROR) {
  21. // Suche war nicht erfolgreich -> Fehlerbehandlung
  22.         }
  23.     …
  24.     }
  25.  
  26.     public void inquiryCompleted(int discType) {
  27. // Abschluss der Suche nach Geräten.
  28. if (discType == DiscoveryListener.INQUIRY_ERROR) {
  29. // Suche war nicht erfolgreich -> Fehlerbehandlung
  30.         }
  31.         …
  32.     }
  33. }
  34.  
  35. LocalDevice local   = LocalDevice.getLocalDevice();
  36. DiscoveryAgent agent   = local.getDiscoveryAgent();
  37.  
  38. // Suche nach Geräten starten
  39. agent.startInquiry(DiscoveryAgent.GIAC, listener);
  40.  
  41. // Suche nach RFCOMM Dienst (0x0003) auf einem bereits gefundenen Gerät starten
  42. UUID[] uuidSet = new UUID[] { new UUID(0x0003) };
  43. int[] attrSet  = null; // null, weil uns nur die Default Attribute interessieren
  44. agent.searchServices(attrSet, uuidSet, remoteDevice, listener);

JABWT (JSR-82) Teil 4: Grundlagen für Erkennung von Diensten und Geräten

Monday, October 29th, 2018

Wie kann man ein Bluetoothgerät zur Laufzeit finden? Das Bluetoothprotokoll unterschiedet zwischen Erkennung von Diensten (Services) und Geräten (Devices). Um eine gezielte Suche zu ermöglichen, wird jedes Bluetoothgerät mit folgenden Informationen gekennzeichnet:

  • major service class (”Positioning”, “Telephony” oder “Networking”)
  • major device class (Grobe Klassifizierung des Geräts z.B. “Peripheral” oder “Audio/Video”)
  • minor device class (Genauere Spezifikation der “major device class” z.B. “Keyboard”)

Da ein Gerät mehrere Dienste anbieten kann, sind mehrere “major service class” Einträge möglich.

Es gibt zwei Typen der Gerätesuche (”Inquiry”): “General/Unlimited Inquiry” und “Limited Dedicated Inquiry”. Die “Limited Dedicated Inquiry” liefert als Suchergebnis nur Geräte, die nur für eine begrenze Zeitdauer gefunden werden können (z.B. PDAs). Ein Bluetooth-Gerät kann sich also in drei verschiedenen Modi befinden: “general”, “limited” oder “not discoverable”.

Im nächsten Teil stelle ich den DiscoveryAgent und den DiscoveryListener vor, mit denen im JABWT die Suche nach Geräten und Diensten ausgeführt wird.

P.S.: Etwas ärgerlich finde ich, dass die offiziellen Bluetooth Spezifikationen nur mit einem sog. Adopter Account runtergeladen werden können. Und den bekommt man nur wenn man das “Bluetooth Trademark Licence Agreement” unterzeichnet(!).

JABWT (JSR-82) Teil 3: RFCOMM Beispiel

Wednesday, October 17th, 2018

Das nachfolgende Codebeispiel zeigt sehr vereinfacht einen Zugriff auf einen GPS Empfänger.

Zunächst wird über die Connector Klasse ein StreamConnection Objekt geholt, mit Hilfe dessen ein InputStream geöffnet wird. Über diesen Stream schickt der GPS Empfänger laufend NMEA-Messages, die die aktuelle Position angeben. Unser Beispielcode interpretiert die ersten ankommenden 256 Bytes als String. Das ist ausreichend um mindestens 1 NMEA-Message komplett zu empfangen. Anschliessend wird die Verbindung im finally Block geschlossen.

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import javax.microedition.io.Connector;
  4. import javax.microedition.io.StreamConnection;
  5.  
  6. StreamConnection conn   = null;
  7. InputStream is          = null;
  8. String message          = null;
  9. try {
  10.         conn = (StreamConnection) Connector.open (“btspp://008049323FAE:1”,
  11.                                                   Connector.READ);
  12.         is = conn.openInputStream();
  13.         byte buffer[] = new byte[256];
  14.         is.read(buffer);
  15.         message = new String(buffer);
  16.  
  17. } catch (IOException io) {
  18.         // handle exception
  19. } finally {
  20.         if (conn != null) {
  21.                 try {
  22.                         conn.close();
  23.                 } catch (IOException ignored) {}
  24.         }
  25.  
  26.         if (is != null) {
  27.                 try {
  28.                         is.close();
  29.                 } catch (IOException ignored) {}
  30.         }
  31. }

Dieser Code ist natürlich in dieser einfachen Form noch nicht “produktionstauglich”. Z.B. würde man den Bluetooth Zugriff in einem separaten Thread oder besser in einem TimerTask auslagern. Zudem ist im Beispiel die Bluetoothadresse noch hartcodiert. Wie man die Adresse zur Laufzeit findet, seht ihr im nächsten Teil

;)

JABWT (JSR-82) Teil 2: RFCOMM

Tuesday, October 9th, 2018

RFCOMM emuliert eine serielle Schnittstelle zwischen zwei Bluetoothgeräten und ist deswegen die “einfachste” API in der JABWT Welt. Für die Verwendung des Protokolls wurden keine neuen Klassen definiert. Stattdessen wird das General Connection Framework (GCF) aus der CLDC-Spezifikation verwendet. Das GCF abstrahiert Verbindungen in einer hierarchischen Struktur (Connection, StreamConnection, HttpConnection, usw.).

Für das Aufbauen von unterschiedlichen Verbindungen ist die Connector Klasse zuständig. Sie gibt je nach übergebener URL das passende Connection Object zurück (z.B. HttpConnection bei URL mit dem Schema “http:“). Für eine RFCOMM-Verbindung lautet das Schema “btspp”.

Beispiel für eine Clientverbindung: btspp://008049323FAE:1
schema:bluetooth address:server channel

Der Server Channel identifiziert eindeutig einen Bluetoothdienst und ist vergleichbar mit einer TCP/IP Portnummer. Zusätzlich können mit der URL auch Parameter übergeben werden. Für eine Clientverbindung sind folgende Parameter möglich:

  • authenticate (true oder false) Gibt an, ob das Remotedevice authentifiziert werden muss.
  • master (true oder false) Gibt an, dass das Gerät “Master” der Verbindung sein muss.
  • encrypt (true oder false) Gibt an, dass die Bluetoothverbindung verschlüsselt sein muss.

Beispiel mit Parameter:
btspp://008049323FAE:1;master=true;authenticate=true

So, genug für heute. Im nächsten Teil gibts Beispiel-Code

:)

JABWT (JSR-82) – Teil 1: Bluetooth Protokolle

Tuesday, September 25th, 2018

JABWT (”Java APIs for Bluetooth wireless technology”) ist der Java-Standard (JSR-82) für Bluetooth Applikationen. Mittlerweile wird dieser Standard von vielen aktuellen Mobiltelefonen unterstützt. In dieser Artikelserie geht es um einen sehr groben Überblick über die Möglichkeiten dieser API.

Als Einstieg kurz die wichtigsten Bluetooth Protokolle :

Bluetooth Protokolle: L2CAP, RFCOMM, OBEX und SDP

L2CAP (Logical Link Control and Adaptation Protocol) – Jede Bluetooth Datenverbindung (Ausnahme: Bluetooth Audio) verwendet das L2CAP Protokoll als Basis. Dieses Protokoll verwendet das HCI (Host Controller Interface) und abstrahiert den eigentlichen Zugriff auf den Bluetooth Controller.

RFCOMM (Radio Frequency Communication) simuliert eine oder mehrere RS-232 Serialport Verbindungen zwischen zwei Geräten. Die Daten werden in Form von Streams ausgetauscht.

OBEX (Object Exchange Protokoll) baut auf RFCOMM auf und ist als Alternative zu HTTP konzipiert worden. Ein OBEX Request (und auch die Response) kann in kleinere Teile zerlegt und verarbeitet werden. Einsatzzweck ist z.B. das Drucken von Dokumenten (Das Basic Printing Profile basiert auf OBEX)

SDP (Service Discovery Protokoll) erlaubt das Suchen und Inspizieren von Bluetooth Diensten.