听dbus信号在debian linux上安装mtp设备

时间:2017-07-21 01:35:55

标签: python linux debian dbus mtp

我正在尝试编写一个python脚本,它将检测何时mtp设备(在本例中为Android手机)已安装到树莓派3(运行raspbian jessie)。我想在插入电话时自动将文件传输到手机。

我从作为this question

的第二个答案的脚本开始

我改变了一些东西,让它在我的覆盆子pi上运行。目前的脚本如下。当我插上/拔掉手机时,我可以看到UnitNew和UnitRemoved信号。当它到达path_to_device函数时,我收到此错误:

DBusException: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.systemd1.Manager was not provided by any .service files

我在类似的问题中读到这是一个权限问题,所以我尝试将脚本运行为sudo ./usb_SYSTEM.py,但我仍然遇到同样的错误。

我也尝试过使用SessionBus而不是SystemBus。信号不同,总线名称是org.gtk.vfs.MountTracker。我仍然得到同样的错误,这次它说org.gtk.vfs.MountTracker不是一个可用的服务。当我尝试使用sudo运行SessionBus版本时,我根本看不到信号。

我是否使用get_object()函数的正确输入?和正确的总线类型?由于信号是广播的,因此没有目的地总线,我不确定这是否是问题的一部分。我对linux和信号/总线的理解非常有限。

脚本:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import dbus
import dbus.service
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
    import dbus.glib

from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
import sys
import os


class DeviceManager:
    def __init__(self):
        self.bus = dbus.SystemBus()
        self.bus.add_signal_receiver(self.device_added,
                        'UnitNew',
                        'org.freedesktop.systemd1.Manager',
                        None,
                        '/org/freedesktop/systemd1',
                        path_keyword='path')

        self.bus.add_signal_receiver(self.device_removed,
                        'UnitRemoved',
                        'org.freedesktop.systemd1.Manager',
                        None,
                        '/org/freedesktop/systemd1',
                        path_keyword='path')

        self.bus.add_signal_receiver(self.print_event, None, None, None, None,
                                     sender_keyword='sender', message_keyword='message')

    def path_to_device(self, path):
        return self.bus.get_object('org.freedesktop.systemd1.Manager', path)

    def device_added(self, *args, **kwds):
        path = kwds['path']
        print 'Added', path
        properties = self.path_to_device(path).GetAllProperties()
        print properties.get('info.category')
        if properties.get('info.category') == u'volume':
            label, dev = properties.get('volume.label'), properties.get('block.device')
            print 'Mounting %s on /mnt/%s' %(dev, label)
            ## os.system('mount %s /mnt/%s' %(dev, label))

    def device_removed(self, *args, **kwds):
        path = kwds['path']
        print 'Removed', path

    def print_event(*args, **sender):
        print "got signal from:"
        print sender

if __name__ == '__main__':
    DBusGMainLoop(set_as_default=True)

    m = DeviceManager()

    mainloop = GLib.MainLoop()
    try:
        mainloop.run()
    except KeyboardInterrupt:
        mainloop.quit()
        print 'Exiting...'
        sys.exit(0)

1 个答案:

答案 0 :(得分:1)

我对systemd D-Bus API不够熟悉,无法判断一般方法是否正确,但这应该有助于解决具体问题:

self.bus.get_object('org.freedesktop.systemd1.Manager', path)

bus.get_object()的第一个参数是服务名称(通常是服务文档中的已知名称)。我非常确定' org.freedesktop.systemd1'是您应该使用的服务名称。您当前使用的那个(' org.freedesktop.systemd1.Manager')是由该服务公开的对象之一实现的接口之一。

接口和服务名称通常看起来很相似的事实在我看来是D-Bus中的设计错误...如果d-feet D-Bus调试器在raspbian上可用(或者你有另一个linux盒子到测试),我建议使用它来查看所有D-Bus服务及其暴露的对象和接口:它使得更容易理解它们之间的相互关系。