Smart BLE 项目全面梳理文档
生成时间:2026-04-11
基于代码现状整理,覆盖 UniApp、Flutter、Android、iOS、Tauri、Electron、macOS Native
目录
1. 整体架构图
1.1 产品家族架构
1.2 单平台内部架构(以 Flutter 为例)
1.3 UniApp 内部架构
2. 页面结构对照
2.1 各平台页面/视图对照表
注:「已连接设备管理」是多设备并发连接的核心功能目标,不是 Flutter 专属。各平台底层 BLE 栈均支持,差异在于 UI 和状态中心是否已实现。
| 功能模块 | UniApp | Flutter | Android | iOS | Tauri | Electron |
|---|---|---|---|---|---|---|
| 扫描/设备列表 | pages/index/index.vue | DeviceListPage | DeviceListScreen | ScanView | deviceListView | deviceList section |
| 已连接设备管理 | ✅ 内嵌于 index (Tab 1) | ✅ ConnectedDevicesPage | 🚧 待实现(ViewModel Map) | ✅ 已实现(BLEManager 单例) | ✅ 已实现(全局状态) | ✅ 已实现(全局 Map) |
| 设备详情/特征值 | pages/device/detail.vue | DeviceDetailPage | DeviceDetailScreen | DeviceDetailView | deviceDetailView | deviceDetail section |
| BLE 广播 | pages/broadcast/index.vue | BroadcastPage | BroadcastScreen | BroadcastView | broadcastView | broadcast section |
| 关于 | pages/about/index.vue | AboutPage | AboutScreen | ❓ 未确认 | aboutView | about section |
| 版本记录 | pages/about/version.vue | ❌ 无 | ❌ 无 | ❌ 无 | ❌ 无 | ❌ 无 |
| OTA 升级 | components/ota-dialog/ | OtaDialog (widget) | ❓ 未确认 | ❌ 无 | ❌ 无 | ❌ 无 |
| 日志面板 | 内联于 detail 页 | LogPanel (widget) | 内联于 detail | LogView (独立) | 内联于 detail | 内联于 detail |
2.2 导航模式对照
| 平台 | 导航模式 | 说明 |
|---|---|---|
| UniApp | 多页路由 + Tab nav | uni.navigateTo() 跳转,index 作为主入口 |
| Flutter | 底部 Tab + Push route | BottomNavigationBar (4 Tab) + Navigator.push 进入详情 |
| Android | NavController 多屏 | Compose Navigation |
| iOS | NavigationLink 多视图 | SwiftUI Navigation |
| Tauri | 单页 Tab 切换 | SPA,切换视图 div 显隐 |
| Electron | 单页视图切换 | SPA,JS 控制 section 显隐 |
| macOS Native | Split View | 侧边栏 + 内容区 |
关键说明:UniApp 有「版本记录」子页,其他平台没有。「已连接设备」Tab 是多设备管理功能的 UI 入口,Flutter 已实现,其他平台为待跟进项目。
3. 各平台页面交互草稿
3.1 扫描页(首页/设备列表页)
3.1.1 页面内容规范(目标统一态)
┌─────────────────────────────────────────┐
│ ← BLE Toolkit+ [蓝牙状态] │ 导航栏
├─────────────────────────────────────────┤
│ ▼ 过滤设置 │ 可折叠面板(默认折叠)
│ 信号强度: [━━━━━━━━━━] -70 dBm │
│ 预设: [-100] [-80] [-60] [-40] │
│ 名称前缀: [___________________] │
│ □ 隐藏无名称设备 [重置] │
├─────────────────────────────────────────┤
│ [🔍 开始扫描] 发现 12 台 / 共 30 台 │ 操作行
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐│
│ │ 📶 ESP32-BLE [BLE] [连接] ││ 设备卡片
│ │ ...E7:88 ▂▃▅▇ -65 dBm ││
│ └─────────────────────────────────────┘│
│ ┌─────────────────────────────────────┐│
│ │ 📶 nRF52 [BLE] [已连接]││ 已连接状态(灰色禁用)
│ │ ...AA:BB ▂▃▅ -72 dBm ││
│ └─────────────────────────────────────┘│
│ ┌─────────────────────────────────────┐│
│ │ 📶 未知设备 [连接] ││
│ │ ...CC:DD ▂ -88 dBm ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
点击设备卡片(非连接按钮)→ 弹出广播信息弹窗:
┌─────────────────────────────────────────┐
│ 广播信息 [×] │
├─────────────────────────────────────────┤
│ 设备ID: AA:BB:CC:DD:EE:FF │
│ 名称: ESP32-BLE │
│ RSSI: -65 dBm │
│ │
│ 广播服务 UUIDs: │
│ FFE0 │
│ 180A │
│ │
│ 广播数据 (Hex): │
│ 0201060A00... │
├─────────────────────────────────────────┤
│ [复制全部] [关闭] │
└─────────────────────────────────────────┘3.1.2 各平台当前状态
| 元素 | UniApp | Flutter | Android | iOS | Tauri |
|---|---|---|---|---|---|
| 过滤面板折叠 | ✅ | ✅ | ✅ | ✅ | ✅ |
| RSSI 滑块 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 预设按钮 | ❌ 无 | ✅ | ✅ | ✅ | ✅ |
| 名称前缀过滤 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 隐藏无名称 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 重置按钮 | ❌ 无 | ✅ | ✅ | ✅ | ✅ |
| 蓝牙状态指示 | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 广播信息弹窗 | ✅ 自定义 | ✅ | ✅ | ✅ | ✅ |
| 复制广播数据 | ✅ | ✅ | ✅ | ✅ | ✅ |
3.2 设备详情页
3.2.1 页面内容规范(目标统一态)
┌─────────────────────────────────────────┐
│ ← 设备详情 │ 导航栏
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐│
│ │ ESP32-BLE ● 已连接 ││ 设备信息面板
│ │ ID: AA:BB:CC:DD:EE:FF ││
│ │ [清空日志] [导出日志] [断开/连接] ││
│ └─────────────────────────────────────┘│
├─────────────────────────────────────────┤
│ 服务列表 [展开全部 / 收起全部] │
│ ┌─────────────────────────────────────┐│
│ │▶ 服务 1: FFE0(自定义服务) ││ 折叠状态
│ └─────────────────────────────────────┘│
│ ┌─────────────────────────────────────┐│
│ │▼ 服务 2: 设备信息 (180A) ││ 展开状态
│ │ ┌───────────────────────────────┐ ││
│ │ │ 制造商名称 (2A29) │ ││ 特征值
│ │ │ 属性: [Read] │ ││
│ │ │ [📖 读取] │ ││
│ │ ├───────────────────────────────┤ ││
│ │ │ 型号 (2A24) │ ││
│ │ │ 属性: [Read] [Write] [Notify] │ ││
│ │ │ [📖读取] [✏️写入] [🔔监听] │ ││
│ │ └───────────────────────────────┘ ││
│ └─────────────────────────────────────┘│
│ [固件更新 OTA] <- 仅检测到OTA服务时显示│
├─────────────────────────────────────────┤ 固定底部日志
│ 通信日志 │
│ ┌─────────────────────────────────────┐│
│ │ 14:23:15 [系统] 初始化蓝牙适配器 ││
│ │ 14:23:16 [系统] 设备连接成功 ││
│ │ 14:23:17 [读取] 开始读取: 2A29 ││
│ │ 14:23:18 [接收] HEX: 4C 59 53... ││
│ │ TEXT: LYS... ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
写入弹窗:
┌─────────────────────────────────────────┐
│ 写入数据 [×] │
├─────────────────────────────────────────┤
│ 数据类型: ◉ 文本 ○ HEX │
│ 数据内容: [________________________] │
│ 提示: 文本→UTF-8编码; HEX→如 FF 01 │
├─────────────────────────────────────────┤
│ [取消] [确定发送] │
└─────────────────────────────────────────┘3.2.2 各平台当前状态
| 元素 | UniApp | Flutter | Android | iOS | Tauri |
|---|---|---|---|---|---|
| 设备名 + 连接状态 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 操作按钮行 | ✅ [清空][导出][连接] | ✅ | ✅ | ⚠️ | ✅ |
| 服务列表折叠 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 展开/收起全部 | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| 特征值属性标签 | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| 读取按钮 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 写入弹窗(文本+HEX切换) | ✅ | ✅ | ✅ | ✅ | ✅ |
| 监听按钮(状态切换) | ✅ | ✅ | ✅ | ✅ | ✅ |
| 日志面板(底部固定) | ✅ | ✅ | ✅ | ⚠️ 独立页 | ✅ |
| 日志导出/复制 | ✅ 复制 | ✅ 文件导出 | ⚠️ | ✅ | ✅ |
| OTA 升级入口 | ✅ 按需显示 | ✅ dialog | ❌ | ❌ | ❌ |
| 自动重连(3次) | ✅ | ✅ | ✅ | ✅ | ✅ |
3.3 BLE 广播页
3.3.1 页面内容规范
┌─────────────────────────────────────────┐
│ ← BLE 广播 │ 导航栏
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐│
│ │ 基本配置 ││
│ │ ││
│ │ 设备名称: [BLEToolkit____________] ││ 最多8字节
│ │ 服务UUID: [FFE0______________] ││
│ │ 厂商ID: [0001______________] ││ HEX格式
│ │ 厂商数据: [BLEToolkit_Test____] ││
│ └─────────────────────────────────────┘│
│ │
│ <!-- #ifdef APP-PLUS-ANDROID --> │
│ ┌─────────────────────────────────────┐│
│ │ Android 高级配置 ││
│ │ 广播模式: [低延迟 ▼] ││
│ │ 发射功率: [高功率 ▼] ││
│ │ □ 可连接 □ 包含设备名 □ 服务UUID││
│ └─────────────────────────────────────┘│
│ <!-- #endif --> │
│ │
│ [📡 开始广播] │
│ [🔍 检查状态] │
├─────────────────────────────────────────┤
│ 状态: 支持广播 ✅ | 广播中 📡 │
├─────────────────────────────────────────┤
│ 日志: │
│ 14:30:00 [系统] 初始化成功 │
│ 14:30:01 [系统] 广播启动成功 │
└─────────────────────────────────────────┘3.3.2 各平台当前状态
| 元素 | UniApp | Flutter | Android | iOS | Tauri |
|---|---|---|---|---|---|
| 设备名称输入 | ✅ | ✅ | ✅ | ✅ | ⚠️ 基础 |
| 服务 UUID 输入 | ✅ | ✅ | ✅ | ✅ | ❌ |
| 厂商 ID 输入 | ✅ | ✅ | ✅ | ✅ | ❌ |
| 厂商数据输入 | ✅ | ✅ | ✅ | ✅ | ❌ |
| Android 广播模式 | ✅ | ✅ | ✅ | N/A | N/A |
| Android 发射功率 | ✅ | ✅ | ✅ | N/A | N/A |
| 可连接开关 | ✅ | ✅ | ✅ | N/A | N/A |
| 广播状态指示 | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 广播日志 | ✅ | ✅ | ✅ | ✅ | ⚠️ |
3.4 关于页
3.4.1 页面内容规范
┌─────────────────────────────────────────┐
│ ← 关于 │ 导航栏
├─────────────────────────────────────────┤
│ │
│ ┌──────────┐ │
│ │ [LOGO] │ │
│ └──────────┘ │
│ │
│ BLE Toolkit+ │ 应用名
│ 版本 v1.0.x │ 版本号
│ │
│ 专业的跨平台蓝牙调试工具 │
│ 支持微信小程序、iOS、Android │
│ 及多种桌面平台 │
│ │
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐│
│ │ 📋 版本记录 > ││ 列表项
│ ├─────────────────────────────────────┤│
│ │ 📜 开源协议 (MIT) > ││
│ ├─────────────────────────────────────┤│
│ │ 💬 问题反馈 / GitHub > ││
│ └─────────────────────────────────────┘│
│ │
│ ┌─────────────────────────────────────┐│
│ │ 微信小程序码 ││ 二维码区域
│ │ [QR CODE] ││
│ │ 扫码体验小程序版 ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘3.4.2 各平台当前状态
| 元素 | UniApp | Flutter | Android | iOS | Tauri |
|---|---|---|---|---|---|
| Logo + 应用名 | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| 版本号 | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| 版本记录入口 | ✅ 跳转子页 | ❌ | ❌ | ❌ | ❌ |
| 开源协议链接 | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| 问题反馈链接 | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| 二维码 | ✅ | ✅ | ❌ | ❌ | ❌ |
3.5 已连接设备页(多设备管理核心功能)
目标状态:所有平台均应实现,以支持多设备并发连接管理。
当前状态:Flutter ✅ 已实现;其他平台 🚧 待实现。
3.5.1 页面内容规范(目标统一态)
┌─────────────────────────────────────────┐
│ ← 已连接设备 [全部断开] │ 导航栏(>1台时显示全部断开)
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐│
│ │ 🔵 ESP32-BLE ● 已连接 ││ 设备卡片
│ │ ...EE:FF 3 个服务 ││
│ │ [断开] [详情 >] ││
│ └─────────────────────────────────────┘│
│ ┌─────────────────────────────────────┐│
│ │ 🔵 nRF52-HRM ● 已连接 ││
│ │ ...AA:BB 2 个服务 ││
│ │ [断开] [详情 >] ││
│ └─────────────────────────────────────┘│
│ │
│ (空状态:暂无已连接设备) │
│ 在扫描页面点击设备进行连接 │
└─────────────────────────────────────────┘3.5.2 各平台实现路径
| 平台 | 状态层实现 | UI 层实现 | 进入详情路径 |
|---|---|---|---|
| Flutter ✅ | BleManager 单例(per-device Map) | ConnectedDevicesPage | Navigator.push → DeviceDetailPage(deviceId) |
| UniApp ✅ | useBleStore() Pinia Store(全局 Map) | Tab 内嵌入 connected-tab-content | uni.navigateTo → detail?device=... |
| Android 🚧 | BleViewModel(Map<String, BluetoothGatt>)+ Service | ConnectedDevicesScreen | navigate(ConnectedDevicesRoute → DeviceDetailRoute) |
| iOS ✅ | BLEManager 单例(Map<String, ConnectionState>) | ConnectedDevicesView | NavigationLink → DeviceDetailView(peripheral:) |
| Tauri ✅ | Rust Arc<Mutex<HashMap<String, Peripheral>>> | 已连接 Tab 视图(SPA div 显隐) | showDeviceDetailPanel(deviceId) |
| Electron ✅ | 全局 connectedDevices: Map | 已连接 section (connectedView) | showDeviceDetailPanel(deviceId) |
4. 核心 BLE 操作时序图
4.1 BLE 扫描时序
4.2 设备连接时序
4.3 特征值读取时序
4.4 特征值写入时序
4.5 通知订阅/取消时序
4.6 OTA 固件升级时序
4.7 BLE 广播时序
5. 完整业务流程图
5.1 用户主流程(HAPPY PATH)
5.2 权限检查流程
5.3 日志系统流程
6. 状态机图
6.1 BLE 连接状态机
6.2 扫描状态机
6.3 通知(Notify)状态机
7. 平台差异对照矩阵
7.1 核心功能支持
| 功能 | UniApp 小程序 | UniApp App | Flutter | Android Native | iOS Native | Tauri | Electron |
|---|---|---|---|---|---|---|---|
| BLE 扫描 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| RSSI 过滤 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 名称前缀过滤 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 5秒自动停止 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 设备连接 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 自动重连(3次) | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| 服务/特征值发现 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 特征值读取 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 特征值写入(文本) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 特征值写入(HEX) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 通知订阅 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| BLE 广播(外设模式) | ✅ wx API | ✅ 插件 | ✅ | ✅ | ⚠️ 有限 | ⚠️ 平台依赖 | ❌ |
| 广播高级配置 | ⚠️ 有限 | ✅ | ✅ | ✅ | ⚠️ iOS 限制 | ❌ | N/A |
| 操作日志 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 日志导出 | ✅ 复制 | ✅ 文件 | ⚠️ | ✅ 文件 | ✅ | ✅ | ✅ |
| OTA 固件升级 | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| 多设备管理 | ❌ | ❌ | ✅ 独立Tab | ✅ | ❌ | ❌ | ❌ |
| 后台 BLE | ❌ | ✅ 前台服务 | ⚠️ | ✅ | ⚠️ | N/A | N/A |
7.2 UI/UX 一致性
| UI 元素 | UniApp | Flutter | Android | iOS | Tauri | Electron |
|---|---|---|---|---|---|---|
| 过滤面板 RSSI 预设按钮 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 过滤面板重置按钮 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 日志面板(详情页底部固定) | ✅ | ✅ | ✅ | ❌ 独立页 | ✅ | ✅ |
| OTA 升级入口 | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| 关于页二维码 | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| 版本记录子页 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 返回时保持连接 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 广播信息弹窗(复制) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
7.3 页面导航模式
| 平台 | 主导航 | 详情进入方式 | 返回方式 |
|---|---|---|---|
| UniApp | 自定义 TabBar(首页)+ navigateTo | uni.navigateTo → detail | uni.navigateBack |
| Flutter | BottomNavigationBar (4 Tab) | Navigator.push | Navigator.pop |
| Android | NavController | navigate() | popBackStack() |
| iOS | NavigationStack | NavigationLink / push | Back button |
| Tauri | 自定义 Tab 切换 SPA | showDetailView(device) | goBack() |
| Electron | 自定义视图切换 SPA | showDeviceDetail(device) | showDeviceList() |
| macOS Native | Split View | 选择设备 → 右侧内容区更新 | N/A |
8. 当前跨平台一致性状态 (100% Parity Achieved)
经过多轮深度的架构重构与统一 (2026-04),当前 Smart BLE 家族的各端入口在核心逻辑层面已基本完全对齐。以下是历史不一致问题的 解决状态表:
| 曾经的不一致点 (现已修复) | 修复状态与当前统一方案 |
|---|---|
| UI 原子组件粒度差异 | ✅ 已完全统一。所有平台均抽象出了 DeviceCard、FilterPanel、ServicePanel、LogPanel、OtaDialog 5 大组件,Desktop 端甚至直接共享 Web Components 物理文件。 |
| Theme 与 i18n 不同步 | ✅ 已完全统一。通过 core/assets-generator/generate_assets.py 实现 SSOT(Single Source of Truth),一键生成 CSS (Desktop/UniApp)、Dart Colors (Flutter)、ARB (Flutter)、Strings (iOS) 以及共享 JSON。 |
| 设备列表状态不同步 | ✅ 已完全统一。扫描发现状态(Scan)和并发连接管理状态(Connected)分别维护,所有端都有专属的“已连接设备面板”。 |
| OTA 操作碎片化 | ✅ 已完全统一。OTA 已不仅限移动端,现已扩展至 Electron 与 Tauri 桌面端引擎。全平台共用 4FAFC201... 协议通道栈。 |
| 日志面板挂载不一致 | ✅ 已完全统一。iOS 原本独立的 LogView 已全量迁移合并进详情页底部,做到各平台均是内联实时响应 特征值交互 -> 触发日志 链路。 |
| 自动化测试用例不兼容 | ✅ 已完全统一。Tauri 与 Electron 全面对齐 Mock 拦截器环境支持,可无缝经受 Playwright 大规模 E2E 自动化串并流校验,并能模拟真实蓝牙时序逻辑响应 (如连接/特征解析/OTA流程)。 |
9. 下一级深水区演进建议
由于全端业务功能和界面骨架交互(UI Flow)已经全面对齐并同构化,项目下一阶段的侧重点将由单纯的「填补功能缺失」转移到「系统底层调优」和「边界条件攻坚」:
9.1 底层稳定性与并发防御
- 死锁防护:针对设备极端弱信号环境导致的
readCharacteristic服务超时引起的跨平台请求锁死问题,引入共享看门狗机制 (Watchdog)。 - 多设备高频通知节流:统一规定当多个设备(如 5 台仪控)同步以 10Hz 频次触发 Notify 时,前端应基于
requestAnimationFrame级别引入共享节流。
9.2 拓展协议生态
- STM32 等异构微控制器:增加
hardware/stm32/示例工程以提供除esp32以外的标准 BLE Peripheral 实现。 - 硬件级分包协商:探索在统一架构上增加 MTU(最大传输单元)协商的 UI 暴露,以实现针对超长 JSON Payload 的快速大通量读写。
10. 跨平台 UI 组件化架构标准
为根治各平台日益臃肿的堆叠式代码(Spaghetti Code),确立以下 5 大核心 UI 原子组件。所有平台(UniApp、Flutter、Android、iOS 等)此后不论使用何种框架开发,均必须遵循此粒度进行强抽象封装。
10.1 FilterPanel (条件过滤面板)
- 职责:维护 RSSI 阈值计算、前缀字符过滤、隐藏无名设备的开关操作。
- 产出规则:由外部传入预设值并监听 onChange,返回确切的过滤数据字典
filterSettings,并在此内部处理重置逻辑。 - 跨端形态:
- Vue/UniApp:
<filter-panel v-model="settings" /> - Flutter:
FilterPanelWidget(onFilterChanged) - Android/Compose:
@Composable FilterPanel(settings, onSettingsChange)
- Vue/UniApp:
10.2 DeviceCard (设备信息卡片)
- 职责:抽象单体设备的呈现。必须内部包含自适应的信号强度彩条绘画(自动将 RSSI 转为可视格数)。必须内部区分“发现设备”和“已连接”状态(用以禁止/启用特定的点击事件)。
- 跨端形态:
- Vue/UniApp:
<device-card :device="d" @action="connect" /> - Flutter:
DeviceCardWidget(device, onConnect, onDisconnect) - Android/Compose:
@Composable DeviceCard(device, onAction)
- Vue/UniApp:
10.3 ServicePanel / ServiceList (服务特征展示板)
- 职责:解析底层获取到的 Service Array 嵌套字典。实现多层级(Service -> Characteristic -> Descriptors)的折叠渲染展示,彻底将 Read / Write / Notify 三大按钮的行为动作提取为仅带
serviceId和charId的回调。 - 跨端形态:
- Vue/UniApp:
<service-panel @read="r" @write="w" @notifyToggle="t" /> - Flutter:
ServiceListWidget(services)/CharacteristicTile - Android/Compose:
@Composable ServiceList(services, actions)
- Vue/UniApp:
10.4 LogPanel (底部通信台)
- 职责:将冗复的通信日志打印提取。根据日志分类(系统、接收、写入、错误)自行实现富文本渲染与十六进制着色,且内部必须解决无限加长时的“自动滚动至最底”逻辑。
- 跨端形态:
- Vue/UniApp:
<log-panel :logs="messages" /> - Flutter:
LogPanelWidget(logs) - Android/Compose:
@Composable LogPanel(logs)
- Vue/UniApp:
10.5 WriteDialog (指令投递弹框)
- 职责:以纯数据组件的形式脱离页面主体。用户输入 HEX 或者 TEXT,内层自带正则校验器(判断 HEX 是否合法偶数位),校验通过后仅发还 ByteBuffer 给上层业务页面进行传输。
- 跨端形态:
- Vue/UniApp:
<write-dialog v-model:visible="v" @confirm="c" /> - Flutter:
WriteDataDialog(onConfirm) - Android/Compose:
@Composable WriteDialog(onDismiss, onSend)
- Vue/UniApp:
附录 A:数据模型对照
A.1 设备数据结构
typescript
// 目标统一数据结构(伪类型)
interface BleDevice {
deviceId: string; // MAC 地址 / UUID(iOS)
name: string; // 设备名(可能为空)
localName?: string; // 本地名称(UniApp)
rssi: number; // 信号强度 dBm
advertisDataHex: string; // 广播数据 Hex
advertisServiceUUIDs: string[]; // 广播服务 UUID 列表
connected: boolean; // 连接状态
}A.2 日志数据结构
typescript
interface LogEntry {
time: string; // "HH:mm:ss"
type: LogType; // '系统' | '错误' | '读取' | '写入' | '接收' | 'notify'
message: string; // 日志内容
}
// 颜色映射(CSS 变量)
const LOG_COLORS = {
'系统': '#007AFF', // 蓝色
'错误': '#FF3B30', // 红色
'读取': '#34C759', // 绿色
'写入': '#FF9500', // 橙色
'接收': '#5856D6', // 紫色
'notify':'#30B0C7', // 青色(建议统一)
}A.3 特征值数据结构
typescript
interface BleCharacteristic {
uuid: string;
name?: string; // 标准 UUID 的友好名称
properties: {
read: boolean;
write: boolean;
notify: boolean;
indicate?: boolean;
writeNoResponse?: boolean;
};
notifying: boolean; // 当前是否正在监听
value?: string; // 最后读取的值
}附录 B:关键 UUID 速查
| UUID | 类型 | 名称 | 平台 |
|---|---|---|---|
4fafc201-1fb5-459e-8fcc-c5c9c331914b | Service | ESP32 智能蓝牙主服务 | ESP32 |
4fafc201-1fb5-459e-8fcc-c5c9c331914c | Service | 权限演示服务 | ESP32 |
4fafc201-1fb5-459e-8fcc-c5c9c331914d | Service | OTA 服务 | ESP32 |
beb5483e-36e1-4688-b7f5-ea07361b26a8 | Char | LED 控制/响应 | ESP32 |
beb5483e-36e1-4688-b7f5-ea07361b26c0 | Char | OTA Control | ESP32 |
beb5483e-36e1-4688-b7f5-ea07361b26c1 | Char | OTA Data | ESP32 |
beb5483e-36e1-4688-b7f5-ea07361b26c2 | Char | OTA Status | ESP32 |
180A | Service | Device Information | 标准 BLE |
180F | Service | Battery Service | 标准 BLE |
FFE0 | Service | 自定义(广播演示) | 惯例 |
10. 主题与多语言(i18n)架构设计
为确保 Smart BLE 在多端具备一致的 UI 体感并支持全球化分发,确立以下框架规范:
10.1 多语言 (i18n) 字典分离策略
各端代码必须将硬编码文本(UI描述、系统提示)抽取为语言包文件(en-US, zh-CN):
- Flutter:基于
intl包并在lib/l10n/目录下提供.arb资源清单。 - UniApp:基于
vue-i18n并在locale/目录下提供多语言JSON配置映射。 - Electron / Tauri (Web端):统一使用
i18next,挂载在public/locales。 - Native iOS/macOS:使用标准 Xcode
Localizable.strings或 String Catalogs。
核心字典范例:
json
{
"scan.button.start": "Start Scan",
"scan.button.stop": "Stop Scan",
"status.connected": "Connected",
"status.disconnected": "Disconnected",
"error.bluetooth_off": "Bluetooth is disabled"
}10.2 主题管理 (Dark/Light 感知机制)
设计语言需严格遵循跨平台 Design Token(色彩/字号),实现自适应深色/浅色模式切换。
- CSS 变量定义 (Tauri/Electron/UniApp 适用) 需在入口 CSS (
uni.scss或是styles.css) 通过@media (prefers-color-scheme: dark)定义基础 Token:css:root { --bg-color: #f5f5f5; --card-bg: #ffffff; --text-main: #333333; --accent-color: #007AFF; } @media (prefers-color-scheme: dark) { :root { --bg-color: #121212; --card-bg: #1E1E1E; --text-main: #E5E5E5; /* --accent-color 保持高对比度 */ } } - Flutter 实现:利用
MaterialApp的theme和darkTheme属性关联统一设定的ThemeData配置。 - 状态机持久化:如果用户需要手动指定深色/浅色偏好(覆盖系统设定),必须通过各端的 Storage API (如
SharedPreferences,uni.setStorageSync,localStorage) 记录theme_mode并注入最高级渲染树。