Как я могу получать события из Skype через D-Bus с помощью python?

(я знаю, что это похоже на Python и d-bus: Как настроить основной цикл?, но без полного кода в «Ответе» я не могу понять, где я ошибаюсь. Это может быть просто изменение в Skype)

Вот моя программа:

import gobject
import dbus
import dbus.mainloop.glib
dbus_gmainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
sessbus = dbus.SessionBus()
skype = sessbus.get_object('com.Skype.API', '/com/Skype')
skypec = sessbus.get_object('com.Skype.API', '/com/Skype/Client')
skype_iface = dbus.Interface(skype, dbus_interface='com.Skype.API')
skype_iface.Invoke("NAME py1")
# ... waits for user click in Skype ...
#==> dbus.String(u'OK')
skype_iface.Invoke("PROTOCOL 7")
#==> dbus.String(u'PROTOCOL 7')
def got_signal(sender, destination, member, interface, path):
  print "got_signal(sender=%s, dest=%s, member=%s, iface=%s, path=%s)" \
    % (sender, destination, member, interface, path)

skypec.connect_to_signal('Notify', got_signal, sender_keyword='sender', \
  destination_keyword='destination', member_keyword='member', \
  interface_keyword='interface', path_keyword='path')

mainloop = gobject.MainLoop()
mainloop.run()

При запуске (например, python skype-call.py) он приостанавливается после отправки команды NAME py1 в Skype и ожидает интерактивного подтверждения в пользовательском интерфейсе Skype, а затем продолжает работу. Таким образом, объект skype_iface явно работает, по крайней мере, до определенной степени.

Однако затем python выдает следующую ошибку:

ERROR:dbus.proxies:Introspect error on :1.152:/com/Skype/Client: dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownObject: No such object path '/com/Skype/Client'

Я также пробовал следующее (вместо connect_to_signal, непосредственно перед запуском основного цикла gobject в конце):

def receiver(x, **kwargs):
  print "receiver(%s)" % (x,)

sessbus.add_signal_receiver(receiver, signal_name='Notify', \
  dbus_interface='com.Skype.API', bus_name='com.Skype.API', path='/com/Skype/Client')

И хотя он не жаловался, его так и не отозвали. Я попытался отправить пользователю Skype сообщение. Какие события должны вызывать его?

Документы на https://dev.skype.com/desktop-api-reference#DBUSUsage не очень полезны.

Это Skype для Linux 4.2.0.11 на многоархитектурной платформе Debian 7.0 (amd64 / i386).


person Rob Starling    schedule 26.05.2013    source источник


Ответы (2)


оглядываясь назад на http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#exporting-methods-with-dbus-service-method, я попытался взять их пример:

import gobject
import dbus
from dbus.decorators import method
import dbus.mainloop.glib
import dbus.service

dbus_gmainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
sessbus = dbus.SessionBus()

class Example(dbus.service.Object):
    def __init__(self, bus):
        dbus.service.Object.__init__(self, bus, '/com/Skype/Client')

    @method(dbus_interface='com.Skype.API.Client', in_signature='s', \
            sender_keyword='sender', destination_keyword='dest', \
            rel_path_keyword='rel_path', path_keyword='path', \
            message_keyword='message', connection_keyword='conn')
    def Notify(self, s, sender=None, dest=None, rel_path=None, path=None, \
               message=None, conn=None):
        print "Notify(%s, sender=%s, dest=%s, rel_path=%s, path=%s, message=%s, conn=%s)" \
              % (s, sender, path, dest, message, rel_path, conn,)

# make one:
ex = Example(sessbus)

skype = sessbus.get_object('com.Skype.API', '/com/Skype')
skype_iface = dbus.Interface(skype, dbus_interface='com.Skype.API')
skype_iface.Invoke("NAME py1")
##=> dbus.String(u'OK')
skype_iface.Invoke("PROTOCOL 7")
##=> dbus.String(u'PROTOCOL 7')

mainloop = gobject.MainLoop()
mainloop.run()

и вот, я получаю Notify звонка:

Notify(CONNSTATUS ONLINE, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Notify(CURRENTUSERHANDLE ******, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Notify(USERSTATUS ONLINE, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Очевидно, это не лучший пример хорошо структурированной программы, но биты d-bus, похоже, подключаются.

person Rob Starling    schedule 08.06.2013
comment
Круто, я не знал о методах получения сигналов таким образом, но, видимо, это работает .. - person redShadow; 08.06.2013
comment
Вот и два других вопроса: "как прослушивать только определенные сигналы с помощью python dbus"> stackoverflow.com/questions/14901615/, stackoverflow.com/questions/6379553/ - person Rob Starling; 08.06.2013

Пытаюсь отладить то же самое, может, вместе что-нибудь разберемся (я тоже использую wheezy amd64, кстати) ...

Насколько я понял, похоже, что com.Skype.API не раскрывает объект с именем /com/Skype/Client (и d-feet это подтверждают).

Я использовал dbus-monitor для наблюдения за автобусом, отправляя сообщение на свой аккаунт в скайпе. Среди других результатов я получил следующее:

method call sender=:1.43 -> dest=:1.132 serial=324 path=/com/Skype/Client; interface=com.Skype.API.Client; member=Notify
   string "CHAT #rshk-testuser1/$myusername;<hex-code-here> ACTIVITY_TIMESTAMP 1370647479"
error sender=:1.132 -> dest=:1.43 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=324
   string "Method "Notify" with signature "s" on interface "com.Skype.API.Client" doesn't exist
"
method call sender=:1.43 -> dest=:1.132 serial=325 path=/com/Skype/Client; interface=com.Skype.API.Client; member=Notify
   string "CHATMESSAGE 1538281 STATUS RECEIVED"
error sender=:1.132 -> dest=:1.43 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=325
   string "Method "Notify" with signature "s" on interface "com.Skype.API.Client" doesn't exist
"

Итак, похоже, что есть еще один интерфейс с именем com.Skype.API.Client, который раскрывает объект /com/Skype/Client, но по какой-то причине этот интерфейс недоступен ...

Я взглянул на /etc/dbus-1/system.d/skype.conf, где указан только com.Skype.API.

Я не очень разбираюсь в dbus, но пытаюсь копнуть дальше и понять в чем дело ..

person redShadow    schedule 07.06.2013
comment
о ... интересно, нужно ли нам что-то добавить в skype.conf. - person Rob Starling; 08.06.2013
comment
Кроме того, мы должны выяснить, правда ли это по-прежнему: Skype использует очень старую версию D-Bus, несовместимую с текущим демоном и библиотекой. Пока они не обновят это, вы не сможете его использовать. - lists.freedesktop.org/archives/dbus/2006-November/ 006492.html - не похоже, так как мы можем отправить, но может ... - person Rob Starling; 08.06.2013