Los números de 2014 (re-despedida)

Recuerden que ahora estamos en fernand0.github.io.

.

Los duendes de las estadísticas de WordPress.com prepararon un informe sobre el año 2014 de este blog.

Aquí hay un extracto:

Un teleférico de San Francisco puede contener 60 personas. Este blog fue visto por 2.600 veces en 2014. Si el blog fue un teleférico, se necesitarían alrededor de 43 viajes para llevar tantas personas.

Haz click para ver el reporte completo.

Anuncios

Fin de la tercera etapa

Esta bitácora empezó en el año 2009 como continuación de otras previas, como contábamos en Tercera Etapa. Por algún motivo nunca he terminado de sentirme confortable aquí.
Es tiempo de hacer pruebas nuevas y nos movemos a otro lugar. Copio aquí el post que lo explica en mi nuevo sitio, Cuarta etapa:

Repito aquí una historia ya contada unas cuantas veces, a la que le vamos añadiendo matices y novedades.

Copio de Tercera Etapa:


Esta bitácora nació allá por el 2001 en forma de [MiBarrapunto](http://barrapunto.com/articles/01/04/23/2033238.shtml): se trataba de un invento que hicieron los creadores de [BarraPunto](http://www.barrapunto.com/) para permitir a los usuarios tener su propia sección con algunas ideas que ya me gustaría ver en alguna plataforma ahora, pero que no cuajaron por problemas de escalabilidad del programa y falta de recursos en aquel momento para mejorarlo (destacable, la promiscuidad absoluta: cualquiera podía tomar una entrada cualquiera del sitio -en particular, de otros usuarios- y reformarla o simplemente republicarla en su propia página).

Parte de esas ideas se han establecido en [GitHub](http://github.com/), donde el código puede copiarse, transformarse y reenviarse al autor original o a otros con herramientas bastante accesibles.

Con ese espíritu empecé a subir los contenidos de algunos de mis sitios a GitHub: Archivo bitácoras fernando para posteriormente descubrir que GitHub permitía publicar Páginas personales y para los proyectos y el sistema que las gestiona, Jekyll, que también permite gestionar un blog: nuestra página estaría albergada en el sistema con las mismas características de gestión del código fuente de los programas: fork permitido, copiar, pegar, modificar y reutilizar. Todavía no es tan fácil como era en la época de BarraPunto, pero aquí lo tenemos. Y aquí estamos.

No creo que la mayoría de la gente vaya a utilizar esto, y tampoco creo que nadie vaya a reutilizar estos contenidos. Pero siento que encaja bien con mi forma de trabajar y publicar (editar en local, subir al sitio y publicar) así que vamos a probar. Desde este momento, la bitácora anterior queda congelada y seguimos por aquí.

Bienvenidos a la cuarta etapa. Proximamente algo más de información sobre cómo gestionar un sitio aquí e ir resolviendo las carencia que aún tenemos (ya hay RSS, las categorías y las etiquetas no funcionan aún).

Les espero en fernand0.github.io.

Una cámara móvil

Una vez que tenemos un bot que nos permite controlar remotamente nuestro proyecto (Segundo bot: avanzamos) y sabemos mover los motores (Movimiento suave con los servos) llega el momento de montar la cámara encima (Una cámara en la Raspberry Pi) y controlarla remotamente.
Recordemos que el control se hace mediante XMPP (por ejemplo, con programas como Pidgin, Google Talk o nuestro cliente de mensajería favorito); la idea era evitar abrir puertos en el router para controlarlo vía web y, sin embargo, poder enviar instrucciones desde internet sin problemas.

Para el montaje seleccionamos un par de cajas (como forma barata y simple de proporcionar el soporte para todo). En una caja más grande hicimos un par de agujeros (para poder colocar dos motores, aunque finalmente sólo hemos utilizado uno):

Hemos pintado la caja #raspi

A post shared by Fernando Tricas García (@ftricas) on

Dentro de la caja van las conexiones (baterías para alimentar los motores, y cables para controlarlos desde la Raspberry Pi, que se queda fuera de la caja).

Caja como soporte para los motores

A post shared by Fernando Tricas García (@ftricas) on

La cámara se monta en una caja más pequeña que se sujeta al servo seleccionado.

Y tenemos un prototipo de mejor aspecto #raspi

A post shared by Fernando Tricas García (@ftricas) on

Cuando se le da la instrucción de movimiento, la cámara va a la posición elegida, se detiene para hacer la foto y la envía por correo. Finalmente, vuelve a su posición inicial.
Toda la secuencia puede verse en el siguiente vídeo.

El código del proyecto está disponible en err-plugins (puede evolucionar más adelante; el código en su estado actual puede verse en pruebas.py).

Recientemente se publicó un proyecto similar en “Raspberry Eye” Remote Servo Cam. Tiene dos diferencias fundamentales: se han incluido movimientos en dos ejes (nuestro proyecto sólo se mueve a derecha e izquierda) y se controla mediante una página web.

¿Qué haremos a continuación?
Tengo varias ideas, pero no se todavía qué haré: sería interesante que la cámara tuviera cierta autonomía (¿detección de movimiento o cambios en la escena?); tampoco me importaría pensar en movilidad real (¿embarcar la cámara en algún tipo de dispositivo con ruedas? me encantó este hexápodo).
Yendo más allá, tal vez podríamos pensar en otros dispositivos de control (¿wearables?).

Por supuesto, ideas, comentarios, sugerencias… Serán bienvenidos.

Movimiento suave con los servos

Uno de los problemas que tienen los servos es que su movimiento es bastante brusco, como podía apreciarse en el vídeo que pusimos en Añadiendo movimiento: servos. Con el montaje que había pensado eso era un problema, porque la cámara tiene un cierto peso y en alguna ocasión podía salir disparada, o desencajarse, como puede imaginarse viendo:

Más pruebas #frikeando #voz #motores #raspi #c3po

A post shared by Fernando Tricas García (@ftricas) on

La solución para el problema es relativamente sencilla: cuando queremos llevar el motor a una determinada posición podemos ir haciéndolo con pequeños pasos. La idea es indicarle una sucesión de posiciones cada vez más próxima al objetivo. Así, aunque los movimientos son bruscos, al ser pasos cortos no afectan tanto al objeto que va montado sobre el motor (en este caso la cámara).
El código podría ser como el de esta función:

def move(self, servo, pos, posIni=MIN, inc=10):

	servoGPIO=18
	servoGPIO=17
	posFin=posIni + (MAX-MIN)*pos
	steps=abs(posFin - posIni) / inc

	print "Pos ini", posIni
	print "Pos fin", posFin
	print "Steps", steps
	print int(steps)

	if pos < 0:
		pos = -pos
		sign = -1
	else:
		sign = 1

	for i in range(int(steps)):
		servo.set_servo(servoGPIO,posIni+10*i*sign)
		time.sleep(VEL)

	print "Pos ini", posIni
	print "Pos fin", posFin
	print "Steps", steps
	print int(steps)

	servo.stop_servo(servoGPIO)

Esto es, suponiendo que partimos de una posición inicial (posIni) y que queremos movernos un cierto porcentaje (un número real entre 0 y 1) calculamos la posición final sabiendo el recorrido total (MAX-MIN):

posFin=posIni + (MAX-MIN)*pos

Y calculamos el número de pasos que daremos basándonos en un incrementos de 10 (inc=10):


steps=abs(posFin - posIni) / inc

Se usa el valor absoluto porque el movimiento puede ser en ambas direcciones (según en qué punto esté el motor), de lo que se ocupa el condicional:


if pos < 0:
...

Finalmente, se hacen los movimientos con el bucle:

for i in range(int(steps)):
	servo.set_servo(servoGPIO,posIni+10*i*sign)
	time.sleep(VEL)

El resultado se parece al que se aprecia en este vídeo:

Montamos la cámara en el motor que se mueve más despacio #raspi

A post shared by Fernando Tricas García (@ftricas) on

Donde se puede observar un movimiento de ida y vuelta con un improvisado modelo. Se puede regular la velocidad con el tiempo que se tarda entre uno de estos pequeños movimientos y el siguiente (parámetro VEL).

Seguramente habría sido mejor elegir otro tipo de motores, pero esto resuelve de manera razonable nuestro problema.

Segundo bot: avanzamos

En Raspberry Pi: ¿qué temperatura hace en mi casa? hablábamos del primer bot que nos permitía interactuar con la Raspberry Pi desde donde nos encontráramos.

Estuve probando SleekXMPP y phenny pero ambos tenían algunas limitaciones así que continué buscando hasta que encontré otro proyecto interesante, err que, además de estar en ese momento con cierta actividad proporciona una arquitectura modular para añadir características e incluso tiene una comunidad en Google+, Err.

Lo primero que hice fue adaptar las pruebas que ya había hecho con phenny a la nueva arquitectura, y añadirle un par de cosas más relacionadas con la toma de fotos y su envío. Puede verse el código del módulo en err-plugins (en el futuro podría cambiar así que nos fijaremos en la versión actual con sus dos ficheros.

El primero es pruebas.plug, que contiene información sobre el módulo en sí, con la sintaxis que define el bot:

[Core]
Name = Pruebas
Module = pruebas

[Documentation]
Description = let’s try things !

Y el fichero pruebas.py que contiene el código en sí. Esencialmente es un fichero con código en Python. Por ejemplo, para que el bot tome una fotografía nos la envíe, sería:

<br />
@botcmd<br />
def foto(self, msg, args):<br />
	&quot;&quot;&quot;Take a picture&quot;&quot;&quot;<br />
	quien=msg.getFrom().getStripped()<br />
	yield &quot;I'm taking the picture, wait a second &quot;<br />
	if(args):<br />
		try:<br />
			cam=int(args)<br />
		except:<br />
			cam=0<br />
	else:<br />
		cam=0<br />
	yield &quot;Camera %s&quot;%cam<br />
	self.camera(&quot;/tmp/imagen.png&quot;,cam)<br />
	yield &quot;Now I'm sending it&quot;<br />
	self.mail(&quot;/tmp/imagen.png&quot;, quien)<br />
	my_msg = &quot;I've sent it to ... %s&quot;%quien<br />
	yield my_msg<br />

Con la primera línea decimos que es una instrucción para el bot y luego definimos una función que es la que se ocupa de las acciones correspondientes. El nombre de la función será la instrucción (con un prefijo configurable, que permite al bot diferenciar entre lo que se le indica a él y lo que son otros textos que no interpretará).

En nuestro caso, la instrucción:

.foto

Ejecutaría una función que es muy parecida a la que comentábamos el otro día en Una cámara en la Raspberry Pi. Las diferencia serían:

  • Recibe los parámetros a través de la llamada a la función

    def foto(self, msg, args):
  • Responde al que le envió la orden:

    quien=msg.getFrom().getStripped()
  • El argumento puede ser 0, 1 o ninguno (no se hace validación) porque tenemos dos cámaras en la Raspberry. Por defecto dispara con la cámara 0.
  • A continuación nos indica qué cámara hemos elegido:

    yield "Camera %s"%cam
  • Invoca a la función que realmente realiza la fotografía, cuyos parámetros son muy similares a los que ya comentamos en su momento (el nombre del fichero donde se almacenará la foto y la cámara elegida):

    self.camera("/tmp/imagen.png",cam)
  • Invoca a la función de envío por correo, cuyos parámetros son el fichero donde está la imagen y a quién se envía el mensaje.

    self.mail("/tmp/imagen.png", quien)
  • Finalmente responde al que dio la orden, nuevamente con yield.

Si miramos el código, la diferencia de estas dos funciones es que no van precedidas con @bootcmd, así que no están disponibles como instrucciones. Por lo demás necesitan (igual que contábamos en su momento) los parámetros de configuración adecuados.

Errbot nos proporciona un mecanimos para eso, mediante:

<br />
def get_configuration_template(self):<br />
return{'ADDRESS' : u'kk@kk.com', 'FROMADD' : u'kk@kk.com',<br />
'TOADDRS' : u'kk@kk.com', 'SUBJECT' : u'Imagen',<br />
'SMTPSRV' : u'smtp.gmail.com:587', 'LOGINID' : u'changeme',<br />
'LOGINPW' : u'changeme'}<br />

Podemos definir en un diccionario los parámetros que podremos configurar (vistos, recuerden en Una cámara en la Raspberry Pi).

Y, tecleando en nuestro cliente de mensajería:

.config Pruebas

En este caso, Pruebas es el nombre del módulo y el punto (.) es el indicador que hemos elegido para las instrucciones. La instrucción config nos devuelve la configuración que el módulo tenga en ese momento (si no está configurado muestra los valores que hemos puesto en la definición; si ya lo hemos configurado mostrará los valores que tenga). Los valores que se devuelven pueden utilizarse como patrón para configurar el módulo:

.config Pruebas {'TOADDRS': u'mydir@mail.com', 'SMTPSRV':
u'smtp.gmail.com:587', 'LOGINPW': u'mypassword',
...
}

Con esto, ya falta menos para hacer el montaje final. Seguiremos
informando.

Enviar una imagen por correo en Python

Una vez que podemos hacer una fotografía con nuestra webcam (Una cámara en la Raspberry Pi) lo siguiente que nos gustaría hacer es verla desde donde estemos.

Hay por ahí muchos textos explicando como hacer un servidor web en el que mirar la imagen capturada por la cámara, pero a mi ese método no me gustaba demasiado: habilitar un servidor web, abrir algunos puertos en el router casero y emplear algún sistema para dar cuenta de las posibles variaciones en la ip me parece poco robusto. Pero también incluye la posibilidad de que alguien pueda terminar conectándose a ese servidor web y acceder a nuestra red de alguna manera (posibilidad remota, seguramente, pero no despreciable).

También estuve evaluando la posibilidad de enviar las imágenes a través del cliente de mensajería pero no se si no es posible, o no he encontrado documentación para hacerlo, así que también lo descarté.

La elección final recayó en el viejo y confiable sistema de correo electrónico: el bot recibe las peticiones como sea (xmpp, IRC, …) y envía las imágenes captadas por correo electrónico.

Hay mucha documentación sobre cómo enviar un mensaje de correo con un adjunto pero yo ya tenía un programita para hacerlo, así que es el que usé. Se puede ver mail.py.

Esencialmente construye un mensaje a partir de sus componentes (Origen, destino, asunto, adjuntos, …).

Necesita unos cuantos parámetros, que hay que configurar para que funcione correctamente. La forma elegida para la configuración es mediante un módulo auxiliar:

import mailConfig


cuyo único contenido son variables cuyos valores han de ser adaptados. Desde nuestro programa simplemente las leemos (aunque podríamos usarlas directamente, claro).

destaddr = mailConfig.ADDRESS
fromaddr = mailConfig.FROMADD
toaddrs = mailConfig.TOADDRS
subject = mailConfig.SUBJECT
smtpsrv = mailConfig.SMTPSRV
loginId = mailConfig.LOGINID
loginPw = mailConfig.LOGINPW

imgFile = '/tmp/imagen.png'


Por defecto fijamos un nombre para la imagen que enviaremos, aunque desde la línea de invocación podríamos elegir otro.

Tenemos una dirección de envío de correos por defecto (destaddr) pero también podemos pasar una desde la línea de instrucciones (poco robusto, no se verifica nada).

A partir de allí, construímos el mensaje.

Detección y configuración del tipo de objeto que envíamos:

format, enc = mimetypes.guess_type(imgFile)
main, sub = format.split('/')
adjunto = MIMEBase(main, sub)


De esta forma, el programa nos serviría para enviar ficheros de distintos tipos y no sólo imágenes.

Generación del adjunto, codificación y se añade al mensaje que estamos construyendo:

adjunto.set_payload(open(imgFile,"rb").read())
Encoders.encode_base64(adjunto)
adjunto.add_header('Content-Disposition', 'attachment; filename="%s"' % imgFile)
mensaje.attach(adjunto)


Y, finalmente, añadimos el resto de parámetros del mensaje:

mensaje['Subject'] = subject
mensaje['From'] = fromaddr
mensaje['To'] = destaddr
mensaje['Cc'] = toaddrs


El mensaje va vacío, no tiene texto (Ejercicio para el lector: ¿le añadimos un texto? Se me ocurre algo así como: ‘Fotografía tomada el día xx-xx-xxxx a las hh:mm’).

Para terminar, hacemosel envío (negociando directamente con el servidor de
correo en envío):

server = smtplib.SMTP()

server.connect(smtpsrv)
server.ehlo()
server.starttls()
server.login(loginId, loginPw)
server.sendmail(fromaddr, [destaddr]+[toaddrs], mensaje.as_string(0))
server.quit()


Y, ya tenemos un programita en Python que enviará por correo el fichero que le pasemos como parámetro a la dirección que le indiquemos. O a la dirección por defecto, el fichero por defecto.
Además envía siempre una copia a toaddrs para que tengamos constancia de todos los mensajes.

Sobre la configuación, tanto destadrr como fromaddr y toaddrs deberían ser
direcciones de correo válidas.

El servidor smtpsrv puede ser cualquiera que podamos utilizar y el programa
supone que es autentificado (de ahí la necesidad de configurar un usuario y
una contraseña). Por ejemplo, para hacer el envío cifrado a través de los
servidores de Google, podríamos usar:

smtpsrv='smtp.gmail.com:587'


Y como usuario y contraseña uno que utilicemos nosotros habitualmente.

Los números de 2013

Los duendes de las estadísticas de WordPress.com prepararon un informe sobre el año 2013 de este blog.

Aquí hay un extracto:

Un teleférico de San Francisco puede contener 60 personas. Este blog fue visto por 3.000 veces en 2013. Si el blog fue un teleférico, se necesitarían alrededor de 50 viajes para llevar tantas personas.

Haz click para ver el reporte completo.

Falsas creencias de los programadores sobre redes y tiempo

En Falsehoods programmers believe about networks un recordatorio de cosas que deberíamos mirar porque probablemente no tenemos claras del todo.

En Falsehoods programmers believe about time otra lista para tener en cuenta sobre el tiempo en los programas que hacen.

Algunas que incluso te encuentras en los primeros cursos de programación,
pero que sigues haciendo mal:

A week always begins and ends in the same month.
A week (or a month) always begins and ends in the same year.

Ya habíamos comentado el de Algunas cosas falsas que los programadores creen sobre los nombres.

Otro caso de SSH y fuerza bruta

Y seguimos con ataques de fuerza bruta al SSH. En este caso nos lo cuentan en El extraño caso del SSH y el ataque de fuerza bruta donde se cuenta otra batallita de intentos de acceso por SSH, uso de un equipo para lo que no se debe y el tiempo perdido tratando de encontrar el problema.

“Guías sobre biometría del INTECO”

Me entero de una noticia de (más o menos) actualidad, para variar. INTECO presenta el Estudio y la Guía sobre tecnologías biométricas aplicadas a la seguridad.

Se pueden descargar tanto el estudio como la guía y pueden ser un buen
resumen sobre estos temas.

Dicha investigación se centra en los usos, beneficios, riesgos y buenas prácticas recomendadas en el uso de la biometría aplicadas al control de identidades y control de accesos. El objetivo es dar a conocer a las empresas y los usuarios el nivel de desarrollo y confianza de las tecnologías biométricas y asegurar que su implantación se realice respetando plenamente la seguridad de la información y la privacidad de los ciudadanos.

Yo, por completar, añadiría estos enlaces (seguramente están comentadas estas ideas en los informes, no los he leído aún):

Y un par de vídeos:

¿Soy contrario a la biometría? No, pero hay que hacer estas cosas con cuidado. A veces, entran más bien en el Security Theater.