D-Bus (incompleto, siga a su propio riesgo)

Instalación con PackageKit cli:

$ su -c "pkcon install ruby-dbus" 
  1. Use gem por ahora, la versión en los repos yum de Fedora está desactualizada.
# gem install ruby-dbus
Fetching: ruby-dbus-0.7.0.gem (100%)
Successfully installed ruby-dbus-0.7.0
1 gem installed
Installing ri documentation for ruby-dbus-0.7.0...
Building YARD (yri) index for ruby-dbus-0.7.0...
Installing RDoc documentation for ruby-dbus-0.7.0...

Dos buses

En un sistema típico hay dos buses en ejecución, el bus del sistema y el bus de sesión.

1>> session_bus = DBus::SessionBus.instance
2...
3>> system_bus = DBus::SystemBus.instance
4...

Listando cosas...

Buscando cómo listar los clientes en el bus:

1>> bus = DBus::SystemBus.instance
2...
3=> ["org.freedesktop.DBus", ":1.7", ":1.8", "org.freedesktop.systemd1", "org.freedesktop.NetworkManager", "com.redhat.ifcfgrh1", "org.freedesktop.ModemManage
4r", "edu.duke.linux.yum", "org.freedesktop.Accounts", "org.freedesktop.RealtimeKit1", ":1.40", "org.freedesktop.PolicyKit1", ":1.20", ":1.43", ":1.21", ":1.22", ":1.44", ":1.45", ":1.197", ":1.395", ":1.198", ":1.430", ":1.199", ":1.574", ":1.48", ":1.156", ":1.553", "fi.epitest.hostap.WPASupplicant", ":1.312", ":1.29", "org.gnome.DisplayManager", "org.freedesktop.ConsoleKit", "org.freedesktop.UDisks", "fi.w1.wpa_supplicant1", "org.freedesktop.login1", "org.freedesktop.ColorManager", ":1.51", ":1.30", ":1.31", ":1.10", ":1.11", ":1.12", "org.freedesktop.UPower", ":1.34", ":1.3", ":1.16", ":1.4", ":1.423", ":1.5", ":1.6", ":1.19"]
5...
6>> bus.proxy.ListNames[0][7]
7=> "edu.duke.linux.yum
8...
9

Haciendo llamadas a métodos

Dado un servicio provistor por otro cliente D-Bus.

>> service = bus.service("edu.duke.linux.yum")
...
>> updatesd = service.object("/Updatesd")
...
>> updatesd.introspect
=> "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"\n"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">\n<node na
me="/Updatesd">\n  <interface name="edu.duke.linux.yum">\n    <method name="CheckNow">\n    </method>\n    <method name="GetUpdateInfo">\n      <arg direction="out" type="a(a{ss}a{ss})" />\n    </method>\n    <method name="ShutDown">\n    </method>\n  </interface>\n  <interface name="org.freedesktop.DBus.Introspectable">\n    <method name="Introspect">\n      <arg direction="out" type="s" />\n    </method>\n  </interface>\n</node>\n" 
...
>> updatesd_intf = updatesd["edu.duke.linux.yum"]
...
>> updatesd_intf.CheckNow
=> ["check queued"]

Microproyecto: escuchar aplicaciones entrar y salir

1>> require 'dbus'
2=> true
3>> bus = DBus::SessionBus.instance
4...
5>> bus.proxy.ListNames[0]
6=> ["org.freedesktop.DBus", "org.gnome.PowerManager", "org.freedesktop.Notifications", ...

Jugando con Rhytmbox

...usando MPRIS

 1>> require 'dbus'
 2=> true
 3>> bus = DBus::SessionBus.instance
 4...
 5>> rb_service = bus.service("org.mpris.MediaPlayer2.rhythmbox")
 6...
 7>> rb_player = rb_service.object("/org/mpris/MediaPlayer2")
 8...
 9>> rb_player.introspect                              ; La introspección es crítica para acceder al objeto remotamente
10...
11>> rb_player_iface = rb_player["org.mpris.MediaPlayer2.Player"]
12...
13>> rb_player_iface.Next
14=> []

Jugando con NM

1>> system_bus = DBus::SystemBus.instance
2...
3>> sys_service = system_bus.service('org.freedesktop.NetworkManager')
4...
5>> nm = sys_service.object("/org/freedesktop/NetworkManager")
6..
7>> nm_iface = nm["org.freedesktop.NetworkManager"]
8..

Creando un servicio

 1require 'dbus'
 2
 3class FPScanner < DBus::Object
 4  # Creación de la interfase
 5  dbus_interface "org.ruby.FPScannerInterface" do
 6
 7    # Creación del método status
 8    dbus_method :status, "out msg:s" do 
 9      # Método de prueba para obtener algo del servicio
10      [msg = 'status']
11    end
12
13    # Creación del método true
14    dbus_method :true, "out bool1:b" do 
15      [bool1 = true]
16    end
17
18    # Método con dos parámetros de salida
19    dbus_method :dos, "out bool2:b, out msg2:s" do 
20      [bool2 = true , msg2 = "Mensaje"] 
21    end
22
23    # Método con un param in, un param out
24    dbus_method :saludo, "in nombre:s, out saludo:s"  do |nombre|
25      [saludo = "Hola #{nombre}"]
26    end
27
28  end
29end
30
31MISERVICIO="org.ruby.fpscanner" 
32OBJETO1="/org/ruby/fpscanner" 
33
34    puts "Inicializando el servicio DBus" 
35    @dbus = DBus.session_bus
36
37    begin
38      @dbus_service = @dbus.request_service(MISERVICIO)
39    rescue DBus::NameRequestError
40      puts "Ha ocurrido un error al solicitar el registro de nombre DBus" 
41      raise
42    end
43
44    @fpscanner = FPScanner.new(OBJETO1)
45    @dbus_service.export(@fpscanner)
46
47    loop = DBus::Main.new
48    loop << @dbus
49    loop.run

F2 dos aplicaciones ruby interactuando

Me interesa desarrollar como prueba dos aplicaciones ruby que se hablen a través de DBUS.

  1. Me interesa que una de las app esté colgada del system-bus en mi Fedora manejando cierto hardware, "es el servidor".
  2. El cliente debe comunicarse con el "servidor" para conseguir interfase con el hw.

Procedimiento scan (1)

  1. El hardware es básicamente un scanner.
  2. Tomar imagen (scanear).
    • ¿Se puede pasar la imagen por DBus?

Referencias