7

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.

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

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
  • 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. – charliesneath Dec 6 '18 at 2:22
  • This works, but do you mind telling me how to make the raspberry pi auto-trust the device after pairing? Thanks – Daniele Segato Jun 17 at 16:08
  • It seems this allows pairing, but does not authorize connections for lack of an agent. I believe the agent part of this script does not work properly. When I run this script, I get No agent is registered, it seems the default-agent command runs to fast. When I input the commands manually, it does not give this error, but once I quit bluetoothctl it unregisters the agent and trying to connect fails. If I leave bluetoothctl running, I get a prompt asking whether to trust the connection, which is not so NoInputNoOutput as you'd hope... – Matthijs Kooijman Jul 8 at 22:25
  • I suspect the NoInputNoOutput is not so much an authorization policy, but part of the bluetooth protocol to figure out what type of authorization mechanisms (e.g. can a pin be used?) are available. – Matthijs Kooijman Jul 8 at 22:27
  • 1
    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 – Matthijs Kooijman Jul 9 at 10:05
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

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
  • 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 '17 at 14:47
0

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

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")
  • 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 '17 at 17:37
  • @Jacobm001 I added code excerpts. Is that better now? – Serge Stroobandt Aug 12 '17 at 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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