Accessing DeviceKit with DBus and Python

Posted by Moser on 08 Jan 2010

Under the impression of loosing some really important data because of a damaged partition table on a USB flash drive I am developing a backup strategy for my system. I know myself and so I decided that I need to automate this. While trying to figure out how one can run a script as soon as a specific drive is mounted, I came across DeviceKit. It’s the planned replacement of HAL and is used in Ubuntu Karmic. Udev is not an option for me, because I don’t want to mess around with mounting myself (and I hate running stuff as root…). So here is what I found out about using DBus and DeviceKit in Python:

import dbus

bus = dbus.SystemBus()

proxy = bus.get_object("org.freedesktop.DeviceKit.Disks", 
                       "/org/freedesktop/DeviceKit/Disks")
iface = dbus.Interface(proxy, "org.freedesktop.DeviceKit.Disks")
#enumerates all devices
print iface.EnumerateDevices()

#gets the device kit path of a specific device
path = iface.FindDeviceByDeviceFile("/dev/sdc1") 
#= "/org/freedesktop/DeviceKit/Disks/devices/sdc"

#gets an object representing the device specified by the path
device = bus.get_object("org.freedesktop.DeviceKit.Disks", path) 

#prints some XML that shows you the available methods, signals and properties
print device.Introspect()

#gets a proxy for getting properties
device_prop = dbus.Interface(device, "org.freedesktop.DBus.Properties")

#you need to specify an interface (properties could be ambiguous)
print device_prop.Get("org.freedesktop.DeviceKit.Disks.Device", "device-mount-paths")

#gets a proxy you can call methods on
device_iface = dbus.Interface(device, "org.freedesktop.DeviceKit.Disks.Device")

#unmounts the partition
device_iface.FilesystemUnmount(dbus.Array([], 's'))

The DBus API of DeviceKit is documented here. Now we want to be notified when a drive is mounted:

import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop

def device_added_callback(device):
    print 'Device %s was added' % (device)

def device_changed_callback(device):
    print 'Device %s was changed' % (device)

#must be done before connecting to DBus
DBusGMainLoop(set_as_default=True)

bus = dbus.SystemBus()

proxy = bus.get_object("org.freedesktop.DeviceKit.Disks", 
                       "/org/freedesktop/DeviceKit/Disks")
iface = dbus.Interface(proxy, "org.freedesktop.DeviceKit.Disks")

#addes two signal listeners
iface.connect_to_signal('DeviceAdded', device_added_callback)
iface.connect_to_signal('DeviceChanged', device_changed_callback)

#start the main loop
mainloop = gobject.MainLoop()
mainloop.run()

A typical output when a flash drive is plugged in looks like this:

Device /org/freedesktop/DeviceKit/Disks/devices/sdc was added
Device /org/freedesktop/DeviceKit/Disks/devices/sdc1 was added
Device /org/freedesktop/DeviceKit/Disks/devices/sdc1 was changed

With this knowledge I’m currently working on a little python script that runs in background and executes a shell script when a file system is mounted. I’ll post it, when it’s finished :-)

Sequel single table inheritance

Posted by Moser on 20 Oct 2009

Sequel’s STI is not so well documented as ActiveRecord’s is. Because it cost me about 20 minutes to find out about it’s syntax, I post a little example.

class A < Sequel::Model
  plugin :single_table_inheritance, :object_type
end

class B < A
end

The second argument is the name of the column to be used to store the class name in DB. Don’t use ‘type’ here, it collides with Ruby’s Object#type. This works with version 3.5.0 and should work with any version >= 2.12.0.

Monkeybars - Little bug

Posted by Moser on 10 Sep 2009

For a little side project I am currently evaluating different ways of GUI programming using Ruby. Monkeybars is one of the most interesting candidates. There is a really good article about it, if you want to learn more. Version 1.0.4 has a little, but annoying bug: If you generate a new application skeleton it won’t compile/run:

manifest.rb:32:in `require': no such file to load -- monkeybars (LoadError)
    from manifest.rb:32
    from manifest.rb:21:in `require'
    from main.rb:21

To fix it, you got to change line 21 of manifest.rb:

add_to_classpath '../lib/java/monkeybars-1.0.2.jar'
#to
add_to_classpath '../lib/java/monkeybars-1.0.4.jar'

First time > 500 km

Posted by Moser on 13 Aug 2009

On last Wednesday I had to write my last test for this semester. As the long term soaring forecast looked quite good I decided to skip the party on the evening and to drive home (i.e. the airfield) instead. The weather report for Thursday promised us good but blue (no clouds that mark the upper ends of thermals) conditions. I don’t really like flying on blue days as you can never be sure if there is still thermal activity where you are heading, but I was quite motivated because I did not fly cross country for nearly two months. On Thursday morning Daniel and I assembled the Ventus 2cx (Thanks btw) and I put in 58 liters of water ballast. At 11 AM me and some of our guests from Hamburg were ready for tow. Fortunately the weather forecast was not entirely correct: We already saw some clouds develop.

At 11.47 AM (local) I released the tow rope a little north western of Cham in about 700 m AGL (above ground level). My first thermal wasn’t good (or I just did not get it the right way). So I proceeded a little further north, lost some more height and found myself in weak, narrow thermal. I decided to drop my water ballast which probably was wrong. Afterwards the thermal improved and I could fly on to the north. Within the first hour I seldom was higher than 1000 m AGL. When I passed Weiden the altitude of the cloud base and the thermals’ strength improved and I got faster. The Fichtelgebirge provided me with some strong lift and soon I passed Kulmbach.

Sonneberg

Sonneberg

Overhead Sonneberg I entered the Thuringian Forest. Some kilometers before Suhl I turned back southward. All in all I had to thermal too much for my taste on the first leg.

New Railway bridge

Bridge construction site on the Nuremberg–Erfurt high-speed railway

On the way back south I did a better job and did not thermal much until I was south of Tirschenreuth. A Janus joined me in close formation for some 40 Km. In order to stretch the flight a little I went on to the south east of Cham and turned near Bischofsmais.

From there I planned my final glide which was quite tight and got tighter due to some strong downdrafts in the area where I turned. But I was lucky and hit some thermals on the glide home. The second one was quite strong and I decided to gain any height I could get in order to make some extra kilometers. I again passed Cham and flew on to the north west. I could use some calm evening thermals, turned at Neunburg vorm Wald for the last time and went home fast.

With a distance of 529 Km and a duration of 6 hours and 37 minutes this was my farthest and longest flight. Because of the high amount of traffic and the sometimes rough thermals I only took a few pictures today.

Here is the flight on the OLC.

xkcd rocks

Posted by Moser on 20 Jul 2009

Estimation (xkcd)

massage passing as means of coordination

Posted by Moser on 01 Jul 2009

A nice quote found on the slides of our distributed systems lecture:

massage passing as means of coordination

One should try massaging each other to improve a team’s coordination. ;-)