Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,314 @@
# 智能传感器数据采集与分析系统
## 概述
这是一套完整的高性能、可扩展的运动传感设备数据采集与分析系统,采用 UTS uni-app-x 技术栈开发,严格遵循 Android 最严格模式规范。系统支持多种生命体征数据的实时采集、存储、分析和可视化。
## 技术架构
### 前端技术栈
- **框架**: UTS uni-app-x
- **语言**: TypeScript (UTS)
- **UI框架**: uni-app-x 原生组件
- **数据请求**: AkSupa 链式请求库
- **实时通信**: Supabase Realtime
- **图表组件**: ak-charts
### 后端技术栈
- **数据库**: PostgreSQL + TimescaleDB
- **实时服务**: Supabase
- **AI分析**: RPC 函数
- **数据存储**: 时序数据库优化
## 功能模块
### 1. 主要页面结构
```
pages/sense/
├── nav.uvue # 导航入口页面
├── index.uvue # 实时监控主页
├── detail.uvue # 数据详情页面
├── analysis.uvue # 数据分析页面
├── devices.uvue # 设备管理页面
├── settings.uvue # 传感器设置页面
├── simulator.uvue # 数据模拟器页面
└── types.uts # 类型定义文件
```
### 2. 支持的传感器类型
- **心率监测**: 心率、RR间期、心率变异性
- **步数统计**: 步数、距离、卡路里
- **血氧检测**: 血氧饱和度、灌注指数
- **血压测量**: 收缩压、舒张压、脉压、平均动脉压
- **体温监测**: 体温、环境温度
- **步幅分析**: 步幅长度、步频、着地时间
- **位置定位**: GPS坐标、海拔、速度
- **心电图**: 原始信号、心律类型、各项间期
### 3. 核心功能
#### 实时数据监控 (index.uvue)
- 设备状态显示
- 实时指标卡片
- 多类型数据趋势图表
- 历史记录列表
- AI分析结果弹窗
- Supabase Realtime 订阅
#### 数据分析 (analysis.uvue)
- 时间范围选择 (24h/7d/30d/90d)
- 健康评分计算
- 指标趋势分析
- 异常检测与警报
- AI智能分析报告
- 数据对比功能
#### 设备管理 (devices.uvue)
- 蓝牙设备扫描
- 设备绑定/解绑
- 设备配置管理
- 采样频率设置
- 上传间隔配置
- 自动同步开关
#### 传感器设置 (settings.uvue)
- 通用设置开关
- 采集频率配置
- 异常阈值设置
- 通知配置
- 数据管理选项
- 隐私设置
- 设备校准功能
- 数据导出选项
#### 数据模拟器 (simulator.uvue)
- 实时数据模拟
- 传感器配置面板
- 批量数据生成
- 统计信息显示
- 数据预览功能
## 数据库设计
### 主要数据表
#### ss_sensor_measurements (通用测量表)
```sql
CREATE TABLE ss_sensor_measurements (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
device_id UUID REFERENCES ak_devices(id),
user_id UUID REFERENCES ak_users(id),
measurement_type VARCHAR(50) NOT NULL,
measured_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
unit VARCHAR(20),
raw_data JSONB NOT NULL,
quality_score INTEGER DEFAULT 100,
created_at TIMESTAMPTZ DEFAULT NOW()
);
```
#### 专项数据表
- `ss_heart_rate_data` - 心率专项数据
- `ss_steps_data` - 步数专项数据
- `ss_spo2_data` - 血氧专项数据
- `ss_blood_pressure_data` - 血压专项数据
- `ss_temperature_data` - 体温专项数据
- `ss_stride_data` - 步幅专项数据
- `ss_location_data` - 位置专项数据
- `ss_ecg_data` - 心电图专项数据
### 索引优化
- 时间序列索引 (measured_at)
- 设备+用户组合索引
- 测量类型索引
- JSONB 字段 GIN 索引
## 前端技术特点
### 1. 严格的 UTS 类型系统
```typescript
export type SensorMeasurement = {
id: string;
device_id: string;
user_id: string;
measurement_type: string;
measured_at: string;
unit: string;
raw_data: UTSJSONObject;
created_at: string;
}
```
### 2. 链式数据请求
```typescript
const result = await supa.from('ss_sensor_measurements')
.eq('device_id', deviceId)
.eq('user_id', userId)
.order('measured_at', { ascending: false })
.limit(50)
.execute()
```
### 3. 实时数据订阅
```typescript
realtimeSubscription = supa.from('ss_sensor_measurements')
.on('INSERT', (payload: UTSJSONObject) => {
// 处理实时数据更新
})
.subscribe()
```
### 4. 响应式设计
- 大屏/小屏自适应
- 动态字体缩放
- 触摸友好的交互
- 无障碍支持
## 性能优化
### 1. 数据库层面
- 时序数据库优化
- 分区表设计
- 索引优化
- 连接池管理
### 2. 前端层面
- 懒加载机制
- 虚拟滚动
- 数据缓存
- 防抖节流
### 3. 实时通信
- WebSocket 连接复用
- 数据压缩
- 断线重连
- 消息队列
## 安全考虑
### 1. 数据安全
- 端到端加密
- 本地数据加密存储
- 传输层 TLS 加密
- 敏感数据脱敏
### 2. 访问控制
- 用户身份验证
- 设备绑定验证
- 数据权限控制
- API 频率限制
### 3. 隐私保护
- 数据最小化原则
- 用户同意机制
- 数据匿名化
- 右to被遗忘
## 部署说明
### 1. 数据库部署
```bash
# 安装 PostgreSQL 和 TimescaleDB
# 运行数据库脚本
psql -f doc_ble/ss_sensor_data_schema.sql
psql -f doc_ble/ss_generate_mock_data.sql
```
### 2. 后端服务
- 配置 Supabase 项目
- 部署 RPC 函数
- 设置实时订阅规则
- 配置数据库连接
### 3. 前端应用
```bash
# 安装依赖
npm install
# 编译运行
npm run dev:app-android
```
## 扩展性设计
### 1. 模块化架构
- 独立的传感器模块
- 可插拔的分析引擎
- 标准化的数据接口
- 微服务架构支持
### 2. 多租户支持
- 租户级别的数据隔离
- 个性化配置
- 资源配额管理
- 计费系统集成
### 3. 国际化支持
- 多语言界面
- 地区化数据格式
- 时区处理
- 文化适配
## 监控与维护
### 1. 系统监控
- 数据采集状态监控
- 性能指标监控
- 错误日志收集
- 用户行为分析
### 2. 数据质量
- 数据完整性检查
- 异常值检测
- 数据一致性验证
- 质量评分系统
### 3. 备份恢复
- 自动数据备份
- 增量备份策略
- 灾难恢复计划
- 数据迁移工具
## 使用指南
### 1. 开发者
- 参考 types.uts 了解数据结构
- 使用 AkSupa 进行数据操作
- 遵循 UTS 严格模式规范
- 实现响应式设计
### 2. 用户
- 从导航页面 (nav.uvue) 开始
- 绑定传感器设备
- 配置采集参数
- 查看实时数据和分析报告
### 3. 管理员
- 监控系统运行状态
- 管理用户和设备
- 配置系统参数
- 维护数据质量
## 后续规划
### 1. 功能增强
- 更多传感器类型支持
- 高级AI分析算法
- 社交功能集成
- 健康建议系统
### 2. 技术升级
- 边缘计算支持
- 机器学习模型部署
- 区块链数据验证
- 5G 网络优化
### 3. 生态建设
- 第三方设备接入
- 开放API平台
- 开发者社区
- 商业化模式
---
本系统为高性能、企业级的传感器数据管理平台,具备完整的功能模块和良好的扩展性,可以满足各种规模的部署需求。

99
doc_ble/SUMMARY.md Normal file
View File

@@ -0,0 +1,99 @@
# 蓝牙协议整体总结
## 1. 协议定位与目标
- **协议名称**Wearable Band Bluetooth Protocol (WBBP)
- **应用场景**:运动手环与手机之间的数据通信
- **技术基础**BLE 4.0+,基于 GATT Profile
- **设计原则**:低功耗、可靠性、扩展性、安全性
## 2. 服务与特征总体结构
协议按功能划分为多个 BLE Service每个 Service 下有若干 Characteristic
- **设备信息服务 (DIS, UUID: 180A)**:型号、序列号、固件/硬件版本等基础信息
- **电池服务 (Battery, UUID: 180F)**:电池电量上报(可读/可通知)
- **主业务自定义服务 (Primary Custom Service)**
- 数据下发 (TX):手机→手环,命令/配置写入
- 数据上报 (RX):手环→手机,状态/数据通知
- 控制命令:关键控制类操作(需响应)
- **健康数据服务 (Health Data Service)**
- 心率、运动、睡眠等数据的定期/实时上报
- **紧急服务 (Emergency Service)**
- SOS 报警、录音数据上传等高优先级通道
## 3. 通信报文统一格式
所有上/下行命令尽量收敛为统一包格式,便于解析与扩展:
- **基础结构**STX + LEN + CMD + SEQ + DATA + CRC
- **字段含义**
- `STX`:固定 0xAA起始标志
- `LEN`:长度(不含 STX/CRC
- `CMD`:命令码,按功能分区(控制/健康/交互/紧急/系统)
- `SEQ`:序列号,用于 ACK / 重传 / 防重放
- `DATA`:变长载荷,最多 16 字节或按 MTU 协商扩展
- `CRC`XOR 校验,兼顾实现简单与错误检测
## 4. 命令空间规划
命令码按功能模块分段,避免冲突并方便查表:
- **基础控制 (0x000x0F)**PING、设备信息、时间同步、配置读写、固件升级、重启、ACK 等
- **健康数据 (0x100x2F)**:心率、步数、睡眠、血氧、体温、卡路里、实时监测控制与配置等
- **交互功能 (0x300x4F)**:消息通知、来电、闹钟、查找设备、相机/音乐控制等
- **紧急功能 (0x500x6F)**SOS 报警、录音数据、位置信息、跌倒/异常心率报警等
- **系统配置 (0x700x8F)**:显示、震动、语言、表盘、用户资料等
- **错误响应 (0xF00xFF)**:通用错误、不支持、参数错误、超时、硬件故障等
## 5. 关键业务流程概览
### 5.1 连接与心跳
- 扫描 → 广播 → 连接 → 服务发现 → PING/ACK 建链
- 通过周期性 CMD_PING 保活,超时触发重连逻辑
### 5.2 健康数据
- **心率/血氧/步数等** 均定义了结构化数据包:
- 含时间戳、数值本体、质量指标、活动类型等
- 支持:
- 单点数据上传
- 实时流式数据(心率、血氧实时监测)
- 组合数据(心率+血氧等生命体征合包,节省带宽)
### 5.3 实时监测控制
- 通过 CMD_REAL_TIME_START / CMD_REAL_TIME_STOP 控制:
- 监测类型(心率/血氧/体温/运动)
- 上报周期、监测时长、质量阈值
- 会话 ID 支撑多次监测任务区分
### 5.4 紧急与录音
- 紧急报警包含:时间戳、类型 (SOS/跌倒/心率异常)、严重程度、位置、用户 ID
- 录音采用分包:头包宣告总长度与格式,数据包携带固定长度音频块
## 6. 安全与可靠性设计
- **安全**
- 配对认证流程:配对码确认 + 密钥交换
- 数据加密AES-128对健康/录音/位置信息等敏感数据加密
- 防重放:依赖 SEQ + 时间戳 + 会话令牌
- **可靠性**
- XOR CRC 校验
- 统一错误码与错误响应结构
- ACK/超时/重传机制
## 7. 性能与功耗优化
- **MTU 协商**:从默认 23 升级到 185/247减少包头开销
- **数据压缩**
- 健康数据差值压缩
- 录音使用 ADPCM
- **功耗控制**
- 连接参数调整(连接间隔、超时)
- 批量发送,减少射频唤醒次数
- 省电模式与高性能模式可切换
## 8. 调试与测试
- 提供:
- PC 端模拟器
- BLE 抓包工具
- 压测方案(并发连接、大流量传输)
- 测试用例覆盖:
- 连接稳定性
- 各类数据上报正确性
- 紧急场景SOS/网络异常/低电量)
---
本总结面向整体架构与实现要点,可作为:
- 蓝牙协议快速入门说明
- APP/固件开发对接概要文档
- 后续扩展(如加入新的传感器/指令)时的设计约束参考。

177
doc_ble/ed.md Normal file
View File

@@ -0,0 +1,177 @@
school_id: bc123456-78cd-4ef0-a123-456789012345
grade_id:bc333333-78cd-4ef0-a123-456789012345
class_id
bc333301-78cd-4ef0-a123-456789012345
bc333302-78cd-4ef0-a123-456789012345
bc333303-78cd-4ef0-a123-456789012345
bc333304-78cd-4ef0-a123-456789012345
bc333305-78cd-4ef0-a123-456789012345
bc333306-78cd-4ef0-a123-456789012345
create table
public.system_dept (
id bigint generated by default as identity,
name character varying(30) not null default ''::character varying,
parent_id bigint not null default 0,
sort integer not null default 0,
leader_user_id bigint null,
phone character varying(11) null default null::character varying,
email character varying(50) null default null::character varying,
status smallint not null,
creator character varying(64) null default ''::character varying,
create_time timestamp without time zone not null default current_timestamp,
updater character varying(64) null default ''::character varying,
update_time timestamp without time zone not null default current_timestamp,
deleted smallint not null default 0,
tenant_id bigint not null default 0,
name_alias character varying null,
constraint pk_system_dept primary key (id)
) tablespace pg_default;
create table
public.member_user (
id bigserial,
nickname character varying(30) null default ''::character varying,
name character varying(30) null,
sex smallint null,
birthday timestamp without time zone null,
area_id integer null,
mark character varying(255) null,
point integer null default 0,
avatar character varying(255) null default ''::character varying,
status smallint not null default '1'::smallint,
mobile character varying(11) null default ''''''::character varying,
password character varying(100) not null default ''::character varying,
register_ip character varying(32) null default ''''''::character varying,
login_ip character varying(50) null default ''::character varying,
login_date timestamp without time zone null,
tag_ids character varying(255) null,
level_id bigint null,
experience bigint null,
group_id bigint null,
creator character varying(64) null default ''::character varying,
create_time timestamp without time zone not null default current_timestamp,
updater character varying(64) null default ''::character varying,
update_time timestamp without time zone not null default current_timestamp,
deleted boolean not null default false,
tenant_id bigint not null default 0,
user_id uuid not null,
cardno character varying null,
certificationnumber character varying null,
dept_ids bigint[] null,
role_ids bigint[] null,
avatar_file jsonb null,
constraint member_user_pkey1 primary key (user_id),
constraint member_user_id_key unique (id),
constraint unique_user_id unique (user_id),
constraint member_user_user_id_fkey foreign key (user_id) references users (id)
) tablespace pg_default;
create table
public.ak_users (
id uuid not null default gen_random_uuid (),
username character varying(64) not null,
email character varying(128) not null,
password_hash character varying(256) not null default gen_random_uuid (),
gender character varying(16) null default 'other'::character varying,
birthday date null,
height_cm integer null,
weight_kg integer null,
avatar_url text null,
region_id uuid null,
school_id uuid null,
grade_id uuid null,
class_id uuid null,
role character varying(32) null default 'student'::character varying,
created_at timestamp with time zone null default now(),
updated_at timestamp with time zone null default now(),
auth_id uuid null,
preferred_language uuid null,
bio text null,
phone text null,
constraint ak_users_pkey primary key (id),
constraint ak_users_email_key unique (email),
constraint ak_users_grade_id_fkey foreign key (grade_id) references ak_grades (id),
constraint ak_users_preferred_language_fkey foreign key (preferred_language) references ak_languages (id),
constraint ak_users_region_id_fkey foreign key (region_id) references ak_regions (id),
constraint ak_users_auth_id_fkey foreign key (auth_id) references users (id) on delete cascade,
constraint ak_users_school_id_fkey foreign key (school_id) references ak_schools (id),
constraint ak_users_class_id_fkey foreign key (class_id) references ak_classes (id)
) tablespace pg_default;
create index if not exists idx_users_region_id on public.ak_users using btree (region_id) tablespace pg_default;
create index if not exists idx_users_school_id on public.ak_users using btree (school_id) tablespace pg_default;
create index if not exists idx_users_grade_id on public.ak_users using btree (grade_id) tablespace pg_default;
create index if not exists idx_users_class_id on public.ak_users using btree (class_id) tablespace pg_default;
create trigger tr_create_user_message_preferences
after insert on ak_users for each row
execute function create_default_message_preferences ();
create table
public.member_user (
id bigserial,
nickname character varying(30) null default ''::character varying,
name character varying(30) null,
sex smallint null,
birthday timestamp without time zone null,
area_id integer null,
mark character varying(255) null,
point integer null default 0,
avatar character varying(255) null default ''::character varying,
status smallint not null default '1'::smallint,
mobile character varying(11) null default ''''''::character varying,
password character varying(100) not null default ''::character varying,
register_ip character varying(32) null default ''''''::character varying,
login_ip character varying(50) null default ''::character varying,
login_date timestamp without time zone null,
tag_ids character varying(255) null,
level_id bigint null,
experience bigint null,
group_id bigint null,
creator character varying(64) null default ''::character varying,
create_time timestamp without time zone not null default current_timestamp,
updater character varying(64) null default ''::character varying,
update_time timestamp without time zone not null default current_timestamp,
deleted boolean not null default false,
tenant_id bigint not null default 0,
user_id uuid not null,
cardno character varying null,
certificationnumber character varying null,
dept_ids bigint[] null,
role_ids bigint[] null,
avatar_file jsonb null,
constraint member_user_pkey1 primary key (user_id),
constraint member_user_id_key unique (id),
constraint unique_user_id unique (user_id),
constraint member_user_user_id_fkey foreign key (user_id) references users (id)
) tablespace pg_default;
create table
public.system_dept (
id bigint generated by default as identity,
name character varying(30) not null default ''::character varying,
parent_id bigint not null default 0,
sort integer not null default 0,
leader_user_id bigint null,
phone character varying(11) null default null::character varying,
email character varying(50) null default null::character varying,
status smallint not null,
creator character varying(64) null default ''::character varying,
create_time timestamp without time zone not null default current_timestamp,
updater character varying(64) null default ''::character varying,
update_time timestamp without time zone not null default current_timestamp,
deleted smallint not null default 0,
tenant_id bigint not null default 0,
name_alias character varying null,
constraint pk_system_dept primary key (id)
) tablespace pg_default;

13
doc_ble/issues.md Normal file
View File

@@ -0,0 +1,13 @@
1.heartbeat 在蓝牙方没有收到。
2.心跳测试基本只维持1分钟。而且界面混乱。会有不明黑色矩形。
3.测试时候界面滑动经常不能正常,也就是结束有困难。
4.spo2这个测试没有数据上传到蓝牙。
5.计步读取不成功,(可能是跟文档有差别)
6.蓝牙关于录音和信息的读取没有方法(需补充文档)
7.偶尔还会死机。。
8.没有主动从蓝牙控制的方法(需补充文档)
9.开始定时检测以后如果1分钟之内没有检测到佩戴状况需要及时中止
10.在心率大于170或者可配置的指标后要执行振动操作如果持续需要1分钟后继续振动操作振动
11.时间读取不成功。
12.测量心率过程中在notify已结束情况下依然绿灯闪烁不会停止中断蓝牙连接也不会停止。

View File

@@ -0,0 +1,150 @@
# 基于 EB21-E 的星闪 SLE 硬件连接与固件初始化最小示例
> 目标:给硬件/固件同学一个可以直接落地的 EB21-E 使用备忘录,用于快速评估和原型验证。
## 1. 模组定位与典型应用
- **模组类型**EB21-E利尔达基于海思 Hi2825 SLE 低功耗星闪 SoC。
- **接口特点**UART/SPI/I2C/GPIO多数场景推荐 **UART 控制 + 外接天线**
- **典型应用**
- 低功耗远距离传感器(心率带、环境监测等);
- 手环/表带与网关之间的近距离/中距离高速链路;
- BLE → 星闪协议迁移过渡方案(利用类似 GATT 的上层抽象)。
## 2. 硬件连接最小原理图说明
以下以 **MCU 使用 UART 控制 EB21-E** 为例:
### 2.1 供电与地
- `VCC_3V3` → EB21-E `VCC` 引脚3.0V3.6V,推荐 3.3V)。
- `GND` → EB21-E `GND` 引脚(至少两点星形接地,靠近模组的地大面积敷铜)。
- 在 EB21-E `VCC` 旁边就近放置:
- 100nF 贴片电容0402/0603
- 4.7µF10µF 钽电容或陶瓷电容
### 2.2 UART 通信
- MCU `TX` → EB21-E `RX`(如 `UART0_RX`)。
- MCU `RX` → EB21-E `TX`(如 `UART0_TX`)。
- 波特率:
- 推荐从 **115200 8N1** 起步,后续可协商更高波特率。
- 注意:
- 若 MCU 为 5V IO需加 **电平转换器**(如 TXS0108E或分压电阻。
- 线长尽量 < 20cm注意地参考一致。
### 2.3 复位与启动控制
- `EB21_RST`接MCU GPIO低电平保持复位高电平正常工作。
- 上电后延时几毫秒再释放 RST。
- 如模组有 `BOOT` / `MODE` 管脚:
- 默认通过上拉/下拉电阻设置为 **正常运行模式**
- 仅在升级固件或调试时切为 Boot 模式。
### 2.4 外接天线E 版的关键)
- `ANT`RF 口 → IPEX 连接器 → 高频同轴线 → 外部天线2.4GHz)。
- PCB 布线:
- `ANT` 到 IPEX 尽量短直,**50Ω 微带线**
- 下方禁止铺地/信号(或按参考设计做阻抗控制)。
- 天线选型:
- 若追求极致远距离:选 **2.4GHz 高增益定向天线(如 1224dBi 八木/栅格)**
## 3. 固件初始化最小流程MCU 侧)
以下示例为伪代码/结构化步骤,可根据具体 MCU 平台改写为 C/C++/Rust 等实现。
### 3.1 上电与 UART 初始化
```c
void eb21_hw_init(void) {
// 1. 供电已由电源管理完成,此处只负责 IO 初始化
// 2. 配置 UART
uart_init(EB21_UART_PORT, 115200, UART_DATABITS_8, UART_STOPBITS_1, UART_PARITY_NONE);
// 3. 配置 RST 引脚
gpio_set_mode(EB21_RST_PIN, GPIO_MODE_OUTPUT);
gpio_write(EB21_RST_PIN, 0); // 先保持复位
delay_ms(10);
gpio_write(EB21_RST_PIN, 1); // 释放复位
// 4. 等待模组自检完成
delay_ms(100); // 视实际文档可调
}
```
### 3.2 与 EB21-E 的简单 AT/协议握手
很多厂商提供两种固件形态:
- AT 命令固件UART 上下发 ASCII 命令)。
- 自定义二进制协议固件(类似本项目中蓝牙协议的 CMD/SEQ/CRC 格式)。
假设 EB21-E 提供 AT 命令风格接口(示例):
```c
void eb21_send_cmd(const char *cmd) {
uart_write(EB21_UART_PORT, (const uint8_t *)cmd, strlen(cmd));
uart_write(EB21_UART_PORT, (const uint8_t *)"\r\n", 2);
}
bool eb21_wait_ok(uint32_t timeout_ms) {
char buf[64] = {0};
size_t len = uart_read_line(EB21_UART_PORT, buf, sizeof(buf), timeout_ms);
if (len == 0) return false;
return strstr(buf, "OK") != NULL;
}
bool eb21_basic_handshake(void) {
eb21_send_cmd("AT"); // 心跳
if (!eb21_wait_ok(100)) return false;
eb21_send_cmd("AT+VER?"); // 查询版本
if (!eb21_wait_ok(100)) return false;
// 其他必要的初始化命令,如设置角色/信道/功率
// eb21_send_cmd("AT+ROLE=PERIPHERAL");
// eb21_send_cmd("AT+POWER=MAX");
return true;
}
```
如果厂商提供 SLE 自定义协议栈,则可以将其看作“星闪版 GATT”
1. 先发“PING”/“HELLO”命令确认链路正常
2. 然后配置本端角色(主/从)、频道、配对参数;
3. 建链后以 TLV/帧格式收发业务数据。
## 4. 与现有 BLE 协议文档的映射思路
你当前的 `doc_ble/蓝牙协议.md` 已经定义了:
- 服务/特征 UUID
- CMD 分段(控制/健康数据/紧急事件等);
- 统一数据包结构 (STX/LEN/CMD/SEQ/DATA/CRC)。
迁移到 EB21-E / 星闪 SLE 时,可以:
1. **上层 CMD 不变**
- 继续使用现有 CMD_xxx 定义和数据结构(如心率包、血氧包)。
2. **底层链路从 BLE GATT → SLE 链路**
- 将原本通过 GATT Notification/Write 的数据,改为通过 EB21-E 的“透传通道”发送;
- 在 MCU 上维护同样的打包/解包逻辑。
3. **安全与加密**
- 若 EB21-E 内置加密/配对机制,可视作“链路加密”;
- 应用层仍可复用 AES/SM4 等加密封装敏感字段。
## 5. 调试建议
- 使用 USB-UART 转串口工具直接与 EB21-E 对话,先确认:
- 上电是否有启动 log
- AT 命令是否响应;
- 在射频侧:
- 初期可用小 PCB 天线进行近距离联调;
- 功能 OK 后再换成高增益天线进行远距离验证。
---
如后续你确定具体 EB21-E 的数据手册/AT 指令集,我可以在本文件中继续补充:
- 完整 AT 命令表;
- 一个“星闪版 PING/心跳协议”的二进制帧格式示例;
- 与现有蓝牙协议命令一一对应的映射表。

View File

@@ -0,0 +1,94 @@
-- =====================================================
-- 模拟传感器数据生成脚本
-- 为单个用户和设备生成高体量生命体征数据
-- 用户ID: eed3824b-bba1-4309-8048-19d17367c084
-- 设备ID: 12345678-1234-5678-9abc-123456789012
-- 按分钟级别生成过去7天内的数据
-- =====================================================
DO $$
DECLARE
v_user_id UUID := 'eed3824b-bba1-4309-8048-19d17367c084';
v_device_id UUID := '12345678-1234-5678-9abc-123456789012';
BEGIN
-- 已直接初始化用户ID和设备ID
-- 步数数据 (每日1440条共 7 天)
INSERT INTO public.ss_sensor_measurements (id, device_id, user_id, measurement_type, measured_at, unit, raw_data, created_at)
SELECT
uuid_generate_v4(), v_device_id, v_user_id, 'steps', ts, 'count', jsonb_build_object('count', (floor(random()*2000 + 1000))::int), now()
FROM generate_series(now() - interval '7 days', now(), '1 minute') AS ts;
INSERT INTO public.ss_steps (measurement_id, step_count, created_at)
SELECT id, (raw_data->> 'count')::bigint, created_at
FROM public.ss_sensor_measurements
WHERE measurement_type = 'steps'
AND measured_at >= now() - interval '7 days';
-- 心率数据
INSERT INTO public.ss_sensor_measurements (id, device_id, user_id, measurement_type, measured_at, unit, raw_data, created_at)
SELECT
uuid_generate_v4(), v_device_id, v_user_id, 'heart_rate', ts, 'bpm', jsonb_build_object('bpm', (floor(random()*40 + 60))::int), now()
FROM generate_series(now() - interval '7 days', now(), '1 minute') AS ts;
INSERT INTO public.ss_heart_rate (measurement_id, heart_rate_bpm, created_at)
SELECT id, (raw_data->> 'bpm')::int, created_at
FROM public.ss_sensor_measurements
WHERE measurement_type = 'heart_rate'
AND measured_at >= now() - interval '7 days';
-- 血氧 (SpO2)
INSERT INTO public.ss_sensor_measurements (id, device_id, user_id, measurement_type, measured_at, unit, raw_data, created_at)
SELECT
uuid_generate_v4(), v_device_id, v_user_id, 'spo2', ts, '%', jsonb_build_object('spo2', (floor(random()*5 + 92))::int), now()
FROM generate_series(now() - interval '7 days', now(), '5 minutes') AS ts;
INSERT INTO public.ss_spo2 (measurement_id, spo2_percent, created_at)
SELECT id, (raw_data->> 'spo2')::int, created_at
FROM public.ss_sensor_measurements
WHERE measurement_type = 'spo2'
AND measured_at >= now() - interval '7 days';
-- 血压
INSERT INTO public.ss_sensor_measurements (id, device_id, user_id, measurement_type, measured_at, unit, raw_data, created_at)
SELECT
uuid_generate_v4(), v_device_id, v_user_id, 'bp', ts, 'mmHg',
jsonb_build_object('systolic', (floor(random()*20 + 110))::int,
'diastolic', (floor(random()*10 + 70))::int), now()
FROM generate_series(now() - interval '7 days', now(), '1 hour') AS ts;
INSERT INTO public.ss_blood_pressure (measurement_id, systolic, diastolic, created_at)
SELECT id,
(raw_data->> 'systolic')::int,
(raw_data->> 'diastolic')::int,
created_at
FROM public.ss_sensor_measurements
WHERE measurement_type = 'bp'
AND measured_at >= now() - interval '7 days';
-- 体温
INSERT INTO public.ss_sensor_measurements (id, device_id, user_id, measurement_type, measured_at, unit, raw_data, created_at)
SELECT
uuid_generate_v4(), v_device_id, v_user_id, 'temp', ts, 'C', jsonb_build_object('temp', (random()*0.5 + 36.5)::numeric), now()
FROM generate_series(now() - interval '7 days', now(), '30 minutes') AS ts;
INSERT INTO public.ss_temperature (measurement_id, temperature_c, created_at)
SELECT id, (raw_data->> 'temp')::float, created_at
FROM public.ss_sensor_measurements
WHERE measurement_type = 'temp'
AND measured_at >= now() - interval '7 days';
-- 步幅
INSERT INTO public.ss_sensor_measurements (id, device_id, user_id, measurement_type, measured_at, unit, raw_data, created_at)
SELECT
uuid_generate_v4(), v_device_id, v_user_id, 'stride', ts, 'cm', jsonb_build_object('stride', (random()*30 + 50)::numeric), now()
FROM generate_series(now() - interval '7 days', now(), '5 minutes') AS ts;
INSERT INTO public.ss_stride_length (measurement_id, stride_cm, created_at)
SELECT id, (raw_data->> 'stride')::float, created_at
FROM public.ss_sensor_measurements
WHERE measurement_type = 'stride'
AND measured_at >= now() - interval '7 days';
RAISE NOTICE '✔️ 模拟数据生成完成';
END $$;

View File

@@ -0,0 +1,328 @@
-- =====================================================
-- 运动传感设备时序数据表设计PostgreSQL/TimescaleDB
-- 表名前缀均为 ss_
-- 适用于高吞吐量、高并发的生命体征与位置数据存储
-- =====================================================
-- 1. 扩展与准备
-- -------------------------------------
-- 需要 uuid-ossp 与 timescaledb若使用时序库
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS timescaledb; -- 启用 TimescaleDB 扩展
-- Enable PostGIS extension for spatial data
CREATE EXTENSION IF NOT EXISTS postgis;
-- 2. 核心设备关联表
-- -------------------------------------
-- 设备管理表引用 ak_devices 表
-- 传感器测量数据均关联到已有设备管理
-- 3. 基础时序数据表:通用测量记录
-- -------------------------------------
CREATE TABLE IF NOT EXISTS public.ss_sensor_measurements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
device_id UUID NOT NULL REFERENCES public.ak_devices(id) ON DELETE CASCADE,
user_id UUID REFERENCES public.ak_users(id) ON DELETE SET NULL,
measurement_type TEXT NOT NULL, -- 如 steps, heart_rate, spo2, stride, bp, temp, location, ecg
measured_at TIMESTAMPTZ NOT NULL,
unit TEXT, -- 单位,如 count, bpm, %, cm, mmHg, ℃, geojson
raw_data JSONB, -- 原始数据或扩展字段
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 高并发场景下用 TimescaleDB 创建 hypertable
-- SELECT create_hypertable('public.ss_sensor_measurements', 'measured_at', chunk_time_interval => interval '1 day');
CREATE INDEX ON public.ss_sensor_measurements(device_id, measured_at DESC);
CREATE INDEX ON public.ss_sensor_measurements(measurement_type, measured_at DESC);
-- 4. 分专题数据表:性能优化(可选)
-- -------------------------------------
-- 对于最常见的生命体征,可划分专项表,以提高查询效率
-- 步数
CREATE TABLE IF NOT EXISTS public.ss_steps (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
step_count BIGINT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_steps(step_count);
-- 心率
CREATE TABLE IF NOT EXISTS public.ss_heart_rate (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
heart_rate_bpm INT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_heart_rate(heart_rate_bpm);
-- 血氧 (SpO2)
CREATE TABLE IF NOT EXISTS public.ss_spo2 (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
spo2_percent INT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_spo2(spo2_percent);
-- 血压
CREATE TABLE IF NOT EXISTS public.ss_blood_pressure (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
systolic INT NOT NULL,
diastolic INT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_blood_pressure(systolic, diastolic);
-- 体温
CREATE TABLE IF NOT EXISTS public.ss_temperature (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
temperature_c FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_temperature(temperature_c);
-- 步幅
CREATE TABLE IF NOT EXISTS public.ss_stride_length (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
stride_cm FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_stride_length(stride_cm);
-- 位置GeoJSON使用经纬度替代 PostGIS 类型)
CREATE TABLE IF NOT EXISTS public.ss_location (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
latitude DOUBLE PRECISION NOT NULL, -- 纬度
longitude DOUBLE PRECISION NOT NULL, -- 经度
altitude FLOAT,
speed FLOAT,
heading FLOAT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_location(latitude, longitude);
-- 心电图 (ECG) 波形数据
-- 分两表:测量元信息 + 样本点
CREATE TABLE IF NOT EXISTS public.ss_ecg_measurements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
duration_sec FLOAT NOT NULL,
sample_rate_hz FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.ss_ecg_samples (
ecg_id UUID NOT NULL REFERENCES public.ss_ecg_measurements(id) ON DELETE CASCADE,
sample_index INT NOT NULL,
voltage_mv FLOAT NOT NULL,
PRIMARY KEY(ecg_id, sample_index)
);
CREATE INDEX ON public.ss_ecg_samples(sample_index);
-- 呼吸率
CREATE TABLE IF NOT EXISTS public.ss_respiratory_rate (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
respiratory_rate INT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_respiratory_rate(respiratory_rate);
-- 潮气量
CREATE TABLE IF NOT EXISTS public.ss_tidal_volume (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
tidal_volume_ml FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_tidal_volume(tidal_volume_ml);
-- 呼吸音
CREATE TABLE IF NOT EXISTS public.ss_respiratory_sounds (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
audio_data BYTEA NOT NULL, -- 原始音频
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 心率变异性
CREATE TABLE IF NOT EXISTS public.ss_hrv (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
hrv_rmssd FLOAT,
hrv_sdnn FLOAT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_hrv(hrv_rmssd);
CREATE INDEX ON public.ss_hrv(hrv_sdnn);
-- 血糖
CREATE TABLE IF NOT EXISTS public.ss_glucose (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
glucose_mg_dl FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_glucose(glucose_mg_dl);
-- 皮肤电反应 (GSR)
CREATE TABLE IF NOT EXISTS public.ss_gsr (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
gsr_us FLOAT NOT NULL, -- 微西门子
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_gsr(gsr_us);
-- 皮肤温度
CREATE TABLE IF NOT EXISTS public.ss_skin_temperature (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
skin_temp_c FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_skin_temperature(skin_temp_c);
-- 卡路里消耗
CREATE TABLE IF NOT EXISTS public.ss_energy_expenditure (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
calories_kcal FLOAT NOT NULL,
met FLOAT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_energy_expenditure(calories_kcal);
-- VO2 / VO2max
CREATE TABLE IF NOT EXISTS public.ss_vo2 (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
vo2_ml_per_min FLOAT,
vo2max_ml_per_min FLOAT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_vo2(vo2_ml_per_min);
CREATE INDEX ON public.ss_vo2(vo2max_ml_per_min);
-- 睡眠指标
CREATE TABLE IF NOT EXISTS public.ss_sleep_metrics (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
sleep_stage VARCHAR(32) NOT NULL, -- awake, light, deep, rem
duration_sec INT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_sleep_metrics(sleep_stage);
-- 跌倒事件
CREATE TABLE IF NOT EXISTS public.ss_fall_events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
fall_detected BOOLEAN NOT NULL,
event_time TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_fall_events(fall_detected);
-- 姿态数据
CREATE TABLE IF NOT EXISTS public.ss_posture (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
posture VARCHAR(32) NOT NULL, -- standing, sitting, lying, walking
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_posture(posture);
-- 肌电 (EMG)
CREATE TABLE IF NOT EXISTS public.ss_emg_measurements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
duration_sec FLOAT NOT NULL,
sample_rate_hz FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.ss_emg_samples (
emg_id UUID NOT NULL REFERENCES public.ss_emg_measurements(id) ON DELETE CASCADE,
sample_index INT NOT NULL,
voltage_mv FLOAT NOT NULL,
PRIMARY KEY(emg_id, sample_index)
);
CREATE INDEX ON public.ss_emg_samples(sample_index);
-- 脑电 (EEG)
CREATE TABLE IF NOT EXISTS public.ss_eeg_measurements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
duration_sec FLOAT NOT NULL,
sample_rate_hz FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.ss_eeg_samples (
eeg_id UUID NOT NULL REFERENCES public.ss_eeg_measurements(id) ON DELETE CASCADE,
sample_index INT NOT NULL,
voltage_uv FLOAT NOT NULL,
PRIMARY KEY(eeg_id, sample_index)
);
CREATE INDEX ON public.ss_eeg_samples(sample_index);
-- 血乳酸
CREATE TABLE IF NOT EXISTS public.ss_lactate (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
lactate_mmol_l FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON public.ss_lactate(lactate_mmol_l);
-- PPG 波形
CREATE TABLE IF NOT EXISTS public.ss_ppg_measurements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
measurement_id UUID NOT NULL REFERENCES public.ss_sensor_measurements(id) ON DELETE CASCADE,
duration_sec FLOAT NOT NULL,
sample_rate_hz FLOAT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.ss_ppg_samples (
ppg_id UUID NOT NULL REFERENCES public.ss_ppg_measurements(id) ON DELETE CASCADE,
sample_index INT NOT NULL,
amplitude FLOAT NOT NULL,
PRIMARY KEY(ppg_id, sample_index)
);
CREATE INDEX ON public.ss_ppg_samples(sample_index);
-- 5. 数据保留与归档(示例)
-- -------------------------------------
-- 定期归档或删除旧数据,可使用 TimescaleDB retention policy
-- SELECT add_retention_policy('public.ss_sensor_measurements', INTERVAL '90 days');
-- 6. 视图和物化视图示例
-- -------------------------------------
-- 最近 1 小时心率聚合
CREATE MATERIALIZED VIEW public.ss_hr_last_hour_summary AS
SELECT device_id,
minute_bucket,
avg(heart_rate_bpm) AS avg_bpm,
min(heart_rate_bpm) AS min_bpm,
max(heart_rate_bpm) AS max_bpm
FROM (
SELECT date_trunc('minute', sm.measured_at) AS minute_bucket,
hr.heart_rate_bpm,
sm.device_id
FROM public.ss_sensor_measurements sm
JOIN public.ss_heart_rate hr ON hr.measurement_id = sm.id
WHERE sm.measured_at > now() - INTERVAL '1 hour'
) sub
GROUP BY device_id, minute_bucket;
-- =====================================================
-- 使用说明:
-- • 通用写入:将任意指标写入 ss_sensor_measurements随后写入专项表
-- • 查询优化:针对常用指标查询专项表
-- • 时序特性:开启 TimescaleDB hypertable 以提高写入与查询性能
-- =====================================================

783
doc_ble/蓝牙协议.md Normal file
View File

@@ -0,0 +1,783 @@
登录/注册 关于ShowDoc
蓝牙协议
运动手环蓝牙通信协议设计文档
一、协议概述
1.1 协议简介
协议名称Wearable Band Bluetooth Protocol (WBBP)
协议版本v1.0
通信方式:蓝牙低功耗 (BLE 4.0+)
传输层GATT (Generic Attribute Profile)
应用场景:手环与智能手机之间的数据交换
1.2 设计原则
低功耗:优化数据包大小,减少传输频率
可靠性:包含确认机制和重传机制
扩展性:支持功能模块化扩展
安全性:数据加密和身份验证
二、BLE服务架构
2.1 主要服务定义
2.1.1 设备信息服务 (Device Information Service)
UUID: 180A
特征值:
制造商名称: 2A29
型号: 2A24
序列号: 2A25
固件版本: 2A26
硬件版本: 2A27
2.1.2 电池服务 (Battery Service)
UUID: 180F
特征值:
电池电量: 2A19 (可读,可通知)
2.1.3 自定义主服务 (Primary Custom Service)
UUID: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
特征值:
数据传输 (TX): 6E400002-B5A3-F393-E0A9-E50E24DCCA9E (可写,无响应)
数据接收 (RX): 6E400003-B5A3-F393-E0A9-E50E24DCCA9E (可读,可通知)
控制命令: 6E400004-B5A3-F393-E0A9-E50E24DCCA9E (可写,需响应)
2.1.4 健康数据服务 (Health Data Service)
UUID: 6E400010-B5A3-F393-E0A9-E50E24DCCA9E
特征值:
心率数据: 6E400011-B5A3-F393-E0A9-E50E24DCCA9E (可读,可通知)
运动数据: 6E400012-B5A3-F393-E0A9-E50E24DCCA9E (可读,可通知)
睡眠数据: 6E400013-B5A3-F393-E0A9-E50E24DCCA9E (可读,可通知)
2.1.5 紧急服务 (Emergency Service)
UUID: 6E400020-B5A3-F393-E0A9-E50E24DCCA9E
特征值:
紧急报警: 6E400021-B5A3-F393-E0A9-E50E24DCCA9E (可写,可通知)
录音数据: 6E400022-B5A3-F393-E0A9-E50E24DCCA9E (可写,可通知)
三、数据包格式
3.1 基础数据包结构
+--------+--------+--------+--------+--------+--------+--------+--------+
| STX | LEN | CMD | SEQ | DATA (0-16 bytes) | CRC |
+--------+--------+--------+--------+--------+--------+--------+--------+
| 1B | 1B | 1B | 1B | Variable | 1B |
+--------+--------+--------+--------+--------+--------+--------+--------+
字段说明:
STX (Start of Text): 起始标志 0xAA
LEN: 数据包长度 (不含STX和CRC)
CMD: 命令类型
SEQ: 序列号 (0-255用于确认和重传)
DATA: 数据负载 (最大16字节适配BLE MTU)
CRC: 校验和 (XOR校验)
3.2 命令类型定义
// 基础控制命令 (0x00-0x0F)
#define CMD_PING 0x00 // 心跳/连接测试
#define CMD_DEVICE_INFO 0x01 // 设备信息查询
#define CMD_TIME_SYNC 0x02 // 时间同步
#define CMD_CONFIG_SET 0x03 // 配置设置
#define CMD_CONFIG_GET 0x04 // 配置查询
#define CMD_FIRMWARE_UPDATE 0x05 // 固件更新
#define CMD_RESET 0x06 // 设备重置
#define CMD_ACK 0x0F // 确认应答
// 健康数据命令 (0x10-0x2F)
#define CMD_HEART_RATE 0x10 // 心率数据
#define CMD_STEP_COUNT 0x11 // 步数数据
#define CMD_SLEEP_DATA 0x12 // 睡眠数据
#define CMD_SPORT_MODE 0x13 // 运动模式
#define CMD_BLOOD_OXYGEN 0x14 // 血氧数据
#define CMD_BODY_TEMP 0x15 // 体温数据
#define CMD_STRESS_LEVEL 0x16 // 压力水平
#define CMD_CALORIES 0x17 // 卡路里消耗
#define CMD_VITAL_SIGNS 0x18 // 生命体征组合数据
#define CMD_REAL_TIME_START 0x19 // 开始实时监测
#define CMD_REAL_TIME_STOP 0x1A // 停止实时监测
#define CMD_MEASUREMENT_CONFIG 0x1B // 测量配置
// 交互功能命令 (0x30-0x4F)
#define CMD_NOTIFICATION 0x30 // 通知推送
#define CMD_CALL_INCOMING 0x31 // 来电通知
#define CMD_MESSAGE 0x32 // 消息通知
#define CMD_ALARM 0x33 // 闹钟设置
#define CMD_FIND_DEVICE 0x34 // 查找设备
#define CMD_CAMERA_CONTROL 0x35 // 相机控制
#define CMD_MUSIC_CONTROL 0x36 // 音乐控制
// 紧急功能命令 (0x50-0x6F)
#define CMD_EMERGENCY_ALERT 0x50 // 紧急报警
#define CMD_VOICE_RECORD 0x51 // 录音数据
#define CMD_LOCATION_REQUEST 0x52 // 位置请求
#define CMD_SOS_STATUS 0x53 // SOS状态
// 系统配置命令 (0x70-0x8F)
#define CMD_DISPLAY_CONFIG 0x70 // 显示配置
#define CMD_VIBRATION_CONFIG 0x71 // 震动配置
#define CMD_LANGUAGE_SET 0x72 // 语言设置
#define CMD_WATCHFACE_SET 0x73 // 表盘设置
#define CMD_USER_PROFILE 0x74 // 用户资料
// 错误码 (0xF0-0xFF)
#define CMD_ERROR 0xF0 // 错误响应
#define CMD_UNSUPPORTED 0xF1 // 不支持的命令
#define CMD_INVALID_PARAM 0xF2 // 无效参数
#define CMD_TIMEOUT 0xF3 // 超时
四、具体协议实现
4.1 连接建立流程
手机端 手环端
| |
|------- 扫描设备 -------> |
| |
|<------ 广播响应 -------- |
| |
|------- 连接请求 -------> |
| |
|<------ 连接确认 -------- |
| |
|------- PING (CMD_PING) ---> |
| |
|<------ ACK (CMD_ACK) --- |
| |
|------- 时间同步 -------> |
| |
|<------ 同步确认 -------- |
4.2 心跳保活机制
// 心跳数据包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x04
uint8_t cmd; // CMD_PING (0x00)
uint8_t seq; // 序列号
uint8_t reserved; // 保留字节
uint8_t crc; // 校验和
} ping_packet_t;
// 心跳响应包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x05
uint8_t cmd; // CMD_ACK (0x0F)
uint8_t seq; // 序列号
uint8_t status; // 设备状态
uint8_t battery; // 电池电量 (0-100)
uint8_t crc; // 校验和
} ping_ack_packet_t;
4.3 健康数据传输
4.3.1 心率数据
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x08
uint8_t cmd; // CMD_HEART_RATE (0x10)
uint8_t seq; // 序列号
uint32_t timestamp; // 时间戳 (Unix时间)
uint8_t heart_rate; // 心率值 (bpm)
uint8_t quality; // 信号质量 (0-100)
uint8_t crc; // 校验和
} heart_rate_packet_t;
Hex样例:
AA 08 10 01 66 B2 F4 A0 4B 55 E2
解析:
AA: STX起始标志
08: 包长度(8字节)
10: 心率命令
01: 序列号1
66 B2 F4 A0: 时间戳(1723456672, 2025-07-21 12:00:00)
4B: 心率75 bpm
55: 信号质量85%
E2: CRC校验和
4.3.2 血氧数据
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0B
uint8_t cmd; // CMD_BLOOD_OXYGEN (0x14)
uint8_t seq; // 序列号
uint32_t timestamp; // 时间戳 (Unix时间)
uint8_t spo2_value; // 血氧饱和度 (%) 范围:85-100
uint8_t quality; // 信号质量 (0-100)
uint8_t pulse_rate; // 脉率 (bpm) 基于血氧测量
uint8_t perfusion_index; // 灌注指数 (0-20) PI值
uint8_t measurement_status; // 测量状态 (0:正常 1:低质量 2:无信号 3:运动干扰)
uint8_t crc; // 校验和
} blood_oxygen_packet_t;
Hex样例:
AA 0B 14 02 66 B2 F4 A0 62 5A 4F 0C 00 1D
解析:
AA: STX起始标志
0B: 包长度(11字节)
14: 血氧命令
02: 序列号2
66 B2 F4 A0: 时间戳(1723456672)
62: 血氧98%
5A: 信号质量90%
4F: 脉率79 bpm
0C: 灌注指数12
00: 测量状态正常
1D: CRC校验和
4.3.3 实时生命体征组合数据
// 心率+血氧组合实时数据 (节省传输带宽)
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0E
uint8_t cmd; // CMD_VITAL_SIGNS (0x18) - 新增命令
uint8_t seq; // 序列号
uint32_t timestamp; // 时间戳
uint8_t heart_rate; // 心率值 (bpm)
uint8_t hr_quality; // 心率信号质量 (0-100)
uint8_t spo2_value; // 血氧饱和度 (%)
uint8_t spo2_quality; // 血氧信号质量 (0-100)
uint8_t rr_interval; // RR间期 (ms/10)
uint8_t perfusion_index; // 灌注指数
uint8_t activity_level; // 活动水平 (0-4)
uint8_t measurement_mode; // 测量模式 (0:自动 1:手动 2:连续 3:运动模式)
uint8_t crc; // 校验和
} vital_signs_packet_t;
Hex样例:
AA 0E 18 03 66 B2 F4 A0 4B 55 62 5A 50 0C 02 01 73
解析:
AA: STX起始标志
0E: 包长度(14字节)
18: 生命体征组合命令
03: 序列号3
66 B2 F4 A0: 时间戳(1723456672)
4B: 心率75 bpm
55: 心率信号质量85%
62: 血氧98%
5A: 血氧信号质量90%
50: RR间期80(800ms)
0C: 灌注指数12
02: 活动水平2(中等活动)
01: 测量模式1(手动)
73: CRC校验和
4.3.4 运动数据
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x10
uint8_t cmd; // CMD_STEP_COUNT (0x11)
uint8_t seq; // 序列号
uint32_t timestamp; // 时间戳
uint32_t steps; // 步数
uint16_t distance; // 距离 (米)
uint16_t calories; // 卡路里
uint8_t activity_type; // 活动类型 (0:静坐 1:走路 2:跑步 3:骑行)
uint8_t crc; // 校验和
} sport_data_packet_t;
运动步数Hex样例:
AA 10 11 05 66 B2 F4 A0 00 00 27 10 0C E4 01 C2 02 8F
解析:
AA: STX起始标志
10: 包长度(16字节)
11: 步数命令(CMD_STEP_COUNT)
05: 序列号5
66 B2 F4 A0: 时间戳(1723456672, 2025-07-21 12:00:00)
00 00 27 10: 步数10000步
0C E4: 距离3300米(3.3公里)
01 C2: 卡路里450卡
02: 活动类型2(跑步)
8F: CRC校验和
4.4 实时测试协议详解
4.4.1 实时监测启动协议
// 实时监测配置包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0A
uint8_t cmd; // CMD_REAL_TIME_START (0x19)
uint8_t seq; // 序列号
uint8_t monitor_type; // 监测类型位掩码 (bit0:心率 bit1:血氧 bit2:体温 bit3:运动)
uint16_t interval_ms; // 数据上报间隔 (毫秒) 建议:1000-5000ms
uint8_t duration_min; // 监测持续时间 (分钟) 0=无限制
uint8_t quality_threshold; // 信号质量阈值 (0-100) 低于此值不上报
uint8_t auto_stop_condition; // 自动停止条件 (0:手动停止 1:低电量 2:信号差 3:超时)
uint8_t notification_level; // 通知级别 (0:静默 1:普通 2:重要)
uint8_t reserved; // 保留字节
uint8_t crc; // 校验和
} realtime_config_packet_t;
// 实时监测响应包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x06
uint8_t cmd; // CMD_ACK (0x0F)
uint8_t seq; // 序列号
uint8_t result; // 结果 (0:成功 1:失败 2:不支持 3:电量不足)
uint16_t session_id; // 会话ID (用于标识本次监测)
uint8_t estimated_battery_min; // 预估电池可用时间 (分钟)
uint8_t crc; // 校验和
} realtime_start_ack_t;
4.4.2 心率实时监测流程
// 心率实时数据增强版
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0F
uint8_t cmd; // CMD_HEART_RATE (0x10)
uint8_t seq; // 序列号
uint16_t session_id; // 会话ID
uint32_t timestamp; // 时间戳
uint8_t heart_rate; // 心率值 (bpm)
uint8_t quality; // 信号质量 (0-100)
uint8_t rr_interval; // RR间期 (ms/10)
uint8_t hrv_score; // 心率变异性评分 (0-100)
uint8_t stress_level; // 压力等级 (0-4: 放松到高压力)
uint8_t confidence; // 测量置信度 (0-100)
uint8_t sensor_contact; // 传感器接触状态 (0:未接触 1:接触良好 2:接触不良)
uint8_t crc; // 校验和
} realtime_heart_rate_t;
// 心率测试状态枚举
typedef enum {
HR_STATUS_IDLE = 0, // 空闲
HR_STATUS_DETECTING = 1, // 检测中
HR_STATUS_STABLE = 2, // 稳定测量
HR_STATUS_UNSTABLE = 3, // 信号不稳定
HR_STATUS_ERROR = 4, // 测量错误
HR_STATUS_TIMEOUT = 5, // 测量超时
} heart_rate_status_t;
4.4.3 血氧实时监测流程
// 血氧实时数据增强版
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x12
uint8_t cmd; // CMD_BLOOD_OXYGEN (0x14)
uint8_t seq; // 序列号
uint16_t session_id; // 会话ID
uint32_t timestamp; // 时间戳
uint8_t spo2_value; // 血氧饱和度 (%) 范围:85-100
uint8_t quality; // 信号质量 (0-100)
uint8_t pulse_rate; // 脉率 (bpm)
uint8_t perfusion_index; // 灌注指数 (0-20)
uint8_t red_signal_strength; // 红光信号强度 (0-100)
uint8_t ir_signal_strength; // 红外光信号强度 (0-100)
uint8_t motion_artifact; // 运动伪影指数 (0-100)
uint8_t ambient_light; // 环境光干扰 (0-100)
uint8_t skin_tone_factor; // 肤色补偿因子 (0-100)
uint8_t measurement_progress; // 测量进度 (0-100)
uint8_t reliability_score; // 可靠性评分 (0-100)
uint8_t crc; // 校验和
} realtime_spo2_t;
// 血氧测试状态枚举
typedef enum {
SPO2_STATUS_IDLE = 0, // 空闲
SPO2_STATUS_INIT = 1, // 初始化
SPO2_STATUS_STABILIZING = 2, // 稳定中
SPO2_STATUS_MEASURING = 3, // 测量中
SPO2_STATUS_COMPLETED = 4, // 测量完成
SPO2_STATUS_LOW_SIGNAL = 5, // 信号太弱
SPO2_STATUS_MOTION_DETECT = 6, // 检测到运动
SPO2_STATUS_AMBIENT_HIGH = 7, // 环境光过强
SPO2_STATUS_ERROR = 8, // 测量错误
} spo2_status_t;
4.4.4 测量控制命令
// 测量配置命令
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0C
uint8_t cmd; // CMD_MEASUREMENT_CONFIG (0x1B)
uint8_t seq; // 序列号
uint8_t sensor_type; // 传感器类型 (1:心率 2:血氧 3:组合)
uint8_t sampling_rate; // 采样率 (0:25Hz 1:50Hz 2:100Hz 3:200Hz)
uint8_t led_intensity; // LED强度 (0-100)
uint8_t filter_mode; // 滤波模式 (0:关闭 1:低通 2:带通 3:自适应)
uint8_t calibration_mode; // 校准模式 (0:出厂 1:用户 2:实时)
uint8_t power_mode; // 功耗模式 (0:高性能 1:平衡 2:省电)
uint8_t ambient_rejection; // 环境光抑制 (0:关闭 1:开启)
uint8_t motion_tolerance; // 运动容忍度 (0-4)
uint8_t auto_gain_control; // 自动增益控制 (0:关闭 1:开启)
uint8_t crc; // 校验和
} measurement_config_t;
// 实时监测停止命令
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x06
uint8_t cmd; // CMD_REAL_TIME_STOP (0x1A)
uint8_t seq; // 序列号
uint16_t session_id; // 会话ID
uint8_t stop_reason; // 停止原因 (0:用户 1:超时 2:电量 3:错误)
uint8_t save_data; // 是否保存数据 (0:不保存 1:保存)
uint8_t crc; // 校验和
} realtime_stop_t;
4.4.5 质量评估算法
// 信号质量评估结构
typedef struct {
uint8_t signal_strength; // 信号强度 (0-100)
uint8_t noise_level; // 噪声水平 (0-100)
uint8_t motion_artifact; // 运动伪影 (0-100)
uint8_t contact_quality; // 接触质量 (0-100)
uint8_t baseline_stability; // 基线稳定性 (0-100)
uint8_t overall_quality; // 综合质量 (0-100)
} signal_quality_t;
// 质量评估函数示例
uint8_t calculate_signal_quality(const sensor_data_t *data) {
uint8_t quality = 0;
// 信号强度权重 30%
quality += (data->signal_strength * 30) / 100;
// 噪声水平权重 25% (取反)
quality += ((100 - data->noise_level) * 25) / 100;
// 接触质量权重 25%
quality += (data->contact_quality * 25) / 100;
// 基线稳定性权重 20%
quality += (data->baseline_stability * 20) / 100;
return quality;
}
4.5 紧急报警协议
4.5.1 紧急报警
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0C
uint8_t cmd; // CMD_EMERGENCY_ALERT (0x50)
uint8_t seq; // 序列号
uint32_t timestamp; // 报警时间戳
uint8_t alert_type; // 报警类型 (1:SOS 2:跌倒 3:心率异常)
uint8_t severity; // 严重程度 (1-5)
uint16_t location_x; // GPS坐标X (可选)
uint16_t location_y; // GPS坐标Y (可选)
uint8_t user_id; // 用户ID
uint8_t crc; // 校验和
} emergency_alert_packet_t;
Hex样例:
AA 0C 50 FF 66 B2 F4 A0 01 05 0A 28 0B 58 7C F2
解析:
AA: STX起始标志
0C: 包长度(12字节)
50: 紧急报警命令
FF: 序列号255(紧急包)
66 B2 F4 A0: 报警时间戳(1723456672)
01: 报警类型1(SOS)
05: 严重程度5(最高)
0A 28: GPS坐标X(2600)
0B 58: GPS坐标Y(2904)
7C: 用户ID(124)
F2: CRC校验和
4.5.2 录音数据传输
// 录音开始包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x08
uint8_t cmd; // CMD_VOICE_RECORD (0x51)
uint8_t seq; // 序列号
uint8_t action; // 动作 (0:开始 1:数据 2:结束)
uint16_t total_length; // 总长度
uint8_t sample_rate; // 采样率 (0:8K 1:16K)
uint8_t format; // 格式 (0:PCM 1:ADPCM)
uint8_t crc; // 校验和
} voice_header_packet_t;
录音开始包Hex样例:
AA 08 51 01 00 0C 80 01 00 D4
解析:
AA: STX起始标志
08: 包长度(8字节)
51: 录音命令
01: 序列号1
00: 动作0(开始录音)
0C 80: 总长度3200字节
01: 采样率1(16K)
00: 格式0(PCM)
D4: CRC校验和
// 录音数据包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x14
uint8_t cmd; // CMD_VOICE_RECORD (0x51)
uint8_t seq; // 序列号
uint8_t action; // 动作 (1:数据)
uint16_t packet_index; // 包序号
uint8_t data[16]; // 音频数据
uint8_t crc; // 校验和
} voice_data_packet_t;
录音数据包Hex样例:
AA 14 51 02 01 00 01 F1 E2 D3 C4 B5 A6 97 88 79 6A 5B 4C 3D 2E 1F 08
解析:
AA: STX起始标志
14: 包长度(20字节)
51: 录音命令
02: 序列号2
01: 动作1(数据传输)
00 01: 包序号1
F1 E2 D3...2E 1F: 16字节音频数据
08: CRC校验和
uint8_t seq; // 序列号
uint8_t action; // 动作 (1:数据)
uint16_t packet_index; // 包序号
uint8_t data[16]; // 音频数据
uint8_t crc; // 校验和
} voice_data_packet_t;
```
4.6 通知推送协议
4.6.1 消息通知
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 可变长度
uint8_t cmd; // CMD_NOTIFICATION (0x30)
uint8_t seq; // 序列号
uint8_t msg_type; // 消息类型 (1:短信 2:微信 3:QQ 4:邮件 5:其他)
uint8_t msg_id; // 消息ID
uint8_t title_len; // 标题长度
uint8_t content_len; // 内容长度
uint8_t data[]; // 标题+内容 (UTF-8编码)
// uint8_t crc; // 校验和 (在data末尾)
} notification_packet_t;
4.6.2 来电通知
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 可变长度
uint8_t cmd; // CMD_CALL_INCOMING (0x31)
uint8_t seq; // 序列号
uint8_t call_action; // 动作 (0:来电 1:接听 2:挂断 3:拒接)
uint8_t name_len; // 姓名长度
uint8_t number_len; // 号码长度
uint8_t data[]; // 姓名+号码 (UTF-8编码)
// uint8_t crc; // 校验和
} call_packet_t;
五、错误处理机制
5.1 错误码定义
#define ERR_SUCCESS 0x00 // 成功
#define ERR_INVALID_CMD 0x01 // 无效命令
#define ERR_INVALID_PARAM 0x02 // 无效参数
#define ERR_CRC_ERROR 0x03 // 校验错误
#define ERR_TIMEOUT 0x04 // 超时
#define ERR_BUSY 0x05 // 设备忙
#define ERR_LOW_BATTERY 0x06 // 电量不足
#define ERR_NOT_SUPPORTED 0x07 // 不支持
#define ERR_PERMISSION_DENIED 0x08 // 权限拒绝
#define ERR_MEMORY_FULL 0x09 // 存储满
#define ERR_UNKNOWN 0xFF // 未知错误
5.2 错误响应格式
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x06
uint8_t cmd; // CMD_ERROR (0xF0)
uint8_t seq; // 原序列号
uint8_t error_cmd; // 出错的命令
uint8_t error_code; // 错误码
uint8_t reserved; // 保留
uint8_t crc; // 校验和
} error_packet_t;
六、安全机制
6.1 配对认证流程
手机端 手环端
| |
|------- 配对请求 -------> |
| |
|<------ 配对码显示 ------ |
| |
|------- 配对码确认 -----> |
| |
|<------ 密钥交换 -------- |
| |
|------- 认证完成 -------> |
6.2 数据加密
加密算法: AES-128
密钥管理: 配对时生成,定期更新
加密范围: 敏感数据 (健康数据、录音、位置等)
6.3 防重放攻击
使用递增序列号
时间戳验证
会话令牌机制
七、性能优化
7.1 数据压缩
健康数据采用差值压缩
录音数据采用ADPCM压缩
批量传输减少包头开销
7.2 功耗优化
连接间隔动态调整
数据缓存与批量发送
睡眠模式管理
7.3 MTU协商
// MTU协商包
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x05
uint8_t cmd; // CMD_CONFIG_SET (0x03)
uint8_t seq; // 序列号
uint8_t config_type; // 配置类型 (0x01: MTU)
uint16_t mtu_size; // 期望MTU大小
uint8_t crc; // 校验和
} mtu_config_packet_t;
八、测试用例
8.1 基础连接测试
连接建立测试
验证BLE广播
验证服务发现
验证特征值读写
心跳测试
定时PING包发送
ACK响应验证
超时断线重连
8.2 数据传输测试
健康数据测试
心率数据实时传输
步数数据同步
大批量历史数据传输
紧急功能测试
SOS报警触发
录音数据传输
网络中断处理
8.3 异常场景测试
网络异常
断线重连
数据重传
缓存溢出处理
电量不足
低电量模式
紧急数据保护
优雅关机
九、版本更新机制
9.1 固件更新协议
// 固件更新请求
typedef struct {
uint8_t stx; // 0xAA
uint8_t len; // 0x0C
uint8_t cmd; // CMD_FIRMWARE_UPDATE (0x05)
uint8_t seq; // 序列号
uint8_t update_action; // 动作 (0:查询 1:开始 2:数据 3:结束 4:验证)
uint32_t firmware_size; // 固件大小
uint16_t firmware_crc; // 固件CRC
uint8_t version_major; // 主版本号
uint8_t version_minor; // 次版本号
uint8_t reserved; // 保留
uint8_t crc; // 校验和
} firmware_update_packet_t;
9.2 OTA更新流程
版本检查: 手机端查询手环固件版本
更新准备: 手环端进入更新模式
数据传输: 分包传输固件数据
校验确认: 校验固件完整性
重启应用: 重启到新固件
十一、Hex样例汇总表
11.1 健康数据协议样例
协议类型 命令码 Hex样例 说明
心跳包 0x00 AA 04 00 01 00 A5 PING心跳序列号1
心率数据 0x10 AA 08 10 01 66 B2 F4 A0 4B 55 E2 心率75bpm质量85%
步数数据 0x11 AA 10 11 05 66 B2 F4 A0 00 00 27 10 0C E4 01 C2 02 8F 步数10000步距离3.3km,跑步模式
血氧数据 0x14 AA 0B 14 02 66 B2 F4 A0 62 5A 4F 0C 00 1D 血氧98%脉率79bpm
生命体征组合 0x18 AA 0E 18 03 66 B2 F4 A0 4B 55 62 5A 50 0C 02 01 73 心率+血氧组合数据
紧急报警 0x50 AA 0C 50 FF 66 B2 F4 A0 01 05 0A 28 0B 58 7C F2 SOS报警最高优先级
录音开始 0x51 AA 08 51 01 00 0C 80 01 00 D4 开始录音16K采样率
录音数据 0x51 AA 14 51 02 01 00 01 F1 E2 D3 C4...2E 1F 08 录音数据包包序号1
11.2 控制命令样例
命令类型 命令码 Hex样例 说明
设备信息查询 0x01 AA 04 01 01 00 A6 查询设备基本信息
时间同步 0x02 AA 08 02 01 66 B2 F4 A0 00 15 同步时间戳
实时监测开始 0x19 AA 0A 19 01 03 E8 03 0A 32 00 01 B2 开始心率+血氧监测
实时监测停止 0x1A AA 06 1A 01 00 01 00 01 23 停止监测,保存数据
ACK确认 0x0F AA 05 0F 01 00 50 B5 确认序列号1电量80%
错误响应 0xF0 AA 06 F0 01 50 06 00 4D SOS命令电量不足错误
11.4 快速参考表
BLE服务和特征UUID表
// 主要服务UUID
#define WEARABLE_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define HEALTH_SERVICE_UUID "180D0000-0000-1000-8000-00805F9B34FB"
#define EMERGENCY_SERVICE_UUID "19B10000-E8F2-537E-4F6C-D104768A1214"
// 特征UUID
#define HEART_RATE_CHAR_UUID "2A37" // 心率测量
#define BLOOD_OXYGEN_CHAR_UUID "2A5F" // 血氧饱和度
#define EMERGENCY_CHAR_UUID "2A65" // 紧急通信
#define CONTROL_CHAR_UUID "2A66" // 控制命令
#define CONFIG_CHAR_UUID "2A67" // 配置参数
命令码快速查找表
基础控制: 0x00-0x0F
├── 0x00: PING心跳包
├── 0x01: 设备信息查询
├── 0x02: 时间同步
├── 0x03: 固件版本
├── 0x04: 电池状态
├── 0x05: 设备重启
└── 0x0F: ACK确认帧
健康监测: 0x10-0x2F
├── 0x10: 心率数据
├── 0x11: 心率配置
├── 0x14: 血氧数据
├── 0x15: 血氧配置
├── 0x18: 生命体征组合
├── 0x19: 实时监测开始
├── 0x1A: 实时监测停止
├── 0x1B: 校准请求
└── 0x1C: 传感器状态
紧急功能: 0x50-0x6F
├── 0x50: SOS紧急报警
├── 0x51: 紧急录音数据
├── 0x52: 紧急位置信息
├── 0x53: SOS状态查询
├── 0x54: 跌倒检测
└── 0x55: 异常心率报警
错误响应: 0xF0-0xFF
├── 0xF0: 通用错误响应
├── 0xF1: 不支持的命令
├── 0xF2: 无效参数
├── 0xF3: 连接超时
├── 0xF4: 校验错误
└── 0xF5: 硬件故障
数据包结构模板
typedef struct {
uint8_t stx; // 起始标志 0xAA
uint8_t length; // 包长度 (不含STX)
uint8_t command; // 命令码
uint8_t sequence; // 序列号
uint8_t data[]; // 数据载荷
uint8_t crc; // XOR校验和
} __attribute__((packed)) BLE_Packet_t;
错误代码定义
#define BLE_SUCCESS 0x00 // 成功
#define BLE_ERROR_INVALID_PARAM 0x01 // 参数错误
#define BLE_ERROR_CONNECTION_LOST 0x02 // 连接丢失
#define BLE_ERROR_TIMEOUT 0x03 // 操作超时
#define BLE_ERROR_CHECKSUM 0x04 // 校验错误
#define BLE_ERROR_SEQUENCE 0x05 // 序列号错误
#define BLE_ERROR_BUFFER_FULL 0x06 // 缓冲区满
#define BLE_ERROR_NOT_SUPPORTED 0x07 // 不支持操作
#define BLE_ERROR_SENSOR_FAULT 0x08 // 传感器故障
#define BLE_ERROR_LOW_BATTERY 0x09 // 电量不足
XOR校验计算算法
uint8_t calculate_crc_xor(const uint8_t *data, uint8_t len) {
uint8_t crc = 0;
for (uint8_t i = 0; i < len; i++) {
crc ^= data[i];
}
return crc;
}
// 使用示例
uint8_t packet[] = {0xAA, 0x08, 0x10, 0x01, 0x66, 0xB2, 0xF4, 0xA0, 0x4B, 0x55};
uint8_t crc = calculate_crc_xor(packet + 1, 9); // 从LEN开始计算
常用数据包长度表
数据包类型 长度(字节) 命令码 说明
PING心跳包 4 0x00 最小数据包
设备信息 15 0x01 包含版本号等
心率数据 8 0x10 单次心率值
步数数据 16 0x11 步数+距离+卡路里
血氧数据 11 0x14 SpO2+心率组合
生命体征 14 0x18 完整健康数据
SOS报警 12 0x50 紧急求助
录音数据 20 0x51 音频片段(受MTU限制)
BLE连接参数推荐
// 连接间隔配置
#define MIN_CONN_INTERVAL 6 // 7.5ms
#define MAX_CONN_INTERVAL 80 // 100ms
#define SLAVE_LATENCY 0 // 无延迟
#define CONN_SUP_TIMEOUT 400 // 4秒超时
// MTU协商
#define DEFAULT_MTU 23 // 默认MTU
#define PREFERRED_MTU 185 // 推荐MTU
#define MAX_MTU 247 // 最大MTU
实时监测采样率配置
#define SAMPLE_RATE_25HZ 0 // 25Hz采样
#define SAMPLE_RATE_50HZ 1 // 50Hz采样
#define SAMPLE_RATE_100HZ 2 // 100Hz采样
#define SAMPLE_RATE_200HZ 3 // 200Hz采样(高精度)
// 功耗模式
#define POWER_MODE_HIGH_PERF 0 // 高性能模式
#define POWER_MODE_BALANCED 1 // 平衡模式
#define POWER_MODE_LOW_POWER 2 // 省电模式
十、开发调试
10.1 调试接口
日志输出: 通过UART或BLE输出调试信息
状态监控: 实时监控连接状态、电量、内存使用
性能分析: 传输速率、响应时间、丢包率统计
10.2 测试工具
模拟器: PC端手环模拟器
抓包工具: BLE协议分析器
压力测试: 并发连接、大数据量传输测试
文档版本: v1.0
最后更新: 2025-07-21
作者: 系统设计团队
审核: 技术负责人