Skip to content

Instantly share code, notes, and snippets.

@RamonGilabert
Last active October 12, 2023 18:24
Show Gist options
  • Star 58 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save RamonGilabert/046727b302b4d9fb0055 to your computer and use it in GitHub Desktop.
Save RamonGilabert/046727b302b4d9fb0055 to your computer and use it in GitHub Desktop.
Bluetoothctl automation
#!/usr/bin/expect -f
set prompt "#"
set address [lindex $argv 0]
spawn sudo bluetoothctl -a
expect -re $prompt
send "remove $address\r"
sleep 1
expect -re $prompt
send "scan on\r"
send_user "\nSleeping\r"
sleep 5
send_user "\nDone sleeping\r"
send "scan off\r"
expect "Controller"
send "trust $address\r"
sleep 2
send "pair $address\r"
sleep 2
send "0000\r"
sleep 3
send_user "\nShould be paired now.\r"
send "quit\r"
expect eof
@masterchop
Copy link

Just what i need it. thanks.
Just a quick question is it really need it do the scan off? i skipped that step.

@AleXSR700
Copy link

Hi everyone,
this script was exactly what I was looking for :)
It works great with my BT mouse, however iit does not work with my BT keyboard as the keyboard requires me to enter a code. The script does not show me the code so it does not pair properly,

Could someone help me change the script to work with a BT keyboard requiring a pairing code to be entered?

Thank you
Alex

@psihozefir
Copy link

psihozefir commented Oct 26, 2021

#!/usr/bin/expect -f
if {$argc != 2} {
    puts "No arguments."
    exit 1
}

# First argument needs to be the device MAC address;
# ... second argument needs to be the PIN.
set DEV [lindex $argv 0]
set PIN [lindex $argv 1]

# Do not wait after getting a response.
set timeout -1

# bluetoothctl is in $PATH
spawn bluetoothctl

# Wait for complete startup.
expect "Agent registered"

# If the device is already paired, we remove it first, so we are in a known state of affairs;
# ... we also handle the case in which the device is not already paired.
send "remove $DEV\r"
expect -re "removed|not available"

send "scan on\r"
# Only scan until we see a response from the device;
# ... if the device is not on or in range, this will block the script in scanning;
# ... please make sure the device is: 1) in range, 2) powered on and 3) discoverable.
expect "Device $DEV"

# Stop scanning.
send "scan off\r"
expect "Discovery stopped"

# Request pairing.
send "pair $DEV\r"
expect "Enter PIN code:"

# Send PIN.
send "$PIN\r"
expect "Pairing successful"

This is a general purpose script to programatically pair with a device from a shell script. License GPL2.

@MariwanJ
Copy link

But no one mentioned how you discover the mac address between hundred devices around you.
name: is the name of the device you want to find the MAC

hcitool scan >list.txt  
grep "name" list.txt>mydevice.txt 
cat mydevice.txt | sed 's/name//' > mac.txt
cat mac.txt |tr -d " \t\n\r" >result.txt

the above works but hcitool is depricated. how do you write the same script for bluetoothctl
Thanks in advance

@aviladev
Copy link

No PIN in my case, it just asks if I accept pairing, have to type yes. I've come to this:

#!/usr/bin/expect -f

set timeout 5

spawn bluetoothctl

set address [lindex $argv 0]
set pairExecuted 0

# Defines procedure (function) `pair`, `address` is the parameter
proc pair {address} {
  send "scan on\n"
  sleep 3
  send "scan off\n"

  send "pair $address\n"
}

send "agent on\n"
send "power on\n"
expect "Changing power on succeeded" {
  send "devices\n"
  expect "Device ${address}" {
    send "remove ${address}\n"

    expect "Device has been removed" {

      # Calls procedure `pair` passing `address` as argument (defined at the top)
      puts [pair ${address}]

      # Increments `pairExecuted` variable, so the next
      # check (if statement below) will know this has already been executed
      incr pairExecuted
    }
  }

  # Checks if the pair procedure has not yet been executed
  # this avoids executing it twice
  # in other words: if procedure `pair` not yet executed, execute it
  if {$pairExecuted == 0}
    puts [pair ${address}]
  }
}

expect "Accept pairing (yes/no):" { send "yes\n" }
expect "Pairing successful" { send "exit\n" }

expect eof

About the language used here: https://www.tcl-lang.org/

@srosato
Copy link

srosato commented Jan 3, 2022

Awesome script thanks so much!

@NeonLightning
Copy link

No PIN in my case, it just asks if I accept pairing, have to type yes. I've come to this:

#!/usr/bin/expect -f

set timeout 5

spawn bluetoothctl

set address [lindex $argv 0]
set pairExecuted 0

# Defines procedure (function) `pair`, `address` is the parameter
proc pair {address} {
  send "scan on\n"
  sleep 3
  send "scan off\n"

  send "pair $address\n"
}

send "agent on\n"
send "power on\n"
expect "Changing power on succeeded" {
  send "devices\n"
  expect "Device ${address}" {
    send "remove ${address}\n"

    expect "Device has been removed" {

      # Calls procedure `pair` passing `address` as argument (defined at the top)
      puts [pair ${address}]

      # Increments `pairExecuted` variable, so the next
      # check (if statement below) will know this has already been executed
      incr pairExecuted
    }
  }

  # Checks if the pair procedure has not yet been executed
  # this avoids executing it twice
  # in other words: if procedure `pair` not yet executed, execute it
  if {$pairExecuted == 0}
    puts [pair ${address}]
  }
}

expect "Accept pairing (yes/no):" { send "yes\n" }
expect "Pairing successful" { send "exit\n" }

expect eof

About the language used here: https://www.tcl-lang.org/

i can't seem to use it. i get
": no such file or directory

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment