From 98721b7644b68cbaaa56a6c5249d2e99d086caaa Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=A2=81=E6=B8=85=E6=A2=A6?= <3449750381@qq.com> Date: Wed, 18 Sep 2024 02:28:23 +0000 Subject: [PATCH] Merge #978 into sdk602patch0626 from refs/changes/978/head MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 安全模式:下载修复文件增加repari_file_start接口 * refs/changes/978/head: (7 commits squashed) - 安全模式:下载修复文件增加repari_file_start接口 - 心率:增加心率动画的资源文件 - 心率:修改心率UI;增加上一次检测数据以及检测间隔 - 心率:同步心率卡片更新 - 心率:修复心率卡片显示异常 - 心率:心率动画修改 - 心率:使用图片icon替换动画 Signed-off-by: Caisking <3449750381@qq.com> Merged-by: snickersun@163.com CR-link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/978 --- .../wearable/fd230app/CMakeLists.txt | 1 + .../nativelauncher/include/UiConfig.h | 41 +- .../heartrate/include/HeartChartView.h | 110 +- .../nativeui/heartrate/include/HeartModel.h | 320 ++-- .../heartrate/include/HeartRateCardView.h | 29 + .../nativeui/heartrate/src/HeartChartView.cpp | 951 +++++++----- .../nativeui/heartrate/src/HeartModel.cpp | 1363 +++++++++-------- .../heartrate/src/HeartRateCardView.cpp | 64 + .../nativeui/heartrate/src/HeartRateView.cpp | 144 +- .../nativeui/main/include/MainViewSample.h | 3 +- .../nativeui/main/src/MainViewSample.cpp | 2 +- .../include/SafeModeManagerModelC.h | 16 + .../src/SafeModeManagerModel.cpp | 12 +- .../fs/user/res/heart_chart/background.bin | 2 +- .../heart_chart/hearticon/HEARTICON_01.bin | 3 + .../heart_chart/hearticon/HEARTICON_02.bin | 3 + .../heart_chart/hearticon/HEARTICON_03.bin | 3 + .../heart_chart/hearticon/HEARTICON_04.bin | 3 + .../heart_chart/hearticon/HEARTICON_05.bin | 3 + .../heart_chart/hearticon/HEARTICON_06.bin | 3 + .../heart_chart/hearticon/HEARTICON_07.bin | 3 + .../heart_chart/hearticon/HEARTICON_08.bin | 3 + .../heart_chart/hearticon/HEARTICON_09.bin | 3 + .../heart_chart/hearticon/HEARTICON_10.bin | 3 + .../heart_chart/hearticon/HEARTICON_11.bin | 3 + .../heart_chart/hearticon/HEARTICON_12.bin | 3 + .../heart_chart/hearticon/HEARTICON_13.bin | 3 + .../heart_chart/hearticon/HEARTICON_14.bin | 3 + .../heart_chart/hearticon/HEARTICON_15.bin | 3 + .../heart_chart/hearticon/HEARTICON_16.bin | 3 + .../heart_chart/hearticon/HEARTICON_17.bin | 3 + .../heart_chart/hearticon/HEARTICON_18.bin | 3 + .../heart_chart/hearticon/HEARTICON_19.bin | 3 + .../heart_chart/hearticon/HEARTICON_20.bin | 3 + .../heart_chart/hearticon/HEARTICON_21.bin | 3 + .../peripheral/utils/custom_cmd_service.c | 5 + .../drivers/peripheral/utils/custom_utils.h | 1 + .../image_makcopy_tool.py | 1 + .../test/hert/heart/back.png | Bin 0 -> 4165 bytes .../test/hert/heart_chart/background.png | Bin 0 -> 4165 bytes .../buttomicon.png | Bin .../{heartchart => heart_chart}/hearticon.png | Bin .../heart_chart/hearticon/HEARTICON_01.png | Bin 0 -> 935 bytes .../heart_chart/hearticon/HEARTICON_02.png | Bin 0 -> 953 bytes .../heart_chart/hearticon/HEARTICON_03.png | Bin 0 -> 986 bytes .../heart_chart/hearticon/HEARTICON_04.png | Bin 0 -> 924 bytes .../heart_chart/hearticon/HEARTICON_05.png | Bin 0 -> 1039 bytes .../heart_chart/hearticon/HEARTICON_06.png | Bin 0 -> 1036 bytes .../heart_chart/hearticon/HEARTICON_07.png | Bin 0 -> 1001 bytes .../heart_chart/hearticon/HEARTICON_08.png | Bin 0 -> 1013 bytes .../heart_chart/hearticon/HEARTICON_09.png | Bin 0 -> 970 bytes .../heart_chart/hearticon/HEARTICON_10.png | Bin 0 -> 1020 bytes .../heart_chart/hearticon/HEARTICON_11.png | Bin 0 -> 1009 bytes .../heart_chart/hearticon/HEARTICON_12.png | Bin 0 -> 1030 bytes .../heart_chart/hearticon/HEARTICON_13.png | Bin 0 -> 977 bytes .../heart_chart/hearticon/HEARTICON_14.png | Bin 0 -> 989 bytes .../heart_chart/hearticon/HEARTICON_15.png | Bin 0 -> 937 bytes .../heart_chart/hearticon/HEARTICON_16.png | Bin 0 -> 951 bytes .../heart_chart/hearticon/HEARTICON_17.png | Bin 0 -> 945 bytes .../heart_chart/hearticon/HEARTICON_18.png | Bin 0 -> 956 bytes .../heart_chart/hearticon/HEARTICON_19.png | Bin 0 -> 887 bytes .../heart_chart/hearticon/HEARTICON_20.png | Bin 0 -> 905 bytes .../heart_chart/hearticon/HEARTICON_21.png | Bin 0 -> 935 bytes .../test/hert/heart_chart/heartrate.gif | Bin 0 -> 10619 bytes .../{heartchart => heart_chart}/topicon.png | Bin .../test/hert/heartchart/background.png | Bin 5841 -> 0 bytes 66 files changed, 1842 insertions(+), 1286 deletions(-) create mode 100644 code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartRateCardView.h create mode 100644 code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateCardView.cpp create mode 100644 code/sdk/application/wearable/fd230app/nativeui/safemodemanager/include/SafeModeManagerModelC.h create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_01.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_02.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_03.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_04.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_05.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_06.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_07.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_08.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_09.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_10.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_11.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_12.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_13.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_14.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_15.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_16.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_17.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_18.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_19.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_20.bin create mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_21.bin create mode 100644 tools/image_converter_tool/image_makcopy_tool.py create mode 100644 tools/image_converter_tool/test/hert/heart/back.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/background.png rename tools/image_converter_tool/test/hert/{heartchart => heart_chart}/buttomicon.png (100%) rename tools/image_converter_tool/test/hert/{heartchart => heart_chart}/hearticon.png (100%) create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_01.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_02.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_03.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_04.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_05.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_06.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_07.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_08.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_09.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_10.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_11.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_12.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_13.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_14.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_15.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_16.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_17.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_18.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_19.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_20.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_21.png create mode 100644 tools/image_converter_tool/test/hert/heart_chart/heartrate.gif rename tools/image_converter_tool/test/hert/{heartchart => heart_chart}/topicon.png (100%) delete mode 100644 tools/image_converter_tool/test/hert/heartchart/background.png diff --git a/code/sdk/application/wearable/fd230app/CMakeLists.txt b/code/sdk/application/wearable/fd230app/CMakeLists.txt index de8c7f7a5..849754813 100644 --- a/code/sdk/application/wearable/fd230app/CMakeLists.txt +++ b/code/sdk/application/wearable/fd230app/CMakeLists.txt @@ -192,6 +192,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/heartrate/src/HeartDetectionPresenter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/heartrate/src/HeartChartView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/heartrate/src/HeartChartPresenter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/heartrate/src/HeartRateCardView.cpp #BloodCheck ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/bloodoxygen/src/BloodResultView.cpp diff --git a/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h b/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h index c10f53e2f..28dc1f2c1 100644 --- a/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h +++ b/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h @@ -71,6 +71,7 @@ namespace OHOS #define APP_DOWNLOAD_DIAL_PATH "/user/userdata/dial" /*表盘市场安装路径*/ #define APP_CUSTOM_DIAL_PATH "/user/userdata/custom_dial" /*自定义表盘安装路径*/ #define APP_LIST_PATH "/user/res/applist_icon" +#define APP_HEARET_ICON_PATH "/user/res/heart_chart/hearticon"//心率动画 static constexpr const char *CARD_CONFIG_PATH = "/user/cardconfig.bin"; @@ -246,25 +247,27 @@ namespace OHOS static constexpr const char *ALARM_DELETE_ADD_PATH = APP_RES_PATH "/DELETE.bin"; static constexpr const char *ALARM_TRUE_ADD_PATH = APP_RES_PATH "/TRUE_ADD.bin"; /* ---------------------------------- 心率动画图片 ---------------------------------- */ - static constexpr const char *PNG_A004_070_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_01.bin"; - static constexpr const char *PNG_A004_071_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_02.bin"; - static constexpr const char *PNG_A004_072_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_03.bin"; - static constexpr const char *PNG_A004_073_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_04.bin"; - static constexpr const char *PNG_A004_074_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_05.bin"; - static constexpr const char *PNG_A004_075_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_06.bin"; - static constexpr const char *PNG_A004_076_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_07.bin"; - static constexpr const char *PNG_A004_077_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_08.bin"; - static constexpr const char *PNG_A004_078_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_09.bin"; - static constexpr const char *PNG_A004_079_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_10.bin"; - static constexpr const char *PNG_A004_080_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_11.bin"; - static constexpr const char *PNG_A004_081_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_12.bin"; - static constexpr const char *PNG_A004_082_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_13.bin"; - static constexpr const char *PNG_A004_083_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_14.bin"; - static constexpr const char *PNG_A004_084_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_15.bin"; - static constexpr const char *PNG_A004_085_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_16.bin"; - static constexpr const char *PNG_A004_086_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_17.bin"; - static constexpr const char *PNG_A004_087_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_18.bin"; - static constexpr const char *PNG_A004_088_IMAGE_PATH = APP_RES_PATH "/HEARTBEAT_IMAGE_19.bin"; + static constexpr const char *PNG_A004_070_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_01.bin"; + static constexpr const char *PNG_A004_071_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_02.bin"; + static constexpr const char *PNG_A004_072_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_03.bin"; + static constexpr const char *PNG_A004_073_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_04.bin"; + static constexpr const char *PNG_A004_074_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_05.bin"; + static constexpr const char *PNG_A004_075_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_06.bin"; + static constexpr const char *PNG_A004_076_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_07.bin"; + static constexpr const char *PNG_A004_077_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_08.bin"; + static constexpr const char *PNG_A004_078_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_09.bin"; + static constexpr const char *PNG_A004_079_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_10.bin"; + static constexpr const char *PNG_A004_080_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_11.bin"; + static constexpr const char *PNG_A004_081_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_12.bin"; + static constexpr const char *PNG_A004_082_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_13.bin"; + static constexpr const char *PNG_A004_083_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_14.bin"; + static constexpr const char *PNG_A004_084_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_15.bin"; + static constexpr const char *PNG_A004_085_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_16.bin"; + static constexpr const char *PNG_A004_086_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_17.bin"; + static constexpr const char *PNG_A004_087_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_18.bin"; + static constexpr const char *PNG_A004_088_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_19.bin"; + static constexpr const char *PNG_A004_089_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_20.bin"; + static constexpr const char *PNG_A004_090_IMAGE_PATH = APP_HEARET_ICON_PATH "/HEARTICON_21.bin"; /* -------------------------------- 蓝牙搜索的动画图片 ------------------------------- */ static constexpr const char *PNG_A019_080_IMAGE_PATH = APP_RES_PATH "/BLUETOOTH_IMAGE_01.bin"; static constexpr const char *PNG_A019_081_IMAGE_PATH = APP_RES_PATH "/BLUETOOTH_IMAGE_02.bin"; diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h index b2e7676b4..ae4c9691b 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h @@ -2,84 +2,96 @@ * @Date: 2024-08-15 18:38:49 * @LastEditors: Caisking 3449750381@qq.com * @LastEditTime: 2024-08-26 15:17:07 - * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h + * @FilePath: + * /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h */ /*** * @Date: 2024-08-15 18:38:49 * @LastEditors: Caisking 3449750381@qq.com * @LastEditTime: 2024-08-15 20:25:38 - * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h + * @FilePath: + * /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartChartView.h */ #ifndef HEART_Chart_VIEW_H #define HEART_Chart_VIEW_H -#include "View.h" #include "BaseView.h" -#include "wearable_log.h" #include "UiConfig.h" -#include "components/ui_label.h" -#include "components/ui_label_ext.h" +#include "View.h" #include "components/ui_button.h" -#include "components/ui_label_button.h" -#include "components/ui_image_animator.h" #include "components/ui_circle_progress.h" +#include "components/ui_image_animator.h" +#include "components/ui_label.h" +#include "components/ui_label_button.h" +#include "components/ui_label_ext.h" #include "components/ui_view_group.h" +#include "wearable_log.h" #include "heartrate/include/HeartChartPresenter.h" -#include "components/ui_scroll_view.h" #include "components/ui_label_button_ext.h" +#include "components/ui_scroll_view.h" -#include "power_display_service.h" -#include "components/ui_image_animator.h" #include "components/ui_chart.h" +#include "components/ui_image_animator.h" +#include "power_display_service.h" #define STOPCHECK "stop_check" -namespace OHOS -{ - class HeartChartPresenter; - class HeartChartView : public View - { - public: - HeartChartView(); - virtual ~HeartChartView(); - void OnStop() override; - void OnSetUpView() override; - void OnTearDownView() override; - void OnStart() override; - static HeartChartView *GetInstance(void); +namespace OHOS { +class HeartChartPresenter; +class HeartChartView : public View { +public: + HeartChartView(); + virtual ~HeartChartView(); + void OnStop() override; + void OnSetUpView() override; + void OnTearDownView() override; + void OnStart() override; + static HeartChartView *GetInstance(void); + + UIImageAnimatorView *GetImageAnimator(void); - UIImageAnimatorView *GetImageAnimator(void); + bool HeartViewInit(); + void InitChartView(void); + void InitChartLabel(void); + void InitChartImageView(void); - bool HeartViewInit(); - void InitChartView(void); - void SetDataChart(); - void SetDataTopAndBottom(); - void HeartImageAnimator(); + void SetDataChart(); + void SetDataTopAndBottom(); + void HeartImageAnimator(); - void UpdateShowHeart(void); - void Update_data_Chart(int serialIndex); - void CleanAllDataView(); + void UpdateShowHeart(void); + void Update_data_Chart(int serialIndex); + void CleanAllDataView(); + void UpdateChartConfig(); + void SetLastHeart(); + UIViewGroup *GetchartGroup(); - private: - UILabelExt *CurrentHeartText{nullptr}; - UILabelExt *MaxHeartText{nullptr}; - UILabelExt *MinHeartText{nullptr}; - UILabelExt *UHeartText{nullptr}; - UILabelExt *RestHeartText{nullptr}; +private: + UIImageView *maxRateIconView_{nullptr}; + UIImageView *minRateIconView_{nullptr}; + UIImageView *chartBackgroundView_{nullptr}; + UIImageView *heartIconView_{nullptr}; - UIImageView *TopimageView{nullptr}; - UIImageView *BottomimageView{nullptr}; - UIImageView *CoordinateimageView{nullptr}; - UIImageView *HeartIconView{nullptr}; + UIImageAnimatorView *imageAnimator{nullptr}; - UIImageAnimatorView *imageAnimator{nullptr}; + Point heartdata[24]; + UIChartDataSerial *heartSerial{nullptr}; + UIChartPolyline *heartchart = nullptr; - Point heartdata[24]; - UIChartDataSerial *heartSerial{nullptr}; - UIChartPolyline *heartchart = nullptr; - }; -} + UILabelExt *displayheart_{nullptr}; + UILabelExt *uheart_{nullptr}; + UILabelExt *lastheart_{nullptr}; + UILabelExt *minheart_{nullptr}; + UILabelExt *maxheart_{nullptr}; + + UILabelExt *maxheart_dynamic_{nullptr}; + UILabelExt *maxheart_dynamic_3_{nullptr}; + UILabelExt *maxheart_dynamic_2_{nullptr}; + UILabelExt *maxheart_dynamic_1_{nullptr}; + UILabelExt *minheart_dynamic_{nullptr}; +}; +} // namespace OHOS #endif // 心率主界面 \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h index 491904d1b..4827a8abc 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h @@ -1,67 +1,61 @@ #ifndef HEART_MODEL_H #define HEART_MODEL_H -#include +#include "MainClockView.h" #include "broadcast_feature.h" #include "broadcast_service.h" #include "samgr_lite.h" -#include "MainClockView.h" +#include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - int PushOHOSMsgToHeartModel(Request *request); - void HeartDataSubscribeTopic(Topic topic); - void HearDatatUnsubscribeTopic(Topic topic); +int PushOHOSMsgToHeartModel(Request *request); +void HeartDataSubscribeTopic(Topic topic); +void HearDatatUnsubscribeTopic(Topic topic); #define HEART_ALL_POINTS 360 - typedef struct - { - uint16_t x; - uint16_t y; - bool flag; - } Point; - - typedef struct - { - /** X coordinate */ - uint16_t x; - /** Y coordinate */ - uint16_t y; - } HeartPoint; - - typedef struct - { - uint16_t perSec; - uint16_t rest; - uint16_t minX; - uint16_t minValue; - uint16_t maxX; - uint16_t maxValue; - uint16_t index; - Point value[HEART_ALL_POINTS]; - } HeartInfo; +typedef struct { + uint16_t x; + uint16_t y; + bool flag; +} Point; + +typedef struct { + /** X coordinate */ + uint16_t x; + /** Y coordinate */ + uint16_t y; +} HeartPoint; + +typedef struct { + uint16_t perSec; + uint16_t rest; + uint16_t minX; + uint16_t minValue; + uint16_t maxX; + uint16_t maxValue; + uint16_t index; + Point value[HEART_ALL_POINTS]; +} HeartInfo; #pragma pack(4) - typedef struct - { - uint16_t perSec; - uint16_t rest; - uint16_t minX; - uint16_t minValue; - uint16_t maxX; - uint16_t maxValue; - uint16_t index; - HeartPoint value[HEART_ALL_POINTS]; - } HeartDatas; +typedef struct { + uint16_t perSec; + uint16_t rest; + uint16_t minX; + uint16_t minValue; + uint16_t maxX; + uint16_t maxValue; + uint16_t index; + HeartPoint value[HEART_ALL_POINTS]; +} HeartDatas; #pragma pack() - namespace OHOS - { +namespace OHOS { #define HEART_AVE_NUM 360 #define HEART_RATE_LIMIT_UPPER 200 #define HEART_RATE_LIMIT_LOWER 0 @@ -75,121 +69,125 @@ extern "C" #define NUM_7 7 #define NUM_16 16 #define NUM_99 99 - // 心率检测状态 - enum class HeartState - { - End = 0, - Start, - }; - enum class HeartCheck - { - RESTSTSTE = 0, // 未检测状态 - PASSIVITY, // 被动检测心率 - CARDCHECK, // 卡片检测 - INITIATIVE, // 主动检测心率 - EXERCISE, // 运动心率 - }; - enum class HeartResult - { - NOT_TESTED = 0, // 未检测 - SUCCESS, // 检测成功 - NOT_WORN, // 未佩戴检测 - TIMEOUT, // 检测超时 - HIGH_RESULT, // 检测结果过高 - LOW_RESULT, // 检测结果过低 - INVALID_DATA // 无效数据 - }; - // 控制心率检测 - typedef struct - { - uint32_t heartRatePerSec; - Point heartRateAvg[HEART_AVE_NUM]; - uint32_t heartRateRest; - Point heartRateMax; - Point heartRateMin; - } HealthAllDatas; - - class HeartModel - { - public: - HeartModel(); - ~HeartModel(); - static HeartModel *GetInstance(void); - void ObtainingHeartRateData(void); - void PushHealthDatas(HealthMsg healthMsg); - Point *GetAveHeartRate(void); - uint16_t GetAveHeartRateCount(void); - void SetAveHeartRateCount(uint16_t value); - Point *GetMaximumHeartRate(void); - void Init(void); - void HeartRatePros(HeartDatas *heartInfo); - void RefreshHeartRateScreen(uint16_t perSec, uint16_t rest, uint16_t maxRate, uint16_t minRate); - void ClearHeartData(void); - void HandleMaxHeart(uint16_t coord, uint16_t value); - void HandleMinHeart(uint16_t coord, uint16_t value); - void SetHeartRatePerSec(uint32_t sec); - uint16_t GetHeartRateMax(void); - uint16_t GetHeartRateMin(void); - /* -------------------------------------------------------------------------- */ - void UpHeartdata(uint16_t heart); - uint16_t GetHeartdata(); - uint16_t GetShowHeartdata(); - uint16_t GetShowMaxHeartdata(); - uint16_t GetShowMinHeartdata(); - - uint16_t GetIndex(); - void SetIndex(uint16_t index); - - uint32_t GetCheckTime(void); - void SetCheckTime(uint32_t time); - void SetWearStatus(int32_t wear); - void SetResult(HeartResult result); - HeartResult GetResult(); - - void Heart_Start(void); - void Heart_Stop(void); - void Heart_Save(void); - void Heart_Result(void); - - void Heart_Control(HeartState state, HeartCheck check); - void ClearDisplayData(); - void Heart_Update_View(void); - void CleanAllData(void); - - private: - HealthAllDatas healthDatas; - uint16_t pretime{0}; - uint16_t entryTimes{0}; - uint16_t aveCount{0}; - uint16_t preMaxValue{0}; - uint16_t preMaxX{NUM_1}; - uint16_t preMinValue{HEART_RATE_LIMIT_UPPER}; - uint16_t preMinX{NUM_1}; - uint16_t countMax{0}; - uint16_t countMin{0}; - bool wearStatus{true}; - uint16_t index_ = 0; - - uint16_t displayheart; // 显示心率 - uint16_t currentheart; // 保存心率 - uint16_t displayheart_max; // 显示最大心率 - uint16_t displayheart_min; // 显示最小心率 - - uint32 timestamp_ms; // 检测时间(存(时、分),大于24小时,改为1天前,小于1分钟为刚刚) - - bool initstatus = true; - bool heartstate = false; - bool sensorstate{false}; - - uint16_t wear_; - uint16_t valid_counter_ = 0; // 有效数计数器 - uint16_t disvalid_counter_ = 0; // 无效数计数器 - uint16_t unwear_counter_ = 0; // 佩戴错误计数器 - - HeartResult heartresult_ = HeartResult::NOT_TESTED; // 检测结果 - HeartCheck checkstate = HeartCheck::RESTSTSTE; // 目前检测状态 - }; - } +// 心率检测状态 +enum class HeartState { + End = 0, + Start, +}; +enum class HeartCheck { + RESTSTSTE = 0, // 未检测状态 + PASSIVITY, // 被动检测心率 + CARDCHECK, // 卡片检测 + INITIATIVE, // 主动检测心率 + EXERCISE, // 运动心率 +}; +enum class HeartResult { + NOT_TESTED = 0, // 未检测 + SUCCESS, // 检测成功 + NOT_WORN, // 未佩戴检测 + TIMEOUT, // 检测超时 + HIGH_RESULT, // 检测结果过高 + LOW_RESULT, // 检测结果过低 + INVALID_DATA // 无效数据 +}; +// 控制心率检测 +typedef struct { + uint32_t heartRatePerSec; + Point heartRateAvg[HEART_AVE_NUM]; + uint32_t heartRateRest; + Point heartRateMax; + Point heartRateMin; +} HealthAllDatas; + +class HeartModel { +public: + HeartModel(); + ~HeartModel(); + static HeartModel *GetInstance(void); + void ObtainingHeartRateData(void); + void PushHealthDatas(HealthMsg healthMsg); + Point *GetAveHeartRate(void); + uint16_t GetAveHeartRateCount(void); + void SetAveHeartRateCount(uint16_t value); + Point *GetMaximumHeartRate(void); + void Init(void); + void HeartRatePros(HeartDatas *heartInfo); + void RefreshHeartRateScreen(uint16_t perSec, uint16_t rest, uint16_t maxRate, + uint16_t minRate); + void ClearHeartData(void); + void HandleMaxHeart(uint16_t coord, uint16_t value); + void HandleMinHeart(uint16_t coord, uint16_t value); + void SetHeartRatePerSec(uint32_t sec); + uint16_t GetHeartRateMax(void); + uint16_t GetHeartRateMin(void); + /* -------------------------------------------------------------------------- + */ + void UpHeartdata(uint16_t heart); + uint16_t GetHeartdata(); + uint16_t GetShowHeartdata(); + uint16_t GetShowMaxHeartdata(); + uint16_t GetShowMinHeartdata(); + + uint16_t GetIndex(); + void SetIndex(uint16_t index); + + uint32_t GetCheckTime(void); + void SetCheckTime(uint32_t time); + void SetWearStatus(int32_t wear); + void SetResult(HeartResult result); + HeartResult GetResult(); + + void Heart_Start(void); + void Heart_Stop(void); + void Heart_Save(void); + void Heart_Result(void); + + void Heart_Control(HeartState state, HeartCheck check); + void ClearDisplayData(); + void Heart_Update_View(void); + void CleanAllData(void); + + std::string GetCheckString(); + uint16_t *GetArrayData(); + void SetArrayData(); + +private: + HealthAllDatas healthDatas; + uint16_t pretime{0}; + uint16_t entryTimes{0}; + uint16_t aveCount{0}; + uint16_t preMaxValue{0}; + uint16_t preMaxX{NUM_1}; + uint16_t preMinValue{HEART_RATE_LIMIT_UPPER}; + uint16_t preMinX{NUM_1}; + uint16_t countMax{0}; + uint16_t countMin{0}; + bool wearStatus{true}; + uint16_t index_ = 0; + + uint16_t displayheart; // 显示心率 + uint16_t currentheart; // 保存心率 + uint16_t displayheart_max; // 显示最大心率 + uint16_t displayheart_min; // 显示最小心率 + + uint32 + timestamp_ms; // 检测时间(存(时、分),大于24小时,改为1天前,小于1分钟为刚刚) + + bool initstatus = true; + bool heartstate = false; + bool sensorstate{false}; + + uint16_t wear_; + uint16_t valid_counter_ = 0; // 有效数计数器 + uint16_t disvalid_counter_ = 0; // 无效数计数器 + uint16_t unwear_counter_ = 0; // 佩戴错误计数器 + + HeartResult heartresult_ = HeartResult::NOT_TESTED; // 检测结果 + HeartCheck checkstate = HeartCheck::RESTSTSTE; // 目前检测状态 + + uint16_t dynamic_heartrate[5]; //动态心率配置项 +}; +} // namespace OHOS #ifdef __cplusplus } diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartRateCardView.h b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartRateCardView.h new file mode 100644 index 000000000..cdab034f6 --- /dev/null +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartRateCardView.h @@ -0,0 +1,29 @@ +#ifndef HEART_RATECARD_VIEW_H +#define HEART_RATECARD_VIEW_H + +#include "components/root_view.h" +#include "components/ui_card_page.h" +#include "heartrate/include/HeartChartView.h" +#include "wearable_log.h" +namespace OHOS { + +class HeartRateCardView : public UICardPage { +public: + HeartRateCardView(); + virtual ~HeartRateCardView(); + static HeartRateCardView *GetInstance(void); + + bool InitView(void); + void PreLoad(void) override; + void UnLoad(void) override; + UIViewGroup *GetHeartRateCardView(); + +private: + HeartChartView *heartRateCardView{nullptr}; + UIViewGroup *heartRateGroupView{nullptr}; + void ClearAll(void); + bool viewiInitStatus{false}; +}; + +} // namespace OHOS +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp index c8dacf31e..7b2663177 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp @@ -2,366 +2,621 @@ * @Date: 2024-08-15 18:39:02 * @LastEditors: Caisking 3449750381@qq.com * @LastEditTime: 2024-09-05 14:36:17 - * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp + * @FilePath: + * /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp */ /*** * @Date: 2024-04-15 10:55:58 * @LastEditors: Caisking 3449750381@qq.com * @LastEditTime: 2024-07-29 15:35:06 - * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp + * @FilePath: + * /FD230/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp */ -#include "UiConfig.h" -#include "wearable_log.h" #include "HeartChartView.h" #include "HeartModel.h" +#include "UiConfig.h" +#include "heart_blood/health_service/health_service.h" +#include "power_display_service.h" #include "ui_image_animator.h" -#include "HeartChartView.h" #include "ui_resource_string.h" -#include "power_display_service.h" #include "uicomponents/UIComponents.h" -#include "heart_blood/health_service/health_service.h" -namespace OHOS -{ - static HeartChartView *g_pHeartCheckView = nullptr; - - // 动态刷新设置 - static constexpr uint16_t IMAGE_SIZE = 180; - static constexpr uint16_t IMAGE_POSITION_Y = 134; - static constexpr uint16_t IMAGE_POSITION_X = 150; - static constexpr uint16_t Chart_IMAGE_ANIMATORVIEW_SIZE = 20; - static constexpr uint16_t Chart_IMAGE_ANIMATORVIEW_SPEED = 40; - // 图片路径 - static constexpr const char *BACKGROUND_IMAGE_PATH = "/user/res/heart_chart/background.bin"; - static constexpr const char *BUTTOM_ICON_PATH = "/user/res/heart_chart/buttomicon.bin"; - static constexpr const char *TOP_ICON_PATH = "/user/res/heart_chart/topicon.bin"; - static constexpr const char *HEART_ICON_PATH = "/user/res/heart_chart/hearticon.bin"; - // 心形心跳 - static constexpr int HEARTBEAT_IMAGE_WIDTH = 92; - static constexpr int HEARTBEAT_IMAGE_HEIGHT = 92; - static constexpr int HEARTBEAT_IMAGE_X = 85; - static constexpr int HEARTBEAT_IMAGE_Y = 50; - static constexpr int HEARTBEAT_IMAGE_NUM = 19; - static constexpr int HEARTBEAT_DELAY = 50; - // 心跳image - static ImageAnimatorInfo g_heartImageInfo[HEARTBEAT_IMAGE_NUM] = { - {PNG_A004_070_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_071_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_072_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_073_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_074_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_075_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_076_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_077_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_078_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_079_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - - {PNG_A004_080_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_081_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_082_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_083_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_084_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_085_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_086_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_087_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_088_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - }; - - HeartChartView::HeartChartView() - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartBandoffView::HeartBandoffView"); - g_pHeartCheckView = this; - } - HeartChartView::~HeartChartView() - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::~HeartChartView"); - - imageAnimator->Stop(); - /* - UIViewGroup *tmpGroup = dynamic_cast(container_); - UIViewGroup::RemoveAndDeleteAllRecursively(tmpGroup); - */ - - delete CurrentHeartText; - CurrentHeartText = nullptr; - delete MaxHeartText; - MaxHeartText = nullptr; - delete MinHeartText; - MinHeartText = nullptr; - delete UHeartText; - UHeartText = nullptr; - delete RestHeartText; - RestHeartText = nullptr; - delete TopimageView; - TopimageView = nullptr; - delete BottomimageView; - BottomimageView = nullptr; - delete CoordinateimageView; - CoordinateimageView = nullptr; - delete HeartIconView; - HeartIconView = nullptr; - delete imageAnimator; - imageAnimator = nullptr; - - heartchart->ClearDataSerial(); - delete heartSerial; - heartSerial = nullptr; - delete heartchart; - heartchart = nullptr; - - g_pHeartCheckView = this; - } - HeartChartView *HeartChartView::GetInstance(void) - { - return g_pHeartCheckView; - } - - /* 更新显示数据 */ - void HeartChartView::UpdateShowHeart() - { - // 获取当前心率 - uint16_t heart_ = HeartModel::GetInstance()->GetShowHeartdata(); - std::string heartrateStr = (heart_ == 0) ? "--" : (heart_ < 50 ? "--" : std::to_string(heart_)); - - // 更新当前心率显示 - if (CurrentHeartText != nullptr) - { - CurrentHeartText->SetText(heartrateStr.c_str()); - } - - // 获取最大心率 - uint16_t heartmax_ = HeartModel::GetInstance()->GetShowMaxHeartdata(); - std::string heartmaxStr = (heartmax_ == 0) ? "--" : (heartmax_ < 50 ? "--" : std::to_string(heartmax_)); - - // 更新最大心率显示 - if (MaxHeartText != nullptr) - { - MaxHeartText->SetText(heartmaxStr.c_str()); - } - - // 获取最小心率 - uint16_t heartmin_ = HeartModel::GetInstance()->GetShowMinHeartdata(); - std::string heartminStr = (heartmin_ == 0) ? "--" : (heartmin_ < 50 ? "--" : std::to_string(heartmin_)); - - // 更新最小心率显示 - if (MinHeartText != nullptr) - { - MinHeartText->SetText(heartminStr.c_str()); - } - } - void HeartChartView::Update_data_Chart(int serialIndex) - { - if (heartchart == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Update_data_Chart fail %d", serialIndex); - return; - } - /*清除原数据*/ - heartSerial->ClearData(); - - /*设置单个项*/ - heartdata[serialIndex].x = serialIndex; - heartdata[serialIndex].y = HealthService::GetInstance()->GetHourlyHeartRate(serialIndex); - - /*重新添加*/ - heartSerial->AddPoints(heartdata, 24); - heartSerial->SetLineColor(Color::Red()); - heartSerial->SetFillColor(Color::Red()); - heartSerial->EnableGradient(true); - - heartchart->AddDataSerial(heartSerial); - heartchart->Invalidate(); - } - void HeartChartView::CleanAllDataView() - { - if (heartchart == nullptr || MaxHeartText == nullptr || MinHeartText == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " CleanAllDataView fail"); - return; - } - for (int serialIndex = 0; serialIndex < 24; serialIndex++) - { - heartdata[serialIndex].x = serialIndex; - heartdata[serialIndex].y = HealthService::GetInstance()->GetHourlyHeartRate(serialIndex); - } - - /*清空原数据*/ - heartSerial->ClearData(); - heartSerial->AddPoints(heartdata, 24); - heartSerial->SetLineColor(Color::Red()); - heartSerial->SetFillColor(Color::Red()); - heartSerial->EnableGradient(true); - - heartchart->AddDataSerial(heartSerial); - // heartchart->RefreshChart(); - - /*更新最大最小值*/ - SetDataTopAndBottom(); - } - /*设置最大最小数据*/ - void HeartChartView::SetDataTopAndBottom() - { - int MaxHeart = HeartModel::GetInstance()->GetHeartRateMax(); - int MinHeart = HeartModel::GetInstance()->GetHeartRateMin(); - - if (MaxHeartText != nullptr) - { - MaxHeartText->SetText(MaxHeart > 0 ? (std::to_string(MaxHeart)).c_str() : "--"); - } - - if (MinHeartText != nullptr) - { - MinHeartText->SetText(MinHeart > 0 ? (std::to_string(MinHeart)).c_str() : "--"); - } - - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "MaxHeart: %d, MinHeart: %d", MaxHeart, MinHeart); - } - /*设置曲线图数据*/ - void HeartChartView::SetDataChart() - { - if (heartchart == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Init_data_Chart new chart fail"); - return; - } - heartSerial = new UIChartDataSerial(); - heartSerial->SetMaxDataCount(24); +#include "wearable_log.h" +namespace OHOS { +static HeartChartView *g_pHeartCheckView = nullptr; + +// 动态刷新设置 +static constexpr uint16_t IMAGE_SIZE = 180; +static constexpr uint16_t IMAGE_POSITION_Y = 134; +static constexpr uint16_t IMAGE_POSITION_X = 150; +static constexpr uint16_t Chart_IMAGE_ANIMATORVIEW_SIZE = 20; +static constexpr uint16_t Chart_IMAGE_ANIMATORVIEW_SPEED = 40; +// 图片路径 +static constexpr const char *BACKGROUND_IMAGE_PATH = + "/user/res/heart_chart/background.bin"; +static constexpr const char *BUTTOM_ICON_PATH = + "/user/res/heart_chart/buttomicon.bin"; +static constexpr const char *TOP_ICON_PATH = + "/user/res/heart_chart/topicon.bin"; +static constexpr const char *HEART_ICON_PATH = + "/user/res/heart_chart/hearticon.bin"; +// 心形心跳 +static constexpr int HEARTBEAT_IMAGE_WIDTH = 54; +static constexpr int HEARTBEAT_IMAGE_HEIGHT = 50; +static constexpr int HEARTBEAT_IMAGE_X = 111; +static constexpr int HEARTBEAT_IMAGE_Y = 57; +static constexpr int HEARTBEAT_IMAGE_NUM = 21; +static constexpr int HEARTBEAT_DELAY = 50; +// 心跳image +static ImageAnimatorInfo g_heartImageInfo[HEARTBEAT_IMAGE_NUM] = { + {PNG_A004_070_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_071_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_072_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_073_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_074_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_075_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_076_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_077_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_078_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_079_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_080_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_081_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_082_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_083_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_084_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_085_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_086_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_087_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_088_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_089_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_090_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, +}; + +HeartChartView::HeartChartView() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartBandoffView::HeartBandoffView"); + g_pHeartCheckView = this; +} +HeartChartView::~HeartChartView() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::~HeartChartView"); + + /* + UIViewGroup *tmpGroup = dynamic_cast(container_); + UIViewGroup::RemoveAndDeleteAllRecursively(tmpGroup); + */ + + delete displayheart_; + displayheart_ = nullptr; + delete maxheart_; + maxheart_ = nullptr; + delete minheart_; + minheart_ = nullptr; + delete uheart_; + uheart_ = nullptr; + delete lastheart_; + lastheart_ = nullptr; + delete maxheart_dynamic_; + maxheart_dynamic_ = nullptr; + delete maxheart_dynamic_3_; + maxheart_dynamic_3_ = nullptr; + delete maxheart_dynamic_2_; + maxheart_dynamic_2_ = nullptr; + delete maxheart_dynamic_1_; + maxheart_dynamic_1_ = nullptr; + delete minheart_dynamic_; + minheart_dynamic_ = nullptr; + + delete maxRateIconView_; + maxRateIconView_ = nullptr; + delete minRateIconView_; + minRateIconView_ = nullptr; + delete chartBackgroundView_; + chartBackgroundView_ = nullptr; + delete heartIconView_; + heartIconView_ = nullptr; + + // imageAnimator->Stop(); + // delete imageAnimator; + // imageAnimator = nullptr; + + heartchart->ClearDataSerial(); + delete heartSerial; + heartSerial = nullptr; + delete heartchart; + heartchart = nullptr; + + g_pHeartCheckView = this; +} +HeartChartView *HeartChartView::GetInstance(void) { return g_pHeartCheckView; } + +/* 更新显示数据 */ +void HeartChartView::UpdateShowHeart() { + // 获取当前心率 + uint16_t heart_ = HeartModel::GetInstance()->GetShowHeartdata(); + std::string heartrateStr = + (heart_ == 0) ? "--" : (heart_ < 50 ? "--" : std::to_string(heart_)); + + // 更新当前心率显示 + if (displayheart_ != nullptr) { + displayheart_->SetText(heartrateStr.c_str()); + } + + // 获取最大心率 + uint16_t heartmax_ = HeartModel::GetInstance()->GetShowMaxHeartdata(); + std::string heartmaxStr = + (heartmax_ == 0) ? "--" + : (heartmax_ < 50 ? "--" : std::to_string(heartmax_)); + + // 更新最大心率显示 + if (maxheart_ != nullptr) { + maxheart_->SetText(heartmaxStr.c_str()); + } + + // 获取最小心率 + uint16_t heartmin_ = HeartModel::GetInstance()->GetShowMinHeartdata(); + std::string heartminStr = + (heartmin_ == 0) ? "--" + : (heartmin_ < 50 ? "--" : std::to_string(heartmin_)); + + // 更新最小心率显示 + if (minheart_ != nullptr) { + minheart_->SetText(heartminStr.c_str()); + } +} +void HeartChartView::Update_data_Chart(int serialIndex) { + if (heartchart == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Update_data_Chart fail %d", + serialIndex); + return; + } + /*清除原数据*/ + heartSerial->ClearData(); + + /*设置单个项*/ + heartdata[serialIndex].x = serialIndex; + heartdata[serialIndex].y = + HealthService::GetInstance()->GetHourlyHeartRate(serialIndex); + + /*重新添加*/ + heartSerial->AddPoints(heartdata, 24); + heartSerial->SetLineColor(Color::Red()); + heartSerial->SetFillColor(Color::Red()); + heartSerial->EnableGradient(true); + + heartchart->AddDataSerial(heartSerial); + heartchart->Invalidate(); + + //更新为刚刚检测 + SetLastHeart(); +} +void HeartChartView::CleanAllDataView() { + if (heartchart == nullptr || maxheart_ == nullptr || minheart_ == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " CleanAllDataView fail"); + return; + } + for (int serialIndex = 0; serialIndex < 24; serialIndex++) { + heartdata[serialIndex].x = serialIndex; + heartdata[serialIndex].y = + HealthService::GetInstance()->GetHourlyHeartRate(serialIndex); + } + + /*清空原数据*/ + heartSerial->ClearData(); + heartSerial->AddPoints(heartdata, 24); + heartSerial->SetLineColor(Color::Red()); + heartSerial->SetFillColor(Color::Red()); + heartSerial->EnableGradient(true); + + heartchart->AddDataSerial(heartSerial); + // heartchart->RefreshChart(); + + /*更新最大最小值*/ + SetDataTopAndBottom(); +} +/*设置最大最小数据*/ +void HeartChartView::SetDataTopAndBottom() { + int MaxHeart = HeartModel::GetInstance()->GetHeartRateMax(); + int MinHeart = HeartModel::GetInstance()->GetHeartRateMin(); + + if (maxheart_ != nullptr) { + maxheart_->SetText(MaxHeart > 0 ? (std::to_string(MaxHeart)).c_str() + : "--"); + } + + if (minheart_ != nullptr) { + minheart_->SetText(MinHeart > 0 ? (std::to_string(MinHeart)).c_str() + : "--"); + } + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "MaxHeart: %d, MinHeart: %d", MaxHeart, + MinHeart); +} +/*设置曲线图数据*/ +void HeartChartView::SetDataChart() { + if (heartchart == nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Init_data_Chart new chart fail"); + return; + } + heartSerial = new UIChartDataSerial(); + heartSerial->SetMaxDataCount(24); #if HEART_DATA_TEST - Point temp[] = { - {0, 150}, {1, 250}, {2, 170}, {3, 0}, {4, 140}, {5, 190}, {6, 100}, {7, 40}, {8, 10}, {9, 100}, {10, 60}, {11, 20}, {12, 150}, {13, 250}, {14, 170}, {15, 140}, {16, 78}, {17, 80}, {18, 100}, {19, 20}, {20, 100}, {21, 100}, {22, 100}, {23, 100}}; - std::copy(std::begin(temp), std::end(temp), heartdata); + Point temp[] = {{0, 150}, {1, 250}, {2, 170}, {3, 0}, {4, 140}, + {5, 190}, {6, 100}, {7, 40}, {8, 10}, {9, 100}, + {10, 60}, {11, 20}, {12, 150}, {13, 250}, {14, 170}, + {15, 140}, {16, 78}, {17, 80}, {18, 100}, {19, 20}, + {20, 100}, {21, 100}, {22, 100}, {23, 100}}; + std::copy(std::begin(temp), std::end(temp), heartdata); #else - for (int serialIndex = 0; serialIndex < 24; serialIndex++) - { - heartdata[serialIndex].x = serialIndex; - heartdata[serialIndex].y = HealthService::GetInstance()->GetHourlyHeartRate(serialIndex); - } + for (int serialIndex = 0; serialIndex < 24; serialIndex++) { + heartdata[serialIndex].x = serialIndex; + heartdata[serialIndex].y = + HealthService::GetInstance()->GetHourlyHeartRate(serialIndex); + } +#endif + heartSerial->AddPoints(heartdata, 24); + heartSerial->SetLineColor(Color::Red()); + heartSerial->SetFillColor(Color::Red()); + heartSerial->EnableGradient(true); + + heartchart->AddDataSerial(heartSerial); + heartchart->Invalidate(); +} +/*设置心率动画*/ +void HeartChartView::HeartImageAnimator() { + imageAnimator = new UIImageAnimatorView(); + if (imageAnimator == nullptr) { + WEARABLE_LOGE( + WEARABLE_LOG_MODULE_APP, + "HeartRateView::[HeartbeatImageAnimator] new imageAnimator fail"); + return; + } + imageAnimator->SetPosition(HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y, + HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT); + imageAnimator->SetImageAnimatorSrc(g_heartImageInfo, HEARTBEAT_IMAGE_NUM, + HEARTBEAT_DELAY); + imageAnimator->SetRepeat(true); + container_->Add(imageAnimator); + imageAnimator->Start(); +} +/*初始化心率曲线*/ +void HeartChartView::InitChartView(void) { + if (heartchart == nullptr) { + heartchart = new UIChartPolyline(); + } + heartchart->SetPosition(80, 199); + heartchart->Resize(313, 122); + heartchart->SetViewId("uiChart1"); + heartchart->SetStyle(STYLE_BACKGROUND_OPA, 0x00); + + UIXAxis &heartXAxis = heartchart->GetXAxis(); + heartXAxis.SetMarkNum(24); + heartXAxis.SetDataRange(0, 24); + heartXAxis.SetLineColor(Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + + UIYAxis &heartYAxis = heartchart->GetYAxis(); + heartYAxis.SetMarkNum(4); + heartYAxis.SetDataRange(0, 220); + heartYAxis.SetLineColor(Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + + heartchart->SetGradientOpacity(78, 64); + + // Add to rootView + container_->Add(heartchart); +} + +//初始化label +/* +需要显示一个动态心率的效果 +有5个label代表 曲线图的yè½´ + 最大心率+10 + 最大心率+10-(最小心率-10)*3/4 + 最大心率+10-(最小心率-10)*2/4 + 最大心率+10-(最小心率-10)*1/4 + 最小心率-10 +*/ +void HeartChartView::InitChartLabel() { + //当前心率值 + InitLabel(displayheart_, 133, 32, 200, 100, "label", "--", GILROY_BOLD_FONT, + 65); + // 单位 + InitRollLabel(uheart_, 283, 52, 100, 60, "label", STR_TIMES_PER_MIN, + DEFAULT_VECTOR_FONT_FILENAME, 30); + uheart_->SetTextColor(Color::GetColorFromRGBA(0x99, 0x99, 0x99, 0xff)); + //上一次检测信息 + InitLabel(lastheart_, 53, 130, 360, 35, "label", "--", + DEFAULT_VECTOR_FONT_FILENAME, 30); + //最小心率 不居中 + InitLabelAdapt(minheart_, 293, 380, 200, 35, "label", "--", + DEFAULT_VECTOR_FONT_FILENAME, 35); + //最大心率 不居中 + InitLabelAdapt(maxheart_, 158, 380, 200, 35, "label", "--", + DEFAULT_VECTOR_FONT_FILENAME, 35); + + //动态心率最大 + InitLabel(maxheart_dynamic_, 30, 190, 50, 20, "label", "220", + DEFAULT_VECTOR_FONT_FILENAME, 20); + maxheart_dynamic_->SetTextColor( + Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + //动态心率3/4 + InitLabel(maxheart_dynamic_3_, 30, 218, 50, 20, "label", "160", + DEFAULT_VECTOR_FONT_FILENAME, 20); + maxheart_dynamic_3_->SetTextColor( + Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + //动态心率2/4 + InitLabel(maxheart_dynamic_2_, 30, 247, 50, 20, "label", "100", + DEFAULT_VECTOR_FONT_FILENAME, 20); + maxheart_dynamic_2_->SetTextColor( + Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + //动态心率1/4 + InitLabel(maxheart_dynamic_1_, 30, 277, 50, 20, "label", "40", + DEFAULT_VECTOR_FONT_FILENAME, 20); + maxheart_dynamic_1_->SetTextColor( + Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + //动态心率最小 + InitLabel(minheart_dynamic_, 30, 306, 50, 20, "label", "0", + DEFAULT_VECTOR_FONT_FILENAME, 20); + minheart_dynamic_->SetTextColor( + Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + + container_->Add(displayheart_); + container_->Add(uheart_); + container_->Add(lastheart_); + container_->Add(minheart_); + container_->Add(maxheart_); + container_->Add(maxheart_dynamic_); + container_->Add(maxheart_dynamic_3_); + container_->Add(maxheart_dynamic_2_); + container_->Add(maxheart_dynamic_1_); + container_->Add(minheart_dynamic_); +} + +void HeartChartView::InitChartImageView() { + + if (minRateIconView_ == nullptr) { + minRateIconView_ = new UIImageView(); + } + minRateIconView_->SetPosition(266, 394); + minRateIconView_->Resize(100, 100); + minRateIconView_->SetViewId("minRateIcon"); + minRateIconView_->SetSrc(BUTTOM_ICON_PATH); + if (maxRateIconView_ == nullptr) { + maxRateIconView_ = new UIImageView(); + } + maxRateIconView_->SetPosition(129, 394); + maxRateIconView_->Resize(100, 100); + maxRateIconView_->SetViewId("maxRateIcon"); + maxRateIconView_->SetSrc(TOP_ICON_PATH); + + if (chartBackgroundView_ == nullptr) { + chartBackgroundView_ = new UIImageView(); + } + chartBackgroundView_->SetPosition(30, 160); + chartBackgroundView_->Resize(100, 100); + chartBackgroundView_->SetViewId("chartBackground"); + chartBackgroundView_->SetSrc(BACKGROUND_IMAGE_PATH); + + container_->Add(chartBackgroundView_); + container_->Add(minRateIconView_); + container_->Add(maxRateIconView_); + + if (heartIconView_ == nullptr) { + heartIconView_ = new UIImageView(); + } + heartIconView_->SetPosition(111, 57); + heartIconView_->Resize(100, 100); + heartIconView_->SetViewId("heartIcon"); + heartIconView_->SetSrc(HEART_ICON_PATH); + + container_->Add(heartIconView_); + heartIconView_->SetVisible(true); +#if 0 + if (lineView_ == nullptr) { + lineView_ = new UIImageView(); + } + lineView_->SetPosition(230, 385); + lineView_->Resize(1, 26); + lineView_->SetViewId("lineView"); + lineView_->SetStyle(STYLE_BACKGROUND_COLOR, 0xff666666); + lineView_->SetStyle(STYLE_BACKGROUND_OPA, 0xff); + + container_->Add(lineView_); + lineView_->SetVisible(true); #endif - heartSerial->AddPoints(heartdata, 24); - heartSerial->SetLineColor(Color::Red()); - heartSerial->SetFillColor(Color::Red()); - heartSerial->EnableGradient(true); - - heartchart->AddDataSerial(heartSerial); - heartchart->Invalidate(); - } - /*设置心率动画*/ - void HeartChartView::HeartImageAnimator() - { - imageAnimator = new UIImageAnimatorView(); - if (imageAnimator == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartRateView::[HeartbeatImageAnimator] new imageAnimator fail"); - return; - } - imageAnimator->SetPosition(HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT); - imageAnimator->SetImageAnimatorSrc(g_heartImageInfo, HEARTBEAT_IMAGE_NUM, HEARTBEAT_DELAY); - imageAnimator->SetRepeat(true); - container_->Add(imageAnimator); - imageAnimator->Start(); - } - /*初始化心率曲线*/ - void HeartChartView::InitChartView(void) - { - if (heartchart == nullptr) - { - heartchart = new UIChartPolyline(); - } - heartchart->SetPosition(95, 178); - heartchart->Resize(320, 110); - heartchart->SetViewId("uiChart"); - heartchart->SetStyle(STYLE_BACKGROUND_OPA, 0x00); - - UIXAxis &heartXAxis = heartchart->GetXAxis(); - UIYAxis &heartYAxis = heartchart->GetYAxis(); - heartXAxis.SetMarkNum(1); - heartXAxis.SetDataRange(0, 24); - heartXAxis.SetLineColor(Color::GetColorFromRGBA(0, 0, 0, 0)); - heartYAxis.SetMarkNum(1); - heartYAxis.SetDataRange(0, 220); - heartYAxis.SetLineColor(Color::GetColorFromRGBA(0, 0, 0, 0)); - - heartchart->SetGradientOpacity(25, 180); - // heartchart->SetGradientOpacity(255, 0); - - container_->Add(heartchart); - } - /*初始化检测界面*/ - bool HeartChartView::HeartViewInit() - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartChartViewInit is begin"); - // 初始化图片 - InitImageView(CoordinateimageView, 38, 130, 390, 200, "CoordinateimageView", BACKGROUND_IMAGE_PATH); - InitImageView(TopimageView, 131, 350, 21, 12, "TopimageView", TOP_ICON_PATH); - InitImageView(BottomimageView, 267, 350, 21, 12, "BottomimageView", BUTTOM_ICON_PATH); - // 初始化心率值 - InitLabel(CurrentHeartText, 172, 62, 102, 79, "CurrentHeartText", "--", GILROY_BOLD_FONT, 65); - InitRollLabel(UHeartText, 283, 85, 100, 35, "UHeartText", STR_TIMES_PER_MIN, DEFAULT_VECTOR_FONT_FILENAME, 30); - InitLabelAdapt(MaxHeartText, 160, 336, 102, 79, "MaxHeartText", "--", DEFAULT_VECTOR_FONT_FILENAME, 35); - InitLabelAdapt(MinHeartText, 295, 336, 102, 79, "MinHeartText", "--", DEFAULT_VECTOR_FONT_FILENAME, 35); - - container_->Add(CoordinateimageView); - container_->Add(TopimageView); - container_->Add(BottomimageView); - container_->Add(CurrentHeartText); - container_->Add(UHeartText); - container_->Add(MaxHeartText); - container_->Add(MinHeartText); - - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartChartViewInit is ok"); - return true; - } - - void HeartChartView::OnStart() - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnStart"); - View::OnStart(); - - SetContainerView(new UIViewGroup()); - container_->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight()); - - if (!HeartViewInit()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartChartView::InitHeartView fail"); - } - - HeartImageAnimator(); - InitChartView(); - SetDataChart(); - SetDataTopAndBottom(); - - SetContainerView(container_); - container_->SetDraggable(true); - container_->SetTouchable(true); - container_->SetOnDragListener(presenter_); - - // 增加按键监听 - RootView::OnKeyActListener *keyactListener = (RootView::OnKeyActListener *)OHOS::HeartChartPresenter::GetInstance(); - RootView::GetInstance()->SetOnKeyActListener(keyactListener); - } - void HeartChartView::OnSetUpView() - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnSetUpView"); - View::OnSetUpView(); - - Draw(); - } - void HeartChartView::OnTearDownView() - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnTearDownView"); - View::OnTearDownView(); - return; - } - - void HeartChartView::OnStop() - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnStop"); - View::OnStop(); - if (container_ != nullptr) - { - container_->RemoveAll(); - delete container_; - container_ = nullptr; - } - return; - } } + +//更新图表配置 +void HeartChartView::UpdateChartConfig() { + if (minheart_dynamic_ == nullptr || maxheart_dynamic_1_ == nullptr || + maxheart_dynamic_2_ == nullptr || maxheart_dynamic_3_ == nullptr || + heartchart == nullptr) { + return; + } + + // 获取动态心率数据 + HeartModel::GetInstance()->SetArrayData(); + uint16_t *dynamicArray = HeartModel::GetInstance()->GetArrayData(); + + //更新label + if (dynamicArray) { + minheart_dynamic_->SetText(std::to_string(dynamicArray[0]).c_str()); + maxheart_dynamic_1_->SetText(std::to_string(dynamicArray[1]).c_str()); + maxheart_dynamic_2_->SetText(std::to_string(dynamicArray[2]).c_str()); + maxheart_dynamic_3_->SetText(std::to_string(dynamicArray[3]).c_str()); + maxheart_dynamic_->SetText(std::to_string(dynamicArray[4]).c_str()); + } + //更新chart + UIYAxis &heartYAxis = heartchart->GetYAxis(); + heartYAxis.SetMarkNum(4); + heartYAxis.SetDataRange(dynamicArray[0], dynamicArray[4]); + heartYAxis.SetLineColor(Color::GetColorFromRGBA(0x33, 0x33, 0x33, 0xff)); + heartchart->Invalidate(); +} +//更新上一次检测信息 +void HeartChartView::SetLastHeart() { + if (lastheart_ == nullptr) + return; + std::string lastStr = HeartModel::GetInstance()->GetCheckString(); + lastheart_->SetText(lastStr.c_str()); +} +/*初始化检测界面*/ +bool HeartChartView::HeartViewInit() { + + //图片 + InitChartImageView(); + //标签 + InitChartLabel(); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartChartViewInit is ok"); + return true; +} +UIViewGroup *HeartChartView::GetchartGroup() { + SetContainerView(new UIViewGroup()); + container_->SetPosition(0, 0, Screen::GetInstance().GetWidth(), + Screen::GetInstance().GetHeight()); + if (!HeartViewInit()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "HeartChartView::InitHeartView fail"); + } + // HeartImageAnimator(); 暂时屏蔽 + InitChartView(); + UpdateChartConfig(); + SetDataChart(); + SetLastHeart(); + SetDataTopAndBottom(); + return container_; +} +void HeartChartView::OnStart() { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnStart"); + View::OnStart(); + + SetContainerView(new UIViewGroup()); + container_->SetPosition(0, 0, Screen::GetInstance().GetWidth(), + Screen::GetInstance().GetHeight()); + + if (!HeartViewInit()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "HeartChartView::InitHeartView fail"); + } + + HeartImageAnimator(); + InitChartView(); + UpdateChartConfig(); + SetDataChart(); + SetLastHeart(); + SetDataTopAndBottom(); + + SetContainerView(container_); + container_->SetDraggable(true); + container_->SetTouchable(true); + container_->SetOnDragListener(presenter_); + + // 增加按键监听 + RootView::OnKeyActListener *keyactListener = + (RootView::OnKeyActListener *)OHOS::HeartChartPresenter::GetInstance(); + RootView::GetInstance()->SetOnKeyActListener(keyactListener); +} +void HeartChartView::OnSetUpView() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnSetUpView"); + View::OnSetUpView(); + + Draw(); +} +void HeartChartView::OnTearDownView() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnTearDownView"); + View::OnTearDownView(); + return; +} + +void HeartChartView::OnStop() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartChartView::OnStop"); + View::OnStop(); + if (container_ != nullptr) { + container_->RemoveAll(); + delete container_; + container_ = nullptr; + } + return; +} +} // namespace OHOS diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp index e87e4b6fb..f21f91f53 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp @@ -1,33 +1,31 @@ #include "heartrate/include/HeartModel.h" -#include "wearable_log.h" -#include "graphic_service.h" #include "IndoorWalkPreparedView.h" #include "IndoorWalkPresenter.h" #include "MainViewSample.h" +#include "graphic_service.h" +#include "wearable_log.h" -#include "heartrate/include/HeartRateView.h" +#include "DialModelHeartRate.h" +#include "heartrate/include/HeartChartView.h" #include "heartrate/include/HeartDetectionPresenter.h" +#include "heartrate/include/HeartRateView.h" #include "heartrate/include/HeartResultPresenter.h" -#include "heartrate/include/HeartChartView.h" -#include "DialModelHeartRate.h" -#include -#include #include "DialModelHeartRate.h" -#include "health_service.h" +#include "custom_runtime.h" #include "custom_utils.h" +#include "health_service.h" #include "ppg_service.h" -#include "custom_runtime.h" +#include #include #include -#include +#include -#include "ui_service.h" #include "battery_hal.h" +#include "ui_service.h" #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #define MAX_UNWEAR_COUNT 30 @@ -36,698 +34,717 @@ extern "C" #define MIN_DISPLAY_HEART 60 #define HEARTTEST 1 //[0 开启测试 1 关闭] - /* 佩戴检测结果 */ - enum - { - SENSOR_WEAR_ON = 0, - SENSOR_WEAR_OFF, - SENSOR_WEAR_UNKNOW, - SENSOR_WEAR_MAX - }; +/* 佩戴检测结果 */ +enum { + SENSOR_WEAR_ON = 0, + SENSOR_WEAR_OFF, + SENSOR_WEAR_UNKNOW, + SENSOR_WEAR_MAX +}; - using namespace OHOS; +using namespace OHOS; #define LEN 32 - static void Notify(void *args, const Topic topic, Request *request); - - Subscriber heartSubscirber = { - .identity = nullptr, - .args = nullptr, - .Notify = Notify, - }; - static void ProcessHeartRateUpdate(Request *request); - static void RefreshHeartData(); - void HeartDataSubscribeTopic(Topic topic) - { - BroadcastApi *broadcastApi = nullptr; - IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME, BROADCAST_FEATURE_NAME); - if (api == nullptr) - { - return; - } - int result = api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi); - if (result != 0 || broadcastApi == nullptr) - { - return; - } - int ret = broadcastApi->SubscribeTopic((IUnknown *)broadcastApi, topic, &heartSubscirber); - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartSubscribeTopic ret = %d, topic = %u", ret, topic); - broadcastApi->Release((IUnknown *)broadcastApi); - } - - void HearDatatUnsubscribeTopic(Topic topic) - { - BroadcastApi *broadcastApi = nullptr; - IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME, BROADCAST_FEATURE_NAME); - if (api == nullptr) - { - return; - } - int result = api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi); - if (result != 0 || broadcastApi == nullptr) - { - return; - } - broadcastApi->UnsubscribeTopic((IUnknown *)broadcastApi, topic, &heartSubscirber); - broadcastApi->Release((IUnknown *)broadcastApi); - } +static void Notify(void *args, const Topic topic, Request *request); + +Subscriber heartSubscirber = { + .identity = nullptr, + .args = nullptr, + .Notify = Notify, +}; +static void ProcessHeartRateUpdate(Request *request); +static void RefreshHeartData(); +void HeartDataSubscribeTopic(Topic topic) { + BroadcastApi *broadcastApi = nullptr; + IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME, + BROADCAST_FEATURE_NAME); + if (api == nullptr) { + return; + } + int result = + api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi); + if (result != 0 || broadcastApi == nullptr) { + return; + } + int ret = broadcastApi->SubscribeTopic((IUnknown *)broadcastApi, topic, + &heartSubscirber); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "HeartSubscribeTopic ret = %d, topic = %u", ret, topic); + broadcastApi->Release((IUnknown *)broadcastApi); +} - static void Notify(void *args, const Topic topic, Request *request) - { - UNUSED(args); - UNUSED(topic); +void HearDatatUnsubscribeTopic(Topic topic) { + BroadcastApi *broadcastApi = nullptr; + IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME, + BROADCAST_FEATURE_NAME); + if (api == nullptr) { + return; + } + int result = + api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi); + if (result != 0 || broadcastApi == nullptr) { + return; + } + broadcastApi->UnsubscribeTopic((IUnknown *)broadcastApi, topic, + &heartSubscirber); + broadcastApi->Release((IUnknown *)broadcastApi); +} - // 训练过程中不需要判断数据准确性,不需要存储心率数据 - if (uapi_dev_runtime_get_train_status() == 1 || request == NULL) - { - return; - } +static void Notify(void *args, const Topic topic, Request *request) { + UNUSED(args); + UNUSED(topic); - switch (request->msgId) - { - case TOPIC_EVENT_HEARTRATE_UPDATA: - // ProcessHeartRateUpdate(request); - break; + // 训练过程中不需要判断数据准确性,不需要存储心率数据 + if (uapi_dev_runtime_get_train_status() == 1 || request == NULL) { + return; + } - case TOPIC_EVENT_NEXTDAY_UPDATE: - case TOPIC_EVENT_UTCTIME_UPDATE: - RefreshHeartData(); - break; + switch (request->msgId) { + case TOPIC_EVENT_HEARTRATE_UPDATA: + // ProcessHeartRateUpdate(request); + break; - case TOPIC_EVENT_WEARSTATE_UPDATE: - break; + case TOPIC_EVENT_NEXTDAY_UPDATE: + case TOPIC_EVENT_UTCTIME_UPDATE: + RefreshHeartData(); + break; - default: - break; - } - } + case TOPIC_EVENT_WEARSTATE_UPDATE: + break; - static void ProcessHeartRateUpdate(Request *request) - { - uint16_t preheart = *reinterpret_cast(request->data); - - // 直接处理心率数据,不进行筛选 - uint16_t index_ = HeartModel::GetInstance()->GetIndex(); - HeartDatas *heartInfo = (HeartDatas *)malloc(sizeof(HeartDatas)); - if (heartInfo == NULL) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[Notify] malloc fail"); - return; - } + default: + break; + } +} - heartInfo->index = index_; - heartInfo->maxX = index_; - heartInfo->minX = index_; - heartInfo->perSec = preheart; - heartInfo->rest = preheart; - /*最大最小值不为0*/ - heartInfo->maxValue = preheart; - heartInfo->minValue = preheart; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "heartRateData = %d %d", heartInfo->index, preheart); - OHOS::HeartModel::GetInstance()->HeartRatePros(heartInfo); - - free(heartInfo); // 释放内存 - heartInfo = nullptr; - } +static void ProcessHeartRateUpdate(Request *request) { + uint16_t preheart = *reinterpret_cast(request->data); + + // 直接处理心率数据,不进行筛选 + uint16_t index_ = HeartModel::GetInstance()->GetIndex(); + HeartDatas *heartInfo = (HeartDatas *)malloc(sizeof(HeartDatas)); + if (heartInfo == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[Notify] malloc fail"); + return; + } + + heartInfo->index = index_; + heartInfo->maxX = index_; + heartInfo->minX = index_; + heartInfo->perSec = preheart; + heartInfo->rest = preheart; + /*最大最小值不为0*/ + heartInfo->maxValue = preheart; + heartInfo->minValue = preheart; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "heartRateData = %d %d", + heartInfo->index, preheart); + OHOS::HeartModel::GetInstance()->HeartRatePros(heartInfo); + + free(heartInfo); // 释放内存 + heartInfo = nullptr; +} - static void RefreshHeartData() - { - OHOS::HeartModel::GetInstance()->ClearHeartData(); - GraphicService::GetInstance()->PostGraphicEvent( - std::bind(&OHOS::HeartModel::Heart_Update_View, OHOS::HeartModel::GetInstance())); - } +static void RefreshHeartData() { + OHOS::HeartModel::GetInstance()->ClearHeartData(); + GraphicService::GetInstance()->PostGraphicEvent(std::bind( + &OHOS::HeartModel::Heart_Update_View, OHOS::HeartModel::GetInstance())); +} #ifdef __cplusplus } #endif -namespace OHOS -{ - void HeartModel::ClearHeartData(void) - { - pretime = 0; - entryTimes = 0; - aveCount = 0; - preMaxValue = 0; - preMaxX = NUM_1; - preMinValue = HEART_RATE_LIMIT_UPPER; - preMinX = NUM_1; - countMax = 0; - countMin = 0; - healthDatas.heartRateMax.x = (uint16_t)0XFFFF; - healthDatas.heartRateMax.y = 0; - healthDatas.heartRateMin.x = (uint16_t)0XFFFF; - healthDatas.heartRateMin.y = (uint16_t)0XFFFF; - for (int i = 0; i < HEART_AVE_NUM; i++) - { - healthDatas.heartRateAvg[i].x = (uint16_t)0XFFFF; - healthDatas.heartRateAvg[i].y = (uint16_t)0XFFFF; - } - if (HeartRateView::GetInstance() != nullptr) - { - HeartRateView::GetInstance()->ClearElectrocardiogram(); - } - SetAveHeartRateCount(0); - GraphicService::GetInstance()->PostGraphicEvent(std::bind(&HeartModel::RefreshHeartRateScreen, HeartModel::GetInstance(), - healthDatas.heartRatePerSec, healthDatas.heartRateRest, healthDatas.heartRateMax.y, healthDatas.heartRateMin.y)); - } - - HeartModel::HeartModel() - { - /*初始化读取文件*/ - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartModel::HeartModel()"); - HeartRateData *data = HealthService::GetInstance()->ReadHeartRateData(); - /*初始化历史文件*/ - HealthService::GetInstance()->LoadDailyHeartRate(); - if (data != nullptr) - { - currentheart = data->Heart; - timestamp_ms = data->timestamp; - // 更新表盘心率数据 - DialModelHeartRate::GetInstance()->UpdateHeartRate(currentheart); - delete data; - } - else - { - currentheart = 0; - timestamp_ms = 0; - } - } - - HeartModel::~HeartModel() - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartModel::~HeartModel()"); - HearDatatUnsubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA); - HearDatatUnsubscribeTopic(TOPIC_EVENT_NEXTDAY_UPDATE); - HearDatatUnsubscribeTopic(TOPIC_EVENT_UTCTIME_UPDATE); - HearDatatUnsubscribeTopic(TOPIC_EVENT_WEARSTATE_UPDATE); - } - - HeartModel *HeartModel::GetInstance(void) - { - static HeartModel heartModel; - return &heartModel; - } - uint16_t HeartModel::GetIndex() - { - return index_; - } - void HeartModel::SetIndex(uint16_t index) - { - index_ = index; - } - - void HeartModel::Init(void) - { - HeartDataSubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA); - HeartDataSubscribeTopic(TOPIC_EVENT_NEXTDAY_UPDATE); - HeartDataSubscribeTopic(TOPIC_EVENT_UTCTIME_UPDATE); - HeartDataSubscribeTopic(TOPIC_EVENT_WEARSTATE_UPDATE); - } - - Point *HeartModel::GetAveHeartRate(void) - { - return healthDatas.heartRateAvg; - } - - void HeartModel::HandleMaxHeart(uint16 coord, uint16 value) - { - healthDatas.heartRateMax.x = coord; - healthDatas.heartRateMax.y = value; - // 插入最大心率 countMax 数据个数 - if (preMaxValue != healthDatas.heartRateMax.y && aveCount < HEART_AVE_NUM) - { - if (preMaxX == healthDatas.heartRateMax.x && countMax < HEART_AVE_NUM) - { - healthDatas.heartRateAvg[countMax].y = healthDatas.heartRateMax.y; - } - else if (aveCount > NUM_2 && (healthDatas.heartRateMax.x == healthDatas.heartRateAvg[aveCount - 1].x)) - { - healthDatas.heartRateAvg[aveCount - 1].y = healthDatas.heartRateMax.y; - } - else - { - healthDatas.heartRateAvg[aveCount] = healthDatas.heartRateMax; - countMax = aveCount; - aveCount++; - } - if (healthDatas.heartRateMax.x != 0) - { - if (healthDatas.heartRateAvg[0].x == 0 && healthDatas.heartRateAvg[1].x == 0) - { - for (int i = 1; i < (aveCount - 1); i++) - { - healthDatas.heartRateAvg[i] = healthDatas.heartRateAvg[i + 1]; - } - aveCount--; - countMax--; - } - } - } - preMaxValue = healthDatas.heartRateMax.y; - preMaxX = healthDatas.heartRateMax.x; - } - - void HeartModel::HandleMinHeart(uint16 coord, uint16 value) - { - // 最小心率 - healthDatas.heartRateMin.x = coord; - healthDatas.heartRateMin.y = value; - // 插入最小心率 - // avecount 当下有效数据个数,在MaxHeart中也用到,看起来似乎有问题??? - // preMinValue 上一个心率最小值 - // preMinX 上一个最小值对应的坐标 - // 当上一个值与当前值不等,且没有超过总数限制,则进行数据处理 - if (preMinValue != healthDatas.heartRateMin.y && aveCount < HEART_AVE_NUM) - { - - if (preMinX == healthDatas.heartRateMin.x && countMin < HEART_AVE_NUM) - { - // 上一个最小坐标和当前值一致,且数据没超过限制,则直接赋值给有效数据 countMin 即可 - healthDatas.heartRateAvg[countMin].y = healthDatas.heartRateMin.y; - } - else if (aveCount > NUM_2 && (healthDatas.heartRateMin.x == healthDatas.heartRateAvg[aveCount - 1].x)) - { - // 有效数据大于2,且当前x值与原始数据最后一个x一致,最后一个数据赋值 - healthDatas.heartRateAvg[aveCount - 1].y = healthDatas.heartRateMin.y; - } - else - { - healthDatas.heartRateAvg[aveCount] = healthDatas.heartRateMin; - countMin = aveCount; - aveCount++; - } - - // 最初的值一直是0 ,则只显示1个 ,不会在后面增加数据。 - if (healthDatas.heartRateMin.x != 0) - { - if (healthDatas.heartRateAvg[0].x == 0 && healthDatas.heartRateAvg[1].x == 0) - { - for (int i = 0; i < (aveCount - 1); i++) - { - healthDatas.heartRateAvg[i] = healthDatas.heartRateAvg[i + 1]; - } - aveCount--; - countMin--; - } - } - } - preMinValue = healthDatas.heartRateMin.y; - preMinX = healthDatas.heartRateMin.x; - } - - void HeartModel::HeartRatePros(HeartDatas *heartInfo) - { - uint16_t perSecHeartRate = 0; - uint16_t restHeartRate = 0; - - // 每秒心率 - perSecHeartRate = heartInfo->perSec; - if (perSecHeartRate >= HEART_RATE_LIMIT_LOWER && perSecHeartRate <= HEART_RATE_LIMIT_UPPER) - { - healthDatas.heartRatePerSec = perSecHeartRate; - } - - GraphicService::GetInstance()->PostGraphicEvent(std::bind(&HeartModel::RefreshHeartRateScreen, HeartModel::GetInstance(), - healthDatas.heartRatePerSec, healthDatas.heartRateRest, healthDatas.heartRateMax.y, healthDatas.heartRateMin.y)); - } - - uint16_t HeartModel::GetAveHeartRateCount(void) - { - return aveCount; - } +namespace OHOS { +void HeartModel::ClearHeartData(void) { + pretime = 0; + entryTimes = 0; + aveCount = 0; + preMaxValue = 0; + preMaxX = NUM_1; + preMinValue = HEART_RATE_LIMIT_UPPER; + preMinX = NUM_1; + countMax = 0; + countMin = 0; + healthDatas.heartRateMax.x = (uint16_t)0XFFFF; + healthDatas.heartRateMax.y = 0; + healthDatas.heartRateMin.x = (uint16_t)0XFFFF; + healthDatas.heartRateMin.y = (uint16_t)0XFFFF; + for (int i = 0; i < HEART_AVE_NUM; i++) { + healthDatas.heartRateAvg[i].x = (uint16_t)0XFFFF; + healthDatas.heartRateAvg[i].y = (uint16_t)0XFFFF; + } + if (HeartRateView::GetInstance() != nullptr) { + HeartRateView::GetInstance()->ClearElectrocardiogram(); + } + SetAveHeartRateCount(0); + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&HeartModel::RefreshHeartRateScreen, HeartModel::GetInstance(), + healthDatas.heartRatePerSec, healthDatas.heartRateRest, + healthDatas.heartRateMax.y, healthDatas.heartRateMin.y)); +} - uint16_t HeartModel::GetHeartRateMax(void) - { - return healthDatas.heartRateMax.y; - } +HeartModel::HeartModel() { + /*初始化读取文件*/ + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartModel::HeartModel()"); + HeartRateData *data = HealthService::GetInstance()->ReadHeartRateData(); + /*初始化历史文件*/ + HealthService::GetInstance()->LoadDailyHeartRate(); + if (data != nullptr) { + currentheart = data->Heart; + timestamp_ms = data->timestamp; + // 更新表盘心率数据 + DialModelHeartRate::GetInstance()->UpdateHeartRate(currentheart); + delete data; + } else { + currentheart = 0; + timestamp_ms = 0; + } + //配置动态数组 + SetArrayData(); +} - uint16_t HeartModel::GetHeartRateMin(void) - { - return healthDatas.heartRateMin.y; - } +HeartModel::~HeartModel() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartModel::~HeartModel()"); + HearDatatUnsubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA); + HearDatatUnsubscribeTopic(TOPIC_EVENT_NEXTDAY_UPDATE); + HearDatatUnsubscribeTopic(TOPIC_EVENT_UTCTIME_UPDATE); + HearDatatUnsubscribeTopic(TOPIC_EVENT_WEARSTATE_UPDATE); +} - void HeartModel::SetHeartRatePerSec(uint32 sec) - { - healthDatas.heartRatePerSec = sec; - if (HeartRateView::GetInstance() == nullptr) - { - return; - } - HeartRateView::GetInstance()->RefreshHeartRatePerSec(healthDatas.heartRatePerSec); - } +HeartModel *HeartModel::GetInstance(void) { + static HeartModel heartModel; + return &heartModel; +} +uint16_t HeartModel::GetIndex() { return index_; } +void HeartModel::SetIndex(uint16_t index) { index_ = index; } + +void HeartModel::Init(void) { + HeartDataSubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA); + HeartDataSubscribeTopic(TOPIC_EVENT_NEXTDAY_UPDATE); + HeartDataSubscribeTopic(TOPIC_EVENT_UTCTIME_UPDATE); + HeartDataSubscribeTopic(TOPIC_EVENT_WEARSTATE_UPDATE); +} - void HeartModel::SetAveHeartRateCount(uint16_t value) - { - aveCount = value; - } +Point *HeartModel::GetAveHeartRate(void) { return healthDatas.heartRateAvg; } + +void HeartModel::HandleMaxHeart(uint16 coord, uint16 value) { + healthDatas.heartRateMax.x = coord; + healthDatas.heartRateMax.y = value; + // 插入最大心率 countMax 数据个数 + if (preMaxValue != healthDatas.heartRateMax.y && aveCount < HEART_AVE_NUM) { + if (preMaxX == healthDatas.heartRateMax.x && countMax < HEART_AVE_NUM) { + healthDatas.heartRateAvg[countMax].y = healthDatas.heartRateMax.y; + } else if (aveCount > NUM_2 && (healthDatas.heartRateMax.x == + healthDatas.heartRateAvg[aveCount - 1].x)) { + healthDatas.heartRateAvg[aveCount - 1].y = healthDatas.heartRateMax.y; + } else { + healthDatas.heartRateAvg[aveCount] = healthDatas.heartRateMax; + countMax = aveCount; + aveCount++; + } + if (healthDatas.heartRateMax.x != 0) { + if (healthDatas.heartRateAvg[0].x == 0 && + healthDatas.heartRateAvg[1].x == 0) { + for (int i = 1; i < (aveCount - 1); i++) { + healthDatas.heartRateAvg[i] = healthDatas.heartRateAvg[i + 1]; + } + aveCount--; + countMax--; + } + } + } + preMaxValue = healthDatas.heartRateMax.y; + preMaxX = healthDatas.heartRateMax.x; +} - void HeartModel::RefreshHeartRateScreen(uint16_t perSec, uint16_t rest, uint16_t maxRate, uint16_t minRate) - { - uint16_t currentViewId = NativeAbility::GetInstance().GetCurSliceId(); - /*主界面刷新心率*/ - if (currentViewId == VIEW_MAIN && MainClockView::GetInstance() != nullptr) - { - MainClockView::GetInstance()->RefreshHeartRate(perSec); - } - /*心率卡片刷新心率数据*/ - if (MainViewSample::GetInstance() != nullptr && HeartRateView::GetInstance() != nullptr) - { - if (MainViewSample::GetInstance()->GetHorCurrentCard() == HEART_RATE) - { - HeartRateView::GetInstance()->RefreshHeartRatePerSec(perSec); - HeartRateView::GetInstance()->RefreshHeartRateMax(maxRate); - HeartRateView::GetInstance()->RefreshHeartRateMin(minRate); - } - } - /*applist心率刷新心率数据*/ - if (HeartChartView::GetInstance() != nullptr) - { - HeartChartView::GetInstance()->UpdateShowHeart(); - } - } - /* ---------------------------------- 状态检测 ---------------------------------- */ - - // 重新初始化 - void HeartModel::ClearDisplayData() - { - /*显示的心率数据清空*/ - currentheart = 0; - timestamp_ms = 0; - displayheart = 0; - displayheart_max = 0; // 显示最大心率 - displayheart_min = 0; // 显示最小心率 - } - // 获取心率数据 - uint16_t HeartModel::GetHeartdata() - { - return currentheart; - } +void HeartModel::HandleMinHeart(uint16 coord, uint16 value) { + // 最小心率 + healthDatas.heartRateMin.x = coord; + healthDatas.heartRateMin.y = value; + // 插入最小心率 + // avecount 当下有效数据个数,在MaxHeart中也用到,看起来似乎有问题??? + // preMinValue 上一个心率最小值 + // preMinX 上一个最小值对应的坐标 + // 当上一个值与当前值不等,且没有超过总数限制,则进行数据处理 + if (preMinValue != healthDatas.heartRateMin.y && aveCount < HEART_AVE_NUM) { + + if (preMinX == healthDatas.heartRateMin.x && countMin < HEART_AVE_NUM) { + // 上一个最小坐标和当前值一致,且数据没超过限制,则直接赋值给有效数据 + // countMin 即可 + healthDatas.heartRateAvg[countMin].y = healthDatas.heartRateMin.y; + } else if (aveCount > NUM_2 && (healthDatas.heartRateMin.x == + healthDatas.heartRateAvg[aveCount - 1].x)) { + // 有效数据大于2,且当前x值与原始数据最后一个x一致,最后一个数据赋值 + healthDatas.heartRateAvg[aveCount - 1].y = healthDatas.heartRateMin.y; + } else { + healthDatas.heartRateAvg[aveCount] = healthDatas.heartRateMin; + countMin = aveCount; + aveCount++; + } + + // 最初的值一直是0 ,则只显示1个 ,不会在后面增加数据。 + if (healthDatas.heartRateMin.x != 0) { + if (healthDatas.heartRateAvg[0].x == 0 && + healthDatas.heartRateAvg[1].x == 0) { + for (int i = 0; i < (aveCount - 1); i++) { + healthDatas.heartRateAvg[i] = healthDatas.heartRateAvg[i + 1]; + } + aveCount--; + countMin--; + } + } + } + preMinValue = healthDatas.heartRateMin.y; + preMinX = healthDatas.heartRateMin.x; +} - uint16_t HeartModel::GetShowHeartdata() - { - return displayheart; - } - uint16_t HeartModel::GetShowMaxHeartdata() - { - return displayheart_max; - } - uint16_t HeartModel::GetShowMinHeartdata() - { - return displayheart_min; - } - uint32_t HeartModel::GetCheckTime() - { - return timestamp_ms; - } +void HeartModel::HeartRatePros(HeartDatas *heartInfo) { + uint16_t perSecHeartRate = 0; + uint16_t restHeartRate = 0; + + // 每秒心率 + perSecHeartRate = heartInfo->perSec; + if (perSecHeartRate >= HEART_RATE_LIMIT_LOWER && + perSecHeartRate <= HEART_RATE_LIMIT_UPPER) { + healthDatas.heartRatePerSec = perSecHeartRate; + } + + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&HeartModel::RefreshHeartRateScreen, HeartModel::GetInstance(), + healthDatas.heartRatePerSec, healthDatas.heartRateRest, + healthDatas.heartRateMax.y, healthDatas.heartRateMin.y)); +} - void HeartModel::SetCheckTime(uint32_t time) - { - timestamp_ms = time; - } - void HeartModel::SetResult(HeartResult result) - { - heartresult_ = result; - } - HeartResult HeartModel::GetResult() - { - return heartresult_; - } - // 控制心率检测 - void HeartModel::Heart_Control(HeartState state, HeartCheck check) - { - if (check < checkstate) - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Higher execution instruction exists"); - return; - } - if (state == HeartState::End && heartstate == true) - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartState End"); - uint8_t md = PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST; - send_ppg_cmd_msg(md); - heartstate = false; - // 复原检测状态 - checkstate = HeartCheck::RESTSTSTE; - } - else if (state == HeartState::Start && heartstate == false) - { - /*充电状态下不进行检测*/ - bool isCharging = get_charge_stat(); // 获取充电状态 - if (isCharging) - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "充电不能检测"); - return; - } - - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartState Start"); - uint8_t md = PPG_SERVICE_CMD_TYPE_DO_PPG_TEST; - send_ppg_cmd_msg(md); - heartstate = true; - checkstate = check; - } - } - // 开始检测 - void HeartModel::Heart_Start() - { - displayheart = 0; - // displayheart_max = 0; // 显示最大心率 [每次检测进行清除] - // displayheart_min = 0; // 显示最小心率 [每次检测进行清除] - - SetResult(HeartResult::NOT_TESTED); // 重置检测 - // 进行初始化操作 - if (!sensorstate) - { - Heart_Control(HeartState::Start, HeartCheck::INITIATIVE); - sensorstate = true; - } - } +uint16_t HeartModel::GetAveHeartRateCount(void) { return aveCount; } - // 结束检测 - void HeartModel::Heart_Stop() - { - valid_counter_ = 0; - disvalid_counter_ = 0; - unwear_counter_ = 0; - - /*主界面卡片检测 或者 被动检测*/ - if (checkstate == HeartCheck::CARDCHECK || checkstate == HeartCheck::PASSIVITY) - { - if (heartresult_ == HeartResult::SUCCESS) - { - Heart_Save(); - /*更新曲线*/ - GraphicService::GetInstance()->PostGraphicEvent(std::bind(&HeartModel::Heart_Update_View, HeartModel::GetInstance())); - } - /*关闭被动检测*/ - Heart_Control(HeartState::End, HeartCheck::PASSIVITY); - return; - } +uint16_t HeartModel::GetHeartRateMax(void) { + return healthDatas.heartRateMax.y; +} - if (sensorstate) - { - // Heart_Control(HeartState::End, HeartCheck::INITIATIVE); 主动检测心率 不需要关闭 - sensorstate = false; - Heart_Result(); // 处理结果 - } - } - // 保存检测数据 - void HeartModel::Heart_Save() - { - HeartRateData data; - data.Heart = currentheart; - data.timestamp = HeartResultPresenter::GetInstance()->GetCurrentTime(); - SetCheckTime(data.timestamp); - HealthService::GetInstance()->UpdateHealthData(data); - - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "保存的心率数据: %d %ld", currentheart, data.timestamp); - } +uint16_t HeartModel::GetHeartRateMin(void) { + return healthDatas.heartRateMin.y; +} - // 显示检测结果// 显示检测结果 - void HeartModel::Heart_Result() - { - // 心率提醒(0开 1关) - uint8_t HeartRemindState = ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_HEARTRATE_REMIND); - uint16_t ThresholdValue = ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_HEARTRATE_THRESHOLD_VALUE); - - if (HeartRemindState) - { - // 检查当前心率是否高于或低于阈值 - uint16_t ThresholdState = ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_HEARTRATE_MAX_MIN); - - if (ThresholdState == 0 && currentheart < ThresholdValue && currentheart != 0) - { - // 当前心率低于阈值 - heartresult_ = HeartResult::LOW_RESULT; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 低结果情况, currentheart = %d, ThresholdValue = %d", currentheart, ThresholdValue); - } - else if (ThresholdState == 1 && currentheart > ThresholdValue) - { - // 当前心率高于阈值 - heartresult_ = HeartResult::HIGH_RESULT; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 高结果情况, currentheart = %d, ThresholdValue = %d", currentheart, ThresholdValue); - } - } +void HeartModel::SetHeartRatePerSec(uint32 sec) { + healthDatas.heartRatePerSec = sec; + if (HeartRateView::GetInstance() == nullptr) { + return; + } + HeartRateView::GetInstance()->RefreshHeartRatePerSec( + healthDatas.heartRatePerSec); +} - // 根据结果进行处理 - switch (heartresult_) - { - case HeartResult::SUCCESS: - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 成功"); - Heart_Save(); - /*更新曲线*/ - GraphicService::GetInstance()->PostGraphicEvent(std::bind(&HeartModel::Heart_Update_View, HeartModel::GetInstance())); - break; - - case HeartResult::NOT_WORN: // 未佩戴状态 - case HeartResult::TIMEOUT: // 超时情况 - case HeartResult::INVALID_DATA: // 无效数据情况 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: %s情况", - heartresult_ == HeartResult::NOT_WORN ? "未佩戴状态" : heartresult_ == HeartResult::TIMEOUT ? "超时" - : "无效数据"); - NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_ABNORMAL); - break; - - case HeartResult::LOW_RESULT: - // 低心率结果处理 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 低结果情况"); - HealthState lowHealthState; - lowHealthState.checkType = BLOOD_CHECK; - lowHealthState.resultStatus = LOW; - lowHealthState.checkResult = ThresholdValue; - HealthService::GetInstance()->SetHealthCurrent(lowHealthState); - NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_INVALID); - break; - - case HeartResult::HIGH_RESULT: - // 高心率结果处理 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 高结果情况"); - HealthState highHealthState; - highHealthState.checkType = BLOOD_CHECK; - highHealthState.resultStatus = HIGH; - highHealthState.checkResult = ThresholdValue; - HealthService::GetInstance()->SetHealthCurrent(highHealthState); - NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_INVALID); - break; - - default: - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 未知状态"); - break; - } - } - void HeartModel::SetWearStatus(int32_t wear) - { - // 设置佩戴状态 - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartModel Weartest::%d", wear); - - // 计数更新 - if (wear_ != 1 && wear != 1) - { - unwear_counter_++; // 佩戴错误计时器计数 - } - else - { - unwear_counter_ = 0; // 佩戴正常情况下清零计数器 - } - wear_ = wear; - // 检查是否达到了最大未佩戴计数限制 - if (unwear_counter_ >= MAX_UNWEAR_COUNT) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 未佩戴计数最大 unwear_counter: %d", unwear_counter_); - SetResult(HeartResult::NOT_WORN); - Heart_Stop(); - } - } +void HeartModel::SetAveHeartRateCount(uint16_t value) { aveCount = value; } + +void HeartModel::RefreshHeartRateScreen(uint16_t perSec, uint16_t rest, + uint16_t maxRate, uint16_t minRate) { + uint16_t currentViewId = NativeAbility::GetInstance().GetCurSliceId(); + /*主界面刷新心率*/ + if (currentViewId == VIEW_MAIN && MainClockView::GetInstance() != nullptr) { + MainClockView::GetInstance()->RefreshHeartRate(perSec); + } + /*心率卡片刷新心率数据*/ + if (MainViewSample::GetInstance() != nullptr && + HeartRateView::GetInstance() != nullptr) { + if (MainViewSample::GetInstance()->GetHorCurrentCard() == HEART_RATE) { + HeartRateView::GetInstance()->RefreshHeartRatePerSec(perSec); + HeartRateView::GetInstance()->RefreshHeartRateMax(maxRate); + HeartRateView::GetInstance()->RefreshHeartRateMin(minRate); + } + } + /*applist心率刷新心率数据*/ + if (HeartChartView::GetInstance() != nullptr) { + HeartChartView::GetInstance()->UpdateShowHeart(); + } +} +/* ---------------------------------- 状态检测 + * ---------------------------------- */ + +// 重新初始化 +void HeartModel::ClearDisplayData() { + /*显示的心率数据清空*/ + currentheart = 0; + timestamp_ms = 0; + displayheart = 0; + displayheart_max = 0; // 显示最大心率 + displayheart_min = 0; // 显示最小心率 +} +// 获取心率数据 +uint16_t HeartModel::GetHeartdata() { return currentheart; } + +uint16_t HeartModel::GetShowHeartdata() { return displayheart; } +uint16_t HeartModel::GetShowMaxHeartdata() { return displayheart_max; } +uint16_t HeartModel::GetShowMinHeartdata() { return displayheart_min; } +uint32_t HeartModel::GetCheckTime() { return timestamp_ms; } + +void HeartModel::SetCheckTime(uint32_t time) { timestamp_ms = time; } +void HeartModel::SetResult(HeartResult result) { heartresult_ = result; } +HeartResult HeartModel::GetResult() { return heartresult_; } +// 控制心率检测 +void HeartModel::Heart_Control(HeartState state, HeartCheck check) { + if (check < checkstate) { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "Higher execution instruction exists"); + return; + } + if (state == HeartState::End && heartstate == true) { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartState End"); + uint8_t md = PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST; + send_ppg_cmd_msg(md); + heartstate = false; + // 复原检测状态 + checkstate = HeartCheck::RESTSTSTE; + } else if (state == HeartState::Start && heartstate == false) { + /*充电状态下不进行检测*/ + bool isCharging = get_charge_stat(); // 获取充电状态 + if (isCharging) { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "充电不能检测"); + return; + } + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartState Start"); + uint8_t md = PPG_SERVICE_CMD_TYPE_DO_PPG_TEST; + send_ppg_cmd_msg(md); + heartstate = true; + checkstate = check; + } +} +// 开始检测 +void HeartModel::Heart_Start() { + displayheart = 0; + // displayheart_max = 0; // 显示最大心率 [每次检测进行清除] + // displayheart_min = 0; // 显示最小心率 [每次检测进行清除] + + SetResult(HeartResult::NOT_TESTED); // 重置检测 + // 进行初始化操作 + if (!sensorstate) { + Heart_Control(HeartState::Start, HeartCheck::INITIATIVE); + sensorstate = true; + } +} - void HeartModel::UpHeartdata(uint16_t heart) - { - // 如果处于训练模式,提前返回 - if (uapi_dev_runtime_get_train_status() == 1) - return; - - displayheart = heart; - - // 更新心率和计数器 - if (displayheart != 0) - { - currentheart = displayheart; // 更新当前心率 - valid_counter_++; // 增加有效计数器 - disvalid_counter_ = 0; // 清空无效计数器 - - // 更新最大和最小心率 - displayheart_max = (displayheart_max < displayheart ? displayheart : displayheart_max); - - // 确保最小心率的第一次赋值大于50 - if (displayheart_min == 0 && displayheart > MIN_DISPLAY_HEART) - { - displayheart_min = displayheart; // 初始化最小心率 - } - else - { - displayheart_min = (displayheart_min > displayheart && displayheart > MIN_DISPLAY_HEART) - ? displayheart - : displayheart_min; - } - } - else - { - disvalid_counter_++; // 增加无效计数器 - valid_counter_ = 0; // 清零有效计数器 - } +// 结束检测 +void HeartModel::Heart_Stop() { + valid_counter_ = 0; + disvalid_counter_ = 0; + unwear_counter_ = 0; + + /*主界面卡片检测 或者 被动检测*/ + if (checkstate == HeartCheck::CARDCHECK || + checkstate == HeartCheck::PASSIVITY) { + if (heartresult_ == HeartResult::SUCCESS) { + Heart_Save(); + /*更新曲线*/ + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&HeartModel::Heart_Update_View, HeartModel::GetInstance())); + } + /*关闭被动检测*/ + Heart_Control(HeartState::End, HeartCheck::PASSIVITY); + return; + } + + if (sensorstate) { + // Heart_Control(HeartState::End, HeartCheck::INITIATIVE); 主动检测心率 + // 不需要关闭 + sensorstate = false; + Heart_Result(); // 处理结果 + } +} +// 保存检测数据 +void HeartModel::Heart_Save() { + HeartRateData data; + data.Heart = currentheart; + data.timestamp = HeartResultPresenter::GetInstance()->GetCurrentTime(); + SetCheckTime(data.timestamp); + HealthService::GetInstance()->UpdateHealthData(data); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "保存的心率数据: %d %ld", + currentheart, data.timestamp); +} - // 检查无效计数器是否达标 - if (disvalid_counter_ >= MAX_DISVALID_HRS_COUNT) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 无效数达标 disvalid_counter: %d", disvalid_counter_); - SetResult(HeartResult::INVALID_DATA); // 标记为无效数据 - Heart_Stop(); - return; - } +// 显示检测结果// 显示检测结果 +void HeartModel::Heart_Result() { + // 心率提醒(0开 1关) + uint8_t HeartRemindState = ConfigModel::GetInstance()->get_configData_int( + ConfigModel::CONFIGMODEL_ITEM_HEARTRATE_REMIND); + uint16_t ThresholdValue = ConfigModel::GetInstance()->get_configData_int( + ConfigModel::CONFIGMODEL_ITEM_HEARTRATE_THRESHOLD_VALUE); + + if (HeartRemindState) { + // 检查当前心率是否高于或低于阈值 + uint16_t ThresholdState = ConfigModel::GetInstance()->get_configData_int( + ConfigModel::CONFIGMODEL_ITEM_HEARTRATE_MAX_MIN); + + if (ThresholdState == 0 && currentheart < ThresholdValue && + currentheart != 0) { + // 当前心率低于阈值 + heartresult_ = HeartResult::LOW_RESULT; + WEARABLE_LOGE( + WEARABLE_LOG_MODULE_APP, + "检测结果: 低结果情况, currentheart = %d, ThresholdValue = %d", + currentheart, ThresholdValue); + } else if (ThresholdState == 1 && currentheart > ThresholdValue) { + // 当前心率高于阈值 + heartresult_ = HeartResult::HIGH_RESULT; + WEARABLE_LOGE( + WEARABLE_LOG_MODULE_APP, + "检测结果: 高结果情况, currentheart = %d, ThresholdValue = %d", + currentheart, ThresholdValue); + } + } + + // 根据结果进行处理 + switch (heartresult_) { + case HeartResult::SUCCESS: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 成功"); + Heart_Save(); + /*更新曲线*/ + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&HeartModel::Heart_Update_View, HeartModel::GetInstance())); + break; + + case HeartResult::NOT_WORN: // 未佩戴状态 + case HeartResult::TIMEOUT: // 超时情况 + case HeartResult::INVALID_DATA: // 无效数据情况 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: %s情况", + heartresult_ == HeartResult::NOT_WORN + ? "未佩戴状态" + : heartresult_ == HeartResult::TIMEOUT ? "超时" + : "无效数据"); + NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_ABNORMAL); + break; + + case HeartResult::LOW_RESULT: + // 低心率结果处理 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 低结果情况"); + HealthState lowHealthState; + lowHealthState.checkType = BLOOD_CHECK; + lowHealthState.resultStatus = LOW; + lowHealthState.checkResult = ThresholdValue; + HealthService::GetInstance()->SetHealthCurrent(lowHealthState); + NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_INVALID); + break; + + case HeartResult::HIGH_RESULT: + // 高心率结果处理 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 高结果情况"); + HealthState highHealthState; + highHealthState.checkType = BLOOD_CHECK; + highHealthState.resultStatus = HIGH; + highHealthState.checkResult = ThresholdValue; + HealthService::GetInstance()->SetHealthCurrent(highHealthState); + NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_INVALID); + break; + + default: + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 未知状态"); + break; + } +} +void HeartModel::SetWearStatus(int32_t wear) { + // 设置佩戴状态 + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HeartModel Weartest::%d", wear); + + // 计数更新 + if (wear_ != 1 && wear != 1) { + unwear_counter_++; // 佩戴错误计时器计数 + } else { + unwear_counter_ = 0; // 佩戴正常情况下清零计数器 + } + wear_ = wear; + // 检查是否达到了最大未佩戴计数限制 + if (unwear_counter_ >= MAX_UNWEAR_COUNT) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "检测结果: 未佩戴计数最大 unwear_counter: %d", + unwear_counter_); + SetResult(HeartResult::NOT_WORN); + Heart_Stop(); + } +} - // 检查有效计数器是否达标 - if (valid_counter_ >= MAX_VALID_HRS_COUNT) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: 成功 valid_counter: %d currentheart: %d", valid_counter_, currentheart); - SetResult(HeartResult::SUCCESS); // 标记为成功检测 - Heart_Stop(); - return; - } +void HeartModel::UpHeartdata(uint16_t heart) { + // 如果处于训练模式,提前返回 + if (uapi_dev_runtime_get_train_status() == 1) + return; + + displayheart = heart; + + // 更新心率和计数器 + if (displayheart != 0) { + currentheart = displayheart; // 更新当前心率 + valid_counter_++; // 增加有效计数器 + disvalid_counter_ = 0; // 清空无效计数器 + + // 更新最大和最小心率 + displayheart_max = + (displayheart_max < displayheart ? displayheart : displayheart_max); + + // 确保最小心率的第一次赋值大于50 + if (displayheart_min == 0 && displayheart > MIN_DISPLAY_HEART) { + displayheart_min = displayheart; // 初始化最小心率 + } else { + displayheart_min = + (displayheart_min > displayheart && displayheart > MIN_DISPLAY_HEART) + ? displayheart + : displayheart_min; + } + } else { + disvalid_counter_++; // 增加无效计数器 + valid_counter_ = 0; // 清零有效计数器 + } + + // 检查无效计数器是否达标 + if (disvalid_counter_ >= MAX_DISVALID_HRS_COUNT) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "检测结果: 无效数达标 disvalid_counter: %d", + disvalid_counter_); + SetResult(HeartResult::INVALID_DATA); // 标记为无效数据 + Heart_Stop(); + return; + } + + // 检查有效计数器是否达标 + if (valid_counter_ >= MAX_VALID_HRS_COUNT) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "检测结果: 成功 valid_counter: %d currentheart: %d", + valid_counter_, currentheart); + SetResult(HeartResult::SUCCESS); // 标记为成功检测 + Heart_Stop(); + return; + } + + // 刷新心率显示 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "[heart data update displayheart %d displayheart_max %d " + "displayheart_min %d]", + displayheart, displayheart_max, displayheart_min); + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&HeartModel::RefreshHeartRateScreen, HeartModel::GetInstance(), + displayheart, 0, displayheart_max, displayheart_min)); +} - // 刷新心率显示 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[heart data update displayheart %d displayheart_max %d displayheart_min %d]", displayheart, - displayheart_max, displayheart_min); - GraphicService::GetInstance()->PostGraphicEvent(std::bind(&HeartModel::RefreshHeartRateScreen, HeartModel::GetInstance(), - displayheart, 0, displayheart_max, displayheart_min)); - } +void HeartModel::Heart_Update_View(void) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新心率界面"); + int hour = HealthService::GetInstance()->GetCurrentHour(); + if (HeartRateView::GetInstance() != nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新主界面卡片"); + HeartRateView::GetInstance()->Update_data_Chart(hour); + } + if (HeartChartView::GetInstance() != nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新测量心率卡片"); + HeartChartView::GetInstance()->Update_data_Chart(hour); + } +} - void HeartModel::Heart_Update_View(void) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新心率界面"); - int hour = HealthService::GetInstance()->GetCurrentHour(); - if (HeartRateView::GetInstance() != nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新主界面卡片"); - HeartRateView::GetInstance()->Update_data_Chart(hour); - } - if (HeartChartView::GetInstance() != nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新测量心率卡片"); - HeartChartView::GetInstance()->Update_data_Chart(hour); - } - } +void HeartModel::CleanAllData(void) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Nextday!"); + if (MainViewSample::GetInstance() != nullptr && + HeartRateView::GetInstance() != nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新主界面心率卡片"); + HeartRateView::GetInstance()->CleanAllDataView(); + } + if (HeartChartView::GetInstance() != nullptr) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新测量心率卡片"); + HeartChartView::GetInstance()->CleanAllDataView(); + } +} - void HeartModel::CleanAllData(void) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Nextday!"); - if (MainViewSample::GetInstance() != nullptr && HeartRateView::GetInstance() != nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新主界面心率卡片"); - HeartRateView::GetInstance()->CleanAllDataView(); - } - if (HeartChartView::GetInstance() != nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "更新测量心率卡片"); - HeartChartView::GetInstance()->CleanAllDataView(); - } - } +//配置5个动态心率数据 +//最大 最小 +void HeartModel::SetArrayData() { + // 如果没有进行心率检测,则默认为0-220 + if (displayheart_max == 0 || displayheart_min == 0) { + dynamic_heartrate[0] = 0; + dynamic_heartrate[1] = 40; + dynamic_heartrate[2] = 100; + dynamic_heartrate[3] = 160; + dynamic_heartrate[4] = 220; + return; // 直接返回 + } + + // 计算心率范围并添加缓冲 + uint16_t adjusted_min = + (displayheart_min > 10) ? (displayheart_min / 2) : displayheart_min; + uint16_t adjusted_max = + (displayheart_max < 210) ? (displayheart_max + 10) : displayheart_max; + + uint16_t range = adjusted_max - adjusted_min; + uint16_t interval = range / 4; // 每个部分的宽度 + + // 设置动态心率数据 + dynamic_heartrate[0] = adjusted_min; + dynamic_heartrate[1] = adjusted_min + interval; + dynamic_heartrate[2] = adjusted_min + 2 * interval; + dynamic_heartrate[3] = adjusted_min + 3 * interval; + dynamic_heartrate[4] = adjusted_max; + + // 确保所有值为整数 + for (int i = 0; i < 5; i++) { + dynamic_heartrate[i] = static_cast(round(dynamic_heartrate[i])); + } + + // 打印动态心率数据 + for (int i = 0; i < 5; i++) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "dynamic_heartrate[%d] = %d", i, + dynamic_heartrate[i]); + } +} +//获取动态心率配置数组 +uint16_t *HeartModel::GetArrayData() { return dynamic_heartrate; } + +// 获取检测字符串 +// 获取检测字符串 +std::string HeartModel::GetCheckString() { + std::string check_string = "检测结果未知"; // 默认返回值 + + // 获取检测数据 + if (currentheart == 0) { + check_string = "暂无检测数据"; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测数据: %s", + check_string.c_str()); // 打印无检测数据信息 + return check_string; // 直接返回,无需继续处理 + } + + // 获取目前的时间戳 + uint32_t currentTime; + if (uapi_get_timestampe_ss(¤tTime) != ERRCODE_SUCC) { + check_string = "获取当前时间戳失败"; // 如果获取时间戳失败,返回相应的信息 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "获取当前时间戳失败"); // 打印错误信息 + return check_string; // 直接返回,无法进行后续计算 + } + + // 检查时间戳是否有效 + if (timestamp_ms == 0) { + check_string = std::to_string(currentheart) + " " + "时间戳无效,无法检测"; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "时间戳无效,无法检测: %s", + check_string.c_str()); + return check_string; // 直接返回,无需继续处理 + } + + // 进行时间戳相减计算 + uint32_t diff = currentTime - timestamp_ms; + uint32_t diff_min = diff / 60; // 计算分钟差 + uint32_t diff_hour = diff_min / 60; // 计算小时差 + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "当前时间: %d, 上次检测时间: %d", + currentTime, timestamp_ms); // 打印时间信息 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "时间差 (秒): %d, 时间差 (分钟): %d, 时间差 (小时): %d", diff, + diff_min, diff_hour); // 打印时间差信息 + + // 根据时间差生成检测字符串 + if (diff_min < 1) { + check_string = std::to_string(currentheart) + "次/分 " + "刚刚检测"; + } else if (diff_hour < 1) { // 一个小时内 + check_string = std::to_string(currentheart) + "次/分 " + + std::to_string(diff_min) + "分钟前"; + } else { + check_string = std::to_string(currentheart) + "次/分 " + "超过一个小时前"; + } + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测结果: %s", + check_string.c_str()); // 打印最终检测结果 + return check_string; } +} // namespace OHOS diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateCardView.cpp b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateCardView.cpp new file mode 100644 index 000000000..b85a86986 --- /dev/null +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateCardView.cpp @@ -0,0 +1,64 @@ +#include "heartrate/include/HeartRateCardView.h" +#include "heartrate/include/HeartChartView.h" + +namespace OHOS { +static HeartRateCardView *g_pHeartRateCardView = nullptr; +HeartRateCardView::HeartRateCardView() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "HeartRateCardView::HeartRateCardView"); + SetPosition(0, 0, HORIZONTAL_RESOLUTION, VERTICAL_RESOLUTION); + g_pHeartRateCardView = this; +} +HeartRateCardView::~HeartRateCardView() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "HeartRateCardView::~HeartRateCardView"); + ClearAll(); + g_pHeartRateCardView = nullptr; +} +HeartRateCardView *HeartRateCardView::GetInstance() { + return g_pHeartRateCardView; +} +void HeartRateCardView::ClearAll(void) { + if (viewiInitStatus == true) { + RemoveAll(); + if (heartRateGroupView != nullptr) { + delete heartRateGroupView; + heartRateGroupView = nullptr; + } + } +} + +bool HeartRateCardView::InitView(void) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartRateCardView::InitView"); + heartRateCardView = new HeartChartView(); + if (heartRateCardView == nullptr) { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "HeartChartView::new HeartChartView fail!"); + return false; + } + + heartRateGroupView = + dynamic_cast(heartRateCardView->GetchartGroup()); + if (heartRateGroupView == nullptr) { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "HeartChartView->HeartChartViewInit() == nullptr!!"); + return false; + } + + Add(heartRateGroupView); + return true; +} +UIViewGroup *HeartRateCardView::GetHeartRateCardView() { + return heartRateGroupView; +} +void HeartRateCardView::PreLoad(void) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartRateCardView::PreLoad"); + if (!viewiInitStatus) { + InitView(); + viewiInitStatus = true; + } +} +void HeartRateCardView::UnLoad(void) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartRateCardView::UnLoad"); +} +} // namespace OHOS \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateView.cpp b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateView.cpp index 26910d3fc..6c7c5d882 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartRateView.cpp @@ -39,13 +39,120 @@ namespace OHOS #define COORDINATE_GRAD_MAX_OPA 180 // 心形心跳 -#define HEARTBEAT_IMAGE_WIDTH 92 -#define HEARTBEAT_IMAGE_HEIGHT 92 -#define HEARTBEAT_IMAGE_X 105 -#define HEARTBEAT_IMAGE_Y 50 -#define HEARTBEAT_IMAGE_NUM 19 -#define HEARTBEAT_DELAY 50 - +static constexpr int HEARTBEAT_IMAGE_WIDTH = 54; +static constexpr int HEARTBEAT_IMAGE_HEIGHT = 50; +static constexpr int HEARTBEAT_IMAGE_X = 111; +static constexpr int HEARTBEAT_IMAGE_Y = 57; +static constexpr int HEARTBEAT_IMAGE_NUM = 21; +static constexpr int HEARTBEAT_DELAY = 50; +// 心跳image +static ImageAnimatorInfo g_heartBeatImageInfo[HEARTBEAT_IMAGE_NUM] = { + {PNG_A004_070_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_071_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_072_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_073_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_074_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_075_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_076_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_077_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_078_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_079_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_080_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_081_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_082_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_083_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_084_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_085_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_086_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_087_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_088_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_089_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, + {PNG_A004_090_IMAGE_PATH, + {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, + HEARTBEAT_IMAGE_WIDTH, + HEARTBEAT_IMAGE_HEIGHT, + IMG_SRC_FILE_PATH}, +}; // 最高心率 #define TOP_IMAGE_WIDTH 32 #define TOP_IMAGE_HEIGHT 32 @@ -104,29 +211,6 @@ namespace OHOS #define PERSEC_HEART_TEXT_WIDTH 75 #define PERSEC_HEART_TEXT_HEIGHT (PERSEC_HEART_TEXT_FONT_SIZE + 5) - // 心跳image - static ImageAnimatorInfo g_heartBeatImageInfo[HEARTBEAT_IMAGE_NUM] = { - {PNG_A004_070_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_071_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_072_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_073_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_074_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_075_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_076_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_077_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_078_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_079_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - - {PNG_A004_080_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_081_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_082_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_083_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_084_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_085_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_086_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_087_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - {PNG_A004_088_IMAGE_PATH, {HEARTBEAT_IMAGE_X, HEARTBEAT_IMAGE_Y}, HEARTBEAT_IMAGE_WIDTH, HEARTBEAT_IMAGE_HEIGHT, IMG_SRC_FILE_PATH}, - }; HeartRateView::HeartRateView() { diff --git a/code/sdk/application/wearable/fd230app/nativeui/main/include/MainViewSample.h b/code/sdk/application/wearable/fd230app/nativeui/main/include/MainViewSample.h index d223ae7b3..904ec7d3c 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/main/include/MainViewSample.h +++ b/code/sdk/application/wearable/fd230app/nativeui/main/include/MainViewSample.h @@ -41,6 +41,7 @@ #include "message/include/MessageControlView.h" #include "sleep/include/SleepCardView.h" #include "set_card/include/SetMainView.h" +#include "heartrate/include/HeartRateCardView.h" namespace OHOS { class MainPresenterSample; @@ -107,7 +108,7 @@ namespace OHOS PlayersView *playersView{nullptr}; CompassControlView *compassControlView{nullptr}; - HeartRateView *heartRateView{nullptr}; + HeartRateCardView *heartRateView{nullptr}; BloodCardView *bloodView{nullptr}; SleepCardView *sleepView{nullptr}; Training_CardView *traingView{nullptr}; diff --git a/code/sdk/application/wearable/fd230app/nativeui/main/src/MainViewSample.cpp b/code/sdk/application/wearable/fd230app/nativeui/main/src/MainViewSample.cpp index cb5f59948..52bd08867 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/main/src/MainViewSample.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/main/src/MainViewSample.cpp @@ -540,7 +540,7 @@ namespace OHOS UICardPage *MainViewSample::InitHeartRatePage(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainViewSample::InitHeartRatePage"); - heartRateView = new HeartRateView(); + heartRateView = new HeartRateCardView(); if (heartRateView == nullptr) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "heartRateView new fail"); diff --git a/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/include/SafeModeManagerModelC.h b/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/include/SafeModeManagerModelC.h new file mode 100644 index 000000000..3f05a59eb --- /dev/null +++ b/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/include/SafeModeManagerModelC.h @@ -0,0 +1,16 @@ + +#ifndef SAFE_MODE_MANAGER_MODEL_C_H +#define SAFE_MODE_MANAGER_MODEL_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +//进行修复开始 +void repari_file_start(void); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/src/SafeModeManagerModel.cpp b/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/src/SafeModeManagerModel.cpp index efbf921ba..b4a6effe9 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/src/SafeModeManagerModel.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/safemodemanager/src/SafeModeManagerModel.cpp @@ -9,6 +9,7 @@ #include "safemodemanager/include/RepairView.h" #include "safemodemanager/include/ResourceCheckView.h" #include "safemodemanager/include/SafeModeManagerModel.h" +#include "safemodemanager/include/SafeModeManagerModelC.h" #include "safemodemanager/include/SafeModeManagerView.h" #include "broadcast_feature.h" @@ -31,6 +32,11 @@ const char *get_version_string(void); } static const char *CHECK_DIFFERENTIAL_FILE = "/system/check_differential.txt"; + +void repari_file_start() { + OHOS::SafeModeManagerModel::GetInstance()->RepairStart(); +} + namespace OHOS { SafeModeManagerModel *SafeModeManagerModel::GetInstance(void) { @@ -52,14 +58,14 @@ static void httpc_download_result(void *arg, httpc_result_t httpc_result, "srv_res %d, err %d\n", httpc_result, rx_content_len, srv_res, err); if (httpc_result == HTTPC_RESULT_OK) { - http_single_download_stop(); OHOS::SafeModeManagerModel::GetInstance()->AddRepairCount(); - //开始下一个文件 - OHOS::SafeModeManagerModel::GetInstance()->RepairStart(); + //发消息进行重新开始 + do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_DOWNLOAD_RES, nullptr, 0); } else { //结束 OHOS::SafeModeManagerModel::GetInstance()->RepairEnd(); } + http_single_download_stop(); file_total_len = 0; return; } diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/background.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/background.bin index edb9ce594..0d2eccddf 100644 --- a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/background.bin +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/background.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab68b0439d276fdf0f5d839281e44a516a6fb44d3bf4843101b3578acdd6d68e +oid sha256:efc0bb2ab65d0ad5bb1469bf529b32e0f0f8cde2b9256def4001c365da2ec845 size 52024 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_01.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_01.bin new file mode 100644 index 000000000..18fa39006 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_01.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbbfb65f766ee8de8840e15812abb1d31035dfe2f1e7d63b23dac073896f5600 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_02.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_02.bin new file mode 100644 index 000000000..d1470415c --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_02.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13a516df219bf7246ec34ca65171bfa9000988907e7c9151584bd85efaddc19d +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_03.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_03.bin new file mode 100644 index 000000000..8b39899f7 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_03.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b108813a68df254a3cebda9f3e938a5d76188133211fa974184b2a607bc689ac +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_04.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_04.bin new file mode 100644 index 000000000..1769245ca --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_04.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbda3ff00bd54d277acc2a86ed3210f3a069302c2363cbafefd60d0379b9d25b +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_05.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_05.bin new file mode 100644 index 000000000..b3c8672ef --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_05.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fd2d8818d0cc756e065e6a872b029081bc38662e05283aca9cc75fedeeab206 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_06.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_06.bin new file mode 100644 index 000000000..d8a0f3aff --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_06.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be60c395114125059579cafdd42e9e8c6a5372d4123e5204d1315026bce8e736 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_07.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_07.bin new file mode 100644 index 000000000..492e25d9b --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_07.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60fef533bd4c8a68cc5ced7d1d51a4af7d2868ca6099564dac103fcc70f79593 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_08.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_08.bin new file mode 100644 index 000000000..ec1a74486 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_08.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1370669175f3ea04c455839c377ec9f6eade73ea04fb88820cb9b2717a76ed1 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_09.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_09.bin new file mode 100644 index 000000000..fee803509 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_09.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56e11c8370939aa63e41851bee4b39f1de58035f63c0ed9ed090fd04e546bcb0 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_10.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_10.bin new file mode 100644 index 000000000..815fa27d9 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_10.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4add68c802082e008168c41c47c8a8ac4d494d9a8ef36fd0116252ca0b54c899 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_11.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_11.bin new file mode 100644 index 000000000..1575ed10a --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_11.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b38bd661e9db76946670deca370c4e7cf12411f82be9c6ca5d185752efe54e01 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_12.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_12.bin new file mode 100644 index 000000000..b411dacfc --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_12.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c528e0e0aaa44eaf902c117c023000eb7843aa967aa245a64bd75b92338ec9f1 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_13.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_13.bin new file mode 100644 index 000000000..f7a35ccae --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_13.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2758f2d5973d4afabbf26c765ca46fd025bcbeb27d9849a226ca261d82ed5aa +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_14.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_14.bin new file mode 100644 index 000000000..f5d4406cd --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_14.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1a9c8e3f967f84b44b140735cd3ae23768531b0f552585b0f6d9326ffa2d12a +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_15.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_15.bin new file mode 100644 index 000000000..6938b241c --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_15.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae604513790f3f29fb2efe5d1077785c361b962a3877f1050df9d3fb91851a5c +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_16.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_16.bin new file mode 100644 index 000000000..cec639653 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_16.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e00d958a71ff06fa866c5b3cc46dc6e5a7b193e8681d84e1b60bad542db7fbc +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_17.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_17.bin new file mode 100644 index 000000000..c3b3281aa --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_17.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e27f49f08cefb628db2aacc319e2ffbbcfab9eb7afc945630254824adf510343 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_18.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_18.bin new file mode 100644 index 000000000..e5f996aac --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_18.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5afb9b60880657ad7092445e90fddc488cc4087eeb1452c0a82df8f31443d78f +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_19.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_19.bin new file mode 100644 index 000000000..a22ff5012 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_19.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac0505e5357f162a082c9675acb47094e9251883ad6289364133e8c52c8ae6eb +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_20.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_20.bin new file mode 100644 index 000000000..7ca22f9eb --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_20.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae4c188da2acee2a817c130543bf3be085676cdf6a108881dae341faf2a78a37 +size 1896 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_21.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_21.bin new file mode 100644 index 000000000..18fa39006 --- /dev/null +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/heart_chart/hearticon/HEARTICON_21.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbbfb65f766ee8de8840e15812abb1d31035dfe2f1e7d63b23dac073896f5600 +size 1896 diff --git a/code/sdk/drivers/peripheral/utils/custom_cmd_service.c b/code/sdk/drivers/peripheral/utils/custom_cmd_service.c index 04dbbbc07..8987dc0fa 100644 --- a/code/sdk/drivers/peripheral/utils/custom_cmd_service.c +++ b/code/sdk/drivers/peripheral/utils/custom_cmd_service.c @@ -39,6 +39,8 @@ #include "bletest.h" +#include "safemodemanager/include/SafeModeManagerModelC.h" + typedef struct { uint8_t cmd; @@ -255,6 +257,9 @@ static void custom_cmd_service_check_task(void const *arg) case CUSTOM_CMD_MSG_CHECK_RES: resfile_checksum_thread(); break; + case CUSTOM_CMD_MSG_DOWNLOAD_RES: + repari_file_start(); + break; default: PRINT("Unknown CUSTOM_CMD_MSG cmd 0x%02X \r\n", mail.cmd); break; diff --git a/code/sdk/drivers/peripheral/utils/custom_utils.h b/code/sdk/drivers/peripheral/utils/custom_utils.h index eacc91c7b..7be63e2da 100644 --- a/code/sdk/drivers/peripheral/utils/custom_utils.h +++ b/code/sdk/drivers/peripheral/utils/custom_utils.h @@ -217,6 +217,7 @@ uint32_t uapi_calendar_store_date(void); #define CUSTOM_CMD_MSG_BR_CONNECT 0x0C #define CUSTOM_CMD_MSG_CHECK_RES 0x0D +#define CUSTOM_CMD_MSG_DOWNLOAD_RES 0x0E typedef enum { BR_HFP_CONNECT=1, BR_HFP_DISCONNECT, diff --git a/tools/image_converter_tool/image_makcopy_tool.py b/tools/image_converter_tool/image_makcopy_tool.py new file mode 100644 index 000000000..65115a8de --- /dev/null +++ b/tools/image_converter_tool/image_makcopy_tool.py @@ -0,0 +1 @@ +import argparse import subprocess import shutil import os def main(): parser = argparse.ArgumentParser(description='Process paths.') parser.add_argument('-c', '--config', help='Config file path', required=True) parser.add_argument('-i', '--input', help='Input path', required=True) parser.add_argument('-o', '--output', help='Output path', required=True) args = parser.parse_args() print(f"Config path: {args.config}") print(f"Input path: {args.input}") print(f"Output path: {args.output}") # 定义命令和参数 command = [ "python", "images_tool.py", "-p", "file", "-d", "cmp", "-c", args.config, "-i", args.input, "-o", args.output ] print(f"Executing command: {' '.join(command)}") # 执行命令 try: subprocess.run(command, check=True) print("Command executed successfully.") except subprocess.CalledProcessError as e: print(f"An error occurred while executing the command: {e}") # 构建目标路径 target_dir = os.path.join('FD230', 'code', 'sdk', 'build', 'config', 'target_config', 'brandy', 'mk_fs_image', 'fd230', 'fs', 'user', 'res') print(f"Source directory: {args.output}") print(f"Target directory: {target_dir}") # 复制文件夹 try: if os.path.exists(target_dir): shutil.rmtree(target_dir) # 删除目标文件夹(如果存在) shutil.copytree(args.output, target_dir) print(f"Copied {args.output} to {target_dir}.") except Exception as e: print(f"An error occurred while copying the directory: {e}") if __name__ == "__main__": main() \ No newline at end of file diff --git a/tools/image_converter_tool/test/hert/heart/back.png b/tools/image_converter_tool/test/hert/heart/back.png new file mode 100644 index 0000000000000000000000000000000000000000..4a7cb442bfe9ed1b55c561958a5f82f53f967dbd GIT binary patch literal 4165 zcmd^D>01)m9>$uwEt08b|K6Cra2vlJ{Dx-K|_Dcs%Kd zvtq`@p=BxYFaYoh>+1mk%Wk=d-S1pK9ofal*)6V@*FOyhyWY4!@aBmjWhXnAqSk1 zo_dCvI6FNSJ8iA+HJM-}*L;Pap;Pi-c< z*f%E^3iD*m%;`Hf)TcQ=QUlyxwZ;ALH<{%xhfbXRa;kI0q9x?yqwChiT2A_$1c=ih z!rFz%VKmAjEt^r$CZPt#t#c^AXd}s9gT$TwIs-g;^364i&kh@@ZF?TRuk>46PS-zJ zz#N_lBKt=+3ElIY^|751^?ZlS4v{7uBL6yr`y;4tTM#+!Zd;q};Xf|S;HP?POrp8MM$9ib z2zSh{#Fvd5gfi-G?Z?3A5Lkyc_gNP~(kOrSh08e1J8yq;7Je~YSA9F*tr-#i0ul`w z)CUGdW528}BW?G|kG5{CNJo}LS?tjCTi)xDF3&N)#%66SPmm;{l!;QrHG{0Rc;##l zuoErH&~D${SpB{>$Ic->O*OqdE`eo2ecy;urQ|n(Sf`apomLS_ zl`gx(^@6yx!=Tw?W$AS<<10_iL-LG80niMbWb6?%b0^zzDHxx{yiyi)Z?WIq07k{k z5_!SP98u|;;Zoy!#zli6RAK_`;b^ao=tGwt?{-3MD(9`BG3Pl%OVYiusN$+y#~VVT zwy#W+-{BGnsXpfGD^lu6-m$0e2Eo!Q#;j@=H#@Sv|M`yqs~2CUksGQ5$dI#NB#h-Q zUE~d^4*PJg6`A-}Xw%>79TVjq%`34?q5C(4_>rgDYv`y?(dzby2DSAC9yDNylo$p4 zS@(z$Sk|{t0BnCHaM^q7qB)h-Q0PsYVnt$a1f9^rF$WZ=$0c1p+PsAL+G2kg!c9tD zt0HbG#AD}(8ZQ#U*irMVJZM&_V?>(%ii2ZQzGsiFL)}Xy@tp3Da`2ROX>K#r4#Og~ zdCOsZ{hCTf9R!s4yu+*;hgVfwyA4SCLZfN?T51xd&A;ExgmNAeAYMCrC2_8v?Ud*a zu7Ge>;3sIw!(+W3CPC3FX(X!xLWg;cl|zMD4V_@U9khphBXnQU5skOTziOORSoAM` zLDbb;yk%SEVm$ZZ4EsP=onuHr`M0YFF7Lmvvrv&N6qLF)3n+_pU_%N%>bjSda*`-p+tRm~8bhhjcha#t1_n4X|fcVz7T?TkYsK(ID#&p*~kzfV+;Iu*FX&R{zG}@n#n&S?+jry&RvcIxOSaIl}XtpD| zR93`^;oEj0XE?*flA2t&ii!M>a=|(=bL<+@vv0fCL?b=1-0h{bVm#z&G3}MfX`)P*y6{G;&}Am zieJVcqV$cZzsisW*5~qR=9^*6Sek63$kPUqM)vd&91x=u5AeaHu+b)a0p6_TMQS&q zHiass?4ATqFE#dpJc{p9CYac$6V39a)$6uLLf1ckUT7(WUjp+_3gk|zs6ZPriXNc zz7%pg*$s9A*Ykv>ua|XPdII~W9s4Q*^9gewqK>qD&&V&E1mR+Kt&Vl$z1!tvzAGc& z*&v}tw!?DhT-1j}k8x#tAb$lXw6A8aVq zZ80a!y%yw>;+#~AWSJ5#W|+ajf$&t&d@6G}V21B-OxzhBbG#@kO|v;9seZQz?DQ?` z1SBAOONAyPN^!~Rg=Qo_%OK3T#>5dneyPX*J#O|o!{_OIlYrl!LHxr^;vtRJwZL2r z=RTJEVaK1t`>bsR$0fbJrVDAp@v4l9A?w*FjVZa=8`LaX@Z8|)*-Yx zm>^qT#Ju3nQXmBrS>9y51#x}Gji85@fDInN2Rg!V&beCMX}hFT7ETJ1_JytfYRvgN z<(BvjCq?-DVl~Lf;Q@Ft=?zVS0i|4FRf!hF(VgL=`#_M@b2wvqKB#FC1@3osb%3^- zZ!V_ilO?j;lbFP5anq%VjL7bj2c6ypGZo|g>w=zE4Os`J?^p&n+dpUOG3i5Zt4c>p z8@V8FebdK;jKp#Ny=X0(x4XeZdHeYa8f&KftLcPIsD~S{K`#N%IE~yqio>&8@?*6_ zX7$thXr3N88dLiYCm#16$}c(oz`8^rWfUj^>!Pj4rZ@c@1pgFN_q4JMx){qpB1l%% zzhh15sBnxLAnp&P({{jZmv8{U*7Co==GMUFUem3sHLCvr0Kmi5^JmJ1Yj^(xO32YD literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/background.png b/tools/image_converter_tool/test/hert/heart_chart/background.png new file mode 100644 index 0000000000000000000000000000000000000000..4a7cb442bfe9ed1b55c561958a5f82f53f967dbd GIT binary patch literal 4165 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 literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heartchart/buttomicon.png b/tools/image_converter_tool/test/hert/heart_chart/buttomicon.png similarity index 100% rename from tools/image_converter_tool/test/hert/heartchart/buttomicon.png rename to tools/image_converter_tool/test/hert/heart_chart/buttomicon.png diff --git a/tools/image_converter_tool/test/hert/heartchart/hearticon.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon.png similarity index 100% rename from tools/image_converter_tool/test/hert/heartchart/hearticon.png rename to tools/image_converter_tool/test/hert/heart_chart/hearticon.png diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_01.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_01.png new file mode 100644 index 0000000000000000000000000000000000000000..3af8325e97006d7a5710d9c7ad70395d6c824131 GIT binary patch literal 935 zcmV;Y16cftP)Px&VM#fHo;^PmB_*h@qGkqALcRY*XIZ4@woMDsS84I#Uo+3D_fTl;QJ=gphXym@cl zylnyS7Y!&aO|UxiYSUwN<}gTk%+t|^={^r8d%6+zcfr%q3Qv2R!k#akpm=spu?;Ikvd4PQBSQ#4icVm7ufM`z_PgVK9czlX<;Sh`O_Jqc>LBe3PpylzPy0eC? z07!1_D=LX_uTfPMaAy6Zx~b+W@ivF3f669=n@W5{Uq zj-%#LOoaVdiVQf~TWoQUb6?cU|MG%0!4^gXO4(BnLZ#M%M!BU4mL3l&1!_HrUIO{Q zz#8@_#zHjSEfh8mTn3H@I+T}{AlByo6 z52+%Uc765!4dLE|U0z~#s9_Y$nPFit7HGB^fakV_F8Rc$B8L4v@%wmf=x#ss>~C-2AP8 zDVMn3!_g?EDPU$~Oo}J!>gu(uYX-*RE_r9baEGhfc+!G4&107*rxHx$XqL|}u=sXQ zv*BsfLs!RJ0>+Leeb~_Z)|@Z>Mm+mT`5147SO&%xOWvCs?p3Q5@=|JZU$c8_CZOeD z%zJb#40O5>e_ar+_o@N41+1C{%IY@3WOuGsdQFejYUgF`{sX#CZ4jfEHxK{-002ov JPDHLkV1fo6zP11W literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_02.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_02.png new file mode 100644 index 0000000000000000000000000000000000000000..4f889199567b68f40bb61cc0a992931a9330d49d GIT binary patch literal 953 zcmV;q14jIbP)Px&b4f%&RA@u(naxg9K@`UiK})2lz0m+kiL_0$8bNB<;6@<2!G)zyAbkSM697+O zc>>Cw1nS0(2CNHNSX)Aj6q4S8kWg*X8?+b-M01*4(%#RR+xyut%Xa3>{N{honKN_S z0N@|AU~9VsbC{}^iq#7?)^h{GeGH6sUk8t?9enPNi@&qwW5{yH@UeIVEBhR9)iX)0 zJ+3P-6}SbX-8Uh`Tx+nwot{Cq{1?#HV!i~~a)sJos1!q>nL%$2h_ofx63lHLK;h3x zZHTX{qh@2uf1A`q4RAhp2#I`&cnlF3E@ojQKm{aR!R+Qi?Wfs6FY)4p9fg~uWJnbZ zp;n*WZ*UdOE7M_Mp>hJ_AGR($K+dEhnBAaw2og9&Fg8478>NKGVBDc{a>+>+3Up(MSCj(3o&lUOgyww1nRjTzxyVtPDEg_U=O?*?x!|x<$&q*9>jBp4NDM##fR^} z>tL^y>!hB0K39ZTdRG~2`RP5F?DJ3?w{ig1kkR$LGT7?#2Tj$4RsgR3{0-ypzbk_! zMgs6EKwf!U0V13;xzE95YP8q$-lq{*7l=7t#2Pz^7<|KEFeAn#rrV~_)uCtKH z|DprK-gZ_^NiEqJjP-mw7Q@Sw+H~p4Xu8J&~jlxng}XLFLRYw`ieM zv!c|_nC+HYpfrK;ZfQo$(ZrNc1S(goAB@T^kKTolr<26xsr%rEzesAEC{aim*9^uR zGvZZiku5>&%O2pDO|7kIFq~M=L!9LBC4toi3@5_!3-57S&pJ#Jk<^apCQJfhh${-? z4%MT5<-+H)=;yrVcrqM}pCA_Og_%cQqVrDbd0MMV_2YDNMd4!9&O1!ynDt0230hdg zz?9U(1QFjVHkI|%Kn(}u4|I&Z{;m#~PVX9~k}0mJwxdS>Z;E0@LztEotpL%jR4P)Px&lu1NERA@u(TFp)qQ4~IezbJogL}~&8odm%|q{s#r@)OTjr{fcF%&R#hHC&g>shJpGg6=^cut(lopIjX53g z6KwKOe?u(|_-e>gQA(cjvcvb`V{LnnVyUk*`}sSq{n!3%VWPRzGCNRwIR9_nnG}P$%vGw_MDnrBb3CippFyk_T0o2U(4hncr+d638U|55L zPv0}aF@cTuG}CDNIo>!$c@OJu_(eiBwkoi&R8Nz=Qc(sg8ZkaBSfNO)P&>%x3|x#aovs;Bls4urdJ~_~4UwY+%@g zlefF<%p}ud`D3pLX(^k6F*l|mD;*WUCVHA_#NiUpqWHn`CXFtvt1~upvg6PO#;8jCGWV0h@{4I3S1 z^cGpB(=aWi#haau6B48#S^>Ey=6ry;4v=7WJhRuqxD@369J{GifRCmmS}(5x#rNHN1tBAgcy?@ z;|6A`?}FuOnc4qE=*?^0j2e=Atr>z^qB^mvrsR=yt??OROm>L#8`3h^?ViildU~K`WH@j9mKLKXNtXk>w4-9jN5YMB#3IG5A07*qo IM6N<$f_bsgXaE2J literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_04.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_04.png new file mode 100644 index 0000000000000000000000000000000000000000..547f8bd87e03efbae04b93381c38893dcff0da9a GIT binary patch literal 924 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 XJY1s*yX6N#00000NkvXXu0mjfu`kux literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_08.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_08.png new file mode 100644 index 0000000000000000000000000000000000000000..5a5e41c4734e14d4b50dad29c340095d170b9b06 GIT binary patch literal 1013 zcmVPx&uSrBfRA@upn$1oVQ545dBhZ8*X(IyB3hg9_MjKj53@${7Zg3%V;l_>S3E&NY zCjg%S+_(i@hzkuLE;L312u6{F)(;XfByA8#D3I#^HZz%-&KJ`ucJ56GNjr1q{_Z*F zf6m-n4-w_a;_z2hP+!nbx9V#tRO6+PuZsLtr`X-8oh)Szj%aRkn`VFiq1nxCQ>(BS z4OCNaFu?xH?Pan@l-kYGVtP-qnaLiS+7vJFSOEjXKx-oQKU-qC#=!b61ZeVRi(7dV^X`AUP7~`}c`zQrP^1GC;27A# z-K!M!S99Sp6z%ZSr94>f!F4X6B&mP$jyxfsH;1Ck(_kL!YN*Yj+2v`(ra$oshW5%6 z4ft{kJy&>g7%`7=n`2PL^!;|%cOCMO^FS4Ot7D6qJ&HYF$%BoxH?hqc9)_ax=xV5C z`x`ur`0F*A`jO6ijN9%Wp5h@K#V`bq^r9IJ_{i<`46T&7&8OJ&n7MPAy6R86GS#r_ z-2L)%;hqORakGe^+gMERYJ=g^i4K7t3hvtbkmr{4>Y_fBaGOHnga-v#%q?9oe1SuV z(e@@+5iW~}v;w7Qsmx}L-Qw{M z;lGBZRj6Zu;bNTZPj+5BaX~??iqEfE`Xz!T@zC-j1O+|iNvS2&FFya(P$;zKX(`9l zH=Y!nnWP(~k1a45M4dy zr$aGEuQeB)cMyq@j~g_$`l~3YW2>Uk(~8YIyCPw`^EmF(*$K_Z$t@au|J`;zIi`wc zuvSCU$t9S68-rG1-51oWwcW$dPxpjaxgp$ j!UFF#*LX|nB{|q%KdQNL85I$M00000NkvXXu0mjfge>8} literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_09.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_09.png new file mode 100644 index 0000000000000000000000000000000000000000..0bacfeaa7fd0d049b1a3ac92a70c475a633433ae GIT binary patch literal 970 zcmV;*12z1KP)Px&gh@m}RA@upn$J%YQ4q(62qm#%+JsOO5!xnNOf&tJ(93i}taA zxg7m8AMjA*lAD6AvrG!-E2s42?E$3@zfu19RPu~CUu?odu7Q4C^ChxJOyf1dBBO3v z43Cl5Imk3&^B@3189+iFU%yCtfaK=GTv~vtU;v5*E*JumQwXjabhBApYtg0MPqdK! zs5nd!Y~#*Vni(0=n%~mz*9v8dZfB`n{n?_2EZE9TKh61uEmfLz@kH*3qFY&QFzkW& z-#?xNE(zCc6p6*W=LRWvZ;~gbx~`%1cajt%0b8BEOo)O!3ew8#^Y?Yt>tINf8@DHT zWUA{t`{DzoieH8Q>tH+u45hcfyj!GLdS41wdKf0xK&?FDRgfp$Pt*Uw?BIr?F+_J1 zToK_NVcrfRhJFETb@~cLMqPH`5^6|PBLWx?)IA9Q$C^4vmKl7vBZ?09{Kq=rf9i-vQVbT=3dQWv4Dpb!{b`d zaPhq)kJ+~JfGKQQD*|jOJVx^-UEEmZvtrdDIkwor9c9mBpyau9tQ(uHCD~&lDvx`u*;=w-yzRA2>4ZY-J1uT3dlQTX z1YDAbI}jXEP|-Jw;@v%(5ok*EvY_h{|JTJ~2J7{t-I$E!UcPD@3EfKMHr8fex2%gO zh%;CDM{Acw)IqcHhy4aPv}Joi0EMe;xqa2BpC%Xv_X->39DP7@SEm(Bp{I*soQFJS(8vT@XWC|Wi4|np;zp*7`BpSB` zh6Qod!9|dn<(FJfSub4MU}gpt1PSaX6t?Y(DPUqyS-LT9_ zXk_216|<}$rbR`y1zD3hTo1i0u_100LU$3|?m}wTL)44EIWQE;S@bg96`L1rwjQjs sklrWcs7^}9!5a4-ey7+;D>c5TKlVDl5J^3-BLDyZ07*qoM6N<$f>BM(?*IS* literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_10.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_10.png new file mode 100644 index 0000000000000000000000000000000000000000..ae29f11428ac9270d7f60d84b1af45bcff9d7685 GIT binary patch literal 1020 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 A-v9sr literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_13.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_13.png new file mode 100644 index 0000000000000000000000000000000000000000..fd4dc907022392235cbbf43c707b5eae243e48e3 GIT binary patch literal 977 zcmV;?11|iDP)Px&i%CR5RA@u(nM+R-Q544y;T0`t8?hKc9!(UDG!(nhg#ytHE(8+y&`$tN zKLK@bLfPm>1Ly)aNFy3WlC~-sdBj!)5(-BBPn^kgI*&Wkna)h(O=dUu-21!#bI-Z= z+zKN4O=Z|B{)7Ef)mu|VBY`v2<3CLy-wE>8RFb#4in2$?l-|oxdOt@C+utd^k)`zB zp{g(RHlCs$e?5hK9?n*qrdAA{uO>UVlBa<6=UOk~R*#ueDIfchaz} zskN^(vHFFwxnorus$gw(wKRA8vfv_yXJc|lexcM{T@lQwQ2ZKc!O4Qb{Z{&~I!-A$ z7w>-hR@NWH1u+v;-545U^sD4Uk|t%EV7goZW4lGWeZleu83PK4!&+~;v_A&V%dg!D3u!M za{N_A$)gk#G&;EXNQJrzqN41P%FRhy^$-kNH(py%@@t<>sNcuNIvQy*-0G^}7+FeD zEV-i&hUl0Y2$8qC(iL!WYUQ03#T2L^PKH}t0Vb!GBA8qDnvze zC+D??Yg;t7{84ecXx8qX82;5byHh~+ z=obf-$Q)=cG7}iAph67g?1Iw+r5Y9GmIQD!w=R|3E%id_2D4+&vF<6U5X`P9?pUgT zVid}dVmu(ul&ESAHv2R;vXLL~&@i;H&ONjnX@(RN4>TTZ;vU`2Y+A{eWvrsXFbGO_ zxayb@G4Y6p$Gl>jDPU#<73`;>7ay2%6brOzU>FSh4z8*9DJs5^p~zy&@P3j5H5H5> z0InGgHf!cPQ6_663-f%$vkseVmvY6C7^RbLoGR4FLN!7DbCGohH zxT16gdG%WBYAsc%Px&mq|oHRA@u(T1`(AK^T4s0?~?Tlg65~F|Uc6v`0reM9 z{{j92%EfEtVmxRdTqH(9jU)=jwh~N4nzT{D@D=1)v!>n7?#}GA-7e`QT-cd+-sgSZ zubF8Z5gpM99BnON4r5iCu^v|!xjRoOu=CryRN6bRWCF;+=sDX(`QN)#+CQ``3vz^k z4f)Q|c+g8jzHU;LDMwP;KcGzU56xt^X#U49MM>6(dd^TR;33G1dQOwOE_Q>N@$BP9e`jRg z;a4B4CR71?6!Oyatxz*!(AA0Ml2yQ*#FmPb#aachsK=$mmJ^4TwF+R#h+iq5P8=xS z$>Tp}9hUZT-}+b)Ak?W--)6?JT?{~}FDo|mMwlUV$8b(0cHU)jk6r`x%^mnFp8 zx74unfLg@|{p9Xww@*V0JLk9eC^(y`SXtEsJF%_Owo^b@13X;r#B3N!6k7q`%h+S^U>wdznSiS(@(s#lQODK428(Uao z)+!@+}NSE8d;^Dt(RV_WR^74@0J-;1=Kq3kR-+yJ_|q1 zY5_|FQ)?aA8xMJT4a%H{<9+;1Rydwm!fFCc6^v)tN#&hd{Gj@HX`QB4ze^cLDl3}p z4A-0<2ytJPBkRQ%zi<^@v%TvIOoTnz1W}iC&tpBX$BMmL#!_9Px&V@X6oRA@u(T2D_CK@@)kC`#3A4G|KA{z*(@6sh)t2NOuV^r9uvGx!OhpTPPF zil4x8HxW)=G&Xv`gU~85iYEP|HnFD3HcHh3MtwsTySuahrn~Hp=}UTPXWq>3{ocIy z=1qG5;5Yn-($fXT8LM5!+6fbUeGm%_LM(6;g8m~Q^!JjVE6o-(cK0Ax+lGSJG~`%I zPh_4+5k(8O%I=d+Y_S%kkH?!yI{H5g4~yHaA&g$A!N0EPi&=FuC~URA*6BSR!|@gy^k->Oo93fPmY zXPLvXTgITVCIcq;dO^GqcWZwgtsA(%0gau#106D8$*}-DxN@eW1>BlE`|Lfed=%-x zFlS+y=TVfQU&h!{d>j^{BRt}QY_U$tElFg+vQrV5iwt#vdC3C0jPdM>ST|z*NOeUX zle1RcC_7`ZfFJUSb6)Z=(|b|YjH=2*ycs{Z>YLW;^1yO)2g0ib*)CMTc+6$Wz<~%= zz_6;v>YgVFuf7EAv9t^I+QL&lqp?M048P=wH5yx*!0-ni&f49r8Z55wcfXXP+4I0F zOg=FIA-~U)#|orh5010ymkn0!laBYgxk$aAwYw>2R+{ zGd6v&_b9!KIpv=CPL_I6APx&aY;l$RA@u(noCa;Q544ykw*kIt)h^Cgf?lYiNum_aG^qUHVGmx#!#m zZAA2!TCla9fcZ?-6UFod8}8|%;WJ${+|wz2UfbCtaqo~y!j2_#zV35GY>S#^xsP_|Nc(%N?2o>60hVf`%Jjyj% zi;pDk9q9Va5G->&Oo>ph+s<~?Ug6s>ntb`mJQxy1W<2cbB)l?~Tq^4(6kWwCQ`eeq zU9qxdDF06LSp#>ze+Gud@&5_i9L^13GQIP%EP}7u~@0I~mCy@UG3>#D=4?i|$D7I|! zfKqSoUZq%|+gGBM#9bPD{()V`((xgh9_jZL7!IG@0`13?Z)!^gsTS^BaeQJvF3E9$ z6v~(Qn_%?tlWNJO3T4aR&4KwvH6yh!f5Q{BA5>GJydb(DZ+fYYm4dT?CD zMaqna8Y)8GdhAxmMx z>pWB3p!Dh%uN(8bV=!2EYu(vhPp*fe(jcxC9*+*#KBPJgJvE#wiYblOpL7RJXHBGX z)F-QN%)B^t9ZU{QsP{0;eqRGjapZD<+~?} zsV9KUIUVhn{*PmJWsA})RZmn>{_e4W$>E8=c8aYPrR2WH24-h+PR5*oIq_a2#Px&Ye_^wRA@u(nn6z!K@`Uy0ZJ4#TP3y$6-qCKM6{(Byg~G$mzGZ;e1g_bK=}kM zpMY}r(u-U)AQ!zfRI3p%X{)gb*d}e%Vk{8#E!kRjXLo0I+wLrO5>B0&eZTp?_h#k| zeE{$qE@12Hf!R#eo?>c(3622}2K$>o7wf+aY3m&xYL2TNpF*v1VrU*|5VK+kvgo@3 zVb664I4^-PIG`{fTRnoUuis%kUx943PBd`Nbq&HECqz5~v_eUpYsV*$t^S1dd|8~U z_=9c1sKF2@5gHQ>A;G9E?-^hjQu&J5WzjbR(MdN1gv(5dqzV;S$(5)9slcLs7sT(3 zG6Bi0M#E5!j}0LyRdcmjc6kg%zI@BHt$aovlUOI7<0jm_r$G%2*$Gu$`=-64c$`Sh+u{A zUGCLt?stt-a6ZlGgW<-BZfK`QiZz8|$2#4?}G*{lHDd@yBd6SZPR z(qC#2+1}R%+j(@G`M6^RjQm70k$$5MW~am;{e4c8arNy#W*Htp1S-d*HhKBhl3kA-O$&qE8+~8C3hZ9gLl}WJ7Fg~Xk|h9 zcd5W|5LR(fIji7Upr~T3btSBVV})V{liU&usS%H}lU~=H8y__mUVa38ePLU7?_k;a9fa9y)c%RUgg`aQd_ek&FV&OIUzA~ zR{1)699LfDY35<+(^19bhTy+Zu$~}TV7jiDQRB>v>#AaA3}qeL17lq=tNZ@}yRvx@ Tpf`Q600000NkvXXu0mjfgygjU literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_18.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_18.png new file mode 100644 index 0000000000000000000000000000000000000000..3e54c9e697b146aa3473c761c56f1e3104f3e8b6 GIT binary patch literal 956 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 literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_21.png b/tools/image_converter_tool/test/hert/heart_chart/hearticon/HEARTICON_21.png new file mode 100644 index 0000000000000000000000000000000000000000..3af8325e97006d7a5710d9c7ad70395d6c824131 GIT binary patch literal 935 zcmV;Y16cftP)Px&VM#fHo;^PmB_*h@qGkqALcRY*XIZ4@woMDsS84I#Uo+3D_fTl;QJ=gphXym@cl zylnyS7Y!&aO|UxiYSUwN<}gTk%+t|^={^r8d%6+zcfr%q3Qv2R!k#akpm=spu?;Ikvd4PQBSQ#4icVm7ufM`z_PgVK9czlX<;Sh`O_Jqc>LBe3PpylzPy0eC? z07!1_D=LX_uTfPMaAy6Zx~b+W@ivF3f669=n@W5{Uq zj-%#LOoaVdiVQf~TWoQUb6?cU|MG%0!4^gXO4(BnLZ#M%M!BU4mL3l&1!_HrUIO{Q zz#8@_#zHjSEfh8mTn3H@I+T}{AlByo6 z52+%Uc765!4dLE|U0z~#s9_Y$nPFit7HGB^fakV_F8Rc$B8L4v@%wmf=x#ss>~C-2AP8 zDVMn3!_g?EDPU$~Oo}J!>gu(uYX-*RE_r9baEGhfc+!G4&107*rxHx$XqL|}u=sXQ zv*BsfLs!RJ0>+Leeb~_Z)|@Z>Mm+mT`5147SO&%xOWvCs?p3Q5@=|JZU$c8_CZOeD z%zJb#40O5>e_ar+_o@N41+1C{%IY@3WOuGsdQFejYUgF`{sX#CZ4jfEHxK{-002ov JPDHLkV1fo6zP11W literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heart_chart/heartrate.gif b/tools/image_converter_tool/test/hert/heart_chart/heartrate.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ac8da6c59c86625762123b6c65bca78cf461ab7 GIT binary patch literal 10619 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 btBkL@GIlTH3j_bNgYp0G*nM=zZt?#CX4GRv literal 0 HcmV?d00001 diff --git a/tools/image_converter_tool/test/hert/heartchart/topicon.png b/tools/image_converter_tool/test/hert/heart_chart/topicon.png similarity index 100% rename from tools/image_converter_tool/test/hert/heartchart/topicon.png rename to tools/image_converter_tool/test/hert/heart_chart/topicon.png diff --git a/tools/image_converter_tool/test/hert/heartchart/background.png b/tools/image_converter_tool/test/hert/heartchart/background.png deleted file mode 100644 index 4252e114b7223b8b64c3ad6174c5abfec439b7fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5841 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 n(Ww&&(zKaBkpEDu?