I am creating a python-based opp obex server using bluez-obex, but I'm having trouble changing the directory. I based my code off of this and turned it into a class with a file path as it's input. I keep getting KeyError: 'object does not export any interfaces; you might need to pass object path as the 2nd argument for get()'
with my current code. Am I setting the path wrong? My class code and calling function are below.
from gi.repository import GLib
import pydbus
class opp_server():
def __init__(self, path):
self.BUS_NAME = 'org.bluez.obex'
self.PATH = '/org/bluez/obex'
self.AGENT_MANAGER_INTERFACE = 'org.bluez.obex.AgentManager1'
self.AGENT_INTERFACE = 'org.bluez.obex.Agent1'
self.SESSION_INTERFACE = 'org.bluez.obex.Session1'
self.TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
self.ses_bus = pydbus.SessionBus()
self.path = path
def transfer_status_handler(self, iface, props_changed, props_removed):
if iface == self.TRANSFER_INTERFACE:
status = props_changed.get('Status')
if status == 'complete':
print('Transfer complete')
elif status == 'queued':
print('Still queued')
elif status == 'active':
print('transferring')
elif status == 'suspended':
print('Suspended')
elif status == 'error':
print('error')
def iface_added_handler(self, dbus_path, interfaces):
if self.SESSION_INTERFACE in interfaces and 'server' in dbus_path:
print('Server session added')
elif self.TRANSFER_INTERFACE in interfaces and 'server' in dbus_path:
print('Transfer started')
transfer = self.ses_bus.get(self.BUS_NAME, dbus_path)
transfer.onPropertiesChanged = self.transfer_status_handler
def AuthorizePush(self):
print('Authorize Push', self.path)
transfer = self.ses_bus.get(self.BUS_NAME, self.path)
props = transfer.GetAll(self.TRANSFER_INTERFACE)
print(props)
return props.get('Name')
def Cancel(self):
print('Authorization Cancelled')
def Release(self):
pass
def server(self):
obex_mngr = self.ses_bus.get('org.bluez.obex', '/')
obex_mngr.onInterfacesAdded = self.iface_added_handler
mainloop = GLib.MainLoop()
self.ses_bus.register_object('/test/agent', self.AuthorizePush(), None)
print('Agent created')
agnt_mngr = ses_bus.get(self.BUS_NAME, self.PATH)
agnt_mngr.RegisterAgent('/test/agent')
print('Agent registered')
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
Calling the class
server = servertest.opp_server('/home/pi/GAMMA/ImageData')
server.server()
It looks like you have mixed up DBus object paths and filesystem paths. For AuthorizePush
the input is the DBus object path for the org.bluez.obex.Transfer1
interfaces but you are trying to use the filesystem path of where you want the file to be put.
You need to have the three methods with the same parameters when you publish/export your org.bluez.obex.Agent1
interface. It might worth looking at the pydbus tutorial for Exporting own objects
The obexd
is started with the information in: /usr/share/dbus-1/services/org.bluez.obex.service
which for me is:
[D-BUS Service]
Name=org.bluez.obex
Exec=/usr/lib/bluetooth/obexd
SystemdService=obex.service
obexd
can be started with other options as can be seen from the help:
$ /usr/lib/bluetooth/obexd -h
Usage:
obexd [OPTION?]
Help Options:
-h, --help Show help options
Application Options:
-d, --debug=DEBUG Enable debug information output
-p, --plugin=NAME,... Specify plugins to load
-P, --noplugin=NAME,... Specify plugins not to load
-n, --nodetach Run with logging in foreground
-r, --root=PATH Specify root folder location. Both absolute and relative can be used, but relative paths are assumed to be relative to user $HOME folder. Default $XDG_CACHE_HOME
-S, --root-setup=SCRIPT Root folder setup script
-l, --symlinks Allow symlinks leading outside of the root folder
-c, --capability=FILE Specify capability file, use '!' mark for scripts
-a, --auto-accept Automatically accept push requests
So you could use the --root=PATH
option to change the default location.
If you did want to change the path in your code, then you need to make the value returned from AuthorizePush
to have an absolute path. e.g:
def AuthorizePush(self, path):
transfer = ses_bus.get(BUS_NAME, path)
props = transfer.GetAll(TRANSFER_INTERFACE)
return '/tmp/' + props.get('Name')
This will put the file in the /tmp
directory.