Introducción.
Hace un tiempo (parte 1 y parte 2) hice algunas pruebas acerca de como utilizar el control del Wii (wiimote) desde el PC desarrollando aplicaciones con C# utilizando la librería WiimoteLib de Brian Peek. Desafortunadamente ni esta librería ni ninguna otra de C# que pudiera encontrar son de plataforma cruzada y por lo tanto no se pueden utilizar desde Linux así que me vi obligado a cambiarme nuevamente a mi lenguaje preferido: Java.
Después de revisar las librerías disponibles obtuve tres candidatos: WiiRemoteJ, WiiUseJ, MoteJ y WiiMote-Simple.
A pesar de que la página de WiiRemoteJ parece haber desaparecido es una de las mas mencionadas y parece ser una de las mas estables. Requiere de una pila Bluetooth como Avetana o Bluecove para ejecutarse sobre ella.
Implementación.
Básicamente el uso de la librería se basa en la manipulación de un objeto WiiRemote y en la implementación de la interfaz WiiRemoteListener encargada de manejar los eventos provenientes del Wiimote y de sus extensiones.
Las clases se encuentran almacenadas en los siguientes paquetes.
import wiiremotej.*; import wiiremotej.event.*;
Al implementar la mencionada interfaz es necesario especificar la implementación de los siguientes métodos.
Método | Evento |
buttonInputReceived | Se presionó un botón del wiimote. |
disconnected | Se desconectó el wiimote. |
extensionConnected | Se conectó una extensión al wiimote. |
extensionPartiallyInserted | La extensión recién conectada quedó mal insertada. |
extensionUnknown | La extensión recién conectada es desconocida. |
extensionInputReceived | La extensión envía datos al wiimote. |
extensionDisconnected | La extensión ha sido desconectada del wiimote. |
accelerationInputReceived | El wiimote ha generado información de aceleración. |
IRInputReceived | El wiimote ha generado información de su cámara infrarroja. |
statusReported | Ha sucedido un reporte de estado. |
combinedInputReceived | Suceso de eventos combinados. |
Evento de presión de botones.
public void buttonInputReceived(WRButtonEvent evt) { // boolean isAnyPressed(int buttonMask) Returns true if any of the given buttons are pressed; otherwise false. // boolean isOnlyPressed(int buttonMask) Returns true if all of the given buttons are pressed and no others are; otherwise false. // boolean isPressed(int buttonMask) Returns true if all of the given buttons are pressed; otherwise false. // boolean wasOnlyPressed(int buttonMask) Returns true if all of the given buttons were pressed and no others are; otherwise false. // boolean wasPressed(int buttonMask) Returns true if all of the given buttons were pressed; otherwise false. // boolean wasReleased(int buttonMask) Returns true if one of the given buttons was released; otherwise false. if (evt.wasPressed(WRButtonEvent.TWO)) this.log("2"); if (evt.wasPressed(WRButtonEvent.ONE)) this.log("1"); if (evt.wasPressed(WRButtonEvent.B)) this.log("B"); if (evt.wasPressed(WRButtonEvent.A)) this.log("A"); if (evt.wasPressed(WRButtonEvent.MINUS)) this.log("Minus"); if (evt.wasPressed(WRButtonEvent.HOME)) this.log("Home"); if (evt.wasPressed(WRButtonEvent.LEFT)) this.log("Left"); if (evt.wasPressed(WRButtonEvent.RIGHT)) this.log("Right"); if (evt.wasPressed(WRButtonEvent.DOWN)) this.log("Down"); if (evt.wasPressed(WRButtonEvent.UP)) this.log("Up"); if (evt.wasPressed(WRButtonEvent.PLUS)) this.log("Plus"); }
Evento de desconexión del control.
public void disconnected() { this.log("The remote controller was disconnected."); wiimote = null; }
Eventos de la extensión.
public void extensionConnected(WiiRemoteExtension extension) { this.log("An extension has been connected! (" + extension.getCode() + "): " + this.getExtensionTypeName(extension)); try { wiimote.setExtensionEnabled(true); } catch(Exception e) { this.log(e.getMessage()); } } public void extensionPartiallyInserted() { this.log("An extension was partially inserted, push it harder next time"); } public void extensionUnknown() { this.log("The extension is unknown, what are you putting into me ?"); } public void extensionInputReceived(WRExtensionEvent evt) { // this.log("The extension is sending me some kind of data ... "); } public void extensionDisconnected(WiiRemoteExtension extension) { this.log("An extension has been disconnected! (" + extension.getCode() + "): " + this.getExtensionTypeName(extension)); }
Evento de aceleración.
public void accelerationInputReceived(WRAccelerationEvent evt) { // double getPitch() Returns the pitch of the remote, in radians from -PI to PI. // double getRoll() Returns the roll of the remote, in radians from 0 to 2PI. // double getXAcceleration() Returns the X-Acceleration of the remote, in terms of G's. // double getYAcceleration() Returns the Y-Acceleration of the remote, in terms of G's. // double getZAcceleration() Returns the Z-Acceleration of the remote, in terms of G's. // boolean isStill() Returns true if the remote is not being moved; otherwise false. }
Evento de la cámara infrarroja.
public void IRInputReceived(WRIREvent evt) { // IRLight[] getIRLights() Returns the array of IR lights seen by the IR sensor. // int getMode() Returns the mode of the IR sensor. }
Evento de reporte de estado.
public void statusReported(WRStatusEvent evt) { // double getBatteryLevel() Returns the battery level of the remote. // boolean[] getLEDStatus() Returns the status of the LED lights. // boolean getLEDStatus(int light) Returns the status of the specified light. // boolean isContinuousEnabled() Returns the status of continuous reporting. // boolean isExtensionConnected() Returns the status of the extension port. // boolean isSpeakerEnabled() Returns the status of the speaker. }
Reporte de recepción combinada de eventos.
public void combinedInputReceived(WRCombinedEvent evt) { // WRAccelerationEvent getAccelerationEvent() Returns the acceleration event of this combined event. // WRButtonEvent getButtonEvent() Returns the button event of this combined event. // WRExtensionEvent getExtensionEvent() Returns the extension event of this combined event. // WRIREvent getIREvent() Returns the IR event of this combined event. }
Ejecución.
Para el desarrollo de esta aplicación de demostración se utilizó la librería de BlueCove, en este caso en la versión 2.10. Es obligatorio obtener el paquete bluecove-*.jar mientras que bluecove-gpl-*.jar sólo es requerido bajo Linux.
$ wget http://bluecove.googlecode.com/files/bluecove-2.1.0.jar
$ wget http://bluecove.googlecode.com/files/bluecove-gpl-2.1.0.jar
Además se requiere de la librería WiiRemoteJ.jar, en este caso en la versión 1.6.
$ wget http://www.world-of-cha0s.hostrocket.com/WiiRemoteJ/WiiRemoteJ%20v1.6.zip.gz
$ cp WiiRemoteJ v1.6/WiiRemoteJ.jar .
Se compila el programa de demostración.
$ javac -classpath bluecove-2.1.0.jar:bluecove-gpl-2.1.0.jar:WiiRemoteJ.jar:. WiiRemoteJTest.java
Se ejecuta.
$ java -classpath bluecove-2.1.0.jar:bluecove-gpl-2.1.0.jar:WiiRemoteJ.jar:. WiiRemoteJTest
Al iniciar la aplicación se debe presionar el botón que dice “Buscar Wiimote” y presionar los botones 1 y 2 del control para ponerlo en modo de descubrimiento. Después de encontrado los eventos (botón, extensión y desconexión) generados en él deberán ser documentados en la ventana de la aplicación.

Enlaces.
- WiiRemoteJ.
http://www.world-of-cha0s.hostrocket.com/WiiRemoteJ/ - BlueCove.
http://bluecove.org/ - Aplicación de demostración.
http://demo.jorgeivanmeza.com/Java/WiiRemoteJTest/
Compadre . . . gracias por la explicación, esta muy bien documentada
Saludos