oriolrius.cat

Des del 2000 compartiendo sobre…

Year: 2009

Per fi agafo vacances, a Punta Cana falta gent

Reading time: < 1 minute Demà marxem uns quants dies a Punta Cana (Republica Dominicana), de fet, anem a desconnectar de tot i a disfrutar de la calor, la platja, la piscina i bon menjar. En poques paraules a fer una mica de vegetals. Que l'any que ve ens espera un altre viatge també a la zona caribenya però amb una dosis d'aventura més gran. Esta bé això de fer un viatge sabent quin serà el següent no ho havia fet mai 🙂 Hotel Catalonia Royal Bavaro

Bé doncs, espero que acabeu de passar unes bones festes i si algú ens busca que no ho faci fins el 8 de gener, com a mínim.

Introducció a RestMS

Reading time: 2 – 4 minutes

RestMS schemaXMPP és un protocol de missatgeria no només orientat a mantenir converses entre usuaris sinó també a ser usat com a sistema RPC entre diferents aplicacions. Malgrat això res és perfecte i AMQP més orientat a la segona funció que no pas a la primera es perfila com estàndard  corporatiu molt més potent i eficient que XMPP en diversos aspectes. Però AMQP peca per ser força inaccessible degut a que no és trivial d’entendre i usar.

En tot aquest món de la missatgeria entre aplicacions hi ha un altre protocol no tan conegut però que preten tenir el millor d’XMPP i d’AMQP: RestMS. De fet, RestMS és realment una simplifiació d’AMQP que usa com a sistema de transport REST.

Es tracta d’un estàndard obert, amb una implementació Open Source força sòlida. Aquest estàndard ens aporta:

  • sistema d’enrutat de missatges
  • models de cues
  • fàcil d’extendre la seva semàntica
  • simple, perquè és precís i petit
  • segur, usa els sistemes de seguretat estàndards d’HTTP
  • escalable, perquè usa servidors, caches, proxies, etc. del món HTTP
  • resol la dicotomia ‘polling vs events’ usant long-polling, igual que BOSH
  • en principi no disposa de sistema de presència, tot i que es podria montar fàcilment
  • pot codificar durant el transportar les dades en XML o JSON
  • portable en diferents sistemes operatius
  • ofereix interoperatibilitat entre diferents llenguatges de programació

Per tot plegat RestMS es perfila com una alternativa interessant per alguns entorns, aportant una solució simple i potent en molts aspectes. Tot i que teoria en mà, el trobo força més lent que no pas AMQP. De fet, des de que vaig veure com s’usava un sistema AMQP per fer balanceix de càrrega en aplicacions de video usant GStreamer per fer una prova ‘fast and dirty’ em vaig quedar impresionat.

Tipus de pantalles tàctils

Reading time: 4 – 7 minutes

Després de treballar força anys en el món dels kioskos i del digital signage, mai se m’havia passat pel cap mirar-me quines eren les diferències reals entre els diferents tipus de pantalles tàctils que hi ha al mercat. Així doncs, finalment he decidit fer-ho i descriure-ho en aquest article.

Resistive Touch Screen

  • La tecnologia amb la millor relació qualitat preu de totes les tecnologies tàctils
  • Disponible per pantalles desde 5.7″ fins a 22″
  • Compost per diferents capes:
    • les més importants són dues capes fines: una metàlica i l’altre formada per capes conductores de l’ectricitat, aquestes capes són molt fines i estan separades entre elles molt poc espai
    • quan un objecte, per exemple un dit, prem la pantalla llavors les capes metàliques es toquen i passen l’electricitat
    • quan hi ha la connexió en aquest punt, el pantell actua com un divisor de voltatges en les sortides que tenen la connexió i registren l’event comunicant a la controladora que algú ha tocat la pantalla
  • la tecnologia és força confiable, durable i acostuma a tenir un temps de vida llarg
  • és la tecnologia més resisten en entorns ostils
  • és económica
  • és molt estable, és a dir no cal recalibrarla mai o quasi mai
  • compatible en diferents tipus de tocs: dit, stylus, llapís, etc.
  • ideal per aplicacions amb alta intensitat d’ús
  • pot arribar a suportar els estàndars NEMA 4/4x/12 i IP 65
  • si ens fixem bé en el tàctil a contrallum podem arribar a veure els minifilaments que el formen
  • susceptible a rallades o esquerdes a la superficie de toc

Surface Acoustic Wave (SAW)

  • la principal virtud és la seva transparència
  • mides de 6.4″ a 42″
  • usa ones ultra-sòniques que passen per sobre de la pantalla táctil
  • quan es toca el tàctil una part de les ones és absorvida
  • llavors es registre on han estat absorvides les ones i es comunica a la controladora el punt del toc
  • la superfie de toc pot estar danyada i continua funcionant (ralles o vidre trencat)
  • la brutícia sobre la superficie de toc pot interferir en el seu funcionament
  • els tàctils d’aquest tipus que estan fets en vidre funcionen millor que els altres
    • a més això fa que siguin més transparents
  • no cal calibrar-los més d’una vegada
  • poden ser usades de qualsevol manera: dit, guants, stylus, etc.

Capacitive

  • llarga duració
  • bona relació qualitat preu
  • inpermeable a la pluja i a la brutícia
  • mides de 5.7″ a 32″
  • sovint fabricats en vidre
  • funcionen a través d’uns sensors que actuen com a capacitors
  • les parets dels capacitors dels eixos horitzontals i els verticals es solapen
  • aprofitant que el cos humà és conductor de l’electricitat, al tocar amb el dit la superficie del sensor el camp elèctric canvia i es produeix un canvi en la capacitància
  • funcionen per proximitat, no cal arribar a tocar el tàctil
  • tecnologia amb força durabilitat i que s’usa a força sistemes POS, industrials, kioskos públics, etc.
  • és força més transparent que la tecnologia resistiva
  • només funciona amb el contacte amb el dit, o amb stylus que siguin conductors
  • suporten sistemes multi-touch
  • una capa dura en el vidre proporciona resistència al desgast
  • força resistent a la brutícia
  • funciona força bé quan hem d’arrossegar elements en la interficie
  • es considera que té un coeficient de transparència a la llum del ~91.5%

Infrared

  • Ideal per entorns ostils i aplicacions a l’exterior
  • Mides de 8.4″ a 17″
  • usa una xarxa d’emisors d’infra-rojos basats en LEDs que estan repartits pels eixos horitzontals i verticals de la pantalla, a més d’uns fotosensors col·locats en els costats inversos dels emisors
  • la idea és crear una xarxa de rajos infra-rojos i quan aquests es tallen ja tenim el toc
  • no s’usa per elements portables només per instal·lacions fixes
  • es pot usar amb el dit, guants, stylus, etc.
  • és estable, no cal calibrar-la
  • no té perquè treballar amb superficies fines, poden ser rugoses
  • poden combinar-se fàcilment amb sistemes antivandàlics
  • usades en estàndards Ingress Protection (IP) i NEMA
  • durant molt

3M MicroTouchTM DST Touch System

  • Superficies tàctils molt grans
  • mides de 32″, 40″, 42″ i 46″
  • vides tractats químicament
  • no cal stylus per usar-la, funciona amb qualsevol objecte o element que toqui la pantalla
  • resposta ràpida
  • no són massa susceptibles a la brutícia
  • 3M Dispersive Signal Technology (DST): bàsicament permet calcular les ondes de reflexió que es produeixen en el vidre tractat al haver-hi un toc
  • Ràpid, precís i molt confiable
  • Suporta esquerdes, rallades o fins hi tot objectes recolzats sobre la pantalla i continua funcionant amb precisió sobre les interaccions
  • Idea per aplicacions multi-usuari
  • Transparència excepcional

Cues del postfix i informacions relacionades

Reading time: 3 – 5 minutes

Per defecte les cues que té el postfix són:

  • hold: missatges que no s’intenten entregar mai
  • incoming: cua d’entrada de missatges
  • active: cua en la que es decideix amb quin delivery agent s’itenta entregar un missatge
  • defer/deferred: missatges que no s’han pogut entregar per un error temporal es posen en aquesta cua
  • bounce: on es generen els missatges d’error cap al remitent dels missatges que no s’han pogut entregar
  • corrupt: cua que conté missatges danyats amb els que no es pot fer res

Accions que podem fer amb els missatges d’una cua:

  • Listing messages
  • Deleting messages
  • Holding messages
  • Requeuing messages
  • Displaying messages
  • Flushing messages

Gestió de les cues:

  • Mostra l’estat de totes les cues.
mailq
  • Mostrar els 10 dominis amb més missatges pendents d’enviar, sovint va bé per controlar quan ens han usat per fer un email i hi ha molts correus enganxats per enviar.
qshape -s deferred|head -n 10
  • Borrar un missatge de les cues.
postsuper -d ID_MSG
  • Borrar tots els missatges de les cues.
postsuper -d ALL
  • Script per borrar missatges de les cues segons origen o destí:
#!/usr/bin/perl -w
#
# pfdel - deletes message containing specified address from
# Postfix queue. Matches either sender or recipient address.
#
# Usage: pfdel 
#                                                                                         

use strict;

# Change these paths if necessary.
my $LISTQ = "/usr/sbin/postqueue -p";
my $POSTSUPER = "/usr/sbin/postsuper";

my $email_addr = "";
my $qid = "";
my $euid = $>;      

if ( @ARGV !=  1 ) {
die "Usage: pfdel \n";
} else {
$email_addr = $ARGV[0];
}                                    

if ( $euid != 0 ) {
die "You must be root to delete queue files.\n";
}                                               

open(QUEUE, "$LISTQ |") ||
die "Can't get pipe to $LISTQ: $!\n";

my $entry = ;    # skip single header line
$/ = "";                # Rest of queue entries print on
# multiple lines.
while ( $entry =  ) {
if ( $entry =~ / $email_addr$/m ) {
($qid) = split(/\s+/, $entry, 2);
$qid =~ s/[\*\!]//;
next unless ($qid);

#
# Execute postsuper -d with the queue id.
# postsuper provides feedback when it deletes
# messages. Let its output go through.
#
if ( system($POSTSUPER, "-d", $qid) != 0 ) {
# If postsuper has a problem, bail.
die "Error executing $POSTSUPER: error " .
"code " .  ($?/256) . "\n";
}
}
}
close(QUEUE);

if (! $qid ) {
die "No messages with the address <$email_addr> " .
"found in queue.\n";
}

exit 0;
  • Borrar missatges segons email origen o destí.
/root/bin/pfdel email
  • Hold a message / Retenir missatges, no intentar servir-los. Posar-los a una cua congelats.
postsuper -d ID_MSG
  • Hold all messages
postsuper -d ALL
  • Moure un missatge de la cua ‘hold’ a la cua ‘active’.
postsuper -H ID_MSG
  • Moure tots els missatges de la cua ‘hold’ a la cua ‘active’.
postsuper -H ALL
  • Re-encuar missatges, per exemple si el postfix tenia un erro de configuració després de corregir-los podem re-encuar els missatges perquè es corregeixin els possibles errors de classificació que hagin patit. Per exemple, canvi de ‘delivery agent’.
postsuper -r ID_MSG
o
postsuper -r ALL
  • Veure el contingut d’un missatge que esta a la cua:
postcat -q ID_MSG
  • Per forçar el re-enviament de missatges a la cua.
postqueue -s
o
postfix flush
  • Per forçar l’enviament de missatges a la cua per un domini.
postqueue -s domini.com

Python: afegir suport de plug-ins al nostre codi

Reading time: 6 – 9 minutes

A vegades quan estem fent un programa ens interessa que el nostre codi pugui ser extés sense haver de tocar la seva estructra, fins hi tot el que ens pot interessar és que aquest codi sigui extés en algunes ocasions i en d’altres no. Un altre requeriment que podem tenir també seria que qui l’extengui no siguem nosaltres. Sovint tot això i molt més s’acostuma a fer amb el que anomenem Plug-ins, per cert, sempre m’ha fet molta gràcia la traducció al català de la paraula: ‘afegitons’.

Doncs bé, com que jo de programació no hi entenc gaire li vaig demanar al Pau que m’ajudés a entendre els models de plug-ins que implementaven alguns programes fets amb Python, ja que m’ineressava integrar aquesta funcionalitat en una serie de codis que estic desenvolupament. En aquest post intentaré explicar com funciona el paradigma dels plug-ins que usa Trac.

Primer de tot cal tenir en compte que Trac usa un patró de desplegament d’objectes anomenat Singleton, o sigui que totes les instàncies d’un objecte es refereixes a la mateixa instància. De fet, no sé dir fins a quin punt és necessari que el codi segueixi aquest patró per usar el sistema de plug-ins; tot i que jo diria que almenys les parts del codi que vulguin ser exteses pel model de plug-ins de Trac l’han de seguir.

Els plug-ins de Trac tenen les següents característiques:

  • Un Plug-in és un component que extent la funcionalitat d’un altre component
  • Un Plug-in pot extendre un altre Plug-in

Per tal d’incorporar la filosofia que té Trac per suportar Plug-ins al nostre codi cal importar el component ‘trac.core’, d’aquest component usarem el següent:

  • trac.core.Interface (classe) s’usa per definir quin és el contracte que hauran de seguir els plug-ins.
  • trac.core.ExtensionPoint (funció) quan volem que un component sigui extés usarà aquesta funció per recuperar les implementacions del contracte. Deifineix els punts de hook que té el nostre codi.
  • trac.core.implements (funció) quan un component usa aquesta funció és per implementar un contracte, o sigui, que els plug-ins que es construeixin l’han d’usar.

Abans de seguir explicaré que s’enten per contracte. Un contracte és en escència una classe de tipus interficie (python no té aquest model com a tal) que defineix quins mètodes (o altres classes) poden ser extesos dins el component original. O sigui, que cal no només definir quin és el contracte que s’ofereix sinó també documentar-lo el millor possible, explicant quines són les entrades i sortides que s’esperen de cada un dels mètodes/classes.

Perquè tot plegat s’entengui millor el Pau em va posar el següent exemple:

Imaginem que tenim una classe del tipus DNI que implementa una base de dades de DNIs, on té un metode que ens permet entrar DNIs a la base de dades:

class DNI(trac.core.Component):
  dni_checks = trac.core.ExtensionPoint(IDNIInput)
  def __init__(self):
     self._dnis = []
  def add(self, dni):
     assert not dni in self._dnis, "DNI ja existeix"for dni_check in self.dni_checks:
     if dni_check.check(dni) is False:
       print "El dni %s  sembla no ser correcte" % ( dni )
       return
    self._dnis.append(dni)
  def llista(self):
    print self._dnis

Cal fixar-se que la línia:

dni_checks = trac.core.ExtensionPoint(IDNIInput)

el que fa és carregar els plug-ins que extenen la funcionalitat del codi original. A més cal que ens fixem que el paràmetre que usa la funció és la classe que defineix el contracte sobre el que es fan els plug-ins:

class IDNIInput(trac.core.Interface):
  def check(dni):
    """ Es cridada cada cop que s'entra un nou dni, espera que es retorni un valor boleà"""

Com es pot veure el contracte només defineix un mètode: ‘check’ que ha de tenir un paràmetre d’entrada i espera un valor boleà de sortida.

Cal fixar-se en que la classe DNI cada vegada que afegeixi un element a la base de dades (en aquest cas una simple llista), cridarà a tots els plug-ins que compleixin el contracte per l’ordre en que s’han instanciat (s’han importat al codi original) mitjançant el següent codi.

for dni_check in self.dni_checks:
  if dni_check.check(dni) is False:
    print "El dni %s  sembla no ser correcte" % ( dni )
    return

Un exemple de plug-in sobre el codi anterior i que compleix el contracte especificat podria ser aquest:

import trac.core
import dni
class ValidDNI(trac.core.Component):
  trac.core.implements(dni.IDNIInput)
  def check(self, dni):
    if type(dni) is not type("str"):
      return False
    if len(dni) != 9:
      return False
    return True

Es pot veure com la classe és una instància de ‘trac.core.Component’ (model Singleton) i implementa la interfice ‘dni.IDNIInput’. A nivell funcional el que es fa és ben simple, comprovem que sigui una cadena de texte i que tingui una mida de 9 caràcters, si això es dona retorna un ‘True’ o sinó un ‘False’.

Un exemple de com quedaria el codi principal seria:

import trac.core                                                           

class IDNIInput(trac.core.Interface):
  def check(nom):
    """ Es cridada cada cop que s'entra un nou dni"""
class DNI(trac.core.Component):
  dni_checks = trac.core.ExtensionPoint(IDNIInput)
  def __init__(self):
    self._dnis = []
  def add(self, dni):
    assert not dni in self._dnis, "DNI ja existeix"
    for dni_check in self.dni_checks:
      if dni_check.check(dni) is False:
        print "El dni %s  sembla no ser correcte" % ( dni )
        return
    self._dnis.append(dni)
  def llista(self):
    print self._dnis

Exemples d’ús:

>>> import trac.core
>>> from dni import DNI
>>>
>>> dni_bd = DNI(comp_mgr)
>>> dni_bd.add("38135009C")
>>> dni_bd.add("38135009")
>>> dni_bd.llista()
['38135009C', '38135009']

# importem el plug-in check_dni
>>> import check_dni
>>> dni_bd.add("11111111")
El dni 11111111  sembla no ser correcte
>>> dni_bd.add("11111111A")
>>> dni_bd.llista()
['38135009C', '38135009', '11111111A']

Definim el codi ‘log_dni’ que serà un altre plug-in:

import trac.core
import dni
class LogDNI(trac.core.Component):
  trac.core.implements(dni.IDNIInput)
  def check(self, dni):
    print "Nou dni entrat %s" % (dni)

Seguim amb l’exemple anterior:

# importem ara el plug-in 'log_dni'
>>> import log_dni
>>> dni_bd.add("22222222B")
Nou dni entrat 22222222B

A aquestes altures ja s’han carregat dos plug-ins que treballen un després de l’altre i s’ha pogut apreciar la simplicitat i potència del model. Obviament es poden trobar coses a faltar com per exemple algún element que defineixi el llistat de plug-ins disponibles i que permeti alterar l’ordre en que aquests s’executen però això ja s’hauria de desenvolupar a part.

Espero haver-ho descrit de forma entenedora i sent el més fidel possible a les explicacions del Pau, al que he d’agrair-li l’esforç i dedicació per explicar-me aquest model de Plug-ins de Python.

llibre d’XMPP – notes a peu de pàgina

Reading time: 1 – 2 minutes

Després de llegir-me el llibre:

He pres les següents notes al moleskine que guardo aquí per poder consultar en el futur:

  • pg.39: IQ or Message
  • RFC 3920: stanza errors list
  • SleekXMPP llibreria python interessant
    • Apendix F: llistat de llibreries XMPP
  • pg.50: Subscription
  • Presence priority: -127 +128
  • XEP 0191: bloquejar JID o dominis
    • Podria ser interessant per bloquejar clients que no paguen
  • XEP 0079: ideal delivery a pantalles, reliable delivery
    • oblidar-nos de problemes si les pantalles estan offline
    • expiration time dels missatges
    • control delivering
  • XEP 0009: JabberRPC
  • XEP 0072: SOAP over XMPP
  • XEP 0060: PubSub
  • XEP 0163: permet que JID sigui un ‘collection node’ que agrupi serveis PubSub això es pot publicar junt amb les capabilities
  • Pg. 132/150: ICE, molt bona explicació
  • Pg. 145/163: VNC over XMPP es pot fer usant socks5 com a proxy segons XEP
  • XEP 0050: remote commands
  • BOSH: 180/198
  • Pg. 189/207: Serverless Messaging
  • Pg. 267/285: DNS SRV

Nagios external commands

Reading time: 1 – 2 minutes

Tan de temps usant nagios i mai havia tingut la necessita de recorrer als Nagios External Commands. Escencialment es tracta d’una named-pipe que usa Nagios per rebre comandes via shell.

  • Sintaxis per injectar les comandes. Per suportar aquesta funcionalitat previament cal haver-la habilitat al fitxer de configuració de nagios, això també ho trobareu a l’anterior enllaç.
  • Comandes suportades, la llista és força gran i hi podem trobar coses com ara forçar un check per host o fins hi tot deshabilitar els checks sobre un servei o un host.

A continuació adjunto la comanda que podeu llençar desdel prompt per llençar una ordre al nagios al cap de deu segons. En aquest cas forcem que es verifiquin tots els serveis d’un host.

# des del directori on hi ha la 'named-pipe' sovint anomenada 'nagios.cmd'
now=$(date +%s); next=$(expr $now + 10); echo "[$now] SCHEDULE_FORCED_HOST_SVC_CHECKS;nom_host;$next" > nagios.cmd

Per veure el resultat de la comanda i si aquesta ha estat rebuda pel nagios només cal que mirem el fitxer nagios.log. La sortida del log serà algo així:

data host_server nagios: EXTERNAL COMMAND: SCHEDULE_FORCED_HOST_SVC_CHECKS;nom_host;unix_ts

Què vol dir Creative Commons?

Reading time: < 1 minute Fa molt temps que tinc aquesta animació en flash donant tombs pel disc dur i avui m'he decidit a penjar-ho per aquí abans de que no li perdi la pista:

Fitxers kmz/kml i htc footprints

Reading time: 3 – 5 minutes

footprintAquestes últimes vacances a madeira he aprofitat per utitlizar una eina que fins ara incorporaven els mòbils que tenia però que fins ara que m’he passat a Android no m’he decidit a expremer, estic parlant d’htc footprints. És una eina que a partir d’un simple formulari permet registrar llocs emblemàtics, bonics, interessants, curiosos o que simplement volem recordar. Aquest formulari guarda coses com una fotografia del lloc, un títol, la posició del GPS, la direcció, pots afegir-hi comentaris de text i fins hi tot de veu; potser hem deixo algún detallet del que pots afegir-hi per cada entrada a footprints però escencialment això és tot el que fa. Obviament el bo del tema és que gràcies a les tecnologies que incorpora el telèfon omplir el formulari és ben senzill, ja que la foto, posició del GPS o gravació de veu es fan amb simples clics, com sempre el més molest és escriure text.

L’interessant del tema és que després això es pot exportar a un fitxer .kmz (tot el contingut del footprints) o un fitxer .kml (només una entrada del footprints). El .kmz conté en escència un paquet amb un fitxer kml i els arxius externs del footprints, per exemple, les fotografies o l’audio. Pel que fa al format del fitxer .kml es tracta d’un fitxer XML amb el contingut del formulari que he comentat anteriorment. Aquests fitxers són directament importables al Google Earth i a moltes altres eines de la saga de Google. Però el que a mi m’interessa comentar en aquest article és la llibereria libkml, també de google, la que vaig usar per parsejar el fitxer kmz de les vacances a Madeira.

schema fitxer kml

A través d’un simple codi amb python vaig generar el codi en format dokuwiki necessari per montar-me l’esquelet de la web de les vacances a Madeira. De fet, el codi no esta gens polit i esta extret d’snippets d’exemple que he trobat per la web, però pel que jo volia era més que suficient. Al final del post hi teniu un enllaç.

Fa dies que en aquesta línia dono voltes a la idea de montar-me un servei que després de fer una entrada al footprints amb el mòbil enviï automàticament el fitxer .kmz/.kml per email a una direcció reservada que parsegi el correu i que automàticament doni d’alta aquest contingut a alguna de les seccions d’oriolrius.cat, de fet, encara no tinc clar si la millor idea és injectar-ho com a post o com a entrada del wiki, el que si que tinc clar és que això després s’haurà de referenciar al meu lifestream perquè així quedi constància de llocs interessants que coneixo i que sempre que vols recordar ja has oblidat. Si algú té idees de com millorar aquesta idea, ja ho sap, que m’avisi.

Referències:

NOTA: el codi del dokuwiki usa el plugin de google maps.

Salt amb paracaigudes

Reading time: < 1 minute Avui he marcat un 'fet' en una de les coses que tinc que fer a la vida abans de morir: