17 enero 2011

Hacking Roomba!

Para quien no lo conozca, Roomba es un modelo de las aspiradoras inteligentes de iRobot. Este tipo de dispositivos pretenden, a un coste bastante elevado, todo hay que decirlo, hacer la vida más cómoda al propietario, librándole de pasar la aspiradora manualmente.

No sé realmente si la razón de que estuviera detrás de una Roomba, era el mantener la casa limpia o el poder "meterle mano a la chacha" (en el buen sentido de la palabra, al ser un robot).

Así pues, y tras leer el libro "Hacking Roomba" (muchas gracias por el ejemplar a Raúl) me dije que esto, simplemente había que probarlo y si no, a las malas, tendría la casa más limpia.

Así pues encargué el modelo 555, que permite programación manual utilizando una botonera en el propio aparato. Lo primero que pensé: "Esto lo programaré en remoto, sin agacharme!"

El objetivo principal era poder decirle a la Roomba: "Ponte a aspirar AHORA" o "Vete a tu base de carga YA!", desde el servidor de casa, controlando vía cron o de forma manual esas operaciones a voluntad.

Así pues, para hacer frente al problema se me pasaron por la cabeza varias opciones. Existe un mando a distancia por Radiofrecuencia que permite ejecutar las mismas operaciones desde cualquier parte de la casa, en la que tengas el mando. Sin embargo, no es compatible más que con el modelo superior: el 581. La siguiente alternativa era utilizar un mando a distancia compatible con todas las roombas. En este caso, funciona mediante Infrarrojos. por lo que podría hacer un cable al puerto serie con un diodo IR y mediante LIRC, grabar la ejecución de cada operación y reproducirla después. Sin embargo, para poder controlar la roomba en toda su inmensidad, la opción más interesante, potente y versátil era utilizar un interfaz bluetooth.

Para los que como yo, no seais muy manitas con el soldador y  los cables, en Sparkfun, venden interfaces bluetooth ya hechos, llamados Rootooth que son "más o menos" plug & play….

Para meterle mano a la Roomba via Bluetooth, esto es lo que debéis hacer:

  1. Enchufar el dispositivo bluetooth a la Roomba. Consejo: sujetad con cinta aislante el cable y el conector, porque dado el movimiento de la roomba, puede sufrir daños. Al principio lo tenía como la foto que se puede ver en el avatar del post.
  2. En mi caso he utilizado Linux con un adaptador Bluetooth para poder conectarnos al Rootooth.  Mediante hcitool buscamos el nuevo dispositivo Bluetooth y nos apuntamos la MAC.
[root@Carmen ~]#  hcitool scan 
Scanning ...
    00:06:66:ZZ:XX:YY    FireFly-XXYY

3.-) Probamos a establecer una conexión mediante "rfcomm" que, una vez hecha la conexión, nos dejará un puerto en /dev/rfcommN al cuál podremos hablar como si de un puerto serie se tratara.

[root@Carmen ~]# rfcomm connect 2 00:06:66:ZZ:XX:YY
Connected /dev/rfcomm2 to 00:06:66:ZZ:XX:YY on channel 1
Press CTRL-C for hangup

4.-) Lo siguiente es comprobar que el modem que incluye Rootooth funciona correctamente a 115200 bps, para no tener errores en la comunicación. Para ello accedemos mediante "minicom" y comprobamos que todo está correcto:

Welcome to minicom 2.00.0


OPCIONES: History Buffer, F-key Macros, Search History Buffer, I18n
Compilado en Feb 21 2005, 19:32:30.


Presione CTRL-A Z para obtener ayuda sobre teclas especiales
                                                  
CMD                                               
?                                                 
***Settings***                                    
BTA=000666ZZXXYY                                  
BTName=FireFly-XXYY
Baudrt=115K
Parity=None
Mode  =Slav
Authen=0
Encryp=0
PinCod=1234
Bonded=0
Rem=NONE SET
END

Una vez que conecta, enviamos los caracteres "$$$"(3 símbolos del dólar, sin las comillas) para entrar en modo Comando al modem Bluetooth. Nos contestará con CMD si todo es correcto. Pulsando D y Enter, nos dará la info que se puede ver más arriba. Importante que esté a 115K, y Parity None. Si algo no está como debe, con la tecla H se accede a la ayuda y se configura para que quede así.
Una vez todo está correcto, pulsamos "---" (tres guiones seguidos, sin comillas) y devolverá END… Ya estamos fuera del modo command.

5.-) Después de probar diversos programas (RoombaCom, Roomba-tilt.pl, Roomba Status) rebuscando en Internet, que prometían controlar la Roomba en remoto, y ver que estaban todos obsoletos, decidí buscar documentación actualizada de la API de la Roomba para poder hablarle.

El documento actualizado para las especificaciones Open Interface de la serie 500 se puede descargar de aquí.

6.-) Manos a la obra… Bajo estas líneas pongo un script (por supuesto en Perl) que recibe como parámetro "clean" o "dock" y hacen que la roomba se ponga a limpiar o se ponga en modo Dock (o, ir a su base de carga)

Incluyo además el código necesario para que cada vez que lo ejecutemos, cree una conexión nueva contra Rootooth, no teniendo que mantener el rfcomm abierto todo el tiempo.

[root@Carmen tmp]# more /usr/local/bin/roomba.pl 
#!/usr/bin/perl

use IPC::Open2;

$port="/dev/rfcomm2"; #el puerto serie a crear. Importante que no esté siendo usado ya
my $param=lc ($ARGV[0]); #capturo parámetro introducido y lo paso a minúsculas
my $rfcomm="rfcomm connect 2 00:06:66:ZZ:XX:YY"; #comando rfcomm para crear puerto

my $value;

if ($param eq "clean")
{#Si la orden es limpiar
    $value=135;    
}
elsif ($param eq "dock")
{#Si la orden es ir a base
    $value=143;
}
else
{#El resto no está aceptado
    die "$0 [CLEAN|DOCK]\n"; 
}

my $pid=open2 (\*READ,\*WRITE,$rfcomm); #lanzamos por un lado la conexión

sleep (10); #Le damos 10 segundos para que se establezca

system("stty -F $port 115200 raw -parenb -parodd cs8 -hupcl -cstopb clocal"); #Parámetros necesarios para configuración del puerto
    
my $roomba;
open $roomba, "+>$port" or die "couldn't open port: $!"; #Abrimos conexión al puerto
select $roomba; $| =1;  #Eliminamos lo que hubiera en el buffer en la lectura
    
printf $roomba "%c",128;  sleep 0.3;                    # START Necesario cada vez que le demos una orden a Roomba
printf $roomba "%c",132;  sleep 1;                    # FULL Tomamos control completo sobre ella

printf $roomba "%c",$value;  sleep 1;                    # CLEAN OR DOCK  Ejecutamos lo ordenado

kill 9,$pid; #Matamos el proceso de rfcomm

exit (0); #bye bye

Pero claro, la idea (al menos la mía) es hacer un programa que dependiendo de un montón de factores como qué horario es aceptable para pasar la aspiradora, control de presencia en casa (si estoy en casa, no la pases,… no sabéis el ruido que mete!), etc, etc,… puede ser interesante obtener información sobre los sensores de la misma. En mi caso, me interesa saber: La capacidad máxima de la batería; el modo de carga (esperando, cargando, etc,..), la carga actual de la batería, la temperatura de la batería, y si está conectada al cargador correctamente o no (si está en su base de carga o está dando vueltas por ahí). Para ello, el código se puede ver bajo estas líneas. Importante: en este caso contamos con una conexión rfcomm ya hecha en otro terminal!

[root@Carmen tmp]# more roomba_sensors.pl 
#!/usr/bin/perl

$port="/dev/rfcomm2";  #el puerto serie a crear. Importante que no esté siendo usado ya

system("stty -F $port 115200 raw -parenb -parodd cs8 -hupcl -cstopb clocal");  #Parámetros necesarios para configuración del puerto
    
my $roomba;

open $roomba, "+>$port" or die "couldn't open port: $!";
select $roomba; $| =1;   #Eliminamos lo que hubiera en el buffer en la lectura
    
printf $roomba "%c",128;  sleep 1;                    # START Necesario cada vez que le demos una orden a Roomba


printf $roomba "%c%c%c%c%c%c%c",149,5,21,25,26,34,24;  sleep 1; # Roomba requiere el envío del opcode 149 + el número de sensorIDs a solicitar + cada sensorID

#Sin embargo, devuelve byte a byte. Con esto perdí muuuucho tiempo porque no lo ví documentado en ningún sitio!!!
for ($i=0; $i<7; $i++) 
{
    $k=getc($roomba);
    $ok=ord ($k);
    print STDOUT "$i $ok\n";
}

Al ejecutarlo vemos algo como:

----------
0 2
1 1
2 108
3 10
4 136
5 2
6 40
------

La primera columna es un contador, sin más y la segunda, el valor del byte devuelto por la Roomba.

Byte        Explicación


0       Estado de carga: 4 significa que está en Waiting (aunque la pongamos en su base, no cargará)
         y 2 es Full charge (que lo podemos poner a cargar)
1       Byte más significativo de carga actual de batería
2       Byte menos significativo de carga actual de batería
3       Byte más significativo de capacidad total de batería
4       Byte menos significativo de capacidad total de batería
5       Presencia de cargador (Fundamentalmente, si está la roomba en su base o no) Si el valor es 0 es
         que no (está por ahí limpiando) y 2 es que está en la base
6       Temperatura en grados celsius de la batería (Interesante por si queremos monitorizarlo)


Los bytes 1 y 2, así como el 3 y 4 indican la carga actual y la capacidad máxima de carga de la batería. El byte más significativo, en mi caso va de 0 a 10 y el menos significativo va de 0 a 255 (lógicamente es lo que cabe en un byte). Cuando se está descargando la batería, los bytes 1 y 2 van disminuyendo y al cargarse aumentando, hasta llegar a 10/136 que es la carga máxima de la batería.

Conclusiones

Roomba no sé si me hará la vida más fácil o no, pero me lo he pasado bomba sacándole las tripas e intentandole hablar y que me conteste. No he encontrado foros en España (o al menos en español) en los que se haga hacking de este tipo a Roomba. Lo más aproximado ha sido en los foros.zackyfiles.com en los que fundamentalmente, se hace hacking físico a los equipos para que aspiren mejor, y hacerles cierto tunning. Los que quieran ir más allá, pueden contar con este foro en inglés  en el que hay gente con estas mismas inquietudes y en el que abrí un hilo pidiendo ayuda en mis problemas de comunicación con mi Roomba.
Para aquellos que tengáis un cacharro de estos y queráis meterle mano, os animo desde aquí a ello. Si os ponéis y se os atasca la situación, contad conmigo para ayudaros en todo lo que sea posible!

Por cierto, que después de tanta confianza que tengo con la Roomba, le he preguntado cuál es su blog de seguridad y hacking favorito y... bueno en la foto siguiente podéis ver cuál fue su respuesta :D

19 comments :

Madrikeka dijo...

Que cracks!!

Es increíble, cualquier cosa programabl tenés que hackearla....
estáis seguros de que eso es bueno?!

Cuando puedas comenta que tal limpia, por que lo mismo, auqneu sea un poco carete, merece la pena y aadiós! aspiradora!

Un saludo.

NecronoiD dijo...

Gran articulo!! me estan entrando ganas de pillarme la roomba :)

Adama dijo...

Lo acabo de flipar. :)

Por curiosidad... ¿Cuánto tiempo has dedicado a hacer el hack?

Lo que me ha hecho más gracia es que después de todo el curro que te has dado, "la roomba te hace la vida más fácil". :)

Por lo que entiendo a la aspiradora no le haces ninguna modificación física ¿no? ¿tiene un puerto serie o lo he entendido mal?

Gran artículo!

Alejandro dijo...

No tenía ni idea que se pudiera hacer este tipo de cosas con el aparato. Llevo un tiempo con el dichoso aparato en mente... ¿lo recomiendas o no? Ahora hay uno que friega y para gente tan floja como yo creo que merece la pena.

Un saludo.

Tonio dijo...

Joer, el que vale, vale. Yo tengo un invento de estos desde hace unos meses pero jamas se me ocurrio meterle mano. Y menos mal porque no sé yo si a mi novia le gustaría mucho. :-D

Lorenzo Martínez dijo...

Gracias a todos por vuestros comentarios:

@Madrikeka -> Si algo viene programado, se podrá reprogramar, lo interesante es saber cómo hacerlo :D

@Adama -> La verdad es la Roomba la tengo desde hace unos 15 días. La probé a nivel usuario, programándola con el scheduler que trae etc,.. y estuve pensando en cómo acceder a ella (RF, infrarrojos, etc,...). Hasta llegar a bluetooth. Perdí mucho tiempo intentando hacer funcionar programas que encontré en Internet válidos para generaciones antiguas de Roomba,... y sobre todo casi desisto en la comunicación de la información de sensores de Roomba (batería, carga, etc,..). Logré que limpiara y volviera al dock con relativa rapidez, pero la forma de devolver la información por parte de Roomba, me hizo probar en Perl y en C, con idénticos malos resultados, hasta que se me ocurrió recoger byte a byte e interpretar los resultados. No sabría poner cuanto tiempo, porque se me ha pasado volando :D
Al cacharro le conectas por un conector PS2 un dispositivo llamado Rootooth, que no es más que un interfaz bluetooth, a través del cual le hablas,...
Modificaciones físicas le he hecho un par de ellas que vi en el foro de zackyfiles.

A tod@s: Yo recomendaría sin pensarlo este tipo de electrodoméstico. Aunque elegir modelo puede ser complicado, al menos el que tengo yo, da buen resultado, y supongo que tendré que pasar la aspiradora de verdad, con una frecuencia menor que antes.
El que friega (Scooba) no he tenido la oportunidad de probarlo, así que no puedo dar ningún tipo de recomendación al respecto....

SiD dijo...

El que diga que la pereza no hace avanzar a la humanidad :)

Un artículo cojonudo y muy práctico.

Muchas gracias por compartir.

Anónimo dijo...

me viene que ni al pelo este post, mañana me llega mi roomba 555 y ya probare a trastearla.

un saludo.

Drk dijo...

Genial artículo!! ;)

Anónimo dijo...

Busca en google: IRobot_Roomba_500_Open_Interface_Spec.pdf

Ahí viene "las órdenes" que admite el robotito y lo que responde ;)

Por cierto, te he conocido desde el foro roomba http://foros.zackyfiles.com/showthread.php?p=4180177#post4180177


Saludos

Lorenzo Martínez dijo...

@SID + @DRK -> Muchas gracias por vuestros elogios...

@Anónimo (último) -> En el post referencio el documento que indicas tú para buscas las órdenes que la Roomba es capaz de entender. Este es el enlace de donde lo bajé yo -> http://www.irobot.lv/uploaded_files/File/iRobot_Roomba_500_Open_Interface_Spec.pdf

RuBiCK dijo...

Muy buen artículo!

Tengo el mismo modelo de roomba desde este verano y ahora que estoy empezando a trastear con arduino se me está ocurriendo ponerle la fonera a la chepa de la roomba y así ahorrarme la pastaza que vale el bluetooth desde luego las posibilidades son infinitas, como poner una webcam o unas cervezas y que te las traiga jijiji

T31m0 dijo...

Tengo leido tus posts ...

Man eres el puto amo ... ;)

Seguire por aki ...

Mui Bueno (todo hackeable)

Ivan dijo...

Fantastico articulo. ¿Sabes si es aplicable a un Roomba 580?

Lorenzo_Martinez dijo...

Una 581? estoy seguro que se puede hacer! Si te animas y tienes alguna duda/problema, estoy a tu disposición...

Crespell dijo...

felicidades, estoy muy agradecido de la informacion, pero mi gran duda es si se posible que al programar una maquina roomba ejemplo 555 hay allguna manera de que diga los numeros, ya que tengo un amigo invidente, y me encantaria poder hacer el regalo de poder programar la roomba.

Lorenzo_Martinez dijo...

Hola Crespell, entiendo que te refieres a programar la 555 mediante voz en vez de la botonera integrada que trae, ¿verdad? Si es así, desafortunadamente no se puede. Sin embargo, si piensas en hacer las modificaciones que hice yo, podrías hacer, utilizando software de reconocimiento de voz, que un programa hecho por tí insertara la programación en una base de datos o un fichero y a partir de ahí, que otro programa lea de ahí y haga funcionar la Roomba a las horas programadas

jose dijo...

Hola conoces algun manual,foro o pagina web que expliquen como poder incorporar el kinect al roomba?

xmcarne dijo...

Hola Lorenzo,


Viendo tu hacking te doy toda la razón respecto al tema que en españa no hay mucho sobre esto. Hace un año largo hice una plaquita Wi-Fi para controlarlo desde el iPad i ahora la utilizan para hablar con aplicaciones puramente software para controlar los robots. Sólo quería pasarte un link que tiene que ver con lo que comentas pero en este caso haciendo que sea mediante Wi-Fi sin tener que programar ni baudrate ni nada de eso, te dejo el link de la web en inglés dónde podrás ver más información (la tengo más actualizada) que hay videos y tal y bueno me lanzé a venderla y la gente parece contenta. Espero que no creas que es Spam pues sólo quería pásartelo para que lo veas (si no quieres no lo publiques). http://www.roowifi.com o en español http://es.roomba-wifi-remote.com.


Un saludo y felicidades por el blog :)
Xavi