pythonbluetoothbluezobex

Python opp obex server using Bluez-obex and pydbus?


For my project, I need to downlink .zip files over Bluetooth. I am using python and obex for this. I have a working python opp client implemented (shout-out to ukBaz for the help), but I am still using os to start the server, so the rest of my server program has no idea when a file is received. The rest of the program is completed, but without output from the server, I can't trigger the unzip function to run. I've read the bluez-obex API documentation and there doesn't seem to be anything on starting a server. Is there another way of doing this? My code is below.

os.system("sudo obexpushd -B -o /home/pi/Desktop/ -n")

Solution

  • I am not familiar with obexpushd and what it gives you over using the functionality that is there with obexd.

    My understanding is that you need to create an obex-agent to accept/reject a Bluetooth object push request with obexd.

    Monitoring the InterfacesAdded DBus signal should give you the information that you need to know when a transfer has started. You can then monitor the PropertiesChanged signal for when the status changes.

    I was able to push a photo from my phone to a Raspberry Pi with the following running on the RPi (I had my phone and RPi already paired):

    from gi.repository import GLib
    import pydbus
    
    BUS_NAME = 'org.bluez.obex'
    PATH = '/org/bluez/obex'
    AGENT_MANAGER_INTERFACE = 'org.bluez.obex.AgentManager1'
    AGENT_INTERFACE = 'org.bluez.obex.Agent1'
    SESSION_INTERFACE = 'org.bluez.obex.Session1'
    TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
    
    ses_bus = pydbus.SessionBus()
    
    
    def transfer_status_handler(iface, props_changed, props_removed):
        if iface == 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(dbus_path, interfaces):
        if SESSION_INTERFACE in interfaces and 'server' in dbus_path:
            print('Server session added')
        elif TRANSFER_INTERFACE in interfaces and 'server' in dbus_path:
            print('Transfer started')
            transfer = ses_bus.get(BUS_NAME, dbus_path)
            transfer.onPropertiesChanged = transfer_status_handler
    
    
    class Agent:
        """
          <node>
            <interface name='org.bluez.obex.Agent1'>
              <method name='Release'>
              </method>
              <method name='AuthorizePush'>
                <arg type='s' name='path' direction='out'/>
                <arg type='o' name='transfer' direction='in'/>
              </method>
              <method name='Cancel'>
              </method>
            </interface>
          </node>
        """
        def AuthorizePush(self, path):
            print('Authorize Push', path)
            transfer = ses_bus.get(BUS_NAME, path)
            props = transfer.GetAll(TRANSFER_INTERFACE)
            print(props)
            return props.get('Name')
    
        def Cancel(self):
            print('Authorization Cancelled')
    
        def Release(self):
            pass
    
    
    if __name__ == '__main__':
        obex_mngr = ses_bus.get('org.bluez.obex', '/')
        obex_mngr.onInterfacesAdded = iface_added_handler
        mainloop = GLib.MainLoop()
        ses_bus.register_object('/test/agent', Agent(), None)
        print('Agent created')
        agnt_mngr = ses_bus.get(BUS_NAME, PATH)
        agnt_mngr.RegisterAgent('/test/agent')
        print('Agent registered')
        try:
            mainloop.run()
        except KeyboardInterrupt:
            mainloop.quit()
    

    This code just accepts any request that is made of it. This is probably a bad thing to do and people might want to add some checking (or prompt the user) if the file should be accepted.