当前位置: 首页 > news >正文

蓝牙上位机开发指南

蓝牙上位机开发指南

蓝牙技术在现代设备通信中扮演着重要角色,从无线耳机到物联网设备都有广泛应用。本文将介绍如何使用Python开发一个功能完整的蓝牙上位机应用,包括设备扫描、连接和数据传输等核心功能。

一、蓝牙上位机开发

1.1 PyBluez2蓝牙工具使用

PyBluez2是一个跨平台的Python蓝牙库,支持Windows和Linux系统。首先需要安装这个库:

pip install pybluez2

基本导入和初始化:

import bluetooth
from bluetooth import *# 检查蓝牙适配器是否可用
def check_bluetooth():try:devices = bluetooth.discover_devices(lookup_names=True)print("找到 {} 个设备".format(len(devices)))return Trueexcept Exception as e:print("蓝牙适配器不可用:", e)return False

1.2 界面设置

使用Tkinter构建简单的GUI界面:

import tkinter as tk
from tkinter import ttk, scrolledtextclass BluetoothApp:def __init__(self, root):self.root = rootself.root.title("蓝牙上位机")self.root.geometry("600x400")self.setup_ui()def setup_ui(self):# 扫描按钮self.scan_btn = ttk.Button(self.root, text="扫描设备", command=self.scan_devices)self.scan_btn.pack(pady=10)# 设备列表self.device_tree = ttk.Treeview(self.root, columns=("name", "address"), show="headings")self.device_tree.heading("name", text="设备名称")self.device_tree.heading("address", text="MAC地址")self.device_tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)# 连接按钮self.connect_btn = ttk.Button(self.root, text="连接设备", command=self.connect_device)self.connect_btn.pack(pady=5)# 数据发送区域self.send_frame = ttk.Frame(self.root)self.send_frame.pack(fill=tk.X, padx=10, pady=5)self.data_entry = ttk.Entry(self.send_frame)self.data_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)self.send_btn = ttk.Button(self.send_frame, text="发送", command=self.send_data)self.send_btn.pack(side=tk.RIGHT)# 接收数据显示区域self.recv_text = scrolledtext.ScrolledText(self.root, height=10)self.recv_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

1.3 子线程扫描蓝牙设备

为了避免界面冻结,使用子线程进行蓝牙设备扫描:

import threading
from threading import Threadclass BluetoothApp:# ... 之前的代码 ...def scan_devices(self):self.scan_btn.config(state=tk.DISABLED)self.device_tree.delete(*self.device_tree.get_children())# 在子线程中扫描设备scan_thread = Thread(target=self._scan_thread)scan_thread.daemon = Truescan_thread.start()def _scan_thread(self):try:devices = bluetooth.discover_devices(lookup_names=True, duration=8)# 回到主线程更新UIself.root.after(0, self._update_device_list, devices)except Exception as e:self.root.after(0, self._scan_error, str(e))def _update_device_list(self, devices):for addr, name in devices:self.device_tree.insert("", tk.END, values=(name, addr))self.scan_btn.config(state=tk.NORMAL)def _scan_error(self, error_msg):self.recv_text.insert(tk.END, f"扫描错误: {error_msg}\n")self.scan_btn.config(state=tk.NORMAL)

1.4 连接蓝牙设备

建立蓝牙连接并处理通信:

class BluetoothApp:def __init__(self, root):# ... 之前的初始化代码 ...self.socket = Noneself.connected = Falsedef connect_device(self):selection = self.device_tree.selection()if not selection:returnitem = self.device_tree.item(selection[0])addr = item['values'][1]connect_thread = Thread(target=self._connect_thread, args=(addr,))connect_thread.daemon = Trueconnect_thread.start()def _connect_thread(self, addr):try:self.socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)self.socket.connect((addr, 1))self.connected = Trueself.root.after(0, self._connection_success)# 启动数据接收线程recv_thread = Thread(target=self._recv_data_thread)recv_thread.daemon = Truerecv_thread.start()except Exception as e:self.root.after(0, self._connection_failed, str(e))def _connection_success(self):self.recv_text.insert(tk.END, "连接成功!\n")self.connect_btn.config(text="断开连接", command=self.disconnect_device)def _connection_failed(self, error_msg):self.recv_text.insert(tk.END, f"连接失败: {error_msg}\n")def disconnect_device(self):if self.socket:self.socket.close()self.socket = Noneself.connected = Falseself.connect_btn.config(text="连接设备", command=self.connect_device)self.recv_text.insert(tk.END, "连接已断开\n")

1.5 发送数据

实现数据发送和接收功能:

class BluetoothApp:# ... 之前的代码 ...def send_data(self):if not self.connected:self.recv_text.insert(tk.END, "未连接设备,无法发送数据\n")returndata = self.data_entry.get()if not data:returntry:self.socket.send(data.encode('utf-8'))self.recv_text.insert(tk.END, f"发送: {data}\n")self.data_entry.delete(0, tk.END)except Exception as e:self.recv_text.insert(tk.END, f"发送失败: {e}\n")self.connected = Falseself.connect_btn.config(text="连接设备", command=self.connect_device)def _recv_data_thread(self):while self.connected:try:data = self.socket.recv(1024)if data:self.root.after(0, self._display_recv_data, data.decode('utf-8'))except:if self.connected:self.root.after(0, self._connection_lost)breakdef _display_recv_data(self, data):self.recv_text.insert(tk.END, f"接收: {data}\n")self.recv_text.see(tk.END)def _connection_lost(self):self.recv_text.insert(tk.END, "连接已断开\n")self.connected = Falseself.connect_btn.config(text="连接设备", command=self.connect_device)

二、PyInstaller打包

将Python应用打包成可执行文件,方便分发和使用:

2.1 安装PyInstaller

pip install pyinstaller

2.2 创建打包配置文件

创建spec文件或直接使用命令行参数。创建一个build.spec文件:

# -*- mode: python ; coding: utf-8 -*-block_cipher = Nonea = Analysis(['bluetooth_app.py'],pathex=[],binaries=[],datas=[],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_files, cipher=block_cipher)exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='BluetoothApp',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=False,  # 设置为True可以显示控制台窗口icon='app_icon.ico',  # 可选:添加应用图标
)

第二种

import PyInstaller.__main__# 这里的是不需要打包进去的三方模块,可以减少软件包的体积,这里只是举个例子
excluded_modules = ["pytest","selenium",
]append_string = []
for mod in excluded_modules:append_string += [f'--exclude-module={mod}']PyInstaller.__main__.run(['-y',  # 如果dist文件夹内已经存在生成文件,则不询问用户,直接覆盖'img_test.py',  # 主程序入口# '--onedir',  # -D 文件夹'--onefile', # -F 单文件# '--nowindowed', # -c 无窗口'--windowed',  # -w 有窗口'-n', 'utils',  # -n 生成的文件名,默认是程序的名称'-i', 'res/logo.ico',  # -i 生成的图标,默认是程序的图标'--add-data=res;res',  # 第一个 res 是当前工作目录下的资源文件夹路径# 第二个 res 是打包后资源文件在应用程序中的相对路径*append_string
])

2.3 执行打包命令

pyinstaller build.spec

或者直接使用命令行:

pyinstaller --onefile --windowed --name BluetoothApp bluetooth_app.py

2.4 常用PyInstaller选项

  • --onefile: 打包成单个可执行文件
  • --windowed: 不显示控制台窗口(GUI应用)
  • --console: 显示控制台窗口
  • --icon=app.ico: 设置应用图标
  • --add-data "source;destination": 添加额外文件
  • --hidden-import modulename: 添加隐藏导入的模块

文章转载自:

http://hiWGVWp6.hxsdh.cn
http://rm9h1CRc.hxsdh.cn
http://RPTxwSaV.hxsdh.cn
http://cnMN72he.hxsdh.cn
http://9roO3p0Z.hxsdh.cn
http://YPQHzLWY.hxsdh.cn
http://gthHLX6k.hxsdh.cn
http://EXwd3bW6.hxsdh.cn
http://EjmCHZWV.hxsdh.cn
http://UyY8mPNc.hxsdh.cn
http://z4ps50yx.hxsdh.cn
http://j2T20KZo.hxsdh.cn
http://38yLvwxi.hxsdh.cn
http://3Qr2vlSJ.hxsdh.cn
http://18tpKXh7.hxsdh.cn
http://StwoorDR.hxsdh.cn
http://d6rF7GtG.hxsdh.cn
http://AA4vX13c.hxsdh.cn
http://r5sIDi0I.hxsdh.cn
http://JabacvJ5.hxsdh.cn
http://YwFtXnV2.hxsdh.cn
http://4opka4g6.hxsdh.cn
http://2SQTBDBf.hxsdh.cn
http://e3BKd50d.hxsdh.cn
http://mCS7ees1.hxsdh.cn
http://X3EeUm9w.hxsdh.cn
http://nch4hUS3.hxsdh.cn
http://S5coRMzq.hxsdh.cn
http://0MLqck7q.hxsdh.cn
http://x4i99ZVJ.hxsdh.cn
http://www.dtcms.com/a/385671.html

相关文章:

  • 【课堂笔记】复变函数-1
  • 谈谈人大金仓数据库
  • C#调用钉钉API发送通知教程
  • 电子电气架构 --- 产线EOL为何需要智能升级?
  • 无人机姿态控制系统详解与实现
  • 7.Redis 主从复制(重在理解)
  • 从零搭建RAG应用:跳过LangChain,掌握文本分块、向量检索、指代消解等核心技术实现
  • 从0开始做一个完整项目 -- 软件跨平台编译打包全流程
  • comfyUI实战——使用openArt的工作流
  • linux 之 struct attribute
  • 强化学习PPO-分类任务
  • 决策树模型全解析:从分类到回归(基于鸢尾花数据集)
  • shell脚本部署lamp
  • c语言6:static 关键字控制变量/函数的 “生命周期” 与 “可见性”
  • MySQL 数据库对象与视图:从概念到实战,掌握虚拟表的核心价值
  • 【VPX361】基于3U VPX总线架构的XCZU47DR射频收发子模块
  • 消火栓设备工程量计算 -【图形识别】秒计量
  • 基于LangGraph的深度研究智能体技术解析
  • 【哈希表】1512. 好数对的数目|2506. 统计相似字符串对的数目
  • Java--多线程基础知识(2)
  • 活泼解析pthread_join函数:多线程世界的等待仪式
  • 机器视觉的智能手表后盖激光打标应用
  • 第七章 来日方长(2025.8学习总结)
  • 卡方检验公式中分母 (a+b)(c+d)(a+c)(b+d)的本质
  • IT基础知识——数据库
  • 电子衍射模拟:基于GPU加速的MATLAB/Julia实现
  • yum只安装指定软件库中的包
  • CentOS网卡接口配置文件详细指南
  • 计算机视觉 - 对比学习(上)MoCo + SimCLR + SWaV
  • SQL模糊查询完全指南