Aller au contenu

Wiimote, Bluetooth et trame


Droiide

Recommended Posts

Bonjour à tous.

Dans le cadre de mon projet de deuxième année de DUT Informatique, je dois creer une application Androïd permettant:

1) De me connecter à une wiimote.

2) D'étudier les trames envoyées par la wiimote.

3) De renvoyer ces trames sur une Debian afin de faire fonctionner un robot.

Pour l'instant, j'ai réussi à lister les appareils bluetooth qui sont autour du telephone, à extraire leur adresses et leurs noms. Seulement, le problème qui se pose à moi maintenant est la connection à la wiimote. En effet, je ne vois pas vraiment comment faire (Il y a bien des exemples sur la documentation d'Androïd mais je ne comprends pas tout).

J'ai vu qu'il fallait un UUID seulement voilà est ce que je peux mettre n'importe quel UUID ou est ce que la wiimote à un UUID particulier?

Une autre question aussi; a quoi sert un handler? J'ai vu qu'il m'en fallait surement un.

Merci d'avance =)

PS: Si vous voulez le code que j'ai pour l'instant fait, dîtes le moi, je le posterai.

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Salut,

si je ne me trompe pas chaque équipement BT a un UUID différent, du coup tu doit pouvoir recup l'UUID de la wiimote lorsque tu la détecte.

Un handler est une méthode appelé lors d'un évènement, dans ton cas, tu vas abonner une de tes classes a un évènement donné sur le BT (par exemple réception d'une trame), lorsqu'une trame sera reçu, android va appeler ta classe et plus spécifiquement le handler qui va bien. Dans ce handler tu aura mis le code nécessaire au traitement que tu doit effectuer.

Modifié par octera
  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Sur le site android dev, tu a une très bonne page qui t'explique comment faire du début à la fin. Dans ton cas il faut que tu te mette en client BT (je pense que tu l'avais compris)

http://developer.android.com/guide/topics/wireless/bluetooth.html

Essaye de mettre ca en place et dis nous ou si tu bloque a nouveau

Modifié par octera
  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Alors j'ai essayé mais je n'arrive pas à les connecter.


public class PeripheriqueDetail  extends Activity implements OnClickListener{

Button mButtonConnection;
private TextView text;
public String adresse;
public String nom;
public String position;
public String NAME = "BluetoothSendTest";
public UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
Handler mHandler;
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();

public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.detail);

       setTitle("Detail du peripherique");

       /**
        * On recupere les informations venant de l'intent
        */
       Bundle extras = getIntent().getExtras();
       if(extras !=null)
       {
       	/**
       	 * Recuperation de l'adresse
       	 */
       	adresse = extras.getString("adresse");
       	/**
       	 * Recuperation du nom
       	 */
       	nom = extras.getString("nom");
       	/**
       	 * Recuperation de la position
       	 */
       	position = extras.getString("position");


       	/**
       	 * On affiche le tout
       	 */
       	TextView tv1 = (TextView) findViewById(R.id.nom);
       	tv1.setText("Nom : " + nom);
       	TextView tv2 = (TextView) findViewById(R.id.adresse);
       	tv2.setText("Adresse: " + adresse);
       	TextView tv3 = (TextView) findViewById(R.id.position);
       	tv3.setText("Position: " + position);


	       mHandler = new Handler() {
	    	    public void handleMessage(Message msg) {
	    	        Bundle data=msg.getData();
	    	        text.setText(String.format("text=%s , number=%d",
	    	        data.getString("text"), data.getInt("number")));
	    	    }
	        };

       	/**
       	 * On crée un bouton pour pouvoir se connecter à l'apparreil
       	 */
       	mButtonConnection = (Button)findViewById(R.id.ButtonConnection);
       	mButtonConnection.setOnClickListener(this);
       }
	}

	/**
	 * Methode permettant l'implementation du bouton de connection
	 */
	public void onClick(View v) 
	{
		/**
		 * Si le bouton connection est actionné.
		 */
		if(mButtonConnection == v)
		{
		BluetoothDevice device = mAdapter.getRemoteDevice(adresse);


		ConnectThread th2 = new ConnectThread(device);
   	    th2.start();

		}
	}



	private class ConnectThread extends Thread {
	    private final BluetoothSocket mmSocket;
	    private final BluetoothDevice mmDevice;

	    public ConnectThread(BluetoothDevice device) {


	        // Use a temporary object that is later assigned to mmSocket,
	        // because mmSocket is final
	        BluetoothSocket tmp = null;
	        mmDevice = device;

	        // Get a BluetoothSocket to connect with the given BluetoothDevice
	        try {
	            // MY_UUID is the app's UUID string, also used by the server code
	            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
	        } catch (IOException e) { }
	        mmSocket = tmp;
	    }

	    public void run() {
	        // Cancel discovery because it will slow down the connection
	        mAdapter.cancelDiscovery();

	        try {
	            // Connect the device through the socket. This will block
	            // until it succeeds or throws an exception
	        	setTitle("on essaye la connection");
	            mmSocket.connect();
	            setTitle("on a reussi la connexion");
	        } catch (IOException connectException) {
	            // Unable to connect; close the socket and get out
	            try {
	                mmSocket.close();
	            } catch (IOException closeException) { }
	            return;
	        }

	        // Do work to manage the connection (in a separate thread)
	        ConnectedThread manageConnectedSocket = new ConnectedThread(mmSocket);
	        manageConnectedSocket.start();
	    }

	    /** Will cancel an in-progress connection, and close the socket */
	    public void cancel() {
	        try {
	            mmSocket.close();
	        } catch (IOException e) { }
	    }
	}

}

Daprès ce que j'ai vu, ça bloque au niveau de la connection (mmSocket.connect();).. ça doit être à cause de l'UUID non?

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Mais est ce que mon code est bon? Il ne faudrait pas aussi faire la partie "connecting as a server" du site développer? Parce que en modifiant encore mon code ce matin j'ai remarque que ca s'arrêtai vraiment lors de l'appelle de la mèthode connect().. (le programme ne s'arrêter pas mais attends quelque chose)..

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Je poste mon nouveau code au cas ou..

public class PeripheriqueDetail  extends Activity implements OnClickListener{

Button mButtonConnection;
private TextView text;
public String adresse;
public String nom;
public String position;
public String NAME = "BluetoothSendTest";
public UUID UUID_RFCOMM_GENERIC = new UUID(0x0000110100001000L,0x800000805F9B34FBL);
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();

public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.detail);

       setTitle("Detail du peripherique");

       /**
        * On recupere les informations venant de l'intent
        */
       Bundle extras = getIntent().getExtras();
       if(extras !=null)
       {
       	/**
       	 * Recuperation de l'adresse
       	 */
       	adresse = extras.getString("adresse");
       	/**
       	 * Recuperation du nom
       	 */
       	nom = extras.getString("nom");
       	/**
       	 * Recuperation de la position
       	 */
       	position = extras.getString("position");


       	/**
       	 * On affiche le tout
       	 */
       	TextView tv1 = (TextView) findViewById(R.id.nom);
       	tv1.setText("Nom : " + nom);
       	TextView tv2 = (TextView) findViewById(R.id.adresse);
       	tv2.setText("Adresse: " + adresse);
       	TextView tv3 = (TextView) findViewById(R.id.position);
       	tv3.setText("Position: " + position);



       	/**
       	 * On crée un bouton pour pouvoir se connecter à l'apparreil
       	 */
       	mButtonConnection = (Button)findViewById(R.id.ButtonConnection);
       	mButtonConnection.setOnClickListener(this);



       }
	}

	/**
	 * Methode permettant l'implementation du bouton de connection
	 */
	public void onClick(View v) 
	{
		/**
		 * Si le bouton connection est actionné.
		 */
		if(mButtonConnection == v)
		{
			BluetoothDevice device = mAdapter.getRemoteDevice(adresse);

			try
			{
				AcceptThread th1 = new AcceptThread();
				th1.start();
				try 
				{
					Thread.sleep(5000);
				} 
				catch (InterruptedException e) 
				{
					e.printStackTrace();
				}

				ConnectThread th2 = new ConnectThread(device);
				th2.start();
				try 
				{
					Thread.sleep(5000);
				} 
				catch (InterruptedException e) 
				{
					e.printStackTrace();
				}



			}
			catch(IllegalThreadStateException e)
			{
				e.printStackTrace();
			}
		}
	}



	public class ConnectThread extends Thread 
	{
	    private final BluetoothSocket mmSocket;
	    private final BluetoothDevice mmDevice;

	    public ConnectThread(BluetoothDevice device) 
	    {

	    	setTitle("Connexion en cours...");
	    	Log.i("Bluetooth", "*****************Debut de construcetur de ConnectThread **********************\n");

	        // Use a temporary object that is later assigned to mmSocket,
	        // because mmSocket is final
	        BluetoothSocket tmp = null;
	        mmDevice = device;

	        // Get a BluetoothSocket to connect with the given BluetoothDevice
	        try 
	        {
	            // MY_UUID is the app's UUID string, also used by the server code
	          tmp = device.createRfcommSocketToServiceRecord(UUID_RFCOMM_GENERIC);
	        } 
	        catch (IOException e) 
	        {}
	        mmSocket = tmp;

	        Log.i("Bluetooth", "*****************fin du constructeur de connectedThread**********************\n");
	    }

	    public void run() 
	    {
	    	Log.i("Bluetooth", "*****************Debut de la methode run de connectedThread**********************\n");

	        // Cancel discovery because it will slow down the connection
	        mAdapter.cancelDiscovery();

	        try 
	        {
	            // Connect the device through the socket. This will block
	            // until it succeeds or throws an exception
	        	setTitle("on essaye de connecter");
	        	Log.i("Bluetooth", "*****************on essaye de connecer la wiimote **********************\n");
	            mmSocket.connect();
	            Log.i("Bluetooth", "*****************La wiimote est connecter **********************\n");
	            setTitle("on a reussi la connexion");
	        } 
	        catch (IOException connectException) 
	        {
	            // Unable to connect; close the socket and get out
	            try 
	            {
	                mmSocket.close();
	            } 
	            catch (IOException closeException) 
	            {}
	            return;
	        }

	        // Do work to manage the connection (in a separate thread)
	        //ConnectedThread manageConnectedSocket = new ConnectedThread(mmSocket);
	       // manageConnectedSocket.start();
	        Log.i("Bluetooth", "*****************Fin la methode run de connectedThread**********************\n");
	    }

	    /** Will cancel an in-progress connection, and close the socket */
	    public void cancel() 
	    {
	        try 
	        {
	            mmSocket.close();
	        } 
	        catch (IOException e) 
	        {}
	    }
	}




	private class AcceptThread extends Thread 
	{
	    private final BluetoothServerSocket mmServerSocket;

	    public AcceptThread() 
	    {

	    	Log.i("Bluetooth", "*****************Constructeur de AccpetThread **********************\n");
	        BluetoothServerSocket tmp = null;
	        try 
	        {
	            // MY_UUID is the app's UUID string, also used by the client code
	            tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, UUID_RFCOMM_GENERIC);
	        } 
	        catch (IOException e) 
	        {}
	        mmServerSocket = tmp;
	        Log.i("Bluetooth", "*****************Fin de Constructeur de AccpetThread **********************\n");
	    }

	    public void run() 
	    {
	    	Log.i("Bluetooth", "*****************Debut de la methode run (AcceptThread) **********************\n");
	        BluetoothSocket socket = null;
	        // Keep listening until exception occurs or a socket is returned
	        while (true) 
	        {
	            try 
	            {
	            	Log.i("Bluetooth", "*****************.acctect() **********************\n");
	                socket = mmServerSocket.accept();
	            } 
	            catch (IOException e) 
	            {
	                break;
	            }
	            // If a connection was accepted
	            if (socket != null) 
	            {
	                // Do work to manage the connection (in a separate thread)
	                //manageConnectedSocket(socket);
	                try 
	                {
						mmServerSocket.close();
					}
	                catch (IOException e) 
	                {
						e.printStackTrace();
					}
	                break;
	            }
	        }
	        Log.i("Bluetooth", "*****************Fin de la methode run (AcceptThread) **********************\n");
	    }

	    /** Will cancel the listening socket, and cause the thread to finish */
	    public void cancel() 
	    {
	        try 
	        {
	            mmServerSocket.close();
	        } 
	        catch (IOException e) 
	        {}
	    }
	}

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Salut,

En principe tu n'arriveras pas à te connecter à ta wiimote à travers l'API Java dAndroid. En effet la wiimote utilise le protocole bluetooth L2CAP qui n'est pas supporté par Android. Les fonctions sont présentes, mais l'ouverture de la socket échouera inexorablement...

Le ticket de bug est ouvert chez Google : http://code.google.com/p/android/issues/detail?id=719

La seule solution qui existe est d'utiliser le NDK d'Android, c'est à dire développer une bibliothèque en C qui accède directement à la libbluetooth.so du système et son implémentation de bluez. Depuis ton application Java tu fais appel à ta bibliothèque en utilisant les fonction de la JNI. Dans cette lib tu peux utiliser http://www.wiiuse.net/ qui est une bibliothèque en C permettant de communiquer avec une wiimote.

Cette solution ne fonctionne a priori pas sur les portables HTC qui ont la surcouche Sense, ni sur le Galaxy S, et certains autres portables, parce que les constructeurs ont modifié la libbluetooth.so qui ne supporte pas le L2CAP. C'est la méthode utilisée et les problèmes rencontrés par ce développeur http://forum.xda-developers.com/showthread.php?t=672884

Tout ça n'est pas une mince affaire. Si tu penses ne pas avoir les compétences ou le temps de réaliser ce pont JNI, tu as encore la solution d'établir une connexion bluetooth entre une wiimote et un PC portable, et communiquer entre le PC et le téléphone via Wifi. Il existe des bibliothèques de contrôle de wiimote en JAVA que tu pourras utiliser sur PC, qui ne fonctionneraient pas je le rappelle sous Android à cause du stack L2CAP non implémenté.

Bon courage ;)

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Il faut utiliser le NDK http://developer.android.com/sdk/ndk/index.html . C'est plus simple à utiliser sous Linux car sous windows il faut travailler sous Cygwin.

Lire cette introduction sur le NDK http://developer.android.com/sdk/ndk/overview.html et compiler quelques exemples.

Quelques conseils pour utiliser la JNI avec Android http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/jni-tips.html

Ensuite tu peux utiliser ce guide pour manipuler la JNI http://java.sun.com/docs/books/jni/html/jniTOC.html

En gros tout le code dont tu as besoin est déjà fait là : http://code.google.com/p/wiiusej/source/browse/#svn%2Ftrunk%2FWiiUseJC'>http://code.google.com/p/wiiusej/source/browse/#svn%2Ftrunk%2FWiiUseJC

Fouille dans le repository de ce projet http://code.google.com/p/wiiusej/ les appels à la JNI sont déjà faits

Tout ce que tu as à faire c'est arriver à compiler la lib wiiuse avec wiiusej_WiiUseApi.c qui sert d'interface avec le JAVA grâce au NDK Android pour avoir une lib binaire compatible avec ton téléphone. Ce projet génère 2 libs libWiiuseJ.so et libwiiuse.so mais tu peux te contenter d'en faire qu'une seule. Tu devras bidouiller ton NDK pour avoir les fichiers d'include du bluetooth (<bluetooth/bluetooth.h><bluetooth/l2cap.h> je crois) pour compiler et la lib libbluetooth.so de ton téléphone pour faire l'édition des liens.

Ensuite tu dois arriver à faire appel à ta lib .so depuis un projet Android avec les tutoriaux du NDK Android.

Enfin sache que pour communiquer avec la wiimote il te faudra probablement créer une bouche d'évènements dans un thread différent du thread principal de ton application, sinon ton interface ne répondra pas pendant que ta boucle récupèrera les infos de ta wiimote, donc le lien sur les conseils pour utiliser la JNI avec Android depuis un thread te sera utile.

Tu t'embarques dans un gros boulot mais c'est faisable. J'ai pas vraiment le temps de faire plus détaillé mais si t'as des questions j'essaierai d'y répondre.

Modifié par kaloskagatos
  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Ah ben justement. J'ai une erreur sur bluetooth.h (/home/adrien/Bureau/workspace/Bluetooth/jni/wiiuse.h:47:34: error: bluetooth/bluetooth.h: No such file or directory). Que faut-il bidouiller dans le NDK? Merci.

Alors j'ai fait un "apt-file search bluetooth.h" et j'ai trouvé celui là "libbluetooth-dev: /usr/include/bluetooth/bluetooth.h"

Je l'ai donc copier dans mon repertoire jni mais il y'a encore des erreurs ..

Modifié par Droiide
  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Ah ben justement. J'ai une erreur sur bluetooth.h (/home/adrien/Bureau/workspace/Bluetooth/jni/wiiuse.h:47:34: error: bluetooth/bluetooth.h: No such file or directory). Que faut-il bidouiller dans le NDK? Merci.

Si tu développes pour android 2.1 donc API Level 7, le NDK n'a pas changé depuis le level 5, donc tu vas bidouiller sous répertoire de platform 5. Par contre si tu développes pour 2.2 il faudra bidouiller sous platform 8. (je n'ai pas de NDK sous les yeux)

Le NDK ne permet l'accès qu'à une certain nombre de bibliothèques en C et tu n'as en principe pas le droit d'accéder au bluetooth. Tu vas devoir ajouter les fichiers d'include nécessaire au bluetooth et libbluetooth.so.

Dans le NDK tu trouveras un répertoire include dans un sous répertoire de la plateforme pour laquelle tu développes. Tu crées un répertoire bluetooth et tu mets dedans les .h nécessaires, bluetooth.h, l2cap.h, etc, le compilo te dira ce qui manque au fur et à mesure que tu les ajoutes. Ces fichiers, il faut les récupérer sur le net. Il faut chercher au pif un répertoire qui les contient tous, certains ne seront pas bon, à toi de tester. Un exemple http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/include/net/bluetooth/ (qui sont des fichiers linux standard, il y a peut-être moyen d'en trouver plus à jour issus du projet android mais ça peut suffire. En fait les .h sont nécessaires au compilateur pour connaitre l'entête des fonctions que tu utilises et qui sont compilées dans libbluetooth.so. )

Une fois que tu les as tous et que ça compile, l'étape de compilation finale est l'édition des liens (unresolved symbol), le compilateur aura besoin de la présence de llibbluetooth.so de ton téléphone que tu devras coller dans un sous répertoire lib de ton NDK sous le bon numéro de plateform, avec les autres .so de la platform cible. Pour le récupérer il faut utiliser l'outil adb fourni avec le SDK http://developer.android.com/guide/developing/tools/adb.html#copyfiles Si ton téléphone la lib doit se trouver dans /system/lib ou un truc comme ça.

PS: si ndk-build ne veut plus compiler il faut supprimer les fichiers .o temporaires qui sont dans le répertoire objects de ton projet, c'est un bug du NDK.

Modifié par kaloskagatos
  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Alors voilà c'est fait.. Mais une autre erreur maintenant. Erreur du genre :

/home/adrien/Bureau/workspace/Bluetooth/obj/local/armeabi/objs/ndkmain/wiiusej_WiiUseApi.o: In function `Java_android_bluetooth_specialPoll':

/home/adrien/Bureau/workspace/Bluetooth/jni/wiiusej_WiiUseApi.c:411: undefined reference to `wiiuse_poll'

Ah non c'était les .o ^^

Modifié par Droiide
  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Bon.. Retour des problemes. J'ai enlevé les .o mais ça me fait quand même:

Compile thumb : ndkmain <= /home/adrien/Bureau/workspace/Bluetooth/jni/wiiusej_WiiUseApi.c

SharedLibrary : libndkmain.so

/home/adrien/Bureau/workspace/Bluetooth/obj/local/armeabi/objs/ndkmain/wiiusej_WiiUseApi.o: In function `Java_android_bluetooth_specialPoll':

/home/adrien/Bureau/workspace/Bluetooth/jni/wiiusej_WiiUseApi.c:411: undefined reference to `wiiuse_poll'

Bizarre non? :mad:

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Rejoignez la conversation

Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.

Invité
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • Créer...