Web.py Skeleton (web.py + routing json + jinja2)

Hoy quería traerles un pequeño proyecto que he publicado en github, es un pequeño conjunto de ayudas pre-configuradas para comenzar un proyecto con el framework Web.py uno de mis preferidos para desarrollar rápidamente aplicaciones web.

Basicamente proporciona out-the-box:

  • Routing from json file.
  • Subapps system.
  • Jinja2 Support.
  • Flash message.

Las únicas dependencias del proyecto por ahora son el framework en si y el sistema de plantillas jinja2:

pip install web.py
pip install jinja2

Espero que sea útil para alguien, y si se puede mejorar los pull request son bienvenidos :D

Puedes descargarlo desde: https://github.com/sdeancos/webpyskeleton

Mandar stream de datos a Carriots con NodeJS

Os presento esta vez una receta sencilla para hacer una petición HTTP a la plataforma IoT Carriots.com y conseguir enviar una trama de datos esta vez con nodejs.

var https = require('https');

var send_stream = function(data){
    var device = 'YOUR_ID_DEVELOPER_DEVICE'
    var apikey = 'YOUR APIKEY'
    var stream = '{"protocol":"v2","device":"'+device+'","at":"now","data":{"key": "'+data+'"}}'

    var options = {
      host: 'api.carriots.com',
      path: '/streams',
      method: 'POST',
      headers: {'User-Agent': 'NodeJS-carriots.com-Client',
                'Content-Type' : 'application/vnd.carriots.api.v2+json;q=7',
                'Accept': 'application/vnd.carriots.api.v2+json;q=7',
                'Content-Length': stream.length,
                'Carriots.apikey': apikey}
    };

    var req = https.request(options, function(response) {
      console.log('STATUS: ' + response.statusCode);
      //console.log('HEADERS: ' + JSON.stringify(response.headers));
      response.setEncoding('utf8');
      response.on('data', function (chunk) {
        console.log('BODY: ' + chunk);
      });
    });

    req.on('error', function(e) {
      console.log('problem with request: ' + e.message);
    });


    req.write(stream);
    req.end();
};

send_stream('Value');

Espero que os sirva de referencia para poder hacerlo mas potente y crear prototipos con BeagleBone.

Mini-tutorial Silex: Autenticación (III)

En la anterior entrega (http://blog.deancos.com/2013/12/27/mini-tutorial-silex-anadiendo-dependencias-twig-ii/) vimos como podíamos integrar fácilmente el sistema de plantilla twig con Silex, gracias a lo cual ya podíamos maquetar nuestros resultados mas fácilmente.

Hoy vamos a dar un nuevo paso en nuestro pequeño programa y vamos a preparar nuestra aplicación para poder autenticar y autorizar.

Vamos a añadir una nueva dependencia al proyecto: Security.
Como vimos en los anteriores capítulos lo único que necesitamos es añadir la dependencia a nuestro composer.json:

   "symfony/security": "~2.3",

Una vez guardado el fichero tendremos algo como esto:

{
    "require": {
        "silex/silex": "~1.1",
        "twig/twig": ">=1.8,<2.0-dev",
        "symfony/twig-bridge": "~2.3",
        "symfony/security": "~2.3"
    }
}

Ahora podemos actualizar nuestro proyecto:

$ php composer.phar update

Bueno, ahora ya tenemos listas las dependencias que necesitamos para poder empezar a preparar nuestro entorno de seguridad.

Los primeros servicios que registramos son UrlGeneratorServiceProvider y SessionServiceProvider, ambos son servicios muy específicos que mas adelante utilizaremos, por ahora creo que sus nombre son bastante auto-explicativos.

Ya sabemos, en nuestro index.php registrar los servicios:

<?php
...
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\SessionServiceProvider());

Bueno, ahora vamos a registrar el servicio principal, SecurityServiceProvider, y lo configuraremos por defecto para poder hacer nuestras primeras pruebas. Por ahora como no tenemos aun base de datos podemos utilizar una configuración como la siguiente.

$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'admin' => array(
            'pattern' => '^/admin/',
            'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
            'logout' => array('logout_path' => '/admin/logout'),
            'users' => array(
                'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
            ),
        ),
    )
));

No entrare mucho a explicar como funciona la configuración pues en siguientes capítulos cuando lo integremos con la base de datos podremos explicarlo mas a fondo. Por ahora con saber que hemos configurado las rutas por defecto para poder hacer login/logout y que hemos creado un usuario admin es suficiente.

Ahora vamos a crear en nuestro controlador frontal una acción para hacer login:

$app->get('/login', function(Request $request) use ($app) {
    return $app['twig']->render('login.html', array(
        'error'         => $app['security.last_error']($request),
        'last_username' => $app['session']->get('_security.last_username'),
    ));
});

Y su vista correspondiente con el formulario de login:

<form action="{{ path('admin_login_check') }}" method="post">
    {{ error }}
    <input type="text" name="_username" value="{{ last_username }}" />
    <input type="password" name="_password" value="" />
    <input type="submit" />
</form>

En este punto os podréis preguntar que significa y de donde sale esta linea en la vista: path(‘admin_login_check’), pues efectivamente de uno de los servicios que antes registramos, exactamente de UrlGeneratorServiceProvider, que justamente se dedica a generar las urls que necesitamos de manera dinámica.

Bueno ya tenemos nuestra acción de login y su vista correspondiente.

Vamos a cambiar un poco lo que teníamos de capítulos anteriores para que tenga mas sentido con esta nueva funcionalidad, este seria nuestro nuevo controlador frontal:

<?php
require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;

$app = new Silex\Application();
$app['debug'] = true;

$app->register(new Silex\Provider\TwigServiceProvider(), array('twig.path' => __DIR__.'/views',));
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\SessionServiceProvider());
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'admin' => array(
            'pattern' => '^/admin/',
            'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
            'logout' => array('logout_path' => '/admin/logout'),
            'users' => array(
                'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
            ),
        ),
    )
));

$app->get('/', function () use ($app) {
    $user = $app['session']->get('user');
    return $app['twig']->render('index.html', array('user' => $user));
});

$app->get('/login', function(Request $request) use ($app) {
    return $app['twig']->render('login.html', array(
        'error'         => $app['security.last_error']($request),
        'last_username' => $app['session']->get('_security.last_username'),
    ));
});

$app->get('/admin', function () use ($app) {
    return 'Admin site';
});

$app->run();

Hemos añadido una nueva acción, /admin, para comprobar que funciona perfectamente el sistema de seguridad.


nota: la url /admin esta definida en la configuración de SecurityServiceProvider, es el valor de la clave pattern: 'pattern' => '^/admin/'

También hemos cambiado un poco nuestra vista, index.html:

Hello {{ user }}, welcome!
<p>
    <a href="login">Login</a>
    <a href="{{ path('admin_logout') }}">Logout</a>
</p>

Una de las lineas nuevas del controlador frontal que aun no hemos explicado en la utilización de la clase request para recoger la petición:

Para utilizarlo lo único que tenemos que hacer es importarla y utilizarla en nuestra acción:

use Symfony\Component\HttpFoundation\Request;
$app->get('/login', function(Request $request) use ($app) {}

Ahora si entramos con nuestro navegador preferido a nuestra aplicación podremos probar y experimentar con el sistema de seguridad.

En próximas entregas entraremos mas a fondo en estos temas y otros también muy interesantes.

Beaglebone configuración WiFi

Pequeña receta para configurar el acceso a internet mediante WiFi con la placa libre Beaglebone.

Yo solo he conseguido hacer funcionar con una tarjeta wifi Belkin Wireless G USB Network Adapter (F5D7050)

Lo que debemos hacer es enchufar nuestra tarjeta wifi a la placa y después crear el siguiente fichero en /var/lib/connman/wifi.config

$ vim /var/lib/connman/wifi.config

[service_home]
Type = wifi
Name = NombrePuntoAcceso
Security = wpa2-psk
Passphrase = PasswordPuntoAcceso

$ :wq!

Lo guardamos y reiniciamos la beagle. Si todo ha ido correctamente ya tendremos acceso a internet mediante WiFi en nuestra placa.

(Si alguien consigue hacerlo funcionar con otras tarjetas WiFi de otros fabricantes y/o otros chipsets podría comentarlo en los comentarios de este post)

Actualizar firmware Beaglebone desde Ubuntu

Estoy trasteando estos días con la placa Beaglebone, una placa libre muy parecida a RapsberryPi.

Lo primero que he intentado hacer es actualizar el firmware pues el que venia pre-instalado estaba un poco atrasado.

Para ello voy a intentar explicar el sencillo proceso que se debería realizar para ello desde un sistema operativo Ubuntu.

Lo primero que tenemos que hacer es descargarnos la ultima versión del firmware desde la pagina oficial: http://beagleboard.org/latest-images

Una vez la la tengamos en nuestra maquina, en nuestro caso Angstrom-Cloud9-IDE-GNOME-eglibc-ipk-v2012.12-beaglebone-2013.06.20.img.xz deberemos descomprimir el fichero, en Ubuntu es sencillo: nautilus > botón derecho > extraer aquí.

Ya tenemos nuestra imagen: Angstrom-Cloud9-IDE-GNOME-eglibc-ipk-v2012.12-beaglebone-2013.06.20.img

Ahora solo tenemos que grabarla en la tarjeta minisd, para ello utilizaremos la consola.

Lo primero es saber que devicenode ha asignado el sistema a nuestra tarjeta:

$ sudo dmesg | tail -20

...
<tt>[ 5047.076459] sd 10:0:0:0: [sdc] Attached SCSI removable disk</tt>
...

Solo nos interesa sdc, que es el nodo de la tarjeta.

Ahora solo nos queda copiar la imagen utilizando el comando dd:

$ sudo dd if=/home/path_donde_este/Angstrom-Cloud9-IDE-GNOME-eglibc-ipk-v2012.12-beaglebone-2013.06.20.img of=/dev/sdc bs=1M

Este proceso tardara un rato, una vez finalice ya tendremos la tarjeta programada y lista para insertarla en nuestra Beaglebone y probar el nuevo firmware.

Un vez arrancada podríamos actualizar los paquetes de la distribución a sus ultimas versiones:

$ opkg update
$ opkg upgrade

Con esto ya tendríamos nuestra beagle con la última versión funcionando!

Presentación Internet Of Things + Raspberry Pi decharlas.com Abril 2014

Presentación Internet Of Things + Raspberry Pi decharlas.com Abril 2014

Internet esta transformándose constantemente, durante los últimos años hemos sido testigos de una evolución hacia lo social, transaccional y móvil, ¿pero cual es el siguiente reto? la respuesta esta en los objetos, cosas cotidianas que paulatinamente están conectándose a la red.

A día de hoy existen mas objetos conectados que personas en el planeta y para el año 2020 existirán mas de 50.000 millones de ellos. ¿Frigoríficos inteligentes que te avisan de la caducidad de alimentos? ¿Cepillos de dientes que detectan caries? ¿Ciudades inteligentes, sostenibles? La aplicación del concepto es ilimitada.

Parece ciencia ficción, pero hoy ya existen personas, empresas e instituciones que están aplicando con éxito estos paradigmas, en parte gracias al abaratamiento de sensores y al hardware libre como Arduino o Raspberry Pi. Hoy día cualquier persona interesada puede adentrarse en el apasionante mundo de el “Internet de las Cosas”

Borrar colas en RabbitMQ con Pika (python) y rabbitmqctl

En ocasiones necesitamos borrar todas las colas de nuestro RabbitMQ, sobretodo en entornos de pruebas.

Este pequeño script en python utilizando la libreria Pika nos puede ayudar a esta tarea.

Para ello utilizaremos la libreria Pika:

pip install pika

(Esta solución esta sacada de http://stackoverflow.com/questions/6742938/deleting-queues-in-rabbitmq/22576477#22576477)

#!/usr/bin/env python
from sys import stdin
from pika import BlockingConnection, ConnectionParameters

connection = BlockingConnection(ConnectionParameters('localhost'))
channel = connection.channel()

queues = stdin.readlines()[1:-1]
for x in queues:
    q = x.split()[0]
    print 'Deleting %s...' %(q)
    channel.queue_delete(queue=q)

connection.close()

Para utilizarlo solo tenemos que hacer esta llamada desde la linea de comandos:

sudo rabbitmqctl list_queues | delete_queues.py

Gracias a este pequeño script nuestra tarea de eliminar todas las colas en RabbitMQ estará solucionada.

Mini-tutorial Silex: Añadiendo dependencias, Twig (II)

En la anterior entrega (http://blog.deancos.com/2013/12/27/mini-tutorial-silex-instalacion-i/) aprendimos como instalar Silex para comenzar un proyecto y escribimos nuestro primer controlador, dicho controlador simplemente lanzaba una cadena como respuesta, pero para poder realizar el proyecto que tenemos entre-manos necesitamos mas potencia a la hora de crear vistas, he aquí la solución: utilizaremos Twig el sistema de plantillas de PHP de moda.

Lo primero que vamos hacer es actualizar las dependencias de nuestro proyecto, como ya vimos en el capitulo anterior utilizaremos el fichero composer.json, añadiendo la dependencia que necesitamos, en este caso Twig:

{
    "require": {
        "silex/silex": "~1.1",
        "twig/twig": ">=1.8,<2.0-dev",
        "symfony/twig-bridge": "~2.3"
    }
}

Una vez guardado el fichero podemos actualizar nuestro proyecto:

$ php composer.phar update

Esto instalara en nuestro proyecto todo lo necesario para poder empezar a utilizar Twig como sistema de plantillas en nuestro proyecto Silex.

Una vez lo tenemos lo siguiente que necesitamos es registrar los servicios necesarios para que Twig este operativo, y cambiar la respuesta de nuestro controlador para que utilice una vista:

<?php
require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();
$app->register(new Silex\Provider\TwigServiceProvider(), array('twig.path' => __DIR__.'/views',));

$app->get('/', function () use ($app) {
    return $app['twig']->render('index.html', array('nombre' => 'Samuel'));
});

$app->run();

Pasemos a explicar un poco las nuevas lineas del código:

En primer lugar registramos TwigServiceProvider y le decimos el path de nuestras vistas, en nuestro caso sera views, con esto ya podemos empezar a escribir el código de nuestras plantillas, en dicha carpeta que previamente deberíamos haber creado dentro de web:

$ mkdir views

Por ultimo la respuesta; como vemos en el código ahora utilizamos el servicio twig y su método render para responder pasando como parámetro la plantilla y un array con las posibles variables que queremos pasar a la vista, en este caso la variable nombre.

Ahora podemos crear nuestra primera plantilla Twig, index.html, dentro de la carpeta views:

<h1>Bienvenido {{ nombre }} a nuestro primer proyecto Silex con Twig!</h1>

Es un pagina sencilla para nuestro primer ejemplo, en capítulos posteriores veremos como aprovechar la potencia de Twig en nuestros proyectos Silex.

Ya lo tenemos, podemos ver el resultado en nuestro navegador preferido.

Ir a tercera parte del tutorial:

Mini-tutorial Silex: Instalación (I)

En este mini-tutorial vamos a explicar desde la instalación hasta la creación de un pequeño proyecto final como funciona el micro-framework basado en Symfony Silex, la idea es crear un mini-cms totalmente operativo.

Lo primero que haremos sera instalar composer el manejador de dependencias de facto de PHP en los últimos tiempos, composer es una herramienta que permite instalar las librerías de las que depende un proyecto PHP, en nuestro caso Silex.

Este mini-tutorial esta orientado a sistemas Linux así que daré por sentado que tenemos las herramientas necesarias.

Para instalar composer simplemente debemos ejecutar la siguiente sentencia en cualquier terminal dentro de la carpeta de nuestro proyecto:

$ curl -sS https://getcomposer.org/installer | php

Ahora ya tenemos composer en nuestra carpeta, lo siguiente que necesitamos es decirle a composer que queremos instalar Silex.

Para ello creamos dentro de la carpeta un fichero llamado composer.json, este es el fichero que composer leera para saber que paquetes queremos instalar, su formato es JSON.

Si necesitas mas información sobre composer escribí hace tiempo sobre ello http://blog.deancos.com/2012/09/22/dependencias-en-php-composer/

{
    "require": {
        "silex/silex": "~1.1"
    }
}

Una vez hemos creado el fichero podemos decirle a composer que instale el paquete y todas sus dependencias:

$ php composer.phar install

Cuando termine su trabajo ya tendremos en nuestra carpeta el microframework Silex preparado para empezar a trabajar con el.

Lo siguiente que haremos sera crear nuestro controlador frontal, para ello creamos una carpeta llamado web dentro de la principal de nuestro proyecto, y dentro un fichero llamado index.php:

$ mkdir web
$ touch index.php

Luego abrimos el fichero con nuestro editor de código favorito y escribimos nuestro primer controlador frontal:

<?php
require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/', function () use ($app) {
    return "Bienvenido a nuestro primer proyecto Silex!";
});

$app->run();

Vamos a explicar un poco el funcionamiento del código anterior:

Lo primero que vemos es que importa el fichero autoload.php, este fichero es creado por composer, basicamente carga las clases necesarias para que los paquetes funcionen, es lo que se denomina un ClassLoader.

La siguiente linea carga la clase principal de Silex: Application, esta clase hereda de Pimple, el contenedor de dependencias que utiliza Silex e implementa HttpKernelInterface. Esta clase es la base de Silex y nos permite crear nuestro controlador frontal asi como construir nuestra aplicación en base a ella.

Lo siguiente que vemos es un controlador, en este caso controlar las peticiones GET para el patron /, esto es raíz, y ejecuta el código de la función anónima, en este caso devuelve una cadena.

Finalmente llamamos al método run de nuestra aplicación, a grandes rasgos este método es el que controla el flujo petición-respuesta (request-response) en la aplicación.

Esta primera aplicación es muy sencilla, ya iremos desgranando el funcionamiento mas detalladamente según vaya creciendo nuestra aplicación en los siguientes capítulos.

Una vez todo este preparado necesitamos que un Servidor Web sirva nuestro proyecto, en nuestro caso vamos a utilizar Apache2, sin meternos mucho en este tema pues no es la finalidad de este tutorial, simplemente creamos un VirtualHost parecido a esto:

<VirtualHost *:8080>
	DocumentRoot /MI_PATH/MI_PROJECTO/web/index.php

	<Directory /MI_PATH/MI_PROJECTO/web/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		Allow from all
	</Directory>

	ErrorLog /var/log/apache2/error_mi_proyecto.log
	LogLevel warn

	CustomLog /var/log/apache2/access_mi_proyecto.log combined
	ServerSignature On
</VirtualHost>

Una vez reiniciado el servidor web, ya tendremos funcionando nuestro primero proyecto Silex.

Ahora ya podemos ver el resultado en nuestro navegador preferido: localhost:8080.

En próximas entregas veremos como añadir dependencias a nuestro proyecto y como crear un mini cms con Silex.

Ir a segunda parte del tutorial: Mini-tutorial Silex: Añadiendo dependencias, Twig (II)

Internet of Things + RaspberryPi + Python con carriots

Código de ejemplo de la Charla-Taller: Internet de las Cosas, RaspberryPi y Python en MediaLab-Prado (http://medialab-prado.es/article/iotraspberrypipython)

Toda la información sobre este proyecto puedes encontrarla en https://www.carriots.com/tutorials/arduino_carriots/alert_system

#-*-coding:utf8-*-
import RPi.GPIO as GPIO, time
import urllib2
import time, datetime
import json

class Client(object):
    api_url = "http://api.carriots.com/streams"

    def __init__ (self, api_key = None, client_type = 'json'):
        self.client_type = client_type
        self.api_key = api_key
        self.content_type = "application/vnd.carriots.api.v2+%s" % (self.client_type)
        self.headers = {'User-Agent': 'Raspberry-Carriots',
                        'Content-Type': self.content_type,
                        'Accept': self.content_type,
                        'Carriots.apikey': self.api_key}

    def send (self, data):
        self.data = json.dumps(data)
        request = urllib2.Request(Client.api_url, self.data, self.headers)
        self.response = urllib2.urlopen(request)
        return self.response

def RCtime(PiPin):
    measurement = 0
    GPIO.setup(PiPin, GPIO.OUT)
    GPIO.output(PiPin, GPIO.LOW)
    time.sleep(0.1)

    GPIO.setup(PiPin, GPIO.IN)

    while (GPIO.input(PiPin) == GPIO.LOW):
        measurement += 1

    return measurement


def main():
    GPIO.setmode(GPIO.BCM)
    ON = 1
    OFF = 2
    DEVICE = "YOUR_DEVICE@YOUR_USERNAME"
    APIKEY = "YOUR_APIKEY"
    lights=OFF

    client_carriots = Client (APIKEY)

    while True:
        timestamp = int (time.mktime(datetime.datetime.utcnow().timetuple()))
        if RCtime(4) > 600:
            new_lights = OFF
        else:
            new_lights = ON

        if lights is not new_lights
            lights = new_lights
            data = {"protocol":"v2","device":DEVICE,"at":timestamp,"data":{"light":("ON" if new_lights is ON else "OFF")}}
            carriots_response=client_carriots.send(data)

if __name__ == '__main__':
    main()