14

I am running a headless Raspberry PI 3, and I want it to automatically accept pairings from any device.

I saw this answer in an identical question:

Automatically accepting Bluetooth connections on a Pi 3

But it seems to be a bit outdated and some of the used commands don't seem to exist.

I am running the 2016-05-27-raspbian-jessie.img OS image.

2
  • What do you mean by "some of the used commands don't seem to exist"? What exactly didn't work for you? Sep 27, 2016 at 11:34
  • 1
    If I remember correctly, bluetooth-agent, but I am not sure. Sep 27, 2016 at 13:15

8 Answers 8

9

Since bluetooth-agent command doesn't exist on Jessie, the modern way is to pipe relevant commands to bluetoothctl. Based on this SO question, the following script should enable automatic pairing without manual pin entry:

sudo bluetoothctl <<EOF
power on
discoverable on
pairable on
agent NoInputNoOutput
default-agent 
EOF
10
  • 1
    This worked for making my RPi Zero W discoverable on boot. I had previously updated my Bluetooth config via the steps outlined here and with this script. Dec 6, 2018 at 2:22
  • This works, but do you mind telling me how to make the raspberry pi auto-trust the device after pairing? Thanks Jun 17, 2019 at 16:08
  • 2
    Probably, but then you'd have to keep feeding yes's for all pairing attempts (and I'm not entirely sure if that works from stdin or perhaps the script tries to be smart and tries to open the terminal directly rather than stdin (that also happens sometimes)... Have not tried this, though, I ended up using the python script from gist.github.com/mill1000/74c7473ee3b4a5b13f6325e9994ff84c Jul 9, 2019 at 10:05
  • 1
    Down voted because bluetoothctl shenanigans are inferior to calling hciconfig hci0 piscan and hciconfig hci0 sspmode 1
    – Phlip
    Feb 18, 2021 at 13:38
  • 1
    The mentioned options still did not work for them, RPi still asked for PIN. What finally worked was hciconfig hci0 class 0x400100. After this I cannot connect RFCOMM socket without prior pairing.
    – Quimby
    Jan 13, 2022 at 10:22
4

I was facing the same issue and found this method to work (RasPi 3, Model B, Raspbian 9 Stretch)

I am using Raspberry Pi as an IoT EDGE Device and needed it to accept Bluetooth Pair Requests without intervention. I have an Android App that communicates text information to the Pi via Bluetooth and my problem statement needed any Android device to connect.

Firstly, I am not running any separate Bluetooth Agents (No Blueman, infact I had to remove it)

Edited the .bashrc file at

    sudo nano /home/pi/.bashrc

Added two commands to this at the end

    sudo hciconfig hci0 piscan 
    sudo hciconfig hci0 sspmode 1

piscan makes Raspberry Pi Bluetooth discoverable

sspmode 1 enables 'Secure Simple Pairing' which is the same type of method used by your Bluetooth Earphones or Speakers (basically devices that don't have a display where you can confirm PIN). And since these commands are in .bashrc they run at boot.

Run Bluetooth Script. Pair. Although there is a pop-up asking me to confirm, I can communicate messages to and from the Pi with my app

Note : hci0 may not be the same throughout, could be hci1, hci2 please check by running hciconfig on your CLI

This is almost like a contraption, and I am not sure if there are any unknown repercussions, but it works. Any improvements are appreciated

1
  • 1
    I put them into /etc/rc.local, because bash only calls .bashrc opportunistically, and I preceded them with hciconfig hci0 up just in case the Bluetooth is feeling down that day.
    – Phlip
    Feb 18, 2021 at 13:39
0

I just used a fresh install of 2016-09-23-raspbian-jessie-lite.img to try it without any additional updates. No apt-get update no apt-get install bluez-utils or anything. This single command makes the Pi discoverable and pairable. Without an agent to control who can connect, it just lets anyone:

sudo hciconfig hci0 piscan
0

One simple way is Just to remove the Blueman if you have installed it by using

sudo apt remove blueman 

And remove the Bluetooth logo from the top menu by right click and remove.

And install bluedot using

sudo pip3 install bluedot

for more about bluedot click here

import time
from bluedot.btcomm import BluetoothServer
import os
import bluetooth

def data_received(data):
    print(data)
    s.send(data)
    

os.system('bluetoothctl discoverable on && bluetoothctl agent NoInputNoOutput')
time.sleep(2)
s = BluetoothServer(data_received)

Now In Android phone go to Bluetooth settings and pair raspberry Pi

And if you will send data it will print on the terminal you can check it's working or not by using this application if you didn't develop your own.

3
  • Raspbian Jessie, used by the questioner, is outdated since 2020-01-01 and not supported anymore. Its repository is archived.
    – Ingo
    Aug 15, 2020 at 8:59
  • I have the same Error and I took 2 days to search and resolve it and I just posted here so someone have the same error it will help Aug 15, 2020 at 15:04
  • What operating system and version do you use? You should edit your answer and mention it.
    – Ingo
    Aug 16, 2020 at 8:02
0

I have to make clear some terminology:

  • A bluetooth service is an asset to which you pair and to which you pair.
  • Therefore a bluetooth client is the asset which you use to connect to the bluetooth server

I am currently working on a project which involves bluetooth pairing in Linux - note that the server you want to connect (defined as bluetooth server - i.e MUST HAVE the "Just works" (aka NoInputNoOutput) capability in order to work. "Just works" means exactly that - the pairing is in the simplest form: does not require authorization/pin/confirmation etc (Hence No Input No Output)

Now, due to the explaination above, automatic pairing becomes a relative term: automatic in relation to what?

  • Automatic in the context of the server having implemented the "NoInputNoOutput" capability means that all the client has to do (automatically) is to call the "Pair" method. This will be sufficient to be able to discover all the GATT services/characteristics.
  • Automatic in the context of the server NOT HAVING the "NoInputNoOutput" capability implemented, means that the client must somehow have the subsequent capability (the one that is implemented in the server) implemented in an Agent. This custom agent could then handle the process automatically, with the exception of a case in which you want to display a code on the server and input in on the client (like bluetooth pairing in a car where the code is displayed on the dashboard and you have to insert it on your phone)

In conclusion, it depends on the capability of the bluetooth device you want to connect to (you are the client, again).

I banged my head to the wall for a long time until I realized this and I was trying to autopair something that is not autopairable.

1
  • 1
    With some more detail, this might be a useful answer. the device you want to connect... that would not be the RPi I'll guess - but what type of device is it?; perhaps some insight into what exactly "Just works" is?
    – Seamus
    Mar 9, 2021 at 17:46
0
sudo apt install bluez-tools 
sudo bt-agent -c DisplayOnly -p pins.txt

pins.txt:

00:00:00:00:00:00 *
*                 *
-1

You may take a peek at the source code of EcoDroidLink. It accepts Bluetooth connections without the need to log in.

EDIT: By popular demand, here are code excerpts of the edl_agent module that makes this happen.

# - automate the agent for running on a headless Pi - to answer pair and connection requests without a blocking query

import dbus
import dbus.service
import dbus.mainloop.glib
import bluezutils

BUS_NAME = 'org.bluez'
AGENT_INTERFACE = 'org.bluez.Agent1'
AGENT_PATH = "/test/agent"

bus = None
device_obj = None
dev_path = None

def set_trusted(path):
    props = dbus.Interface(bus.get_object("org.bluez", path),
                    "org.freedesktop.DBus.Properties")
    props.Set("org.bluez.Device1", "Trusted", True)

def dev_connect(path):
    dev = dbus.Interface(bus.get_object("org.bluez", path),
                            "org.bluez.Device1")
    dev.Connect()

class Rejected(dbus.DBusException):
    _dbus_error_name = "org.bluez.Error.Rejected"

class Agent(dbus.service.Object):
    exit_on_release = True

    def set_exit_on_release(self, exit_on_release):
        self.exit_on_release = exit_on_release

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="", out_signature="")
    def Release(self):
        printlog("Release")
        if self.exit_on_release:
            mainloop.quit()

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="os", out_signature="")
    def AuthorizeService(self, device, uuid):
        printlog("AuthorizeService (%s, %s)" % (device, uuid))
        authorize = "yes" #ask("Authorize connection (yes/no): ")
        if (authorize == "yes"):
            return
        raise Rejected("Connection rejected by user")

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="o", out_signature="s")
    def RequestPinCode(self, device):
        printlog("RequestPinCode (%s)" % (device))
        set_trusted(device)
        return "0000" #ask("Enter PIN Code: ")

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="o", out_signature="u")
    def RequestPasskey(self, device):
        printlog("RequestPasskey (%s)" % (device))
        set_trusted(device)
        passkey = "0000" #ask("Enter passkey: ")
        return dbus.UInt32(passkey)

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="ouq", out_signature="")
    def DisplayPasskey(self, device, passkey, entered):
        printlog("DisplayPasskey (%s, %06u entered %u)" %
                        (device, passkey, entered))

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="os", out_signature="")
    def DisplayPinCode(self, device, pincode):
        printlog("DisplayPinCode (%s, %s)" % (device, pincode))

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="ou", out_signature="")
    def RequestConfirmation(self, device, passkey):
        printlog("RequestConfirmation (%s, %06d)" % (device, passkey))
        confirm = "yes" #ask("Confirm passkey (yes/no): ")
        if (confirm == "yes"):
            set_trusted(device)
            return
        raise Rejected("Passkey doesn't match")

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="o", out_signature="")
    def RequestAuthorization(self, device):
        printlog("RequestAuthorization (%s)" % (device))
        auth = "yes" #ask("Authorize? (yes/no): ")
        if (auth == "yes"):
            return
        raise Rejected("Pairing rejected")

    @dbus.service.method(AGENT_INTERFACE,
                    in_signature="", out_signature="")
    def Cancel(self):
        printlog("Cancel")
2
  • 1
    Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
    – Jacobm001
    Aug 11, 2017 at 17:37
  • @Jacobm001 I added code excerpts. Is that better now? Aug 12, 2017 at 8:28
-1

Raspbian - Jessie

sudo apt-get install expect

xxxxx.sh

#!/usr/bin/expect -f
set prompt "#"
spawn sudo bluetoothctl
sleep 1
expect -re $prompt
sleep 1
send "agent NoInputNoOutput\r"
sleep 2
expect "Agent registered"
send "default-agent\r"
expect -re $prompt
sleep 3
interact
expect eof
2
  • 1
    An answer that consists of code only is not very explicit so please provide some more detailed explanation on your answer. Also indent your code block to make it appear like code; use 4 spaces or a tab, at your preference.
    – user29510
    Nov 1, 2017 at 14:47
  • downvoted because scripting bluetoothctl is inferior to calling hciconfig hci0 piscan and hciconfig hci0 sspmode 1
    – Phlip
    Feb 18, 2021 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.