我正在尝试编写一个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)
答案 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服务及其暴露的对象和接口:它使得更容易理解它们之间的相互关系。