Reputation: 1706
In Linux I used to use "hidd --connect mmac" to connect with BT devices but that is now gone since Bluez5. I can use bluetoothctl to make the connection manually but I need to use these commands from my app and using bluetoothctl would be difficult.
What are the hcitool equivalent commands to do what bluetoothctl does?
For example, I would type in bluetoothctl:
select <cmac>
scan on
trust <mmac>
pairable on
pair <mmac>
connect <mmac>
I can use "hcitool scan" for the scanning but I haven't figured out connecting. I've tried using "hcitool cc mmac" followed by "hcitool auth mmac" but nothing works.
Or can hcitool do what bluetoothctl does?
Upvotes: 12
Views: 36983
Reputation: 14834
You can give commands as arguments directly to bluetoothctl
from the shell, without needing expect scripts.
I use this in a Bash script in Ubuntu 20.04 :
mac="90:03:B7:17:00:08"
# turn on bluetooth in case it's off
rfkill unblock bluetooth
bluetoothctl power on
bluetoothctl connect $mac
To disconnect, use
bluetoothctl disconnect
This assumes the destination $mac
is already paired of course. If it isn't, you can first do
bluetoothctl pair $mac
To list all available commands:
bluetoothctl help
Upvotes: 2
Reputation: 331
I wrote a python3 script to auto-connect my gamepads on my game cabinet. You have to run it for each device you want to connect, but no user interaction is needed. It uses the expect python module, similar to the above answers, to communicate with bluetoothctl. I found it a little easier to use than the expect/tcl scripts. If python can't find pexpect, you would need to install python3-pexpect.
sudo apt install python3-pexpect
You'll want to change the mylist list variable to search for the MACs that match the first 3 bytes (the vendor part) of your bluetooth devices. So, for example, if the first 3 bytes of the MACs on your devices start with AA:BB:CC:, then change the EF\:17\:D8\: part to AA\:BB\:CC\:
You can add as many devices you want to scan for in the mylist variable. My example searches for two different vendors, one starting with EF\:17\:D8\:, and one starting with 16\:04\:18\: The script will reject all other bluetooth devices that may be transmitting, and only connect the gamepad MACs you've configured in the mylist variable.
mylist = ['E4\:17\:D8\:[0-9A-F].[:][0-9A-F].[:][0-9A-F].', '16\:04\:18\:[0-9A-F].[:][0-9A-F].[:][0-9A-F].',pexpect.EOF]
Here is the python3 script:
#!/usr/bin/python3
import os,sys,time,pexpect
def findaddress():
address=''
p = pexpect.spawn('hcitool scan', encoding='utf-8')
p.logfile_read = sys.stdout
mylist = ['E4\:17\:D8\:[0-9A-F].[:][0-9A-F].[:][0-9A-F].', '16\:04\:18\:[0-9A-F].[:][0-9A-F].[:][0-9A-F].',pexpect.EOF]
p.expect(mylist)
address=p.after
if address==pexpect.EOF:
return ''
else:
return address
def setbt(address):
response=''
p = pexpect.spawn('bluetoothctl', encoding='utf-8')
p.logfile_read = sys.stdout
p.expect('#')
p.sendline("remove "+address)
p.expect("#")
p.sendline("scan on")
mylist = ["Discovery started","Failed to start discovery","Device "+address+" not available","Failed to connect","Connection successful"]
while response != "Connection successful":
p.expect(mylist)
response=p.after
p.sendline("connect "+address)
time.sleep(1)
p.sendline("quit")
p.close()
#time.sleep(1)
return
address=''
while address=='':
address=findaddress()
time.sleep(1)
print (address," found")
setbt(address)
I wrote another python3 script that wraps the entire process in a Vte and shows the process as it is happening, and lets you to exit it, if needed. If you want to see that, just let me know.
Upvotes: 0
Reputation: 98921
I solved this using tmux, i.e.:
Install tmux
:
apt install tmux
Create Session:
tmux new-session -d -s ServerFault 'sudo bluetoothctl -a |& tee /run/shm/BLUETOOTH_OUTPUT'
Then you can issue commands like:
tmux send-keys -t ServerFault "pair AC:22:0B:9F:0C:D6" Enter
Upvotes: 1
Reputation: 902
Another solution (the best in my opinion) would be to use expect TCL scripting with bluetoothctl.
I use it to automatically connect to bluetooth devices using bluetoothctl without having to interact with it.
For example to connect to a device identified by its MAC address
#!/usr/bin/expect -f
set address [lindex $argv 0]
set prompt "#"
log_user 0
spawn bluetoothctl
expect $prompt
send -- "remove $address\r"
expect $prompt
send -- "scan on\r"
expect "Discovery started"
sleep 10
send -- "scan off\r"
expect "Discovery stopped"
expect $prompt
send -- "trust $address\r"
expect "trust succeeded"
expect $prompt
send -- "pair $address\r"
expect "Pairing successful"
expect "Device $address Connected: no"
expect $prompt
send -- "connect $address\r"
expect "Connection successful"
expect $prompt
send "quit\r"
expect "eof"
You can launch this script as it ./myExpectScript <MAC_addr>
If you want to see the output just set the log_user
value to 1
Upvotes: 9
Reputation: 445
You can pass commands to bluetoothctl like this:
echo -e 'power on\nquit' | bluetoothctl
You can even use tab to autocomplete:
echo -e 'power on\nconnect \t \nquit' | bluetoothctl
I am not adding this as a comment on Jiri's answer so it is more visible.
Upvotes: 13
Reputation: 181
I am using bluetoothctl from scripts like this:
#!/bin/bash
bluetoothctl << EOF
power on
EOF
And it is possible to specify multiple commands as one command per line.
Strangely enough, it does not work like this for me:
echo "power on" | bluetoothctl
(I am using bluez-5.21-r1 - not sure whether this is version dependent)
Upvotes: 17