699 lines
23 KiB
C
699 lines
23 KiB
C
/*
|
||
* @Description:
|
||
* @Version: 1.0
|
||
* @Author: lzc
|
||
* @Date: 2023-02-14 14:46:56
|
||
* @LastEditors: lzc
|
||
* @LastEditTime: 2023-12-13 12:57:41
|
||
*/
|
||
#include <stdio.h>
|
||
#include "sleepReport.h"
|
||
sleepReport_t sleepReport;
|
||
|
||
extern warning_config_t warning_config;
|
||
extern char MovementBuffer[REPORT_BUFFER_MAX]; // 12小时的体动数据__attribute__((at(0x080E0000)))
|
||
extern char HeartRateBuffer[REPORT_BUFFER_MAX]; // 12小时的心率数据 __attribute__((at(0x080E0000 + (0x400))))
|
||
extern char BreathRateBuffer[REPORT_BUFFER_MAX];
|
||
extern char sleepStatusBuffer[REPORT_BUFFER_MAX]; // 12小时的睡眠阶段数据__attribute__((at(0x080E0000 + (0x800))))
|
||
extern char sleepTempBuffer[REPORT_BUFFER_MAX + 20];
|
||
// 睡眠得分的分支
|
||
float ReportScore_G1 = 0.0f;
|
||
float ReportScore_G2 = 0.0f;
|
||
// 睡眠得分拟合系数
|
||
float sleepTimeParas[5][2] = {
|
||
{-1.37169382, 17.32667718}, // 当x < 3: 处于婴幼儿时期时
|
||
{-0.13367955, 11.87384112}, // 当 x >= 3且 x < 12处于儿童期
|
||
{-0.13197821, 11.7037808}, // 当x >= 12且 x < 19处于青少年
|
||
{-0.03604769, 9.77795514}, // 当x >= 19且 x < 60处于成人时期
|
||
{-0.06062882, 11.41229097}}; // 当x >= 60处于老年期
|
||
|
||
/**
|
||
* @function: GetValue_MaxMin
|
||
* @brief: 二分法求最大最小值
|
||
* @param {float} a
|
||
* @param {int} i
|
||
* @param {int} j
|
||
* @param {char} *fmax
|
||
* @param {char} *fmin
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
// void GetValue_MaxMin(char a[], int i, int j, char *fmax, char *fmin)
|
||
// {
|
||
// int mid;
|
||
// char l_max, l_min, r_max, r_min;
|
||
// if (i == j)
|
||
// {
|
||
// *fmax = a[i];
|
||
// *fmin = a[j];
|
||
// return;
|
||
// }
|
||
// else if (i == j - 1)
|
||
// {
|
||
// if (a[i] > a[j])
|
||
// {
|
||
// *fmax = a[i];
|
||
// *fmin = a[j];
|
||
// }
|
||
// else
|
||
// {
|
||
// *fmax = a[j];
|
||
// *fmin = a[i];
|
||
// }
|
||
// return;
|
||
// }
|
||
// else
|
||
// {
|
||
// mid = (j - i) / 2 + i;
|
||
// GetValue_MaxMin(a, i, mid, &l_max, &l_min);
|
||
// GetValue_MaxMin(a, mid + 1, j, &r_max, &r_min);
|
||
// if (l_max > r_max)
|
||
// *fmax = l_max;
|
||
// else
|
||
// *fmax = r_max;
|
||
// if (l_min < r_min)
|
||
// *fmin = l_min;
|
||
// else
|
||
// *fmin = r_min;
|
||
// }
|
||
// return;
|
||
// }
|
||
|
||
/**
|
||
* @function: GetValue_MaxMin
|
||
* @brief: 遍历法求最大最小值
|
||
* @param {float} a
|
||
* @param {int} i
|
||
* @param {int} j
|
||
* @param {char} *fmax
|
||
* @param {char} *fmin
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void GetValue_MaxMin(char a[], int i, int j, char *fmax, char *fmin)
|
||
{
|
||
*fmax = a[i];
|
||
*fmin = a[i];
|
||
|
||
int length = 0;
|
||
for (length = i; length < j; length++)
|
||
{
|
||
if (a[length] > *fmax)
|
||
{
|
||
*fmax = a[length];
|
||
}
|
||
else if (a[length] < *fmin)
|
||
{
|
||
*fmin = a[length];
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @function: GetValue_Avg
|
||
* @brief: 获取非0平均值
|
||
* @param {char} a
|
||
* @param {int} i
|
||
* @param {int} j
|
||
* @param {float} *avg
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void GetValue_NoneZero_Avg(char a[], int length, float *avg)
|
||
{
|
||
uint64_t Sum_Value = 0;
|
||
uint64_t SleepNum = 0;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
for (int i = 0; i < REPORT_BUFFER_MAX; i++)
|
||
{
|
||
if (a[i] != 0)
|
||
{
|
||
sleepTempBuffer[SleepNum] = a[i];
|
||
SleepNum++;
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < SleepNum; i++)
|
||
{
|
||
Sum_Value += sleepTempBuffer[i];
|
||
}
|
||
*avg = Sum_Value / (float)SleepNum;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @function: GetValue_Avg
|
||
* @brief: 获取平均值
|
||
* @param {char} a
|
||
* @param {int} i
|
||
* @param {int} j
|
||
* @param {float} *avg
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void GetValue_Avg(char a[], int length, float *avg)
|
||
{
|
||
uint64_t Sum_Value = 0;
|
||
for (int i = 0; i < length; i++)
|
||
{
|
||
Sum_Value += a[i];
|
||
}
|
||
*avg = Sum_Value / (float)length;
|
||
return;
|
||
}
|
||
/**
|
||
* @function: SleepReportScore
|
||
* @brief: None
|
||
* @return {float} 睡眠得分
|
||
* @author: lzc
|
||
*/
|
||
float SleepReportScore(char age)
|
||
{
|
||
float paras_P0 = 0.0f;
|
||
float paras_P1 = 0.0f;
|
||
float paras_P2 = 0.0f;
|
||
float reportSleepHour = 0.0f;
|
||
float humanNeedSleepTime = 0.0f;
|
||
if (age < 3)
|
||
{
|
||
paras_P0 = sleepTimeParas[0][0];
|
||
paras_P1 = sleepTimeParas[0][1];
|
||
}
|
||
else if (age >= 3 && age < 12)
|
||
{
|
||
paras_P0 = sleepTimeParas[1][0];
|
||
paras_P1 = sleepTimeParas[1][1];
|
||
}
|
||
else if (age >= 12 && age < 19)
|
||
{
|
||
paras_P0 = sleepTimeParas[2][0];
|
||
paras_P1 = sleepTimeParas[2][1];
|
||
}
|
||
else if (age >= 19 && age < 60)
|
||
{
|
||
paras_P0 = sleepTimeParas[3][0];
|
||
paras_P1 = sleepTimeParas[3][1];
|
||
}
|
||
else if (age >= 60)
|
||
{
|
||
paras_P0 = sleepTimeParas[4][0];
|
||
paras_P1 = sleepTimeParas[4][1];
|
||
}
|
||
else
|
||
{
|
||
age = 24;
|
||
paras_P0 = sleepTimeParas[3][0];
|
||
paras_P1 = sleepTimeParas[3][1];
|
||
}
|
||
// 计算睡眠得分
|
||
if (sleepReport.SleepSumTime > 0 && sleepReport.DeepSleepTime > 0)
|
||
{
|
||
reportSleepHour = (sleepReport.SleepSumTime / 60);
|
||
printf("!!!!!!!!Sleep report Hour: %f\n", reportSleepHour);
|
||
printf("!!!!!!!!Sleep SleepSumTime : %d\n", sleepReport.SleepSumTime);
|
||
|
||
humanNeedSleepTime = (paras_P0 * age + paras_P1);
|
||
if (humanNeedSleepTime <= 1) // 防止错误数据导致全部都是100分
|
||
humanNeedSleepTime = 8.0f;
|
||
printf("!!!!!!!!Age :%d Sleep Need Hour: %f\n", age, humanNeedSleepTime);
|
||
|
||
paras_P2 = (reportSleepHour / humanNeedSleepTime);
|
||
printf("!!!!!!!!Sleep Score P1: %f\n", paras_P2);
|
||
|
||
ReportScore_G1 = 50 * paras_P2;
|
||
printf("!!!!!!!!Sleep Score G1: %f\n", ReportScore_G1);
|
||
|
||
if ((sleepReport.DeepSleepTime) / (sleepReport.SleepSumTime) >= 0.25f)
|
||
ReportScore_G2 = 50;
|
||
else
|
||
ReportScore_G2 = 4 * 50 * ((sleepReport.DeepSleepTime) / (sleepReport.SleepSumTime));
|
||
printf("!!!!!!!!Sleep Score G2: %f\n", ReportScore_G2);
|
||
sleepReport.SleepScore = ReportScore_G1 + ReportScore_G2;
|
||
// 给一个上下限
|
||
if (sleepReport.SleepScore >= 100)
|
||
sleepReport.SleepScore = 100;
|
||
else if (sleepReport.SleepScore <= 0)
|
||
sleepReport.SleepScore = 10;
|
||
return sleepReport.SleepScore;
|
||
}
|
||
else
|
||
return 60;
|
||
}
|
||
/**
|
||
* @function: SleepReportEfficiency
|
||
* @brief: None
|
||
* @return {float} 睡眠效率
|
||
* @author: lzc
|
||
*/
|
||
float SleepReportEfficiency(void)
|
||
{
|
||
// 计算睡眠效率 在床时间(20:00之后开始计算)
|
||
if (sleepReport.InBedSumMinute > 0 && sleepReport.SleepSumTime > 0)
|
||
{
|
||
printf("\r\n!!!!!!!!SleepSumTime :%d \r\n", sleepReport.SleepSumTime);
|
||
printf("\r\n!!!!!!!!InBedSumMinute :%d \r\n", sleepReport.InBedSumMinute);
|
||
printf("\r\n!!!!!!!!SleepReportEfficiency :%f \r\n", ((float)sleepReport.SleepSumTime / (float)sleepReport.InBedSumMinute));
|
||
return ((float)sleepReport.SleepSumTime / (float)sleepReport.InBedSumMinute);
|
||
}
|
||
else
|
||
return 60;
|
||
}
|
||
/**
|
||
* @function: SleepReportUpload
|
||
* @brief: 睡眠报告转HEX包上传
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
extern float Local_ON_BED_Threshold;
|
||
extern float Local_OFF_BED_Threshold;
|
||
void SleepReportUpload(uint16_t SleepLength)
|
||
{
|
||
char UploadMsg[33] = {0};
|
||
// 帧头
|
||
UploadMsg[0] = 0xA5;
|
||
UploadMsg[1] = 0x5A;
|
||
// 长度
|
||
UploadMsg[2] = 21;
|
||
UploadMsg[3] = 0x00;
|
||
// 帧类型
|
||
UploadMsg[4] = 0x1D;
|
||
// 时间戳
|
||
memcpy(&UploadMsg[5], &sleepReport.Asleep_TimeStamp, sizeof(sleepReport.Asleep_TimeStamp));
|
||
// 在床持续总时间
|
||
UploadMsg[13] = SleepLength >> 8;
|
||
UploadMsg[14] = SleepLength & 0xff;
|
||
// 得分
|
||
UploadMsg[15] = sleepReport.SleepScore;
|
||
// 效率
|
||
UploadMsg[16] = sleepReport.SleepEfficiency * 100;
|
||
// 心率最大值
|
||
UploadMsg[17] = sleepReport.max_heartbeat;
|
||
// 心率最小值
|
||
UploadMsg[18] = sleepReport.min_heartbeat;
|
||
// 呼吸最大值
|
||
UploadMsg[19] = sleepReport.max_breath;
|
||
// 呼吸最小值
|
||
UploadMsg[20] = sleepReport.min_breath;
|
||
// 翻身次数
|
||
UploadMsg[21] = sleepReport.roll_over;
|
||
// 平均心率
|
||
UploadMsg[22] = sleepReport.heartbeat_avg;
|
||
// 平均呼吸
|
||
UploadMsg[23] = sleepReport.breath_avg;
|
||
// 时区
|
||
UploadMsg[24] = warning_config.timeZone;
|
||
// 在床阈值
|
||
memcpy(&UploadMsg[25], &Local_ON_BED_Threshold, sizeof(Local_ON_BED_Threshold));
|
||
// 离床阈值
|
||
memcpy(&UploadMsg[29], &Local_OFF_BED_Threshold, sizeof(Local_OFF_BED_Threshold));
|
||
// 发送睡眠得分以及效率
|
||
wifi_crc_send((uint8_t *)UploadMsg, sizeof(UploadMsg));
|
||
}
|
||
|
||
/**
|
||
* @function: SleepStageDetailUpload
|
||
* @brief: 睡眠阶段上报
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void SleepStageDetailUpload(int StageLength)
|
||
{
|
||
int MsgLength = 0;
|
||
uint8_t *my_puts = NULL;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
printf("\r\n ~~~~~~~Stage~~~~~ %d\r\n", StageLength);
|
||
// 总长度
|
||
MsgLength = ((StageLength) + 15) - 4;
|
||
// 帧头
|
||
sleepTempBuffer[0] = 0xA5;
|
||
sleepTempBuffer[1] = 0x5A;
|
||
// 长度
|
||
sleepTempBuffer[2] = MsgLength & 0xff;
|
||
sleepTempBuffer[3] = MsgLength >> 8;
|
||
// 帧类型
|
||
sleepTempBuffer[4] = 0x2A;
|
||
// 入睡时间戳
|
||
memcpy(&sleepTempBuffer[5], &sleepReport.Asleep_TimeStamp, sizeof(sleepReport.Asleep_TimeStamp));
|
||
// 睡眠阶段长度
|
||
sleepTempBuffer[13] = StageLength & 0xff;
|
||
sleepTempBuffer[14] = StageLength >> 8;
|
||
// 睡眠阶段
|
||
memcpy(sleepTempBuffer + 15, sleepStatusBuffer, StageLength);
|
||
for (int i = 0; i < StageLength + 15; i++)
|
||
{
|
||
printf(" %x ", sleepTempBuffer[i]);
|
||
}
|
||
// 发送睡眠得分以及效率
|
||
wifi_crc_send((uint8_t *)sleepTempBuffer, (StageLength) + 15);
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
}
|
||
|
||
/**
|
||
* @function: SleepStageDetailUpload
|
||
* @brief: 心率曲线上报
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void SleepHeartWaveUpload(int StageLength)
|
||
{
|
||
int MsgLength = 0;
|
||
uint8_t *my_puts = NULL;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
printf(" \r\n~~~~~~ Heart ~~~~~~~ %d\r\n", StageLength);
|
||
// 总长度
|
||
MsgLength = ((StageLength) + 15) - 4;
|
||
// 帧头
|
||
sleepTempBuffer[0] = 0xA5;
|
||
sleepTempBuffer[1] = 0x5A;
|
||
// 长度
|
||
sleepTempBuffer[2] = MsgLength & 0xff;
|
||
sleepTempBuffer[3] = MsgLength >> 8;
|
||
// 帧类型
|
||
sleepTempBuffer[4] = 0x2B;
|
||
// 入睡时间戳
|
||
memcpy(&sleepTempBuffer[5], &sleepReport.Asleep_TimeStamp, sizeof(sleepReport.Asleep_TimeStamp));
|
||
// 睡眠阶段长度
|
||
sleepTempBuffer[13] = StageLength & 0xff;
|
||
sleepTempBuffer[14] = StageLength >> 8;
|
||
// 睡眠阶段
|
||
memcpy(sleepTempBuffer + 15, HeartRateBuffer, StageLength);
|
||
for (int i = 0; i < StageLength + 15; i++)
|
||
{
|
||
printf(" %x ", sleepTempBuffer[i]);
|
||
}
|
||
// 发送睡眠得分以及效率
|
||
wifi_crc_send((uint8_t *)sleepTempBuffer, (StageLength) + 15);
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
}
|
||
|
||
/**
|
||
* @function: SleepBreathWaveUpload
|
||
* @brief: 呼吸曲线上报
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void SleepBreathWaveUpload(int StageLength)
|
||
{
|
||
int MsgLength = 0;
|
||
uint8_t *my_puts = NULL;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
printf(" \r\n~~~~~~ Breath ~~~~ %d\r\n", StageLength);
|
||
// 总长度
|
||
MsgLength = ((StageLength) + 15) - 4;
|
||
// 帧头
|
||
sleepTempBuffer[0] = 0xA5;
|
||
sleepTempBuffer[1] = 0x5A;
|
||
// 长度
|
||
sleepTempBuffer[2] = MsgLength & 0xff;
|
||
sleepTempBuffer[3] = MsgLength >> 8;
|
||
// 帧类型
|
||
sleepTempBuffer[4] = 0x2C;
|
||
// 入睡时间戳
|
||
memcpy(&sleepTempBuffer[5], &sleepReport.Asleep_TimeStamp, sizeof(sleepReport.Asleep_TimeStamp));
|
||
// 睡眠阶段长度
|
||
sleepTempBuffer[13] = StageLength & 0xff;
|
||
sleepTempBuffer[14] = StageLength >> 8;
|
||
// 睡眠阶段
|
||
memcpy(sleepTempBuffer + 15, BreathRateBuffer, StageLength);
|
||
for (int i = 0; i < StageLength + 15; i++)
|
||
{
|
||
printf(" %x ", sleepTempBuffer[i]);
|
||
}
|
||
wifi_crc_send((uint8_t *)sleepTempBuffer, (StageLength) + 15);
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
}
|
||
/**
|
||
* @function: SleepReportGenerate
|
||
* @brief: None
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
extern uint64_t InBedTimeStamp;
|
||
extern warning_config_t warning_config;
|
||
void SleepReportGenerate(uint64_t AwayFromBed_TimeStamp, uint16_t CountNum, char Resend) // 离床时间戳
|
||
{
|
||
uint16_t s_rem_cnt = 0; // REM计时
|
||
uint16_t s_sleep_cnt = 0; // 睡眠计时
|
||
uint16_t s_deep_cnt = 0; // 深度睡眠计时
|
||
uint16_t s_SleepSumTime = 0; // 实际睡眠总时长
|
||
uint16_t mySleepNum = 0;
|
||
// 清除睡眠报告 确保数据为0
|
||
memset(&sleepReport, 0, sizeof(sleepReport));
|
||
// 获取平均
|
||
GetValue_Avg(MovementBuffer, CountNum, &sleepReport.move_avg);
|
||
GetValue_NoneZero_Avg(BreathRateBuffer, CountNum, &sleepReport.breath_avg);
|
||
GetValue_NoneZero_Avg(HeartRateBuffer, CountNum, &sleepReport.heartbeat_avg);
|
||
for (int i = 0; i < CountNum; i++)
|
||
{
|
||
// 有体动 + 不是离床状态
|
||
if (MovementBuffer[i] != 0 && MovementBuffer[i] != 0xff)
|
||
{
|
||
if (sleepReport.body_move_cnt == 0)
|
||
sleepReport.body_move_sum = 0;
|
||
sleepReport.body_move_cnt++;
|
||
sleepReport.non_body_move_cnt = 0;
|
||
sleepReport.body_move_sum = sleepReport.body_move_sum + MovementBuffer[i];
|
||
sleepReport.body_move_avg = sleepReport.body_move_sum / sleepReport.body_move_cnt;
|
||
}
|
||
else
|
||
{
|
||
sleepReport.body_move_cnt = 0;
|
||
sleepReport.non_body_move_cnt++;
|
||
sleepReport.body_move_avg = sleepReport.body_move_sum / sleepReport.non_body_move_cnt;
|
||
}
|
||
// 如果体动达到标准,状态变为清醒状态
|
||
if ((sleepReport.body_move_cnt >= ANA_MOVE_CNT_WAKE) && (sleepReport.body_move_avg >= ANA_INT_MOVE_WAKE))
|
||
{
|
||
sleepReport.SleepState = SLEEP_PHASE_WAKE;
|
||
if (sleepReport.SleepWakeFlag == 0)
|
||
{
|
||
sleepReport.SleepWakeFlag = 1;
|
||
}
|
||
}
|
||
sleepReport.MinuteTime_cnt += 1;
|
||
// 如果睡眠阶段的状态是清醒状态
|
||
if ((sleepReport.SleepState == SLEEP_PHASE_WAKE))
|
||
{
|
||
// 如果之前是清醒状态
|
||
if (sleepReport.SleepWakeFlag == 1)
|
||
{
|
||
// 如果无体动到达一定程度或者心率小于平均值同时时间到达一定程度
|
||
if ((sleepReport.non_body_move_cnt >= ANA_MOVE_DELAY_SLEEP) ||
|
||
((HeartRateBuffer[i] < sleepReport.heartbeat_avg) &&
|
||
(sleepReport.MinuteTime_cnt > ANA_START_WAKE_TO_SLEEP_TIME)))
|
||
sleepReport.SleepState = SLEEP_PHASE_SLEEP; // 睡眠阶段sleep时期的判断
|
||
}
|
||
// 之前不是清醒状态,无体动到达一定程度同时平均体动小于阈值
|
||
else if ((sleepReport.non_body_move_cnt >= ANA_WAKE_TO_SLEEP_TIME) &&
|
||
(sleepReport.move_avg <= ANA_INT_MOVE_SLEEP))
|
||
{
|
||
sleepReport.SleepState = SLEEP_PHASE_SLEEP;
|
||
} // 睡眠阶段sleep时期的判断
|
||
sleepReport.wakeTime_cnt += 1; // 清醒 时间计数增加
|
||
sleepReport.sleep_delay = 0; // 浅睡转换时间
|
||
}
|
||
// 如果睡眠阶段的状态是浅睡状态
|
||
else if (sleepReport.SleepState == SLEEP_PHASE_SLEEP)
|
||
{
|
||
// 如果是浅睡阶段,增加浅睡状态转换时间的计数
|
||
sleepReport.sleep_delay += 1; // sleep_Delay不知道反映什么意思
|
||
// 无体动计数到一定程度同时心率小于平均浅睡心率同时浅睡转换时间大于阈值
|
||
if ((sleepReport.non_body_move_cnt >= ANA_MOVE_DELAY_DEEP) &&
|
||
(HeartRateBuffer[i] <= (sleepReport.heartbeat_avg + ANA_DEEP_SLEEP_HEART_OFFSET)) &&
|
||
(sleepReport.sleep_delay >= ANA_DELAY_SLEEP_TO_DEEP))
|
||
{
|
||
sleepReport.SleepState = SLEEP_PHASE_DEEP; // 睡眠阶段deep sleep 深睡时期的判断
|
||
sleepReport.SleepWakeFlag = 0;
|
||
sleepReport.sleep_delay = 0;
|
||
}
|
||
}
|
||
// 如果睡眠阶段的状态是深度睡眠状态
|
||
else if (sleepReport.SleepState == SLEEP_PHASE_DEEP)
|
||
{
|
||
if (sleepReport.body_move_cnt > 1)
|
||
sleepReport.SleepState = SLEEP_PHASE_SLEEP;
|
||
sleepReport.deep_delay += 1;
|
||
if (HeartRateBuffer[i] >= (sleepReport.heartbeat_avg + ANA_REM_HEART_OFFSET) &&
|
||
(sleepReport.deep_delay >= ANA_DELAY_DEEP_TO_REM))
|
||
{
|
||
sleepReport.SleepState = SLEEP_PHASE_REM; // 睡眠阶段眼动时期的判断
|
||
sleepReport.deep_delay = 0;
|
||
}
|
||
}
|
||
// 如果睡眠阶段的状态是眼动状态
|
||
else if (sleepReport.SleepState == SLEEP_PHASE_REM)
|
||
{
|
||
if (sleepReport.body_move_cnt > 1)
|
||
sleepReport.SleepState = SLEEP_PHASE_SLEEP;
|
||
if (HeartRateBuffer[i] <= (sleepReport.heartbeat_avg - ANA_REM_HEART_OFFSET))
|
||
sleepReport.SleepState = SLEEP_PHASE_DEEP; // #睡眠阶段deep sleep 深睡时期的判断
|
||
}
|
||
else
|
||
sleepReport.SleepState = SLEEP_PHASE_WAKE; // 睡眠阶段wake 时期的判断
|
||
// 睡眠状态保存,夜间离床的计算
|
||
if (MovementBuffer[i] == 0 && HeartRateBuffer[i] == 0 && BreathRateBuffer[i] == 0)
|
||
{
|
||
sleepStatusBuffer[i] = (char)SLEEP_PHASE_AWAY;
|
||
}
|
||
else
|
||
sleepStatusBuffer[i] = sleepReport.SleepState;
|
||
}
|
||
// 获取计数值
|
||
for (int i = 0; i < CountNum; i++)
|
||
{
|
||
switch (sleepStatusBuffer[i])
|
||
{
|
||
case SLEEP_PHASE_SLEEP:
|
||
s_sleep_cnt++;
|
||
break;
|
||
case SLEEP_PHASE_REM:
|
||
s_rem_cnt++;
|
||
break;
|
||
case SLEEP_PHASE_DEEP:
|
||
s_deep_cnt++;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
s_SleepSumTime = s_rem_cnt + s_deep_cnt + s_sleep_cnt;
|
||
// 其他数据的计算
|
||
sleepReport.InBedSumMinute = CountNum;
|
||
sleepReport.DeepSleepTime = s_deep_cnt;
|
||
sleepReport.SleepSumTime = s_SleepSumTime;
|
||
// 翻身次数
|
||
sleepReport.roll_over = Roll_Over_Count;
|
||
// 得分 和 效率 最低60
|
||
sleepReport.SleepScore = SleepReportScore(warning_config.age);
|
||
sleepReport.SleepEfficiency = SleepReportEfficiency();
|
||
// 最大 最小 值
|
||
mySleepNum = 0;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
printf("\r\n------------------------ VALUE ------------------------------\r\n");
|
||
for (int i = 0; i < REPORT_BUFFER_MAX; i++)
|
||
{
|
||
if (BreathRateBuffer[i] != 0)
|
||
{
|
||
sleepTempBuffer[mySleepNum] = BreathRateBuffer[i];
|
||
mySleepNum++;
|
||
}
|
||
}
|
||
for (int i = 0; i < mySleepNum; i++)
|
||
{
|
||
printf(", %d ", sleepTempBuffer[i]);
|
||
}
|
||
printf("\r\n---------------------------%d---------------------------------\r\n", mySleepNum);
|
||
GetValue_MaxMin(sleepTempBuffer, 0, mySleepNum, &sleepReport.max_breath, &sleepReport.min_breath);
|
||
|
||
mySleepNum = 0;
|
||
memset(sleepTempBuffer, 0, sizeof(sleepTempBuffer));
|
||
printf("\r\n------------------------ VALUE ------------------------------\r\n");
|
||
for (int i = 0; i < REPORT_BUFFER_MAX; i++)
|
||
{
|
||
if (HeartRateBuffer[i] != 0)
|
||
{
|
||
sleepTempBuffer[mySleepNum] = HeartRateBuffer[i];
|
||
mySleepNum++;
|
||
}
|
||
}
|
||
for (int i = 0; i < mySleepNum; i++)
|
||
{
|
||
printf(", %d ", sleepTempBuffer[i]);
|
||
}
|
||
printf("\r\n---------------------------%d---------------------------------\r\n", mySleepNum);
|
||
GetValue_MaxMin(sleepTempBuffer, 0, mySleepNum, &sleepReport.max_heartbeat, &sleepReport.min_heartbeat);
|
||
// 时间戳
|
||
sleepReport.AwayBed_TimeStamp = AwayFromBed_TimeStamp; // 离床时间戳
|
||
// sleepReport.InBed_TimeStamp = sleepReport.AwayBed_TimeStamp - (sleepReport.InBedSumMinute * 60 * 1000); // 在床时间戳 = 离床时间戳 - 在床时间
|
||
sleepReport.InBed_TimeStamp = InBedTimeStamp;
|
||
sleepReport.Asleep_TimeStamp = sleepReport.InBed_TimeStamp; // 现在版本入睡 = 在床
|
||
sleepReport.AsleepAddZone_TimeStamp = sleepReport.Asleep_TimeStamp +
|
||
((signed char)warning_config.timeZone) * 60 * 60 * 1000; // 增加时区的
|
||
printf("\r\n----------------------sleepReport--------------------------\r\n");
|
||
printf("CountNum %d\r\n", CountNum);
|
||
printf("sleepReport.sleep_cnt %d\r\n", s_sleep_cnt);
|
||
printf("sleepReport.deep_cnt %d\r\n", s_deep_cnt);
|
||
printf("sleepReport.rem_cnt %d\r\n", s_rem_cnt);
|
||
printf("sleepReport.score: %f\r\n", sleepReport.SleepScore);
|
||
printf("sleepReport.roll_over %d\r\n", sleepReport.roll_over);
|
||
printf("sleepReport.eff: %f\r\n", sleepReport.SleepEfficiency);
|
||
printf("sleepReport.InBed_TimeStamp: %lld\r\n", sleepReport.InBed_TimeStamp);
|
||
printf("sleepReport.Asleep_TimeStamp: %lld\r\n", sleepReport.Asleep_TimeStamp);
|
||
printf("sleepReport.AwayBed_TimeStamp: %lld\r\n", sleepReport.AwayBed_TimeStamp);
|
||
printf("sleepReport.AsleepAddZone_TimeStamp: %lld\r\n", sleepReport.AsleepAddZone_TimeStamp);
|
||
printf("sleepReport.max_breath: %d , sleepReport.min_breath: %d\r\n", sleepReport.max_breath, sleepReport.min_breath);
|
||
printf("sleepReport.max_heartbeat: %d , sleepReport.min_heartbeat: %d\r\n", sleepReport.max_heartbeat, sleepReport.min_heartbeat);
|
||
printf("sleepReport.heartbeat_avg: %f breath_avg :%f, sleepReport.move_avg: %f\r\n", sleepReport.heartbeat_avg, sleepReport.breath_avg, sleepReport.move_avg);
|
||
printf("\r\n------------------------Status------------------------------\r\n");
|
||
for (int i = 0; i < CountNum; i++)
|
||
{
|
||
printf(" %d ", sleepStatusBuffer[i]);
|
||
}
|
||
printf("\r\n------------------------ Move ------------------------------\r\n");
|
||
for (int i = 0; i < CountNum; i++)
|
||
{
|
||
printf(" %d ", MovementBuffer[i]);
|
||
}
|
||
printf("\r\n-------------------------Send------------------------------\r\n");
|
||
for (char i = 0; i < Resend; i++)
|
||
{
|
||
#if SLEEP_REPORT_EN
|
||
SleepReportUpload(CountNum);
|
||
delay_ms(500);
|
||
SleepStageDetailUpload(CountNum);
|
||
delay_ms(500);
|
||
SleepHeartWaveUpload(CountNum);
|
||
delay_ms(500);
|
||
SleepBreathWaveUpload(CountNum);
|
||
delay_ms(500);
|
||
IWDG_Feed(); // NOTE:喂狗
|
||
#else
|
||
IWDG_Feed(); // NOTE:喂狗
|
||
#endif
|
||
}
|
||
printf("\r\n--------------------------end------------------------------\r\n");
|
||
}
|
||
|
||
/**
|
||
* @function: ClearReportBuffer
|
||
* @brief: 清除睡眠报告相关
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
void ClearReportBuffer(void)
|
||
{
|
||
// 清空
|
||
Roll_Over_Count = 0;
|
||
memset(&sleepReport, 0, sizeof(sleepReport));
|
||
memset(MovementBuffer, 0, REPORT_BUFFER_MAX);
|
||
memset(BreathRateBuffer, 0, REPORT_BUFFER_MAX);
|
||
memset(HeartRateBuffer, 0, REPORT_BUFFER_MAX);
|
||
}
|
||
|
||
/**
|
||
* @function: SleepReportBufferOptimize
|
||
* @brief 睡眠报告数据优化
|
||
* @return {*}
|
||
* @author: lzc
|
||
*/
|
||
__weak void SleepReportBufferOptimize(uint16_t CountNum)
|
||
{
|
||
char Count = 0;
|
||
for (uint16_t i = 0; i < CountNum; i += 2)
|
||
{
|
||
if (BreathRateBuffer[i] == 0 &&
|
||
HeartRateBuffer[i] == 0)
|
||
{
|
||
if (BreathRateBuffer[i + 1] == 0 &&
|
||
HeartRateBuffer[i + 1] == 0)
|
||
{
|
||
Count++;
|
||
}
|
||
else
|
||
{
|
||
Count = 0;
|
||
}
|
||
}
|
||
}
|
||
} |