求助:基于树莓派+Tkinter开发蓝牙扫描界面及配对连接功能
树莓派蓝牙连接应用开发求助:扫描展示、配对与连接功能实现
我正在使用Python bluetooth模块搭配Tkinter开发一款蓝牙连接应用,现寻求技术支持,在树莓派上实现蓝牙设备扫描界面,将扫描到的设备以列表形式展示在界面中,同时希望添加设备配对与连接功能。
当前代码
import time from time import sleep import serial import bluetooth import sys import tkinter as tk import tkinter.font as font from tkinter import * from tkinter import ttk from tkinter import messagebox from tkinter import scrolledtext import datetime now = datetime.datetime.now() main_window = tk.Tk() main_window.title('Scan for nearby Bluetooth devices') #changes the size of the screens window window_width = 900 window_height = 500 screen_width = main_window.winfo_screenwidth() screen_height = main_window.winfo_screenheight() center_x = int(screen_width/2 - window_width / 2) center_y = int(screen_height/2 - window_height / 2) main_window.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}') main_window.grid_columnconfigure(1, weight=1) main_window.grid_rowconfigure(1, weight=1) text = tk.Text(main_window, height=30, width=30) text.grid(row=1, column=1, sticky=tk.EW) def get_time(): return now.strftime('%H:%M:%S') text.insert('1.0','The time of the scan: ' + str(get_time()) + '\n\n') def button_clicked(): text['state'] = 'normal' now = datetime.datetime.now() def get_time(): return now.strftime('%H:%M:%S') print() text.delete('0.0', tk.END) print("Scanning") nearby_devices = bluetooth.discover_devices(lookup_names=True) print("Found {} devices.".format(len(nearby_devices))) for addr, name in nearby_devices: print(" {} - {}".format(addr, name)) return text.insert('1.0','The time of the scan: ' + str(get_time()) + '\n\n') text.insert('0.0', 'Amount of devices found: ' + str(len(out)) + '\n\n') text['state'] = 'disabled' main_button = ttk.Button( main_window, text='Scan again', command=lambda: button_clicked() ) main_button.grid(row=0, column=1, sticky=tk.EW) exit_button = ttk.Button( main_window, text='Exit', command=lambda: main_window.quit() ) exit_button.grid(row=2, column=1, sticky=tk.EW) text['state'] = 'disabled' main_window.mainloop()
问题修复与功能实现方案
1. 修复扫描结果不显示的问题
原代码中button_clicked函数在打印扫描结果后直接return,导致后续插入文本到界面的代码无法执行,需删除该多余的return。
2. 改用Listbox展示设备列表
将原Text控件替换为Listbox,方便后续选中单个设备执行配对、连接操作。
3. 添加配对与连接功能
由于Python bluetooth模块在树莓派上的配对支持有限,这里通过调用系统bluetoothctl命令实现配对和连接,树莓派默认已预装bluez工具包(依赖此工具)。
修改后的完整代码
import time import bluetooth import tkinter as tk from tkinter import ttk, messagebox import datetime import subprocess main_window = tk.Tk() main_window.title('蓝牙设备扫描与管理') # 设置窗口大小并居中 window_width = 900 window_height = 500 screen_width = main_window.winfo_screenwidth() screen_height = main_window.winfo_screenheight() center_x = int(screen_width/2 - window_width / 2) center_y = int(screen_height/2 - window_height / 2) main_window.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}') # 网格布局配置 main_window.grid_columnconfigure(1, weight=1) main_window.grid_rowconfigure(1, weight=1) # 设备列表展示控件 device_list = tk.Listbox(main_window, height=30, width=80) device_list.grid(row=1, column=1, sticky=tk.EW) # 存储扫描到的设备(显示文本:地址) scanned_devices = {} def get_current_time(): return datetime.datetime.now().strftime('%H:%M:%S') def scan_devices(): device_list.delete(0, tk.END) scanned_devices.clear() # 记录扫描时间 scan_time = get_current_time() print(f"[{scan_time}] 开始扫描蓝牙设备...") # 扫描附近蓝牙设备 try: nearby_devices = bluetooth.discover_devices(lookup_names=True, duration=8) print(f"找到 {len(nearby_devices)} 个设备") # 将设备添加到列表和字典 for addr, name in nearby_devices: display_text = f"{name} - {addr}" device_list.insert(tk.END, display_text) scanned_devices[display_text] = addr # 显示扫描信息 device_list.insert(0, f"扫描时间: {scan_time} | 找到设备: {len(nearby_devices)} 个") except Exception as e: messagebox.showerror("扫描错误", f"扫描失败: {str(e)}") def pair_device(): selected = device_list.curselection() if not selected: messagebox.warning("提示", "请先选择一个设备") return selected_text = device_list.get(selected[0]) if "扫描时间" in selected_text: messagebox.warning("提示", "请选择具体设备") return device_addr = scanned_devices[selected_text] # 调用bluetoothctl进行配对 try: proc = subprocess.Popen( ["bluetoothctl"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) proc.stdin.write(f"pair {device_addr}\n") proc.stdin.flush() # 等待配对操作(若设备需PIN码,需手动在终端输入,可扩展GUI输入框) time.sleep(5) proc.stdin.write("quit\n") proc.stdin.flush() stdout, stderr = proc.communicate() if "Pairing successful" in stdout: messagebox.showinfo("成功", "设备配对成功") else: messagebox.showerror("配对失败", f"错误信息: {stderr.strip()}") except Exception as e: messagebox.showerror("配对错误", f"配对过程出错: {str(e)}") def connect_device(): selected = device_list.curselection() if not selected: messagebox.warning("提示", "请先选择一个设备") return selected_text = device_list.get(selected[0]) if "扫描时间" in selected_text: messagebox.warning("提示", "请选择具体设备") return device_addr = scanned_devices[selected_text] # 调用bluetoothctl进行连接 try: proc = subprocess.Popen( ["bluetoothctl"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) proc.stdin.write(f"connect {device_addr}\n") proc.stdin.flush() time.sleep(3) proc.stdin.write("quit\n") proc.stdin.flush() stdout, stderr = proc.communicate() if "Connection successful" in stdout: messagebox.showinfo("成功", "设备连接成功") else: messagebox.showerror("连接失败", f"错误信息: {stderr.strip()}") except Exception as e: messagebox.showerror("连接错误", f"连接过程出错: {str(e)}") # 按钮控件 scan_btn = ttk.Button(main_window, text='扫描设备', command=scan_devices) scan_btn.grid(row=0, column=1, sticky=tk.EW, padx=5, pady=5) pair_btn = ttk.Button(main_window, text='配对选中设备', command=pair_device) pair_btn.grid(row=2, column=0, sticky=tk.EW, padx=5, pady=5) connect_btn = ttk.Button(main_window, text='连接选中设备', command=connect_device) connect_btn.grid(row=2, column=2, sticky=tk.EW, padx=5, pady=5) exit_btn = ttk.Button(main_window, text='退出', command=main_window.quit) exit_btn.grid(row=3, column=1, sticky=tk.EW, padx=5, pady=5) # 程序启动时自动扫描一次设备 scan_devices() main_window.mainloop()
说明
- 程序启动后会自动执行一次设备扫描
- 选中列表中的设备后,可点击对应按钮完成配对或连接操作
- 若配对需要PIN码,当前版本需手动在终端输入,可根据需求扩展GUI PIN码输入功能
- 确保树莓派蓝牙已开启,可通过
bluetoothctl power on命令开启
内容的提问来源于stack exchange,提问作者Depua
相关产品推荐
相关产品推荐

