一个小时搞定蓝牙调试助手!!!

2026-01-18 16:39:56 避难所建设

一个小时搞定蓝牙调试助手!!!项目介绍 蓝牙调试助手是一个用于蓝牙低功耗(BLE)设备开发和调试的移动应用程序,旨在帮助开发者更高效地进行蓝牙相关项目的调试和分析。

主要功能包括:

蓝牙数据捕获:实时捕获蓝牙设备之间的通信数据,包括连接状态、传输数据等。数据包分析:解析蓝牙数据包,显示详细信息如信号强度、设备地址、数据内容等。设备管理:支持对蓝牙设备的扫描、连接、数据收发和断开操作。实时监控:提供实时的蓝牙设备状态监控,帮助开发者快速定位问题。配置管理:支持对蓝牙设备的配置参数进行调整和管理。该工具以图形化界面呈现,操作简单,适用于需要进行蓝牙通信测试和调试的场景。

平台支持AndroidiOSAiFlutter市场链接:蓝牙调试助手App

平台实现步骤1. 注册登录打开 低代码平台登录网页 ,使用微信快捷登录或者扫描二维码登录。

2. 创建项目点击【新增项目】->【手动添加】,在平台内部创建项目在跳出的弹窗中输入项目名称、项目描述,建议结合项目功能描述命名,便于检索输入完成后点击确定

3. 创建页面(1)点击已经创建好的项目进入到操作界面,默认会存在一个HomePage页面,操作界面相关详情可查看教程 操作界面

(2)创建三个页面 AddBleDevice、SetBleName、DeviceNetWork

点击【添加页面】 -> 【创建页面】在跳出的弹窗中输入 页面名称、页面描述最后点击确定即可

(4)删除HomePage页面,在【页面管理】中右击要删除的页面,并点击【删除】

(5)设置AddBleDevice为主页面,在【页面管理】中单击要删除的页面,并在右侧的属性编辑器中设置页面路由为/

4. 页面设计AddBleDevice页面设计页面描述

在页面初始化时,会依次执行以下操作 监听蓝牙扫描状态,接收到状态变化后重新构建页面蓝牙扫描结果监听,接收到扫描结果后进行存储并重新构建页面开始蓝牙扫描,扫描时长8秒连接设备,在设备列表中选择设备进行连接,连接成功后跳转到数据收发页面重新扫描,蓝牙扫描结束后,点击【重新扫描】开始扫描,此时会断开已连接的蓝牙设备效果图

实现流程

(1)在【页面管理】中单击AddBleDevice页面,在右侧的属性编辑器中添加页面变量

需要定义的变量如下

变量名称变量类型是否为数组默认值变量描述devicesMap是设备原始数据列表,用来去重scaningBool否false蓝牙扫描状态 true 正在扫描 false 未扫描deviceListMap是页面显示的设备列表

操作成功如下

(2)添加页面初始化动作,在右侧的属性编辑器中点击【动作】-> 【打开】

在操作流程编辑器中,页面初始化 事件下点击+号添加事件,再点击+号添加动作,信息如下

动作类型 --【自定义代码块】,添加customCode1自定义代码块并选择操作成功如下

(3)开启顶部导航栏,点击页面编辑窗口右上角的【顶部导航栏】并开启,配置顶部导航栏背景色为 #FF006FFF

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到顶部导航栏中间位置中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容蓝牙连接文本颜色#FFFFFFFF文本大小18从【小部件面板】-> 【常用元素】中选择按钮小部件拖入到顶部导航栏右侧位置中,然后在右侧的属性编辑器中配置属性,属性信息如下: 按钮宽 40 高40按钮背景颜色#00C8C8C8按钮阴影大小0按钮打开动作流程编辑器,单击 事件下点击+号添加事件,再点击+号添加动作,信息如下 动作类型 --【导航】,设置导航到SetBleName页面从【小部件面板】-> 【基本元素】中选择图标小部件拖入到按钮小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 图标选择 setting图标大小 24图标颜色 #FFFFFFFF(4)页面内容设计

从【小部件面板】-> 【常用元素】中选择容器小部件拖入到页面编辑窗口内的上下布局中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 80 高20

背景颜色#00C8C8C8

从【小部件面板】-> 【基本元素】中选择雷达小部件拖入到页面编辑窗口内的上下布局中,然后在右侧的属性编辑器中配置属性,属性信息如下:

绑定变量 deviceList

宽320 高320

雷达指针

开启true指针颜色#FF00478D背景渐变

开启 true渐变类型 放射性渐变过渡点 颜色:#7740FAB0, 过渡点:0 颜色:#FFFFFFFF, 过渡点:1渐变中心 0,0渐变半径0.5水波纹属性

水波纹个数3水波纹颜色#1CE6ECEC是否填充 true扫描目标属性

点的大小 15点的颜色 #FF3B35B7操作成功如下

再次从【小部件面板】-> 【常用元素】中选择容器小部件 拖入到页面编辑窗口内的上下布局中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 无限大 高40

背景颜色#00C8C8C8

从【小部件面板】-> 【基本元素】中选择 条件生成器小部件 拖入到容器小部件中,然后在右侧的属性编辑器中选择变量scaning,属性信息如下:

条件 scaning = false,勾选展示此界面,从【小部件面板】-> 【常用元素】中选择按钮小部件拖入到条件生成器小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

按钮宽 120 高40按钮背景颜色#00C8C8C8按钮阴影大小0按钮动作面板中打开动作流程编辑器,单击 事件下点击+号添加事件,再点击+号添加动作,信息如下 动作类型 --【自定义代码块】,添加customCode2自定义代码块并选择从【小部件面板】-> 【常用元素】中选择文本小部件拖入到按钮小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容 重新扫描

字体颜色 #FF006FFF

字体大小 18

字体粗细 500

条件 scaning = true,勾选展示此界面,从【小部件面板】-> 【常用元素】中选择文本小部件拖入到条件生成器小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

文本内容 正在扫描文本大小 18字体粗细 500操作成功如下

从【小部件面板】-> 【基本元素】中选择滚动条小部件拖入到页面编辑窗口内的上下布局中

从【小部件面板】-> 【布局元素】中选择列表布局小部件拖入到滚动条小部件中

绑定变量 deviceList

宽340 高350

操作成功如下

从【小部件面板】-> 【常用元素】中选择容器小部件拖入到列表布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽无限大 高80

背景颜色 #FFFFFFFF

圆角10

内边距10

外边距 上:10 下:10

从【小部件面板】-> 【常用元素】中选择左右布局小部件拖入到容器小部件中

从【小部件面板】-> 【常用元素】中选择上下布局小部件拖入到左右布局小部件中

拖入容器+文本到上下布局小部件中,并设置 文本内容 ${deviceList[index]["name"] == '' ? '未知' : deviceList[index]["name"]}字体大小 16字体粗细 700容器宽 120 高20容器背景颜色#00C8C8C8拖入容器+文本到上下布局小部件中,并设置 文本内容 Mac: ${deviceList[index]['mac']} RSSI: ${deviceList[index]["rssi"]}字体颜色 #FF999999字体大小 14字体粗细 500容器宽 260 高20容器背景颜色#00C8C8C8从【小部件面板】-> 【常用元素】中选择按钮小部件拖入到左右布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 60 高40背景颜色#00C8C8C8阴影大小0

按钮动作面板中打开动作流程编辑器,单击 事件下点击+号添加事件,再点击+号添加动作,信息如下

动作类型 --【自定义代码块】,添加customCode3自定义代码块并选择

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到按钮小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

文本内容 连接

字体颜色 #FF006FFF

字体大小 14

字体粗细 500

操作成功如下

customCode1内容如下

void function() {

// 控制雷达扫描的动画

waterRippleController = AnimationController(

vsync: this,

duration: const Duration(seconds: 2),

);

radarViewController = AnimationController(

vsync: this,

duration: const Duration(seconds: 5),

);

// 蓝牙扫描结果处理

ble.onScanResults(callbackLast: (event) {

String name = event.advertisementData.advName;

// 设备名称过滤

String DEVICE_NAME = StorageUtil().read('DEVICE_NAME') ?? '';

if ((DEVICE_NAME.isNotEmpty &&

(name == '' || !name.contains(DEVICE_NAME))) ||

devices.contains(event)) {

return;

}

// 去重操作,防止重复设备添加

devices.add(event);

if (mounted) {

setState(() {

// 添加至设备列表

deviceList.add({

"name": event.device.platformName,

"rssi": event.rssi,

"mac": "mac",

"raw": event

});

});

}

});

// 扫描状态处理

ble.isScaning((event) {

if (mounted) {

setState(() {

scaning = event;

});

if (event) {

waterRippleController?.repeat();

radarViewController?.repeat();

} else {

waterRippleController?.stop();

radarViewController?.stop();

}

}

});

// 开始扫描

ble.status(timeout: const Duration(seconds: 8));

}customCode2内容如下

function() async {

EasyLoading.dismiss();

if (mounted) {

// 断开蓝牙

await ble.disconnect();

setState(() {

// 清空设备列表

devices.clear();

});

// 重新扫描设备

ble.status(timeout: const Duration(seconds: 8));

}

}customCode3内容如下

void function(index) {

if (scaning) {

ble.stopScan();

}

EasyLoading.show();

// 连接蓝牙

ble.connect(deviceList[index]['raw'].device,

serviceUUID: StorageUtil().read("serviceUUID") ?? '',

readCharacteristicUUID:

StorageUtil().read("readCharacteristicUUID") ?? '',

writeCharacteristicUUID:

StorageUtil().read("writeCharacteristicUUID") ?? '',

notifyCallBcak: () async {

Map json = {

"name": deviceList[index]['name'],

"id": deviceList[index]['mac']

};

await Get.toNamed('/DeviceNetWork', arguments: json);

EasyLoading.dismiss();

});

}SetBleName页面设计页面描述

蓝牙名称过滤,设置BLE名称后蓝牙只搜索该名称的设备读写UUID,如果不设置蓝牙的读写UUID,则默认向所有的读写UUID发送数据和接收数据效果图

实现流程

(1)在【页面管理】中单击SetBleName页面,在右侧的属性编辑器中添加页面变量

需要定义的变量如下

变量名称变量类型是否为数组默认值变量描述DEVICE_NAMEString否${StorageUtil().read("DEVICE_NAME") ?? ''}设备名称serviceUUIDString否服务UUIDreadCharacteristicUUIDString否读特征UUIDwriteCharacteristicUUIDString否写特征UUID操作成功如下

(2)开启顶部导航栏,点击页面编辑窗口右上角的【顶部导航栏】并开启,配置顶部导航栏背景色为 #FF006FFF

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到顶部导航栏中间位置中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容设置文本颜色#FFFFFFFF文本大小18(3)页面内容设计

从【小部件面板】-> 【常用元素】中选择容器小部件拖入到页面编辑窗口内的上下布局中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 无限大 高600

背景颜色#00C8C8C8

内边距10

从【小部件面板】-> 【常用元素】中选择上下布局小部件拖入到容器小部件中

从【小部件面板】-> 【常用元素】中选择上下布局小部件拖入到上下布局小部件中

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到上下布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容BLE名称从【小部件面板】-> 【常用元素】中选择容器小部件拖入到上下布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 宽 无限大 高50背景颜色#00C8C8C8下边框 宽度 1 颜色 #FF999999 样式 一从【小部件面板】-> 【表单元素】中选择文本输入框小部件拖入到容器小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 数据绑定变量 DEVICE_NAME光标颜色#FF006FFF操作成功如下复制上述上下布局小部件及其子小部件的内容,并粘贴,修改内容如下

文本内容 服务UUID 、读特征UUID 、写特征UUID绑定变量 serviceUUID 、readCharacteristicUUID 、writeCharacteristicUUID操作成功如下

从【小部件面板】-> 【常用元素】中选择按钮小部件拖入到上下布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到按钮小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

文本内容 确认

字体颜色 #FFFFFFFF

字体大小 14

字体粗细 500

宽 无限大 高40

背景颜色#FF006FFF

阴影大小4

圆角大小10

按钮动作面板中打开动作流程编辑器,单击 事件下点击+号添加事件,再点击+号添加动作,信息如下

动作类型 --【自定义代码块】,添加customCode1自定义代码块并选择customCode1内容如下

void function(){

StorageUtil().write("DEVICE_NAME", DEVICE_NAME);

StorageUtil().write("serviceUUID", serviceUUID);

StorageUtil().write("readCharacteristicUUID", readCharacteristicUUID);

StorageUtil().write("writeCharacteristicUUID", writeCharacteristicUUID);

EasyLoading.showSuccess("设置成功");

Get.back();

}DeviceNetWork页面设计页面描述

在页面初始化时,会依次执行以下操作 蓝牙接收数据监听,接收到数据后进行存储并重新构建页面蓝牙连接状态监听,如果蓝牙断开连接,则在400ms后回到上一个页面发送数据,用户在输入框中输入16进制数据后点击发送即可效果图

实现流程

(1)在【页面管理】中单击DeviceNetWork页面,在右侧的属性编辑器中添加页面变量

需要定义的变量如下

变量名称变量类型是否是列表默认值变量描述passwordMap是接收的数据内容isConnectedBool否false连接状态wifinameString否发送数据内容_getDataVar否数据接收流_connectionSubscriptionVar否连接状态流disconnectTimerVar否断开连接定时器(2)添加页面初始化动作,在右侧的属性编辑器中点击【动作】-> 【打开】

在操作流程编辑器中,页面初始化 事件下点击+号添加事件,再点击+号添加动作,信息如下

动作类型 --【自定义代码块】,添加customCode1自定义代码块并选择customCode1内容如下

void function(){

_connectionSubscription?.cancel();

_connectionSubscription = ble.connectController.stream.listen((event) {

if (event is BluetoothConnectionState) {

if (mounted) {

setState(() {

switch (event) {

case BluetoothConnectionState.connected:

isConnected = true;

break;

case BluetoothConnectionState.disconnected:

disconnectTimer?.cancel();

disconnectTimer = Timer(const Duration(milliseconds: 400), () {

if (connectStatus == BluetoothConnectionState.disconnected) {

//400毫秒后还是未连接才代表断开了连接,回到以前的界面

print("400毫秒后还是未连接才代表断开了连接,回到以前的界面");

EasyLoading.showError("设备断开了连接");

Get.offNamed('/');

}

});

break;

default:

}

});

}

}

});

_getData?.cancel();

_getData = ble.getBleDateController.stream.listen((event) {

if (event is List && event.length != 0) {

List newArr = event;

print("蓝牙发送过来的数据_netWork:$newArr");

List dataArr = [];

for (var i = 0; i < newArr.length; i++) {

var element = newArr[i];

String str = '';

str = element.toRadixString(16);

str = str.length == 1 ? "0$str" : str;

dataArr.add(str);

}

password.add({

"type": "接收",

"data": dataArr.join(),

"time": DateFormat("HH:mm:ss").format(DateTime.now()),

});

setState(() {});

}

});

}(3)开启顶部导航栏,点击页面编辑窗口右上角的【顶部导航栏】并开启,配置顶部导航栏背景色为 #FF006FFF

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到顶部导航栏中间位置中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容数据收发文本颜色#FFFFFFFF文本大小18(4)页面内容设计

从【小部件面板】-> 【常用元素】中选择容器小部件拖入到页面编辑窗口内的上下布局中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 无限大 高700

背景颜色#C8C8C800

内边距10

从【小部件面板】-> 【常用元素】中选择上下布局小部件拖入到容器小部件中

拖入 容器+文本 到上下布局小部件中,并设置

文本内容 连接状态: ${isConnected?'已连接': '未连接' }宽 无限大 高30背景颜色#00C8C8C8拖入 容器+文本 到上下布局小部件中,并设置

文本内容 数据收发内容宽 无限大 高40背景颜色#00C8C8C8从【小部件面板】-> 【常用元素】中选择容器小部件拖入到上下布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 无限大 高300背景颜色#00C8C8C8从【小部件面板】-> 【布局元素】中选择列表布局小部件拖入到容器小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 数据变量绑定 password从【小部件面板】-> 【常用元素】中选择文本小部件拖入到列表布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容 ${password[index]['type']}: ${password[index]['data']}拖入 容器+文本 到上下布局小部件中,并设置

文本内容 发送数据内容宽 无限大 高40背景颜色#00C8C8C8从【小部件面板】-> 【常用元素】中选择容器小部件拖入到上下布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

宽 无限大 高50背景颜色#00C8C8C8下边框 颜色 #FF999999 宽度 1 样式 一从【小部件面板】-> 【表单元素】中选择文本输入框小部件拖入到容器小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 输入框数据变量绑定 wifiname输入框光标颜色 #006FFFFF从【小部件面板】-> 【常用元素】中选择按钮小部件拖入到上下布局小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下:

从【小部件面板】-> 【常用元素】中选择文本小部件拖入到按钮小部件中,然后在右侧的属性编辑器中配置属性,属性信息如下: 文本内容 发送数据

字体颜色 #FFFFFFFF

宽 200 高40背景颜色 #FF006FFF圆角 10按钮动作面板中打开动作流程编辑器,单击 事件下点击+号添加事件,再点击+号添加动作,信息如下 动作类型 --【自定义代码块】,添加customCode2自定义代码块并选择customCode2内容如下

void function() async {

if (wifiname == null) {

EasyLoading.showError("请输入数据".tr);

return;

}

List intArray = [];

for (int i = 0; i < wifiname.length; i += 2) {

String hexPair = wifiname.substring(i, i + 2);

intArray.add(int.parse(hexPair, radix: 16));

}

password.add({"type": "发送", "data": wifiname});

setState(() {});

await ble.writeWithOut(intArray);

}

最新发表
友情链接