Traducciones desde GTalk bots

Este año Google habilitó el servicio de traducción asistida a través de bots del servicio de GTalk.  Para utilizarlos se debe agregar como contacto la dirección del bot y posteriormente aceptarlo como contacto.

Las direcciones de los bots tienen el siguiente formato.

[lenguaje orígen] 2 [lenguaje destino]@bot.talk.google.com

Esto quiere decir que el bot que traduce de español a inglés es es2en@bot.talk.google.com y el que realiza el proceso contrario es en2es@bot.talk.google.com.

Las combinaciones de idiomas disponibles son las siguientes.

  1. Arabic – English:      ar2en      en2ar
  2. Bulgarian – English:     bg2en     en2bg
  3. Czech – English:     cs2en     en2cs
  4. Danish – English:     da2en     en2da
  5. German – English:     de2en     en2de
  6. German – French:     de2fr     fr2de
  7. Greek – English:     el2en     en2el
  8. Spanish – English:     es2en     en2es
  9. Finnish – English:     fi2en     en2fi
  10. French – English:     fr2en     en2fr
  11. Hindi – English:     hi2en     en2hi
  12. Croatian – English:     hr2en     en2hr
  13. Italian – English:     it2en     en2it
  14. Japanese – English:     ja2en     en2ja
  15. Korean – English:     ko2en     en2ko
  16. Dutch – English:     nl2en     en2nl
  17. Norwegian – English:     no2en     en2no
  18. Polish – English:     pl2en     en2pl
  19. Portuguese – English:     pt2en     en2pt
  20. Romanian – English:     ro2en     en2ro
  21. Russian – English:     ru2en     en2ru
  22. Swedish – English:     sv2en     en2sv
  23. Chinese – English:     zh2en     en2zh
  24. Traditional Chinese – English:     zh-hant2en     en2zh-hant
  25. Traditional Chinese – Chinese:     zh-hant2zh     zh2zh-hant

Este servicio se encuentra basado en el servicio de traducción de Google.

Enlaces:

Documentación de CodeIgniter en español

CodeIgniter es un framework MVC para el desarrollo de aplicaciones web.  Es una alternativa interesante ya que es útil, facilita el desarrollo pero a su vez es lo suficientemente desacoplado para no obligarle a utilizar nada que no se desee usar.  Entre sus ventajas se cuentan su velocidad, su buena documentación, tutoriales y el soporte de una comunidad de tamaño decente.

Si por alguna extraña razón, no es de su agrado la lectura de la documentación en inglés también puede elegir otros idiomas.  Encontré que hay dos proyectos que se encuentran traduciendo la documentación al español actualmente.

Para mas información consultar el sitio Wiki de CodeIgniter acerca del estado de los proyectos de traducción.

Utilizando el Wiimote con C#: parte II

HelloWii 0.1 screenshot
HelloWii 0.1 screenshot

Introducción.

Antes de publicar el código fuente del HelloWii, decidí hacer un poco de refactory obteniendo los siguientes productos y conclusiones.

  • La clase WiiController que es un recubrimiento (wrapper) de la librería WiimoteLib y que simplifica su acceso.  Está desarrollada en C#.
  • Se utilizó el patrón observador (interfaz WiiControllerObserver) para permitirle a los interesados registrarse con el control para ser notificados de sus cambios de estado.  De igual manera es posible obtener información de este por demanda.
  • Si el observador es el mismo componente de UI (Form por ejemplo) es recomendable remover el registro del observador (unregisterObserver) antes de cerrar/destruír la componente/aplicación y evitar así excepciones generadas durante intentos de actualización mientras se cierra el componente.
  • Se adaptó la aplicación de demostración para utilizar a un objeto WiiController como interfaz en lugar de utilizar a la librería directamente.
  • Con el rediseño se esperaba evitar el problema del cross-threading pero no fue posible.

Como se mencionó no fue posible obviar la situación generada por la ejecución de instrucciones entre distintos hilos: la interfaz de usuario y la librería de acceso al wiimote que genera los problemas y explicación ya fueron expuestos.  Sin embargo, revisando el foro de WiimoteProject encontré que es posible indicarle al componente visual de .NET que se encuentre accediendo a la librería (inclusive indirectamente a través de WiiController) que ignore este tipo de accesos ilegales entre hilo al evitando su revisión, esto se logra agregando la siguiente instrucción al constructor del componente.

CheckForIllegalCrossThreadCalls = false;

API de la clase WiiController.

La clase WiiController cuenta con los siguientes métodos.

  • public void connect() – Creates the conexion with the wiimote.
  • public void disconnect() – Makes the disconnection of the wiimote..
  • public bool isConnected() – Checks if the wiimote has been already connected..
  • public void refreshStatus(WiimoteState source) – Updates the references to the internal information of the wiimote.
  • public void setReportType(WiimoteLib.InputReport type) – Selects the the type of information report that is expected from the controller.
  • public float getBattery() – Gets the battery level of the wiimote.
  • public String getId() – Gets the ID of the controller.
  • public bool[] getAllButtonsStatus() – State of all buttons of the wiimote.
  • public bool getButtonStatus(String name) – The status of a button on the wiimote.
  • public bool[] getAllLedsStatus() – The status of all leds of the wiimote.
  • public bool getLedStatus(int id) – The status of an individual led.
  • public void setLeds(bool l1, bool l2, bool l3, bool l4) – Change the state of the wiimote’s leds.
  • public void setLeds(bool[] leds) – Change the state of the wiimote’s leds.
  • public void turnLed(int index, bool status) – Change the state of an individual led.
  • public int[] getAcceleration() – Obtains the acceleration of the wiimote.
  • public int getAcceleration(String axis) – Obtains the acceleration of the wiimote.
  • public bool isRumbling() – Checks if the rumbling device is active.
  • public void rumble(bool status) – Change the state of the wiimote’s rumbling device.
  • public bool isObserver(WiiControllerObserver observer) – Checks if an observer is already registered.
  • public bool registerObserver(WiiControllerObserver observer) – Register a new observer on the controller.
  • public bool unregisterObserver(WiiControllerObserver observer) – Unregister an observer from the controller.
  • public bool isExtensionConnected() – Checks if a wiimote’s extension is connected.
  • public String getExtensionTypeConnected() – Get the type name of the connected extension.
  • public int[] getNunchukAcceleration() – Get the acceleration of the nunchuk extension.
  • public int getNunchukAcceleration(String axis) – Get the acceleration of the nunchuk extension.
  • public bool[] getAllNunchukButtonsStatus() – Get the state of the buttons on the nunchuk extension.
  • public bool getNunchukButtonStatus(String name) – Get the state of a button on the nunchuk extension.
  • public int[] getNunchukJoystick() – Get the joystick state on the nunchuk extension.
  • public int getNunchukJoystick(String axis) – Get the joystick value on a selected axis from the nunchuk extension.

Para mas información acerca del API de la clase y de su respectiva utilización consulte la documentación del código fuente inmersa en el archivo WiiController.cs y en WiiForm.cs (aplicación de demostración).

Registrar observadores.

Para registrarse como observador de eventos del wiimote la clase debe implementar la interfaz jimezam.wii.controller.WiiControllerObserver.  Esta interfaz obliga a que se implementen los siguientes métodos.

  • void update() – Invoked when the status of the wiimote is changed.
  • void updateExtension() -Invoked when an extension is connected/disconnected to the wiimote.

La manipulación del registro de un observador se realiza utilizando los métodos registerObserver y unregisterObserver de la clase WiiController descritos anteriormente.

Enlaces.

Selección de Debug/Release en Visual C# Express 2008

Esta semana, gracias a las pruebas con el Wiimote he vuelto a trabajar con C#, esta vez con utilizando el Visual C# Express 2008.  Encontré un problema, cuando quise generar la versión final de la aplicación no pude encontrar la opción que me permitiera elegir entre las presentaciones Debug/Release del ejecutable generado.

Buscando en Internet encontré que hay dos formas de hacerlo.

  1. Presionando F5 se construye el ejecutable en modo Debug, presionando CTRL+F5 se construye el ejecutable en modo Release.
  2. Si realmente se desea tener visible el menú que le permita seleccionar el modo del ejecutable y la CPU objetivo realice los siguientes pasos.
  • Elija el menú Tools > Options.
  • Seleccione la casilla de verificación Show all settings en la parte inferior izquierda.
  • Seleccione la rama Projects and solutions > General.
  • Selecciona la casilla de verificación Show advanced build configurations.
  • Presione el botón OK para aceptar los cambios.

debug-release-bar

Utilizando el Wiimote con C#

Ejes del Wiimote - tomado de http://wiimotecommande.sf.net/
Ejes del Wiimote - tomado de http://wiimotecommande.sf.net/

Introducción.

Hace unos dias me prestaron un control de Wii (que si funcionaba) y tuve un par de noches para jugar con el.  Hice una aplicación muy sencilla para experimentar como acceder a la información provista por el control y como utilizar algunos de sus recursos.

La aplicación de demostración se realizó utilizando la librería WiimoteLib de Brian Peek y Visual C# Express bajo Windows Vista (utilizando la pila de Bluetooth del sistema operativo).

Implementación.

Instalación de la librería.

  • Descargar WiimoteLib (se utilizó la versión 1.6) desde su repositorio en CodePlex.
  • Se debe descomprimir el paquete y ubicar el archivo WiimoteLib.dll en un sitio conocido.
  • Al proyecto o solución en Visual Studio se le debe agregar la referencia a este archivo.
    • En el explorador de soluciones hacer clic derecho sobre el proyecto.
    • Seleccionar la opción Agregar referencia ….
    • Seleccionar la etiqueta Examinar.
    • Buscar el archivo Wiimote.dll y presionar el botón Aceptar.

Inclusión del espacio de nombres.

Para utilizar cualquiera de las clases de la librería dinámica es necesario incluír en el código fuente al espacio de nombres apropiado.

using WiimoteLib;

Referencia al Wiimote.

El acceso a la información del control se realizará a través de esta referencia, motivo por el cual la utilizo como atributo de la instancia.

private Wiimote wm;

Instanciación de referencia con el Wiimote.

Para que la creación de la instancia y posterior conexión sean exitosas es necesario que el control se encuentre ya asociado al equipo a través del emparentamiento Bluetooth.  El procedimiento para realizar esta conexión puede consultarse en este sitio (video) utilizando las herramientas nativas de Windows Vista o en este otro sitio utilizando la pila de Bluesoleil.

            try
            {
                wm = new Wiimote();
            }
            catch (System.IO.IOException ioe)
            {
                Console.WriteLine("No es posible ejecutar la aplicación: " + ioe.Message);
            }

Registro de eventos.

Se establecen métodos para manejar dos tipos de eventos del control:

  • Eventos generados por el control mismo: wm_WiimoteChanged.
  • Eventos generados por la conexión/desconexión de extensiones: wm_WiimoteExtensionChanged.
            wm.WiimoteChanged += wm_WiimoteChanged;
            wm.WiimoteExtensionChanged += wm_WiimoteExtensionChanged;

Establecimiento de la conexión.

            try
            {
                wm.Connect();
            }
            catch (Exception wnfe)
            {
                Console.WriteLine("No es posible ejecutar la aplicación: " + wnfe.Message);
            }

Establecimiento del nivel de reporte.

Determina que tipo de información (informes) estamos interesados en tomar del Wiimote.

            wm.SetReportType(InputReport.IRExtensionAccel, true);

Los diferentes tipos de reportes son las siguientes constantes definidas en InputReport.

  • Status.  Estado general.
  • ReadData. Datos de la memoria interna.
  • Buttons. Botones pulsados
  • ButtonsAccel. Botones y acelerómetro.
  • IRAccel. Botones, acelerómetro e infrarrojo.
  • ButtonsExtension. Botones y extensiones conectadas (como el Nunchuk, el control convencional, la guitarra, etc.)
  • ExtensionAccel. Botones, acelerómetro y extensiones.
  • IRExtensionAccel. Botones, acelerómetro, infrarrojos y extensiones.

Manejo de eventos en conexión de extensiones.

El método wm_WiimoteExtensionChanged es invocado cuando suceden cambios de conexión entre el Wiimote y sus extensiones.  La verificación de conexión se realiza con la propiedad args.Inserted.

        void wm_WiimoteExtensionChanged(object sender, WiimoteExtensionChangedEventArgs args)
        {
            if (args.Inserted)
                wm.SetReportType(InputReport.IRExtensionAccel, true);    // return extension data
            else
                wm.SetReportType(InputReport.IRAccel, true);             // back to original mode
        }

Manejo de eventos ante cambios en el Wiimote.

El método wm_WiimoteChanged es invocado cuando sucede un cambio en las variables del control (el acelerómetro detectó movimiento, se presionó un botón, etc.).

        void wm_WiimoteChanged(object sender, WiimoteChangedEventArgs args)
        {
              // ...
        }

Este es el punto ideal para realizar las consultas actualizadas acerca del estado del control.

Consulta del estado del control.

La información del estdo del control se almacena entre diferentes propieades del Wiimote.

  • Estado general del Wiimote.
  • Estado de los botones.
  • Estado de los leds.
  • Estado del acelerómetro.
WiimoteState ws = args.WiimoteState;
WiimoteLib.ButtonState bs = ws.ButtonState;
LEDState ls = ws.LEDState;
AccelState at = ws.AccelState;

Consulta de la batería.

int battery = (int) ws.Battery;

Consulta del estado de los botones del Wiimote.

            bool[] bStatus =
            {
                bs.Up, bs.Down, bs.Left, bs.Right,
                bs.A, bs.B,
                bs.Minus, bs.Home, bs.Plus,
                bs.One, bs.Two
            };

Cada una de las constantes corresponde con los botones etiquetados de igual manera en el control:

  • Control de dirección: Up, Down, Left, Right.
  • Botones superiores: A y B.
  • Botones medios: Minus (-), Home (casita) y Plus (+).
  • Botones inferiores: One (1) y Two (2).

Las propiedades son booleanas y serán true si el botón se encuentra presionado, false de lo contrario.

Manipulación del estado de los leds.

Su información se puede acceder de manera similar a lo realizado anteriormente con los botones.

            bLed = new bool[4]
            {
                ls.LED1, ls.LED2, ls.LED3, ls.LED4
            };

El dispositivo cuenta con cuatro leds.  Su estado puede modificarse de la siguiente manera.

            wm.SetLEDs(bLed[0], bLed[1], bLed[2], bLed[3]);

Donde cada parámetro corresponde a cada uno de los leds y el valor enviado deberá ser true para encenderlo o false para apagarlo.

Información del acelerómetro.

Como su nombre lo indica, provee información acerca de la aceleración del movimiento del control en sus tres ejes (consultar gráfica inicial).  Sus valores son enteros y pertenecen al rango entre 0 y 255.

            int rx = (int)at.RawValues.X;
            int ry = (int)at.RawValues.Y;
            int rz = (int)at.RawValues.Z;

Manipulación del vibrador.

Con la siguiente instrucción es posible verificar si el dispositivo vibrador del control se encuentra activo o no, retorna true o false según corresponda.

            wm.WiimoteState.Rumble;

De igual manera es posible encender o apagar al dispositivo vibrador según se requiera, esto se realiza de la siguiente manera.

            wm.SetRumble(state);

Donde state es true o false según se desee encender o apagar.

Información de las extensiones – Nunchuk.

Verificar si se encuentra o no alguna extensión conectada al Wiimote.

            bool ext = ws.Extension;

Verificar si la extensión conectada es el Nunchuk.

            if (ws.ExtensionType.ToString() == "Nunchuk")
            {
                 ...
            }

Estado del joystick del Nunchuk.

            WiimoteLib.Point joystick = ws.NunchukState.RawJoystick;
            int joyX = joystick.X;
            int joyY = joystick.Y;

Estado de los botones del Nunchuk.

            bool bCn = ws.NunchukState.C;
            bool bZn = ws.NunchukState.Z;

Información del acelerómetro del Nunchuk.

            Point3 nAccel = ws.NunchukState.AccelState.RawValues;
            int rnx = nAccel.X;
            int rny = nAccel.Y
            int rnz = nAccel.Z;

De manera similar a la información acelerómetro del Wiimote, sus valores van entre 0 y 255.

Problemas con el acceso entre hilos de C#.

En la implementación de la aplicación de demostración me encontré con un problema del lenguaje C#/.NET.  Al parecer cuando se ejecuta el código de la librería (código nativo me imagino) se ejecuta (por seguridad, me imagino nuevamente) en un hilo diferente, así que cuando intentaba realizar una actualización de la interfaz de usuario a partir de un valor obtenido del Wiimote se lanzaba una excepción.

Con este problema la siguiente instrucción, que actualiza el valor de un Label con la aceleración en X del Nunchuk es problemática.

           this.lnaXValue.Text = ws.NunchukState.AccelState.RawValues.X.ToString();

Por suerte encontré en Threading in Windows Forms una buena descripción del problema y la estrategia para encontrar una solución, no muy elegante para mi gusto, para solventar el problema por lo menos de manera temporal y continuar con el experimento del Wiimote.

Para ejecutar la instrucción problemática tuve que implementar un método actualizador de Labels y llamarlo a través de un delegado.

        delegate void updateLabelInformationDelegate(Label l, String value);

        public void updateLabelInformation(Label l, String value)
        {
            l.Text = value;
        }

La invocación se realiza entonces de la siguiente manera.

        if (InvokeRequired)
        {
             BeginInvoke(new updateLabelInformationDelegate(updateLabelInformation),
                         new object[] {
                                       this.lnaXValue,
                                       ws.NunchukState.AccelState.RawValues.X.ToString()
                         });
        }

Aplicación de demostración.

HelloWii 0.1
HelloWii 0.1

HelloWii 0.1 es la aplicación de prueba que implementé utilizando la librería y operaciones descritas anteriormente.  La funcionalidad de esta aplicación es la siguiente.

Wiimote.

  • Estado del d-pad.
  • Estado de los botones.
  • Estado de los leds.
  • Encender/apagar los leds haciendo clic sobre ellos.
  • Estado de la batería.
  • Número del HID.
  • Valores de aceleración en sus tres ejes.
  • Estado del vibrador.
  • Encender/apagar el vibrador seleccionado o removiendo la casilla de verificación.
  • Estado de la extensión: presente o ausente.

Nunchuk (si está presente).

  • Dirección del joystick.
  • Estado de los botones.
  • Valores de aceleración en sus tres ejes.

Esta aplicación y su código fuente pueden descargarse de manera libre.

Conclusiones.

La implementación de aplicaciones que interactúan con el Wiimote utilizando C#/WiimoteLib es muy sencillo, obviando el problema de comunicación entre hilos, no se presentó ningún inconveniente.  El API de la librería se encuentra bien documentado en un CHM que viene incluído en su distribución.

Habiendo probado ya su funcionamiento y documentado su implementación es necesario continuar con algunas pruebas un poco mas elaboradas y estructuras que en lo posible, eviten la necesidad de los delegados y permitan integrar su código con aplicaciones mas complejas y otras librerías de terceros.  También es necesario realizar pruebas con el lector infrarrojo del control y con el parlante, que según creo aún no tiene soporte por esta librería.

De igual manera planeo realizar pruebas similares utilizando Java.

Enlaces.

Para consultar el código fuente de la aplicación de demostración acceda al enlace de la segunda parte de este artículo.