Archivo de la categoría: Uncategorized

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)

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:

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).

Por fin nos libramos de las patentes de software

Después de haber luchado incansablemente por que las patentes de software no salgan adelante, después de haber explicado sus contras, después de habernos llevado grandes disgustos y pequeñas alegrías, por fín puedo decir que la propuesta de patentes de software en Europa ha sido definitivamente derogada contundentemente por 648 votos a favor, 14 en contra y 18 abstenciones.

¡¡¡ Estamos de Enhorabuena !!!

Wake On LAN y Magic Packet

Todos sabemos que podemos apagar el ordenador con un comando o bién con una combinación de pulsaciones de teclado o ratón, también hay programas que dado cierto evento hacen que se apague el sistema.

Esto no tiene ningún misterio, pero… ¿y si se trata de encenderlo?. Puede que con el solo hecho de pulsar el botón de encendido de la cpu nos sea suficiente (a veces con pulsar un botón del teclado o mover el ratón), sin embargo cuando no estamos físicamente presentes la cosa cambia: un cibercafe donde es más cómodo encender todos los ordenadores a la vez, o encender un ordenador remoto que por las noches se apaga para ahorrar electricidad, etc. Antiguamente los ordenadores se apagaban y punto, pero desde que irrumpió en el mercado el formato ATX de cajas y placas madre y con el estandar ACPI la cosa no ha hecho más que facilitarnos las cosas: ahora gracias a esos dos estandares somos capaces de apagar el ordenador por software, apagar el equipo ordenadamente por hardware, suspender, volver a reactivar, volver a encender, etc. En la parte que nos toca hay unos eventos que son capaces de encender un ordenador cuando este está apagado, y para la gestión remota de ese encendido se puede usar unos metodos denominados wake on ring, wake on modem (por modem) o wake on lan (por red).

Este artículo se centra en el método Wake On Lan (+ o – despertar por red). Este sistema se basa en que un ordenador cuando se apaga, no lo hace totalmente, sino que la fuente de alimentación sigue alimentando a la placa madre, y esta puede gestionar con muy bajo consumo los eventos que se den, como por ejemplo, encender el ordenador cuando recibe un paquete especial por la tarjeta de red. Este paquete, conocido como Magic Packet es muy simple y su formato consiste en 6 bytes con valor hexadecimal FF y otros 16 grupos de 6 bytes con la dirección MAC de la tarjeta de red. Da igual en que protocolo se envié ese paquete (IPX, TCP/IP, etc), con tal de que se envíe por toda la red. Así si se quiere encender un ordenador con una MAC 01:02:03.04:05:06 se enviaría un paquete con estos bytes en hexadecimal:

FFFFFFFFFFFF
010203040506010203040506010203040506010203040506
010203040506010203040506010203040506010203040506
010203040506010203040506010203040506010203040506
010203040506010203040506010203040506010203040506

El paquete debe enviarse a toda la red, por lo que hay que intentar que sea con el protocolo que se haga, este debe permitir enviar paquetes broadcast. Esto normalmente se puede conseguir con el protocolo IP, ya que poniendo como destinatario la dirección IP 255.255.255.255 debería llegar a todos los nodos de todas las redes que lo permitan. El TCP o UDP que venga por encima no es importante, aunque personalmente prefiero el UDP por no ser orientado a conexión. Por encima del UDP vendrá el magic packet. A continuación pongo un ejemplo de codigo fuente en varios lenguajes de programación para que podais probarlo (son tan cortos que no hacen falta comentarlos, tampoco tienen gestión de errores para su simplicidad), en vuestro caso solo tendrías que modificar el puerto (1976) y la dirección MAC (01:02:03:04:05:06):

C para Linux/Unix y Windows

Perl

Java

Visual Basic (Para que funcione debeis insertar un control Winsock)

Por supuesto no hay método que sirva para marcar todas las tarjetas a la vez, así que habrá que ir una por una mandando el magic packet para que se vaya encendiendo cada ordenador. La tarjeta de red de cada ordenador apagado compara todos los paquetes que le llegan del tráfico de red para ver si contiene 16 veces su dirección MAC y así mandar a la placa madre que encienda el ordenador.

Las tarjetas de red que vengan incorporadas ya de fábrica en la placa madre ya tienen esta función activada. Sin embargo las que estan sueltas en ranuras PCI o ISA, deben:
1) Permitir el wake on lan (no todas tienen un firware con esa posibilidad)
2) La placa madre debe tener un conector de 3 pines que permita este evento.
3) Un cable que vaya desde la tarjeta hasta la placa madre.
En ambos casos se debe activar en la BIOS el mantenimiento de energía y posteriormente el evento WAKE ON LAN.

En mi portatil no puedo probar esta característica (cuando se apaga este, la tarjeta ethernet incorporada también se apaga). En el ordenador de sobremesa no me ha funcionado (tampoco funcionan eventos como el de encender el ordenador con una pulsación del teclado) y con el servidor me ha funcionado perfectamente.

El Magic Packet también se puede hacer desde Internet:
Si teneis conexión directa solo debeis modificar vuestro programa para que apunte a vuestra IP pública de Internet (si no es fija podeis usar cosas como dyndns).
Si no teneis conexión directa o no quereis usar un programa, podeis hacerlo desde aquí.
Sin embargo, a no ser que tengais un router que este conectado a Internet y donde podais poner rutas estáticas con IP, puertos y direcciones MAC no podreis hacerlo funcionar, ya que el router (como el mio) borra de la tabla arp las relaciones MAC/IP cuando detecta que no hay tráfico en una tarjeta determinada, por lo que aunque reciba un paquete que luego deba reenviar a una ip interna, lo ignora al no encontrarlo en la tabla; tampoco tiene opción para redireccionarlo como broadcast dentro de la red si no sabe que hacer con el.

Ejecutar un programa sin sistema operativo

Todo pc ejecuta código máquina: Ya sea en el arranque (La bios no es más que código máquina), en la carga del sistema operativo (el kernel esta programado en su mayor parte en código maquina) y en la ejecución de programas (el código fuente compilado o interpretado se transforma de una u otra manera en código máquina). Esta forma de trabajar hace que realmente no sea necesario un sistema operativo para ejecutar aplicaciones (y si me lo poneis dificil, hasta tampoco haría falta la bios). Es por ello que hay aplicaciones como los gestores de arraque (lilo, grub, nt loader), virus, etc que no necesitan de un sistema operativo para funcionar.

Siguiendo este camino, cualquiera podría crear una aplicación que, manteniendola y añadiendola nuevas funcionalidades, podría convertirse en el kernel que Linus Torvalds desarrolló de minix y que posteriormente se transformaría en linux.

Mi intención esta lejos de desarrollar un sistema operativo propio… aún :-), sin embargo a continuación pongo una aplicación, que ejecutada desde un disquete nada más arrancar el pc, muestra un menú y realiza operaciones básicas (chorras). Necesitareis un disquete ya formateado, el programa debug del msdos (por defecto en todos los windows) y que como primera unidad de arranque del pc sea la disquetera (próximamente hablaremos de como pasarlo a un cd mediante el estandar «el torito»). Para los linuxeros de pc, próximamente pondré algo parecido al rawrite. Las instrucciones para hacerlo funcionar son las siguientes:

1-cargad una consola msdos (en windows 9x: inicio/ejecutar/command, en windows nt,2000 o xp: inicio/ejecutar/cmd)

2-Insertad un disquete ya formateado en la disquetera y que no tenga nada importante (ya que perdereis toda la información que contuviera)

3-copiad el siguiente texto a un fichero de texto en vuestro disco duro (dejad al final un retorno de carro), por ejemplo codigo.txt:

a
jmp 1f7
db ‘Seleccione una opcion del menu’
db ‘1- Mostrar hora’
db ‘2- Coche Fantastico’
db ‘3- Salir’
db ‘Desarrollado por Oscar Rodriguez http://sistemasorp.blogspot.com’
db ’00:00:00′
db ‘Fijese en las luces del teclado’
db ‘Retire el disco o cd de la unidad de arranque y pulse una tecla’
cli
xor ax,ax
mov ss,ax
mov sp,7c00
mov es,ax
mov ds,ax
sti
mov ah,0
mov dl,0
int 13h
mov ax,201
mov bx,7e00
mov cx,2
xor dx,dx
int 13h
mov ax,3
int 10h
mov ax,1001
mov bh,1
int 10h
mov ax,1300
mov bx,2
mov cx,1e
mov dx,0119
mov bp,7c03
int 10h
mov ax,1300
mov bx,2
mov cx,0f
mov dx,0519
mov bp,7c21
int 10h
mov ax,1300
mov bx,2
mov cx,13
mov dx,0619
mov bp,7c30
int 10h
mov ax,1300
mov bx,2
mov cx,8
mov dx,0719
mov bp,7c43
int 10h
mov ax,1300
mov bx,4
mov cx,46
mov dx,1705
mov bp,7c4b
int 10h
mov ah,0
int 16h
push ax
mov ax,700
mov bh,0
mov cx,0900
mov dx,094f
int 10h
pop ax
cmp ah,2
je 29f
cmp ah,3
je 2fd
cmp ah,4
jne 29d
jmp 32f
jmp 278
mov ah,2
int 1ah
push cx
mov bx,7c91
mov al,ch
mov cl,4
shr al,cl
add al,30
mov [bx],al
inc bx
mov al,ch
and al,0f
add al,30
mov [bx],al
add bx,2
pop cx
mov ch,cl
mov al,ch
mov cl,4
shr al,cl
add al,30
mov [bx],al
inc bx
mov al,ch
and al,0f
add al,30
mov [bx],al
add bx,2
mov al,dh
mov cl,4
shr al,cl
add al,30
mov [bx],al
inc bx
mov al,dh
and al,0f
add al,30
mov [bx],al
mov ax,1300
mov bx,7
mov cx,8
mov dx,0919
mov bp,7c91
int 10h
jmp 278
mov ax,1300
mov bx,7
mov cx,1f
mov dx,0919
mov bp,7c99
int 10h
mov cx,3
mov ah,2
call 346
mov ah,4
call 346
mov ah,1
call 346
mov ah,4
call 346
loop 311
mov ah,0
call 346
jmp 278
mov ax,1300
mov bx,7
mov cx,3f
mov dx,0908
mov bp,7cb8
int 10h
mov ah,0
int 16h
int 19h
push cx
cli
mov al,ed
out 60,al
in al,64
test al,2
loopnz 34c
mov al,ah
out 60,al
sti
mov ah,0
int 1ah
mov bx,dx
add bx,9
mov ah,0
int 1ah
cmp bx,dx
jnz 360
pop cx
ret

w 100 0 0 2
q

4-Ejecutad el siguiente comando: debug < codigo.txt

5-Reiniciad el ordenador con el disquete dentro

Este proceso lo que hace es ejecutar tanto comandos del debug del msdos, como intrucciones en ensamblador. Con esto guardamos en el sector de arranque del disquete (no del disco duro) un programa que se ejecutará nada más reiniciar el ordenador, antes de que se cargue el sistema operativo. Este programa tiene un menú con 3 opciones:
1- Mostrar hora: Muestra la hora actual del sistema.
2- Coche Fantastico: Simula las luces del coche fantástico en los led del teclado
3- Salir: Sale del programa, cuando se retira el disquete carga el sector de arranque del disco duro.

Con este programa se muestra todo lo que que se puede necesitar de un pc:
-interfaz con el usuario de entrada (teclado)
-interfaz con el usuario de salida (monitor)
-lectura de disco (lectura del resto del programa en otro sector)
-gestión de memoria (las cadenas de texto y la pila)
-gestión de dispositivos (luces de teclado)

Las instrucciones del debug son:
a: introducir código en ensamblador.
w 100 0 0 2: escribir el programa en los primeros sectores de arranque del disquete desde la posicion de memoria 100.
q: salir del debug.

No voy a explicar que hace cada cosa en el programa, sin embargo si alguien tiene dudas puede preguntarme que significa cualquier parte del código en ensamblador. A grosso modo usa las funciones de la bios para poder funcionar: la interrupción 10h la uso para mostrar cadenas, la interrupción 13h para leer un segundo sector del disquete, la interrupción 16h para leer caracteres pulsados del teclado, la interrupción 19h para reiniciar el sistema sin tener que testearlo todo de nuevo, la interrupción 1ah para hacer retardos y averiguar la hora del sistema. Escribo en el puerto 60 para modificar el estado de los leds del teclado. Su arquitectura se basa en la peculiaridad de la bios de guardar nada más arrancar el primer sector del disquete en la zona de memoria 0000:7C00 y luego enviar la ejecución a ese punto.

El hecho de haber usado la herramienta debug es porque lo tiene todo el mundo en su windows. Sin embargo no esta orientada a usarse para programar sectores de arranque, más bién para editarlos, editar ficheros o crear ficheros ejecutables con extensión .COM; por este último motivo he tenido que ir jugando con los saltos relativos a pelo, es decir, como los programas en debug empiezan en el desplazamiento 100h de la memoria (típico de los ficheros .COM) he estado poniendo los destinos de los saltos en base a esa posición 100h, por lo que cuando he necesitado modificar una instrucción, he tenido que cambiarlos también. Por suerte al ser saltos relativos (e internamente el debug los convierte así) no influye en el resultado final.

Por último si teneis curiosidad por el mundo del pc y sus interioridades, saber como es el proceso de arranque del pc, cambiar las luces del teclado y muchísimo más, teneis el maravilloso y gratuito libro EL UNIVERSO DIGITAL DEL IBM PC, AT Y PS/2 de Ciriaco García de Celis, el cual explica con mucho detalle las tripas de los pcs.

Gateway SMS/EMAIL/SMS

Bueno, pues hoy voy a enseñar un pequeño proyecto el cual ya hace tiempo que había terminado, pero que hoy doy a la luz pública (en fase beta) para que lo probeis a ver que os parece.

La idea de hacer un gateway sms2email y email2sms hacía tiempo que me rondaba la cabeza. Mi idéa era hacerlo bajo linux, ya que es el mejor sistema operativo que puede hacer de servidor y para este caso en concreto necesitaba un servidor POP3 y SMTP. Segundo necesitaba un aparato que enviase y recibiese sms, por lo que aproveché mi antiguo Siemens M35 y un cable de datos que ya tenía anteriormente para que hiciese las veces de servidor sms. Tercero necesitaba el software que gestionase los sms y los correos, por lo que para el primer caso usé la estupenda herramienta SMS server tools cuyo funcionamiento se reduce a guardar en un directorio un archivo con formato por cada sms nuevo del móvil, y enviar un sms por cada archivo con formato que encuentre en otro directorio; para el segundo caso he usado el perl con las librerias Net::POP3, Net::SMTP, MIME::Parser, MIME::Entity y MIME::Body.

El resultado final es el siguiente que os explico:

Para enviar un correo y que se transforme en sms:
-En el destinatario del correo poneis sms@sistemasorp.com
-En el asunto del correo poneis SOLO el número de teléfono con prefijo 34 o sin el (no acepta mensajes a móviles que no sean de España).
-En la primera línea del mensaje poneis el texto que querais siendo menor de 140 carácteres.

Para enviar un sms y que se transforme en mail:
-Poner la dirección de correo electrónico seguido de un espacio y el texto del mensaje.
-Enviadlo al número de móvil 699744630. Esto os costará lo que vuestro proveedor de telefonía móvil os cobre por un sms normal y corriente (normalmente 15 céntimos de euro).

En el caso de que sea mi sistema el que envíe el sms después de recibir un correo, me costará 15 céntimos de euro, aunque como estoy probando el sistema y el sim que tengo es de los que tienen dinero aún acumulado por la promoción de compra de un nuevo móvil, no me importa que se gaste. Más adelante lo pondré con contraseña para que solo yo o la gente que decida puedan usarlo.

El código fuente en perl no esta aún comentado, aunque si quereis una copia, podeis pedirmela sin problemas.

Los mensajes sms pueden recibirse o enviarse inmediatamente, tardiamente o nunca, eso ya depende de los proveedores de telecomunicaciones, de vuestro servidor de smtp tenga la última ip de mi dominioa través del DNS que use, etc.