代码之家  ›  专栏  ›  技术社区  ›  Sarah Kirby

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

  •  2
  • Sarah Kirby  · 技术社区  · 7 年前

    我正在尝试编写一个python脚本,该脚本将检测mtp设备(在本例中为Android手机)何时安装到raspberry pi 3(运行raspbian jessie)。我想在手机接通电源时自动将文件传输到手机。

    this question

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

    我在一个类似的问题中读到,这是一个权限问题,所以我尝试以sudo./usb_系统的形式运行脚本。但是我仍然得到同样的错误。

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

    我是否使用了get\u 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 回复  |  直到 7 年前
        1
  •  1
  •   Jussi Kukkonen    7 年前

    我对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服务及其公开的对象和接口:这样可以更容易地理解它们之间的关系。