mcu_hi3321_watch/tjd/service/service_hrsensor.c
2025-05-26 20:15:20 +08:00

637 lines
24 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*----------------------------------------------------------------------------
* Copyright (c) TJD Technologies Co., Ltd. 2020. All rights reserved.
*
* Description: service_hrsensor.c
*
* Author: liangjianfei
*
* Create: 2024-4-26
*--------------------------------------------------------------------------*/
#include "service_hrsensor.h"
#include "cmsis_os2.h"
#include "common_def.h"
#include "hr_api.h"
#include "pm.h"
#include "rtc_api.h"
#include "securec.h"
#include "soc_osal.h"
#include "sql_fit.h"
#include "sys_config.h"
#include "sys_typedef.h"
#include "task_service_timer.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "cwm_port.h"
#define ENABLE_PRINT_INFO 1
#define ENABLE_DEBUG 0
#if ENABLE_PRINT_INFO
#define static_print_info(...) sys_hr_log_i(__VA_ARGS__) // 一般信息打印宏控制
#define static_print_warn(...) sys_hr_log_w(__VA_ARGS__) // 警告信息打印一般常开
#define static_print_error(...) sys_hr_log_e(__VA_ARGS__) // 错误信息打印一般常开
#if ENABLE_DEBUG
#define static_print_debug(...) sys_hr_log_d(__VA_ARGS__) // debug
#else
#define static_print_debug(...)
#endif
#else
#define static_print_info(...)
#define static_print_warn(...)
#define static_print_error(...)
#endif
#define LOOP_PERIOD_TIME 1000 * 30
#define HRV_LOOP_PERIOD_TIME 1000 * 60
static const uint16_t HR_INTERVAL_MIN = 5;
static const uint16_t HRV_INTERVAL_MIN = 60;
static const uint16_t SPO2_INTERVAL_MIN = 60;
hrsensor_data_t g_hr_data = {0};
static uint8_t g_ui_cur_hrvalue = 0;
static uint8_t g_ui_cur_spo2value = 0;
static uint8_t g_ui_cur_hrvvalue = 0;
static osTimerId_t g_hr_servise_timer;
bool g_hr_is_running = false;
bool g_hr_service_inited = false;
hr_service_id_t g_hr_service_id = 0;
static int32_t tjd_service_hrsensor_open(hr_api_info_t hr_api_info);
static int32_t tjd_service_hrsensor_close(void);
static void tjd_protocol_measure_data_send(const uint8_t id);
static void hr_service_timer_callback(void *argument)
{
uint8_t *p_hr_array;
uint8_t *p_spo2_array;
uint8_t *p_hrv_array;
sql_fit_get_hr_daydata(&p_hr_array);
sql_fit_get_spo2_daydata(&p_spo2_array);
sql_fit_get_sterss_daydata(&p_hrv_array);
memset(p_hr_array, 0, sizeof(uint8_t) * HR_DAY_MAX_NUM);
memset(p_spo2_array, 0, sizeof(uint8_t) * SPO2_DAY_MAX_NUM);
memset(p_hrv_array, 0, sizeof(uint8_t) * STRESS_DAY_MAX_NUM);
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
if (local_time.tm_hour == 0)
sql_fit_clear_health_day_data(local_time.tm_wday);
else if (local_time.tm_hour == 23)
sql_fit_clear_health_day_data(local_time.tm_wday+1);
uint32_t next_sec = ((24-local_time.tm_hour)*3600) - (local_time.tm_min*60) - local_time.tm_sec;
osStatus_t ret = osTimerStart(g_hr_servise_timer, next_sec*1000);
if (ret != osOK) {
static_print_error("hr_service_timer_callback osTimerStart failed:%d", ret);
return;
}
static_print_info("hr_service_timer_callback succ!");
}
static uint32_t hr_get_curtime_index(uint64_t *timestamp)
{
struct rtc_time local_time;
struct rtc_class_ops *handle = tjd_driver_rtc_get_ops();
handle->get_rtc_time(&local_time);
uint32_t totalMinutes = local_time.tm_hour * 60 + local_time.tm_min;
// 计算索引值每5分钟一个索引
uint32_t index = totalMinutes / 5;
handle->get_timestamp(timestamp);
return index;
}
static uint32_t spo2_hrv_get_curtime_index(uint64_t *timestamp)
{
struct rtc_time local_time;
struct rtc_class_ops *handle = tjd_driver_rtc_get_ops();
handle->get_rtc_time(&local_time);
// 计算索引值每60分钟一个索引
uint32_t index = local_time.tm_hour;
handle->get_timestamp(timestamp);
return index;
}
static int32_t tjd_task_service_hrsensor_store_data(hr_service_id_t id)
{
uint8_t hrValue = 0;
uint8_t spo2Value = 0;
uint8_t hrvValue = 0;
uint64_t timestamp = 0;
static uint8_t stop_count = 0;
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
uint8_t wearStatus = g_hr_data.wear_status;
static_print_debug("wearStatus:%d hr value:%d spo2:%d%% stress:%d%%", wearStatus, g_hr_data.hr_result,
g_hr_data.spo2_result, g_hr_data.hrv_result);
if (wearStatus == 1) {
//佩戴状态,需要连续发正常范围内的数据给算法。
cwm_set_device_status(wearStatus);
if(g_hr_data.hr_result >30 && g_hr_data.hr_result < 200) {
cwm_set_hr_value(g_hr_data.hr_result);
}
if (id != HR_SERVICE_BO_ALLDAY && id != HR_SERVICE_UI_BO && id != HR_SERVICE_STRESS_ALLDAY) {
hrValue = g_hr_data.hr_result;
hrValue = hrValue < 40 || hrValue > 200 ? (hrValue < 40 ? 0 : 200) : hrValue;
if (hrValue > sql_fit_get_hr_max(local_time.tm_wday)) {
sql_fit_set_hr_max(hrValue, local_time.tm_wday);
}
if (hrValue != 0 && hrValue < sql_fit_get_hr_min(local_time.tm_wday)) {
sql_fit_set_hr_min(hrValue, local_time.tm_wday);
}
uint32_t index = hr_get_curtime_index(&timestamp);
if (hrValue >= 40 && hrValue <= 200) {
sql_fit_set_hr_curdata(index, hrValue);
sql_fit_set_last_hr(hrValue, local_time.tm_wday);
sql_fit_set_last_hr_timestamp(timestamp, local_time.tm_wday);
}
} else if (id == HR_SERVICE_BO_ALLDAY || id == HR_SERVICE_UI_BO) {
spo2Value = g_hr_data.spo2_result;
hrValue = g_hr_data.hr_result;
spo2Value = spo2Value < 70 || spo2Value > 99 ? (spo2Value < 70 ? 0 : 99) : spo2Value;
hrValue = hrValue < 40 || hrValue > 200 ? (hrValue < 40 ? 0 : 200) : hrValue;
// 存心率
if (hrValue > sql_fit_get_hr_max(local_time.tm_wday)) {
sql_fit_set_hr_max(hrValue, local_time.tm_wday);
}
if (hrValue != 0 && hrValue < sql_fit_get_hr_min(local_time.tm_wday)) {
sql_fit_set_hr_min(hrValue, local_time.tm_wday);
}
uint32_t index = hr_get_curtime_index(&timestamp);
if (hrValue >= 40 && hrValue <= 200) {
sql_fit_set_hr_curdata(index, hrValue);
sql_fit_set_last_hr(hrValue, local_time.tm_wday);
sql_fit_set_last_hr_timestamp(timestamp, local_time.tm_wday);
}
// 存血氧
if (spo2Value > sql_fit_get_spo2_max(local_time.tm_wday)) {
sql_fit_set_spo2_max(spo2Value, local_time.tm_wday);
}
if (spo2Value != 0 && spo2Value < sql_fit_get_spo2_min(local_time.tm_wday)) {
sql_fit_set_spo2_min(spo2Value, local_time.tm_wday);
}
if (spo2Value >= 70 && spo2Value <= 100) {
uint32_t index = spo2_hrv_get_curtime_index(&timestamp);
sql_fit_set_spo2_curdata(index, spo2Value);
sql_fit_set_last_spo2(spo2Value, local_time.tm_wday);
// sql_fit_set_last_spo2_timestamp(timestamp);
}
} else if (id == HR_SERVICE_STRESS_ALLDAY) {
hrvValue = g_hr_data.hrv_result;
hrvValue = hrvValue < 0? 0:hrvValue;
if (hrvValue > sql_fit_get_stress_max(local_time.tm_wday)) {
sql_fit_set_stress_max(hrvValue, local_time.tm_wday);
}
if (hrvValue != 0 && hrvValue < sql_fit_get_stress_min(local_time.tm_wday)) {
sql_fit_set_stress_min(hrvValue, local_time.tm_wday);
}
if (hrvValue > 0 && hrvValue < 100) {
uint32_t index = spo2_hrv_get_curtime_index(&timestamp);
sql_fit_set_stress_curdata(index, hrvValue);
sql_fit_set_last_stress(hrvValue, local_time.tm_wday);
}
}
} else {
if (id == HR_SERVICE_HR_ALLDAY || id == HR_SERVICE_BO_ALLDAY || id == HR_SERVICE_STRESS_ALLDAY) {
stop_count++;
if (stop_count == 3) {
stop_count = 0;
return -1;
}
}
}
g_ui_cur_hrvalue = hrValue;
g_ui_cur_spo2value = spo2Value;
g_ui_cur_hrvvalue = hrvValue;
return 0;
}
static signed int service_hrsensor_handle(void *param)
{
bool need_close = true;
hr_service_info_t *hr_service_info = (hr_service_info_t *)param;
if (hr_service_info->time_ms == 0xffffffff) {
if (g_hr_is_running) {
tjd_task_service_hrsensor_store_data(hr_service_info->id);
need_close = false;
}
} else if (hr_service_info->time_ms >= 1000) {
hr_service_info->time_ms -= 1000;
need_close = false; // 还有需要运行的心率的模块
if (tjd_task_service_hrsensor_store_data(hr_service_info->id) == -1) {
need_close = true;
}
} else {
hr_service_info->time_ms = 0;
hr_service_info->status = HRS_STATUS_OFF;
need_close = true;
}
if (need_close) {
g_ui_cur_hrvalue = 0;
g_ui_cur_spo2value = 0;
g_ui_cur_hrvvalue = 0;
tjd_service_hrsensor_close();
tjd_protocol_measure_data_send(hr_service_info->id);
return 0;
}
return 1000;
}
static signed int tjd_service_timer_hrsensor_start_send(void *param)
{
static_print_info("tjd_service_timer_hrsensor_start_send");
static hr_service_info_t hr_service_info = {0};
hr_service_info_t temp_hr_service_info = {0};
temp_hr_service_info = *(hr_service_info_t *)param;
if (temp_hr_service_info.id >= HR_SERVICE_MAX)
return HRS_STATUS_ERROR;
if (g_hr_is_running == false) {
g_hr_is_running = true;
} else {
if (hr_service_info.time_ms != 0) {
tjd_service_hrsensor_close();
g_hr_is_running = true;
}
}
if (temp_hr_service_info.id == HR_SERVICE_BO_ALLDAY || temp_hr_service_info.id == HR_SERVICE_UI_BO)
tjd_driver_hr_api_get_ops()->mode_set(HR3695_SPO2_MODE);
else if (temp_hr_service_info.id == HR_SERVICE_STRESS_ALLDAY)
tjd_driver_hr_api_get_ops()->mode_set(HR3695_HRV_MODE);
else
tjd_driver_hr_api_get_ops()->mode_set(HR3695_HRS_MODE);
hr_service_info = temp_hr_service_info;
queue_default_info_t msg_data = {service_hrsensor_handle, &hr_service_info, 1000, NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_timer_hrsensor_start succ.");
return HRS_STATUS_ON;
}
static signed int tjd_service_timer_hrsensor_end_send(void *param)
{
static_print_info("tjd_service_timer_hrsensor_end_send");
queue_default_info_t msg_data = {service_hrsensor_handle, NULL, 0, NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
if (ret != OSAL_SUCCESS) {
static_print_error("[%s] osal_msg_queue_write_copy fail", __func__);
return ret;
}
g_hr_is_running = false;
static_print_info("service_timer_hrsensor_end succ.");
return HRS_STATUS_OFF;
}
// 整点每5分钟测量
static signed int tjd_task_service_timer_hrsensor_hr_all_day_handle(void *param)
{
static bool exit_flag = true;
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
// 整点不测量(和整点血氧一起出值)
if ((local_time.tm_min == 0 && exit_flag)||(tjd_service_charger_get_charger_status())) {
uint32_t trigger_sec = local_time.tm_min % HR_INTERVAL_MIN == 0
? (HR_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((HR_INTERVAL_MIN * 60) - (local_time.tm_min % HR_INTERVAL_MIN * 60 - local_time.tm_sec));
return trigger_sec * 1000;
}
if (g_hr_is_running) {
exit_flag = false;
return 120 * 1000; // 推迟120s再运行
}
//更新时间给算法。
struct algo_datetime date;
date.year = local_time.tm_year;
date.mon = local_time.tm_mon;
date.day = local_time.tm_mday;
date.hour = local_time.tm_hour;
date.min = local_time.tm_min;
date.sec = local_time.tm_sec;
cwm_set_datetime_to_algo(&date, sizeof(struct algo_datetime));
static_print_debug("tjd_task_service_timer_hrsensor_hr_all_day_handle");
hr_service_info_t hr_service_info = {HR_SERVICE_HR_ALLDAY, LOOP_PERIOD_TIME, HRS_STATUS_ON};
tjd_service_timer_hrsensor_start_send((void *)&hr_service_info);
exit_flag = true;
uint32_t trigger_sec = local_time.tm_min % HR_INTERVAL_MIN == 0
? (HR_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((HR_INTERVAL_MIN * 60) - (local_time.tm_min % HR_INTERVAL_MIN * 60 - local_time.tm_sec));
return trigger_sec * 1000;
}
// 整点每60分钟测量
static signed int tjd_task_service_timer_hrsensor_spo2_all_day_handle(void *param)
{
if (g_hr_is_running) {
return 120 * 1000; // 推迟120s再运行
}
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
uint32_t trigger_sec = local_time.tm_min % SPO2_INTERVAL_MIN == 0
? (SPO2_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((SPO2_INTERVAL_MIN * 60)-(local_time.tm_min % SPO2_INTERVAL_MIN * 60 - local_time.tm_sec));
if (tjd_service_charger_get_charger_status())
{
return trigger_sec * 1000;
}
static_print_debug("tjd_task_service_timer_hrsensor_spo2_all_day_handle");
hr_service_info_t hr_service_info = {HR_SERVICE_BO_ALLDAY, LOOP_PERIOD_TIME, HRS_STATUS_ON};
tjd_service_timer_hrsensor_start_send((void *)&hr_service_info);
return trigger_sec * 1000;
}
// 整点每60分钟测量
static signed int tjd_task_service_timer_hrsensor_hrv_all_day_handle(void *param)
{
if (g_hr_is_running) {
return 120 * 1000; // 推迟120s再运行
}
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
uint32_t trigger_sec = local_time.tm_min % HRV_INTERVAL_MIN == 0
? (HRV_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((HRV_INTERVAL_MIN * 60)-(local_time.tm_min % HRV_INTERVAL_MIN * 60 - local_time.tm_sec));
if (tjd_service_charger_get_charger_status())
{
return trigger_sec * 1000;
}
hr_service_info_t hr_service_info = {HR_SERVICE_STRESS_ALLDAY, HRV_LOOP_PERIOD_TIME, HRS_STATUS_ON};
tjd_service_timer_hrsensor_start_send((void *)&hr_service_info);
return trigger_sec * 1000;
}
static int32_t tjd_service_hrsensor_hr_allday_open(void)
{
if (g_hr_service_inited == false) {
static_print_error("tjd_service_hrsensor_hr_allday_open fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
uint32_t trigger_sec = local_time.tm_min % HR_INTERVAL_MIN == 0
? (HR_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((HR_INTERVAL_MIN * 60)-(local_time.tm_min % HR_INTERVAL_MIN * 60 - local_time.tm_sec));
static_print_debug("tjd_service_hrsensor_hr_allday_open trigger_sec:%d", trigger_sec);
queue_default_info_t msg_data = {tjd_task_service_timer_hrsensor_hr_all_day_handle, NULL, trigger_sec * 1000, NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_hrsensor_spo2_allday_open succ!");
return 0;
}
static int32_t tjd_service_hrsensor_hr_allday_close(void)
{
if (g_hr_service_inited == false) {
static_print_error("tjd_service_hrsensor_hr_allday_close fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
queue_default_info_t msg_data = {tjd_task_service_timer_hrsensor_hr_all_day_handle, NULL, 0, NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_hrsensor_spo2_allday_close succ!");
return 0;
}
static int32_t service_hrsensor_spo2_allday_open(void)
{
if (g_hr_service_inited == false) {
static_print_error("service_hrsensor_spo2_allday_open fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
uint32_t trigger_sec = local_time.tm_min % SPO2_INTERVAL_MIN == 0
? (SPO2_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((SPO2_INTERVAL_MIN * 60)-(local_time.tm_min % SPO2_INTERVAL_MIN * 60 - local_time.tm_sec));
queue_default_info_t msg_data = {tjd_task_service_timer_hrsensor_spo2_all_day_handle, NULL, trigger_sec * 1000,
NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_hrsensor_spo2_allday_open succ!");
return 0;
}
static int32_t service_hrsensor_spo2_allday_close(void)
{
if (g_hr_service_inited == false) {
static_print_error("service_hrsensor_spo2_allday_close fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
queue_default_info_t msg_data = {tjd_task_service_timer_hrsensor_spo2_all_day_handle, NULL, 0, NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_hrsensor_spo2_allday_close succ!");
return 0;
}
static int32_t service_hrsensor_hrv_allday_open(void)
{
if (g_hr_service_inited == false) {
static_print_error("service_hrsensor_hrv_allday_open fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
struct rtc_time local_time;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
uint32_t trigger_sec = local_time.tm_min % HRV_INTERVAL_MIN == 0
? (HRV_INTERVAL_MIN * 60 - local_time.tm_sec)
: ((HRV_INTERVAL_MIN * 60)-(local_time.tm_min % HRV_INTERVAL_MIN * 60 - local_time.tm_sec));
static_print_debug("service_hrsensor_hrv_allday_open trigger_sec:%d", trigger_sec);
queue_default_info_t msg_data = {tjd_task_service_timer_hrsensor_hrv_all_day_handle, NULL, trigger_sec * 1000,
NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_hrsensor_hrv_allday_open succ!");
return 0;
}
static int32_t service_hrsensor_hrv_allday_close(void)
{
if (g_hr_service_inited == false) {
static_print_error("service_hrsensor_hrv_allday_close fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
queue_default_info_t msg_data = {tjd_task_service_timer_hrsensor_hrv_all_day_handle, NULL, 0, NULL};
int ret = osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data,
sizeof(queue_default_info_t), 0);
static_print_info("service_hrsensor_hrv_allday_close succ!");
return 0;
}
static int32_t tjd_service_hrsensor_open(hr_api_info_t hr_api_info)
{
if (g_hr_service_inited == false) {
static_print_error("tjd_service_hrsensor_open fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
g_hr_service_id = hr_api_info.id;
hr_service_info_t hr_service_info = {hr_api_info.id, hr_api_info.time_ms, HRS_STATUS_ON};
tjd_service_timer_hrsensor_start_send((void *)&hr_service_info);
return HRS_STATUS_ON;
}
static int32_t tjd_service_hrsensor_close(void)
{
if (g_hr_service_inited == false) {
static_print_error("tjd_service_hrsensor_close fail. g_hr_service_inited is false");
return HRS_STATUS_ERROR;
}
//未佩戴,发送一次状态
if(!g_hr_data.wear_status)
{
cwm_set_device_status(g_hr_data.wear_status);
cwm_set_hr_value(0);
}
tjd_service_timer_hrsensor_end_send(NULL);
tjd_driver_hr_api_get_ops()->mode_set(HR3695_CLOSE);
return HRS_STATUS_OFF;
}
uint8_t tjd_service_hrsensor_get_cur_hrvalue(void) { return g_ui_cur_hrvalue; }
uint8_t tjd_service_hrsensor_get_cur_spo2value(void) { return g_ui_cur_spo2value; }
uint8_t tjd_service_hrsensor_get_cur_stressvalue(void) { return g_ui_cur_hrvvalue; }
static void tjd_service_hrsensor_init(void)
{
if (g_hr_service_inited == true) {
static_print_error("hr_service has been opened");
return;
}
g_hr_servise_timer = osTimerNew(hr_service_timer_callback, osTimerOnce, NULL, NULL);
if (!g_hr_servise_timer) {
static_print_error("g_hr_servise_timer osTimerNew failed");
return;
}
struct rtc_time localTime;
tjd_driver_rtc_get_ops()->get_rtc_time(&localTime);
uint32_t next_sec = ((24-localTime.tm_hour)*3600) - (localTime.tm_min*60) - localTime.tm_sec;
osStatus_t ret = osTimerStart(g_hr_servise_timer, next_sec*1000);
if (ret != osOK) {
static_print_error("tjd_service_hrsensor_init osTimerStart failed:%d", ret);
return;
}
g_hr_service_inited = true;
static_print_info("hr_service open suceess");
}
static void tjd_protocol_measure_data_send(const uint8_t id)
{
uint32_t index = 0;
uint64_t timestamp = 0;
static send_measure_data_t send_data = {0};
struct rtc_time local_time;
uint8_t stress_min = 0, stress_max = 0;
uint8_t *heartrate_array = NULL;
uint8_t *spo2_array = NULL;
uint8_t *stress_array = NULL;
tjd_driver_rtc_get_ops()->get_rtc_time(&local_time);
if(id ==HR_SERVICE_BO_ALLDAY || id == HR_SERVICE_UI_BO){
index = spo2_hrv_get_curtime_index(&timestamp);
sql_fit_get_spo2_daydata(&spo2_array);
send_data.mode = MeasureMode_Spo2;
send_data.vlue = spo2_array[index];
}else if(id == HR_SERVICE_STRESS_ALLDAY){
index = spo2_hrv_get_curtime_index(&timestamp);
stress_max = sql_fit_get_stress_max(local_time.tm_wday);
stress_min = sql_fit_get_stress_min(local_time.tm_wday);
sql_fit_get_sterss_daydata(&stress_array);
send_data.mode = MeasureMode_Blood;
send_data.vlue = ((stress_max<<8)&0xFF00) | ((stress_min)&0xFF);
}else{
index = hr_get_curtime_index(&timestamp);
sql_fit_get_hr_daydata(&heartrate_array);
send_data.mode = MeasureMode_Heart;
send_data.vlue = heartrate_array[index];
}
tjd_service_send_current_measurement_data(&send_data);
}
static void tjd_service_hrsensor_deinit(void) { g_hr_service_inited = false; }
static hr_wear_status_t tjd_service_hrsensor_get_wear_status(void) { return g_hr_data.wear_status; }
static hr_service_id_t tjd_service_hrsensor_get_service_id(void) { return g_hr_service_id; }
static service_hrs_api g_service_hrs_info = {
.init = tjd_service_hrsensor_init,
.deinit = tjd_service_hrsensor_deinit,
.open = tjd_service_hrsensor_open,
.close = tjd_service_hrsensor_close,
.hr_allday_open = tjd_service_hrsensor_hr_allday_open,
.hr_allday_close = tjd_service_hrsensor_hr_allday_close,
.spo2_allday_open = service_hrsensor_spo2_allday_open,
.spo2_allday_close = service_hrsensor_spo2_allday_close,
.hrv_allday_open = service_hrsensor_hrv_allday_open,
.hrv_allday_close = service_hrsensor_hrv_allday_close,
.hrs_wear_status = tjd_service_hrsensor_get_wear_status,
.hrs_get_service_id = tjd_service_hrsensor_get_service_id,
};
service_hrs_api *tjd_service_hrs_get_ops(void) { return &g_service_hrs_info; }