Initial commit of akmon project
This commit is contained in:
314
doc_ble/SENSOR_SYSTEM_DOCUMENTATION.md
Normal file
314
doc_ble/SENSOR_SYSTEM_DOCUMENTATION.md
Normal 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
99
doc_ble/SUMMARY.md
Normal 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. 命令空间规划
|
||||
命令码按功能模块分段,避免冲突并方便查表:
|
||||
- **基础控制 (0x00–0x0F)**:PING、设备信息、时间同步、配置读写、固件升级、重启、ACK 等
|
||||
- **健康数据 (0x10–0x2F)**:心率、步数、睡眠、血氧、体温、卡路里、实时监测控制与配置等
|
||||
- **交互功能 (0x30–0x4F)**:消息通知、来电、闹钟、查找设备、相机/音乐控制等
|
||||
- **紧急功能 (0x50–0x6F)**:SOS 报警、录音数据、位置信息、跌倒/异常心率报警等
|
||||
- **系统配置 (0x70–0x8F)**:显示、震动、语言、表盘、用户资料等
|
||||
- **错误响应 (0xF0–0xFF)**:通用错误、不支持、参数错误、超时、硬件故障等
|
||||
|
||||
## 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
177
doc_ble/ed.md
Normal 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
13
doc_ble/issues.md
Normal file
@@ -0,0 +1,13 @@
|
||||
1.heartbeat 在蓝牙方没有收到。
|
||||
2.心跳测试基本只维持1分钟。而且界面混乱。会有不明黑色矩形。
|
||||
3.测试时候界面滑动经常不能正常,也就是结束有困难。
|
||||
4.spo2这个测试没有数据上传到蓝牙。
|
||||
5.计步读取不成功,(可能是跟文档有差别)
|
||||
6.蓝牙关于录音和信息的读取没有方法(需补充文档)
|
||||
7.偶尔还会死机。。
|
||||
8.没有主动从蓝牙控制的方法(需补充文档)
|
||||
9.开始定时检测以后,如果1分钟之内没有检测到佩戴状况,需要及时中止
|
||||
10.在心率大于170或者可配置的指标后,要执行振动操作,如果持续,需要1分钟后继续振动操作振动
|
||||
11.时间读取不成功。
|
||||
12.测量心率过程中,在notify已结束情况下,依然绿灯闪烁,不会停止,中断蓝牙连接也不会停止。
|
||||
|
||||
150
doc_ble/nearlink_eb21_notes.md
Normal file
150
doc_ble/nearlink_eb21_notes.md
Normal 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.0V–3.6V,推荐 3.3V)。
|
||||
- `GND` → EB21-E `GND` 引脚(至少两点星形接地,靠近模组的地大面积敷铜)。
|
||||
- 在 EB21-E `VCC` 旁边就近放置:
|
||||
- 100nF 贴片电容(0402/0603)
|
||||
- 4.7µF–10µ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 高增益定向天线(如 12–24dBi 八木/栅格)**。
|
||||
|
||||
## 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/心跳协议”的二进制帧格式示例;
|
||||
- 与现有蓝牙协议命令一一对应的映射表。
|
||||
94
doc_ble/ss_generate_mock_data.sql
Normal file
94
doc_ble/ss_generate_mock_data.sql
Normal 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 $$;
|
||||
328
doc_ble/ss_sensor_data_schema.sql
Normal file
328
doc_ble/ss_sensor_data_schema.sql
Normal 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
783
doc_ble/蓝牙协议.md
Normal 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
|
||||
作者: 系统设计团队
|
||||
审核: 技术负责人
|
||||
|
||||
Reference in New Issue
Block a user