# aihealth **Repository Path**: ccstclink/aihealth ## Basic Information - **Project Name**: aihealth - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-11 - **Last Updated**: 2026-11-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AIHealth 健康管理平台 类 Joeme Fit 的手表健康生态:Android App(BLE 直连手表)+ Spring Boot 后台 + Vue3 管理端。 ``` [阶段一] Android App (Kotlin+Compose) ──BLE(F008 私有协议/标准 GATT)──> 白牌手表 │ Room 本地存储(主数据源)+ Outbox 队列 └──[阶段二] Retrofit/WorkManager 同步 ──REST──> server (Spring Boot) <──REST/SSE──> web (Vue3 管理端) └── H2(开发) / MySQL(生产) ``` ## 目录结构 | 目录 | 说明 | |---|---| | `app/` | Android App:BLE 连接、Veepoo 协议命令表(`VeepooCommands.kt`)、Outbox 同步、配置应用(`ConfigApplier.kt`) | | `server/` | Spring Boot Kotlin 后台:用户域 `/api/v1` + 管理域 `/admin/api`(JWT 双域鉴权) | | `web/` | Vue3 + Element Plus 管理端(主入口 `/`;server 内置原生遗留页 `/admin`) | | `docs/sql/` | 生产 MySQL DDL(`schema.sql`)与种子数据(`seed.sql`) | | `deploy/` | 生产部署:`docker-compose.yml` + `nginx.conf`(+ `.env.example`) | | `tools/` | 验证脚本与 BLE 抓包工具(`smoke-config.ps1` / `smoke-live.ps1`) | ## 快速启动(开发模式) ```powershell # 1. 后台(默认 H2 文件库 ./server/data/aihealth,schema 幂等自动执行) .\gradlew.bat :server:bootRun # 2. 管理端(5173,/admin 与 /api 均代理到 8088) Set-Location web; npm install; npm run dev # 3. App(Android Studio 打开根工程,或) .\gradlew.bat :app:assembleDebug ``` > **端口冲突注意**:开发机上 IDE 后台代理 `AgentService.exe` 常驻占用 `8080`,会导致 `bootRun` 默认启动报端口占用。此时无需改动配置文件,可临时改用其他端口启动后端,并同步通知前端代理目标。 后端改用 8082(`--server.port` 覆盖 `application.yml`,无需改文件): ```powershell .\gradlew.bat :server:bootRun --args="--server.port=8082" ``` 前端代理跟随(`web/vite.config.ts` 已支持 `BACKEND_PORT` 环境变量): ```powershell $env:BACKEND_PORT=8082; Set-Location web; npm run dev ``` 验证链路:访问 `http://localhost:5173/api/v1` 经代理返回 `401`(JWT 过滤器生效)即表示前后端连通。该方式完全可逆——停掉后端、去掉参数与变量即可恢复默认 8088(开发端口;生产 docker 仍为 8080)。 首次启动引导(`AdminBootstrap`)幂等创建默认管理员,并写入 RBAC 权限点/角色(与 `docs/sql/seed.sql` 一致)。 ### 默认账号 | 类型 | 账号 | 密码 | 登录入口 | 说明 | |---|---|---|---|---| | 超级管理员 | `admin` | `Admin@123456` | 管理后台 `http://localhost:5173`(`POST /admin/api/login`) | **首字母 `A` 大写**,BCrypt 大小写敏感;生产必须立即改密 | | 普通用户(用户域) | `15308407230` | `12345678` | 手表/手机 App(`POST /api/v1/auth/login`) | 仅供 App 用户域使用,**不能**用于本管理后台 | > ⚠️ 管理后台(`web/`,即 `localhost:5173`)只接受 `admin` 类后台账号;普通用户的手机号/密码在此登录会报"用户名或密码错误"。 > 后台登录**连续失败 5 次锁定 15 分钟**(内存态,重启后端即清空)。 ## 管理端功能与权限点 | 菜单 | 权限点 | 说明 | |---|---|---| | 工作台 | `menu:dashboard` | 注册/设备/今日采样看板 | | 用户管理 | `menu:user` | 列表/详情/封禁(手机号掩码存储) | | 设备管理 | `menu:device` | 列表/解绑/**配置下发**(`device:config`)/**指令下发**(`device:command`) | | 数据查询 | `menu:data` | 采样明细/CSV 导出(`data:view` / `data:export`) | | 告警中心 | `menu:alert` | 心率过高/血氧过低处理 | | 系统管理 | `menu:system` | RBAC 角色-权限分配 | | 审计日志 | `menu:audit` | 管理操作审计 | | 实时监测 | `menu:live` | SSE 采样入库实时流(OPS/CS/SUPER) | | 备用直连 | `menu:ble` | 浏览器 Web Bluetooth 直报(OPS/SUPER) | 角色:SUPER_ADMIN(全量)/ OPS / CS / ANALYST / AUDITOR,权限点由 `AdminBootstrap` 幂等引导。 ## 核心链路 - **数据同步**:App Outbox(业务写与入队同事务)→ `/api/v1/sync/batch`,条目级幂等(`client_msg_id` 唯一)、批次级幂等(`batch_no`)、失败整批回队重试。 - **配置下发**(device_configs 版本链):管理端写入即新版本 PENDING → App 经 `/api/v1/sync/checkpoint` 拉取 → `ConfigApplier` 应用(heart_warning→AC 帧、long_seat→E1 帧、night_spo2→unsupported 降级)→ `/api/v1/config/ack` 按 (device,key,version≤n) 收敛。state:0 待应用 / 1 已应用 / 2 设备不支持 / 3 应用失败。 - **实时监测**(F2):采样入库事务提交后经 SSE 推送 `/admin/api/live/stream`(事件仅含脱敏字段);25s 心跳防代理断连;前端 fetch 流式读取(EventSource 无法带 Authorization)。 - **数据实时推送**(App 侧 `RealtimePushManager`):测量/预警数据落库入 Outbox 后 2.5s 去抖 + 5s 冷却节流即时上报(开关:设备页「硬件」页签),管理端实时监测延迟从最长 15 分钟收敛到秒级;与 SyncWorker 并发安全(drain 取批与标记 sending 同一 Room 事务 + 条目级幂等)。 - **硬件反向控制**(2026-10-28 新增):管理端可下发气泵血压启停(90 01/00 05)/血压模式+校准读写(91)/血压与 ECG 功能开关(92、94 05)/心电启停(93 01)/六轴流开关(F1 20/00)/翻腕亮屏(AA)/PPG 实时传输(EB)等 13 条指令;App 端另有「气泵不动」前置编排(读 91 设置→写校准→启动 90)。 - **F002 传感通道**:维誉第二 BLE 通道(f0020001/f0020002)订阅 GSensor 三轴加速度(0x89 帧)与气泵原始波形(0x94 帧),通道缺失时优雅降级(不订阅、不影响主链路)。 - **历史数据补拉**(待办②):A1 确认成功即自动串行拉取 D1 五分钟综合 → D2 血氧 → D9 HRV → E0 睡眠,各回看 3 天(单天 35s 超时兜底);历史数据 recordedAt 固定于设备侧,同 `(mac, type, recordedAt)` / `(mac, startAt)` 防重落库,落库与 Outbox 入队同 Room 事务;补拉完成后自动开启血氧连续测量(80 01 02)。 - **设备指令箱**(Outbox 镜像,云端反向控制):`device_commands` 表无版本链(自增 id 即回执凭据);管理端 `/admin/api/devices/{id}/commands` 下发 PENDING → App 经 checkpoint 按 id 升序拉取执行 → `/api/v1/command/ack` 回执(applied/unsupported/failed 三态收敛);设备未连接不 ack 保持 PENDING,指令集与 App 端 `CommandApplier` 同源(start_bp_measure / stop_bp_measure / time_sync)。 - **定时回连兜底**(待办④):分层回连 = autoConnect(true)(单次连接内断线)→ DeviceConnectionService 30s 轮询(进程存活期)→ ReconnectWorker 15min 周期(跨进程生命周期)。 - **备用直连**(F5):浏览器 Web Bluetooth 订阅标准心率服务(0x180D/0x2A37)与电量(0x180F/0x2A19),攒批(5 条或 10s)经用户域 JWT 直报 `/api/v1/sync/batch`;隐私限制无真实 MAC,以 deviceId 哈希派生稳定伪 MAC 建档(`protocol_family=web-bluetooth`)。 ## 生产部署(docker-compose) ```powershell # 前置产物 .\gradlew.bat :server:bootJar # → server/build/libs/server-*.jar npm --prefix web run build # → web/dist/ # 配置密钥 Copy-Item deploy\.env.example deploy\.env # 修改密码与密钥(至少 32 字节随机) # 启动(MySQL 初始化自动执行 docs/sql/schema.sql + seed.sql) docker compose --project-directory deploy -f deploy/docker-compose.yml up -d ``` - server 经 `SPRING_DATASOURCE_URL` 连 MySQL(驱动已内置),`SPRING_SQL_INIT_MODE=never` 关闭 H2 脚本; - 密钥经 `APP_JWT_SECRET` / `APP_CRYPTO_PEPPER` 覆盖(`application.yml` 中的默认值仅限开发); - 入口:nginx 80 → web 管理端静态 + `/admin`、`/api` 反代到 server:8080。 ## HTTPS 与 Web Bluetooth F5 备用直连要求 **secure context**(HTTPS 或 localhost)。生产启用 TLS 时在 `deploy/nginx.conf` 的注释段放开 443 配置(证书放 `deploy/certs/`): ```nginx server { listen 443 ssl; ssl_certificate /etc/nginx/certs/fullchain.pem; ssl_certificate_key /etc/nginx/certs/privkey.pem; # ... 其余 location 与 80 段相同 } ``` ## 验证脚本(tools/) | 脚本 | 覆盖 | |---|---| | `smoke-config.ps1` | 配置下发闭环 11 步:admin 下发 → checkpoint 拉取 → ack 收敛 → unsupported 降级 → 越界 400 | | `smoke-command.ps1` | 指令箱闭环 10 步:指令下发 → checkpoint 下行 → ack 三态收敛 → 未知键 400 | | `smoke-live.ps1` | SSE 实时流:admin 订阅 → 用户上报 → 断言 `event:sample` 帧到达 | 运行前提:server 已在对应端口启动(默认 `8080`;若 `8080` 被占用改用其他端口,见上方「端口冲突注意」,脚本中的端口需一并调整)。 ## 已知限制 - `night_spo2` 与 `auto_measure`(自动测量 0xB3)协议帧已按 jadx `hf.b`(AutoMeasureOpt)实装并三端打通(单测全绿),尚未经 F520Pro 真机验证(见 docs/design/05-真机实锤验证清单.md P0); - 找手表(0xAE)/闹钟(0xAB)/通知转发(0xC2)命令字已实锤(真机实测 AE 系被拒),待 F520Pro 真机回归; - 硬件增强族(2026-10-28 JoemeFit 二轮逆向新增):气泵/袖带血压(90 01/00 05)、血压功能开关(92)、ECG 功能开关(94 05)、六轴 GSensor 流(F1 20/00 + F002 通道 0x89 帧)、翻腕亮屏(AA)、PPG 实时传输(EB)已三端打通(单测全绿),`AA` 回执时段字段偏移与 F002 通道可用性待 F520Pro 真机回归校准; - `devices.mac` 列宽 17 字符:Web Bluetooth 直连设备使用伪 MAC 建档; - Web Bluetooth 仅 Chrome/Edge 89+ 且需 HTTPS/localhost。