Upload
leone-blaise
View
114
Download
5
Embed Size (px)
Citation preview
BT_java1
Bluetooth orienté java : JSR82 + Android
Notes de cours et mise en œuvre
jean-michel Douin, douin au cnam point fr
version du 22 Novembre 2011
BT_java2
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:// …
BT_java3
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.htmlhttp://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 – UFRIMAUne 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.pdfhttp://www.ieee802.org/11/Tutorial/90538S-WPAN-Bluetooth-Tutorial.pdfhttp://www.cs.umu.se/kurser/TDBD16/VT07/Bluetooth-Tutorial-2001.pdf
http://www.bluetooth.comhttp://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/listhttp://www.bluecove.org pour un grand nombre de JVM …
http://developer.android.com/guide/topics/wireless/bluetooth.html
souvent référencé
BT_java4
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 KRZRNote: à priori, le WTK ne permet qu’une émulation du BT
HTC Galaxy Tab, 2.2 API 8, HTC Magic
http://www.iogear.com/product/GBU341W6/http://www.iogear.com/product/GBU421W6/
BT_java5
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
BT_java6
Bluetooth
• Protocole de communication sans filpeu 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
BT_java7
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 …
BT_java8
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
BT_java9
Principe : des ondes autour de nous
Découverte aux alentours Plusieurs périphériques peuvent répondre à une demande de services
BT_java10
Principe : des ondes autour de nous
Le périphérique possesseur du service est connu
BT_java11
Vocabulaire : Piconet
• Un Maître et ses esclaves
• Esclaves affranchis Maître
BT_java12
Vocabulaire : Scatternets
• Un Scatternet = plusieurs piconets
BT_java13
Scatternets se font et se défont
• http://www.acm.org/crossroads/xrds9-4/blue.html
BT_java14
Combien ?
• 255 appareils, 7 communications simultanées
BT_java15
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
BT_java16
Où sommes nous ?
• www.cs.umu.se/kurser/TDBD16/VT07/Bluetooth-Tutorial-2001.pdf
BT_java17
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
BT_java18
De la documentation originale
BT_java19
En résumé
• www.bluetooth.com/.../Technology/Works/OBEX.htm
BT_java20
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
BT_java21
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/
BT_java22
Android
• android.bluetooth
• Qui suis-je ?, qui est là ?, répondez …
– http://developer.android.com/guide/topics/wireless/bluetooth.html
BT_java23
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)
BT_java24
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, J2SEjavac -cp .;bluecove-2.1.0.jar QuiSuisJe.java
java -cp .;bluecove-2.1.0.jar QuiSuisJe
http://www.bluecove.org/bluecove/apidocs/
BT_java25
Sur simulateur de mobile et sur mobile : QuiSuisJe
A cette URL http://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/
téléchargez sur votre postehttp://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/bluecove-2.1.0.jarhttp://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/microemulator.jarhttp://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/BTQuiSuisJe.jarhttp://jfod.cnam.fr/SEJA/jnlp/midlet/BTQuiSuisJe/run_microemulateur.bat
Puis exécutez
> run_microemulateur.bat
Sur votre mobile installez cette Midlette
BTQuiSuisJe.jar
BT_java26
Sur Android *
QuiSuisJe ?
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
String name = btAdapter.getAddress();
* Sur un mobile, bluetooth non pris en compte par l’émulateur
BT_java27
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
BT_java28
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
BT_java29
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");
BT_java30
Android
• Architecture retenue
– Recherche du service bluetooth au sein d’une sous-classe d’AsyncTask
– Communication dans un Thread,
– Synchronisation en utilisant une SynchronousQueue
BT_java31
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) {
BT_java32
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();
BT_java33
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) {}
} } }}
BT_java34
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(); }
BT_java35
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
BT_java36
A typical usecase
BT_java37
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 faireSélection d’un service
Effectuer une recherche exhaustive
BT_java38
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:1 le port de communication
BT_java39
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://
BT_java40
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();
BT_java41
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
BT_java42
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);
BT_java43
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();
}}
BT_java44
Android, même principe
• Extrait de http://developer.android.com/guide/topics/wireless/bluetooth.html
BluetoothServerSocket btServerSocket;
btServerSocket =
mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
BT_java45
Un premier exemple : une passerelle BT/HTTP
• BT/Web
• Pourquoi faire ?
HTTP://
BT_java46
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
BT_java47
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é
BT_java48
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://
BT_java49
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
BT_java50
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
BT_java51
Quelques traces
• Côté serveur–http://jfod.cnam.fr/SEJA/jnlp/BTProxyHTTP2.jnlp
• Côté client– http://jfod.cnam.fr/SEJA/jnlp/MiniBrowser.jnlp– un autre exemple voir page suivante
Application extraite de • http://www.java-tips.org/java-se-tips/javax.swing/how-to-create-a-simple-browser-in-swing-3.html
BT_java52
Un client … du classique
// à 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);
…
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(); }
BT_java53
Le serveur en quelques lignes
LocalDevice local = LocalDevice.getLocalDevice();local.setDiscoverable(DiscoveryAgent.GIAC);
StreamConnectionNotifier notifier = (StreamConnectionNotifier)Connector.open("btspp://localhost:" +
"102030405060708090A0B0C0D0E0F0BB" + ";name=BTProxyHTTP2"); …
while(true){ StreamConnection conn = notifier.acceptAndOpen(); new ConnexionBT(conn).start(); }
ConnexionBT Un Thread à chaque connexion Bluetoothet Un Thread pour chaque requête HTTP !
Protocole :envoi de l’URL « http:// … » puis attente du résultat
BT_java54
Le serveur suite, classe interne ConnexionBT
private static class ConnexionBT extends Thread{ private StreamConnection conn; private String url; public ConnexionBT(StreamConnection conn){this.conn = conn;} public void run(){ try{ OutputStream out = conn.openOutputStream(); Reader in = new InputStreamReader(conn.openInputStream()); this.url = readLine(in); if (url!=null) { ConnexionHTTP connect = new ConnexionHTTP(url); System.out.print(" -> une requete en " + this.url); String result = connect.result(); System.out.println(", page lue et envoyée : " + result.length() + " octet(s), iso-8859-1"); byte data[] = result.getBytes("iso-8859-1"); // le contenu out.write(data); out.flush(); } out.close(); in.close(); conn.close(); }catch(Exception e){} }}
BT_java55
Découverte suite
• Avec BTProxyHTTP, BTProxyHTTP2– L’URL est connue
agent.selectService(new UUID("102030405060708090A0B0C0D0E0F0BB", false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
• Notion de familles de services
• Quelles sont ces familles ?
• Quels sont les services ?
BT_java56
Quels sont les services aux alentours ?
• Tout d’abord – quels sont les périphériques BT aux alentours ?– Grâce à mon agent
• agent.startInquiry() : patience… au moins 10 secondes …
• ensuite– Recherche des services bien connus ?
• OBEX : push obex, ftp, • Etc …
BT_java57
Obtention de la liste de tous les périphériques bluetooth aux alentours
BT_java58
Comment ? startInquiry deviceDiscovered
BT_java59
En Java : un listener appelé par l’API
• L’interface DiscoveryListener– 4 méthodes,
• 2 pour la découverte des périphériques• 2 pour la découverte des services
public void deviceDiscovered( RemoteDevice rd, DeviceClass cod ) ;
public void inquiryCompleted( int status );
public void serviceSearchCompleted( int transID, int respCode ) ;
public void servicesDiscovered( int transID, ServiceRecord[] rec);
BT_java60
Exemple : Liste des périphériques BT, startInquiry
public class BTDeviceList{
private static Object inquiry = new Object(); private static Vector<RemoteDevice> devices = new Vector<RemoteDevice>();
public static void main(String argv[]) throws Exception{
LocalDevice local = LocalDevice.getLocalDevice();
DiscoveryAgent agent = local.getDiscoveryAgent();
agent.startInquiry( DiscoveryAgent.GIAC, new DeviceDiscover());
System.out.println("start device inquiry ...");
synchronized(inquiry){ inquiry.wait();} // attente … en sec.
System.out.println("device list : " + devices);
}
BT_java61
Exemple suite : le listener…
private static class DeviceDiscover implements DiscoveryListener{
public void deviceDiscovered( RemoteDevice rd, DeviceClass cod ) {
devices.addElement(rd);
}
public void inquiryCompleted( int status ) {
synchronized(inquiry) {
try { inquiry.notify(); } catch(Exception e) {}
}
}
public void serviceSearchCompleted( int transID, int respCode ) {}
public void servicesDiscovered( int transID, ServiceRecord[] rec){}
}
}
BT_java62
Démonstration
– Il suffit de cliquer ici • http:/jfod.cnam.fr/SEJA/jnlp/BTDeviceList.jnlp
Des affichages sur la console sont effectués
Il vous faut sélectionner l’option Afficher La Console
panneau de configuration, Java, puis dans l’onglet Avancé
Ou bien en téléchargeant l’archive
– java -cp bluecove-2.1.0.jar;BTDeviceList.jar BTDeviceList
BT_java63
Un schéma/résumé extrait de la bibliographie
• http://www.usc.edu/dept/ee/scip/assets/001/57411.pdf
BT_java64
Un autre exemple plus compact …
public static void main(String[] args) throws Exception{ LocalDevice localDevice = LocalDevice.getLocalDevice(); DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent(); discoveryAgent.startInquiry(DiscoveryAgent.GIAC, new DiscoveryListener(){ public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod){ try{
System.out.println(" New device discovered : " + btDevice.getFriendlyName(true) + " (" + btDevice.getBluetoothAddress() + ")" ); } catch(Exception e){e.printStackTrace();} }
public void inquiryCompleted(int discType){ System.out.println("inquiryCompleted");System.exit(0); }
public void servicesDiscovered(int transID, ServiceRecord[] servRecord){} public void serviceSearchCompleted(int transID, int respCode){} });
}
BT_java65
Quels services ?, filtrage possible ?
• bluecove.inquiry.duration – Device Inquiry time in seconds defaults to 11 seconds.
– General Inquiry Access Code GIAC– Limited Inquiry Access Code LIAC
• Notez que pour aller plus vite– Nous pouvons retrouver les périphériques déjà découverts
• De DiscoveryAgent methode retrieveDevices(): – RemoteDevice[] retrieveDevices(int option);
– ...– Avec comme option
• CACHED périphériques déjà découverts dans le passé• PREKNOWN la liste des pré-configuré … ? À éclaicir
– Mais aucune garantie que le périphérique est toujours accessible,– Il a été découvert dans le passé, c’est tout
BT_java66
Exemple : PREKNOW / CACHED
private void addDevices_PREKNOW_AND_CACHED(){ RemoteDevice[] list = null;
list = agent.retrieveDevices(DiscoveryAgent.PREKNOWN);
if(list!=null){ System.out.println(list.length + " preknow"); for(int i = 0; i < list.length; i++){ devices.addElement(list[i]); } }
list = agent.retrieveDevices(DiscoveryAgent.CACHED);
if(list!=null){ System.out.println(list.length + " devices cached"); for(int i = 0; i < list.length; i++){ devices.addElement(list[i]); } } }
BT_java67
Cached
• CACHED– Détecté lors d’un précédent inquiry …
–La pile s’en charge … évite (parfois) le recours à la phase inquiry …
BT_java68
Diagramme d’états, ou un résumé
La suite
BT_java69
Services -> Nouvelles questions ?
– Quels sont les services ?
– Quel filtre pour l’obtention des services ? Comment ?
– Démonstration• Autorisez le bluetooth de vos mobiles …
• http://jfod.cnam.fr/SEJA/jnlp/BTServiceBrowser.jnlp
BT_java70
À la recherche des services (famille listener)
• http://www.usc.edu/dept/ee/scip/assets/001/57411.pdf
BT_java71
Exemple, UUID et plus
• Sur chaque périphérique découvert– discoveryAgent.searchServices(attrSet, uuidSet, remoteDevice, this);
– Avec – UUID[] uuidSet = {new UUID(0x0100)};
• // 0x0100 au dessus de L2CAP• // 0x105 only searches btspp services• http://www.avetana-gmbh.de/avetana-gmbh/produkte/doc/javax/bluetooth/UUID.html
– int[] attrSet = {0x0100, 0x0003, 0x0004};
• // 0x0100 ProtocolDescriptorList • // 0x0003 ServiceID UUID• // 0x0004 ProtocolDescriptorList • http://www.forum.nokia.com/document/Java_Developers_Library_v2/GUID-9F75713D-5642-4C39-9A33-
C20928F37BF7/javax/bluetooth/ServiceRecord.html
BT_java72
Un lundi après-midi au Cnam, 3ème étage
LocalDevice properties: VIVALDI (0019155A34C7)
New device discovered : LMI84 (0019EF01194C) New device discovered : La Tigresse (00180FD94A7C)
Searching for Services on: LMI84 (0019EF01194C) A new service is discovered: Service Discovery A new service is discovered: S e r v i c e u t i l i s a t e u r a d - h o c p e r s o n n e l
Searching for Services on: La Tigresse (00180FD94A7C) A new service is discovered: Dial-up networking A new service is discovered: Nokia PC Suite A new service is discovered: COM 1 A new service is discovered: Audio Gateway A new service is discovered: SIM ACCESS A new service is discovered: OBEX Object Push A new service is discovered: OBEX File Transfer A new service is discovered: SyncML Client
BT_java73
Exemple liste de tous les services
• http://jfod.cnam.fr/SEJA/jnlp/BTServiceBrowser.jnlp
BT_java74
Comment ?
• Les périphériques découverts:– Vector<RemoteDevice> devices = new Vector<RemoteDevice>();
• Les services découverts:– Vector<ServiceRecord> services = new Vector<ServiceRecord>();
public void startSearchServices() throws Exception{ UUID uuids[] = {new UUID(0x0100)}; // "0100" L2CAP int attridset[] = {0x0100}; // SERVICE_NAME_ATTRID = 0x0100; this.services.clear(); System.out.println("start search services for " + devices.size() + " devices");
for( int i=0; i<devices.size(); i++ ) { RemoteDevice rd = devices.elementAt(i); System.out.println(" search services for " + rd.getBluetoothAddress()); agent.searchServices(attridset, uuids, rd, this); synchronized(this) { while(!serviceSearchCompleted) wait(); serviceSearchCompleted=false; } } }
BT_java75
Les services en clair …
// tous les services, <HostDevice,nom du service, URL>
for(int i=0; i< services.size(); i++){ str.append("<"); str.append(services.elementAt(i).getHostDevice().getBluetoothAddress()); try{ DataElement nameElement =
(DataElement)services.elementAt(i).getAttributeValue(SERVICE_NAME_ATTRID);
str.append(","); if ( nameElement != null )
str.append((String)nameElement.getValue()); else str.append("_"); str.append(",");
str.append(services.elementAt(i).getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));
}catch(Exception e){} str.append(">\n"); } return str.toString();
BT_java76
Lire les résultats retournés
• Comment ?
• Quelle Structure ? À faire
• 0x4:• DATSEQ {• DATSEQ {• UUID 0000010000001000800000805f9b34fb• }• DATSEQ {• UUID 0000000300001000800000805f9b34fb• U_INT_1 0x10• }• }• 0x1:• DATSEQ {• UUID 102030405060708090a0b0c0d0e0f088• UUID 0000110100001000800000805f9b34fb• }• 0x0:• U_INT_4 0x10100• }
BT_java77
Comment ? suite
public void serviceSearchCompleted( int transID, int respCode ) { System.out.println("service search complete"); synchronized(this) { try { serviceSearchCompleted=true; this.notifyAll(); } catch(Exception e) {} }
} public void servicesDiscovered( int transID, ServiceRecord[] rec){ if(rec!=null && rec.length>0){ for( int i=0; i<rec.length; i++ ) { services.addElement(rec[i]); } }
• http://www.bluecove.org/bluecove/apidocs/
BT_java78
http://www.bluecove.org/bluecove/apidocs/ voir UUID
Base UUID Value (Used in promoting 16-bit and 32-bit UUIDs to 128-bit UUIDs) 0x0000000000001000800000805F9B34FB 128-bitSDP 0x0001 16-bitRFCOMM 0x0003 16-bitOBEX 0x0008 16-bitHTTP 0x000C 16-bitL2CAP 0x0100 16-bitBNEP 0x000F 16-bitSerial Port 0x1101 16-bitServiceDiscoveryServerServiceClassID 0x1000 16-bitBrowseGroupDescriptorServiceClassID 0x1001 16-bitPublicBrowseGroup 0x1002 16-bitOBEX Object Push Profile 0x1105 16-bitOBEX File Transfer Profile 0x1106 16-bitPersonal Area Networking User 0x1115 16-bitNetwork Access Point 0x1116 16-bitGroup Network 0x1117 16-bit
BT_java79
Autre exemple
• Qui aux alentours possède ce service ?– Object push, c’est un service au protocole OBEX
– final UUID OBEX_OBJECT_PUSH = new UUID(0x1105);– final UUID OBEX_FILE_TRANSFER = new UUID(0x1106);– final int SERVICE_NAME_ATTRID = 0x0100;
public void startSearchServices() throws Exception{ UUID uuids[] = {OBEX_OBJECT_PUSH}; int attridset[] = {SERVICE_NAME_ATTRID}; for(int i=0;i<devices.size();i++){ RemoteDevice rd = devices.elementAt(i);
agent.searchServices(attridset, uuids, rd, this); synchronized(this) { while(!serviceSearchCompleted) wait(); serviceSearchCompleted=false; } } }
BT_java80
Exemple : Remote Control
• A l’origine un exemple sur le web
– sourceforge.net/projects/blurc
– Défilement distant de diapositives PowerPoint (par exemple)
• Contrôle distant du clavier– Ajouts d’évènements dans la file « du système »
» Usage de java.awt.Robot
• http://doc.javastaff.com/?p=159 le blog de Federico Paparoni– http://doc.javastaff.com/?dl=11– http://doc.javastaff.com/?dl=10
• BTFree ici http://code.google.com/p/btfree/downloads/list– Une librairie qui peut être utile
BT_java81
Mise en œuvre « Prise de contrôle distant »
• Choix d’un protocole de communication– Plusieurs mobiles en même temps – la connexion reste ouverte
• Envoi de next\n vers le serveur, (son interprétation ->)• Envoi de previous\n vers le serveur, (son interprétation <-)• Etc…
HTTP://
BT_java82
Démonstration
• Côté serveur– http://jfod.cnam.fr/SEJA/jnlp/BTServerVNC2.jnlp– Usage de java.awt.Robot
• Un client sur PC pour les tests– http://jfod.cnam.fr/SEJA/jnlp/BTClientVNC2.jnlp
–Avec microemulator–Télécharger ces fichiers
•http://jfod.cnam.fr/SEJA/jnlp/midlet/BTClientVNC/•Puis >run_microemulateur
– Sur votre mobile installez cette MIDlette•BTClientVNC.jar•http://jfod.cnam.fr/SEJA/jnlp/midlet/BTClientVNC/
BT_java83
Démonstration suite
• Pas de clé BT sur PC, pas de téléphones … le néant…
• Utilisation du WTK et de l’émulateur Bluetooth intégré
– Le « serveur » est une midlette• Le source du serveur perfectible• http://jfod.cnam.fr/SEJA/jnlp/midlet/BTServerVNC/
– Il ne vous plus qu’à développer le client !• Serait-ce une question de tp …
BT_java84
Un schéma / résumé
BT_java85
En résumé
• Le client et son agent
BT_java86
OBEX
• http://developers.sun.com/mobility/apis/articles/bluetoothobex/• http://www.ibm.com/developerworks/java/library/wi-boogie1/index.html• http://wiki.forum.nokia.com/index.php/Using_Bluetooth_obex_server_in_Java_ME
BNEP Bluetooth Network Encapsulation ProtocolAVC(D)TP Audio/Video Control(Distribution) Transport ProtocolHCI Host Controller Interface
BT_java87
OBEX
BT_java88
OBEX Client/Server
• Les clients OBEX – CONNECT, GET, PUT …import javax.obex.ClientSession;import javax.obex.HeaderSet;import javax.obex.Operation;import javax.obex.ResponseCodes;–
• Le ServeurUUID uuid = new UUID("8841", true); String url = "btgoep://localhost:" + uuid +
";name=FTP;authenticate=false;master=false;encrypt=false";
import javax.obex.Operation;import javax.obex.HeaderSet;import javax.obex.ResponseCodes;import javax.obex.ServerRequestHandler;import javax.obex.SessionNotifier;
BT_java89
OBEX : les UUID
• Object Push Profile OPP 0x1105• File Transfer Profile FTP 0x1106• Synchronization Profile SYP 0x1104• Basic Imaging Profile BIP 0x111A• Phone Book Access Profile PBAP 0x1130• Basic Printing Profile BPP 0x1122
• http://www.bluecove.org/bluecove/apidocs/– Lire le Quick Tutorial
– 0x1105– Ou – 0000110500001000800000805F9B34FB en version longue …
BT_java90
Une session Client, ici un envoi d’un fichier
1. Recherche du « bon service » ici serverURL2. Puis établissement d’une connexion au protocole OBEX
public boolean obexPut(String serverURL) {
ClientSession clientSession clientSession = (ClientSession) Connector.open(serverURL); HeaderSet hsConnectReply = clientSession.connect(clientSession.createHeaderSet());
if (hsConnectReply.getResponseCode() != ResponseCodes.OBEX_HTTP_OK) { System.out.println("Connect Error " + hsConnectReply.getResponseCode()); }
HeaderSet hsOperation = clientSession.createHeaderSet(); hsOperation.setHeader(HeaderSet.NAME, fileName); String type = ObexTypes.getObexFileType(fileName); hsOperation.setHeader(HeaderSet.LENGTH, new Long(data.length)); Operation po = clientSession.put(hsOperation);
// envoi du fichier analyse po.getResponseCode()
po.close(); HeaderSet hsDisconnect = clientSession.disconnect(null); // hsDisconnect.getResponseCode() == ResponseCodes.OBEX_HTTP_OK
BT_java91
ObexTypes.getObexFileType, apparenté mimes
public static class ObexTypes {
private static Hashtable<String,String> types = new Hashtable<String,String>();
static { types.put("jpg", "image/jpeg"); types.put("jpeg", "image/jpeg"); types.put("gif", "image/gif"); types.put("mp3", "audio/mpeg"); types.put("txt", "text/plain"); types.put("jar", "application/java-archive"); }
static String getFileExtension(String fileName) { int extEnd = fileName.lastIndexOf('.'); if (extEnd == -1) { return ""; } else { return fileName.substring(extEnd + 1).toLowerCase(); } }
static String getObexFileType(String fileName) { return (String) types.get(getFileExtension(fileName)); } }
BT_java92
Le service
• Inscription du service SessionNotifier serverConnection = (SessionNotifier)
Connector.open("btgoep://localhost:"+ serverUUID + ";name=ObexPutServer2");
• A chaque client– Une requête/un thread
– Connection conn = serverConnection.acceptAndOpen(new RequestHandler());
– Traitement de la reqûete, PUT,GET, … : -> RequestHandler
BT_java93
Le service : RequestHandler
private class RequestHandler extends ServerRequestHandler { public int onPut(Operation op) { try { HeaderSet hs = op.getReceivedHeaders(); String name = (String) hs.getHeader(HeaderSet.NAME); InputStream is = op.openInputStream(); StringBuffer buf = new StringBuffer(); int data; while ((data = is.read()) != -1) { buf.append((char) data); } op.close();
synchronized(lock){notify();} return ResponseCodes.OBEX_HTTP_OK; } catch (IOException e) { e.printStackTrace(); return ResponseCodes.OBEX_HTTP_UNAVAILABLE; } }}
BT_java94
Un client OBEX du serveur au complet
private static class ClientObex extends Thread{ private Connection conn; private SessionNotifier serverConnection; private Object lock; private class RequestHandler extends ServerRequestHandler {…} public ClientObex(SessionNotifier serverConnection) throws IOException{ this.serverConnection = serverConnection; this.lock = new Object(); this.conn = serverConnection.acceptAndOpen(new RequestHandler()); this.setPriority(10); this.start(); } public void run(){ synchronized(lock){ try{ wait(); conn.close(); }catch(Exception e){} }}}
BT_java95
Applications, c.f. bluecove
• Extraites des exemples joints avec bluecove–http://jfod.cnam.fr/SEJA/jnlp/OBEX_server.jnlp
http://jfod.cnam.fr/SEJA/jnlp/OBEX_client.jnlp
http://www.bluecove.org/bluecove/apidocs/
BT_java96
Démonstration BTFileUpload
• Envoi d’un fichier sur tous les mobiles ici présents …–1) Recherche de tous les périphériques BT
•Autoriser vos portables
–2) Sélection de tous les périphériques possédant ce service•OBEX Object push 0x1105
–http://jfod.cnam.fr/SEJA/jnlp/BTFileUpLoad.jnlp
BT_java97
Un petit outil très contagieux
• Diffusion, mise à jour, déploiement
• Hypothèse :– Une Midlet capable de diffuser une Midlet capable de diffuser une …– Usage du service OBEX Push Object prédéfini
– Comment ?
• Une archive contenue dans le .jar de la midlette est envoyée à tous ses voisins• Le voisin reçoit une archive soit une midlette qui contient une archive …
• Viable ? – TTL déguisé
• Fonctionne quelque soit le mobile ?
BT_java98
Petit outil de diffusion suite
• La Midlette BTFileUpLoad–Contient une archive BTFileUpLoad.jar qui contient à son tour …
BT_java99
Petit Outil en démonstration
• Préambule•Ok
–Avec le micro-émulateur !
–Sony Ericsson, S500i
• Motorola K1, –envoi ok,–réception incorrecte…
• La Midlette est là–http://jfod.cnam.fr/SEJA/jnlp/midlet/BTFileUpload/
BT_java100
Démo du WTK
• Voir obexdemo– Et le sous répertoire j2seObexDemo…
• Et surtout http://wiki.forum.nokia.com/index.php/Using_Bluetooth_obex_server_in_Java_ME
BT_java101
Démo microemulator/ pile bluecove
• http://wiki.forum.nokia.com/index.php/Using_Bluetooth_obex_server_in_Java_ME• Installées ici http://jfod.cnam.fr/SEJA/projet/obex_midlet/
server
BT_java102
Le patron/observateur/Observé-MVC
• HTTP– Observateurs/Observé
Contrôle Vue
modele
VueVue
vue1http://modele/notifyObservers/?temperature=300
http://vue1/update/?temperature=300
1,notification)
2,mise à jour)
http://vue2/update/?temperature=300
0,init) http://modele/addObserver/http://vue1/update/
BT_java103
MVC HTTP+BT
• HTTP/BT–Observateurs/Observé– Midlettes
•BTProxyHTTP•BTServerHTTP
Contrôle Vue
modele
VueVue
vue1http://modele/notifyObservers/?temperature=300
http://vue1/update/?temperature=300
1,notification)
2,mise à jour)
http://vue2/update/?temperature=300
0,init) http://modele/addObserver/http://vue1/update/
http://modele/addObserver/uuid=11223344556677889900
BT_java104
Patrons Observateur + Fabrique
• ObservableServer– addObserver, notifyObservers comme services Web/HTTP
• ObserverServer–Update comme service Web
• ObserversHTTPList–La liste des observateurs
• ConnectionFactory–Une fabrique de Connexion
• Deux connexions concrètes–Bluetooth et HTTP (dépend de l’url choisie)
BT_java105
Un exemple avec Httpunit
public void test_notifyBTObservers(){ try{ new Thread(new Runnable(){ // création de l’observable public void run(){ ObservableServer.main(new String[]{"8226"}); }}).start(); WebConversation conversation = new WebConversation(); WebRequest request = null;
// inscription d’un observateur
request = new GetMethodWebRequest("http://localhost:8226/addObserver/?uuid=102030405060708090A0B0C0D0E0F088"); WebResponse response = conversation.getResponse( request ); assertTrue(" pas de réponse ???", response.getText().length() > 0); assertTrue(" la réponse doit doit ici retournée true ???", response.getText().contains("true"));
// une première notification
request = new GetMethodWebRequest("http://localhost:8226/notifyObservers/?temperature=300&capteur=DS1921" ); response = conversation.getResponse( request ); assertTrue(" pas de réponse ???", response.getText().length() > 0);
// une seconde notification
request = new GetMethodWebRequest("http://localhost:8226/notifyObservers/?temperature=200&capteur=DS1922" );
response = conversation.getResponse( request ); assertTrue(" pas de réponse ???", response.getText().length() > 0); }finally{ ObservableServer.stopServer(); }}
BT_java106
Une démonstration …
• Démonstration en ligne : –http://jfod.cnam.fr/SEJA/jnlp/TestsObervable.html
• Traces côté Observable–BlueCove version 2.1.0 on winsock–Request: GET /notifyObservers/?temperature=200&capteur=DS1922 HTTP/1.1–Request: GET /addObserver/?uuid=102030405060708090A0B0C0D0E0F088 HTTP/1.1–addObserver : 102030405060708090A0B0C0D0E0F088–Request: GET /notifyObservers/?temperature=300&capteur=DS1921 HTTP/1.1–Request: GET /notifyObservers/?temperature=200&capteur=DS1922 HTTP/1.1–
• Côté Mobile, bluetooth
BT_java107
Petite conclusion
• Observateur/Observé sur le web
• Mobiles– Contrôles/ Vue
– Modèle ? / liaison web ?
• En quelques lignes– Abstraction des distances
– À terminer
BT_java108
Conclusion plus grande ?
• Bluetooth– Mobile/java
• Motorola K1, Sony Ericsson• À tester : http://www.opera.com/mini/download/all/
– Clé USB ou intégré sur PC
• bluecove API jsr82– http://www.bluecove.org/
• Cette présentation : impasse sur l2cap ?– Dans une prochaine mouture
BT_java109
Conclusion
http://www.bluecove.org/à vérifier sur d’autres périphériques
BT_java110
Annexes
• UbiqMuseum• Réseaux ad’hoc broadcast• Télécommandes…
BT_java111
UbiqMuseum comme projet
• http://monet.knu.ac.kr/~cktoh/data/Springer_jucano_pmanzoni_Toh.pdf
BT_java112
UbiqMuseum
• Tout visiteur reçoit une MIDlet de visite– MIDLet clienteet/ou– MIDLet serveur …
• Chaque pièce du musée est équipé d’un PC/BT/Wifi– Serveur / Client …– PC relié entre eux voir Java Messaging Service (JMS)
• Mode connecté– < 8 périphériques simultanés
• Mode de type Session
• Côté client– RFComm– OBEX
BT_java113
UbiqMuseum
• Discussion
BT_java114
Annexe javawebStart
• http://jfod.cnam.fr/SEJA/jnlp/mode_emploi_jnlp.html• Un certificat
– > keytool -genkey -alias jmd -keypass PASSWORD -keystore jmdstore -storepass PASSWORD
– jar cvf MiniBrowser.jar webBrowser/*.class– jarsigner -keystore jmdstore MiniBrowser.jar jmd
– http://jfod.cnam.fr/SEJA/jnlp/BTProxyHTTP2.jnlp
<jnlp spec="1.0+" codebase="http://jfod.cnam.fr/SEJA/jnlp/" href="MiniBrowser.jnlp"> <information> <title>MiniBrowser</title> <vendor>SEJA Cnam</vendor> <description>MiniBrowser</description> <offline-allowed/> </information> <security> <all-permissions/> </security> <resources> <j2se version="1.5+"/> <jar href="MiniBrowser.jar"/> <jar href="bluecove-2.1.0.jar"/> </resources> <application-desc main-class="webBrowser.MiniBrowser"/></jnlp>
BT_java115
Annexe : MIDlet javax.bluetooth.*
• JSR82– javax.bluetooth
BT_java116
Device Management
• Device Management– LocalDevice() appelé par l’application cliente– setDiscoverable()– updateRecord()– getBluetoothAddress()– getProperty()– RemoteDevice() informations du fournisseur– getBluetoothAddress()– authenticate()– authorize()– isEncrypted()
BT_java117
Résumé Communication
JSR 82 supports a low-level data transfer (Logic Link Control& Adaptation) and a stream communication interface (RFCOMM)
• L2CAP interface not commonly used– Need significant effort from user to handle the packets, fragmentation etc.,
• Stream communication API is used extensively in MIDP development• btspp://hostname:[CN | UUID];parameters
1. - btspp indique le protocole RFCOMM (StreamConnection)2. - hostname soit localhost, ou l’adresse Bluetooth3. - CN est le numéro de port4. - UUID l’identifiant du service5. - parameters authenticate, authorize, and encrypt information
• - Eg: btspp://hostname;authenticate=true;authorize=true;encrypt=true
BT_java118
Annexe Klings
BT_java119
BTBrowserMIDlet de klings
• http://wireless.klings.org/main.php/BTBrowser/
• Mise en œuvre, développement– WTK
– Avec le microemulateur*• Pile bluecove et avetana
• Les sources et exécutables– http://jfod.cnam.fr/SEJA/projet/btbrowser_klings_midlet/
– *java -cp ./microemulator.jar;./bluecove-2.0.3.jar;. org.microemu.app.Main BTBrowserMIDlet
BT_java120
BTBrowser, avec un autre émulateur
• http://kobjects.sourceforge.net/me4se/
java -cp ./me4se-2.2.0.jar;./bluecove-2.0.3.jar;. org.me4se.MIDletRunner BTBrowserMIDlet