监听 dbus 信号以在 debian 上挂载 mtp 设备 linux
Listening to dbus signals to mount mtp device on debian linux
我正在尝试编写一个 python 脚本来检测何时将 mtp 设备(在本例中为 Android phone)安装到 raspberry pi 3(运行宁 raspbian 杰西)。我想在 phone 插入时自动传输文件。
的第二个答案给出的脚本开始
我更改了一些内容以在 raspberry pi 上将其设置为 运行。当前脚本如下。当我 plug/unplug 我的 phone 时,我可以看到 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 和 signals/buses.
的了解非常有限
脚本:
#!/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)
我对 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 服务及其暴露的对象和接口:它使理解它们之间的关系变得容易得多。
我正在尝试编写一个 python 脚本来检测何时将 mtp 设备(在本例中为 Android phone)安装到 raspberry pi 3(运行宁 raspbian 杰西)。我想在 phone 插入时自动传输文件。
的第二个答案给出的脚本开始我更改了一些内容以在 raspberry pi 上将其设置为 运行。当前脚本如下。当我 plug/unplug 我的 phone 时,我可以看到 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 和 signals/buses.
的了解非常有限脚本:
#!/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)
我对 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 服务及其暴露的对象和接口:它使理解它们之间的关系变得容易得多。