
Bluetooth orienté java : JSR82 + Android jean-michel Douin, douin au cnam point fr version du 22 Novembre 2011 Notes de cours et mise en œuvre
Sommaire • Le contexte • Bluetooth, caractéristiques, brève présentation • Les protocoles et profils • JSR82, Principes • Deux paquetages, • Usage identique pour J2SE et J2ME • Découverte • Des périphériques BT et des services • Android, en première approche • Client • Communication • RFComm btspp:// • OBEX btgoep:// …
Bibliographie utilisée La doc de l’API jsr82, http://jcp.org/aboutJava/communityprocess/final/jsr082/index.html http://www.kjhole.com/Standards/BT/BTdownloads.html http://bluevirus.googlecode.com/files/bluetooth-for-java.9781590590782.22021.pdf http://www.bluecove.org/bluecove/apidocs/ Recherche google : Un exposé de Macherel Bruno ppt M2PGI – UFRIMA Une présentation de Apurva Kumar(www.research.ibm.com/people/k/kapurva) Un exposé de Camille Diou, université de Metz, http://www.usc.edu/dept/ee/scip/assets/001/57411.pdf http://www.ieee802.org/11/Tutorial/90538S-WPAN-Bluetooth-Tutorial.pdf http://www.cs.umu.se/kurser/TDBD16/VT07/Bluetooth-Tutorial-2001.pdf http://www.bluetooth.com http://www.newlogic.com http://javabluetooth.chris-lorenz.com/ The JavaBluetooth Stack is a 100% (no native) Java implementation of the Bluetooth Specifications Version 1.1. It currently supports HCI, L2CAP and SDP. http://code.google.com/p/btfree/downloads/list http://www.bluecove.org pour un grand nombre de JVM … http://developer.android.com/guide/topics/wireless/bluetooth.html souvent référencé
http://www.iogear.com/product/GBU341W6/http://www.iogear.com/product/GBU421W6/http://www.iogear.com/product/GBU341W6/http://www.iogear.com/product/GBU421W6/ Préambule Le contexte J2SE 6.0, update 11 WindowsXP/SP2, Outil de développement Bluej 2.2.1 … PC/clé Iogear GBU341W6, GBU421W6 librairie bluecove www.bluecove.org 2.1.0, « on winsock » Les MIDlet Outils NetBeans 6.5, WTK 2.5.2 CLDC1.1, MIDP2.0 sur PC avec le micro-emulator http://www.microemu.org/ sur mobiles : sony ericsson S500i, W580i, Motorola K1 KRZR Note: à priori, le WTK ne permet qu’une émulation du BT HTC Galaxy Tab, 2.2 API 8, HTC Magic
Marketing Aux alentours de 10 à 100 mètres (BT 2.0, class 1, class 2) Source : http://www.cs.umu.se/kurser/TDBD16/VT07/Bluetooth-Tutorial-2001.pdf
Bluetooth • Protocole de communication sans fil peu chère, peu consommatrice d’énergie…, adapté aux mobiles • Spécifications ici http://www.bluetooth.com/bluetooth/ • Bluetooth is not a one-on-one data transmission technology so it can communicate with up to eight devices within its transmission radius at one time • Vocable « habituel » : • Découverte multicast des services • Client/serveur, serveur/serveur
Mesures, à vérifier… Figures extraites de http://www.licm.sciences.univ-metz.fr/IMG/pdf/Cours_Bluetooth.pdf http://www.dandu.be/article/article-bluetooth-comparaison-dongles-46.html http://www.sena.com/blog/?p=74 BT 2.0 10-100m … Performances : à vérifier …
Des chiffres • Ondes radios : 2400 – 2483,5 MHz • Débits annoncés : 1 Mb/s .. 2 Mb/s • Portée : 1 à plus de 100m (1 à 100mW) • Class 3 Devices 100mW plus de 100 meters • Class 2 Devices 10mW plus de 10 meters • Class 1 Devices 1mW de 0.1-10 meters • Communication par paquets • Encadrés par des blocs de données de contrôles
Principe : des ondes autour de nous Découverte aux alentours Plusieurs périphériques peuvent répondre à une demande de services
Principe : des ondes autour de nous Le périphérique possesseur du service est connu
Vocabulaire : Piconet • Un Maître et ses esclaves • Esclaves affranchis Maître
Vocabulaire : Scatternets • Un Scatternet = plusieurs piconets
Scatternets se font et se défont • http://www.acm.org/crossroads/xrds9-4/blue.html
Combien ? • 255 appareils, 7 communications simultanées
Protocoles et profils • L2CAP • Logical Link Control and adaptation Protocol • Envoi de paquets avec un protocole donné vers le gestionnaire approprié. • RFCOMM • Émulation de ports séries au dessus de L2CAP. • OBEX • Object Exchange Protocol. • Analogue à HTTP/GET-POST, FTP • SDP • Service Discovery Protocol (SDP). • TCS • telephony control specification
Où sommes nous ? • www.cs.umu.se/kurser/TDBD16/VT07/Bluetooth-Tutorial-2001.pdf
Profils • Profils ou Capacités d’un périphériques BT à … • ftp version bluetooth, • Téléphonie sans fil, • Imprimer des documents, • Découverte des services (SDP), • .. • Applications dédiées • -> Recensement des capacités d’un appareil BT
En résumé • www.bluetooth.com/.../Technology/Works/OBEX.htm
Bluetooth, existentiel • Qui suis-je ? • Je me présente • Qui êtes vous ? • Aux alentours • Parmi vous qui possède ce service ? • Avez d’autres services à proposer ? • Quels sont-ils ? • UUID ou identification d’un service … • Adéquation UUID/URL • UUID prédéfinis, UUID pour une application • Quels protocoles ? • Où suis-je, où vais-je ? … • pas facile voir blipnet ericsson • http://www.blipsystems.com/files/filer/technical_overview.pdf
J2SE / JSR82 • Deux paquetages • Qui suis-je ?, qui est là ?, répondez … • javax.bluetooth.*; • Nommage, • Découverte • Recherche de services • Communication • btspp://localhost:{UUID} + (flux habituels) • Un protocole répandu OBEX • java.obex.*; • btgoep://localhost:localhost:{UUID} + (flux habituels) • tcpobex://1905 • Irdaobex://localhost:1900 • Session • Transfert d’objets • put, get • http://java.sun.com/javame/reference/apis/jsr082/javax/bluetooth/package-summary.html • http://www.jsr82.com • http://www.bluecove.org/
Android • android.bluetooth • Qui suis-je ?, qui est là ?, répondez … • http://developer.android.com/guide/topics/wireless/bluetooth.html
Qui suis-je ? • Chaque périphérique BT possède • Une adresse (physique) sur 48 bit et unique • (MAC adresse) • Un nom lui est associé (en général)
Premier exemple : quelle est mon adresse BT ? import javax.bluetooth.LocalDevice; public class QuiSuisJe{ public static void main(String[] args)throws Exception{ LocalDevice localDevice = LocalDevice.getLocalDevice(); System.out.println(localDevice.getBluetoothAddress() + " : " + localDevice.getFriendlyName()); } } Depuis un PC, J2SE javac -cp .;bluecove-2.1.0.jar QuiSuisJe.java java -cp .;bluecove-2.1.0.jar QuiSuisJe http://www.bluecove.org/bluecove/apidocs/
Sur simulateur de mobile et sur mobile : QuiSuisJe • A cette URL http://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/ • téléchargez sur votre poste • http://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/bluecove-2.1.0.jar • http://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/microemulator.jar • http://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/BTQuiSuisJe.jar • http://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/run_microemulateur.bat • Puis exécutez • > run_microemulateur.bat • Sur votre mobile installez cette Midlette • BTQuiSuisJe.jar
Sur Android * • QuiSuisJe ? • BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); • String name = btAdapter.getAddress(); • * Sur un mobile, bluetooth non pris en compte par l’émulateur
Bluetooh et nommage • 0019EF0117DA • Devrons nous connaître les adresses physiques ? • Non merci … • Sauf les fixes … • Une UUID associera nom logique / adresse physique • Universal Unique IDentifier • http://www.avetana-gmbh.de/avetana-gmbh/produkte/doc/javax/bluetooth/UUID.html • -> UUID nous utiliserons
La suite • Initialisation de la pile (protocole) • A la recherche d’un service • Android • J2SE/JSR82 • Découverte de périphériques BT • Aux alentours • Nommage/UUID Universally Unique IDentifier (128 bits), • existe en version courte • Communication • java.io.*, etc… • Découverte des services • Au sein de chaque entité • Nommage/UUID Universally Unique IDentifier (128 bits) • http://www.handheld-basic.com/documentation/text/page_1766.html
Un service se trouve sur ce périphérique • Il nous faut • L’adresse MAC du périphérique • Être appairé (Android) • Ex. "00:19:EF:01:17:9C" • UUID (128bits) • Qui identifie le service • ("10203040-5060-7080-90A0-B0C0D0E0F0FF");
Android • Architecture retenue • Recherche du service bluetooth au sein d’une sous-classe d’AsyncTask • Communication dans un Thread, • Synchronisation en utilisant une SynchronousQueue
Sous-classe d’AsyncTask • Proposition private class ConnexionBT extends AsyncTask<String,String,BluetoothSocket>{ protected void onPreExecute() { protected BluetoothSocket doInBackground( String... args) { protected void publishProgress(String... infos) { protected void onPostExecute(BluetoothSocket btSocket) {
Exemple private UUID MY_UUID = UUID.fromString("10203040-5060-7080-90A0-B0C0D0E0F0FF"); private class ConnexionBT extends AsyncTask<String,String,BluetoothSocket>{ private ProgressDialog dialog = null; private BluetoothDevice btDevice; protected void onPreExecute() { dialog = ProgressDialog.show(…); } protected BluetoothSocket doInBackground(String... args) { try{ this.btDevice = btAdapter.getRemoteDevice(args[0]); // @ MAC btSocket = btDevice.createRfcommSocketToServiceRecord(MY_UUID); btAdapter.cancelDiscovery(); btSocket.connect(); }catch(Exception e){} return btSocket; } protected void onPostExecute(BluetoothSocket btSocket) { os = btSocket.getOutputStream();
Communication sur os : dans un Thread public class Sender extends Thread{ private BlockingQueue<byte[]> queue; public Sender(){ queue = new SynchronousQueue<byte[]>(); this.start(); } public boolean offer(byte[] cmd){ return queue.offer(cmd); } public void close(){ this.interrupt(); } public void run(){ while(!isInterrupted()){ try { byte[] cmd = queue.take(); os.write(cmd); } catch (Exception e) { } } } } }
J2SE/Un client // à la découverte du service … connString = agent.selectService(new UUID("102030405060708090A0B0C0D0E0F0BB", false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); StreamConnection conn = (StreamConnection)Connector.open(connString); OutputStream out = conn.openOutputStream(); Reader in = new InputStreamReader(conn.openInputStream()); String str = "http://jfod.cnam.fr:8999/ds2438/\n"; out.write(str.getBytes()); out.flush(); String response = readFile(in); … // dans un Thread private static String readFile(InputStream in) throws IOException { StringWriter data = new StringWriter(); int aByte; while((aByte = in.read())!=-1){ data.write( (byte)aByte); } return data.toString(); }
Parmi mes voisins … • Parmi les périphériques BT aux alentours • Quel est celui qui possède ce service … • Apparenté à la découverte multicast… • Un service : un UUID • new UUID("102030405060708090A0B0C0D0E0F011" ,false) • 128 bits … pourquoi pas celui-ci … • Plusieurs BT peuvent répondre pour un service souhaité • « dépôt d’un fichier », mp3 … • redondance
A la découverte de … obtention d’un agent import javax.bluetooth.LocalDevice; import javax.bluetooth.DiscoveryAgent; public class ALaDécouverteDe{ public static void main(String[] args) throws Exception{ LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable( DiscoveryAgent.GIAC ); // GIAC General inquire Access Code DiscoveryAgent agent = local.getDiscoveryAgent(); un agent capable de tout faire Sélection d’un service Effectuer une recherche exhaustive
Adéquation UUID / URL LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable( DiscoveryAgent.GIAC ); // General inquire Access Code DiscoveryAgent agent = local.getDiscoveryAgent(); UUID uuid = new UUID("102030405060708090A0B0C0D0E0F011", false); String connString = agent.selectService(uuid, ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); System.out.println("connString : " + connString); Un exemple d’affichage : connString: btspp://0019EF01194C:1;authenticate=false;encrypt=false;master=false 0019EF01194C l’adresse physique :1le port de communication
Un service comme un autre • Nous avons • Un service -> un UUID • un UUID -> une URL • Une URL -> une communication • Une syntaxe de type J2ME • Une communication • Un flux d’octets, btspp:// • Un flux structuré, btgeop://
Exemple de service/UUID/J2SE C’est un serveur … protocole btspp:// StreamConnectionNotifier notifier = (StreamConnectionNotifier)Connector.open( "btspp://localhost:102030405060708090A0B0C0D0E0F010"); attente d’une requête StreamConnection conn = notifier.acceptAndOpen();
Un serveur au complet public class SimpleBTSPPServer { public static void main(String[] args) throws Exception{ LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable(DiscoveryAgent.GIAC); StreamConnectionNotifier notifier = (StreamConnectionNotifier)Connector.open( "btspp://localhost:" + "102030405060708090A0B0C0D0E0F010"); StreamConnection conn = notifier.acceptAndOpen(); InputStream in = conn.openInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(); int data; while ((data = in.read()) != -1) { out.write(data); } System.out.println(" message recu : " + out.toString()); in.close(); conn.close(); notifier.close(); } } note : ci-dessus vous avez un serveur d’une seule connexion… c’est peu… UUID
Le client à la recherche de cet UUID • Les essentiels • agent .selectService … String connString = agent.selectService( new UUID("102030405060708090A0B0C0D0E0F010", false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); • StreamConnection StreamConnection conn = (StreamConnection) Connector.open(connString);
Un exemple de client de ce service public static void main(String[] args) throws Exception{ LocalDevice local = LocalDevice.getLocalDevice(); local.setDiscoverable( DiscoveryAgent.GIAC ); DiscoveryAgent agent = local.getDiscoveryAgent(); String connString = agent.selectService( new UUID("102030405060708090A0B0C0D0E0F010", false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); StreamConnection conn = (StreamConnection) Connector.open(connString); OutputStream out = conn.openOutputStream(); out.write("next".getBytes()); out.flush(); out.close(); conn.close(); } }
Android, même principe • Extrait de http://developer.android.com/guide/topics/wireless/bluetooth.html BluetoothServerSocket btServerSocket; btServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
Un premier exemple : une passerelle BT/HTTP • BT/Web • Pourquoi faire ? HTTP://
Autre exemple une borne Bluetooth/HTTP • Un service Bluetooth, PC, J2SE relié au web • Attend une connexion BT, • réception d’une URL (en String) • Effectue la requête • Retourne la page reçue • Un client Bluetooth • Recherche ce service • Envoie une URL • Affiche le résultat
Démonstration : le serveur • Le Proxy BT<->HTTP • est une application JavaWebStart • Il suffit de cliquer ici • http:/jfod.cnam.fr/SEJA/jnlp/BTProxyHTTP.jnlp • UUID = 102030405060708090A0B0C0D0E0F0A • Réception d’une URL • Envoi du fichier, précédé de la taille de celui-ci, • Le client reste connecté
Démonstration : Côté client • Le client BT / sur un autre poste • est également une application JavaWebStart • (depuis un autre poste) http:/jfod.cnam.fr/SEJA/BTProxyClientDS2438.jnlp • Effectue une requête en http://jfod.cnam.fr:8999/ds2438/ toutes les 10mn • Le ds2438 est un capteur d’humidité relative • Côté client un navigateur ? • Sur mobile • http://sourceforge.net/search/?type_of_search=soft&words=browser+j2ME • Opera mini, sources java disponibles ? • Analogue à l’usage d’un proxy mais au protocole btspp://
Côté client/mobile • Le client BT sur votre mobile, • téléchargez cette midlette BTProxyHTTPClient.jar • http://jfod.cnam.fr/SEJA/jnlp/midlet/BTProxyHTTPClient/ • Le client BT sur un émulateur de mobile • Téléchargez tous les fichiers, puis exécuter run_microemulateur.bat
Une Variante de BTProxyHTTP • BTProxyHTTP2 • http://jfod.cnam.fr/SEJA/jnlp/BTProxyHTTP2.jnlp • Une connexion par client • Envoi d’une URL, • Réception du fichier • Fermeture de la connexion