Manejar aparatos eléctricos desde el PC: domótica (4/5)

Después de un largo periodo de descanso empiezo a escribir el siguiente artículo sobre domótica.

Ya hemos tratado varias formas de acceder remotamente o localmente al sistema de domótica a través de TCP/IP. La cuestión es que hasta ahora las interfaces que necesitábamos para poder interactuar con el sistema necesitaban de un ordenador que se conectara al sistema central (que podía ser el mismo que contiene el sistema) para enviarle ordenes y recibir el estado. En este artículo trataremos una forma más «casera» de interactuar con el sistema.

Todo el mundo tiene un mando a distancia en su casa y/o sabe como usarlo, asi que con esta sencilla interfaz podemos interactuar con todos los aparatos del sistema de domótica simplemente interpretando las pulsaciones que recibe del mando a distancia (en mi caso mediante un puerto serie) y convirtiendolo en comandos del protocolo del sistema de domótica. Para ello cargamos el programa Remoto, que es una aplicación de consola, pasándole como parámetros el puerto serie, el servidor, el usuario y la contraseña. Este lo que hará es acceder mediante TCP/IP al servidor Luces con el usuario y contraseña dados y a continuación abrirá el puerto serie para empezar a recibir las señales infrarojas.

Cuando se pulsa el botón 1, 2, 3 o 4 del mando a distancia cambia el estado del aparato a encendido o apagado si se encuentra apagado o encendido respectivamente. Por supuesto tiene que haber visión directa entre el mando a distancia y el receptor (que puede no estar en la misma habitación que el ordenador al que esta enchufado).

De la aplicación podemos salir pulsando intro. El mando a distancia que tengo y el cable receptor lo obtuve de una capturadora de televisión, sin embargo si no teneis uno similar podeis comprar ya uno hecho de cualquier capturadora MIRO o AVERMEDIA o haceros vosotros mismos uno: http://www.tldp.org/linuxfocus/Castellano/March2000/article137.html.

Manejar aparatos eléctricos desde el PC: domótica (3/5) Manejar aparatos eléctricos desde el PC: domótica (5/5)

Manejar aparatos eléctricos desde el PC: domótica (3/5)

Al estar el sistema de domótica centralizado en un solo programa que escucha por un puerto TCP, se puede ampliar todo lo que sea necesario para cubrir todo tipo de necesidades de comunicación.

Una de las posibilidades que ofrece la domótica es poder acceder a los aparatos aún cuando no se está presente en el hogar. Es por ello que necesitaba un medio por el cual poder acceder al sistema desde fuera de mi casa. Pues bién, aprovechando la infraestructura de Internet, y que el protocolo HTTP es el que esta más extendido, instalé un servidor web en casa e hice un portal al cual pudiera acceder desde cualquier sitio que tuviese acceso a Internet mediante un navegador.

En la imágen se puede observar el punto de entrada a la web. En su momento instalé un IIS e hice toda la programación con DHTML + ASP. Al ser una web se puede acceder a ella mediante proxy (seleccionando la opción de HTML) y sin proxy (seleccionando la opción de Java). El usuario y contraseña usa la misma base de datos de la que tira el programa Luces.

La sección de HTML es especial para proxys puesto que en muchos sitios se usan (sobre todo empresas) para compartir una conexión de Internet, mantener un registro de accesos, etc. El problema es que si hay proxy es muy posible que no haya otro medio de conectarse a Internet sin pasar por el y por tanto no pueda hacerse una conexión permanente al servidor. Por ello la interfaz esta diseñada para recibir información cuando se hace la petición http al servidor y no se refresca hasta que no se vuelva a seleccionar otro estado (eligiendo el aparato y pulsando Enviar) o ver el estado actual (pulsando el botón Ver Estado). Si el usuario es administrador, además de poder visualizar los aparatos e interactuar con ellos como otro usuario con permisos, también es capaz de manejar los comandos privilegiados además de poder hacer consultas sql a la base de datos. El fichero ASP es el encargado de hacer la conexión TCP/IP al programa Luces (tanto Luces como el IIS residen en la misma máquina), para ello usé un componente ActiveX llamado vbwinsock y que lo podeis descargar aquí.

La sección java es similar a la de HTML pero orientada a usuarios que tienen acceso directo a Internet. Se llama así porque la parte donde estan representados los aparátos es un applet de java con conexión directa al servidor de Luces (la seguridad de java solo deja conectarse al mismo dominio desde que se pidió la página). Por ello si pulsamos en cualquiera de los botones se actualiza rápidamente el estado, incluso si otro usuario cambia el estado de alguno de los aparatos también se vería reflejado. Sería como conectarse por telnet pero de una forma mucho más sencilla y amigable.

Ha habido gente que me ha preguntado por qué tardo tanto en escribir entre artículo y artículo, la razón es que tengo poco tiempo y otras veces no tengo ganas de salir del trabajo para ponerme otra vez en frente del ordenador, por eso os pido un poco de paciencia.

Otras personas me han preguntado si voy a dejar accesible el código fuente de las aplicaciones que aquí menciono, y si, efectivamente lo liberaré para que otros puedan hacer soluciones similares o basarse en esta para hacer algo nuevo. Además tengo pensado grabar un video del funcionamiento de todo el sistema de domótica.

Manejar aparatos eléctricos desde el PC: domótica (2/5) Manejar aparatos eléctricos desde el PC: domótica (4/5)

Manejar aparatos eléctricos desde el PC: domótica (2/5)

Para poder controlar el módulo por software se me planteaba una duda, ¿cómo hacer para que varios programas accediesen a este?. Todos tenían que ser ejecutables y ser lanzados con el Port Talk, sin embargo no era lo más optimo porque no había manera de saber que aparatos estaban encendidos y cuales no, además de que mi interés era controlar los aparatos no solo desde el propio ordenador donde estaba conectado el módulo, sino también a través de otros dispositivos.

La solución se mostraba por sí sola: solo un programa accedería al módulo y los demás deberían comunicarse con este para lanzarle las peticiones y recibir el estado actual en que se encontraban los aparatos. De ahí salió el programa Luces, el cual era un simple servidor tcp que escuchaba por el puerto 1976 (mi año de nacimiento) y se comunicaba con sus clientes mediante un sencillo protocolo basado en números (al estilo del protocolo simple de transferencia de correo – SMTP). Los códigos que devuelve el servidor son los siguientes:

100 Saludo al nuevo cliente conectado
101 Estado en que se encuentran los aparatos (máscara)
200 Usuario introducido
201 Contraseña introducida
202 Permitir o denegar peticiones, cerrar programa o apagar equipo
300 Estado no identificado
301 Comando no reconocido
302 Fallo en la autentificación

Por su parte el cliente envia los siguientes comandos (en mayúsculas o en minúsculas):

USER:<usuario> Usuario a validar
PASS:<contraseña> Contraseña a validar
<Número> Estado que se quiere aplicar a los aparatos (máscara)
OPEN Permite a los usuarios no administradores manejar los aparatos
CLOSE Deniega a los usuarios no administradores manejar los aparatos
QUIT Cierra la aplicación
BYE Apaga el equipo

En primer lugar el orden que se debe seguir es:

Servidor: Mensaje de Saludo.
Cliente: Enviar USER: y el nombre de usuario.
Servidor: Mensaje de Usuario Introducido.
Cliente: Enviar PASS: y la contraseña del usuario.
Servidor: Mensaje de Contraseña Introducida.

  • Si el usuario introduce una contraseña incorrecta el servidor le mostrará un fallo en la autentificación (302) y cerrará la conexión.
  • Si el usuario introduce un comando no reconocido cuando se está validando el servidor le mostrará un comando no reconocido (301) y le cerrará la conexión, en cambio cuando este validado solo le mostrará el estado de los aparatos (101).
  • Si el usuario introduce antes el comando PASS que el USER el servidor le mostrará estado no identificado (300) y le cerrará la conexión.

En segundo lugar cuando el usuario ya esta validado puede introducir o bién los comandos OPEN, CLOSE, QUIT y BYE; o bién un número de 0 a 15 que actuaría como máscara para encender o apagar los aparatos (si el número es mayor que 15 se usa el módulo de 16).

Haciendo un telnet, lo anterior comentado se vería de la siguiente forma:

Y en la aplicación Luces se vería así:

Si ahora cometemos un error (por ejemplo metemos mal el usuario) el resultado quedaría así:

Como se puede observar, la segunda conexión la he hecho a través de otro ordenador. Gracias a que se usa el protocolo el tcp/ip se puede conectar desde cualquier programa (independientemente del sistema operativo, arquitectura de ordenador, etc).

Por otro lado el sistema se basa en una base de datos para gestionar los usuarios, los eventos y los aparatos:

En mi caso usé una base de datos access, pero como es lógico pensar, se puede usar cualquier tipo de base de datos relacional. Las tablas son sólo 4 y se detallan a continuación:

tblUsuarios Donde se almacenan los usuarios del sistema y sus permisos
intID Autonúmerico (o secuencia) que identifica al usuario inequivocamente
strNombre Nombre del usuario
strApellidos Apellido o apellidos del usuario
strLogin Identificador del usuario para validarse en el sistema
strPassword Contraseña del usuario para validarse en el sistema
blnActivo Bandera que indica si un usuario puede validarse en el sistema o no
bytNivel Nivel del usuario (100 administrador, 50 usuario normal, 0 visitante)
bytMascara Máscara de permiso para aparatos: Si el usuario tiene por ejemplo 10 (1010 en binario) sólo puede utilizar los aparatos 2 y 4, en cambio los aparatos 1 y 3 únicamente puede ver su estado
tblAcciones Donde se almacenan las distintas acciones del usuario
bytID Autonúmerico (o secuencia) que identifica la acción inequivocamente
strAccion Nombre de la acción (Usuario Validado, Usuario Desconectado, Orden y Comando)
tblLog Donde se almacena la actividad que lleva a cabo el usuario
intID Autonúmerico (o secuencia) que identifica la acción del usuario
intUsuario Campo relacionado con el intID de la tabla tblUsuarios
bytAccion Campo relacionado con el bytID de la tabla tblAcciones
datFecha Fecha y hora de la acción
strIP IP de la máquina donde se ordenó la acción
strDescripcion Descripción de la acción
tblAparatos Donde se almacenan los nombres de los aparatos a manejar
intID Autonúmerico (o secuencia) que identifica el aparato inequivocamente
strNombre Nombre del aparato

Manejar aparatos eléctricos desde el PC: domótica (1/5) Manejar aparatos eléctricos desde el PC: domótica (3/5)

Manejar aparatos eléctricos desde el PC: domótica (1/5)

Continuando la serie de artículos sobre aparatos que tengo, introduzco el último y más importante del sistema casero de domótica que he creado.

El kit o módulo que aparece en la fotografía pertenece a la familia de módulos a relé de la empresa CEBEK, cuyo código es T-1. Es un módulo que puede manejar hasta 4 relés a través de unos bornes de entrada. Tiene muchas ventajas, como que aisla la señal de entrada del resto del circuito con optoacopladores o como que usa un puente rectificador para la alimentación del circuito. El módulo se alimenta con una tensión de 12 voltios e intensidad de 200 mA (muchos transformadores pequeños de móvil u otros aparatos los proporcionan de sobra).

La idea es que con este circuito se puedan manejar aparatos eléctricos (incluidos electrodomesticos) desde el ordenador. Para ello, por una parte se usan los relés a modo de interruptor de un cable normal (en mi caso uso alargadores para no tener que pelar los de los aparatos eléctricos), por lo que en el circuito que uso podría manejar hasta cuatro aparatos distintos; por otra parte los cuatro bornes de entrada van conectados a cuatro de los ocho cables de datos de un cable paralelo.

Aprovechando que es muy sencillo acceder al puerto paralelo del ordenador y que las señales son de 5 voltios (más que suficiente para activar los optoacopladores) es posible mandar un byte al puerto de datos del paralelo (0x378) para que llegue a los bornes del circuito y posteriormente active los relés. ¿Como funciona la lógica de encender y apagar relés? pues cuando se manda un byte a través del puerto paralelo, los bits que esten a 1 hacen que los correspondientes pines del puerto paralelo se activen a 5 voltios, lo que en el circuito provoca finalmente que se activen los relés asociados. Asi por ejemplo si enviamos un 3, en binario es 0011, activándose los dos primeros relés. Con este sistema se pueden encender lámparas, calefacciones, microondas, lavadoras, persianas eléctricas, sistemas de riego, etc.

En windows 95, 98 y Millenium se puede acceder directamente al puerto paralelo, sin embargo en windows nt, 2000 y xp se necesita crear un driver que se ejecute en el nivel (ring) privilegiado 0, porque en el nivel 3 no se permite hacer directamente. Como tampoco quise perder tiempo en crear mi propio driver, usé un programa que ya hace todo eso de una forma muy sencilla: Port Talk, el cual, una vez instalado, da permiso a una aplicación (proceso) para que acceda a un puerto determinado (o a todos) desde la linea de comandos. Finalmente solo basta usar el método _outp en C para enviar datos al puerto paralelo:

_outp(0x378,3);

Manejar aparatos eléctricos desde el PC: domótica (2/5)

PC a móvil a PC

Hace un tiempo desarrollé un gateway sms/mail/sms donde además del software, la pieza clave era esta:

El gateway esta dado de baja (tuvo demasiado éxito), sin embargo el móvil que aparece en la imágen lo sigo usando en algunos de mis proyectos (pronto sabreis por qué estoy escribiendo artículos sobre aparatos). Se trata de un siemens m35i que en su día me cargué la pantalla y lo destiné como modem gsm para poder enviar y recibir sms. Este se comunica con un cable de datos por el puerto serie con el ordenador. Como el cable tiene que usar el mismo compartimento que la fuente de alimentación del móvil y necesitaba tener los dos al mismo tiempo, conecté los pines donde se conecta la batería del móvil a un pequeño circuito con un L7805C y dos condensadores, funcionando todo ello con una fuente de alimentación de 12 voltios.

En este caso el móvil al ser un modem gsm (como la inmensa mayoría) se puede manejar con comandos AT, aunque algunos son característicos de los móviles (como el de mandar sms).

Para trabajar con el, en mi caso, tengo que abrir el puerto serie a 19200 baudios, 8 bits, ninguna paridad y un bit de stop.

En mi caso, siempre me interesa usarlo como transmisor/receptor de sms, por lo que leyendo un poco la documentación del móvil veo que para enviar sms se usa el comando AT+CMGS. Sin embargo mi móvil no permite mensajes de texto de forma directa, sino que necesita enviarlos en formato estandar PDU (también cuando muestra los recibidos). Buscando por ahí no he encontrado mucho código fuente (en java smstools) por lo que me hice una rutina en C para pasar de texto a PDU y viceversa:

Manejar un ordenador con un mando a distancia

En el mercado de hoy en día se venden tarjetas sintonizadoras de televisión para el PC. Muchas de ellas tienen mando a distancia. Y en algunas de ellas el receptor de infrarojos que trae es para conectarlo a un puerto serie del PC.

Al ser el receptor de infrarojos un conector para el puerto serie, es muy sencillo comprobar que información le envía el mando a distancia y tomar esos datos para aprovecharlos en futuras aplicaciones, como por ejemplo:

-Apagar el equipo.
-Cargar una aplicación
-Simular pulsaciones del teclado predefinidas o mover el puntero ratón y simular pulsaciones de los botones.
-Escuchar música y subir el volúmen de los altavoces

La forma sencilla de saber que datos manda y en que formato sin tener que investigar mucho es usar un sniffer del puerto serie. En mi caso he usado el portmon, que es una excelente utilidad para rastrear la información que va y viene desde los puertos serie y paralelo.

Si os fijais en la imagen, se muestra como inicializa el puerto a 1200 baudios, 8 bits de datos, ninguna paridad y 1 bit de stop. A continuación vienen los datos propiamente dichos. Para la prueba he pulsado el botón 1 del mando a distancia y el resultado es FE 9F 31, si hubiese pulsado el 2 el resultado sería FE 3D 32. Si lo observamos veremos que el 1 y el 2 (y el resto de números) coinciden con su representación ASCII en hexadecimal (31 y 32). En otros casos como la pulsación de las teclas de subir (FE F1 3B) y bajar (FE 64 3D) volumen o subir (FE 17 3F)y bajar (FE C6 3E) de canal muestran otros caracteres. En el caso de que dejáramos una tecla pulsada los códigos varían ligeramente, como en la imágen, que aparece el triplete FE 77 71 cuando se deja pulsado el botón 1 del mando a distancia.

En definitiva, da igual que sea en linux o en windows, podemos capturar estos tripletes y actuar en consecuencia con cada pulsación recibida (si se pulsa el botón de off apagamos el equipo, si pulsamos los botones de subir y bajar el volumen y los canales podemos manejar el puntero del ratón, con el mute podemos apagar el altavoz del equipo, con el botón de play podemos enviar un tabulador, con los números podemos escribir letras estilo sms, etc). Por supuesto, que esa información venga así en mi receptor de infrarojos no significa que sea igual en otros, de ahi que haya que mirar como funciona con utilidades como el portmon.

Recuperar los títulos de las canciones de un CD con FREEDB

Desde hace mucho tiempo estan disponibles dos servicios en Internet cuyo cometido es almacenar una gigantesca base de datos con los títulos de las canciones de cualquier CD de música que se haya editado. La primera es Gracenote (también conocida antes del 2000 por cddb), de la cual no hablaremos en este artículo por requerir licencia. La segunda es freedb la cual sigue siendo gratuita y con una simple página web podemos consultar la información que nos interesa. En la sección developers podreis encontrar la información necesaria para trabajar con esta tecnología.

Básicamente consiste en obtener una identificación única a partir de la información de la tabla de contenidos de un CD (TOC). Una vez obtenida la identificación, solo hay que hacer una petición web al servidor de freedb con la misma para que nos devuelva el título del CD y la lista de títulos de canciones y sus respectivos autores de las distintas pistas que conforman el CD.

El algoritmo para hallar el identificador único consiste en:
-Sumar los números en segundos de lo que dura cada pista. Es decir, si una cancion dura 4:17, entónces son 257 segundos, luego la suma es 2+5+7=14.
-Una vez obtenido el sumatorio de todas las pistas con el anterior algoritmo, se le saca el módulo de 255 y a continuación se le multiplica por 16777216 (2^24); a este resultado se le suma el tiempo total del CD multiplicado por 256 (2^8) y finalmente a este resultado se le suma el número total de pistas que contiene el CD.

Una vez hallado el identificador único, se transforma a un número hexadecimal y se hace una peticion a freedb de la siguiente manera:

http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+<ID UNICO>&hello=name+host.com+appname+1.0&proto=1

cddb read misc <ID UNICO> del parámetro cmd es el comando que indica que estamos haciendo una petición a la base de datos con el ID UNICO. Por ejemplo cddb read misc c510910d.

name host.com appname 1.0 del parámetro hello indica que persona, dominio, aplicación y versión de la misma esta solicitando la información. Por ejemplo: sistemasorp sistemasorp.blogspot.com testeoCDDB 1.0.

Y finalmente el 1 del parámetro proto indica que versión del protocolo queremos usar para hacer la petición a la base de datos, devolviendonos acorde a la versión una información formateada.

Así por ejemplo si lanzamos esta petición:

http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+c510910d&hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&proto=1

Nos devuelve lo siguiente (terminado en una linea con un punto, al estilo del SMTP):

210 misc c510910d CD database entry follows (until terminating `.’)
# xmcd CD database file
#
# Track frame offsets:
# 150
# 24460
# 45650
# 71127
# 98425
# 118997
# 146585
# 164707
# 188897
# 216340
# 240932
# 271642
# 297722
#
# Disc length: 4243 seconds
#
# Revision: 2
# Processed by: cddbd v1.5PL3 Copyright (c) Steve Scherf et al.
# Submitted via: CDex 1.40Beta9
#
DISCID=c510910d
DTITLE=Various / Rave Massacre [Disk 1]
TTITLE0=Raving Bastards – Love Time
TTITLE1=Chill’n Force – Move Raver (Kemo Mix)
TTITLE2=M.A.F. X-Perience – Dreamland
TTITLE3=Society for Psychical Research – Silversky
TTITLE4=Obsessiv – Tune In, Tune On, Drop Out
TTITLE5=Nettuno – I Cry
TTITLE6=Razor – Is It Love
TTITLE7=Sunbeam – Outside World
TTITLE8=Raver’s Nature – Tricky Symphony
TTITLE9=NIP Collective – I’m About
TTITLE10=RBM – Banyo Love
TTITLE11=Paranoia X – Party Program
TTITLE12=NR-Gizer – Raving Generation
EXTD= YEAR: 1994 ID3G: 31
EXTT0=
EXTT1=
EXTT2=
EXTT3=
EXTT4=
EXTT5=
EXTT6=
EXTT7=
EXTT8=
EXTT9=
EXTT10=
EXTT11=
EXTT12=
PLAYORDER=
.

Donde entre comentarios (con la almohadilla delante) da información sobre el disco, copyright y demás; continuando con una lista de parejas nombre/valor que contienen la información que queremos:

DISCID: El mismo identificador de disco que le hemos pasado
DTITLE: El autor y título del CD
TTITLEX: El título de canción que está en la pista X
EXTD: Información extendida sobre el disco
EXTTX: Información extendida sobre la canción que está en la pista X
PLAYORDER: El orden en el que se deberían reproducir las pistas
YEAR: El año de edición del disco
ID3G: La categoría o clase de música que contiene el CD

A continuación expongo dos codigos fuentes (el primero para windows y el segundo para linux) que muestran como recoger el identificador único de un cd y a continuación solicitar la información de ese cd a freedb. Ambos se ejecutan en la consola de texto pasandoles como parámetro la unidad o dispositivo de cd.

WINDOWS(ejecutable y fuentes)

LINUX(ejecutable y fuentes)

webchat en tiempo real con php y mysql

Después de un pequeño descanso volvemos a las andadas. Esta vez voy a mostrar como crear un webchat en tiempo real.

El problema de los webchat es que la inmensa mayoría de los que existen se dedican a refrescar la página de la charla cada X tiempo o cuando el usuario ha escrito un mensaje. Esto es debido a que el protocolo HTTP esta diseñado para que una vez recibido los datos cierre la conexión, y si queremos recuperar datos nuevos tenemos que hacer una nueva petición.

Para lograr una interactividad y un realismo temporal cercanos al irc, messenger, etc. y seguir usando la web tenemos que usar un truco, y es crear una página que nunca termine de ejecutarse. Quizá os pregunteis que si nunca termina de ejecutarse, entónces no saldrá ningún resultado, pues bién, podemos desactivar el buffer del php desde el principio o hacer un volcado continuo para que cada dato nuevo se vaya enviando al navegador del cliente. Los navegadores muestran el contenido según les va llegando, por lo que una sentencia como esta (en pseudocodigo):

mientras verdadero
recupera mensajes nuevos
muestra mensajes nuevos
fin del mientras

haría que cada vez que un mensaje nuevo apareciese se enviase al navegador y este lo mostrara instantaneamente, con lo que habríamos conseguido que fuese el tiempo real.

Parar lograr este planteamiento en php tenemos que seguir los siguientes pasos (he reducido su código para simplificarlo):

ob_start();

Que activa el tratamiento del buffer en php

set_time_limit(0);

Indica al motor de php que el script nunca debe caducar a pesar de lo que dure.


for(;;)
{

Este es el bucle que constantemente se va repitiendo.


$rs=mysql_query(«SELECT * FROM chat_mensajes WHERE IDMensaje>'» . $id . «‘ AND WEEK(DatFecha,1)=WEEK(NOW(),1) AND YEAR(DatFecha)=YEAR(NOW()) ORDER BY IDMensaje»)
or die («No se puede realizar la consulta»);

En mi caso guardo los mensajes en una base de datos mysql, por lo que con la consulta SQL compruebo aquellos mensajes cuyo ID sea mayor que el último ID de mensaje que se ha mostrado (solo aquellos dentro de la semana actual del año en curso).


if(mysql_num_rows($rs)>0)
{
while($fila=mysql_fetch_array($rs,MYSQL_ASSOC)) {

Compruebo si hay nuevos mensajes y los recorro.


$id=$fila[«IDMensaje»];

Voy actualizando la variable id para que contenga al final el último ID y así en la siguiente pasada del bucle solo recoger los últimos mensajes escritos a partir del indicado.


echo «<div>\n»;
echo «<span>» . $fila[«DatFecha»] . » » . «</span>»;
echo «<span>» . $fila[«StrUsuario»] . «&gt;</span>»;
echo «<span>» . $fila[«StrMensaje»] . «</span>»;
echo «</div>\n»;
}

Se va mostrando el contenido de los mensajes (fecha, remitente y mensaje).


echo «<script>scrollTo(0,999999999);</script>\n»;
ob_flush();
flush();
}

Con un pequeño truco en javascript logramos desplazar la ventana del navegador siempre hasta el final del contenido. A continuacuón vaciamos el buffer hacia el navegador del cliente.


sleep(1);
}

Para no recargar mucho el servidor mysql haciendo constantemente consultas, pausamos durante un segundo la ejecución para después continuar con la siguiente iteración del bucle.

Quizá penseis que esta solución recarga mucho el servidor (tanto el web como el de mysql), pero el impacto es mínimo y si teneis un hosting esto os ahorrará ancho de banda puesto que gasta más por usuario el estar haciendo peticiones al servidor web cada X tiempo que una sola petición que dure eternamente (solo gasta lo que envia, como una petición normal); en cuanto al servidor mysql si este esta en localhost (como el 99% de los hosting) el impacto es mínimo porque no consume ningún recurso de red, además de que el propio mysql es rapídisimo y eficiente haciendo las consultas y no mermará el rendimiento por estar haciendo una cada segundo por cada usuario. Sin embargo si no quereis usar mysql, podeis usar ficheros (fopen) o bién memoria compartida (Shmop). Por supuesto esto no es la panacea, pero para cosas pequeñas (20 personas a la vez) si puede ir bién tenerlo así montado.

En la web en la que colaboro tengo implementado este sistema, que aunque lo tengo bastante desarollado, todavía tengo que mejorar ciertos aspectos de funcionalidad.

Generar imágenes aleatorias con php y google

Hace poco me planteé meter una sección de imágenes aleatorias en la web que estoy administrando junto con un amigo sobre coleccionismo español de la guerra de las galaxias.

El caso es que el hecho de tener un montón de imágenes almacenadas no es la mejor solución para un hosting si no tienes mucho espacio, por lo que se me ocurrió recurrir a la sección de imágenes de google. En esta sección se muestran en formato thumbnail (imágen pequeña de referencia) todas las imágenes de las páginas web que en su día indexó google, por lo que además de tener un vasto repertorio de imágenes, todas ellas estan asociadas al texto de la web a la que pertenecen. Así, si buscamos por palabras, podemos encontrar imágenes que concuerden con la búsqueda.

A mi me viene de lujo para mis intenciones, puesto que poniendo star wars en el cuadro de texto de la sección de imágenes de google aparecen algo menos de un millón de resultados. Añadiendo que la sección que quería poner en la web era más bién pequeña, las imágenes thumbnail de google son perfectas en cuanto a dimensiones para que quepa en la sección de la web.

Ahora bién, ¿como hacer para que los thumnails que google ha generado salgan en la web como propios?…Pues gracias a php puedo leer el contenido de las urls y mostrarlo con una cabecera apropiada como si fuera una imagen normal y corriente.

1-Una imagen en HTML se hace con la etiqueta IMG y el atributo src. En mi caso la imágen aletoria de la web debería apuntar siempre a un mismo sitio ya que es el propio php quien mostraría una imagen distinta cada vez. Por lo que en la web si os habeis fijado aparece:

<img src=»aleatorio.php» alt=»Imagen aleatoria (Gracias a Google Images)»>

Que indica al navegador que debe mostrar la imagen que genera la página aleatoria.php (con esto os podeis imaginar que los nombres de los ficheros le importan un pimiento al navegador, solo le interesa las cabeceras que devuelva el servidor)

2-Ahora tenemos que programar el código que recupere y muestre los bytes de la imagen que se quiere escoger al azar. Para ello debemos coger las imagenes de google, pero ¿como?. Pues antes de mostrar nada de código, voy a explicar muy por encima como funciona la sección de imágenes de google:

Voy a http://images.google.es/ y pongo como busqueda star wars

Me salen 20 imágenes, y unos enlaces para ir avanzando en el catálogo de imágenes. Sin embargo los thumbnails que aparecen son todavía un poco grandes para la sección de la web, por lo que elijo la opción Medianas, ahora pulsaremos por ejemplo sobre la página 3 del catálogo. Si os fijais a medida que he ido pulsando enlaces la url aparece con más datos:

http://images.google.es/images?q=star+wars&imgsz=small%7Cmedium%7Clarge%7Cxlarge&svnum=10&hl=es&lr=&start=40&sa=N

Esto es lo que nos servirá como primer punto para la busqueda de imágenes relacionadas con un tema determinado. Si os fiajis en los parámetros de la url está la letra q, donde se almacena el criterio de la búsqueda (en mi caso star+wars); imgsz, que indica el tamaño de las imágenes a buscar (puede ser también xxlarge e icon, aunque en mi caso es small%7Cmedium%7Clarge%7Cxlarge); svnum que no se para que sirve, ya que si lo quito funciona igual; hl para el idioma de los resultados; lr que tampoco sé para que sirve, start que indica desde que indice empezar, este es muy importante ya que aqui usaremos el primer número aleatorio; sa=N que no se para que sirve.

Como os comentaba, con start se puede indicar desde que índice de las imágenes empezar a mostrar: 0 sería desde la primera página, 20 desde la segunda página, 40 desde la tercera, etc. También podemos poner valores intermedios, pero yo sigo el camino de google con sus enlaces.

Una vez que ya podemos elegir que página de imágenes queremos cargar, ya solo queda elegir que imagen de las 20 que aparece en esa página mostrar, momento por el cual debemos usar el segundo número aleatorio. Pero claro, lo que nos interesa son las imágenes de google, no las originales a las que apunta el enlace de cada una de ellas. Por eso debemos recorrer el codigo fuente HTML de la página que hemos recuperado para ir etiqueta por etiqueta IMG hasta alcanzar el número aleatorio que habiamos solicitado. Sin embargo no podemos empezar desde el principio puesto que google tiene en su página un logo, unas imagenes de 1 pixel de grosor, etc. Es por ello que debemos comenzar a partir de un punto donde sepamos que a continuación todas las etiquetas IMG son las de los thumbnails. En mi caso uso la cadena «Solamente se muestran las«.

A partir de entónces, cuando ya obtengamos el atributo src de la etiqueta IMG requerida, ya podremos recuperar los bytes de la imagen thumbnail de google a través de su url. Posteriormente solo queda mostrarla a través del PHP.

El siguiente código fuente muestra como lo hacer lo que he comentado anteriormente desde una página php:

Podeis ver un ejemplo de su funcionamiento en la web que os indicaba arriba o directamente en este enlace http://www.starwarsspanishstuff.info/aleatorio.php.

Recomiendo poner en el texto alternativo un reconocimiento a google.

Ejecutar una variable

Tal como se lee puede parecer algo un tanto extraño. Todo el mundo que programa usa las variables para leer o introducir datos en ellas (aunque a veces lo que se esta haciendo por debajo es realmente llamar a una función). El caso es que el C, y por extensión el C++ (ignoro si el C# tiene esta caracteristica) puede crear punteros a funciones. Estos punteros, como el resto, son una variable que contiene una dirección de memoria; sin embargo, su uso normal es asignarle el nombre de una función en vez de una variable, tal que así:

Pero que pasaría si en vez de asignarle una función le asignamos una variable? Pues
que el contenido de esa variable lo ejecutaría. Por supuesto, la variable no puede tener cualquier contenido; los bytes que contendría deberían ser codigo maquina. Por ejemplo el siguiente código en ensamblador:

traducido a codigo máquina del intel x86 sería:

B8 09 00 00 00
C3

Por lo que si ejecutamos las siguientes lineas:

Lo que hemos hecho es llamar a una dirección de memoria que contenia una ristra de bytes, los cuales son significativos para el microprocesador. En el ejemplo hemos asignado al registro EAX (registro que almacena siempre lo que devuelve una función) el número 9 y a continuación ejecutamos un RET para retornar de la llamada de la función. Así hemos simulado una llamada a una función tal y como lo habría hecho el compilador, pudiendo incluso modificar el código (el contenido de la variable) en tiempo de ejecución sin problemas de violaciones de memoria o similares. Este código funciona tanto en Linux como en Windows siempre que sea un micro intel x86, aunque se puede usar en un motorola, power pc, o lo que querais siempre que conozcais el
lenguaje maquina del micro.

Este artículo dará pie a otro mucho más avanzado sobre como lograr que un programa original pueda acceder a un web service sin que otros se aprovechen de esa información (si usar contraseñas ni nada parecido).