RuView 怎么用 sleep-monitor.js 跑整晚睡眠监测并回放已录数据?
【免费下载链接】RuViewπ RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.项目地址: https://gitcode.com/GitHub_Trending/wi/RuView
RuView 的scripts/sleep-monitor.js是一个基于 CSI 的睡眠分期脚本(ADR-077):它消费 ESP32 节点上报的生命体征数据(呼吸率 BR、心率 HR、运动能量),按 5 分钟滑动窗口把每个窗口分类为 Awake / Light / REM / Deep 四个阶段,输出 ASCII 睡眠图(hypnogram)和汇总统计(总睡眠时长、睡眠效率、各阶段占比)。它有两条使用路径:实时模式监听 UDP 端口、整晚持续分类;回放模式(--replay)读取已录好的.csi.jsonl文件离线分析,不需要在线硬件。脚本是纯 Node.js 实现,无外部依赖。
需要说明:该脚本是消费级信息工具,不是医疗器械,输出不能用于临床诊断(脚本输出头部和 ADR-077 均带有此声明)。
准备条件
- Node.js环境。ADR-077 说明这组脚本是"Pure JS, no native dependencies, runs on any platform with Node.js"。
- 实时模式的前提:房间里有按 ADR-018 二进制协议通过 UDP 5006 端口上报 vitals 包(magic
0xC5110002,融合包为0xC5110004)的 ESP32-S3 节点。ADR-077 的 Context 一节描述的基础设施是 2 个 ESP32-S3 节点以约 1 Hz/节点 上报呼吸率、心率、运动能量和存在分数,采集周期按 6–8 小时(整晚)设计。 - 回放模式的前提:本地已有一个
.csi.jsonl录制文件。回放时脚本逐行解析 JSON,只处理type为"vitals"的记录,并从记录中读取以下字段(见 sleep-monitor.js 的parseVitalsJsonl):
| 字段 | 用途 |
|---|---|
timestamp | 记录时间戳(秒) |
node_id | 节点编号,用于按节点分缓冲 |
breathing_bpm | 呼吸率,缺失按 0 计 |
heartrate_bpm | 心率,缺失按 0 计 |
motion_energy | 运动能量,缺失按 0 计 |
项目文档中的录制文件约定放在data/recordings/目录下(sensing server 的 Recording 接口创建.csi.jsonl文件,见 ADR-043)。
命令行参数
以下参数及默认值来自 sleep-monitor.js 源码中的parseArgs定义(strict: true,未定义的选项会被拒绝):
| 参数 | 短写 | 默认值 | 说明 |
|---|---|---|---|
--port | -p | 5006 | 实时模式监听的 UDP 端口 |
--replay | -r | 无 | 回放模式,指定.csi.jsonl文件路径 |
--json | — | false | 以 JSON 行输出,便于程序化消费 |
--interval | -i | 5000 | 分析间隔,单位毫秒 |
--window | -w | 300 | 滑动窗口长度,单位秒(默认 5 分钟) |
带--replay时进入回放模式,否则进入实时 UDP 监听模式。
文档冲突提示:docs/user-guide.md 的 Health & Wellness 一节给出的实时命令是
node scripts/sleep-monitor.js --port 5006 --bind 192.168.1.20,但脚本源码的parseArgs并未定义--bind选项,且strict: true下传入未定义选项会报错。请按源码支持的实际参数执行(即不带--bind)。
实时模式:整晚运行
在项目根目录执行:
node scripts/sleep-monitor.js --port 5006绑定成功后脚本会打印Sleep Monitor listening on UDP :5006 (window 300s)。此后它会持续接收 vitals 包,并按--interval(默认 5000 ms)周期性在终端刷新当前状态,包括:
Current stage:当前窗口分类出的阶段;- 窗口内的 BR 均值/方差、HR 均值/CV、Motion 均值、样本数(
Window: N samples); - ASCII hypnogram 与实时汇总(
Duration / Sleep / Efficiency及四阶段百分比)。
数据积累前会显示Collecting data...(每个节点缓冲至少需要 3 个样本才会产生统计)。
运行整晚后,按 Ctrl+C 退出时脚本会打印一行会话汇总:
Session: 411.3 min | Sleep: 372.9 min | Efficiency: 90.7%(上面的数值仅为格式示例,实际输出取决于当晚数据。)
如果下游需要程序化采集,加--json即可:此时不再清屏刷新,而是每产生一个窗口分析结果就输出一行 JSON,字段为timestamp、stage、br_mean、br_var、hr_mean、hr_cv、motion_mean。
回放模式:分析已录数据
回放不需要任何在线硬件:
node scripts/sleep-monitor.js --replay data/recordings/overnight-1775217646.csi.jsonl路径data/recordings/overnight-1775217646.csi.jsonl是 ADR-077 验证一节使用的示例录制(文档描述为 113k 帧、约 40 分钟的 overnight 录制)。仓库中不一定存在该文件,请把路径替换为你自己录制生成的.csi.jsonl;文件不存在时脚本会打印File not found: <path>并以退出码 1 结束。
回放逐行读取 JSONL,按数据内时间戳推进,每当累计满一个--interval的数据时间就做一次窗口分类,默认(非 JSON)输出逐窗口一行:
[03:14:07] Light | BR 14.2 (var 3.10) | HR 58.4 | Motion 0.85读完整个文件后打印SLEEP SESSION SUMMARY:hypnogram(W=Awake L=Light R=REM D=Deep字符条)、Total recorded、Total sleep、Efficiency、Entries(分析窗口数)、各阶段占比与时长,最后一行是Processed N vitals packets。
加--json则每个窗口输出一行 JSON(timestamp、stage、br_mean、br_var、hr_mean、hr_cv、motion_mean),文件末尾追加一行{"type":"summary", ...}汇总,可直接交给其他程序处理。
需要调整分析粒度时:--window改变窗口长度(默认 300 秒),--interval改变分析触发间隔。注意 ADR-077 对算法的设计描述是"5-minute windows, 1-minute stride",与脚本源码默认--interval 5000(5 秒)不完全一致,具体以脚本源码的默认值为准,两个参数都可以按数据量调整。
结果验证
回放结束后如何判断结果是合理的:
- 处理计数:最后一行
Processed N vitals packets告诉你文件里有多少条 vitals 记录被消费。如果N为 0,说明该 JSONL 中没有type: "vitals"的记录(回放只认这种记录;只含其他类型帧的文件会得到空 hypnogram 和Processed 0 vitals packets),文件类型或来源需要检查。 - hypnogram 形态:ADR-077 给出的验证预期是,overnight 数据应表现出从活动(awake)到静息状态的过渡、运动能量随时间下降、睡眠片段内 BR 趋于稳定。可以对照这些现象判断回放是否正常还原了数据的时间结构。
- 汇总数值:
Total recorded应接近录制文件首末时间戳跨度;Efficiency是 TST / 在床时间(ADR-077 的定义);各阶段百分比之和为 100%。
阶段判定的实现依据
ADR-077 给出的分期阈值表(每个 5 分钟窗口计算 BR 均值与方差、HR 均值与 CV、运动能量均值后分类,判级次序为 Awake > REM > Light > Deep):
| 阶段 | BR (BPM) | BR 方差 | HR 模式 | 运动 |
|---|---|---|---|---|
| Deep (N3) | 6–12 | 很低(<2.0) | 慢而规律 | 无 |
| Light (N1/N2) | 12–18 | 中等(2.0–8.0) | 正常 | 极少 |
| REM | 15–25 | 高(>8.0),不规律 | 偏高 | 仅眼球(CSI 运动很低) |
| Awake | >18 或 <6 | 任意 | 可变 | 中等–较高 |
具体阈值与判级代码实现在 sleep-monitor.js 的VitalsBuffer.classify中,两者数值略有出入,精确行为以源码为准。
限制
- 脚本头部与 ADR-077 均声明:这是消费级信息工具,非诊断用途;无 EEG 的睡眠分期是近似结果(consumer-grade accuracy)。
- ADR-077 的 Consequences 一节列出的限制:vitals 精度取决于 ESP32 CSI 质量(RSSI、多径);1 Hz 采样的 HRV 分析相比 ECG 较粗糙。
- 回放是离线分析,结果不会写回任何文件;
--json的输出需由调用方自行重定向保存。
【免费下载链接】RuViewπ RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.项目地址: https://gitcode.com/GitHub_Trending/wi/RuView
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考