Share files between 2 computers via bluetooth from terminal

First, you need to apt install bluez-tools obexpushd.

To send and receive files, you need to set up and pair the devices first.

SETUP


from Arch Wiki - bluetooth:

Bluetoothctl

Start the bluetoothctl interactive command. There one can input help to get a list of available commands.

  • Turn the power to the controller on by entering power on. It is off by default.
  • Enter devices to get the MAC Address of the device with which to pair.
  • Enter device discovery mode with scan on command if device is not yet on the list.
  • Turn the agent on with agent on.
  • Enter pair MAC Address to do the pairing (tab completion works).
  • If using a device without a PIN, one may need to manually trust the device before it can reconnect successfully. Enter trust MAC Address to do so.
  • Finally, use connect MAC_address to establish a connection.

The last two bullet points are not necessary for the send part of a file transfer, but you need the connect later for the receive part.

An example session may look this way:

# bluetoothctl 
[NEW] Controller 00:10:20:30:40:50 pi [default]
[bluetooth]# agent KeyboardOnly 
Agent registered
[bluetooth]# default-agent 
Default agent request successful
[bluetooth]# scan on
Discovery started
[CHG] Controller 00:10:20:30:40:50 Discovering: yes
[NEW] Device 00:12:34:56:78:90 myLino
[CHG] Device 00:12:34:56:78:90 LegacyPairing: yes
[bluetooth]# pair 00:12:34:56:78:90
Attempting to pair with 00:12:34:56:78:90
[CHG] Device 00:12:34:56:78:90 Connected: yes
[CHG] Device 00:12:34:56:78:90 Connected: no
[CHG] Device 00:12:34:56:78:90 Connected: yes
Request PIN code
[agent] Enter PIN code: 1234
[CHG] Device 00:12:34:56:78:90 Paired: yes
Pairing successful
[CHG] Device 00:12:34:56:78:90 Connected: no
[bluetooth]# connect 00:12:34:56:78:90
Attempting to connect to 00:12:34:56:78:90
[CHG] Device 00:12:34:56:78:90 Connected: yes
Connection successful

To make changes permanent and in order to have the device active after a reboot, a udev rule is needed:

/etc/udev/rules.d/10-local.rules

# Set bluetooth power up
ACTION=="add", KERNEL=="hci0", RUN+="/usr/bin/hciconfig %k up"

Tip: Replace KERNEL=="hci0" with KERNEL=="hci[0-9]*" to match all BT interfaces.

After a suspend/resume-cycle, the device can be powered on automatically using a custom systemd service:

/etc/systemd/system/[email protected]

[Unit]
Description=Bluetooth auto power on
After=bluetooth.service sys-subsystem-bluetooth-devices-%i.device suspend.target

[Service]
Type=oneshot
ExecStart=/usr/bin/hciconfig %i up

[Install]
WantedBy=suspend.target

Enable an instance of the unit using your bluetooth device name, for example [email protected].


Now your devices are paired. Check that you can see the other with bt-device -l.

SEND

Next, you have to send up your systemd infrastructure for the send to work, otherwise you get the following error:

Acquiring proxy failed: Error calling StartServiceByName for org.bluez.obex: GDBus.Error:org.freedesktop.systemd1.LoadFailed: Unit dbus-org.bluez.obex.service failed to load: No such file or directory.

Make the necessary systemd changes with

systemctl --user start obex
sudo systemctl --global enable obex

This makes sure you can send files. A sudo also in the first line will fail!

You can send files now by bluetooth-sendto --device=12:34:56:78:9A:BC filename filename2. If a transfer hangs at 100%, a ctrlc finalizes it (or aborts earlier).

To know your device name (12:34:56:78:9A:BC), you can issue bt-device -l.

RECEIVE


from Raspberry Pi forum:

We want to set up a OBEX push server, this is why obexpushd was needed.

The compatibility flag on the Bluetooth daemon is needed, you have to edit /etc/systemd/system/dbus-org.bluez.service with the editor of your choice by adding the -C flag to the end of the ExecStart= line. It should look like this:

ExecStart=/usr/lib/bluetooth/bluetoothd -C

Reboot or restart the service with sudo systemctl daemon-reload after editing. Choose a specific directory where received files are placed, for example by sudo mkdir /bluetooth.

Start the server with sudo obexpushd -B -o /bluetooth -n, it should respond with:

obexpushd 0.11.2 Copyright (C) 2006-2010 Hendrik Sattler
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
Listening on bluetooth/[00:00:00:00:00:00]:9

If that's not working, and you get:

obexpushd 0.11.2 Copyright (C) 2006-2010 Hendrik Sattler
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
BtOBEX_ServerRegister: Address already in use
net_init() failed

it could be because you have another daemon or program running which occupies the rfcomm channel 9 that obexpushd uses by default. In this case, change the channel to 23 like this:

sudo obexpushd -B23 -o /bluetooth -n

to use channel 23.

Once you get obexpushd running, open a second terminal window. You can verify that the OBEX service is registered with

sudo sdptool browse local

It should list (at channel 23 in this case), among others, this:

Service Name: OBEX Object Push
Service Description: a free OBEX server
Service Provider: obexpushd
Service RecHandle: 0x10005
Service Class ID List:
  "OBEX Object Push" (0x1105)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 23
  "OBEX" (0x0008)
Profile Descriptor List:
  "OBEX Object Push" (0x1105)
    Version: 0x0100

In that window, while obexpushd is still running, use bluetoothctl to set discoverable on. Now pair from your other device. Pairing MUST be done while obexpushd is running, or the other device wont recognize the service is available. If the phone is already paired, remove it from your other device, use bluetoothctl to remove it from the Ubuntu computer, and re-pair.

After you connect (the last bullet point from the above list), you should be able to receive files. They will appear in the /bluetooth directory. Notice that they will be owned by root, so you'll need sudo to access them. Or you can do a chmod 0777 /bluetooth for a public exchange directory, since the bluetooth authentification is device-based and not user-based anyway.

In order to automate the obexpushd command, create the file /etc/systemd/system/obexpush.service

[Unit]
Description=OBEX Push service
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/obexpushd -B23 -o /bluetooth -n

[Install]
WantedBy=multi-user.target

Then, set that to autostart with

sudo systemctl enable obexpush

After a reboot or restart of the service with sudo systemctl daemon-reload, you should be able to send and receive files in both directions now.

Don't forget to connect the devices when trying to receive files.