~ Ijsland
» Door Joren op woensdag 21 juli 2010Ijsland.
The problem: There is a group of people that want access to Hackerspace Ghent but there is only one remote to open the gate.
The solution: Build a system that reacts to a phone call by opening the gate if the number of the caller is whitelisted.
What you need:
The Hack: First of all try to get caller id working by following the Caller ID with Linux and Huawei e220 tutorial. If this works you can listen to the serial communication using pySerial and react to a call. The following python code shows the wait for call method:
1
2
3
4
5
6
7
8
9
10
def wait_for_call(self):
self.data_channel.open()
call_id_pattern = re.compile('.*CLIP.*"\+([0-9]+)",.*')
while True:
bytes = self.data_channel.inWaiting()
buffer = self.data_channel.readline(bytes)
call_id_match = call_id_pattern.match(buffer)
if call_id_match:
number = call_id_match.group(1)
self.handle_call(number)
The handle_call method … handles the call.
The second thing that is needed is a way to send a signal from the beagle board to the remote. Sending a signal from the beagle board using Linux is really simple. The following bash commands initialize, activate and deactivate a pin.
1
2
3
echo 168 > /sys/class/gpio/export
echo "high" > /sys/class/gpio/gpio168/direction
echo "low" > /sys/class/gpio/gpio168/direction
Omdat er op jobsopschool gevoellige informatie te vinden is (bijvoorbeeld C.V.’s van kandidaten) is de beveiliging ervan belangrijk. Om die veiligheid te garanderen werd de vacaturesite voor onderwijzers op een volledig dichtgetimmerde aparte virtuele server geplaatst. Een server met enkel de broodnodige software zorgt voor een veilige en snelle afhandeling van requests.
Ook werd er voor gezorgd dat alle verkeer versleuteld wordt via SSL. De lighttpd webserver server werd geconfigureerd met deze tutorial die de configuratie van lighttpd met SSL bespreekt. Er werd een SSL certificaat van godaddy aangekocht omdat het root certificaat van godaddy in zowat alle browsers aanwezig is en omdat ze een redelijke prijs vragen.
This is the scenario: you have a Huawei e220, a linux computer and you want to react to a call from a set of predefined numbers. E.g. ordering a pizza when you receive a call from a certain number.
The Huawei e220 supports a subset of the AT commands, which subset is an enterprise secret of te Huawei company. So there is no documentation available for the device I bought, thanks Huawei. Anyhow when you attach the e220 to a Linux machine you should get two serial ports:
1
2
/dev/ttyUSB0
/dev/ttyUSB1
To connect to the devices you can use a serial client. GNU Screen can be used as a serial client like this: screen /dev/ttyUSB0 115200. The first device, ttyUSB0 is used to control ttyUSB1, so to enable caller ID on te Huawei e220 you need to send this message to ttyUSB0:
AT+CLIP=1
To check for calls you should listen to ttyUSB1. A serial session for ttyUSB1 looks like:
1
2
3
4
5
^BOOT:44594282,0,0,0,6
^RSSI:18
RING
+CLIP: "+33499311152",145,,,,0
^BOOT:44594282,0,0,0,6
The RING and CLIP messages are the most interesting. The RING signifies an incoming call, the CLIP is the caller ID. The BOOT and RSSI are some kind of ping messages. The following Python script demonstrates a complete session that enables caller ID, waits for a phone call and prints the number of the caller.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python
import serial, re
command_channel = serial.Serial(
port='/dev/ttyUSB0',
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
command_channel.open()
#enable caller id
command_channel.write("AT+CLIP=1" + "\r\n")
command_channel.close()
ser = serial.Serial(
port='/dev/ttyUSB1',
baudrate=9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
ser.open()
pattern = re.compile('.*CLIP.*"\+([0-9]+)",.*')
while 1:
buffer = ser.read(ser.inWaiting()).strip()
buffer = buffer.replace("\n","")
match = pattern.match(buffer)
if match:
number = match.group(1)
print number
To make Tarsos more portable I wrote a pitch tracker in pure JAVA using the YIN algorithm based on the implementation in C of aubio. The implementation also uses some code written by Karl Helgasson and Teun de Lange of the Jazzperiments project.
It can be used to perform real time pitch detection or to analyse files. To use it as a real time pitch detector just start the JAR-file by double clicking. To analyse a file execute one of the following. The first results in a list of annotations (text), the second shows the annotations graphically.
1
2
java -jar pitch_detector_yin.jar flute.novib.mf.C5B5.wav
java -jar pitch_detector_yin.jar --file flute.novib.mf.C5B5.wav
The provided flute sample is from The Musical Samples library of the University of Iowa and converted to mono wav. The source code of the pitch tracker can be found below.
Recently I bought a big shiny red USB-button. It is big, red and shiny. Initially I planned to use it to deploy new versions of websites to a server but I found a much better use: ordering pizza. Graphically the use case translates to something akin to:

If you would like to enhance your life quality leveraging the power of a USB pizza-button: you can! This is what you need:
Technically we need a driver to check when the button was pushed, a way to communicate the fact that the button was pushed and lastly we need to be able to react to the request.
The driver: on the internets I found a driver for the button. Another modification was done to make the driver process a daemon.

The communication: The original Python script executed another script on the local pc. A more flexible approach is possible using sockets. With sockets it is possible to notify any computer on a network.
1
2
3
4
5
6
7
if PanicButton().pressed():
# create a TCP socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect to server on the port
s.connect((SERVER, SERVER_TCP_PORT))
# send the order (margherita at restaurant mario)
s.send("mario: [margherita_big]\n")
The reaction: a ruby TCP server waits for message from the driver. When it does it automates a HTTP session on a website. It executes a series of HTTP-GET’s and POST’s. It uses the mechanize library.
1
2
3
4
5
6
7
8
9
login_url = "http://www.just-eat.be/pages/member/login.aspx"
a = WWW::Mechanize.new
a.get(login_url) do |login_page|
#post login_form
login_form = login_page.forms.first
login_form.txtUser = "username"
login_form.txtPass = "password"
a.submit(login_form, login_form.buttons[1])
end
Some libraries are needed. For python you need the usb library, the python deamons lib needs to be installed seperatly. Setuptools are needed to install the deamons package.
sudo apt-get install python-usb python-setuptools
Ruby needs rubygems to install the needed mechanize and daemons library. Mechanize needs the libxslt-dev package. You also need the build-essential package to build mechanize.
1
2
sudo apt-get install rubygems libxslt-dev
sudo gem install mechanize daemons
To automatically start the daemons on boot you can use the crontab @reboot directive of the root user. E.g.:
1
2
@reboot /opt/pizza_service/pizza_daemon.rb
@reboot /opt/pizza_service/pizza_button_driver.py

This blog post is about how to use the Touchatag RFID reader hardware on Ubuntu Linux without using the Touchatag web service.
An RFID reader with tags can used to fire events. With a bit of scripting the events can be handled to do practically any task.
Normally a Touchatag reader is used together with the Touchatag web service but for some RFID applications the web service is just not practical. E.g. for embedded Linux devices without an Internet connection. In this tutorial I wil document how I got the Touchatag hardware working under Ubuntu Linux.
To follow this tutorial you will need:
The touchatag USB reader works at 13.56MHz (High Frequency RFID) and has a readout distance of about 4 cm (1.5 inch) when used with the touchatag RFID tags. Internally it uses an ACS ACR122U reader with a SAM card. A Linux driver is readily available so when you plug it in lsusb you should get something like this:
1
2
3
4
lsusb
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 004: ID 072e:90dd Advanced Card Systems, Ltd
lsusb recognizes the device incorrectly but that’s not a problem. To read RFID-tags and respond to events additional software is needed: tagEventor is a software library that does just that. It can be downloaded using an svn command:
svn export http://tageventor.googlecode.com svn/trunk/ tageventor
To compile tagEventor a couple of other software packages or header files should be available on your system. Te tagEventor software dependencies are described on the tagEventor wiki. On Ubuntu (and possibly other Debian based distro’s the installation is simple:
1
2
3
sudo aptitude install build-essential libpcsclite-dev build-essential pcscd libccid
#if you need gnome support
#sudo aptitude install libgtk2.0-dev
Now the tricky part. Two header files of the pcsclite package need to be modified (update: this bug is fixed see here). tagEventor builds and can be installed:
1
2
3
4
5
6
7
cd tageventor
make
...
tagEventor BUILT (./bin/Release/tagEventor)
sudo ./install.sh
...
When tagEventor is correctly installed the only thing left is … to build your application. When an event is fired tagEventor executes the /etc/tageventor/generic script with three parameters (see below). Using some kind of IPC an application can react to events. A simple and flexible way to propagate events (inter-processes, over a network, platform and programming language independent) uses sockets. The code below is the /etc/tageventor/generic script (make sure it is executable), it communicates with the server: the second script. To run the server execute ruby /name/of/server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/ruby
# $1 = SAM (unique ID of the SAM chip in the smart card reader if exists, "NoSAM" otherwise
# $2 = UID (unique ID of the tag, as later we may use wildcard naming)
# $3 = Event Type (IN for new tag placed on reader, OUT for tag removed from reader)
require 'socket'
data = ARGV.join('|')
puts data
streamSock = TCPSocket.new( "127.0.0.1", 20000 )
streamSock.send(data, 0)
streamSock.close
1
2
3
4
5
6
7
8
require "socket"
dts = TCPServer.new('localhost', 20000)
loop do
Thread.start(dts.accept) do |s|
puts s.gets
s.close
end
end
The tagEventor software is made by the Autelic Association a Non-Profit association dedicated to making technology easier to use for all. I would like to thank Andrew Mackenzie, the founder and president of the association for creating the software and the support.
Ik heb in opdracht van scholengroep Sperregem een website gemaakt die het vinden van kandidaten voor korte vervangingen vlotter doet verlopen. Mensen met interesse voor een job in het onderwijs in de omgeving van Torhout, Kortrijk, Zedelgem kunnen zich er op inschrijven.
De website heeft enkele voordelen voor verschillende scholen in de scholengroep:
Ook voor de aspirant onderwijzers is de website handig:
Daarnaast is het ook voor de personeelsdienst een handige tool: die kan nu een beter overzicht bewaren over de vacatures en de invulling ervan in de verschillende scholen.
Hieronder staan enkele screenshots.

Vandaag is de vernieuwde vooruitwebsite gelanceerd:
We bieden je nog meer video’s, foto’s, audiotracks en tekstmateriaal en hebben ook jouw persoonlijke voordelen uitgebreid. Wanneer je lid wordt van www.vooruit.be, kan je nog steeds je kalender aanvullen, vrienden maken en reacties posten, maar daarnaast krijg je ook aanbevelingen op maat, kan je voorstellingen tippen en kan je berichten sturen naar vrienden *.
Het gepersonaliseerde aanbevelingssysteem is door Greet Dolvelde en mezelf in het kader van onze thesis: Collaborative Filtering: Onderzoek & implementatie [pdf] ontwikkeld. Dus waar wacht je nog op? Word lid, check de aanbevelingen bij concerten en vooral je gepersonaliseerde aanbevelingen.
Voor de iets minder enthousiaste doorklikkikkers staan hieronder wat screenshots van de verschillende soorten aanbevelingen op www.vooruit.be:

Waarschijnlijk heb je het al gemerkt: deze site gaat nu heel wat sneller. Dit is te danken aan een verhuis. 0110.be wordt nu gehost op een VPS.
De virtuele server heeft Ubuntu 8.04 LTS Server als besturingssysteem en draait op een Xen hypervisor. De fysieke server zelf bevat een achttal Intel® Xeon® E5440 @ 2.83GHz CPU’s.
De server staat in Amsterdam en is rechtstreeks verbonden met het grootste internetknooppunt ter wereld: AMS-IX.
Ik heb een nieuwe, ditmaal dynamische, site gemaakt voor Halte-R. Als je er enkele bouwstenen van deze site er in ziet: dat is geen toeval het werkt op hetzelfde CMS.

Uit de lijst van postcodes van alle Belgische steden heb ik een SQL-bestand samengesteld. De gegevens bevatten de postcode zelf, de naam van de stad, de naam van de stad in hoofdletters en een veld “structure” waaruit de gemeente-deelgemeente relatie gehaald kan worden als er op gesorteerd wordt. Dit zijn bijvoorbeeld de deelgemeentes van Chimay.
6460 CHIMAY 6460 Bailièvre 6460 Robechies 6460 Saint-Remy (Ht.) 6460 Salles 6460 Villers-la-Tour 6461 Virelles 6462 Vaulx-lez-Chimay 6463 Lompret 6464 Baileux 6464 Bourlers 6464 Forges 6464 l'Escaillère 6464 Rièzes
Het sorteren kan in PostgreSQL met deze SQL instructie: order by translate(structure, ' ', 'z'). Het SQL-script zelf is een lijst van INSERT INTO SQL-Statements.
insert into cities(zipcode,name,up,structure) VALUES ('1790','Affligem','AFFLIGEM','1790 AFFLIGEM');
insert into cities(zipcode,name,up,structure) VALUES ('9051','Afsnee','AFSNEE','9051 Afsnee');
insert into cities(zipcode,name,up,structure) VALUES ('5544','Agimont','AGIMONT','5544 Agimont');
...
Dit is het SQL-bestand met een lijst van alle Belgische postcodes en steden. Hopelijk is hier iemand ooit iets mee.

While working at the Vooruit Arts Centre I got the assignment to create a tool to query an Oracle database with ticketing data. There were a few requirements for the Query Tool, in the current version all of these are met:
By publishing the Query Tool on my website I hope that the fruits of my labour can be enjoyed by a wider audience. To see it in action you can give it a spin. A recent version, version 6, of the JRE is needed.
The program supports two ways to query a database:
The two buttons below are self explanatory. When the button “CVS Export” is hit a CVS file is created in a configured directory.
Depending on the complexity of a query it can take a long time before results are returned. Because the application is multithreaded the user interface remains responsive and the query can be stopped at any time.
The contents of the tab “log” gives you an idea what the application does. When something goes awry while executing a query a message appears in this tab.
The tab “Config” can be used to set configuration parameters. The tab “Help” contains… helpful information.

The list of predefined queries is constructed by iterating over SQL-files in a configured directory. Adding additional queries to the program is easy, just add an extra SQL-file to the directory. An SQL-file should have the following format, otherwise it is ignored:
TITEL
----
DESCRIPTION
----
SQL-INSTRUCTION with zero or more !{PARAMETERS}!
In the screen shot above this query is visible:
Select products in category
----
Select all the products in a category.
----
SELECT * FROM
products WHERE categoryid = !{category}!
To make the queries dynamic the Query Tool supports different kinds of parameters. A parameter has this form: !{type name}!, the name is optional. If there is a name specified it is used as a label in the interface, otherwise type is used. There are three types of parameters:
!{string}!!{boolean}!!{double}!!{date}!!{integer}!!{sql}!If you want to use your own database you need to configure the database connection string. The program uses JDBC to connect to the database. It uses metadata provided by the JDBC layer. If your database has a JDBC driver with support for metadata the Query Tool will work correctly. The JDBC driver must be included in the classpath.
The Query Tool uses the famfamfam mini icons.
For demoing purposes the executable contains a lightweight hsql database. The data in the database is a modified version of the Microsoft Northwind database. The northwind hsql database is created with this SQL-script.
Volgens een onderzoek die enkele dagen geleden verscheen op o.a. de morgen en slashdot is er een verband tussen de eerste letter van een email-adres en de hoeveelheid spam er op terecht komt. Ik host mijn eigen mail server voor 0110.be en ik krijg heel wat spam. Als er een email verstuurd wordt naar een onbestaand email adres dan komt dit in een logbestand terecht:
550 5.1.1 <abernathy@0110.be>: Recipient address rejected: User unknown in virtual mailbox table
Aangezien er maar enkele @0110.be adressen in gebruik zijn kan met zo’n logbestand gekeken worden welke letters het meeste spam te verduren krijgen:

De resultaten zijn dus nogal verrassend: enkel de adressen die starten met a,b,c en in mindere mate d worden gespammed. De rest nagenoeg niet. Mijn spammers zitten dus met een zeer beperkte namenlijst, of zijn het spammen beu na 3 letters. Misschien kunnen ze beter de namenlijst niet alfabetisch maar willekeurig overlopen. Met beter bedoel ik beter niet. Dit steekproefje, waarbij een week aan log files werden geanalyseerd, maakt duidelijk dat er bij 0110.be wel degelijk een verband is tussen de eerste letter en het aantal spam mails. Dit is het script dat gebruikt werd voor de analyse:
1
2
3
4
5
6
7
8
9
10
11
12
frequencies = Hash.new
('a'..'z').each {|l| frequencies[l]=0}
File.open("syslog", "r") do |infile|
while (line = infile.gets)
if(line =~ /.*<(.*)@0110.be>: Recipient address rejected.*/) then
frequencies[$1[0,1]]=frequencies[$1[0,1]]+1
end
end
end
frequencies.sort.each{ |pair| puts "#{pair[0]};#{pair[1]}" }

Na het bekijken van het onderstaande filmpje van een zwerm spreeuwen vroeg ik mij af of die bewegingen zich aan een bepaald algoritme houden en of ik een programma kon schrijven die dit gedrag simuleerde. Na wat onderzoek bleek dat zowat alle dieren die zich in kudde voortbewegen dit doen volgens gelijkaardige, relatief eenvoudige processen.
Er zijn drie basisregels waaraan onder andere scholen vissen, zwermen vogels en kuddes gnoes zich houden:
De paper Flocks, Herds, and Schools:
A Distributed Behavioral Model – 1987 van Craig W. Reynolds was de eerste die deze regels formeel omschreef. Aan de hand van die documentatie en een praktische omschrijving kon ik aan een implementatie beginnen. De boids implementatie in Python gebruikt pygame om een groep creaturen voor te stellen met een gekleurd vierkantje. De creaturen bewegen zich volgens de drie bovenstaande regels. Daarnaast proberen ze om binnen het zichtbare kader te blijven en begeven ze zich naar het midden van het kader. Om de boel wat interactiever te maken wordt de muisaanwijzer gezien als een gevaarlijk roofdier die niets liever lust dan vierkantjes. De vierkantjes proberen de roof-muis dus te ontlopen. De zesde en laatste regel legt een maximum snelheid op, zodat de bewegingen realistisch blijven.
De huidige implementatie is O(n²), terwijl het O(nk) zou moeten zijn, met k de grootte van de burenlijst. Een vloeiende simulatie van een zwerm van duizenden is dus momenteel niet mogelijk. De berekeningen voor een extra dimensie zijn erg eenvoudig te implementeren, helaas is de visualisatie van de resultaten dat niet. Ik heb geprobeerd om met de OpenGL bindingen voor Python te werken maar veel resultaat heeft dat niet opgeleverd. Dit is de 3D-versie, maar dan met een 2D visualsatie.
Ik heb er voor het gemak ook een uitvoerbaar bestand voor Windows van gemaakt.

Ik heb een B-Tree en een Red-Black tree geschreven in Ruby. Om die datastructuren te testen heb ik een programma geschreven dat alle woorden uit een grote tekst inleest in een b-tree met het woord als sleutel en de frequentie als waarde en daarna een red black tree gebruikt als priority queue met als sleutel de frequentie en als waarde het woord. Op die manier kunnen de meest voorkomende woorden bepaald worden. De broncode is hier neer te laden.
Het programma is een ideale test voor Ruby VM’s: het is redelijk intensief en gevarieerd. IronRuby, JRuby, Ruby 1.8 en Ruby 1.9 werden getest op een Intel Core 2 Duo E6660 en dit zijn de resultaten:
| VM | Duur | Geheugen | VM details |
|---|---|---|---|
| JRuby | 28.79 sec | 162MB | jruby 1.1.3 (ruby 1.8.6 patchlevel 114) (2008-07-20 rev 7243) [x86-java] |
| IronRuby | 88.15 sec | 195MB | IronRuby 1.0.0.1 on .NET 2.0.50727.1433 |
| Ruby 1.8 | 104.1 sec | 102MB | ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32] |
| Ruby 1.8 | 66.8 sec | 96MB | ruby 1.8.6 (2007-09-24 patchlevel 111) [universal-darwin9.0] |
| Ruby 1.9 | 33.42 sec | 88MB | ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-darwin9.2.0] |
De verschillen zijn dus erg groot. Zowel in geheugengebruik als in duur. Ruby 1.8 is blijkbaar erg traag maar gebruikt relatief weinig geheugen. JRuby is in deze test drie keer sneller maar gebruikt meer geheugen. Ook IronRuby is sneller dan de standaard Ruby VM maar gebruikt net niet het dubbele aan geheugen. Hierbij moet wel verteld worden dat IronRuby een alfa build is, de resultaten kunnen dus nog veel veranderen.
Ruby 1.9 werd later getest op Mac OS X, met dezelfde pc. De nieuwe Ruby lijkt toch enkele beloften in te lossen. Ter vergelijking werd de voor Mac OS X geoptimaliseerde Ruby 1.8 VM die standaard met het besturingssysteem meegeleverd wordt ook nog getest.

I have modified a bash-script to backup PostgreSQL databases, this is the original script. The modified version can be used to backup databases on a remote or local database server. Also this script does not need a trust relationship but uses a login and password. To get started you need to:
The script empties ~/.pgpass and writes login info for the system databases. Then it logs in and fetches an up-to-date list of databases. For every database an entry is made in ~/.pgpass and every database is backed up. The results are logged to $logfile.