/* * @Description: * @Version: 1.0 * @Author: lzc * @Date: 2023-12-07 15:08:04 * @LastEditors: lzc * @LastEditTime: 2024-06-25 15:45:34 */ #include "sys.h" #include "opm.h" #include "usart.h" #include "cJSON.h" #include "general.h" #include "wificom.h" #include "sleepReport.h" const char s_Date[12] = __DATE__; // 取编译日期 const char s_Time[9] = __TIME__; // 取编译时间 uint8_t BreathRateWarn = 0; uint8_t HeartBeatRateWarn = 0; uint8_t BreathRate = 0; uint8_t HeartBeatRate = 0; uint8_t BreathRate_Record = 0; uint8_t HeartBeatRate_Record = 0; uint64_t reportTimeClock = 0; uint64_t keepAliveCount = 0; uint8_t B_AvgValue_Warn = 0; uint8_t H_AvgValue_Warn = 0; uint8_t M_AvgValue_Warn = 0; static uint16_t Array_Count = 0; static uint32_t B_AvgValueSum = 0; // 呼吸一分钟总数 static uint32_t H_AvgValueSum = 0; // 心跳一分钟总数 static uint32_t M_AvgValueSum = 0; // 体动一分钟总数 static uint16_t AvgValueCount = 0; static uint64_t TimeClock_OverValueCount = 0; extern float Diff; extern uint16_t number0; extern char wifi_json_flg; extern char FFT_Count_State_Flag; extern uint8_t g_mon, g_day, g_hour, g_min, g_sec; extern WarningMsg_t WarningMsg; extern warning_config_t warning_config; static int bR_warningCounter[4] = {0}; static int hR_warningCounter[6] = {0}; static char BuildTimeString[36] = {0}; extern char MovementBuffer[REPORT_BUFFER_MAX]; extern char HeartRateBuffer[REPORT_BUFFER_MAX]; extern char BreathRateBuffer[REPORT_BUFFER_MAX]; extern char sleepStatusBuffer[REPORT_BUFFER_MAX]; extern char sleepTempBuffer[REPORT_BUFFER_MAX]; void CheckCoiledData(void); void sleepReportLastPack(void); void sleepReportClearData(void); void bubbleSort(int a[], int n); void checkCounters(uint8_t Breath, uint8_t Heart); void wifiSendMsgOneMoreTimes(uint8_t *data, uint32_t length, char Times); void WarnMsg_CheckStatus(uint8_t breathRate, uint8_t heartbeat, uint8_t Move); uint16_t delateLastAwayBedData(uint16_t Array_Size, char *Buffer); /** * @function: LED_judge * @brief: 判断LED的状态 * @return {*} * @author: lzc */ void LED_judge(void) { if (TimeClock_Flag == 1) { switch (equipment_status_value) { case 3: // 离床 LED_B = 1; LED_R = 1; LED_G = !LED_G; break; case 4: // 在床 LED_B = 1; LED_R = 1; LED_G = 0; break; default: LED_B = 1; LED_G = 1; LED_R = !LED_R; printf("ERROR:LOW OPTION"); break; } } // note:在睡眠时一直喂狗防止出现问题 if (Array_Count != 0) IWDG_Feed(); } /** * @function: Warn_UpdateTimeTick * @brief: 更新时间 * @return {*} * @author: lzc */ void Warn_UpdateTimeTick(void) { WarningMsg.Move_OverThreshold_CountTick = WarningMsg.SysTick_Count; WarningMsg.Heart_OverThreshold_CountTick = WarningMsg.SysTick_Count; WarningMsg.Breath_OverThreshold_CountTick = WarningMsg.SysTick_Count; } /** * @function: wifi_buf_synthesis * @brief 体动以及在离床的数据组包 * @return {*} * @author: lzc */ #define REPORT_DEBUG 1 // 是否开启睡眠报告的调试 #if REPORT_DEBUG #define REPORT_OVERTIME 5 // (5分钟以内的在床清除) #define MSG_DATA_LENGTH 120 // 数据长度 #define REPORT_UPLOAD_ONCE 10 // 每隔多久上报一次睡眠报告 #define OFF_BED_15_MIN_VALUE 1800 // 离床总时间 0.5 Sec / 次 = 1800 #define OFF_BED_30_MIN_VALUE 3600 // 离床总时间 0.5 Sec / 次 = 3600 #define OFF_BED_45_MIN_VALUE 5400 // 离床总时间 0.5 Sec / 次 = 5400 #define OFF_BED_60_MIN_VALUE 7200 // 离床总时间 0.5 Sec / 次 = 3600 #define ONE_MINUTES_TICK_VALUE 120 // 500ms一次 用于1分钟计时 #else #define REPORT_OVERTIME 10 //(10分钟以内的在床清除) #define MSG_DATA_LENGTH (30) // 数据长度 #define REPORT_UPLOAD_ONCE 30 // 每隔多久上报一次睡眠报告 #define OFF_BED_30_MIN_VALUE 3600 // 离床总时间 0.5 Sec / 次 = 3600 #define OFF_BED_45_MIN_VALUE 5400 // 离床总时间 0.5 Sec / 次 = 5400 #define OFF_BED_60_MIN_VALUE 7200 // 离床总时间 0.5 Sec / 次 = 3600 #define ONE_MINUTES_TICK_VALUE 120 #endif #define REPORT_LOG 1 // 是否开启睡眠报告的日志 char AwayBedFlag = 0; char MinutesTickCount = 0; uint32_t OverTimeCount = 0; // 超时计数 uint64_t InBedTimeStamp = 0; extern char bodyCheckSignal; extern float Local_ON_BED_Threshold; extern float Local_OFF_BED_Threshold; char OverTime_Count = 0; char OverTime_CheckFlag = 0; // Sort the Count int count_br[4] = {0}; int count_hr[6] = {0}; void wifi_buf_synthesis(void) { float Difference = 0.0f; // 差值 uint8_t B_AvgValue = 0; uint8_t H_AvgValue = 0; uint8_t M_AvgValue = 0; // 离床的时间 uint16_t BedOffCount = 0; // 光功数据 uint8_t farray[2] = {0}; uint8_t time_num[8] = {0}; IWDG_Feed(); // NOTE:喂狗 sprintf(BuildTimeString, "compile %s %s", s_Date, s_Time); // 体征数据 // NOTE:和上一秒的光功进行比较,如果差值大则有体动数据 /* if (standard < Slight_Movement_Threshold) // 体动值判断 { body_movement_value = Normal_Movement; } else if (standard < Middle_Movement_Threshold) { body_movement_value = Slight_Movement; } else if (standard < Large_Movement_Threshold) { body_movement_value = Middle_Movement; } else if ((standard < Huge_Movement_Threshold)) { body_movement_value = Large_Movement; } else if (standard >= (Huge_Movement_Threshold)) { // 睡眠报告在床情况下,开始记录翻身次数(19:00~第二天8:00) if (OffBed_Flag == 4 && (g_hour <= 8 || g_hour >= 19)) Roll_Over_Count++; } */ // note: 采用CWT的体动标志 body_movement_value = FFT_Count_State_Flag; if (equipment_status_value == InBed_Status) { number0 = 17; if (body_movement_value == FFT_No_breath) body_movement_value = FFT_Still_state; } else { number0 = 17; } memcpy(farray, &number0, sizeof(number0)); wifi_opm_send_buf[0] = 0xA5; wifi_opm_send_buf[1] = 0x5A; wifi_opm_send_buf[2] = farray[0]; wifi_opm_send_buf[3] = farray[1]; #if THE_VERSION wifi_opm_send_buf[4] = 0x01; // 帧类型 0x00 hex 0x01 json #else wifi_opm_send_buf[4] = 0x00; // 帧类型 0x00 hex 0x01 json #endif memcpy(time_num, &timeClockCount_Send, sizeof(timeClockCount_Send)); wifi_opm_send_buf[5] = time_num[0]; wifi_opm_send_buf[6] = time_num[1]; wifi_opm_send_buf[7] = time_num[2]; wifi_opm_send_buf[8] = time_num[3]; wifi_opm_send_buf[9] = time_num[4]; wifi_opm_send_buf[10] = time_num[5]; wifi_opm_send_buf[11] = time_num[6]; wifi_opm_send_buf[12] = time_num[7]; // keepAliveCount++; // 动态离床阈值调整 (夜间) if ((Array_Count > 0)) { #if 1 // 略微增加一点阈值范围 if (abs(Local_OFF_BED_Threshold) - abs(maxOpticalPower) >= (float)3.6) { if (abs(Local_OFF_BED_Threshold) - abs(maxOpticalPower) >= (float)6.0) Difference = 0.8; else Difference = 0.4; ON_BED_Threshold = Local_ON_BED_Threshold - Difference; OFF_BED_Threshold = Local_OFF_BED_Threshold + Difference; } else #endif { ON_BED_Threshold = Local_ON_BED_Threshold - (float)0.2; OFF_BED_Threshold = Local_OFF_BED_Threshold + (float)0.2; } // 在睡眠报告开始计算前清除存储的睡眠报告 便于下一次生成 if (g_hour == NIGHT_SLEEP_POS_2 - 1 && g_min == 30) { // 清除存储的睡眠报告 sleepReportClearData(); } } else { ON_BED_Threshold = Local_ON_BED_Threshold; OFF_BED_Threshold = Local_OFF_BED_Threshold; } ///////////////////////////////////////////////////////////////////////////////////////// 人体在床 if (equipment_status_value == InBed_Status) { wifi_opm_send_buf[13] = HeartBeatRate; // nnom_output_data_BH_KC[1]是预测的心跳值 wifi_opm_send_buf[14] = BreathRate; // nnom_output_data_BH_KC[0]是预测的呼吸值 wifi_opm_send_buf[15] = body_movement_value; // 体动值 0_正常 3_轻微体动 4_中度体动 5_大幅体动 -100_无效值(一分钟的体动值分布,0x00-oxFF 数值越大,体动越明显) wifi_opm_send_buf[16] = InBed_Status; // 设备状态值 3_离床 4_在床 5_光纤故障 9_传感器负荷 10_信号弱 #if THE_VERSION if (warning_config.sex != 0) { BreathRateWarn = BreathRate; HeartBeatRateWarn = HeartBeatRate; checkCounters(BreathRateWarn, HeartBeatRateWarn); WarnMsg_CheckStatus(BreathRateWarn, HeartBeatRateWarn, body_movement_value); } else { // printf("Wait Config...\r\n"); // wifi_crc_send(get_config_buf, 13); } #else ; #endif OverTimeCount = 0; // 1分钟记录一次 if (MinutesTickCount >= ONE_MINUTES_TICK_VALUE) { B_AvgValue = B_AvgValueSum / AvgValueCount; H_AvgValue = H_AvgValueSum / AvgValueCount; M_AvgValue = M_AvgValueSum / AvgValueCount; // 如果在床算出都是0则给默认值 if (H_AvgValue == 0 && B_AvgValue == 0) { H_AvgValue = 68; B_AvgValue = 18; } B_AvgValue_Warn = B_AvgValue; H_AvgValue_Warn = H_AvgValue; M_AvgValue_Warn = M_AvgValue; /* if (g_hour > (NIGHT_SLEEP_POS_2 - 1) || g_hour < NIGHT_SLEEP_POS_1) { #if REPORT_DEBUG // 20~8 周期内开始记录 // printf("\r\n-------------------!!!One Minute Done!!!---------------------\r\n"); // printf("B_AvgValue :%d \r\n", B_AvgValue); // printf("H_AvgValue :%d \r\n", H_AvgValue); // printf("M_AvgValue :%d \r\n", M_AvgValue); // printf("\r\n------------------------ end ------------------------------\r\n"); // printf("B_AvgValue %d ,H_AvgValue %d,M_AvgValue %d\r\n", B_AvgValue, H_AvgValue, M_AvgValue); // wifi_local_log_send("InBed", B_AvgValue, H_AvgValue, M_AvgValue); #else printf("[IN] = !!!! B_AvgValue %d ,H_AvgValue %d,M_AvgValue %d,Array_Count %d !!!!\r\n", B_AvgValue, H_AvgValue, M_AvgValue, Array_Count); #endif bodyCheckSignal = BODY_CHECK_DISABLE; // 表示在床则不进行检测非生命体 // BreathRateBuffer[Array_Count] = B_AvgValue; // HeartRateBuffer[Array_Count] = H_AvgValue; // MovementBuffer[Array_Count] = M_AvgValue; if (OverTime_Count < REPORT_OVERTIME) OverTime_Count++; if (Array_Count < REPORT_BUFFER_MAX) // 必须12小时以内否则数组越界,数组定义现在720 { CheckCoiledData(); // TODO: 连续在床 REPORT_OVERTIME 分钟以上则开始记录 if (OverTime_Count >= REPORT_OVERTIME) { if (OverTime_CheckFlag) Array_Count++; } else { BreathRateBuffer[OverTime_Count] = B_AvgValue; HeartRateBuffer[OverTime_Count] = H_AvgValue; MovementBuffer[OverTime_Count] = M_AvgValue; } } // 记录在床时间戳 需要回溯 if (Array_Count >= REPORT_OVERTIME && InBedTimeStamp == 0) { InBedTimeStamp = timeClockCount - (REPORT_OVERTIME * 60 * 1000); // printf("Record!!!!!!!!!!! %lld\r\n", InBedTimeStamp); } if (Array_Count != 0) { // DONE: 每 REPORT_UPLOAD_ONCE 分钟上报一次睡眠报告 if (Array_Count % REPORT_UPLOAD_ONCE == 0) { IWDG_Feed(); // NOTE:喂狗 // SleepReportGenerate(timeClockCount_Send, Array_Count, 1); } } }*/ B_AvgValueSum = 0; H_AvgValueSum = 0; M_AvgValueSum = 0; AvgValueCount = 0; MinutesTickCount = 0; } else { AvgValueCount++; B_AvgValueSum += BreathRate; H_AvgValueSum += HeartBeatRate; M_AvgValueSum += body_movement_value; } #if REPORT_DEBUG char buffer[512] = {0}; sprintf(buffer, "InBed Time %d:%d:%d | KeepAlive %.1f minute | OverTimeCount %ld", g_hour, g_min, g_sec, (float)(((keepAliveCount) / (float)2.0f) / 60), OverTimeCount); // 是否开启睡眠报告的调试 #if REPORT_LOG wifi_factorySend(); wifi_RealTime_log_send(buffer); #endif // printf("OverTimeCount %d ,Array_Count %d\r\n", OverTimeCount, Array_Count); #else ; #endif IWDG_Feed(); // NOTE:喂狗 } ///////////////////////////////////////////////////////////////////////////////////////// 人体离床 else if (equipment_status_value == OffBed_Status) { wifi_opm_send_buf[13] = 0; // nnom_output_data_BH_KC[1]是预测的心跳值 wifi_opm_send_buf[14] = 0; // nnom_output_data_BH_KC[0]是预测的呼吸值 wifi_opm_send_buf[15] = 0; // 体动值 0_正常 3_轻微体动 4_中度体动 5_大幅体动 -100_无效值(一分钟的体动值分布,0x00-oxFF 数值越大,体动越明显) wifi_opm_send_buf[16] = equipment_status_value; // 设备状态值 3_离床 4_在床 5_光纤故障 6_离线 9_传感器负荷 10_信号弱 memset(fft_HeartBeatRate_StashBuffer, 0, sizeof(fft_HeartBeatRate_StashBuffer)); #if THE_VERSION if (warning_config.sex != 0) { Warn_UpdateTimeTick(); } else { // printf("Wait Config...\r\n"); // wifi_crc_send(get_config_buf, 13); } #else ; #endif #if REPORT_DEBUG char buffer[512] = {0}; sprintf(buffer, "OffBed Time %d:%d:%d | KeepAlive %.1f minute | OverTimeCount %ld", g_hour, g_min, g_sec, (float)(((keepAliveCount) / (float)2.0f) / 60), OverTimeCount); // 是否开启睡眠报告的调试 #if REPORT_LOG wifi_factorySend(); wifi_RealTime_log_send(buffer); #endif // printf("AwayBed Sum Time OverTimeCount %d ,Array_Count %d\r\n", OverTimeCount, Array_Count); #else ; #endif IWDG_Feed(); // NOTE:喂狗 // 1分钟记录一次 离床 if (MinutesTickCount >= ONE_MINUTES_TICK_VALUE) { if (OverTime_Count < REPORT_OVERTIME && OverTime_Count > 0) OverTime_Count++; CheckCoiledData(); if (Array_Count != 0) { // 20~8 周期内开始记录离床 if (g_hour > (NIGHT_SLEEP_POS_2 - 1) || g_hour < (NIGHT_SLEEP_POS_1)) { #if REPORT_DEBUG // printf("\r\n-------------------!!!One Minute Done!!!---------------------\r\n"); // printf("B_AvgValue :0 \r\n"); // printf("H_AvgValue :0 \r\n"); // printf("M_AvgValue :0 \r\n"); // printf("\r\n-------------------------- end ------------------------------\r\n"); // wifi_local_log_send("OffBed", B_AvgValue, H_AvgValue, M_AvgValue); #else printf("[OUT] = !!!! B_AvgValue %d,H_AvgValue %d,M_AvgValue %d !!!!!\r\n", B_AvgValue, H_AvgValue, M_AvgValue); #endif if (Array_Count < REPORT_BUFFER_MAX) // 必须12小时以内否则数组越界,数组定义现在1440 { if (OverTime_CheckFlag) Array_Count++; } // DONE: 每 REPORT_UPLOAD_ONCE 分钟上报一次睡眠报告 if ((Array_Count % REPORT_UPLOAD_ONCE == 0)) { IWDG_Feed(); // NOTE:喂狗 // NOTE:测试版本去除睡眠报告 // SleepReportGenerate(timeClockCount_Send, Array_Count, 1); } } } MinutesTickCount = 0; } BedOffCount = OFF_BED_30_MIN_VALUE; // 离床持续 X 分钟 - 0.5s/次 if (OverTimeCount >= BedOffCount) { OverTimeCount = 0; // 有一定的记录数(分钟) if (Array_Count > MSG_DATA_LENGTH) { // 并且大于上午5点 小于12点才会清除 if (g_hour >= 5 && g_hour <= (NIGHT_SLEEP_POS_1)) sleepReportLastPack(); // -------------------------conty 20230720 并且大于上午20点 小于23点才会清除--------------------- if (g_hour >= 20 && g_hour <= 23) sleepReportLastPack(); // ---------------------------------------------------------------------------------------------- } } } ///////////////////////////////////////////////////////////////////////////////////////// 错误情况 else { wifi_opm_send_buf[13] = HeartBeatRateWarn; // nnom_output_data_BH_KC[1]是预测的心跳值 wifi_opm_send_buf[14] = BreathRateWarn; // nnom_output_data_BH_KC[0]是预测的呼吸值 wifi_opm_send_buf[15] = 0; // 体动值 0_正常 3_轻微体动 4_中度体动 5_大幅体动 -100_无效值(一分钟的体动值分布,0x00-oxFF 数值越大,体动越明显) wifi_opm_send_buf[16] = equipment_status_value; // 设备状态值 3_离床 4_在床 5_光纤故障 6_离线 9_传感器负荷 10_信号弱 #if THE_VERSION if (warning_config.sex != 0) { Warn_UpdateTimeTick(); } else { // printf("Wait Config...\r\n"); // wifi_crc_send(get_config_buf, 13); } #else ; #endif #if REPORT_DEBUG char buffer[512] = {0}; sprintf(buffer, "OffBed Time %d:%d:%d | KeepAlive %.1f minute | OverTimeCount %ld", g_hour, g_min, g_sec, (float)(((keepAliveCount) / (float)2.0f) / 60), OverTimeCount); // 是否开启睡眠报告的调试 #if REPORT_LOG wifi_RealTime_log_send(buffer); #endif // printf("AwayBed Sum Time OverTimeCount %d ,Array_Count %d\r\n", OverTimeCount, Array_Count); #else ; #endif IWDG_Feed(); // NOTE:喂狗 } } /** * @function: wifi_send * @brief: WIFI_的发送 * @return {*} * @author: lzc */ // 数据变化上报机制 // static char Storage_BreathRate = 10; // static char Storage_HeartBeatRate = 10; // static char Storage_body_movement_value = 0; // static char Storage_equipment_status_value = 0; char DataCount = 0; char PowerON_Report_Aborted = 0; void wifi_send(void) { uint8_t *ptr = NULL; get_check_result(); // 放弃初次上电的上报的2次体动信息 if (PowerON_Report_Aborted >= 2) { wifi_buf_synthesis(); PowerON_Report_Aborted = 2; } PowerON_Report_Aborted++; if (equipment_status_value == InBed_Status) // 在床 { #if SLEEP_DEBUG_MODE #else // 数据变化上报机制 // if (Storage_BreathRate != wifi_opm_send_buf[14] || // Storage_HeartBeatRate != wifi_opm_send_buf[13] || // Storage_body_movement_value != wifi_opm_send_buf[15] || // Storage_equipment_status_value != wifi_opm_send_buf[16]) // { // wifiSendMsgOneMoreTimes(wifi_opm_send_buf, number0, 1); // } // 一直上报 wifiSendMsgOneMoreTimes(wifi_opm_send_buf, number0, 1); #endif #if OPM_SEND_MODE delay_ms(150); wifi_opm_send_buf[2] = 0xE1; wifi_opm_send_buf[3] = 0x07; wifi_opm_send_buf[4] = 0x2D; wifi_crc_send(wifi_opm_send_buf, (4 * 500) + 17); wifi_opm_send_buf[2] = 0x11; wifi_opm_send_buf[3] = 0x00; wifi_opm_send_buf[4] = 0x01; delay_ms(150); wifi_json_send(); delay_ms(150); #else ; #endif OffBed_Time = 0; DataCount = 3; } // 离床定时上报 else { #if SLEEP_DEBUG_MODE #else // // 数据变化上报机制 // if (Storage_BreathRate != wifi_opm_send_buf[14] || // Storage_HeartBeatRate != wifi_opm_send_buf[13] || // Storage_body_movement_value != wifi_opm_send_buf[15] || // Storage_equipment_status_value != wifi_opm_send_buf[16]) // { // wifiSendMsgOneMoreTimes(wifi_opm_send_buf, number0, 1); // } // // 一直上报 wifiSendMsgOneMoreTimes(wifi_opm_send_buf, number0, 1); #endif } wifi_json_flg = 1; USART_RX_Length = 0; // 数据变化上报机制 // Storage_BreathRate = wifi_opm_send_buf[14]; // nnom_output_data_BH_KC[0]是预测的呼吸值 // Storage_HeartBeatRate = wifi_opm_send_buf[13]; // nnom_output_data_BH_KC[1]是预测的心跳值 // Storage_body_movement_value = wifi_opm_send_buf[15]; // 体动值 0_正常 3_轻微体动 4_中度体动 5_大幅体动 -100_无效值(一分钟的体动值分布,0x00-oxFF 数值越大,体动越明显) // Storage_equipment_status_value = wifi_opm_send_buf[16]; // 设备状态值 3_离床 4_在床 5_光纤故障 9_传感器负荷 10_信号弱 } /** * @function: * @brief: None * @return {*} * @author: lzc */ static char Heartbeat_Warn_Flag = 0, Breath_Warn_Flag = 0, Move_Warn_Flag = 0; void Warn_MsgCreate(uint8_t breathRate, uint8_t heartbeat, uint8_t Move) { char warningMsgSendBuffer[41] = {0}; // TODO:Send warning Msg // NOTE:帧头 warningMsgSendBuffer[0] = 0XA5; warningMsgSendBuffer[1] = 0X5A; // NOTE:帧长 warningMsgSendBuffer[2] = 41; warningMsgSendBuffer[3] = 0X00; // note:帧类型 warningMsgSendBuffer[4] = 0X1B; //////////////////////////////////////////////////////////////////////// // note:心率告警开始时间戳 memcpy(warningMsgSendBuffer + 5, &WarningMsg.Heart_OverThreshold_TimeStamp, 8); // note:心率是否有警告 warningMsgSendBuffer[13] = Heartbeat_Warn_Flag; if (Heartbeat_Warn_Flag) { Heartbeat_Warn_Flag = 0; // 发送之前已经更新 // WarningMsg.Heart_OverThreshold_TimeStamp = WarningMsg.SysTick_Count; } // note:心率告警是最大还是最小,以及阈值(大于:1 小于 :2) if (heartbeat > warning_config.heart_max_th) { warningMsgSendBuffer[14] = 1; warningMsgSendBuffer[15] = warning_config.heart_max_th; } // note:心率告警是最大还是最小,以及阈值(大于:1 小于 :2) else if (heartbeat < warning_config.heart_min_th) { warningMsgSendBuffer[14] = 2; warningMsgSendBuffer[15] = warning_config.heart_min_th; } // note:持续时间 warningMsgSendBuffer[16] = warning_config.heart_keep_th; // TODO: 当前心率值 warningMsgSendBuffer[17] = H_AvgValue_Warn; //////////////////////////////////////////////////////////////////////// // note:呼吸告警开始时间戳 memcpy(warningMsgSendBuffer + 18, &WarningMsg.Breath_OverThreshold_TimeStamp, 8); // note:呼吸是否有警告 warningMsgSendBuffer[26] = Breath_Warn_Flag; if (Breath_Warn_Flag) { Breath_Warn_Flag = 0; // 发送之前已经更新 // WarningMsg.Breath_OverThreshold_TimeStamp = WarningMsg.SysTick_Count; } // note:呼吸告警是最大还是最小,以及阈值(大于:1 小于 :2) if (breathRate > warning_config.breath_max_th) { warningMsgSendBuffer[27] = 1; warningMsgSendBuffer[28] = warning_config.breath_max_th; } // note:呼吸告警是最大还是最小,以及阈值(大于:1 小于 :2) else if (breathRate < warning_config.breath_min_th) { warningMsgSendBuffer[27] = 2; warningMsgSendBuffer[28] = warning_config.breath_min_th; } // note:持续时间 warningMsgSendBuffer[29] = warning_config.breath_keep_th; // TODO: 当前呼吸值 warningMsgSendBuffer[30] = B_AvgValue_Warn; //////////////////////////////////////////////////////////////////////// // note:体动告警开始时间戳 memcpy(warningMsgSendBuffer + 31, &WarningMsg.Move_OverThreshold_TimeStamp, 8); // note:体动是否有警告 warningMsgSendBuffer[39] = Move_Warn_Flag; if (Move_Warn_Flag) { Move_Warn_Flag = 0; // 发送之前已经更新 // WarningMsg.Move_OverThreshold_CountTick = WarningMsg.SysTick_Count; } // note:持续时间 warningMsgSendBuffer[40] = warning_config.breath_keep_th; for (char i = 0; i < 41; i++) { // printf("%x ", warningMsgSendBuffer[i]); } // 发送 必须真的有预警 if (B_AvgValue_Warn >= warning_config.breath_max_th || B_AvgValue_Warn <= warning_config.breath_min_th || H_AvgValue_Warn >= warning_config.heart_max_th || H_AvgValue_Warn <= warning_config.heart_min_th) { wifi_crc_send((uint8_t *)warningMsgSendBuffer, 41); } } /** * @function:WarnMsg_CheckStatus * @brief: None * @return {*} * @author: lzc */ void WarnMsg_CheckStatus(uint8_t breathRate, uint8_t heartbeat, uint8_t Move) { #if REPORT_DEBUG // printf("Warning msg check breath rate %d, heartbeat %d, move %d\n", breathRate, heartbeat, Move); #else ; #endif // NOTE: 心率异常 if ((heartbeat <= warning_config.heart_max_th && heartbeat >= warning_config.heart_min_th)) { Heartbeat_Warn_Flag = 0; // 范围内无异常则一直更新计数值 WarningMsg.Heart_OverThreshold_CountTick = WarningMsg.SysTick_Count; } else { // printf("[INFO]WarningMsg.SysTick_Count is %lld\n", WarningMsg.SysTick_Count); // printf("[INFO]WarningMsg.Heart_OverThreshold_CountTick is %lld\n", WarningMsg.Heart_OverThreshold_CountTick); // 超过时间阈值,每个count是500ms if ((WarningMsg.SysTick_Count - WarningMsg.Heart_OverThreshold_CountTick) > ((warning_config.heart_keep_th) * 60 * 2)) { Heartbeat_Warn_Flag = 1; // 更新计数值 WarningMsg.Heart_OverThreshold_CountTick = WarningMsg.SysTick_Count; // 计算时间戳 WarningMsg.Heart_OverThreshold_TimeStamp = timeClockCount - (warning_config.heart_keep_th * 60 * 1000); // 需要发送预警 if (heartbeat > warning_config.heart_max_th) { // 大于最大值 // printf("!!!!!!!!!!!!!!!!!!Heart Rate Over Event: > %d keep %d \n", // warning_config.heart_max_th, warning_config.heart_keep_th); WarningMsg.Heart_OverThreshold_CountTick = WarningMsg.SysTick_Count; } else { // 小于最小值 // printf("!!!!!!!!!!!!!!!!!!Heart Rate Over Event: < %d keep %d \n", // warning_config.heart_min_th, warning_config.heart_keep_th); WarningMsg.Heart_OverThreshold_CountTick = WarningMsg.SysTick_Count; } } } // NOTE:呼吸异常 (TODO) if (breathRate <= warning_config.breath_max_th && breathRate >= warning_config.breath_min_th) { Breath_Warn_Flag = 0; // 范围内无异常则一直更新计数值 WarningMsg.Breath_OverThreshold_CountTick = WarningMsg.SysTick_Count; } else { // printf("[INFO]WarningMsg.SysTick_Count is %lld\n", WarningMsg.SysTick_Count); // printf("[INFO]WarningMsg.Breath_OverThreshold_CountTick is %lld\n", WarningMsg.Breath_OverThreshold_CountTick); // 超过时间阈值,每个count是500ms if ((WarningMsg.SysTick_Count - WarningMsg.Breath_OverThreshold_CountTick) > ((warning_config.breath_keep_th) * 60 * 2)) { Breath_Warn_Flag = 1; // 更新计数值 WarningMsg.Breath_OverThreshold_CountTick = WarningMsg.SysTick_Count; // 计算时间戳 WarningMsg.Breath_OverThreshold_TimeStamp = timeClockCount - (warning_config.breath_keep_th * 60 * 1000); // 需要发送预警 if (breathRate > warning_config.breath_max_th) { // 大于最大值 // printf("!!!!!!!!!!!!!!!!!!Breath Rate Over Event: > %d keep %d \n", // warning_config.breath_max_th, warning_config.breath_keep_th); WarningMsg.Breath_OverThreshold_CountTick = WarningMsg.SysTick_Count; } else { // 小于最小值 // printf("!!!!!!!!!!!!!!!!!!Breath Rate Over Event: < %d keep %d \n", // warning_config.breath_min_th, warning_config.breath_keep_th); WarningMsg.Breath_OverThreshold_CountTick = WarningMsg.SysTick_Count; } } } // NOTE:无体动异常 if (Move != Normal_Movement) { Move_Warn_Flag = 0; // 范围内无异常则一直更新计数值 WarningMsg.Move_OverThreshold_CountTick = WarningMsg.SysTick_Count; // 记录当前时间戳 WarningMsg.Move_OverThreshold_TimeStamp = timeClockCount; } else { warning_config.Move_keep_th = 120; // 默认 120 分钟 // printf("[INFO]WarningMsg.SysTick_Count is %lld\n", WarningMsg.SysTick_Count); // printf("[INFO]WarningMsg.Move_OverThreshold_CountTick is %lld\n", WarningMsg.Move_OverThreshold_CountTick); // 超过时间阈值,每个count是500ms if ((WarningMsg.SysTick_Count - WarningMsg.Move_OverThreshold_CountTick) > ((warning_config.Move_keep_th) * 60 * 2)) { Move_Warn_Flag = 1; // 计算时间戳 WarningMsg.Move_OverThreshold_TimeStamp = timeClockCount - (warning_config.Move_keep_th * 60 * 1000); // 更新计数值 WarningMsg.Move_OverThreshold_CountTick = WarningMsg.SysTick_Count; // 需要发送预警 // printf("!!!!!!!!!!!!!!!!!!Move Over Event keep %d \n", warning_config.Move_keep_th); } } if (Move_Warn_Flag || Breath_Warn_Flag || Heartbeat_Warn_Flag) { Warn_MsgCreate(breathRate, heartbeat, Move); } } /** * @function:VectorTableReInit * @brief: None * @return {*} * @author: lzc */ void VectorTableReInit(void) { if ((*(__IO uint32_t *)0x08008000) == 0x1111) // 1111--升级完成 { NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x80000); } else // 0101--启动老程序 { NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x10000); } } /** * @function: wifi_json_send * @brief: json数据的组包 * @return {*} * @author: lzc */ static char HealthCount = 0; static char StorageHealth = 0; static char StorageSensorLoad = 0; static char StorageLightSignal = 0; static char StorageOpticalFibre = 0; void wifi_json_send(void) { cJSON *cjson_test = NULL; cJSON *cjson_status = NULL; uint8_t farray[2] = {0}; char str[512] = {"\0"}; char JsonOutputBuffer[100] = {0}; char length = 0; // NOTE: 采用组包方式 sprintf(JsonOutputBuffer, "{\"time\": %llu,\"health\": %d,\"status\":{\"opticalFibre\": %d,\"sensorLoad\": %d,\"lightSignal\": %d}}", timeClockCount_Send, health_flg, opticalFibre_flg, sensorLoad_flg, lightSignal_flg); // printf("JSON OUTPUT: %s\n", JsonOutputBuffer); length = strlen(JsonOutputBuffer); str[0] = 0XA5; str[1] = 0x5A; str[2] = length & 0xff; str[3] = length >> 8; str[4] = 0x40; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); #if SLEEP_DEBUG_MODE #else // // 数据变化上报机制 // if (StorageHealth != health_flg || StorageSensorLoad != sensorLoad_flg || // StorageLightSignal != lightSignal_flg || StorageOpticalFibre != opticalFibre_flg) // { // for (char i = 0; i < 3; i++) // { // USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); // delay_ms(100); // } // } // StorageHealth = health_flg; // StorageSensorLoad = sensorLoad_flg; // StorageLightSignal = lightSignal_flg; // StorageOpticalFibre = opticalFibre_flg; // // 定时发送 差不多5秒 HealthCount++; if (HealthCount >= 5) { HealthCount = 0; USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); } #endif } //-------------------------------------------------------------------------------------------------------------------------------- ADD /** * @function: wifi_json_send * @brief: json数据的组包 * @return {*} * @author: lzc */ extern float i_count_Max; char ResultBuffer[128] = {0}; static char factoryStartDeal = 1; static char factoryUpload = 0; static char factoryCount = 0; static char factoryCountValue = 0; uint32_t ThirdMinutesCountDown = 0; uint16_t OneMinutesCountDown = 0; void wifi_factorySend(void) { #if FACTORY_ENABLE cJSON *cjson_test = NULL; cJSON *cjson_status = NULL; uint8_t farray[2] = {0}; char str[512] = {"\0"}; char JsonOutputBuffer[128] = {0}; char length = 0; str[0] = 0XA5; str[1] = 0x5A; str[4] = 0x2f; // NOTE: 采用组包方式 if (ThirdMinutesCountDown >= (3 * 60 * 2) && factoryStartDeal) { if (OneMinutesCountDown >= (100 * 2)) { if (factoryCountValue >= 70 && factoryUpload == 0) { sprintf(JsonOutputBuffer, "{\"累加数据\": %d,\"数据\": %.4f,\"结果\": \"正常\"}", factoryCountValue, i_count_Max); memcpy(ResultBuffer, JsonOutputBuffer, strlen(JsonOutputBuffer)); length = strlen(JsonOutputBuffer); str[2] = length & 0xff; str[3] = length >> 8; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); factoryCount++; if (factoryCount >= 120) factoryUpload = 1; factoryStartDeal = 0; } else if (factoryCountValue < 70 && factoryUpload == 0) { sprintf(JsonOutputBuffer, "{\"累加数据\": %d,\"数据\": %.4f,\"结果\": \"错误\"}", factoryCountValue, i_count_Max); memcpy(ResultBuffer, JsonOutputBuffer, strlen(JsonOutputBuffer)); length = strlen(JsonOutputBuffer); str[2] = length & 0xff; str[3] = length >> 8; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); factoryCount++; if (factoryCount >= 120) factoryUpload = 1; factoryStartDeal = 0; } OneMinutesCountDown = (100 * 2); // 给默认值 } else { sprintf(JsonOutputBuffer, "{\"累加数据\": %d,\"数据\": %.4f,\"结果\": \"检测中...\"}", factoryCountValue, i_count_Max); // 判断是否正常 if (i_count_Max <= 0.003f) factoryCountValue++; else if (i_count_Max > 0.003f && factoryCountValue != 0) factoryCountValue--; length = strlen(JsonOutputBuffer); str[2] = length & 0xff; str[3] = length >> 8; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); } ThirdMinutesCountDown = (4 * 60 * 2); // 给默认值 } else if (ThirdMinutesCountDown < (3 * 60 * 2)) { sprintf(JsonOutputBuffer, "{\"数据\": %.4f,\"结果\": \"启动...\"}", i_count_Max); length = strlen(JsonOutputBuffer); str[2] = length & 0xff; str[3] = length >> 8; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); } // printf("JSON OUTPUT: %s\n", JsonOutputBuffer); // length = strlen(JsonOutputBuffer); // str[2] = length & 0xff; // str[3] = length >> 8; // memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); // // 定时发送 差不多5秒 // factoryCount++; // if (factoryCount >= 2) // { // factoryCount = 0; // USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); // } #endif } //-------------------------------------------------------------------------------------------------------------------------------- /** * @function: wifi_local_log_send * @brief: json数据的组包 * @return {*} * @author: lzc */ void wifi_local_log_send(char *MyStr, char Breath, char Heart, char Move) { uint8_t farray[2] = {0}; char str[1024] = {"\0"}; char JsonOutputBuffer[512] = {0}; char length = 0; // NOTE: 采用组包方式 sprintf(JsonOutputBuffer, "{\"addZoneTime\": %llu,\"log\":\"%s\",\"Array_Count\": %d,\"AvgValue\":{\"B_AvgValue\": %d,\"H_AvgValue\": %d,\"M_AvgValue\": %d}}", (timeClockCount + (((signed char)warning_config.timeZone) * 60 * 60 * 1000)), MyStr, Array_Count, Breath, Heart, Move); length = strlen(JsonOutputBuffer); // printf("%d JSON OUTPUT: %s \n", length, JsonOutputBuffer); str[0] = 0XA5; str[1] = 0x5A; str[2] = length & 0xff; str[3] = length >> 8; str[4] = 0x2E; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); #if SLEEP_DEBUG_MODE #else USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); #endif delay_ms(50); } /** * @function: wifi_RealTime_log_send * @brief: json数据的组包 * @return {*} * @author: lzc */ extern char bootResult; extern float Diff; extern float FFT_br; extern float Diff_Detail; extern float ADC_1310; extern float i_count_Std; extern float i_count_Max; extern float OPM_Current; extern float OPM_Record; extern float OPM_Record_2; extern float OPM_Original; extern char i_count_off_bed; extern char i_count_no_human; extern char i_count_No_Breath; extern float Diff_detail_Record; extern uint16_t FiveMinutesCount; extern uint16_t fft_HeartBeatRate_Result; extern uint16_t time_HeartBeatRate_Result; extern unsigned char version[8]; extern float stash_Ratio[ARRAY_NUMBER]; extern float32_t HeartValueRes2Peaks[4]; extern float Calculate_1310_dbm_array[50]; void wifi_RealTime_log_send(char *MyStr) { uint8_t farray[2] = {0}; char UploadVersion[8] = {0}; char temp[16] = {0}; char array[512] = {0}; char str[3072] = {"\0"}; char JsonOutputBuffer[3072] = {0}; int length = 0; // NOTE: 采用组包方式 sprintf(UploadVersion, "%d.%d.%d", version[5], version[6], version[7]); // 如果没有存完 就简单出1秒一次的 if (Calculate_1310_dbm_array[49] == 0x00) { sprintf(JsonOutputBuffer, "{\"version\":\"%s\",\"build\":\"%s\",\"addZoneTime\": %llu,\"TimeStamp\": %llu,\"bootResult\": %d,\"log\":\"%s\",\"Array_Count\": %d,\"i_count_no\": %d,\"i_count_std\": %f,\"Optical\": %.2f}", UploadVersion, BuildTimeString, (timeClockCount_Send + (((signed char)warning_config.timeZone) * 60 * 60 * 1000)), timeClockCount_Send, bootResult, MyStr, Array_Count, i_count_no_human, (float)i_count_Std, (float)dbm_value_1310); length = strlen(JsonOutputBuffer); } else { for (char i = 0; i < 49; i++) { sprintf(temp, "%.3f,", Calculate_1310_dbm_array[i]); strcat(array, temp); } sprintf(temp, "%.3f", Calculate_1310_dbm_array[49]); strcat(array, temp); sprintf(JsonOutputBuffer, "{\"version\":\"%s\",\"build\":\"%s\",\"addZoneTime\": %llu,\"TimeStamp\": %llu ,\ \"bootResult\": %d,\"log\":\"%s\",\"Diff_detail_Record\": %f,\"ADC_Value\": %.4f,\"Channel_1310\": %d,\"i_count_no\": %d,\"i_count_off_bed\": %d,\ \"i_count_No_Breath\": %d,\"i_count_max\": %f,\"FFT_br\": %f,\"Diff\": %f,\"Diff_Detail\": %f,\"OPM\": %f,\"OPM_Record\": %f,\"OPM_Record_2\": %f,\ \"OPM_Origin\": %f,\"Ratio[0]\": %f,\"Ratio[1]\": %f,\"Peak[0]\": %f,\"Peak[1]\": %f,\"Peak[2]\": %f,\"Peak[3]\": %f,\"HR_result\": %d,\"time_result\": %d,\ \"Optical\": [", UploadVersion, BuildTimeString, (timeClockCount_Send + (((signed char)warning_config.timeZone) * 60 * 60 * 1000)), timeClockCount_Send, bootResult, MyStr, (float)Diff_detail_Record, ADC_1310, channel_1310, i_count_no_human, i_count_off_bed, i_count_No_Breath, (float)i_count_Max, (float)FFT_br, (float)Diff, (float)Diff_Detail, (float)OPM_Current, (float)OPM_Record, (float)OPM_Record_2, (float)OPM_Original, (float)(stash_Ratio[0]), (float)(stash_Ratio[1]), (float)(HeartValueRes2Peaks[0]), (float)(HeartValueRes2Peaks[1]), (float)(HeartValueRes2Peaks[2]), (float)(HeartValueRes2Peaks[3]), fft_HeartBeatRate_Result, time_HeartBeatRate_Result); length = strlen(JsonOutputBuffer) + strlen(array) + 2; // strcat(JsonOutputBuffer, array); // printf("Length 2 = %d\n", length); strcat(JsonOutputBuffer, "]}"); } // printf("%d JSON OUTPUT: %s \n", length, JsonOutputBuffer); str[0] = 0XA5; str[1] = 0x5A; str[2] = length & 0xff; str[3] = length >> 8; str[4] = 0x2E; memcpy(str + 5, JsonOutputBuffer, strlen(JsonOutputBuffer)); #if SLEEP_DEBUG_MODE #else USART1_SendData((uint8_t *)str, strlen(JsonOutputBuffer) + 5); #endif delay_ms(50); } /** * @function: wifiSendMsgOneMoreTimes * @brief: None * @param {uint8_t} *data * @param {uint32_t} length * @param {char} Times * @return {*} * @author: lzc */ void wifiSendMsgOneMoreTimes(uint8_t *data, uint32_t length, char Times) { for (char i = 0; i < Times; i++) { delay_ms(1200); wifi_crc_send(data, length); delay_ms(1200); } } /** * @function:CheckCoiledData * @brief 判断有没有连续 * @return {*} * @author: lzc */ void CheckCoiledData(void) { // 判断有没有连续 if (!OverTime_CheckFlag && OverTime_Count >= REPORT_OVERTIME) { int i = 0; for (i = 0; i < REPORT_OVERTIME; i++) { if (BreathRateBuffer[i] == 0) break; } if (i == REPORT_OVERTIME) // 连续 { OverTime_CheckFlag = 1; Array_Count = REPORT_OVERTIME - 1; } else // 不连续 清除 { Array_Count = 0; OverTime_Count = 0; OverTime_CheckFlag = 0; ClearReportBuffer(); } } } /** * @function:delateLastAwayBedData * @brief 删除最后一包睡眠报告中离床数据 * @return {*} * @author: lzc */ uint16_t delateLastAwayBedData(uint16_t Array_Size, char *Buffer) { uint16_t index = 0; // 去除最后的离床数据 for (int i = Array_Size - 1; i >= 0; i--) { // printf("TestBuffer[%d] = %d\n", i, *(Buffer + i)); if (*(Buffer + i) == 0 && *(Buffer + (i - 1)) == 0) { // printf("Count ++\r\n"); } else { index = i; // printf("index = %d\r\n", index); return index; } } return Array_Size; } /** * @function: sleepReportClearData * @brief 睡眠报告清除 * @return {*} * @author: lzc */ void sleepReportClearData(void) { // 清除存储的睡眠报告 ClearReportBuffer(); Array_Count = 0; InBedTimeStamp = 0; OverTime_Count = 0; OverTime_CheckFlag = 0; } /** * @function: sleepReportLastPack * @brief 睡眠报告最后离床上报清除 * @return {*} * @author: lzc */ void sleepReportLastPack(void) { char SleepHours[128] = {0}; reportTimeClock = timeClockCount + ((signed char)warning_config.timeZone) * 60 * 60 * 1000; IWDG_Feed(); // NOTE:喂狗 // TODO: 进行最后的睡眠报告的上报 printf("Sleep Last Package!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n"); Array_Count = delateLastAwayBedData(Array_Count, HeartRateBuffer); // SleepReportGenerate(timeClockCount_Send, Array_Count, 6); // 清除存储的睡眠报告 sleepReportClearData(); bodyCheckSignal = BODY_CHECK_ENABLE; } /** * @function: bubbleSort * @brief: None * @param {int} a * @param {int} n * @return {*} * @author: lzc */ void bubbleSort(int a[], int n) { int i, t; for (i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1; j++) if (a[j] < a[j + 1]) { t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; } } } /** * @function: checkCounters * @brief: None * @param {int} a * @return {*} * @author: lzc */ void checkCounters(uint8_t Breath, uint8_t Heart) { // NOTE: Check if br in range if (Breath >= 11 && Breath <= 12) bR_warningCounter[0]++; else if (Breath >= 13 && Breath <= 15) bR_warningCounter[1]++; else if (Breath >= 16 && Breath <= 18) bR_warningCounter[2]++; else if (Breath >= 19 && Breath <= 20) bR_warningCounter[3]++; // NOTE: Check if Hr in range if (Heart >= 61 && Heart <= 65) hR_warningCounter[0]++; else if (Heart >= 66 && Heart <= 70) hR_warningCounter[1]++; else if (Heart >= 71 && Heart <= 75) hR_warningCounter[2]++; else if (Heart >= 76 && Heart <= 80) hR_warningCounter[3]++; else if (Heart >= 81 && Heart <= 85) hR_warningCounter[4]++; else if (Heart >= 86 && Heart <= 90) hR_warningCounter[5]++; // NOTE: Out of range if ((Breath < 7 || Breath >= 30) && Breath != 0) { memcpy(count_br, bR_warningCounter, sizeof(bR_warningCounter)); bubbleSort(count_br, 4); if (count_br[0] == bR_warningCounter[0]) Breath = 11; else if (count_br[0] == bR_warningCounter[1]) Breath = 14; else if (count_br[0] == bR_warningCounter[2]) Breath = 17; else if (count_br[0] == bR_warningCounter[3]) Breath = 19; else Breath = 20; // WarnMsg_CheckStatus(count_br[0], Heart, body_movement_value); BreathRateWarn = Breath; printf("Upload Breath is %d\n", Breath); } if ((Heart < 45 || Heart >= 110) && Heart != 0) { memcpy(count_hr, hR_warningCounter, sizeof(hR_warningCounter)); bubbleSort(count_hr, 6); if (count_hr[0] == hR_warningCounter[0]) Heart = 64; else if (count_hr[0] == hR_warningCounter[1]) Heart = 68; else if (count_hr[0] == hR_warningCounter[2]) Heart = 73; else if (count_br[0] == hR_warningCounter[3]) Heart = 78; else if (count_br[0] == hR_warningCounter[4]) Heart = 83; else if (count_br[0] == hR_warningCounter[5]) Heart = 88; else Heart = 90; // WarnMsg_CheckStatus(Breath, count_hr[0], body_movement_value); HeartBeatRateWarn = Heart; printf("Upload Heart is %d\n", Heart); } }