每次我要在pi上运行python脚本之前,我都会在终端上运行一系列Bluetoothctl命令。我想从pi自动连接到BLE设备,而无需任何配对确认或用户交互。 这是我每次重新启动pi之前必须运行的命令,然后再运行另一个python脚本(此脚本将继续运行数天,直到停止或重新启动pi为止):
$sudo bluetoothctl
[Bluetooth]power on
[Bluetooth]discoverable on
[Bluetooth]pairable on
[Bluetooth]agent NoInputNoOutput
[Bluetooth]default-agent
我想使这个过程自动化。 因此,我尝试使用bluetoothctl包装器并对其进行了修改,但似乎不起作用。也没有错误。
import time
import pexpect
import subprocess
import sys
import re
class BluetoothctlError(Exception):
"""This exception is raised, when bluetoothctl fails to start."""
pass
class Bluetoothctl:
def __init__(self):
out = subprocess.check_output("rfkill unblock bluetooth", shell = True)
self.child = pexpect.spawn("bluetoothctl", echo = False)
print("bluetoothctl")
def get_output(self, command, pause = 0):
"""Run a command in bluetoothctl prompt, return output as a list of lines."""
self.child.send(command + "\n")
time.sleep(pause)
start_failed = self.child.expect(["bluetooth", pexpect.EOF])
if start_failed:
raise BluetoothctlError("Bluetoothctl failed after running " + command)
return self.child.before.split(b"\r\n")
def make_discoverable(self):
"""Make device discoverable."""
try:
out = self.get_output("discoverable on")
print("discoverable on")
except BluetoothctlError as e:
print(e)
return None
def power_on(self):
"""Start agent"""
try:
out = self.get_output("power on")
print("power on")
except BluetoothctlError as e:
print(e)
return None
def pairable_on(self):
"""Start agent"""
try:
out = self.get_output("pairable on")
print("pairable on")
except BluetoothctlError as e:
print(e)
return None
def agent_noinputnooutput(self):
"""Start agent"""
try:
out = self.get_output("agent NoInputNoOutput")
print("agent Registered Successfully")
except BluetoothctlError as e:
print(e)
return None
def default_agent(self):
"""Start default agent"""
try:
out = self.get_output("default-agent")
print("set as default agent")
except BluetoothctlError as e:
print(e)
return None
if __name__ == "__main__":
print("Init bluetooth...")
bl = Bluetoothctl()
bl.power_on()
bl.make_discoverable()
bl.pairable_on()
bl.agent_noinputnooutput()
bl.default_agent()
答案 0 :(得分:0)
我写了一个python3脚本来自动连接游戏柜上的游戏手柄。您必须为要连接的每个设备运行它,但是不需要用户交互。它使用Expect python模块。我发现它比期望/ tcl脚本更容易使用。如果python无法找到pexpect,则需要安装python3-pexpect。
sudo apt install python3-pexpect
您将要更改 mylist 列表变量,以搜索与蓝牙设备的前3个字节(供应商部分)匹配的MAC。因此,例如,如果设备上MAC的前3个字节以AA:BB:CC:开头,则将EF \:17 \:D8 \:部分更改为AA \:BB \:CC \:>
您可以在 mylist 变量中添加要扫描的设备。我的示例搜索两个不同的供应商,一个以EF \:17 \:D8 \:开头,另一个以16 \:04 \:18 \开头:该脚本将拒绝可能正在传输的所有其他蓝牙设备,并且仅连接您在 mylist 变量中配置的游戏手柄MAC。
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]
这是python3脚本:
#!/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)
我编写了另一个python3脚本,该脚本将整个过程包装在Vte中并显示正在发生的过程,并允许您在需要时退出它。如果您想看看,请告诉我。