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.

WiiRemoteJTest 0.1
Enlaces.
http://www.world-of-cha0s.hostrocket.com/WiiRemoteJ/WiiRemoteJ%20v1.6.zip.gz
http://www.world-of-cha0s.hostrocket.com/WiiRemoteJ/WiiRemoteJ%20v1.6.zip.gz