Ejemplo Python + GTK

En este artículo encontrareis un ejemplo muy sencillo de cómo desarrollar una aplicación que comunica con vuestro Roomba Wi-Fi Remote basado en un simple script desarrollado en Python usando GTK para vuestra distribución Linux preferida. En el caso de este ejemplo se ha desarrollado en un sistema con Ubuntu Desktop 12.04 de 32 bits aunque con la instalación de los paquetes necesarios para vuestra distribución desde el repositorio que os toque, no deberíais tener problemas siempre que utilicéis el entorno Gnome (que si no recuerdo mal es el que tiene Ubuntu por defecto). Si os descargáis el archivo comprimido que está al final de este articulo (está en formato ZIP por si alguien hace sus scripts Python sobre Linux), veréis que se trata de un ejemplo sin demasiado código pues si ya habéis leído sobre el modo transparente del Roomba Wi-Fi Remote, se trata de conectarse al Servidor TCP/IP del dispositivo por el puerto TCP 9001 y enviar y recibir información como si estuvieses conectados al robot por el canal serie de vuestro PC.

Somos conscientes que con una API o una clase escrita en Python vosotros ya os espabilaríais a desarrollar el resto, por eso estamos tratando de realizarla a la vez que ultimamos la segunda versión de este embebido y no dudamos que en breve las tendréis colgadas junto a otras opciones para otros entornos de programación para lenguajes como xcode (iOS), java (Android y PC) o C# (Windows).

Dicho esto ataquemos el primer ejemplo oficial de Roomba Wi-Fi Remote ;)

Contenido de la descarga

Si os descargáis el archivo que hay al final de este artículo, veréis que se trata de un archivo comprimido con algunas imágenes y dos archivos que son realmente los importantes: RoombaWifiRemote y RoombaWifiRemote.py:

RoombaWifiRemote

Script que lo único que permite es ejecutar el script Python directamente desde el Nautilus de Ubuntu o el navegador de archivos de vuestro entorno gráfico de la distribución Linux que tengáis instalada. Por este motivo lo único que contiene este script es lo siguiente:

#!/bin/bash
python RoombaWifiRemote.py

RoombaWifiRemote.py

Este es el archivo .py que contiene el código del script que lanza la User Interface, permite al usuario insertar la dirección IP del Roomba Wi-Fi Remote y comunicarse con el robot para, en este ejemplo, realizar desde nuestro ordenador de escritorio o portátil la acción equivalente a presionar los botones o conocer el estado de carga del robot.

Para la creación de la User Interface se usan las librerías GTK que permiten realizar form o ventanas de diálogo de forma muy rápida desde código y que está preparado para Gnome de Ubuntu. Hemos escogido esta interface y no la Qt u otra dado que la distribución más extendida actualmente es Ubuntu y es la que lleva por defecto y en caso de no ser desarrollador poder dar una pequeña aplicación para controlar el robot al usuario básico y medio de Linux.

La estructura del código es bastante sencilla pues sólo se declaran un par de constantes al inicio del código que coinciden con los comandos SCI del robot que permite la aplicación y una clase llamada RoombaWifiRemoteGUI que es la que contiene básicamente las funciones de envío de información mediante un socket tcp/ip, el propio socket TCP/IP y toda la GUI. De esta manera lo único que tiene el “main” del script es básicamente una llamada al constructor de esta clase.

Las librerías que se usan en el script son:

import socket #Para trabajar a nivel de socket tcp/ip
import pygtk #Para trabajar con Python y GUI Gtk
pygtk.require('2.0')
import gtk
import operator
import time #Para trabajar con funciones relacionadas con tiempo como time.sleep(x)
import string #Para trabajar con strings (actualización del estado de la batería en la GUI)

Funciones de la clase RoombaWifiRemoteGUI

Tal y como se ha estructurado el código, que seguro que se puede hacer mejor, a cada botón se le ha asignado una función de la propia clase que ejecuta un envío de datos por el socket TCP/IP que incorpora esta clase. Hemos preferido realizar la conexión al principio y que los botones de CLEAN, SPOT o DOCK se limiten a enviar información por el socket. Para no tener problemas hemos introducido este código en el constructor de la clase principal de manera que los botones encargados de Desconectarse del Roomba Wifi Remote, refrescar el estado de la batería o los botones virtuales estén deshabilitados por defecto y sólo se habiliten cuando se esté conectado al dispositivo. Notad que hemos enviado carácter a carácter para que quede más claro que se está mandando, evidentemente no es la mejor opción.

def ConnectWithRoomba(self, widget, data=None):
   print("Connect Button Pressed")
   try:
      self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      self.remote_ip = (self.TextIP.get_text())
      self.s.connect((self.remote_ip , self.port))
      self.s.send(chr(FULL_MODE_COMMAND))
      time.sleep(1)
      self.s.send(chr(LED_COMMAND))
      self.s.send(chr(25))
      self.s.send(chr(255))
      self.s.send(chr(128))	    
      #Peticion del estado de la bateria
      self.s.send(chr(SENSOR_COMMAND))
      self.s.send(chr(SENSOR_PACKET_0))
      time.sleep(1)
      data = self.s.recv(NUM_BYTES_PACKET_0)
      aux1 = 100*(ord(data[22])*256+ord(data[23]))
      aux2 = ord(data[24])*256+ord(data[25])
      self.label.set_label ("Battery: " + str(aux1/aux2) + "%")
      widget.set_sensitive(False)
      self.button_Disconnection.set_sensitive(True)
      self.button_Clean.set_sensitive(True)
      self.button_Spot.set_sensitive(True)
      self.button_Dock.set_sensitive(True)
      self.button_Refresh.set_sensitive(True)
   except:
      self.label.set_label ("CAN'T CONNECT")

Probamos de conectar con el robot, esta función se llama sólo cuando se pulsa el botón de conexión. A modo de ejemplo sabemos que sirve, aunque somos conscientes que haría falta verificar si el texto introducido por el usuario es una dirección IP o un Host válido para conectarse así como también realizar la conexión de forma asíncrona para no dejar bloqueado al programa.

Una vez realizada la conexión con el robot mandamos un comando que nos da control total (modo full) del robot y encendemos los leds rojos y el azul del robot a tope para identificar visualmente que estamos conectados mediante Roomba Wifi Remote. Para acabar hacemos una lectura de todos los sensores pero nos quedamos únicamente con los bytes con los cuáles podemos obtener el porcentaje de batería restante.

Las funciones que contienen el simple comando de limpiar, limpiar a fondo y volver a base:

#Emular Boton Clean del Robot
def CleanRoomba(self, widget,  data=None):
	self.s.send(chr(CLEAN_COMMAND))	

#Emular Boton Spot del Robot
def SpotRoomba(self, widget,  data=None):
	self.s.send(chr(SPOT_COMMAND))	

#Emular Boton Dock del Robot
def DockRoomba(self, widget,  data=None):
	self.s.send(chr(DOCK_COMMAND))

La función que cierra el socket:

#Desconectar de Roomba Wi-Fi Remote
def DisconnectWithRoomba(self, widget,  data=None):
	widget.set_sensitive(False)
	self.button_Connection.set_sensitive(True)
	self.button_Clean.set_sensitive(False)
	self.button_Spot.set_sensitive(False)
	self.button_Dock.set_sensitive(False)
	self.button_Refresh.set_sensitive(False)
	print("Disconnect Button Pressed")
	self.s.close()

Para acabar la función que lee el estado de la batería como en el caso de la conexión (lo sabemos: muy mal por no aprovechar código, no pidáis milagros en 3-4 minutos aún así nos disculpamos)

#Refresco de la carga de bateria
def RefreshRoomba(self, widget, data=None):
	self.s.send(chr(SENSOR_COMMAND))
	self.s.send(chr(SENSOR_PACKET_0))
	time.sleep(1)
	data = self.s.recv(NUM_BYTES_PACKET_0)
	aux1 = 100*(ord(data[22])*256+ord(data[23]))
	aux2 = ord(data[24])*256+ord(data[25])
	self.label.set_label ("Battery: " + str(aux1/aux2) + "%")

Requisitos

Para poder ejecutar el script desde vuestro Sistema Ubuntu, tened en cuenta que debéis tener instalados los siguientes paquetes descargables desde el repositorio de Ubuntu:

  • gtk
  • python

Para tener estos componentes actualizados no olvidéis realizar lo siguiente en caso que ya los tengáis instalados:

  • sudo apt-get update
  • sudo apt-get upgrade

Descarga

Descargar RoombaWifiRemotePythonGTK

Captura del script en ejecución

Ubuntu Python GTK Roomba Wifi Remote Ejemplo

Ubuntu Python GTK Roomba Wifi Remote Ejemplo

Tagged with: , , ,
Posted in Desarrolladores, Ejemplos