User:Magick777/Adventures with D-Bus

(Step 2: dbus-send (actually, a false step))
(Undo revision 51581 by joerg_rw (Talk))
 
(9 intermediate revisions not shown)
Line 1: Line 1:
-
This page started because I'm trying to figure out D-BUS, as a relative newbie to Python and Telepathy, and the documentation is, shall we say, "fragmented". All the D-BUS recipes on the Wiki don't seem to include a simple way to place a call via the sofiasip client. The Telepathy documentation speaks to a vague architecture, not to my N900's implementation of it, and seems better for someone who wants to write a whole new interface than someone who just wants to use an existing one. I've read more source code and more forum posts than you can shake a stick at and I'm still none the wiser. So, this is a generic HOWTO for newbies (written by one) on how to track down an existing application's behaviour on D-BUS and replicate it. Work in progress September 2010.
+
This page started because I'm trying to figure out D-Bus, as a relative newbie to Python and Telepathy, and the documentation is, shall we say, "fragmented". All the D-Bus recipes on the Wiki don't seem to include a simple way to place a call via the sofiasip client. The Telepathy documentation speaks to a vague architecture, not to my [[Nokia N900|N900]]'s implementation of it, and seems better for someone who wants to write a whole new interface than someone who just wants to use an existing one. I've read more source code and more forum posts than you can shake a stick at and I'm still none the wiser. So, this is a generic HOWTO for newbies (written by one) on how to track down an existing application's behaviour on D-Bus and replicate it. Work in progress September 2010.
== Step 1: dbus-monitor ==
== Step 1: dbus-monitor ==
-
After some playing around with dbus-monitor, I've established that when I make a SIP call via the inbuilt Phone application, the first thing that happens on the session bus is:
+
After some playing around with <code>dbus-monitor</code>, I've established that when I make a SIP call via the inbuilt Phone application, the first thing that happens on the session bus is:
-
method call sender=:1.121 ->
+
<pre>
-
dest=org.freedesktop.Telepathy.AccountManager
+
method call sender=:1.121 ->
-
serial=439
+
dest=org.freedesktop.Telepathy.AccountManager
-
path=/org/freedesktop/Telepathy/Account/sofiasip/sip/_31030137_40sipgate_2eco_2euk0;
+
serial=439
-
interface=com.nokia.Account.Interface.ChannelRequests;
+
path=/org/freedesktop/Telepathy/Account/sofiasip/sip/_31030137_40sipgate_2eco_2euk0;
-
member=Create
+
interface=com.nokia.Account.Interface.ChannelRequests;
-
    array [
+
member=Create
-
      dict entry(
+
  array [
-
          string "org.freedesktop.Telepathy.Channel.TargetHandleType"
+
      dict entry(
-
          variant            uint32 1
+
        string "org.freedesktop.Telepathy.Channel.TargetHandleType"
-
      )
+
        variant            uint32 1
-
      dict entry(
+
      )
-
          string "org.freedesktop.Telepathy.Channel.TargetID"
+
      dict entry(
-
          variant            string "sip:50000@sipgate.co.uk"
+
        string "org.freedesktop.Telepathy.Channel.TargetID"
-
      )
+
        variant            string "sip:50000@sipgate.co.uk"
-
      dict entry(
+
      )
-
          string "org.freedesktop.Telepathy.Channel.ChannelType"
+
      dict entry(
-
          variant            string "org.freedesktop.Telepathy.Channel.Type.StreamedMedia"
+
        string "org.freedesktop.Telepathy.Channel.ChannelType"
-
      )
+
        variant            string "org.freedesktop.Telepathy.Channel.Type.StreamedMedia"
-
    ]
+
      )
-
    uint64 14701758
+
  ]
-
    string ""
+
  uint64 14701758
 +
  string ""
 +
</pre>
and, for a call to a PSTN number, via a different SIP account:
and, for a call to a PSTN number, via a different SIP account:
-
method call sender=:1.191 ->
+
<pre>
-
dest=org.freedesktop.Telepathy.AccountManager
+
method call sender=:1.191 ->
-
serial=500
+
dest=org.freedesktop.Telepathy.AccountManager
-
path=/org/freedesktop/Telepathy/Account/sofiasip/sip/_330147398_40sip_2evoipfone_2eco_2euk0;  
+
serial=500
-
interface=com.nokia.Account.Interface.ChannelRequests;  
+
path=/org/freedesktop/Telepathy/Account/sofiasip/sip/_330147398_40sip_2evoipfone_2eco_2euk0;  
-
member=Create
+
interface=com.nokia.Account.Interface.ChannelRequests;  
-
    array [
+
member=Create
-
      dict entry(
+
  array [
-
          string "org.freedesktop.Telepathy.Channel.TargetHandleType"
+
      dict entry(
-
          variant            uint32 1
+
        string "org.freedesktop.Telepathy.Channel.TargetHandleType"
-
      )
+
        variant            uint32 1
-
      dict entry(
+
      )
-
          string "org.freedesktop.Telepathy.Channel.ChannelType"
+
      dict entry(
-
          variant            string "org.freedesktop.Telepathy.Channel.Type.StreamedMedia"
+
        string "org.freedesktop.Telepathy.Channel.ChannelType"
-
      )
+
        variant            string "org.freedesktop.Telepathy.Channel.Type.StreamedMedia"
-
      dict entry(
+
      )
-
          string "org.freedesktop.Telepathy.Channel.TargetID"
+
      dict entry(
-
          variant            string "08081703703"
+
        string "org.freedesktop.Telepathy.Channel.TargetID"
-
      )
+
        variant            string "08081703703"
-
    ]
+
      )
-
    uint64 1284595510
+
  ]
-
    string ""
+
  uint64 1284595510
 +
  string ""
 +
</pre>
From this, we can deduce that:
From this, we can deduce that:
-
* we need to make a method call over D-BUS to initiate the SIP call
+
* we need to make a method call over D-Bus to initiate the SIP call
-
* we need to send it to dest=org.freedesktop.Telepathy.AccountManager
+
* we need to send it to <code>org.freedesktop.Telepathy.AccountManager</code>
-
* our path is /org/freedesktop/Telepathy/Account/ plus SofiaSIP account path
+
* our path is <code>/org/freedesktop/Telepathy/Account/</code> plus SofiaSIP account path
** which can be found via "mc-tool list" (package libmissioncontrol-utils)
** which can be found via "mc-tool list" (package libmissioncontrol-utils)
-
** or, no doubt, via D-BUS, but we'll worry about that later
+
** or, no doubt, via D-Bus, but we'll worry about that later
-
* our interface is com.nokia.Account.Interface.ChannelRequests
+
* our interface is <code>com.nokia.Account.Interface.ChannelRequests</code>
* the action we must take on that interface is to Create (a new channel)
* the action we must take on that interface is to Create (a new channel)
* for which we must supply an array of dicts, a number and an empty string
* for which we must supply an array of dicts, a number and an empty string
Line 66: Line 70:
** ChannelType is StreamedMedia
** ChannelType is StreamedMedia
** Target ID contains our destination SIP address or phone number
** Target ID contains our destination SIP address or phone number
-
** not sure what that UInt64 is about, some kind of timestamp?
+
** not sure what that <code>uint64</code> is about, some kind of timestamp?
and we can hope that, if we can pack up that set of instructions and deliver it to telepathy-sofiasip, it will (hopefully) place a call for us.
and we can hope that, if we can pack up that set of instructions and deliver it to telepathy-sofiasip, it will (hopefully) place a call for us.
Line 72: Line 76:
== Step 2: dbus-send (actually, a false step) ==
== Step 2: dbus-send (actually, a false step) ==
-
I spent a while playing with dbus-send and reading forums, until a thread led me to the following statement in the fine manual page:  
+
I spent a while playing with dbus-send and reading the forums, until a thread led me to the following statement in the (fine) manual page:  
'''"dbus-send does not permit empty containers or nested containers (e.g. arrays of variants)"'''
'''"dbus-send does not permit empty containers or nested containers (e.g. arrays of variants)"'''
-
We can assume that dbus-send isn't going to like an array of dicts any more than it likes an array of variants, ergo, that what we want to do cannot be done with dbus-send. That would explain why there's no simple recipe on the Wiki, then. Well, if we can't use dbus-send, I guess we'll have to resort to python.
+
We can assume that <code>dbus-send</code> isn't going to like an array of dicts any more than it likes an array of variants, ergo, that what we want to do cannot be done with <code>dbus-send</code>. That would explain why there's no simple recipe on the Wiki, then. Well, if we can't use <code>dbus-send</code>, I guess we'll have to resort to Python. That's going to be fun; I'm not in the habit of conversing with reptiles.
== Step 3: python ==
== Step 3: python ==
 +
 +
The only example I could find of a shell script making a D-Bus method call is the "athome" script on the [[DbusScripts]] page, which in theory should act as a starting point for what I want to do.
 +
 +
<source lang="python">
 +
#!/usr/bin/python
 +
 +
import dbus
 +
import sys
 +
import re
 +
import telepathy
 +
 +
# This gets us a connnection to the session bus
 +
bus = dbus.SessionBus()
 +
 +
# This would seem to set up a proxy object, referring to our target SIP  account
 +
account = bus.get_object('org.freedesktop.Telepathy.AccountManager',
 +
                        '/org/freedesktop/Telepathy/Account/sofiasip/sip/_309517129090')
 +
 +
# This would seem to make a method call on the object
 +
#account.Set('org.freedesktop.Telepathy.Account', 'RequestedPresence', \
 +
#              dbus.Struct(( dbus.UInt32( presence_const) ,  presence_text,  ""), signature='uss'),
 +
#              dbus_interface='org.freedesktop.DBus.Properties')
 +
 +
# We need to make a method call to Create a new channel
 +
 +
account.Set('org.freedesktop.Telepathy.Account', 'RequestedPresence', \
 +
              dbus.Struct(( dbus.UInt32( presence_const) ,  presence_text,  ""), signature='uss'),
 +
              dbus_interface='org.freedesktop.DBus.Properties')
 +
</source>
 +
 +
[[Category:Python]]

Latest revision as of 16:13, 12 May 2013

This page started because I'm trying to figure out D-Bus, as a relative newbie to Python and Telepathy, and the documentation is, shall we say, "fragmented". All the D-Bus recipes on the Wiki don't seem to include a simple way to place a call via the sofiasip client. The Telepathy documentation speaks to a vague architecture, not to my N900's implementation of it, and seems better for someone who wants to write a whole new interface than someone who just wants to use an existing one. I've read more source code and more forum posts than you can shake a stick at and I'm still none the wiser. So, this is a generic HOWTO for newbies (written by one) on how to track down an existing application's behaviour on D-Bus and replicate it. Work in progress September 2010.

[edit] Step 1: dbus-monitor

After some playing around with dbus-monitor, I've established that when I make a SIP call via the inbuilt Phone application, the first thing that happens on the session bus is:

method call sender=:1.121 ->
dest=org.freedesktop.Telepathy.AccountManager
serial=439
path=/org/freedesktop/Telepathy/Account/sofiasip/sip/_31030137_40sipgate_2eco_2euk0;
interface=com.nokia.Account.Interface.ChannelRequests;
member=Create
   array [
      dict entry(
         string "org.freedesktop.Telepathy.Channel.TargetHandleType"
         variant             uint32 1
      )
      dict entry(
         string "org.freedesktop.Telepathy.Channel.TargetID"
         variant             string "sip:50000@sipgate.co.uk"
      )
      dict entry(
         string "org.freedesktop.Telepathy.Channel.ChannelType"
         variant             string "org.freedesktop.Telepathy.Channel.Type.StreamedMedia"
      )
   ]
   uint64 14701758
   string ""

and, for a call to a PSTN number, via a different SIP account:

method call sender=:1.191 ->
dest=org.freedesktop.Telepathy.AccountManager
serial=500
path=/org/freedesktop/Telepathy/Account/sofiasip/sip/_330147398_40sip_2evoipfone_2eco_2euk0; 
interface=com.nokia.Account.Interface.ChannelRequests; 
member=Create
   array [
      dict entry(
         string "org.freedesktop.Telepathy.Channel.TargetHandleType"
         variant             uint32 1
      )
      dict entry(
         string "org.freedesktop.Telepathy.Channel.ChannelType"
         variant             string "org.freedesktop.Telepathy.Channel.Type.StreamedMedia"
      )
      dict entry(
         string "org.freedesktop.Telepathy.Channel.TargetID"
         variant             string "08081703703"
      )
   ]
   uint64 1284595510
   string ""

From this, we can deduce that:

  • we need to make a method call over D-Bus to initiate the SIP call
  • we need to send it to org.freedesktop.Telepathy.AccountManager
  • our path is /org/freedesktop/Telepathy/Account/ plus SofiaSIP account path
    • which can be found via "mc-tool list" (package libmissioncontrol-utils)
    • or, no doubt, via D-Bus, but we'll worry about that later
  • our interface is com.nokia.Account.Interface.ChannelRequests
  • the action we must take on that interface is to Create (a new channel)
  • for which we must supply an array of dicts, a number and an empty string
    • TargetHandleType is 1
    • ChannelType is StreamedMedia
    • Target ID contains our destination SIP address or phone number
    • not sure what that uint64 is about, some kind of timestamp?

and we can hope that, if we can pack up that set of instructions and deliver it to telepathy-sofiasip, it will (hopefully) place a call for us.

[edit] Step 2: dbus-send (actually, a false step)

I spent a while playing with dbus-send and reading the forums, until a thread led me to the following statement in the (fine) manual page:

"dbus-send does not permit empty containers or nested containers (e.g. arrays of variants)"

We can assume that dbus-send isn't going to like an array of dicts any more than it likes an array of variants, ergo, that what we want to do cannot be done with dbus-send. That would explain why there's no simple recipe on the Wiki, then. Well, if we can't use dbus-send, I guess we'll have to resort to Python. That's going to be fun; I'm not in the habit of conversing with reptiles.

[edit] Step 3: python

The only example I could find of a shell script making a D-Bus method call is the "athome" script on the DbusScripts page, which in theory should act as a starting point for what I want to do.

#!/usr/bin/python 
 
import dbus
import sys
import re
import telepathy
 
# This gets us a connnection to the session bus
bus = dbus.SessionBus()
 
# This would seem to set up a proxy object, referring to our target SIP  account
account = bus.get_object('org.freedesktop.Telepathy.AccountManager',
                         '/org/freedesktop/Telepathy/Account/sofiasip/sip/_309517129090')
 
# This would seem to make a method call on the object
#account.Set('org.freedesktop.Telepathy.Account', 'RequestedPresence', \
#               dbus.Struct(( dbus.UInt32( presence_const) ,  presence_text,  ""), signature='uss'),
#               dbus_interface='org.freedesktop.DBus.Properties')
 
# We need to make a method call to Create a new channel
 
account.Set('org.freedesktop.Telepathy.Account', 'RequestedPresence', \
               dbus.Struct(( dbus.UInt32( presence_const) ,  presence_text,  ""), signature='uss'),
               dbus_interface='org.freedesktop.DBus.Properties')