拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于加速度传感器与MySQL状态机的睡眠阶段检测小程序

简介这是一套面向计算机专业本科生的毕业设计级微信小程序实战项目聚焦睡眠健康管理场景提供从需求分析、前后端开发到部署上线的完整技术闭环。资源包含基于uniapp或原生小程序框架开发的前端代码、Java/PHP后端服务及MySQL 5.7数据库设计覆盖助眠音乐控制、睡眠数据可视化记录、睡眠知识问答与个人信息管理四大核心模块并配套开题报告、设计文档与答辩PPT等学术材料。压缩包共110个文件含53张界面截图png、14个逻辑脚本js、13个配置文件json、11个样式文件wxss及10个页面结构文件wxml辅以2份Word文档、2段教学视频mp4和1个动态加载动画gif整体大小14.63MB。目前已有169人学习下载读者可直接导入HBuilder X或微信开发者工具运行调试快速掌握小程序MySQL全栈开发流程与毕业论文撰写规范。1. 睡眠检测小程序不是健康数据看板而是闭环行为干预系统很多开发者拿到「睡眠检测小程序」这个标题第一反应是做个带时间选择器和打卡按钮的静态页面再连个 MySQL 存几条“23:05 入睡”“07:18 起床”。但真实场景里用户凌晨两点点开小程序看到“今日睡眠质量差深度睡眠仅1.2h”下一秒就切出微信刷短视频——数据没触发任何动作检测就失去了意义。这个毕业设计源码包的价值恰恰在于它用最小可行结构实现了「感知→反馈→引导」闭环前端通过手机加速度传感器粗粒度识别体动频次非医疗级但符合学生项目边界后端用 MySQL 建模睡眠阶段过渡规律比如连续10分钟低频体动心率区间匹配浅睡期再通过小程序模板消息推送轻量干预建议“您昨晚浅睡偏多今晚可尝试睡前1小时关闭蓝光屏幕”。它面向的是能独立部署、理解数据流向、并能基于业务逻辑调整阈值参数的 IT 类毕业生不是只懂拖拽生成器的零基础学员。2. 用 wx.getAccelerometer 获取体动特征而非调用未授权的健康平台API小程序无法直接读取手机内置的睡眠监测芯片如华为 TruSleep、苹果 HealthKit但可通过wx.getAccelerometerAPI 以 50ms 频率采集加速度三轴原始数据。毕业设计源码中采用滑动窗口法处理该数据流这是兼顾性能与有效性的常见做法。2.1 加速度数据采集与本地降噪小程序端在用户点击“开始检测”后启动监听// pages/sleep/start.js Page({ data: { isMonitoring: false, rawData: [] }, startMonitor() { const that this; wx.startAccelerometer({ interval: game, // 最高采样频率约50ms/次 success: () { that.setData({ isMonitoring: true }); wx.onAccelerometerChange((res) { // 只保留z轴垂直方向数据人体平躺时z轴变化最敏感 const zValue Math.abs(res.z); // 滑动窗口保留最近200个点约10秒超长则截断 const newRaw [...that.data.rawData.slice(-199), zValue]; that.setData({ rawData: newRaw }); }); } }); } });提示interval: game是关键参数ui或normal模式下采样间隔过长200ms无法捕捉翻身等短时体动但需注意wx.onAccelerometerChange在后台会被系统暂停因此必须要求用户保持小程序前台运行。2.2 服务端用 MySQL 计算体动活跃度指标前端每30秒将rawData数组通过 POST 发送至/api/sleep/upload接口后端Node.js Express解析后存入 MySQL 表sleep_raw_dataCREATE TABLE sleep_raw_data ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, user_id VARCHAR(32) NOT NULL COMMENT 微信openid, session_id VARCHAR(64) NOT NULL COMMENT 本次检测会话唯一标识, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, z_values JSON NOT NULL COMMENT JSON数组存储30秒内所有z轴绝对值, PRIMARY KEY (id), INDEX idx_user_session (user_id, session_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;注意z_values字段使用 JSON 类型而非拆成多行记录是因为学生项目需控制表数量与查询复杂度实际生产环境应拆为子表并建时间分区。服务端计算逻辑简化版// routes/sleep.js app.post(/api/sleep/upload, async (req, res) { const { userId, sessionId, zValues } req.body; // 计算30秒内“显著体动次数”z值 0.3g 的连续段数量过滤微小抖动 const threshold 0.3; let movementCount 0; let inMovement false; for (let i 0; i zValues.length; i) { if (zValues[i] threshold !inMovement) { movementCount; inMovement true; } else if (zValues[i] threshold) { inMovement false; } } // 插入汇总指标到 sleep_summary 表 await db.query( INSERT INTO sleep_summary (user_id, session_id, timestamp, movement_count) VALUES (?, ?, NOW(), ?), [userId, sessionId, movementCount] ); res.json({ code: 0 }); });该movement_count就是后续判断“入睡潜伏期”“夜间觉醒次数”的核心输入。MySQL 中不进行实时复杂计算只做轻量聚合符合学生项目对数据库能力的合理预期。3. MySQL 设计睡眠阶段状态机用触发器自动标记阶段跃迁单纯存储“每30秒体动次数”无法反映睡眠结构。毕业设计源码通过在 MySQL 中构建有限状态机FSM将连续时间段映射为“清醒→浅睡→深睡→REM”的粗略阶段这是比纯前端判断更可靠的方案——状态持久化后可回溯任意时刻状态支撑“历史睡眠报告”功能。3.1 状态定义与状态转移规则在sleep_stage_log表中定义四类状态及跃迁条件状态码名称触发条件基于前3分钟 movement_count 均值持续时间要求0清醒 8 次/分钟—1浅睡3~8 次/分钟≥ 5 分钟2深睡≤ 2 次/分钟≥ 10 分钟3REM体动频次回升但低于清醒阈值4~6次/分钟 心率区间匹配≥ 3 分钟注意心率数据在本项目中由用户手动录入模拟实际可接入微信运动接口需用户授权但毕业设计未强制依赖外部API降低部署门槛。3.2 用 MySQL 触发器实现状态自动更新当新记录插入sleep_summary表时触发器检查最近数据流并更新当前会话的最新状态DELIMITER $$ CREATE TRIGGER update_sleep_stage AFTER INSERT ON sleep_summary FOR EACH ROW BEGIN DECLARE avg_mov DECIMAL(5,2); DECLARE last_stage TINYINT; DECLARE current_time DATETIME; SET current_time NEW.timestamp; -- 计算前3分钟平均体动次数单位次/分钟 SELECT IFNULL(AVG(movement_count) * 2, 0) INTO avg_mov FROM sleep_summary WHERE session_id NEW.session_id AND timestamp BETWEEN DATE_SUB(current_time, INTERVAL 3 MINUTE) AND current_time; -- 获取当前会话最新状态 SELECT COALESCE(stage_code, 0) INTO last_stage FROM sleep_stage_log WHERE session_id NEW.session_id ORDER BY timestamp DESC LIMIT 1; -- 状态跃迁逻辑简化版 IF avg_mov 8 THEN IF last_stage ! 0 THEN INSERT INTO sleep_stage_log (session_id, stage_code, start_time, end_time) VALUES (NEW.session_id, 0, current_time, NULL); END IF; ELSEIF avg_mov BETWEEN 3 AND 8 THEN IF last_stage ! 1 THEN -- 结束上一状态 UPDATE sleep_stage_log SET end_time current_time WHERE session_id NEW.session_id AND end_time IS NULL; -- 开启新状态 INSERT INTO sleep_stage_log (session_id, stage_code, start_time, end_time) VALUES (NEW.session_id, 1, current_time, NULL); END IF; END IF; END$$ DELIMITER ;该触发器不处理深睡/REM 的完整判定需结合心率但已覆盖主要跃迁路径。学生可在此基础上扩展heart_rate字段和更精细条件而无需改动应用层代码。3.3 查询某次会话的完整睡眠阶段序列前端请求/api/sleep/report?sessionIdxxx时后端执行SELECT stage_code, TIME_FORMAT(TIMEDIFF(end_time, start_time), %H:%i:%s) AS duration, COUNT(*) AS segment_count FROM sleep_stage_log WHERE session_id xxx AND end_time IS NOT NULL GROUP BY stage_code ORDER BY MIN(start_time);返回结果直接用于绘制睡眠周期图如 ECharts 柱状堆叠图避免前端做状态拼接。4. 前后端分离下的 token 安全传递与会话绑定策略小程序用户身份由微信code换取openid后确立但毕业设计源码中未使用 JWT 或 Redis Session而是采用 MySQL 表user_session实现轻量会话管理——这既满足毕业设计对“可读性”和“无额外中间件依赖”的要求又规避了wx.login过期导致的频繁重登问题。4.1 登录流程code 换 openid 后写入会话表小程序端获取code后提交至后端// utils/login.js export async function login() { const { code } await wx.login(); const res await wx.request({ url: https://your-domain.com/api/auth/login, method: POST, data: { code } }); if (res.data.token) { wx.setStorageSync(auth_token, res.data.token); // 本地缓存 } }后端Node.js处理// routes/auth.js app.post(/api/auth/login, async (req, res) { const { code } req.body; // 调用微信接口换取 openid需配置 appid secret const wxRes await axios.get( https://api.weixin.qq.com/sns/jscode2session?appid${APPID}secret${SECRET}js_code${code}grant_typeauthorization_code ); const { openid, session_key } wxRes.data; // 生成32位随机token非JWT无签名仅作会话索引 const token crypto.randomBytes(16).toString(hex); // 写入 user_session 表有效期24小时 await db.query( INSERT INTO user_session (token, openid, expires_at) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 24 HOUR)), [token, openid, null] ); res.json({ token }); });对应 MySQL 表结构CREATE TABLE user_session ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, token CHAR(32) NOT NULL UNIQUE, openid VARCHAR(64) NOT NULL, expires_at DATETIME NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), INDEX idx_openid_expire (openid, expires_at) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;4.2 接口鉴权每次请求校验 token 有效性所有受保护接口如/api/sleep/upload前置中间件function authMiddleware(req, res, next) { const token req.headers.authorization?.replace(Bearer , ); if (!token) return res.status(401).json({ code: 401, msg: Missing token }); db.query( SELECT openid FROM user_session WHERE token ? AND expires_at NOW(), [token], (err, results) { if (err || results.length 0) { return res.status(401).json({ code: 401, msg: Invalid or expired token }); } req.userOpenid results[0].openid; next(); } ); }提示此方案不依赖 Redis所有状态落盘 MySQL适合学生部署在单台 CentOS 7.9 服务器如阿里云 ECS但需注意user_session表定期清理可在 crontab 中添加# 每日凌晨2点删除过期会话 0 2 * * * mysql -u root -ppassword your_db -e DELETE FROM user_session WHERE expires_at NOW();5. 说明文档LW不是操作手册而是部署决策日志毕业设计中的“说明文档LW”常被误解为功能列表或截图堆砌但高质量的 LW 应记录每个技术选型背后的约束与权衡。源码包中的 LW 文档包含以下不可省略的章节它们直接决定部署成功率。5.1 MySQL 版本与字符集兼容性声明明确标注测试环境为MySQL 5.7.32非 8.0原因如下项目MySQL 5.7.32MySQL 8.0选型理由JSON 支持✅ 基础 JSON 函数JSON_CONTAINS✅ 更多函数JSON_TABLE项目仅需JSON_CONTAINS判断字段存在性默认字符集latin1utf8mb4避免建表时因字符集不一致报错学生可手动执行ALTER DATABASE your_db CHARACTER SET utf8mb4系统变量名max_allowed_packet同名但默认值更大上传大体积z_valuesJSON 时需确认该值 ≥ 64M注意若在 CentOS 7.9 上安装 MySQL官方推荐使用mysql57-community-release-el7-11.noarch.rpm包而非mysql80-community-release-el7-6.noarch.rpm避免触发ONLY_FULL_GROUP_BY严格模式导致聚合查询失败。5.2 小程序app.json中的关键配置项说明LW 文档需逐条解释app.json中影响上线的字段例如{ permission: { scope.userFuzzyLocation: { desc: 用于获取用户模糊地理位置非必需本项目未使用 }, scope.record: { desc: 【必须开启】用于调用 wx.startAccelerometer } }, requiredPrivateInfos: [accelerometer], sitemapLocation: sitemap.json }requiredPrivateInfos是微信 2023 年起强制要求的字段漏填会导致真机调试时wx.startAccelerometer报错fail permission deniedsitemap.json必须存在且内容为{ desc: all }否则小程序无法通过微信审核即使只是毕业设计演示。5.3 部署时config.js的 3 个必改参数后端config.js中以下参数必须人工修改LW 文档用表格强调参数名示例值修改说明DB_HOST127.0.0.1若 MySQL 与 Node.js 不在同一机器需改为内网 IP禁止填localhostWX_APPIDwx1234567890abcdef微信公众平台申请的小程序 AppID不是公众号 AppIDSTATIC_URLhttps://your-domain.com小程序中图片/音频资源的 CDN 域名若用本地路径/static/xxx.png需确保 Nginx 已配置静态文件路由部署者只需按此表修改即可跳过 80% 的“启动报错”问题。LW 的价值正在于把“别人踩过的坑”变成“你抄作业的 checklist”。验证 MySQL 是否正确加载睡眠阶段数据执行SELECT * FROM sleep_stage_log WHERE session_id test_001 ORDER BY start_time;应返回至少 3 条不同stage_code的连续记录且end_time字段非空。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门