Bluetooth orienté java : JSR82 + Android

Slides:



Advertisements
Présentations similaires
Mais vous comprenez qu’il s’agit d’une « tromperie ».
Advertisements

Le Nom L’adjectif Le verbe Objectif: Orthogram
ORTHOGRAM PM 3 ou 4 Ecrire: « a » ou « à » Référentiel page 6
Page 1 Retour sur le e- tourisme. Page 2 Quelques chiffres…
Réaliser en Java un programme client d’une Base de Données
Le monde i-mode Epreuve Oral – 16/03/05 Master STIC / CAM API et environnement de développement Bakogiannis Anastasios ( )
Additions soustractions
Distance inter-locuteur
1 Plus loin dans lutilisation de Windows Vista ©Yves Roger Cornil - 2 août
Au programme du jour …. Ce que vous navez pas encore vu Constantes et variables de classe Main et Tests Utilisation de lAPI Existence des packages Existence.
Android View, onClick, Activity, Modèle Vue Contrôleur
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Les numéros 70 –
Les numéros
Les identités remarquables
Le, la, les words Possessive Adjectives MINE!!. 2 My in french is mon, ma,mes... Le word/ begins with a vowel: Mon La word: Ma Les word: Mes.
1 V-Ingénierie… La compétence au service de lexigence… vous présente.
Cours MIAGE « Architectures Orientées Services » Henry Boccon-Gibod 1 Orchestration de Web Services Module 5 Exercice Pratique à l'usage de l'environnement.
Cours MIAGE « Architectures Orientées Services » Henry Boccon-Gibod 1 Architectures Orientées Services Composants de Service Exemple pratique de développement.
Architecture de réseaux
Introduction à la logique
Algorithme et structure de données
LICENCE MIAGE Introduction Programmation Orientée Objet JAVA philippe
LES TRIANGLES 1. Définitions 2. Constructions 3. Propriétés.
User management pour les entreprises et les organisations Auteur / section: Gestion des accès.
Révision (p. 130, texte) Nombres (1-100).
La législation formation, les aides des pouvoirs publics
1 7 Langues niveaux débutant à avancé. 2 Allemand.
Exercice Trame Ethernet
Initiation et perfectionnement à lutilisation de la micro-informatique Créer un blog avec Windows Live Spaces sur un Mac ou sur un PC ©Yves Roger Cornil.
1 5 octobre 2011 / paw Présentation du 7 octobre 2011.
La méthodologie………………………………………………………….. p3 Les résultats
LOG 02 Bases de Données Avancées Rappels sur JSP / Servlet
XML-Family Web Services Description Language W.S.D.L.
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
Le soccer & les turbans Sondage mené par lAssociation détudes canadiennes 14 juin 2013.
Présentation générale
1 Guide de lenseignant-concepteur Vincent Riff 27 mai 2003.
GRAM 1 CE2 Je sais transformer une phrase affirmative en phrase négative.
Le drapeau canadien comme symbole de fierté nationale : une question de valeurs partagées Jack Jedwab Association détudes canadiennes 28 novembre 2012.
Si le Diaporama ne s'ouvre pas en plein écran Faites F5 sur votre clavier.
Projet poker 1/56. Introduction Présentation de léquipe Cadre du projet Enjeux Choix du sujet 2.
F Copyright © Oracle Corporation, Tous droits réservés. Créer des programmes avec Procedure Builder.
Internet : la mémoire courte ? Capture de sites Web en ligne Conférence B.N.F, Avril 2004 Xavier Roche(HTTrack)
Logiciel gratuit à télécharger à cette adresse :
Les chiffres & les nombres
DUMP GAUCHE INTERFERENCES AVEC BOITIERS IFS D.G. – Le – 1/56.
802.1x Audric PODMILSAK 13 janvier 2009.
Année universitaire Réalisé par: Dr. Aymen Ayari Cours Réseaux étendus LATRI 3 1.
Macherel Bruno M2PGI - UFRIMA
COURS DE PROGRAMMATION ORIENTEE OBJET :
1 CSI 2532 Lab6 Application Web et DB Février 27, 2012.
Java, les objets : tout de suite ! Rassembler, grouper les objets
Proxy et plus Cnam Paris jean-michel Douin, douin au cnam point fr
Android View, onClick, Activity, Modèle Vue Contrôleur
MAGIE Réalisé par Mons. RITTER J-P Le 24 octobre 2004.
1 INETOP
Aire d’une figure par encadrement
1111 Gestion des exceptions Objectifs À la fin de ce cours, vous serez capables de : • Expliquer les concepts de base de la gestion des exceptions.
MAGIE Réalisé par Mons. RITTER J-P Le 24 octobre 2004.
JEE 5 F.Pfister 2 institut eerie JEE – Une plateforme serveur  Développement et exécution d'applications réparties.
1/65 微距摄影 美丽的微距摄影 Encore une belle leçon de Macrophotographies venant du Soleil Levant Louis.
Certains droits réservés pour plus d’infos, cliquer sur l’icône.
Nom:____________ Prénom: ___________
La formation des maîtres et la manifestation de la compétence professionnelle à intégrer les technologies de l'information et des communications (TIC)
CEG3585/CEG3555 Tutorat 2 Hi ver 2013.
Les sockets.
Schéma de conception Factory Method Exemple Sylvain Giroux.
Architecture Client/Serveur
Transcription de la présentation:

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 Les protocoles et profils JSR82, Principes 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é

Préambule Le contexte J2SE 6.0, update 11 WindowsXP/SP2, http://www.iogear.com/product/GBU341W6/ http://www.iogear.com/product/GBU421W6/ 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 BT 2.0 10-100m … 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 RFCOMM OBEX SDP TCS 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 Describe configuration of the Bluetooth stack for different types of applications. Specify minimum requirements from Bluetooth layers for each profile. Generic access profile give recommendations and common requirements for access procedures.

De la documentation originale

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.bluetooth Android 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 Devrons nous connaître les adresses physiques ? 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) {

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 typical usecase

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 :1 le 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 StreamConnectionNotifier notifier = 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 ?

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 http://jfod.cnam.fr/SEJA/jnlp/BTProxyHTTP2.jnlp Une connexion par client Envoi d’une URL, Réception du fichier Fermeture de la connexion

Quelques traces Côté serveur Côté client 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

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();

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 Bluetooth et Un Thread pour chaque requête HTTP ! Protocole : envoi de l’URL « http:// … » puis attente du résultat

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){} }}

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 ?

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 …

Obtention de la liste de tous les périphériques bluetooth aux alentours

Comment ? startInquiry  deviceDiscovered

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);

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); }

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){}

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

Un schéma/résumé extrait de la bibliographie http://www.usc.edu/dept/ee/scip/assets/001/57411.pdf

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){} });

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

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); System.out.println(list.length + " devices cached");

Cached CACHED Détecté lors d’un précédent inquiry … La pile s’en charge … évite (parfois) le recours à la phase inquiry …

Diagramme d’états, ou un résumé La suite

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

À la recherche des services (famille listener) http://www.usc.edu/dept/ee/scip/assets/001/57411.pdf

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

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

Exemple liste de tous les services http://jfod.cnam.fr/SEJA/jnlp/BTServiceBrowser.jnlp

Comment ? Les périphériques découverts: Les services découverts: 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; } Les périphériques découverts: Vector<RemoteDevice> devices = new Vector<RemoteDevice>(); Les services découverts: Vector<ServiceRecord> services = new Vector<ServiceRecord>();

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(services.elementAt(i).getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false)); }catch(Exception e){} str.append(">\n"); } return str.toString();

Lire les résultats retournés Comment ? Quelle Structure ? À faire 0x4: DATSEQ { UUID 0000010000001000800000805f9b34fb } UUID 0000000300001000800000805f9b34fb U_INT_1 0x10 0x1: UUID 102030405060708090a0b0c0d0e0f088 UUID 0000110100001000800000805f9b34fb 0x0: U_INT_4 0x10100

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/

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-bit SDP 0x0001 16-bit RFCOMM 0x0003 16-bit OBEX 0x0008 16-bit HTTP 0x000C 16-bit L2CAP 0x0100 16-bit BNEP 0x000F 16-bit Serial Port 0x1101 16-bit ServiceDiscoveryServerServiceClassID 0x1000 16-bit BrowseGroupDescriptorServiceClassID 0x1001 16-bit PublicBrowseGroup 0x1002 16-bit OBEX Object Push Profile 0x1105 16-bit OBEX File Transfer Profile 0x1106 16-bit Personal Area Networking User 0x1115 16-bit Network Access Point 0x1116 16-bit Group Network 0x1117 16-bit

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; }

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

Mise en œuvre « Prise de contrôle distant » HTTP:// 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…

Démonstration Côté serveur Un client sur PC pour les tests 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

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 …

Un schéma / résumé

En résumé Le client et son agent

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 Protocol AVC(D)TP Audio/Video Control(Distribution) Transport Protocol HCI Host Controller Interface

OBEX

OBEX Client/Server Les clients OBEX Le Serveur CONNECT, GET, PUT … import javax.obex.ClientSession; import javax.obex.HeaderSet; import javax.obex.Operation; import javax.obex.ResponseCodes; Le Serveur UUID uuid = new UUID("8841", true); String url = "btgoep://localhost:" + uuid + ";name=FTP;authenticate=false;master=false;encrypt=false"; import javax.obex.ServerRequestHandler; import javax.obex.SessionNotifier;

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 …

Une session Client, ici un envoi d’un fichier Recherche du « bon service » ici serverURL 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

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));

Le service Inscription du service A chaque client 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

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; }}

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){} }}}

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/

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

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 ?

Petit outil de diffusion suite La Midlette BTFileUpLoad Contient une archive BTFileUpLoad.jar qui contient à son tour …

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/

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

Démo microemulator/ pile bluecove server 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/

Le patron/observateur/Observé-MVC HTTP Observateurs/Observé modele 2,mise à jour) http://vue1/update/?temperature=300 http://vue2/update/?temperature=300 Contrôle Vue Vue 1,notification) Vue vue1 http://modele/notifyObservers/?temperature=300 0,init) http://modele/addObserver/http://vue1/update/

MVC HTTP+BT modele Contrôle Vue Vue Vue vue1 HTTP/BT 2,mise à jour) Observateurs/Observé Midlettes BTProxyHTTP BTServerHTTP modele 2,mise à jour) http://vue1/update/?temperature=300 http://vue2/update/?temperature=300 Contrôle Vue Vue 1,notification) Vue vue1 http://modele/notifyObservers/?temperature=300 0,init) http://modele/addObserver/http://vue1/update/ http://modele/addObserver/uuid=11223344556677889900

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)

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 ); // une seconde notification request = new GetMethodWebRequest("http://localhost:8226/notifyObservers/?temperature=200&capteur=DS1922" ); }finally{ ObservableServer.stopServer(); }

Une démonstration … Démonstration en ligne : Traces côté Observable 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 Côté Mobile, bluetooth

Petite conclusion Observateur/Observé sur le web Mobiles Contrôles/ Vue Modèle ? / liaison web ? En quelques lignes Abstraction des distances À terminer

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

Conclusion http://www.bluecove.org/ à vérifier sur d’autres périphériques

Annexes UbiqMuseum Réseaux ad’hoc broadcast Télécommandes…

UbiqMuseum comme projet http://monet.knu.ac.kr/~cktoh/data/Springer_jucano_pmanzoni_Toh.pdf

UbiqMuseum Tout visiteur reçoit une MIDlet de visite MIDLet cliente et/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

UbiqMuseum Discussion

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>

Annexe : MIDlet javax.bluetooth.* JSR82 javax.bluetooth

Device Management Device Management LocalDevice() appelé par l’application cliente setDiscoverable() updateRecord() getBluetoothAddress() getProperty() RemoteDevice() informations du fournisseur authenticate() authorize() isEncrypted()

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 - btspp indique le protocole RFCOMM (StreamConnection) - hostname soit localhost, ou l’adresse Bluetooth - CN est le numéro de port - UUID l’identifiant du service - parameters authenticate, authorize, and encrypt information - Eg: btspp://hostname;authenticate=true;authorize=true;encrypt=true

Annexe Klings

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

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