637 lines
24 KiB
C
637 lines
24 KiB
C
/*----------------------------------------------------------------------------
|
||
* 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(×tamp);
|
||
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(×tamp);
|
||
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(×tamp);
|
||
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(×tamp);
|
||
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(×tamp);
|
||
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(×tamp);
|
||
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(×tamp);
|
||
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; }
|