From: @CHENG <2393524978@qq.com> Date: Tue, 3 Dec 2024 09:23:15 +0000 (+0800) Subject: k18 lib_hr_yll_v0.5.3.120324.a X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=84e454fcd6da38c0786b39a5202bf22f5103d62d;p=mirrors%2FASR3603_Z5.git k18 lib_hr_yll_v0.5.3.120324.a --- diff --git a/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor.c b/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor.c index 2bd2dfee..f52f6f48 100644 --- a/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor.c +++ b/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor.c @@ -72,6 +72,7 @@ void mmi_health_info_get(nv_watch_health_info_t * health_info) health_info->blood_low_value = s_health_info.blood_low_value; health_info->spo2_value = s_health_info.spo2_value; health_info->body_value = s_health_info.body_value; + memcpy(&(health_info->heart_time), &(s_health_info.heart_time), sizeof(hal_rtc_t)); #endif } @@ -82,6 +83,7 @@ void mmi_health_info_set(nv_watch_health_info_t * health_info) s_health_info.blood_low_value = health_info->blood_low_value; s_health_info.spo2_value = health_info->spo2_value; s_health_info.body_value = health_info->body_value; + memcpy(&(s_health_info.heart_time), &(health_info->heart_time), sizeof(hal_rtc_t)); uint32_t nv_data_length = sizeof(nv_watch_health_info_t); diff --git a/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c b/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c index eb3ee8a4..35787d41 100644 --- a/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c +++ b/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c @@ -997,6 +997,8 @@ const void * lang_text_ch[] = { "天线耦合", // WATCH_TEXT_ID_ANTENNA_COUPLING, "脉搏波测试", // WATCH_TEXT_ID_PULSE_WAVE_TEST, "测试时请保持静止", // WATCH_TEXT_ID_PULSE_WAVE_PROMPT, + "深睡", // WATCH_TEXT_ID_DEEP_SLEEP, + "浅睡", // WATCH_TEXT_ID_LIGHT_SLEEP, //CHENG_MODIFY "确认是否跌倒?", // WATCH_TEXT_ID_falldown, diff --git a/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c b/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c index 873e6361..650c6d1f 100644 --- a/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c +++ b/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c @@ -998,6 +998,8 @@ const void * lang_text_en[] = { "Antenna coupling", // WATCH_TEXT_ID_ANTENNA_COUPLING, "pulse wave", // WATCH_TEXT_ID_PULSE_WAVE_TEST, "Keep still", // WATCH_TEXT_ID_PULSE_WAVE_PROMPT, + "Deep sleep", // WATCH_TEXT_ID_DEEP_SLEEP, + "Light sleep", // WATCH_TEXT_ID_LIGHT_SLEEP, //CHENG_MODIFY "Confirm a fall", diff --git a/2.sdk/sdk/gui/lv_watch/include/ui_nvm_interface.h b/2.sdk/sdk/gui/lv_watch/include/ui_nvm_interface.h index 90c303bb..f2918721 100644 --- a/2.sdk/sdk/gui/lv_watch/include/ui_nvm_interface.h +++ b/2.sdk/sdk/gui/lv_watch/include/ui_nvm_interface.h @@ -226,6 +226,7 @@ typedef struct typedef struct { uint16_t heart_value; + hal_rtc_t heart_time; uint16_t blood_high_value; uint16_t blood_low_value; uint16_t spo2_value; diff --git a/2.sdk/sdk/gui/lv_watch/include/ui_textid.h b/2.sdk/sdk/gui/lv_watch/include/ui_textid.h index ed68a11c..c4ec5658 100644 --- a/2.sdk/sdk/gui/lv_watch/include/ui_textid.h +++ b/2.sdk/sdk/gui/lv_watch/include/ui_textid.h @@ -1005,6 +1005,8 @@ enum WATCH_TEXT_ID_ANTENNA_COUPLING, /* "天线耦合" "Antenna coupling" */ WATCH_TEXT_ID_PULSE_WAVE_TEST, /* "脉搏波测试" "pulse wave" */ WATCH_TEXT_ID_PULSE_WAVE_PROMPT, /* "测试时请保持静止" "Keep still" */ + WATCH_TEXT_ID_DEEP_SLEEP, /* "深睡" "Deep sleep" */ + WATCH_TEXT_ID_LIGHT_SLEEP, /* "浅睡" "Light sleep" */ //CHENG_MODIFY WATCH_TEXT_ID_FALLDWON, /*确认是否跌倒*/ diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/heng_ai_sleep_k18.c b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/heng_ai_sleep_k18.c index 9f867287..bb260dab 100644 --- a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/heng_ai_sleep_k18.c +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/heng_ai_sleep_k18.c @@ -397,7 +397,7 @@ static bool mmi_hengai_k18_sleep_data_send(void) static void mmi_hengai_k18_sleep_data_get(void) { - if(0 != mmi_hsensor_measure_get_wear_status()) + //if(0 != mmi_hsensor_measure_get_wear_status()) { sleep_time_t curtime = {0}; hal_rtc_t cur_time = {0}; @@ -410,7 +410,19 @@ static void mmi_hengai_k18_sleep_data_get(void) curtime.minute = cur_time.tm_min; int result = 0; - result = get_sleep_time(s_hengai_sleep_gsensor_data, HENGAI_SLEEP_GSENSOR_DATA_MAX, curtime, &s_hengai_sdata); +/* + int get_sleep_data_ex(gsensor_data_t gdata[], const int glen, int pdata[], const int plen, const sleep_time_t curtime, sleep_data_t* sdata); + - gdata£¬gsensorÊý×飨gsensorÊý¾Ý½á¹¹ÔÚÍ·ÎļþÖж¨Ò壩£¬²É¼¯µÄgsensorÊý¾Ý + - glen£¬ÕûÐÍ£¬gdata³¤¶È£¨Ò»°ãÊäÈë1sÖӵij¤¶È£¬¼´60*fs£© + - pdata£¬ppgÊý×飬²É¼¯µÄppgÊý¾Ý + - plen£¬ÕûÐÍ£¬gdata³¤¶È£¨Ò»°ãÊäÈë1sÖӵij¤¶È£¬¼´60*fs£© + - curtime£¬×Ô¶¨ÒåÀàÐÍ£¬µ±Ç°Ê±¼ä£¨¾«È·µ½·ÖÖÓ£© + - sdata, sleep_dataÖ¸ÕëÀàÐÍ£¬·µ»ØµÄʱ¼äÊý¾Ý + ##### ·µ»ØÖµ£º + - result£¬ÕûÐÍ£¬0±íʾûÓÐ˯ÃßÊý¾Ý£¬1±íʾ·µ»ØË¯ÃßÊý¾Ý +*/ + result = get_sleep_data_ex(s_hengai_sleep_gsensor_data, HENGAI_SLEEP_GSENSOR_DATA_MAX, NULL, 0, curtime, &s_hengai_sdata); + printf("[@CHENG_DEBUG][%s][%d]: result=%d\n", __FUNCTION__, __LINE__, result); HENGAI_HEALTH_UART_LOG("[@CHENG_DEBUG][%s][%d]: result=%d\n", __FUNCTION__, __LINE__, result); if(1 == result) @@ -471,6 +483,39 @@ void mmi_hengai_k18_get_sleep_data_cb(uint32_t para) mmi_hengai_k18_sleep_task_msg_send(MMI_WATCH_SLEEP_MSG_600MS); //, void * msg_param) } +static void mmi_hengai_k18_sleep_get_hr_cb(uint8_t * hr, sleep_time_t * hr_time) +{ + nv_watch_health_info_t health_info = {0}; + + mmi_health_info_get(&health_info); + if(0 != health_info.heart_value) + { + *hr = health_info.heart_value; + hr_time->year = health_info.heart_time.tm_year; + hr_time->month = health_info.heart_time.tm_mon; + hr_time->day = health_info.heart_time.tm_mday; + hr_time->hour = health_info.heart_time.tm_hour; + hr_time->minute = health_info.heart_time.tm_min; + } + else + { + *hr = 70; + memset(hr_time, 0x0, sizeof(sleep_time_t)); + } +} + +static void mmi_hengai_k18_sleep_get_wear_cb(int8_t * worn) +{ + if(mmi_hsensor_measure_get_wear_status()) + { + *worn = 1; + } + else + { + *worn = 0; + } +} + void mmi_hengai_get_sleep_data_start(void) { printf("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); @@ -487,8 +532,31 @@ void mmi_hengai_get_sleep_data_start(void) s_hengai_sleep_gsensor_counter = 0; _lv_memset_00(s_hengai_sleep_gsensor_data, sizeof(s_hengai_sleep_gsensor_data)); - //³õʼ»¯sdata - init_sleep_data(&s_hengai_sdata); +/* + unsigned int extern_get_wear_state_cb_reg(extern_get_wear_state_cb_t fun); + - fun£¬typedef void (*extern_get_wear_state_cb_t)(int8_t* worn) + ÀàÐͺ¯ÊýÖ¸Õ룬¸Ãº¯ÊýÓÉÓ¦Ó÷½¶¨Òå²¢´«Èë¸ø¸Ã×¢²á½Ó¿Ú¡£ + - º¯ÊýÖ¸ÕëÖ¸ÏòµÄº¯ÊýÔ­Ð͵IJÎÊýÐè×öÈçÏÂ˵Ã÷£º + - worn, ÕûÐÍÖ¸Õ룬1±íʾÅå´÷£¬ 0±íʾδÅå´÷¡£ +*/ + extern_get_wear_state_cb_reg(mmi_hengai_k18_sleep_get_wear_cb); + +/* + unsigned int extern_get_inst_hr_cb_reg(extern_get_inst_hr_cb_t fun); + - fun£¬typedef void (*extern_get_inst_hr_cb_t)(uint8_t* hr, sleep_time_t* hr_time);ÀàÐͺ¯ÊýÖ¸Õ룬¸Ãº¯ÊýÓÉÓ¦Ó÷½¶¨Òå²¢´«Èë¸ø¸Ã×¢²á½Ó¿Ú¡£ + - º¯ÊýÖ¸ÕëÖ¸ÏòµÄº¯ÊýÔ­Ð͵IJÎÊýÐè×öÈçÏÂ˵Ã÷£º + - hr, ÕûÐÍÖ¸Õ룬µ±Ç°µÄÐÄÂÊÖµ¡£ + - hr_time, ˯Ãßʱ¼ä½á¹¹Ì壬ÊäÈëÐÄÂʵ±Ç°Ê±¼ä +*/ + extern_get_inst_hr_cb_reg(mmi_hengai_k18_sleep_get_hr_cb); + +/* + void init_sleep_algo_ex(sleep_data_t* sdata, int gfs, int pfs); + - sdata, sleep_dataÖ¸ÕëÀàÐÍ£¬½á¹¹¼ûÍ·Îļþ¡£ + - gfs, ÕûÐÍ£¬gsensorÊý¾Ý²ÉÑùÂÊ + - pfs, ÕûÐÍ£¬ppgÊý¾Ý²ÉÑùÂÊ +*/ + init_sleep_algo_ex(&s_hengai_sdata, 50, 0); uos_timer_start(s_hengai_sleep_gsensor_timer_id, MS_TO_TICKS(600), diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/health_measure/health_measure.c b/2.sdk/sdk/gui/lv_watch/lv_apps/health_measure/health_measure.c index 8090dacf..5d58d63f 100644 --- a/2.sdk/sdk/gui/lv_watch/lv_apps/health_measure/health_measure.c +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/health_measure/health_measure.c @@ -696,6 +696,7 @@ void mmi_health_measure_send_heart(void * param) nv_watch_health_info_t health_info = {0}; mmi_health_info_get(&health_info); health_info.heart_value = heart_value; + Hal_Rtc_Gettime(&(health_info.heart_time)); mmi_health_info_set(&health_info); } diff --git a/2.sdk/sdk/product/craneg_modem/CMakeLists.txt b/2.sdk/sdk/product/craneg_modem/CMakeLists.txt index 21d66484..c52073fb 100644 --- a/2.sdk/sdk/product/craneg_modem/CMakeLists.txt +++ b/2.sdk/sdk/product/craneg_modem/CMakeLists.txt @@ -547,7 +547,7 @@ set_property(TARGET modem PROPERTY IMPORTED_OBJECTS softutil/rsfota/redstone/lib/librsdl.a cust/heng_ai_sleep/lib/lib_sleep_yll_v0.2.6.111623.a #cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.090324.lib - cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120224.lib + cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120324.a # MODEM_LIB_ALIOS_LTEGSM_END ) endif() # if($ENV{PS_MODE} STREQUAL "LTEGSM") diff --git a/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120224.lib b/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120224.lib deleted file mode 100644 index 25bdb068..00000000 --- a/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120224.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4497f147cda742ae1023055118d4aa8fef6ca2d8f63c994762fd7eae3617be75 -size 222712 diff --git a/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120324.a b/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120324.a new file mode 100644 index 00000000..950a271b Binary files /dev/null and b/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/lib_hr_yll_v0.5.3.120324.a differ diff --git "a/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/\343\200\220\345\265\214\345\205\245\345\274\217\347\253\257\343\200\221Pro\347\211\210\344\270\213\346\262\211\345\272\223\346\216\245\345\217\243\346\226\207\346\241\243.md" "b/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/\343\200\220\345\265\214\345\205\245\345\274\217\347\253\257\343\200\221Pro\347\211\210\344\270\213\346\262\211\345\272\223\346\216\245\345\217\243\346\226\207\346\241\243.md" new file mode 100644 index 00000000..622c3a93 --- /dev/null +++ "b/2.sdk/sdk/product/craneg_modem/cust/heng_ai_sleep/lib/\343\200\220\345\265\214\345\205\245\345\274\217\347\253\257\343\200\221Pro\347\211\210\344\270\213\346\262\211\345\272\223\346\216\245\345\217\243\346\226\207\346\241\243.md" @@ -0,0 +1,881 @@ +# YYLPro下沉算法库接口说明文档 + +***恒爱*** +***2022å¹´07月07日*** + +************************************************************************ + +| 版本 | 日期 | 作者 | 状态 | 描述 | +| ---- | ---------- | --- | --- | -------------- | +| V0.0 | 2022-07-07 | hl | 初稿 | 项目初始文档 | +| v0.1 | 2022-09-22 | hl | 修改稿 | 改接口说明 | +| v0.2 | 2022-10-31 | hl | 修改稿 | 添加内存初始化接口 | +| v0.3 | 2023-02-01 | hl | 修改稿 | 添加HRV中间值接口 | +| v0.4 | 2023-05-09 | hl | 修改稿 | 添加血压接口和获取版本号接口 | +| v0.5 | 2023-09-26 | hl | 修改稿 | 添加云医链相关算法接口 | + +************************************************************************ + +## 1 概述 + + 本文档定义了下沉算法库算法库接口信息和使用规范。 + 本文档的主要目的是为了嵌入式工程师能够按照正确的方法使用算法库,并加快开发进度。 + 本文档的阅读对象是项目相关的项目经理、嵌入式工程师。 + +************************************************************************ + +## 2 算法库接口定义 + +--------------------------------------------------------------------------------------------------------------------------- + +### 2.1 申请认证接口 + +##### 原型: + +``` +void request_validation(const unsigned char fact[], const unsigned int fact_len,const unsigned char imei[], const unsigned int imei_len,unsigned char req_code[], unsigned int* req_code_len); +``` + +##### 输入: + +- fact,字符串型,厂商名称 + +- fact_len,无符号整型,字符串fact长度,不超过16个字符 + +- imei,字符串型,设备号 + +- imei_len,无符号整型,字符串imei长度,一般为12个字符 + +##### 输出: + +- req_code,字符串型,算法库激活请求码 + +- req_code_len,无符号整型指针,字符串req_code长度的指针 + +##### 返回值: + +- 无 + +##### 说明: + +- 调用中间值、压力、心率算法之前调用此接口,并把输出的算法激活请求码req_code持久化存储在本地,并传给手机APP端; +- 手机APP端通过该请求码向服务器申请认证,认证成功则返回激活码,手表接收到此激活码后同样进行持久化存储在本地。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 2.2 算法激活接口 + +``` +int activate_algorithm(const unsigned char req_code[], const unsigned int req_code_len,const unsigned char key_code[], const unsigned int key_code_len); +``` + +##### 输入: + +- req_code,字符串型,调用request_validation接口得到的req_code字符串(请求码) + +- req_code_len,无符号整型,字符串req_code的长度 + +- key_code,字符串型,调用request_validation接口后从手机端返回的激活码,或者本地存储的激活码 + +- key_code_len,无符号整型,字符串key_code的长度 + +##### 输出: + +- 无 + +##### 返回值: + +- status,整型,0表示激活失败,1表示激活成功 + +##### 说明: + +- 调用中间值、压力、心率算法之前,接收到APP端返回的激活码之后,调用此接口。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.3 中间值接口 + +##### 原型: + +``` +int ppg_midvalue(int data[], int datalen, int fs, float Fm[50][8], int* fmlen); +``` + +##### 输入: + +- data,整型数组,采集的ppg数据 + +- datalen,整型,data长度(一般为10s的数据长度,即10*fs) + +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +- Fm[50][8],二维浮点型数组,存放计算出的中间值,该中间值用于向服务器请求服务器端算法支持。 + +- fmlen,整型指针,存放中间值的有效个(组)数 + +##### 返回值: + +- status,整型,-1表示该算法未被激活,-2表示未佩戴,-3表示运动中,-4表示信号差计算失败,0表示正常计算出中间值 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 + +- 头文件中的SAMPLETIME值定义每次输入接口的最大数据长度,例如SAMPLETIME值为10,表示每次输入接口的最大数据长度不大于10s,即10*fs个数据。 + +- 该接口循环调用,每满datalen长度的新数据就调用一次。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.4 心率接口 + +##### 原型: + +``` +int get_hr(int data[], int datalen, int fs, int* hr); +``` + +##### 输入: + +- data,整型数组,采集的ppg数据 + +- datalen,整型,data长度(一般为5s的数据长度,即5*fs) + +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +- hr,整型指针,存储计算出的心率值 + +##### 返回值: + +- status,整型,-1表示该算法未被激活,-2表示未佩戴,-3表示运动中,0表示正常计算出心率。 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 + +- 头文件中的SAMPLETIME值定义每次输入接口的最大数据长度,例如SAMPLETIME值为10,表示每次输入接口的最大数据长度不大于10s,即10*fs个数据。 + +- 该接口一般采用加滑动窗的形式进行循环使用,滑动窗长即为datalen,滑动窗的步长一般为1s的数据,即fs个数据。 + +- 使用该接口前一定要注册3.6的心率调用类型时间传入回调函数注册接口 ,否则无法正常返回心率值。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.5 情绪压力合并接口 + +##### 原型: + +``` +int get_emotion_pi(int data[], int datalen, int fs, int* emo, int* pi); +``` + +##### 输入: + +- data,整型数组,采集的ppg数据 +- datalen,整型,data长度(可为10s的数据长度,即10*fs) +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +- emo, 整型指针,存储计算的情绪结果(-1表示数据量不足,需要继续调用若干次)0表示消极情绪,1表示平和情绪,2表示积极情绪。 +- pi,整型指针,存储计算的压力结果(-1表示数据量不足,需要继续调用若干次) + +##### 返回值: + +- status,整型,-1表示该算法未被激活,-5表示当前次调用输出情绪压力值不可用,0表示已得出正确的压力值。 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 +- 头文件中的SAMPLETIME值定义每次输入接口的最大数据长度,例如SAMPLETIME值为5,表示每次输入接口的最大数据长度不大于5s,即5*fs个数据。 +- 该接口循环调用,目前设定每datalen=5s调用一次,调用6次(即1分钟)可出情绪压力结果。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.6 心率调用类型时间传入回调函数注册接口 + +##### 原型: + +``` +unsigned int extern_get_hr_run_time_cb_reg(extern_get_hr_run_time_cb_t fun); +``` + +##### 输入: + +- fun,typedef void (*extern_get_hr_run_time_cb_t)(int *type, int *sec)类型函数指针,该函数由应用方定义并传入给该注册接口。 + + - 函数指针指向的函数原型的参数需做如下说明: + + - type, 整型指针,定义当前应用需要测量的心率处于何种模式下,目前可定义以下4种模式: + + - 一般模式,手表正常佩戴不做任何操作, type = 0, + - 运动模式,手表点击进入运动模式,type = 1, + - 实时模式,手表打开心率测量界面,type = 2, + - 其他状态,type = 3. + + - sec, 整型指针,定义当前模式开启的时间(单位为s),相当于一个秒表计数器,从心率模块打开开始从0计时,每过1s加1;心率模块关闭就清零。 + +##### 返回值: + +- 0。 + +##### 说明: + +- 在应用算法之前需要把该接口注册好,方便根据外部信息做算法结果修正。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.8 日志打印回调函数注册接口 + +##### 原型: + +``` +unsigned int extern_printf_cb_reg(extern_printf_cb_t fun); +``` + +##### 输入: + +- fun,typedef void (*extern_printf_cb_t)(const char* format, ...)类型函数指针,改函数由应用方定义并传入给传入给注册接口 + +##### 返回值: + +- 0。 + +##### 说明: + +- 在应用算法之前需要把该接口注册好,方便打印算法内部日志。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.9 内存初始化接口 + +##### 原型: + +``` +int init_algorithm(unsigned char* buf, unsigned int len); +``` + +##### 输入: + +- buf,无符号字符串型,给算法使用的整块存储空间首地址 + +- len,无符号整型,给算法使用的整块存储空间地址长度(按字节计算) + +##### 返回值: + +- status,整型,-21表示内存空间不足,0内存空间初始化成功。 + +##### 说明: + +- 当前算法使用大块空间输入必须大于等于 3 * 100 * SAMPLETIME * sizeof(int) + 30 * 10 * sizeof(int) + 25 * 8 * sizeof(float)。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.10 HRV中间值接口 + +##### 原型: + +``` +int ppg_hrv_midvalue(int data[], int datalen, int fs, float midv[25], int* midvlen); +``` + +##### 输入: + +- data,整型数组,采集的ppg数据 + +- datalen,整型,data长度(一般为10s的数据长度,即10*fs) + +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +- midv[25],一维浮点型数组,存放计算出的中间值,该中间值用于向服务器请求HRV算法支持。 + +- midvlen,整型指针,存放中间值的有效个(组)数 + +##### 返回值: + +- status,整型,-1表示该算法未被激活,-2表示未佩戴,-3表示运动中,-4表示信号差计算失败,0表示正常计算出中间值 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 + +- 头文件中的SAMPLETIME值定义每次输入接口的最大数据长度,例如SAMPLETIME值为10,表示每次输入接口的最大数据长度不大于2s,即2*fs个数据。 + +- 该接口循环调用,每满datalen长度的新数据就调用一次,每次调用后把midvlen长度的midv[]存储起来。 + +- 当存储的midv[]满6分钟(若函数每次调用输入数据长度为5s钟数据,则函数调用72次),把它传给手机APP。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.11 加载模型接口 + +##### 原型: + +``` +int load_bp_model(unsigned char str_model[], const unsigned int str_model_len); +``` + +##### 输入: + +- str_model,字符串,从后台请求的个人血压模型简易版字符串 + +- str_model_len,整型,字符串长度 + +##### 输出: + +##### 返回值: + +- status,整型,0表示加载成功,其他表示加载失败 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 + +- APP向后台请求简易模型,然后下发至手表,手表可以把它存储起来。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.12 下沉血压算法接口 + +##### 原型: + +``` +int get_bp(int data[], int datalen, int fs, int* sbp, int* dbp); +``` + +##### 输入: + +- data,整型数组,采集的ppg数据 + +- datalen,整型,data长度(一般为10s的数据长度,即10*fs) + +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +- sbp,整型指针,存放计算出来的舒张压。 + +- dbp,整型指针,存放计算出来的收缩压。 + +##### 返回值: + +- status,整型,-1表示该算法未被激活,-2表示未佩戴,-3表示运动中,-5表示当前次调用输出血压值不可用,0表示已得出血压值。 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 + +- 头文件中的SAMPLETIME值定义每次输入接口的最大数据长度,例如SAMPLETIME值为5,表示每次输入接口的最大数据长度不大于5s,即5*fs个数据。 + +- 该接口循环调用,目前设定每datalen=5s调用一次,调用6次(即半分钟)可出血压结果。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.13 通用血压模型个人信息加载接口 + +##### 原型: + +``` +int load_gen_info(int height, int weight, int age, int gender); +``` + +##### 输入: + +- height,整型,受试身高(单位: cm) +- weight,整型,受试体重(单位: kg) +- age,整型,受试年龄 +- gender, 整型,受试性别,0:女, 1:男 + +##### 输出: + +##### 返回值: + +- status,整型,0表示加载成功,其他表示加载失败 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 +- 一定要在调用通用血压算法接口之前调用此接口。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.14 下沉通用血压算法接口 + +##### 原型: + +``` +int get_bp_general(int data[], int datalen, int fs, int* sbp, int* dbp); +``` + +##### 输入: + +- data,整型数组,采集的ppg数据 + +- datalen,整型,data长度(一般为10s的数据长度,即10*fs) + +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +- sbp,整型指针,存放计算出来的舒张压。 + +- dbp,整型指针,存放计算出来的收缩压。 + +##### 返回值: + +- status,整型,-1表示该算法未被激活,-2表示未佩戴,-3表示运动中,-5表示当前次调用输出血压值不可用,0表示已得出血压值。 + +##### 说明: + +- 一定要在调用申请认证接口和算法激活接口后再调用此接口。 + +- 头文件中的SAMPLETIME值定义每次输入接口的最大数据长度,例如SAMPLETIME值为5,表示每次输入接口的最大数据长度不大于5s,即5*fs个数据。 + +- 该接口循环调用,目前设定每datalen=5s调用一次,调用6次(即半分钟)可出血压结果。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.15 获取库版本接口 + +##### 原型: + +``` +void version_get_string(char* string, unsigned int* str_len); +``` + +##### 输入: + +##### 输出: + +- string,字符串数组,用于存放输出的版本号。 + +- str_len,整型指针,存放版本号的字符长度。 + +##### 返回值: + +- void + +##### 说明: + +- string的初始空间长度需要设为20以上。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.16 判断PPG信号好坏接口 + +##### 原型: + +``` +int is_good_ppg(int ppg[], unsigned int ppglen, int fs); +``` + +##### 输入: + +- ppg,整型数组,采集的ppg数据 + +- ppglen,整型,ppg长度(一般为10s的数据长度,即10*fs) + +- fs,整型,ppg信号的采样率(HA小板采样率为81Hz) + +##### 输出: + +##### 返回值: + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.17 睡眠佩戴状态回调函数注册接口 + +##### 原型: + +``` +unsigned int extern_get_wear_state_cb_reg(extern_get_wear_state_cb_t fun); +``` + +##### 输入: + +- fun,typedef void (*extern_get_wear_state_cb_t)(int8_t* worn)类型函数指针,该函数由应用方定义并传入给该注册接口。 + + - 函数指针指向的函数原型的参数需做如下说明: + + - worn, 整型指针,1表示佩戴, 0表示未佩戴。 + +##### 返回值: + +- 0。 + +##### 说明: + +- 在应用算法之前需要把该接口注册好,方便根据外部信息做算法结果修正。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.18 睡眠心率回调函数注册接口 + +##### 原型: + +``` +unsigned int extern_get_inst_hr_cb_reg(extern_get_inst_hr_cb_t fun); +``` + +##### 输入: + +- fun,typedef void (*extern_get_inst_hr_cb_t)(uint8_t* hr, sleep_time_t* hr_time);类型函数指针,该函数由应用方定义并传入给该注册接口。 + + - 函数指针指向的函数原型的参数需做如下说明: + + - hr, 整型指针,当前的心率值。 + + - hr_time, 睡眠时间结构体,输入心率当前时间 + +##### 返回值: + +- 0。 + +##### 说明: + +- 在应用算法之前需要把该接口注册好,方便根据外部信息做算法结果修正。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.19 睡眠算法初始化接口 + +##### 原型: + +``` +void init_sleep_algo_ex(sleep_data_t* sdata, int gfs, int pfs); +``` + +##### 输入: + +- sdata, sleep_data指针类型,结构见头文件。 + +- gfs, 整型,gsensor数据采样率 + +- pfs, 整型,ppg数据采样率 + + ##### 输出: + +- 无 + + ##### 返回值: + +- 无 + +##### 说明: + +- 必须在调用睡眠接口之前调用初始化接口 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.20 睡眠数据获取接口 + +##### 原型: + +``` +int get_sleep_data_ex(gsensor_data_t gdata[], const int glen, int pdata[], const int plen, const sleep_time_t curtime, sleep_data_t* sdata); +``` + +##### 输入: + +- gdata,gsensor数组(gsensor数据结构在头文件中定义),采集的gsensor数据 + +- glen,整型,gdata长度(一般输入1s钟的长度,即60*fs) + +- pdata,ppg数组,采集的ppg数据 + +- plen,整型,gdata长度(一般输入1s钟的长度,即60*fs) + +- curtime,自定义类型,当前时间(精确到分钟) + +- sdata, sleep_data指针类型,返回的时间数据 + + ##### 返回值: + +- result,整型,0表示没有睡眠数据,1表示返回睡眠数据 + + ##### 说明: + +- 该接口1分钟调用一次,每次传入1分钟的gsensor数据及当前时间; + +- 该接口返回值为1时表示睡眠结束,可读取到睡眠数据;返回值为0,表示睡眠未结束,没有睡眠数据。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.21 云医链算法初始化接口 + +##### 原型: + +``` +void YYL_Init_PFE(unsigned char* buf, unsigned int len); +``` + +##### 输入: + +- buf,无符号字符串型,给算法使用的整块存储空间首地址 + +- len,无符号整型,给算法使用的整块存储空间地址长度(按字节计算) + +##### 返回值: + +- void + +##### 说明: + +- 当前算法使用大块空间输入必须大于等于 14100个字节。该接口必须在其他云医链接口调用之前调用,用于初始化相应的内存空间。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.22 云医链算法输入接口 + +##### 原型: + +``` +void YYL_Input_PFE(yylPFE_InputData_t *pInputData, int32_t hr); +``` + +##### 输入: + +- pInputData,yylPFE_InputData_t *指针类型(该结构参考对应头文件) + +- hr,整型,当前时刻的心率值 + +##### 返回值: + +- void + +##### 说明: + +- 该接口每出一个数据调用一次。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.23 云医链算法输出接口 + +##### 原型: + +``` +yylPFE_OutputData * YYL_Output_PFE(int32_t *outputLen); +``` + +##### 输入: + +- void + + ##### 输出: + +- outputLen: 整型指针类型,得到输出结构体数组的长度 + +##### 返回值: + +- output: yylPFE_OutputData *指针类型(参考对应头文件),一个输出结果的结构数组 + +##### 说明: + +- 该接口只在每输出3000个数据(30s)时调用。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.24 云医链算法结果清空接口 + +##### 原型: + +``` +void YYL_Output_PFE_Array_Clear(void); +``` + +##### 输入: + +- void + +##### 返回值: + +- void + +##### 说明: + +- 该接口用于清空输出数据,可在每分钟调用结果输出接口后调用。 + +--------------------------------------------------------------------------------------------------------------------------- + +### 3.25 云医链算法版本获取接口 + +##### 原型: + +``` +char * YYL_PFE_Get_Current_Version(void); +``` + +##### 输入: + +- void + +##### 返回值: + +- version: 字符串类型,输入的版本号字符串 + +##### 说明: + +- 该接口获取当前云医链算法版本号。 + +************************************************************************ + +## 3 算法库使用示例 + +``` +#include "lib_hr.h" +#include "yyl_pfev01.h" + +int sec_counter = 0; // 每1s钟增加1,通过计时器函数进行变化 +int hr_type = 0; // 当前模式,通过模式切换函数进行变化 +unsigned char buf[14100]; // 算法库计算过程中所需要的缓存 + +void get_hr_run_time(int* type, int* sec) +{ + *type = hr_type; + *sec = sec_counter; +} + +void get_wear_state(int* worn) +{ + *worn = worn_from_other; +} + +void get_inst_hr(int* hr) +{ + *hr = hr_from_other; +} + +void test_get_version() +{ + char ver[20]; + unsigned int ver_len; + version_get_string(ver, &ver_len); + printf("result is %s\n%d\n", ver, ver_len); +} + +void test_algorithm() +{ + // 注册回调函数 + extern_printf_cb_reg(printf); // 日志打印回调函数注册,printf是外部定义的符合头文件中接口的日志打印函数 + extern_get_hr_run_time_cb_reg(get_hr_run_time); //注册hr类型时间回调函数 + + extern_get_wear_state_cb_reg(get_wear_state); //注册佩戴状态获取回调函数 + extern_get_inst_hr_cb_reg(get_inst_hr); //注册实时心率获取回调函数 + // 激活步骤 + // 申请激活认证(第一次使用该设备和算法的时候调用,需联手机APP) + unsigned char req_code[128]; + unsigned int req_code_len = 0; + unsigned char* fact = "hengaigaoke"; // 获取厂商名字(不超过32个字节的字符串) + const unsigned int fact_len = strlen(fact); + unsigned char* imei = "584aecdd73d9"; // 获取设备号(12个字节字符串) + const unsigned int imei_len = strlen(imei); + request_validation(fact, fact_len, imei, imei_len, req_code, &req_code_len); + + // ToDo:根据得到的req_code_len把req_code中的有效申请码(字符串)通过蓝牙接口发送给手机端,同时把它存储到本地; + + // 手机端响应申请码后如果认证通过,会通过蓝牙发送激活码(字符串)给手表端,手表端程序需把它也存储到本地,同时调用下面的激活接口。 + // 除第一次使用设备时调用以上接口之外,之后每一次重新启动手表程序不用再调用以上接口,可直接读取存储在本地的申请码和激活码,调用以下的激活接口,即可每次激活使用。 + + unsigned char* key_code; // 通过蓝牙接口从手机端接收到的激活码(字符串) + unsigned int key_code_len = 88; // 通过蓝牙接口从手机端接收到的激活码(字符串)长度 + int result; + result = activate_algorithm(req_code, req_code_len, key_code, key_code_len); //result=1表示算法激活 + + // 每次程序运行,以上激活步骤只需调用一次 + + // 算法调用步骤 + int counter = 0; + int status; + int len, fmlen, outlen; + float Fm[25][8]; + int fs = SAMPLERATE; + int segdata[SAMPLERATE*SAMPLETIME]; + const unsigned int seglen = SAMPLERATE * SAMPLETIME; + + int count = 0; + sleep_time_t curtime; + int sleep_count = 0; + gsensor_data_t gdata[3000]; + const size_t glen = 3000; + int pdata[3000]; + const size_t plen = 3000; + sleep_data_t sdata; + + HAEMO: + // 情绪算法初始化缓存 + init_algorithm(buf, 8000); + init_sleep_algo_ex(&sdata, 25, 25); + while(1) // 改为中断循环调用 + { + len = read_segment(fp, segdata, seglen); // 5s长度的数据 + status = ppg_midvalue(segdata, len, fs, Fm, &fmlen); + // 得到Fm数组中fmlen长度的有效中间值数据存储起来 + if (counter == 11) + { + // 得到1分钟累计Fm数据上传至服务器 + counter = 0; + goto YYLPFE; // 得到数据后切换到中医算法 + } + + curtime = time(year, month, day, hour, minute); // 伪代码,当前时间(精确到分钟) + if (get_sleep_data_ex(gdata, glen, pdata, plen, curtime, &sdata)) + { + sleep_count++; + printf("begin_sleep_time: %d-%d-%d: %d-%d\n", + sdata.begin_sleep_time.year, + sdata.begin_sleep_time.month, + sdata.begin_sleep_time.day, + sdata.begin_sleep_time.hour, + sdata.begin_sleep_time.minute); + printf("end_sleep_time: %d-%d-%d: %d-%d\n", + sdata.end_sleep_time.year, + sdata.end_sleep_time.month, + sdata.end_sleep_time.day, + sdata.end_sleep_time.hour, + sdata.end_sleep_time.minute); + printf("total_sleep_time: %d M\n", sdata.total_sleep_time); + printf("sleep detail: \nstate count: %d\n", sdata.state_count); + for (int j = 0; j < sdata.state_count; j++) + { + printf("sleep state: %d - %d m\n", sdata.data[j].state, sdata.data[j].duration); + } + } + count++; + + + counter++; + } + + yylPFE_OutputData *pOutputData; + + YYLPFE: + // 中医算法初始化缓存 + YYL_Init_PFE(buf, 8000); + while(1) // 改为中断循环调用 + { + yylPFE_InputData_t pInputData; // 每0.01s从传感器获取的ppg/g-sensor和hr数据 + int32_t hr; + YYL_Input_PFE(&pInputData, hr); + + // 得到Fm数组中fmlen长度的有效中间值数据存储起来 + if (counter % 3000 == 2999) + { + pOutputData = YYL_Output_PFE(&outlen); + // 从pOutputData指针指向的长度为outlen的结果数据上传至服务器 + if (counter == 5999) + goto HAEMO; // 得到数据后切换到情绪算法 + counter++; + } + counter++; + } + +} +``` + +************************************************************************ \ No newline at end of file