在这里插入图片描述

前言

睡眠质量是影响运动表现和身体恢复的关键因素。一个完善的运动健康应用不仅要记录运动数据,还应该帮助用户了解和改善睡眠状况。本文将详细介绍如何在Flutter与OpenHarmony平台上实现一个专业的睡眠监测组件,包括睡眠时长记录、睡眠阶段分析、睡眠质量评分等功能模块的完整实现方案。

睡眠监测的技术实现涉及多个方面:通过传感器数据判断用户的睡眠状态,分析睡眠周期中的不同阶段,计算睡眠质量评分,以及以直观的方式展示睡眠数据。我们需要在准确性和用户体验之间找到平衡,为用户提供有价值的睡眠洞察。

Flutter睡眠数据模型

class SleepRecord {
  final DateTime bedTime;
  final DateTime wakeTime;
  final Duration totalDuration;
  final int qualityScore;
  final List<SleepStage> stages;
  
  SleepRecord({
    required this.bedTime,
    required this.wakeTime,
    required this.stages,
  }) : totalDuration = wakeTime.difference(bedTime),
       qualityScore = _calculateQualityScore(stages);
  
  static int _calculateQualityScore(List<SleepStage> stages) {
    int deepSleepMinutes = stages
        .where((s) => s.type == SleepStageType.deep)
        .fold(0, (sum, s) => sum + s.duration.inMinutes);
    return (deepSleepMinutes / 90 * 100).clamp(0, 100).toInt();
  }
}

睡眠数据模型是睡眠监测功能的基础。模型包含入睡时间、醒来时间、总睡眠时长、质量评分和睡眠阶段列表。totalDuration通过醒来时间减去入睡时间自动计算得出。qualityScore基于深度睡眠时长计算,深度睡眠是身体恢复的关键阶段,成年人每晚理想的深度睡眠时长约为90分钟,我们以此为基准计算百分比评分。这种设计将复杂的睡眠数据结构化,便于后续的存储、分析和展示。

睡眠阶段类型定义

enum SleepStageType { awake, light, deep, rem }

class SleepStage {
  final SleepStageType type;
  final DateTime startTime;
  final Duration duration;
  
  SleepStage({
    required this.type,
    required this.startTime,
    required this.duration,
  });
  
  String get typeName {
    switch (type) {
      case SleepStageType.awake: return '清醒';
      case SleepStageType.light: return '浅睡';
      case SleepStageType.deep: return '深睡';
      case SleepStageType.rem: return '快速眼动';
    }
  }
  
  Color get typeColor {
    switch (type) {
      case SleepStageType.awake: return Colors.orange;
      case SleepStageType.light: return Colors.lightBlue;
      case SleepStageType.deep: return Colors.indigo;
      case SleepStageType.rem: return Colors.purple;
    }
  }
}

睡眠阶段是睡眠分析的核心概念。我们定义了四种睡眠阶段类型:清醒、浅睡、深睡和快速眼动(REM)。每个睡眠阶段记录类型、开始时间和持续时长。typeName和typeColor属性提供了阶段的中文名称和对应颜色,用于UI展示。正常的睡眠周期会在这四个阶段之间循环,每个周期约90分钟。深度睡眠主要出现在前半夜,对身体恢复最重要;REM睡眠主要出现在后半夜,与梦境和记忆巩固相关。

OpenHarmony睡眠检测服务

import sensor from '@ohos.sensor';

class SleepDetectionService {
  private isMonitoring: boolean = false;
  private motionData: Array<number> = [];
  
  startMonitoring(): void {
    this.isMonitoring = true;
    sensor.on(sensor.SensorId.ACCELEROMETER, (data) => {
      if (this.isMonitoring) {
        let magnitude = Math.sqrt(data.x * data.x + data.y * data.y + data.z * data.z);
        this.motionData.push(magnitude);
        this.analyzeMotion();
      }
    }, { interval: 1000000000 });
  }
  
  private analyzeMotion(): void {
    if (this.motionData.length >= 60) {
      let recentData = this.motionData.slice(-60);
      let variance = this.calculateVariance(recentData);
      // 根据运动方差判断睡眠状态
    }
  }
  
  stopMonitoring(): void {
    this.isMonitoring = false;
    sensor.off(sensor.SensorId.ACCELEROMETER);
  }
}

睡眠检测通过分析用户的运动模式来判断睡眠状态。OpenHarmony的加速度传感器可以检测设备的运动情况,当用户佩戴智能手表或将手机放在床上时,可以通过运动数据推断睡眠状态。我们计算加速度的矢量幅度,然后分析一段时间内的运动方差。方差小表示用户静止,可能处于睡眠状态;方差大表示用户活动,可能处于清醒或浅睡状态。interval参数设置为1秒采样一次,平衡了精度和功耗。

Flutter睡眠时长显示组件

class SleepDurationDisplay extends StatelessWidget {
  final Duration duration;
  final Duration targetDuration;
  
  const SleepDurationDisplay({
    Key? key,
    required this.duration,
    required this.targetDuration,
  }) : super(key: key);
  
  
  Widget build(BuildContext context) {
    int hours = duration.inHours;
    int minutes = duration.inMinutes % 60;
    double progress = duration.inMinutes / targetDuration.inMinutes;
    
    return Container(
      padding: EdgeInsets.all(24),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Color(0xFF1a237e), Color(0xFF3949ab)],
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
        ),
        borderRadius: BorderRadius.circular(20),
      ),
      child: Column(
        children: [
          Icon(Icons.nightlight_round, color: Colors.yellow, size: 48),
          SizedBox(height: 16),
          Text('${hours}小时${minutes}分钟', style: TextStyle(fontSize: 32, color: Colors.white, fontWeight: FontWeight.bold)),
          SizedBox(height: 8),
          LinearProgressIndicator(value: progress.clamp(0.0, 1.0), backgroundColor: Colors.white24, valueColor: AlwaysStoppedAnimation(Colors.yellow)),
          SizedBox(height: 8),
          Text('目标: ${targetDuration.inHours}小时', style: TextStyle(color: Colors.white70)),
        ],
      ),
    );
  }
}

睡眠时长显示组件以醒目的方式展示用户的睡眠时长。我们使用深蓝色渐变背景营造夜晚的氛围,月亮图标强化睡眠主题。中央大字体显示睡眠时长,格式为"X小时X分钟",比纯数字更易理解。进度条显示相对于目标睡眠时长的完成度,成年人推荐的睡眠时长为7-9小时。黄色的进度条和图标在深蓝背景上形成鲜明对比,视觉效果突出。这种设计让用户一眼就能了解自己的睡眠是否充足。

OpenHarmony睡眠数据存储

import relationalStore from '@ohos.data.relationalStore';

class SleepDataStorage {
  private rdbStore: relationalStore.RdbStore | null = null;
  
  async initDatabase(context: Context): Promise<void> {
    const config: relationalStore.StoreConfig = {
      name: 'sleep.db',
      securityLevel: relationalStore.SecurityLevel.S1,
    };
    this.rdbStore = await relationalStore.getRdbStore(context, config);
    
    await this.rdbStore.executeSql(
      'CREATE TABLE IF NOT EXISTS sleep_records (id INTEGER PRIMARY KEY AUTOINCREMENT, bed_time INTEGER, wake_time INTEGER, quality_score INTEGER, date TEXT)'
    );
  }
  
  async saveSleepRecord(bedTime: number, wakeTime: number, score: number): Promise<void> {
    if (this.rdbStore) {
      let date = new Date(wakeTime).toISOString().split('T')[0];
      let valueBucket = {
        'bed_time': bedTime,
        'wake_time': wakeTime,
        'quality_score': score,
        'date': date,
      };
      await this.rdbStore.insert('sleep_records', valueBucket);
    }
  }
}

睡眠数据需要持久化存储以支持历史分析和趋势展示。我们使用关系型数据库存储睡眠记录,表结构包含入睡时间戳、醒来时间戳、质量评分和日期字段。时间使用时间戳格式存储,便于计算和比较。date字段存储日期字符串,便于按天查询。通过数据库存储,我们可以查询任意时间段的睡眠数据,计算平均睡眠时长,分析睡眠规律,为用户提供有价值的睡眠洞察和改善建议。

Flutter睡眠阶段图表

class SleepStageChart extends StatelessWidget {
  final List<SleepStage> stages;
  
  const SleepStageChart({Key? key, required this.stages}) : super(key: key);
  
  
  Widget build(BuildContext context) {
    return Container(
      height: 120,
      child: CustomPaint(
        size: Size(double.infinity, 120),
        painter: SleepStagePainter(stages: stages),
      ),
    );
  }
}

class SleepStagePainter extends CustomPainter {
  final List<SleepStage> stages;
  
  SleepStagePainter({required this.stages});
  
  
  void paint(Canvas canvas, Size size) {
    if (stages.isEmpty) return;
    
    double totalMinutes = stages.fold(0.0, (sum, s) => sum + s.duration.inMinutes);
    double xOffset = 0;
    
    for (var stage in stages) {
      double width = (stage.duration.inMinutes / totalMinutes) * size.width;
      double height = _getHeightForType(stage.type, size.height);
      double yOffset = size.height - height;
      
      Paint paint = Paint()..color = stage.typeColor;
      canvas.drawRect(Rect.fromLTWH(xOffset, yOffset, width, height), paint);
      xOffset += width;
    }
  }
  
  double _getHeightForType(SleepStageType type, double maxHeight) {
    switch (type) {
      case SleepStageType.awake: return maxHeight * 0.25;
      case SleepStageType.rem: return maxHeight * 0.5;
      case SleepStageType.light: return maxHeight * 0.75;
      case SleepStageType.deep: return maxHeight;
    }
  }
  
  
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

睡眠阶段图表以可视化方式展示整晚的睡眠结构。我们使用CustomPaint绑制自定义图表,横轴表示时间,纵轴表示睡眠深度。每个睡眠阶段用不同颜色的矩形表示,宽度与持续时间成正比,高度与睡眠深度相关。深睡阶段显示在最底部(高度最大),清醒阶段显示在最顶部(高度最小)。这种设计类似于专业睡眠监测设备的输出,让用户直观地看到睡眠周期的变化,了解自己的睡眠结构是否健康。

Flutter睡眠质量评分组件

class SleepQualityScore extends StatelessWidget {
  final int score;
  
  const SleepQualityScore({Key? key, required this.score}) : super(key: key);
  
  String _getQualityLabel() {
    if (score >= 80) return '优秀';
    if (score >= 60) return '良好';
    if (score >= 40) return '一般';
    return '较差';
  }
  
  Color _getScoreColor() {
    if (score >= 80) return Colors.green;
    if (score >= 60) return Colors.lightGreen;
    if (score >= 40) return Colors.orange;
    return Colors.red;
  }
  
  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          Stack(
            alignment: Alignment.center,
            children: [
              SizedBox(
                width: 120,
                height: 120,
                child: CircularProgressIndicator(
                  value: score / 100,
                  strokeWidth: 10,
                  backgroundColor: Colors.grey[200],
                  valueColor: AlwaysStoppedAnimation(_getScoreColor()),
                ),
              ),
              Column(
                children: [
                  Text('$score', style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold)),
                  Text(_getQualityLabel(), style: TextStyle(color: Colors.grey)),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  }
}

睡眠质量评分组件将复杂的睡眠数据简化为一个直观的分数。我们使用0-100的评分体系,并将分数划分为四个等级:优秀、良好、一般和较差。不同等级使用不同的颜色标识,绿色表示优秀,红色表示较差,形成直观的视觉反馈。圆形进度环显示分数的百分比,中央显示具体分数和等级标签。这种设计让用户无需理解复杂的睡眠指标,通过一个简单的分数就能了解自己的睡眠质量,并与之前的记录进行比较。

OpenHarmony睡眠提醒服务

import reminderAgentManager from '@ohos.reminderAgentManager';

class SleepReminderService {
  async setBedtimeReminder(hour: number, minute: number): Promise<number> {
    let reminderRequest: reminderAgentManager.ReminderRequestAlarm = {
      reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM,
      hour: hour,
      minute: minute,
      daysOfWeek: [1, 2, 3, 4, 5, 6, 7],
      title: '睡眠提醒',
      content: '该休息了,保持规律作息有助于提高睡眠质量',
      ringDuration: 30,
      snoozeTimes: 1,
      snoozeInterval: 5,
    };
    
    let reminderId = await reminderAgentManager.publishReminder(reminderRequest);
    return reminderId;
  }
  
  async cancelReminder(reminderId: number): Promise<void> {
    await reminderAgentManager.cancelReminder(reminderId);
  }
}

睡眠提醒帮助用户建立规律的作息习惯。OpenHarmony的reminderAgentManager模块提供了系统级的提醒功能,即使应用未运行也能准时提醒。我们创建闹钟类型的提醒,设置每天固定时间触发。daysOfWeek设置为1-7表示每天都提醒,用户也可以只选择工作日。ringDuration设置提醒铃声时长,snoozeTimes和snoozeInterval设置贪睡次数和间隔。通过这种提醒机制,用户可以养成固定时间上床的习惯,这是改善睡眠质量的重要因素。

Flutter睡眠趋势分析

class SleepTrendAnalysis extends StatelessWidget {
  final List<SleepRecord> weeklyRecords;
  
  const SleepTrendAnalysis({Key? key, required this.weeklyRecords}) : super(key: key);
  
  
  Widget build(BuildContext context) {
    double avgDuration = weeklyRecords.isEmpty ? 0 :
        weeklyRecords.map((r) => r.totalDuration.inMinutes).reduce((a, b) => a + b) / weeklyRecords.length;
    double avgScore = weeklyRecords.isEmpty ? 0 :
        weeklyRecords.map((r) => r.qualityScore).reduce((a, b) => a + b) / weeklyRecords.length;
    
    return Card(
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('本周睡眠分析', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                _buildStatItem('平均时长', '${(avgDuration / 60).toStringAsFixed(1)}小时'),
                _buildStatItem('平均评分', '${avgScore.toStringAsFixed(0)}分'),
                _buildStatItem('记录天数', '${weeklyRecords.length}天'),
              ],
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildStatItem(String label, String value) {
    return Column(
      children: [
        Text(value, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.indigo)),
        Text(label, style: TextStyle(color: Colors.grey)),
      ],
    );
  }
}

睡眠趋势分析帮助用户了解一段时间内的睡眠模式。我们计算一周内的平均睡眠时长和平均质量评分,这些指标比单日数据更能反映真实的睡眠状况。记录天数显示用户的使用频率,鼓励用户坚持记录。通过对比不同周的数据,用户可以发现自己的睡眠是在改善还是恶化,从而调整生活习惯。这种分析功能将零散的睡眠数据转化为有意义的洞察,帮助用户做出改善睡眠的决策。

总结

本文全面介绍了Flutter与OpenHarmony平台上睡眠监测组件的实现方案。从睡眠数据模型到传感器检测,从阶段分析到质量评分,从数据存储到趋势分析,涵盖了睡眠监测功能的各个方面。通过科学的算法和直观的界面设计,我们可以为用户提供有价值的睡眠洞察,帮助他们改善睡眠质量,从而提升运动表现和整体健康水平。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐