14

I'm looking to develop a platform for my car which automatically connects any device which attempts to connect to the Pi via bluetooth. Currently it requires a pairing accept by the Pi but in this case there will be no screen so it will need to do it automatically. How can I accomplish this?

Darth Vader
  • 4,206
  • 24
  • 45
  • 69
Oliver Kuchies
  • 235
  • 1
  • 4
  • 13
  • could you please elaborate on which pi model that you have, as only the pi 3 is carib;e of bluetooth without external hardware? – Mohammad Ali May 17 '16 at 14:18
  • Raspberry Pi 3 Model B - Built in bluetooth – Oliver Kuchies May 18 '16 at 00:43
  • So all you expect is for the Pi to be constantly broadcasting and to accept any pairing connections being made by your phone? you do understand the security implications? right? And also is writing a small Python script to do the job an acceptable solution? – Mohammad Ali May 18 '16 at 03:33
  • Yep but to make it more secure I suggest showing how to limit to one connection before rediscovering. Also feel free to add security implications to answer to help others :) – Oliver Kuchies May 18 '16 at 04:28
  • wont using as custom uuid, handle the security issue? – Murtaza Haji Mar 05 '21 at 17:37

5 Answers5

12

(Note that this answer is no longer working as of Raspbian Jessie, since bluez removed the bluetooth-agent command)

So currently you state that you can connect to the Pi just fine, but require a monitor for the pairing process.

Note: accepting any connection is an incredibly insecure idea, and if you are only using a limited set of devices, setting them up as trusted devices would make a lot more sense as it would limit connection to your Mac addresses but wold not allow for new devices to be added without a monitor

But anyway, the commands that you will need to run to accept all connections being made to the Pi, to make it discoverable and to set a predictable pin are listed below:

Note: you may need to change the zero in hci0 to your devices Bluetooth number.

hciconfig hci0 up
hciconfig hci0 sspmode 1
hciconfig hci0 piscan
sudo bluetooth-agent 1234

Now after running these commands and seeing if they work as expected we can move on to setting them up to start on the boot of your Pi.

  1. We start by creating a bash file by running the command sudo nano mohammadIsAmazing.sh
  2. We now enter the following into that file:

    #!/bin/sh
    sleep 20
    hciconfig hci0 up
    hciconfig hci0 sspmode 1
    hciconfig hci0 piscan
    sudo bluetooth-agent 1234
    
  3. Now we save and close our file using the control key and x

  4. We open up the file /etc/rc.local using the following command:

    Sudo nano /etc/rc.local
    
  5. Now we enter the command to run our bash script into /etc/rc.local

    sudo /path/to/script/mohammadIsAmazing.sh &
    

    Note: you have to put the command before the last line in /etc/rc.local that contains: exit 0

  6. We now save and close that file, then reboot the Pi.

On a side note: be sure to chose a random pin to marginally increase security

On another side note: If you would like to change the bluetooth device name, you need to create a file called /etc/machine-info which should contain the following:

PRETTY_HOSTNAME=device-name

Then run service bluetooth restart after that

Mohammad Ali
  • 2,383
  • 1
  • 11
  • 18
1

A few years later, I did this on Raspberry Pi 4B, maybe this can help someone.

Steps: 1.Make Pi's Bluetooth discoverable and pairable. Create a bluetooth-pair.sh file with content as below at /home/pi/AutoStart

sudo bluetoothctl <<EOF
discoverable on
pairable on
exit

2.Correct the Bluetooth spec file to make time limit to nolimit.

sudo nano /etc/bluetooth/main.conf

set timelimit to 0

DiscoverableTimeout = 0
PairableTimeout = 0

3.Let the bluetooth-pair.sh file to be run automatically when Pi starts. Correct /etc/rc.local Add

sudo sh /home/pi/AutoStart/bluetooth-pair.sh

before

exit 0

This works on Pi 4B normally.

ning
  • 21
  • 4
  • Please take note that using /etc/rc.local has limitations due to Compatibility with SysV. We have seen many problems here on this site using it. Following the recommendation of the developers from systemd you should avoid using it. – Ingo Sep 08 '20 at 11:25
0

Based on what I understand what you require is a slave bluetooth module. You can use the popular HC-06 Module and connect it to the raspberry pi via a level shifter to the TX and RX pins on the Pi and use a python script to read the serial data and process it as required

evolutionizer
  • 296
  • 2
  • 6
  • I would assume there would be a python module which could be run as soon as a bluetooth device connects rather than connecting hardware? I'm not too shabby with the pi, still a beginner but it seems it would be a logical approach – Oliver Kuchies May 15 '16 at 08:54
  • @OliverKuchies I've never done any bluetooth programming (or use!) on linux but you are looking for some kind of daemon service that will respond to such things. To elaborate: a python module will not run itself, it has to be used by a process that's already running. That's a daemon. Searching "bluetooth linux daemon" does turn up some stuff. I think I've noticed systemd has one, you presumably have to configure it to behave in specific ways. – goldilocks May 16 '16 at 17:19
  • @OliverKuchies have a look at http://blog.miguelgrinberg.com/post/a-cheap-bluetooth-serial-port-for-your-raspberry-pi – evolutionizer May 17 '16 at 04:11
0

In Raspberry Pi3 Model B there is a bulit in bluetooth and wifi. Using OBEX server you can receive the files from other devices without asking about pairing request every time. You have to do pairing first time with that device and make one directory, in that the files received all the time.

Just follow the step of below link.

https://www.raspberrypi.org/forums/viewtopic.php?p=963751#p963751

  • 1
    Have you read the question? The OP specifically asks how to avoid manual pairing because there will be no screen, and you suggest he should do pairing anyway? – Dmitry Grigoryev Sep 27 '16 at 11:40
  • You have to do pairing only once in this so for the first time you may connect with display for pairing. – Mihit Gandhi Sep 27 '16 at 12:15
  • You only have to do it once per device. And if anyone new wants to get on it, that means digging it out from wherever it is and hooking it up to a monitor and keyboard, which is why he's looking for a way to avoid that. – Different55 Jan 06 '20 at 08:07
0

I'm not going to discuss the security implication or not but this is how I do it:

  1. Create a script called auto_connect.sh with the following content:
#!/bin/bash
bt-adapter --set Powered 1
bt-adapter --set DiscoverableTimeout 0
bt-adapter --set Discoverable 1
bt-adapter --set PairableTimeout 0
bt-adapter --set Pairable 1
/path/to/python_script.py >/dev/nul 2>dev/nul &
list=""
bt-device -l | grep -E -o '[[:xdigit:]]{2}(:[[:xdigit:]]{2}){5}' | { while read line
do
       list="$list connect $line
"
done
bluetoothctl << EOF
$list
EOF
}
  1. Create the file /path/to/python_script.py with the following content:
#!/usr/bin/python3

from __future__ import absolute_import, print_function, unicode_literals

#import gobject
from gi.repository import GObject as gobject

import re
import dbus
import dbus.mainloop.glib
import subprocess

relevant_ifaces = [ "org.bluez.Adapter1", "org.bluez.Device1" ]

def property_changed(interface, changed, invalidated, path):
    iface = interface[interface.rfind(".") + 1:]
    for name, value in changed.iteritems():
        val = str(value)
        print("{%s.PropertyChanged} [%s] %s = %s" % (iface, path, name, val))

def interfaces_added(path, interfaces):
    for iface in interfaces:
        if not(iface in relevant_ifaces):
            continue
        try:
            found = re.search('dev\_(..\_..\_..\_..\_..\_..)', path).group(1)
        except AttributeError:
            found = '' # apply your error handling
            mac=found.replace("_",":")
            cmd='echo -e "trust '+mac+' \\nconnect '+mac+' \\nquit" | bluetoothctl'
            subprocess.call(cmd, shell=True)

def interfaces_removed(path, interfaces):
    for iface in interfaces:
        if not(iface in relevant_ifaces):
            continue
        print("{Removed %s} [%s]" % (iface, path))

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()

    bus.add_signal_receiver(interfaces_added, bus_name="org.bluez", dbus_interface="org.freedesktop.DBus.ObjectManager", signal_name="InterfacesAdded")

    bus.add_signal_receiver(interfaces_removed, bus_name="org.bluez", dbus_interface="org.freedesktop.DBus.ObjectManager", signal_name="InterfacesRemoved")

    mainloop = gobject.MainLoop()
    mainloop.run()
  1. Depending on the OS you are using make sure you run the auto_connect.sh on your boot.

What this all does:

  1. Sets the device to be always discoverable.

  2. When a device pairs to it, it will automatically mark it at trusted device and connect to it.

  3. On every boot it will itinerant through the list of known devices and will try to connect to them.

Please be mindful that this approach goes directly against any kind of security, but there might be user cases when you want to achieve just that.

Emil Borconi
  • 101
  • 2