Administra tu Blog

¡Crea tu Blog Ya! Fácil y Gratis

Categoría: Desarrollo

Programación del puerto paralelo

teknoplof 17/09/2009 @ 09:03

foto0.jpgSi existe una tecnología que inexorablemente camina hacia su extinción, esa es la del archiconocido y bien querido por todos nosotros puerto paralelo. Este conector que ya no viene en los portátiles (ni en muchos ordenatas de sobremesa) apareció de la mano de IBM en 1981 con su primer PC y ha llegado incorrupto hasta nuestros días.

Su estructura de 25 pines hace de él un conector nada discreto, mas muy fácil de manejar. No es el más rápido, pero mediante su manejo podemos interconectarnos con el mundo real de la manera más sencilla, sabiendo un poquito de aquí y un poquito de allá. Cierto es que su uso ha sido casi exclusivamente dedicado al control de impresoras, pero vía puerto paralelo podemos manejar desde un juego de luces a una lavadora, un robot o una excavadora. ¿Cómo se te queda el cuerpo? Y fácil, muy fácil.

foto1.jpg

Básicamente, lo que podemos hacer con cada uno de los 25 pines de un puerto paralelo es ponerlos a 0 ó a 5 voltios. Esta situación binaria combinada es capaz de activar un relé, por ejemplo, que a su vez active un electrodoméstico, una bombilla o cualquier otro elemento electrónico.

Comencemos viendo en la siguiente imagen la estructura de pines del puerto en cuestión. Realmente, el puerto paralelo consta de tres puertos diferentes integrados en el propio conector (los que aparecen de color azul, rojo y naranja en la imagen).

foto2.gif

El puerto de datos (DATA), permite transmitir un byte (8 bits) de datos. Cada uno de los bits se corresponde con uno de los pines D0 a D7. Por tanto, en conjunto, se pueden transmitir valores entre 0 y 255 en formato binario. Por ejemplo, para transmitir el 139, 10001011 en binario, se pondrán a 5 voltios los pines D7, D3, D1 y D0. Este puerto puede configurarse para servir tanto de entrada como de salida de datos.

El puerto de control (CONTROL) es sólo de salida y se corresponde con los pines C0 a C3, con lo que en principio nos permite trasmitir valores entre 0 y 16. En un principio este puerto se utilizaba para transferir comandos inmediatos a la impresora como un salto de línea o un reset, y los pines conservan los nombres que se les dieron en esa época (C0=Strobe, C1=Auto feed, C2=Initialize y C3=Select). Y por razones históricas tambien, C0, C1 y C3 están invertidos, lo que quiere decir que invierten la salida y, al contrario que los pines normales, representan el 0 con 5 voltios y el 1 con 0 voltios. Por ejemplo, el número 6, que es 0110 en binario, al estar los bits invertidos, deberíamos poner C3, C2 y C0 a 5 voltios y C1 a 0.

Por último tenemos el puerto de estado (STATUS). Se usaba originalmente para recibir el estado de la impresora, también ha heredado los nombres de los pines de aquella época (S3=Error, S4=Select in, S5=Paper end, S6=Acknowledge y S7=Busy) y también presenta algún pin invertido (el S3 y el S6). Es un puerto sólo de entrada.

El resto de pines (los que están en verde en el gráfico anterior) están conectados a tierra y nos ofrecen el voltaje de referencia de 0 voltios.

Para empezar a cacharrear con el puerto paralelo, lo ideal es montar un adaptador hembra en una placa de pruebas (protoboard en inglés), que no es otra cosa que una plancha de plástico reutilizable, con agujerillos y contactos metálicos, usada para construir prototipos electrónicos (o realizar pruebas experimentales) normalmente sin soldadura.

Además, necesitaremos un cable paralelo para conectar el prototipo al ordenador y, también, que este ordenador disponga a su vez de puerto paralelo, si no vamos aviados.

foto3.jpg

Lo que vamos a hacer es soldar un cable a cada pin y, en la placa de pruebas, ordenar los extremos en línea, usando un color en cada tipo de puerto para distinguirlos fácilmente (imágenes siguientes).

Los cables rojos pertenecen al puerto de control, los amarillos al de datos y los verdes al de estado. Utilizaremos también dos cables negros para los conectores a tierra.

foto4.jpg

foto5.jpg

foto6.jpg

Como ejemplo de utilización vamos a conectar 8 leds a cada uno de los pines de datos, de esta manera obtendremos feedback visual en tiempo real de lo que ocurre en cada momento, es decir, si ponemos un pin a 0 el led deberá de permanecer apagado si lo ponemos a 1 se encenderá. Utilizaremos el siguiente esquema para la realización del montaje.

foto7.gif

Por supuesto necesitaremos 8 leds y 8 pequeñas resistencias de 470 ohmnios, que son las representadas en la imagen por esos pequeños rectángulos intercalados entre pin y led. Las resistencias sirven para limitar la corriente que pasará por cada cable, aunque en este caso concreto son prescindibles, porque cada pin del puerto paralelo sólo puede suministrar 40mA como máximo, una corriente suficientemente baja para que aguanten la mayoría de los leds y no se quemen. Pero por si las moscas...

foto8.jpg

Una vez tengamos el engendro preparado, ya sólo nos queda conectarlo al ordenador a través del puerto paralelo y ponernos a programar. El siguiente ejemplo está escrito en C para Linux, pero es fácilmente portable a cualquier otro lenguaje de programación para cualquier plataforma. El propio código está comentado, pero después se apuntan un par de cosillas interesantes como refuerzo.

[código]

#include
#include
// En asm/io.h están definidas las funciones ioperm() y outb()
#include
 
// Esta es la dirección más frecuente para un puerto paralelo
#define DATAPORT 0x378
 
int main()
{
  // Obtenemos permiso de acceso para la dirección de DATAPORT y
  // las 2 siguientes
  if (ioperm(DATAPORT, 3, 1)) {perror("ioperm"); return 1;}
 
  // Entramos en un bucle infinito
  while(1)
  {
    int input;
 
    // Le pedimos al usuario que introduzca un número
    printf("Introduce un número entre 0 y 255 (-1 para salir)\n");
    // Leemos el valor introducido y lo guardamos en "input"
    scanf("%d", &input);

    // Si "input" vale "-1" salimos del bucle
    if(input==-1) break;

    // Si "input" no está entre "0" y "255" (y no era "-1") no nos
    // interesa, así que volvemos directamente al comienzo del bucle
    if(input < 0 || input > 255) continue;
 
    // Si hemos llegado hasta aquí es que "input" vale entre "0" y
    // "255" y podemos sacarlo por el puerto paralelo
    outb(input, DATAPORT);
  }
 
  // Antes de terminar el programa, dejamos los permisos de acceso
  // a los puertos como estaban
  if (ioperm(DATAPORT, 3, 0)) {perror("ioperm"); return 1;}
 
  //El programa termina sin errores
  return 0;
}

[/código]

La función ioperm() modifica los permisos de acceso a los puertos. Recibe tres enteros: el primero le indica la dirección del primer puerto cuyos permisos queremos modificar, el segundo es el número de puertos y el tercero debe ser 1 para conceder el permiso y 0 para denegarlo. De esta manera, la sentencia ioperm(DATAPORT, 3, 1) asigna permiso a 3 puertos, esto es, al de datos, al de estado y al de control. Al final del programa restablecemos el estado dejando todo como estaba con ioperm(DATAPORT, 3, 0).

La función outb() se encarga de enviar un byte de datos a un determinado puerto. Recibe dos enteros: el primero es el byte que se quiere enviar (debe estar entre 0 y 255) y el segundo es la dirección del puerto. La dirección del puerto de datos paralelo, en la gran mayoría de los ordenadores es, en hexadecimal, 0×378. Esta declaración se encuentra al principio del listado en la variable DATAPORT con #define DATAPORT 0x378. Para una segundo puerto paralelo sería 0x278 y para un tercero 0x3BC. De todas maneras, se puede consultar la dirección de nuestro puerto paralelo en la BIOS de la placa base.

Ejecutando el programa podremos obtener resultados como los de las dos imágenes siguientes. Por un lado (a la izquierda) tenemos la salida del puerto de datos con el número 13 (00001101 en binario) y, por otro (a la derecha), tenemos la salida del número 167 (10100111 en binario). Como es el puerto de datos y los bits no están invertidos, cada 1 se corresponderá con un led encendido y cada 0 un led apagado.

foto9.jpg

Muy bien. Todo claro. Ya sabemos cómo inducir voltaje mediante software en una serie de pins para que enciendan y apaguen unos leds. Pero, ¿cómo demonios se hace para leer información del conector? ¿Cómo puedo saber, por ejemplo, que un interruptor ha sido pulsado?

Bien, en este punto debemos comentar que para ello nos hace falta algún elemento más para nuestra placa de pruebas. Evidentemente un interruptor y, también, una resistencia pull-down. Y ¿para qué la resistencia? Pues muy sencillo. Nosotros no podemos saber con rigor absoluto cuando un pin está a 0 voltios, porque los componentes electrónicos son muy puñeteros y ¿quién me asegura a mí que después de retirar una corriente de 5 voltios de un pin, el circuito detrás de ese pin no esté induciendo un cierto voltaje? ¿O si quizás la propia configuración del circuito podría hacer que éste estuviera actuando como un diminuto condensador guardando alguna pequeña carga, quizá entre 0 y 5 voltios? Nosotros no podemos asegurar nunca que un pin de entrada no conectado a nada está a 0 voltios. Eso sería una falacia. Estará a un voltaje arbitrario (puede que cero, puede que no) y desconocido para nosotros.

Para evitar este pequeño escollo utilizamos una resistencia pull-down, que no es otra cosa que una resistencia puesta entre una línea y masa cuyo objetivo es dar a esa línea un valor lógico de nivel bajo de masa (0 voltios) cuando no hay ninguna señal conectada. Se emplea una resistencia de valor intermedio. Lo más habitual es que sea de 1 ó 10 KΩ. Cuando el interruptor está cerrado, la resistencia que ofrece la rama del circuito que va a los 5V es mucho menor que la que va hasta los 0V, así que el voltaje en el nodo donde confluyen las tres ramas del circuito es prácticamente 5V. Lo bueno es que aquí, cuando el interruptor se abre, el pin de entrada no queda aislado, sino que sigue conectado a tierra a través de la resistencia. Cualquier carga que hubiera quedado atrapada en el circuito se descarga rápidamente a través de la resistencia y la entrada se pone a 0V. ¡Ingenioso!

En la siguiente imagen vemos como queda el circuito.

foto10.jpg

Existen también las resistencias pull-up, que funcionan de igual manera pero conectadas a los 5 voltios. En el código de ejemplo siguiente utilizaremos una de ellas.

¿Y el software? Pues igual de sencillo que el código para escribir datos en el puerto; para leer disponemos de la función inb(), que devuelve un byte de datos leído a través del puerto. Por ejemplo, para leer desde el puerto de estado (Status) y guardarlo en la variable entrada pondríamos hacer short int entrada = inb(0x379).

El siguiente ejemplo lee el valor de dos interruptores conectados a los pines 3 y 4 del puerto de estado. Los interruptores usan resistencias pull-up, por lo que la lectura de un 0 lógico en uno de esos pines representa una pulsación en su interruptor asociado. Un mensaje en pantalla dice qué interruptor se está pulsando.

[código]

// Este programa monitoriza el estado de 2 pulsadores conectados
// a las líneas de STATUS y muestra por pantalla si se ha pulsado
// alguno de ellos
 
#include
#include
 
// En asm/io.h están definidas las funciones ioperm() y outb()
#include
 
// Esta es la dirección más frecuente para el puerto paralelo
#define DATAPORT 0x378
// Y esta es la dirección de las líneas de estado
#define STATUSPORT DATAPORT+1
 
#define TIEMPOCONPULSACION 300000
#define TIEMPOSINPULSACION 10000
 
// Máscaras para los pines 3 y 4 del puerto de estado
#define BOTON1 8
#define BOTON2 16
 
int main()
{
  // Obtenemos permiso de acceso para la dirección de DATAPORT y
  // las 2 siguientes
  if (ioperm(DATAPORT, 3, 1)) {perror("ioperm"); return 1;}
 
  //Entramos en el bucle principal del programa
  while(1)
  {
    // "input" va a guardar el valor leído desde el puerto
    short int input=0;
    // "pulsacion" nos va a decir qué botón se ha pulsado
    short int pulsacion = 0;
 
  // Leemos el byte de las líneas de estado y lo guardamos en "input"
  input=inb(STATUSPORT);
 
  // Si "input" tiene el bit BOTON1 a cero es que se ha pulsado el
  // boton correspondiente
  if((input & BOTON1) ==0)
    // Ponemos "pulsacion" a "1" para indicarlo y sacamos un
    // mensaje por pantalla
    pulsacion=1;
    // Si tiene a cero el bit BOTON2 es que se ha pulsado el otro
    // botón
  else if((input & BOTON2) ==0)
    pulsacion=2;
 
 // Si pulsacion !=0 es que se ha pulsado algun botón
 // Esperamos TIEMPOCONPULSACION microsegundos para no inundar la 
 // pantalla de texto
 if(pulsacion)
 {
  printf("Pulsando botón %d\n",pulsacion);
   fflush(stdout);
  usleep(TIEMPOCONPULSACION);
 }
 // En caso contrario sólo esperamos TIEMPOSINPULSACION microsegundos
 else usleep(TIEMPOSINPULSACION);
  }
  // Antes de terminar el programa dejamos los permisos de acceso
  // a los puertos como estaban
  if (ioperm(DATAPORT, 3, 0)) {perror("ioperm"); return 1;}
 
  // El programa termina sin errores
  return 0;
}

[/código]

Pues bien, después de esto ya deberíamos estar preparados para comenzar a adentrarnos en este intrigante mundo. Hombre, de aquí a manejar una lavadora queda, la verdad. Pero hay que tener en cuenta que todo es cuestión de leer y escribir datos desde y en el puerto paralelo, lo demás ya es cuestión eléctrica y electrónica. Además, se puede encontrar mucha y muy jugosa información en Internet acerca de este tema. Ya se sabe, preguntando al tío Google se llega Roma (.com).

FUENTE: Las imágenes, parte del texto y la inspiración provienen del magnífico blog Obsoletos.

Programación de videojuegos para móviles

teknoplof 04/08/2009 @ 12:30

juegos_mov.jpgEl mundo de los videojuegos lleva muchos años dando ingentes cantidades de dinero a desarrolladores y empresas de software. Quizá no tanto en España, es verdad, pero la razón no es otra que la falta de calidad, originalidad y, sobre todo, presupuesto para su producción. Muchas veces la calidad y la originalidad van muy de la manita con el presupuesto, ya que, si no hay pelas, no hay tiempo que invertir, ergo no hay neuronas que quemar para que el movimiento de esa patada circular voladora no parezca una transición cutre entre dos sprites en distintas posiciones.

No señores, en España no hay una industria videojueguil al estilo yanqui o nipón. Y es una pena, porque el talento que se pierde sólo por no querer (o no saber) aprovechar el tirón del mercado, vale mucho más que los millones de euros que se invierten en superproducciones de motor gráfico encorsetado en las que lo mismo da matar aliens que vacas radiactivas voladoras.

Un dato: España está a la cola (pero a la cola, cola) en desarrollo de videojuegos. Otro dato: España es el cuarto mercado europeo en cuanto a número de ventas de videojuegos (detrás de Reino Unido, Alemania y Francia). ¿Qué está pasando? ¿Nadie le da al coco para ver el negocio?

Es cierto que existen honrosas excepciones, por supuesto, como Pyro Studios (http://www.pyrostudios.com) y Virtual Toys (http://www.virtualtoys.net), que son, entre otras pocas, dos de las empresas españolas punteras en desarrollo de videojuegos para las distintas plataformas. Pero el problema de la financiación y la distribución sigue siendo acuciante. Y en este país no se está por la labor.

Recuperar la esencia de los ochenta, cuando firmas como ERBE, Topo Soft, Dinamic, Opera Soft o Zigurat llevaron a la cumbre al software español con títulos como "Abu Simbel Profanation", "La abadía del crimen", Army Moves", "Las tres luces de Glaurung" o "París Dakar", ya parece una misión imposible. ¿O no? Y es que parece que la industria da un respingo y se pone en pie gracias a los videojuegos para dispositivos móviles, más concretamente para teléfonos celulares.
 
El mercado español de videojuegos ha asomado la cabeza y se centra en el desarrollo para móviles, considerado como uno de los segmentos de mayor crecimiento a nivel mundial, junto con los juegos Flash para la Web. Estos productos requieren inversiones mínimas frente a los miles de euros que se necesitan para desarrollar un juego para una consola normal; a excepción de la plataforma PlayStation que, además de esos miles de euros, necesitarás varias cajas de analgésicos, antiácidos y, probablemente, un par de mesecitos en algún que otro centro psiquiátrico si consigues finalizar el proyecto (esto es debido a la propia política de Sony, que sólo quiere juegos de calidad desarrollados por empresas con mucha pasta y mucho tiempo libre, como vino a decir recientemente Kazuo Hirai, directivo de la multinacional).

El creciente desarrollo de dispositivos y redes móviles y el perfil de los consumidores de videojuegos en España son los ingredientes perfectos para un cóctel explosivo en el mercado de los videojuegos. Además, la inversión de producción se ha reducido tanto que cualquiera en su casa con un ordenador puede desarrollar un videojuego para móvil prácticamente con un mínimo esfuerzo y una curva de aprendizaje muy suave. ¿Qué es necesario? ¿Me puedo forrar con esto? ¿Me haré multimillonario y las chicas del Bar Coyote se me tirarán al cuello?

Tranqui, tranqui. Vamos por pasos.

Los juegos para móvil están, prácticamente el 99%, programados en J2ME, un subconjunto del lenguaje Java con las principales bibliotecas reconfiguradas para ser adaptadas al hardware de los móviles. El lenguaje Java, inventado por Sun Microsystems a mediados de los años noventa originalmente para controlar lavadoras y otros electrodomésticos, fue rápidamente portado al ámbito informático debido a su robustez y, sobre todo, a la independencia de la plataforma en la que se ejecute, ya que, por medio de consolas virtuales, un programa desarrollado en Java puede ejecutarse de igual manera en un PC bajo Windows, en un sistema operativo Linux, en un Mac, en un teléfono móvil, en un Pocket PC, etcétera.

Esta característica ha conseguido que Java se convierta de facto en un estándar de programación de aplicaciones para teléfonos móviles, porque todos los desarrolladores de sistemas operativos para celulares incorporaron compatibilidad con este lenguaje desde el minuto cero.

La edición Java 2 Micro Edition (J2ME) se desarrolló con el propósito de habilitar aplicaciones Java para pequeños dispositivos con capacidades restringidas, ya sean gráficas, de procesamiento o de memoria. Posee unos componentes básicos adaptados de su hermano mayor y otras virtudes dirigidas específicamente a las características intrínsecas de un teléfono móvil, como manejo de redes telefónicas, conectividades varias o conexión GPS.

Para desarrollar un programa, juego o no, en J2ME sólo será necesario cualquier editor de texto ASCII plano (léase el Bloc de notas de Windows), un copilador estándar de Java y las API de configuración, todo ello descargable desde el sitio web para Java de Sun Microsystems (http://java.sun.com).

Además de lo anterior, necesitaremos, como es obvio, unos conocimientos de programación en Java desde básicos hasta profesionales, en función de la aplicación que queramos desarrollar. Y, por supuesto, un teléfono móvil para poder cargar nuestro proyecto cuando esté compilado, depurado, libre de errores y comprobado en un emulador. ¿Dónde puedo adquirir los conocimientos para desarrollar mi propio juego? Pues mira, no me voy a andar por las ramas, aquí: http://www.lcc.uma.es/~galvez/ftp/libros/J2ME.pdf. Este es un libro muy bueno, en formato PDF, dedicado exclusivamente al desarrollo para la plataforma J2ME y escrito por ingenieros informáticos de la Universidad de Málaga.

Como se puede comprobar, con una serie de conocimientos y algunas herramientas de desarrollo gratuitas podemos embarcarnos en la programación de nuestro primer juego en Java. Coste cero; tiempo mucho. ¿Qué hacemos después? Venderlo, por supuesto. No nos vamos a quedar con nuestro flamante juego instalado en nuestro móvil sin que el resto de la humanidad disfrute de nuestra genial creación.

Pues sí, los juegos Java para móviles son más fáciles de colocar en el mercado de lo que te crees. Existen empresas como Greystripe (https://www.greystripe.com) que se dedican a distribuir juegos para móviles de manera gratuita financiados por publicidad incluida en el propio juego, lo que llaman los cursis ad-supported mobile games. Esta empresa que os comento en concreto es propietaria del portal GameJump (http://www.gamejump.com), el cual se dedica a la distribución de juegos gratis para móviles en los que se incluye publicidad. Este modelo de negocio, terriblemente menospreciado y vilipendiado en un principio, está haciendo de oro de Greystripe: servir anuncios en momentos concretos del juego que no interrumpan la partida, como por ejemplo al principio y al final de la misma, entre niveles o fases, etc., a cambio de disponer del juego sin soltar un euro.

Lo bueno del tema es que la mayoría de los desarrolladores de los juegos de GameJump son pequeños programadores independientes (como tú o como yo) con dificultad para distribuir sus títulos mediante grandes operadoras nacionales y que aquí encuentran un hueco para hacerse megafamosos y muchimillonarios... o al menos un poquito. O si no, otra opción, podría ser vender tus propios juegos de manera particular o por medio de un página web propia, algo más engorroso y con menos repercusión, pero mucho más ventajoso si cuaja.

Visto lo visto, si a alguien le apetecía meterse en este mundo y siempre había pensado que esto es terreno vedado a grandes compañías y gurús megabíticos, que sepa que es un mundo al alcance de cualquiera y, sobre todo, una profesión muy divertida. A ver quién no quiere ganar pasta pasándose el día jugando, ¿eh? Un placer, digo.

Cómo escribir código VB .NET puro (y no morir en el intento)

teknoplof 07/10/2008 @ 17:32

Habrás leído mil veces en otras tantas páginas web que a la hora de diseñar tu aplicación en Visual Basic .NET, lo ideal es olvidarse del antiguo Visual y aprender a generar código puro para el Framework .NET. El problema es que si estás en proceso de adaptación a la nueva plataforma, es más que probable que no sepas cuando estás utilizando una instrucción que viene de antiguo y cuando no.

El quid de la cuestión está en el espacio de nombres Microsoft.VisualBasic, que Visual Studio importa por defecto a tus nuevos proyectos debido a esa sempiterna manía de Microsoft de lo que denominan "compatibilidad hacia atrás", y que a veces es tan bueno y otras veces no tanto. Al principio esto puede parecer útil en un proceso de migración, pero en última instancia te va a resultar contraproducente en tu nuevo proceso de adaptación y aprendizaje.

Vale, y entonces ¿cómo lo hago? Muy fácil, chaval. Te voy a contar un truco de cosecha propia que reducirá tu curva de aprendizaje sustancialmente.

¡Venga, venga, dime! Ya voy, no te aceleres.

Cuando escribas código procura utilizar siempre clases nativas de .NET. Yo no te voy a contar qué se puede y qué no se puede usar, lo puedes encontrar en multitud de sitios web y en la propia documentación de migración de Microsoft. Al terminar el proceso de desarrollo, vete a las propiedades de la aplicación, a la pestaña Referencias, y desactiva la casilla de verificación del espacio de nombres Microsoft.VisualBasic. En este momento, todo tu código se llenará de preciosos errores allí donde haya un pedazo antiguo y no soportado en .NET de forma nativa.

Ahora ya puedes ir depurando cada error hasta que Visual Studio te vuelva a dejar compilar tu bonito assembly libre de código obsoleto.

¡Chupao!

Antes de cal, ahora de arena

teknoplof 02/10/2008 @ 12:53

Si en el anterior post ensalzaba yo las grandezas de la plataforma .NET, ahora le toca el turno a una ración de fusta contra esta misma tecnología. Y es que así como se me llenaba la boca, embobado, parloteando del ASP.NET 2.0, hoy se me encharca de improperios contra el último ADO.NET.

Y digo yo, ¿por qué le han llamado ADO.NET y no AARGGGH.NET? Esto es tan parecido al ADO de toda la vida como Windows Vista a Windows 3.11 (para trabajo en grupo, rezaba debajo, ¿no?).

Vamos que la intención es similar pero el manejo no se parece en nada de nada. Y no es que las formas hayan cambiado mucho, y uno ya, a su edad, no esté como para andar renovando neuronas cada año y medio, es que el ADO.NET no hay por donde cogerlo. Es muy potente, y muy bonito, y de currelo desconectado y todo lo que quieran, pero no hay Santo Padre que le meta mano.

Lo que antes era Conectar-Abrir-Leer-Cerrar-Desconectar, hoy se ha convertido en Crear el DataAdapter-Generar los comandos-Asignar los comandos al DataAdapter-Configurar-Crear el DataSet-Llenar el DataSet-Cerrar-Leer-Desconectar. Esto, claro está, para extraer un dato y en formato simplificado, que no se le vaya a pasar a usted por la cabeza querer añadir datos a la tabla, que deberá realizar alguna operación que otra más. Un dolor, digo.

Me agrada que los hombres de Redmon renueven tecnologías y amplíen miras, pero, por Dios (y la Virgen, que son dos), no nos hagan la vida más complicada de lo que ya es.

Gracias a la providencia divina, y a la desinteresada aportación de un desarrollador de los de pro, encontré (hace ya) en Planet Source Code una clase para manejar ADO.NET a golpe de comandos al estilo DAO/ADO... <suspiro>qué tiempos aquellos</suspiro>. Para el que le interese, se puede descargar haciendo clic aquí (¡toma normas de utilización de hipervínculos!).

Cuando más conozco el .NET...

teknoplof 02/10/2008 @ 12:33

.NET... más me pone. Y es que hay que reconocer que los chicos del tío Bill se salieron desarrollando esta tecnología.

Imaginen el entorno de desarrollo perfecto, un espacio que sea independiente del lenguaje utilizado, que sea multiplataforma y que permita desarrollar aplicaciones de escritorio, aplicaciones web, para dispositivos móviles o servicios basándose en las mismas técnicas de trabajo y en la misma actitud. Eso es .NET.

Imaginen una biblioteca de clases compartida por todos los lenguajes de programación, un entorno de ejecución común, una infraestructura común, un lenguaje intermedio de compilación común y unas especificaciones reguladoras comunes. Imaginen un conjunto de tipos de datos comunes y una arquitectura de acceso a datos común. Imaginen un espacio de trabajo común. ¿Puede haber algo más común que lo común?

Los programadores de Visual Basic ya no podrán ser denostados por los gurús súpermegageeks de ce masmás, porque ahora comparten las mismas características, incluidas las archimanidas herencia, encapsulación y polimorfismo, que son tres cosas raras de los lenguajes orientados a objeto de las que todo hijo de vecino farfulla y luego ni Dios entiende correctamente.

Amén de ello, es importante dedicar un renglón o dos a ensalzar ASP.NET 2.0, que permite desarrollar un sitio web como si de un programilla casero de facturación se tratrase. Ya podemos separar la lógica del diseño, utilizar propiedades y eventos o interacturar con el estado del cliente sin hacer perder tiempo al usuario con eternas recargas de elementos repetidos.

Si a esto le agregamos un poco de SOAP, algo de AJAX (o AVBAX :P), una pizquilla de Silverlight y un chorrito de CSS, obtendremos el batuburrillo perfecto para volvernos locos entre tanta tecnología que, aunque resulte un lío de acrónimos, merece la pena un rato.

NB: Si "SOAP" es jabón en inglés y "AJAX" (pino) es una marca de jabón, progongo denominar FAIRY a la siguiente versión del .NET, o lo que es lo mismo "Framework of Alternative Intelligence Rather Yobbo". No sé, así a bote pronto.

AVBAX es AJAX, pero raro (y III)

teknoplof 02/10/2008 @ 11:13

Bueno. Por fin vamos a terminar esta serie explicando la mejor utilidad que se le puede dar al AVBAX, esto es, el acceso asíncrono a un archivo XML, que para eso se inventó todo este tinglado; vamos, digo yo...

Supongamos un archivo XML (al que llamaremos archivoxml.xml para seguir con la originalidad) que guarda grupos de música y álbumes publicados y que contenga las siguientes líneas

[código]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml>
  <Album ref="CD142" categoria="Pop">
    <titulo>Guapa</titulo>
    <artista>La oreja de Van Gogh</artista>
  </Album>
  <Album ref="CD720" categoria="Rock">
    <titulo>Zapatillas</titulo>
    <artista>El canto del loco</artista>
  </Album>
  <Album ref="CD024" categoria="Rap">
    <titulo>Vivir para contarlo</titulo>
    <artista>Violadores del verso</artista>
  </Album>
</xml>

[/código]

Veamos primero el procedimiento Sub:

[código]

Sub ObtenerDatos()
  AVBAX.Open "GET", "archivoxml.xml"
  AVBAX.onreadystatechange = Getref("ComprobarEstadoYLeer")
  AVBAX.Send()
End Sub

[/código]

Y ahora la función que recoge los datos (y controla el estado de la transacción):

[código]

Function ComprobarEstadoYLeer()
  If (AVBAX.readyState = 4) Then
    Set XMLDoc = AVBAX.responseXML.documentElement
    Set NodosXML = XMLDoc.ChildNodes
    For Each Elemento In NodosXML
      miCapaContenido.innerHtml = miCapaContenido.innerHtml _
      & "<BR>" & Elemento.ChildNodes(0).NodeName & ": " _
      & Elemento.ChildNodes(0).Text & " // " & _
      Elemento.ChildNodes(1).NodeName & ": " _
      & Elemento.ChildNodes(1).Text
    Next
    miCapaContenido.innerHtml = miCapaContenido.innerHtml _
    & "<BR><BR>" & "Número de registros: " & NodosXML.Length
    Set AVBAX=Nothing
  End If
End Function

[/código]

En este caso deberemos cambiar la propiedad responseText por responseXML, haciendo así que se interprete el archivo con su formato original, y no como un simple fichero de texto. Nos creamos una variable que guardará el objeto de elemento del documento con la propiedad documentElement de responseXML. Así pues, en XMLDoc se almacena el objeto de documento completo.

Para poder acceder a los distintos elementos internos del XML (o nodos para los puristas) nos servimos de otra variable para almacenarlos; esta variable será NodosXML que hace uso de la colección ChildNodes del objeto XMLDoc previamente declarado. Y ahora recorremos todos los nodos con un bucle For... Next.

Mientras leemos los nodos extraemos el nombre de cada subnodo (o nodo hijo con respecto al anterior) con la propiedad NodeName y su contenido textual con la propiedad Text. Los índices 0 y 1 se refieren a cada uno de los subnodos dependientes del anterior (0 para <titulo> y 1 para <artista>).

Entiéndase bien. Los nodos hijos del documento XML (guardados en NodosXML) son los distintos <Album>. Ahora, los nodos hijos de NodosXML son los distintos artistas y títulos de discos.

Todo el resultado se almacena en el innerHtml de la capa (objeto DIV) llamada miCapaContenido.

Por último escribimos el número de registros con la propiedad Length del objeto guardado en NodosXML.

Disponemos de multitud de propiedades para sacarle jugo a este objeto, entre otras: FirstChild, NodeType, NodeValue, OwnerDocument o ParentNode. También métodos: AppendChild, CloneNode, HasChildNodes o RemoveChild. Pero esto ya corre de vuestra cuenta y de vuestras ganas de investigar. Ajo y agua.

AVBAX es AJAX, pero raro (II)

teknoplof 01/10/2008 @ 17:45

Pos vale. Pos malegro. Y además de poder leer un archivo de texto alojado en el servidor remoto, ¿pa' que más me sirve esto?

No se me alteren, por Dios, no se me alteren. En este segundo post vamos a explicar cómo hacer peticiones GET y POST a una página web con paso de parámetros y todo. ¡Acérquense que estamos que lo regalamos! ¡A regolvé, a regolvé!

Efectivamente, con el objeto XMLHttpRequest también podemos capturar el resultado de la petición parametrizada que escupe un ASP, o un PHP, o cualquier otro, actuando contra una base de datos.

Para peticiones GET deberemos especificar los parámetros en la línea del Open así (por ejemplo):

[código]

VBAX.Open "GET", "index.html?parametro1=Hola&parametro2=" & _
Escape(Cadena2), True

[/código]

Donde Cadena2 es una variable previamente definida y con valor asignado, y Escape es una función VBScript que codifica una cadena transformándola en válida para una transacción HTTP. Esta función debe utilizarse siempre, o casi siempre, para evitarnos problemas a la hora de realizar las peticiones. Ya sabéis, nos convierte los caracteres raros para una URL (como espacios, eñes, tildes y demás) en otros todavía más raros (como +, %F1, etcétera) pero comprensibles para el navegador. ¿Cuando hablarán derecho estos paratos?

Para peticiones POST la cosa cambia un poco. Los parámetros han de pasarse desde el método Send de la siguiente manera:

[código]

AVBAX.Open "POST", "index.html", True
AVBAX.Send("parametro1=Hola&parametro2=" & Escape(Cadena2))

[/código] 

Como se comentó en el anterior post, entre ambas líneas de código irá la que indica la función que recogerá los resultados (la del onreadystatechange).

AVBAX es AJAX, pero raro (I)

teknoplof 01/10/2008 @ 17:36

Uno que viene mamado del BASIC del Spectrum y aborrece todo lo que suene a Java y JavaScript, tuvo que aguzar el ingenio para no perder el tren AJAX sin necesidad de utilizar una sola llave de código ni un anodino masmás de esos (que vienen a ser el contador suma de toda la vida, vaya). Por ello, y tras horas de prueba-error, llegó a la conclusión de que había inventado el AVBAX, o lo que es lo mismo, el AJAX vía VBScript. Días más tarde descubrió que ya estaba inventado y que, incluso (¡será posible!), algún avezado programador chino, o japonés, o tailandés, o lo que sea, le había llamado también AVBAX. Snif, snif.

Autorías aparte, el asincronismo con VBScript y XML es AJAX variando el leguaje script, por lo que el objetivo final es el mismo y el resultado igualico igualico. Lo único que, como no tengo la menor intención de aprender más JavaScript del que ya sé, a mí me resulta más sencillo e intuitivo.

Intentemos arrojar un poco de luz sobre el tema de la apotema comenzando, en este primer post, con un ejemplo que accede a un simple archivo de texto plano.

Al igual que con JavaScript, el primer paso consiste en crear el objeto XMLHttpRequest para poder acceder de manera asíncrona a un documento XML. Esto lo hacemos de aquesta forma:

[código]

Dim AVBAX
Set AVBAX = CreateObject ("Msxml2.XMLHttp")

[/código]

Lo siguiente es definir el procedimiento Sub para obtener los datos del archivo de texto al que, haciendo gala de gran originalidad e inventiva, llamaremos archivo.txt.

[código]

Sub ObtenerDatos ()
  Dim URL
  URL = "archivo.txt"
  AVBAX.Open "GET", URL, True
  AVBAX.onreadystatechange = Getref ("ComprobarEstadoYLeer")
  AVBAX.Send ()
End Sub

[/código]

El método Open prepara una conexión HTTP a través del objeto XMLHttpRequest. El primer parámetro es el método de conexión (GET o POST); el segundo parámetro es la URL para la petición HTTP (en este caso un simple fichero textual alojado en el mismo directorio que el HTML); el tercero es un parámetro booleano que toma valor True para utilizar el método asíncrono y False para el método síncrono (valga este último palabro, inexistente para el DRAE).

Por su lado, la propiedad onreadystatechange asigna la función que se ejecutará cuando la propiedad readyState (ver más adelante) cambie de valor. En este caso asignamos una función que se llama ComprobarEstadoYLeer, que definiremos a continuación. Send envía los datos de la petición.

Por último, definimos la función que comprobará el estado de la solicitud y actuará en consecuencia.

[código]

Function ComprobarEstadoYLeer ()
  If (AVBAX.readyState = 4) Then
    miCapaContenido.innerHtml = AVBAX.responseText
    Set AVBAX = Nothing
  End If
End Function

[/código]

readyState toma los siguientes valores:

0 - Sin inicializar.
1 - Abierto.
2 - Enviado.
3 - Recibiendo.
4 - A punto.

Nosotros sólo podemos acceder a la respuesta cuando readyState sea igual a 3 ó 4, de ahí la condicional.

responseText devuelve el texto del documento descargado en la petición y, con la propiedad innerHtml del objeto miCapaContenido (que es una capa u objeto DIV), escribimos el resultado en pantalla. Al final descargamos el objeto de la memoria.

Por último queda decir que en el evento onClick de un botón de comando, por ejemplo, haríamos la llamada al procedimiento Sub y listo, Calisto. Chupado. No me digan.

Por supuesto, todo el código antes expuesto habría de ir contenido entre las marcas de rigor.