简体   繁体   中英

bluetoothctl to hcitool equivalent commands

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?

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)

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.

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

I solved this using tmux , ie:

  1. Install tmux :

    apt install tmux

  2. Create Session:

    tmux new-session -d -s ServerFault 'sudo bluetoothctl -a |& tee /run/shm/BLUETOOTH_OUTPUT'

  3. Then you can issue commands like:

    tmux send-keys -t ServerFault "pair AC:22:0B:9F:0C:D6" Enter

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM