From f3516116a564b0e72c98e46bacbcfa2c7a5df3b8 Mon Sep 17 00:00:00 2001 From: Caisking Date: Fri, 18 Apr 2025 11:54:43 +0800 Subject: [PATCH] =?utf8?q?=E3=80=90=E5=81=A5=E5=BA=B7=E6=9C=8D=E5=8A=A1?= =?utf8?q?=E3=80=91UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../nativeui/heart_blood/BloodCardView.cpp | 236 ++++++ .../nativeui/heart_blood/BloodCardView.h | 79 ++ .../heart_blood/CheckAbnormalPresenter.cpp | 127 ++++ .../heart_blood/CheckAbnormalPresenter.h | 44 ++ .../heart_blood/CheckAbnormalView.cpp | 176 +++++ .../nativeui/heart_blood/CheckAbnormalView.h | 70 ++ .../heart_blood/CheckInvalidPresenter.cpp | 100 +++ .../heart_blood/CheckInvalidPresenter.h | 43 ++ .../nativeui/heart_blood/CheckInvalidView.cpp | 227 ++++++ .../nativeui/heart_blood/CheckInvalidView.h | 82 +++ .../health_service/defult_health.json | 12 + .../health_service/health_service.cpp | 692 ++++++++++++++++++ .../health_service/health_service.h | 131 ++++ .../heart_blood/set_heart/SetHeartModel.cpp | 0 .../heart_blood/set_heart/SetHeartModel.h | 0 .../set_heart/SetHeartPresenter.cpp | 0 .../heart_blood/set_heart/SetHeartPresenter.h | 0 .../heart_blood/set_heart/SetHeartView.cpp | 0 .../heart_blood/set_heart/SetHeartView.h | 0 19 files changed, 2019 insertions(+) create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/defult_health.json create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartModel.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartModel.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartPresenter.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartPresenter.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartView.h diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.cpp new file mode 100644 index 000000000..12aee59c7 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.cpp @@ -0,0 +1,236 @@ + +#include "heart_blood/BloodCardView.h" +#include "common/image_cache_manager.h" +#include "UiConfig.h" +#include "ui_resource_image.h" +#include +#include "components/ui_button.h" +#include "MainViewSample.h" +#include "components/ui_view_group.h" +#include "DialModelSPO2.h" +#include "DialModelHeartRate.h" + +#include "UiConfig.h" +#include "uicomponents/UIComponents.h" +#include "MainPresenterSample.h" + +#include "bloodoxygen/include/BloodResultPresenter.h" +#include "bloodoxygen/include/BloodOxygenModel.h" +namespace OHOS +{ + static BloodCardView *g_pBloodCardView{nullptr}; + + BloodCardView::BloodCardView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BloodCardView::BloodCardView"); + SetPosition(0, 0, HORIZONTAL_RESOLUTION, VERTICAL_RESOLUTION); + g_pBloodCardView = this; + } + + BloodCardView::~BloodCardView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BloodCardView::~BloodCardView"); + DeInit(); + g_pBloodCardView = nullptr; + } + + BloodCardView *BloodCardView::GetInstance() + { + return g_pBloodCardView; + } + + /* -------------------------------------------------------------------------- */ + void BloodCardView::UpSPO2Text() + { + if (bloodLabel == nullptr || timeLabel == nullptr) + return; + + // 更新血氧数据 + uint16_t spo2 = BloodOxygenModel::GetInstance()->GetSPO2data(); + if (spo2 != 0) // 判断是否为默认数据 + { + // 更新数据 + std::string bloodoxygenStr = std::to_string(spo2) + "%"; + bloodLabel->SetText(bloodoxygenStr.c_str()); + + // 获取时间差 + uint32_t time = BloodResultPresenter::GetInstance()->GetCurrentTime(); + uint32_t check_time = BloodOxygenModel::GetInstance()->GetCheckTime(); + int time_diff = BloodResultPresenter::GetInstance()->GetTDOA(time, check_time); + + if (time_diff == 0) + { + timeLabel->SetTextId(STR_CHECKNEW); + } + else if (time_diff <= 60) + { + UpdateLabel(timeLabel, time_diff, STR_CHECKTIME); + } + else + { + timeLabel->SetTextId(STR_CHECKLONG); + } + } + else + { + bloodLabel->SetText("--"); + timeLabel->SetTextId(STR_CHECKNO); + } + } + + /* -------------------------------------------------------------------------- */ + /*** + * @description: + * @return 添加按键是否成功 + */ + bool BloodCardView::AddButton() + { + InitButtonExt(checkButton, 118, 336, 230, 80, MAIN_CLICK_BLOOD, STR_CHECK, 30); + checkButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xffFF5A36); // 设置按键颜色 + // 设置按键监听 + UIView::OnClickListener *clickListener = (UIView::OnClickListener *)OHOS::MainPresenterSample::GetInstance(); + checkButton->SetOnClickListener(clickListener); + + Add(checkButton); + return true; + } + /*** + * @description: + * @return 初始化标签是否成功 + */ + bool BloodCardView::InitLable() + { + /*初始化title*/ + InitRollLabel(titleLabel, 83, 50, 300, 35, "title", STR_BLOOD, DEFAULT_VECTOR_FONT_FILENAME, 30); + /*初始化血氧值label*/ + InitUILabel(bloodLabel, 83, 22, 300, 300, "bloodtext", "--", DEFAULT_VECTOR_FONT_FILENAME, 120); + /*初始化检测时间*/ + InitRollLabel(timeLabel, 53, 260, 360, 35, "time", STR_CHECKNO, DEFAULT_VECTOR_FONT_FILENAME, 30); + // 设置来回滚动属性 + timeLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + timeLabel->SetRollSpeed(23); + + UpSPO2Text(); + + Add(titleLabel); + Add(bloodLabel); + Add(timeLabel); + + return true; + } + /*** + * @description: + * @return 初始化背景是否成功 + */ + bool BloodCardView::Initbackground() + { + + background = new UIImageView(); + + background->SetPosition(0, 0); // widget's left position and top position + background->Resize(466, 466); // widget's width and height + background->SetViewId("image1"); // Set style + + Add(background); + return true; + } + /*** + * @description: + * @return 是否初始化成功 + */ + bool BloodCardView::InitView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "bool BloodCardView::InitView()"); + if (!Initbackground()) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Initbackground error!\n"); + }; + if (!InitLable()) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "InitLable error!\n"); + }; + if (!AddButton()) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AddButton error!\n"); + }; + // SetCoverable(true); + return true; + } + /*** + * @description: + * @return 删除组件 + */ + void BloodCardView::DeInit() + { + UnLoadBloodImageRes(); + RemoveAll(); + if (background != nullptr) + { + delete background; + background = nullptr; + } + if (bloodLabel != nullptr) + { + delete bloodLabel; + bloodLabel = nullptr; + } + if (timeLabel != nullptr) + { + delete timeLabel; + timeLabel = nullptr; + } + if (titleLabel != nullptr) + { + delete titleLabel; + titleLabel = nullptr; + } + } + /* -------------------------------------------------------------------------- */ + /*预加载血氧图片资源*/ + void BloodCardView::PreLoadBloodImageRes(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::PreLoadBloodImageRes"); + if (!resLoadStatus) + { + ImageInfo *image = ImageCacheManager::GetInstance().LoadOneInMultiRes(BLOODOXYGEN_BACKGOUND, BLOOD_IAMGES); + if (image == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingView::LoadTrainingImage fail"); + return; + } + background->SetSrc(image); + resLoadStatus = true; + } + } + + /*卸载血氧图片资源*/ + void BloodCardView::UnLoadBloodImageRes(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::UnLoadBloodImageRes"); + if (resLoadStatus) + { + ImageInfo *img = nullptr; + background->SetSrc(img); + ImageCacheManager::GetInstance().UnloadOneInMultiRes(BLOODOXYGEN_BACKGOUND, BLOOD_IAMGES); + resLoadStatus = false; + } + } + + void BloodCardView::PreLoad(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::PreLoad"); + if (!viewiInitStatus) + { + InitView(); + viewiInitStatus = true; + } + PreLoadBloodImageRes(); + } + + void BloodCardView::UnLoad(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::UnLoad"); + UnLoadBloodImageRes(); + } + /* -------------------------------------------------------------------------- */ +} diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.h new file mode 100644 index 000000000..d0c6f34d8 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/BloodCardView.h @@ -0,0 +1,79 @@ +/*** + * @Date: 2024-06-28 16:08:09 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-29 11:48:50 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/BloodCardView.h + */ +/*** + * @Date: 2024-06-26 16:13:19 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-06-26 16:52:01 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/BloodCardView.h + */ + +#ifndef _Blood_CARD_VIEW_H +#define _Blood_CARD_VIEW_H + + +#include "View.h" +#include +#include "components/ui_view_group.h" +#include "components/ui_label.h" +#include "components/ui_label_ext.h" +#include "components/ui_image_view.h" +#include "components/ui_button.h" +#include "components/ui_image_animator.h" +#include "components/ui_label_button_ext.h" +#include "components/ui_card_page.h" +#include "components/ui_label_button_ext.h" + +namespace OHOS +{ + +#define CHECK "buttoncheck" + + class BloodCardView : public UICardPage + { + + public: + BloodCardView(); + virtual ~BloodCardView(); + static BloodCardView *GetInstance(void); + + bool InitView(); + void DeInit(); + + bool AddButton(); + bool InitLable(); + bool Initbackground(); + + void PreLoad(void) override; + void UnLoad(void) override; + + void UpSPO2Text(); + + private: + void PreLoadBloodImageRes(void); + void UnLoadBloodImageRes(void); + + private: + UIView::OnDragListener *draglistener{nullptr}; + BloodCardView(BloodCardView &&) = delete; + BloodCardView &operator=(BloodCardView &&) = delete; + + UIImageView *background = nullptr; + UIButton *warnButton = nullptr; + UILabelButton *monitorButton = nullptr; + UILabelExt *titleLabel = nullptr; + UILabelExt *timeLabel = nullptr; + UILabel *bloodLabel = nullptr; + + UILabelButtonExt *checkButton{nullptr}; + + bool viewiInitStatus{false}; + bool resLoadStatus{false}; + + int bloodoxygen; + }; +} // namespace OHOS +#endif // Blood_PRESENTER_H diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.cpp new file mode 100644 index 000000000..13462f477 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.cpp @@ -0,0 +1,127 @@ +/*** + * @Date: 2024-07-30 11:22:00 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-08-16 15:59:09 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/CheckAbnormalPresenter.cpp + */ +/* + * Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved. + * Description: bloodOxygen view + * Author: + * Create: 2021-08-01 + */ + +#include "heart_blood/CheckAbnormalPresenter.h" +#include "common/task_manager.h" +#include "BloodOxygenModel.h" + +#include "bloodoxygen/include/BloodDetectionView.h" +#include "heart_blood/CheckAbnormalView.h" + +#include "components/ui_label.h" +#include "components/ui_label_ext.h" + +#include "ChangeSliceListener.h" +#include "broadcast_service.h" +#include +#include "iostream" +#include +#include +#include +#include +#include "wearable_log.h" +#include "cmsis_os.h" +#include "securec.h" +#include "broadcast_service.h" +#include "graphic_service.h" +#include +#include +#include + +#ifdef PPG_HX3695 +#include "ppg_service.h" +#endif + +// #include "displaybrightness/include/DisplayBrightnessModel.h" +#include "power_display_service.h" +#include "custom_utils.h" + +#ifdef ENABLE_CYWEE +#include "cywee_service.h" +#endif + +#include "MainModel.h" +#include "heart_blood/health_service/health_service.h" + +// #include "battery_hal.h" + +#include "NativeRegisterManager.h" + +namespace OHOS +{ + + REGIST_SLICE(VIEW_CODED_LOCK, CheckAbnormalView, CheckAbnormalPresenter); + + + static CheckAbnormalPresenter *g_pCheckAbnormalPresenter; + + CheckAbnormalPresenter::CheckAbnormalPresenter() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CheckAbnormalPresenter::new CheckAbnormalPresenter"); + g_pCheckAbnormalPresenter = this; + } + CheckAbnormalPresenter::~CheckAbnormalPresenter() + { + g_pCheckAbnormalPresenter = nullptr; + } + CheckAbnormalPresenter *CheckAbnormalPresenter::GetInstance() + { + return g_pCheckAbnormalPresenter; + } + void CheckAbnormalPresenter::OnStart() + { + Presenter::OnStart(); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CheckAbnormalPresenter::On Start "); + } + void CheckAbnormalPresenter::OnPause(void) {} + + void CheckAbnormalPresenter::OnResume(void) {} + + void CheckAbnormalPresenter::OnStop(void) {} + + bool CheckAbnormalPresenter::OnClick(UIView &view, const ClickEvent &event) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodPresenter::OnClick"); + + if (strcmp(view.GetViewId(), CLICK_BLOOD_STOP) == 0) + { + NativeAbility::GetInstance().Back(); + } + if (strcmp(view.GetViewId(), CLICK_BLOOD_RE) == 0) + { + // 检测过程中充电 失败可以弹窗 + // bool isCharging = get_charge_stat(); // 获取充电状态 + bool isCharging = false; + + if (isCharging) + { + HealthState highHealthState; + highHealthState.checkType = CHARGE; + HealthService::GetInstance()->SetHealthCurrent(highHealthState); + NativeAbility::GetInstance().ChangeSlice(VIEW_CHECK_INVALID); + return true; + } + // 回到上一个检测界面 + uint16 preSlice = NativeAbility::GetInstance().GetPreSliceId(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "preSlice %d", preSlice); + + if (preSlice == VIEW_MAIN) { + MainModel::GetInstance().SetFromSetCardView(true); + MainModel::GetInstance().SetFromCardId(HEART_RATE); + } + NativeAbility::GetInstance().ChangeSlice(preSlice); + } + return true; + } + +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.h new file mode 100644 index 000000000..a420c9bc6 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalPresenter.h @@ -0,0 +1,44 @@ +/*** + * @Date: 2024-07-30 11:22:09 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 16:39:17 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/CheckAbnormalPresenter.h + */ + +#ifndef CHECK_ABNORMAL_PRESENTER_H +#define CHECK_ABNORMAL_PRESENTER_H + +#include "Presenter.h" +#include "ModelListenerSample.h" +#include "components/ui_circle_progress.h" +#include "ohos_types.h" +#include "KeyInputListener.h" +#include "common/key_code.h" +#include "heart_blood/CheckAbnormalView.h" + +namespace OHOS +{ + static constexpr const char *CLICK_BLOOD_STOP = "clickbloodstop"; // 血氧检测暂停 + static constexpr const char *CLICK_BLOOD_RE = "clickbloodre"; // 血氧检测重新 + + class CheckAbnormalView; + class CheckAbnormalPresenter : public Presenter, + public UIView::OnClickListener, + + public UIView::OnDragListener + { + public: + CheckAbnormalPresenter(); + virtual ~CheckAbnormalPresenter(); + static CheckAbnormalPresenter *GetInstance(void); + + void OnStart() override; + void OnPause() override; + void OnResume() override; + void OnStop() override; + + bool OnClick(UIView &view, const ClickEvent &event) override; + }; +} + +#endif diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.cpp new file mode 100644 index 000000000..0a59025ba --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.cpp @@ -0,0 +1,176 @@ +/*** + * @Date: 2024-04-15 10:55:58 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 16:39:56 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/bloodoxygen/src/CheckAbnormalView.cpp + */ + +#include "common/image_cache_manager.h" +#include "ui_resource_image.h" +#include +#include "components/ui_button.h" +#include "MainViewSample.h" +#include "components/ui_view_group.h" +#include "DialModelSPO2.h" +#include "DialModelHeartRate.h" +#include "BloodOxygenModel.h" + +#include "UiConfig.h" +#include "uicomponents/UIComponents.h" +#include "MainPresenterSample.h" + +#include "heart_blood/CheckAbnormalPresenter.h" +#include "heart_blood/CheckAbnormalView.h" + +#include "vibrator_service.h" +#include "custom_runtime.h" + +namespace OHOS +{ + static CheckAbnormalView *g_pCheckAbnormalView{nullptr}; + static const char *BLOOD_PATH_NOTE = "/user/res/Blood/Error.bin"; + + CheckAbnormalView::CheckAbnormalView() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckAbnormalView::CheckAbnormalView"); + g_pCheckAbnormalView = this; + } + + CheckAbnormalView::~CheckAbnormalView() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckAbnormalView::~CheckAbnormalView"); + DeInit(); + g_pCheckAbnormalView = nullptr; + } + + CheckAbnormalView *CheckAbnormalView::GetInstance() + { + return g_pCheckAbnormalView; + } + + /* -------------------------------------------------------------------------- */ + /*** + * @description: + * @return 添加按键是否成功 + */ + bool CheckAbnormalView::AddButton() + { + InitButtonExt(StButton, 58, 320, 170, 90, CLICK_BLOOD_STOP, STR_STOP, 30); + StButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); // 设置按键颜色 + StButton->SetOnClickListener(presenter_); + + InitButtonExt(ReButton, 238, 320, 170, 90, CLICK_BLOOD_RE, STR_RECHECK, 30); + ReButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xffFF8A36); // 设置按键颜色 + ReButton->SetOnClickListener(presenter_); + + AddViewToRootContainer(StButton); + AddViewToRootContainer(ReButton); + return true; + } + /*** + * @description: + * @return 初始化标签是否成功 + */ + bool CheckAbnormalView::InitLable() + { + /*初始化title*/ + InitRollLabel(titleLabel, 83, 50, 300, 35, "title", STR_CHECKERROR, DEFAULT_VECTOR_FONT_FILENAME, 30); + + InitLabelExt(noteLabel, 53, 230, 360, 70, "time", STR_PWUWC, DEFAULT_VECTOR_FONT_FILENAME, 30); + // 设置来回滚动属性 + noteLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + noteLabel->SetRollSpeed(23); + + AddViewToRootContainer(titleLabel); + AddViewToRootContainer(noteLabel); + return true; + } + /*** + * @description: + * @return 初始化背景是否成功 + */ + bool CheckAbnormalView::Initbackground() + { + + noteimage = new UIImageView(); + noteimage->SetPosition(193, 120, 80, 80); + noteimage->SetSrc(BLOOD_PATH_NOTE); + + AddViewToRootContainer(noteimage); + return true; + } + /*** + * @description: + * @return 是否初始化成功 + */ + bool CheckAbnormalView::CheckAbnormalViewInit() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "bool CheckAbnormalView::InitView()"); + if (!Initbackground()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Initbackground error!"); + }; + if (!InitLable()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "InitLable error!"); + }; + if (!AddButton()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AddButton error!"); + }; + return true; + } + /*** + * @description: + * @return 删除组件 + */ + void CheckAbnormalView::DeInit() + { + if (StButton != nullptr) + { + delete StButton; + StButton = nullptr; + } + if (ReButton != nullptr) + { + delete ReButton; + ReButton = nullptr; + } + if (noteLabel != nullptr) + { + delete noteLabel; + noteLabel = nullptr; + } + if (titleLabel != nullptr) + { + delete titleLabel; + titleLabel = nullptr; + } + if (noteimage != nullptr) + { + delete noteimage; + noteimage = nullptr; + } + } + + void CheckAbnormalView::OnStart() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckAbnormalView::OnStart"); + + if (!CheckAbnormalViewInit()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckAbnormalView::InitBloodView fail"); + } + + if(true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb() && (!uapi_sleep_mode_flag_get())) + { + ui_api_vibrate_once_func(); + } + + + GetRootContainer()->SetDraggable(true); + GetRootContainer()->SetTouchable(true); + GetRootContainer()->SetOnDragListener(presenter_); + // GetRootContainer()->SetOnKeyActListener(presenter_); + } +} diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.h new file mode 100644 index 000000000..7f6246df9 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckAbnormalView.h @@ -0,0 +1,70 @@ +/*** + * @Date: 2024-04-15 10:55:58 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 11:46:23 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/bloodoxygen/include/CheckAbnormalView.h + */ +/*** + * @Date: 2024-04-15 10:55:58 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-05-07 18:51:13 + * @FilePath: /XTS_FD230/FD230/code/sdk/application/wearable/fd230app/nativeui/bloodoxygen/include/CheckAbnormalView.h + */ +/* + * Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved. + * Description: bloodResult view + * Author: + * Create: 2021-08-01 + */ + +#ifndef CHECK_ABNORMAL_VIEW_H +#define CHECK_ABNORMAL_VIEW_H + +#include "View.h" + +#include "wearable_log.h" +#include "UiConfig.h" +#include "components/ui_label.h" +#include "components/ui_label_ext.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_view_group.h" +#include "heart_blood/CheckAbnormalPresenter.h" + +#include "components/ui_scroll_view.h" +#include "components/ui_label_button_ext.h" +namespace OHOS +{ + class CheckAbnormalPresenter; + class CheckAbnormalView : public View + { + public: + CheckAbnormalView(); + virtual ~CheckAbnormalView(); + static CheckAbnormalView *GetInstance(void); + + + void OnStart() override; + + bool CheckAbnormalViewInit(); + + void DeInit(); + bool AddButton(); + bool InitLable(); + bool Initbackground(); + + private: + // 提醒图标 + UIImageView *noteimage = nullptr; + // 按键 + UILabelButtonExt *StButton = nullptr; + UILabelButtonExt *ReButton = nullptr; + // 提醒label + UILabelExt *titleLabel = nullptr; + UILabelExt *noteLabel = nullptr; + }; +} + +#endif // 血氧主界面 \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.cpp new file mode 100644 index 000000000..f13bf69ff --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.cpp @@ -0,0 +1,100 @@ +/*** + * @Date: 2024-07-30 11:22:44 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-31 15:22:17 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/CheckInvalidPresenter.cpp + */ +/* + * Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved. + * Description: bloodOxygen view + * Author: + * Create: 2021-08-01 + */ + +#include "heart_blood/CheckInvalidPresenter.h" +#include "common/task_manager.h" +#include "BloodOxygenModel.h" + +#include "bloodoxygen/include/BloodDetectionView.h" +#include "heart_blood/CheckInvalidView.h" + +#include "components/ui_label.h" +#include "components/ui_label_ext.h" + +#include "ChangeSliceListener.h" +#include "broadcast_service.h" +#include +#include "iostream" +#include +#include +#include +#include +#include "wearable_log.h" +#include "cmsis_os.h" +#include "securec.h" +#include "broadcast_service.h" +#include "graphic_service.h" +#include +#include +#include + +#ifdef PPG_HX3695 +#include "ppg_service.h" +#endif + +// #include "displaybrightness/include/DisplayBrightnessModel.h" +#include "power_display_service.h" +#include "custom_utils.h" + +#ifdef ENABLE_CYWEE +#include "cywee_service.h" +#endif + +#include "MainModel.h" + +#include "NativeRegisterManager.h" + +namespace OHOS +{ + + REGIST_SLICE(VIEW_CHECK_INVALID, CheckInvalidView, CheckInvalidPresenter); + + + static CheckInvalidPresenter *g_pCheckInvalidPresenter; + + CheckInvalidPresenter::CheckInvalidPresenter() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CheckInvalidPresenter::new CheckInvalidPresenter"); + g_pCheckInvalidPresenter = this; + } + CheckInvalidPresenter::~CheckInvalidPresenter() + { + g_pCheckInvalidPresenter = nullptr; + } + CheckInvalidPresenter *CheckInvalidPresenter::GetInstance() + { + return g_pCheckInvalidPresenter; + } + void CheckInvalidPresenter::OnStart() + { + Presenter::OnStart(); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CheckInvalidPresenter::On Start "); + } + void CheckInvalidPresenter::OnPause(void) {} + + void CheckInvalidPresenter::OnResume(void) {} + + void CheckInvalidPresenter::OnStop(void) {} + + bool CheckInvalidPresenter::OnClick(UIView &view, const ClickEvent &event) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodPresenter::OnClick"); + + if (strcmp(view.GetViewId(), CLICK_HEALTH_KONW) == 0) + { + NativeAbility::GetInstance().Back(); + } + return true; + } + +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.h new file mode 100644 index 000000000..ef24ac107 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidPresenter.h @@ -0,0 +1,43 @@ +/*** + * @Date: 2024-07-30 11:22:09 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 16:39:17 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/CheckInvalidPresenter.h + */ + +#ifndef CHECK_Invalid_PRESENTER_H +#define CHECK_Invalid_PRESENTER_H + +#include "Presenter.h" +#include "ModelListenerSample.h" +#include "components/ui_circle_progress.h" +#include "ohos_types.h" +#include "KeyInputListener.h" +#include "common/key_code.h" +#include "heart_blood/CheckInvalidView.h" + +namespace OHOS +{ + static constexpr const char *CLICK_HEALTH_KONW = "clickbloodkown"; // 检测重新 + + class CheckInvalidView; + class CheckInvalidPresenter : public Presenter, + public UIView::OnClickListener, + + public UIView::OnDragListener + { + public: + CheckInvalidPresenter(); + virtual ~CheckInvalidPresenter(); + static CheckInvalidPresenter *GetInstance(void); + + void OnStart() override; + void OnPause() override; + void OnResume() override; + void OnStop() override; + + bool OnClick(UIView &view, const ClickEvent &event) override; + }; +} + +#endif diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.cpp new file mode 100644 index 000000000..a0a99d23c --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.cpp @@ -0,0 +1,227 @@ +/*** + * @Date: 2024-07-30 11:20:16 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-31 15:16:05 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/CheckInvalidView.cpp + */ +/*** + * @Date: 2024-04-15 10:55:58 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 16:39:56 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/bloodoxygen/src/CheckInvalidView.cpp + */ + +#include "common/image_cache_manager.h" +#include "ui_resource_image.h" +#include +#include "components/ui_button.h" +#include "MainViewSample.h" +#include "components/ui_view_group.h" +#include "DialModelSPO2.h" +#include "DialModelHeartRate.h" +#include "BloodOxygenModel.h" + +#include "UiConfig.h" +#include "uicomponents/UIComponents.h" +#include "MainPresenterSample.h" + +#include "heart_blood/CheckInvalidPresenter.h" +#include "heart_blood/CheckInvalidView.h" + +#include "heart_blood/health_service/health_service.h" + +#include "vibrator_service.h" +#include "custom_runtime.h" + +namespace OHOS +{ + static CheckInvalidView *g_pCheckInvalidView{nullptr}; + static const char *BLOOD_PATH_NOTE = "/user/res/Blood/Error.bin"; + + CheckInvalidView::CheckInvalidView() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckInvalidView::CheckInvalidView"); + g_pCheckInvalidView = this; + } + + CheckInvalidView::~CheckInvalidView() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckInvalidView::~CheckInvalidView"); + DeInit(); + g_pCheckInvalidView = nullptr; + } + + CheckInvalidView *CheckInvalidView::GetInstance() + { + return g_pCheckInvalidView; + } + + void CheckInvalidView::SetViewData() + { + HealthState healthState = HealthService::GetInstance()->GetHealthCurrent(); + + // 判断类型 + if (healthState.checkType == BLOOD_CHECK) + { + titleLabel->SetTextId(STR_CHECKEWARN); + + if (healthState.resultStatus == LOW) + { + SetNoteLabel(STR_BLOODSHORT, healthState.checkResult); + } + } + else if (healthState.checkType == HEART_CHECK) + { + titleLabel->SetTextId(STR_HEARTTITLE); + // 处理心率状态 + switch (healthState.resultStatus) + { + case HIGH: + SetNoteLabel(STR_HEARTMAX, healthState.checkResult); + break; + case LOW: + SetNoteLabel(STR_HEARTMIN, healthState.checkResult); + break; + default: + SetNoteLabel(STR_HEARTMAX, healthState.checkResult); + break; + } + } + else if (healthState.checkType == CHARGE) + { + titleLabel->SetTextId(STR_CHARGE); + noteLabel->SetTextId(STR_CHARGE_NOTE); + remindLabel->SetVisible(false); + } + } + + void CheckInvalidView::SetNoteLabel(UIResourceTextId viewId, int checkResult) + { + noteLabel->SetTextId(viewId); + UpdateLabel(noteLabel, checkResult, viewId); + } + /* -------------------------------------------------------------------------- */ + /*** + * @description: + * @return 添加按键是否成功 + */ + bool CheckInvalidView::AddButton() + { + /*初始化按键*/ + InitButtonExt(kownButton, 0, 366, 466, 100, CLICK_HEALTH_KONW, STR_KONW, 30); + kownButton->SetImageSrc(PNG_466x100BUTTON_IMAGE, PNG_466x100BUTTON_IMAGE); + kownButton->SetOnClickListener(presenter_); + + AddViewToRootContainer(kownButton); + return true; + } + /*** + * @description: + * @return 初始化标签是否成功 + */ + bool CheckInvalidView::InitLable() + { + /*初始化title*/ + InitRollLabel(titleLabel, 83, 50, 300, 35, "title", STR_CHECKEWARN, DEFAULT_VECTOR_FONT_FILENAME, 30); + InitRollLabel(remindLabel, 53, 270, 360, 70, "remindLabel", STR_HEARTNOTE, DEFAULT_VECTOR_FONT_FILENAME, 30); + // 设置来回滚动属性 + InitLabelExt(noteLabel, 53, 230, 360, 70, "time", STR_HEARTNOTE, DEFAULT_VECTOR_FONT_FILENAME, 30); + noteLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + noteLabel->SetRollSpeed(23); + + AddViewToRootContainer(titleLabel); + AddViewToRootContainer(remindLabel); + AddViewToRootContainer(noteLabel); + return true; + } + /*** + * @description: + * @return 初始化背景是否成功 + */ + bool CheckInvalidView::Initbackground() + { + + noteimage = new UIImageView(); + noteimage->SetPosition(193, 120, 80, 80); + noteimage->SetSrc(BLOOD_PATH_NOTE); + + AddViewToRootContainer(noteimage); + return true; + } + /*** + * @description: + * @return 是否初始化成功 + */ + bool CheckInvalidView::CheckInvalidViewInit() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "bool CheckInvalidView::InitView()"); + if (!Initbackground()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Initbackground error!"); + }; + if (!InitLable()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "InitLable error!"); + }; + if (!AddButton()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AddButton error!"); + }; + return true; + } + /*** + * @description: + * @return 删除组件 + */ + void CheckInvalidView::DeInit() + { + if (kownButton != nullptr) + { + delete kownButton; + kownButton = nullptr; + } + if (noteLabel != nullptr) + { + delete noteLabel; + noteLabel = nullptr; + } + if (titleLabel != nullptr) + { + delete titleLabel; + titleLabel = nullptr; + } + if (remindLabel != nullptr) + { + delete remindLabel; + remindLabel = nullptr; + } + if (noteimage != nullptr) + { + delete noteimage; + noteimage = nullptr; + } + } + + void CheckInvalidView::OnStart() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckInvalidView::OnStart"); + View::OnStart(); + + if (!CheckInvalidViewInit()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckInvalidView::InitBloodView fail"); + } + SetViewData(); + + if(true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb() && (!uapi_sleep_mode_flag_get())) + { + // 震动提醒 + ui_api_vibrate_once_func(); + } + + // 增加按键监听 + RootView::OnKeyActListener *keyactListener = (RootView::OnKeyActListener *)OHOS::CheckInvalidPresenter::GetInstance(); + RootView::GetInstance()->SetOnKeyActListener(keyactListener); + } + +} diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.h new file mode 100644 index 000000000..f3b2b6a6b --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/CheckInvalidView.h @@ -0,0 +1,82 @@ +/*** + * @Date: 2024-07-30 11:22:29 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 17:39:46 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/CheckInvalidView.h + */ +/*** + * @Date: 2024-04-15 10:55:58 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 11:46:23 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/bloodoxygen/include/CheckInvalidView.h + */ +/*** + * @Date: 2024-04-15 10:55:58 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-05-07 18:51:13 + * @FilePath: /XTS_FD230/FD230/code/sdk/application/wearable/fd230app/nativeui/bloodoxygen/include/CheckInvalidView.h + */ +/* + * Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved. + * Description: bloodResult view + * Author: + * Create: 2021-08-01 + */ + +#ifndef CHECK_Invalid_VIEW_H +#define CHECK_Invalid_VIEW_H + +#include "View.h" + +#include "wearable_log.h" +#include "UiConfig.h" + +#include "components/ui_label.h" +#include "components/ui_label_ext.h" +#include"ui_resource_string.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_view_group.h" +#include "heart_blood/CheckInvalidPresenter.h" + +#include "components/ui_scroll_view.h" +#include "components/ui_label_button_ext.h" +namespace OHOS +{ + class CheckInvalidPresenter; + class CheckInvalidView : public View + { + public: + CheckInvalidView(); + virtual ~CheckInvalidView(); + static CheckInvalidView *GetInstance(void); + + + void OnStart() override; + + bool CheckInvalidViewInit(); + + void DeInit(); + bool AddButton(); + bool InitLable(); + bool Initbackground(); + + void SetViewData(); + void SetNoteLabel(UIResourceTextId viewId, int checkResult); + + private: + // 提醒图标 + UIImageView *noteimage = nullptr; + // 按键 + UILabelButtonExt *kownButton = nullptr; + // 提醒label + UILabelExt *titleLabel = nullptr; + UILabelExt *noteLabel = nullptr; + UILabelExt *remindLabel = nullptr; + }; +} + +#endif // 血氧主界面 \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/defult_health.json b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/defult_health.json new file mode 100644 index 000000000..0abdbde23 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/defult_health.json @@ -0,0 +1,12 @@ +data{ + "heart_latest_data": { + "value": 0, + "timestamp": 0 + }, + "heart_data_list": [ + { + "value": 0, + "timestamp": 0 + } + ] +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.cpp new file mode 100644 index 000000000..cea17e948 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.cpp @@ -0,0 +1,692 @@ +#include "health_service.h" +#include "bloodoxygen/include/BloodOxygenModel.h" +#include "cJSON.h" +#include "heartrate/include/HeartModel.h" +#include "kv_store.h" +#include "wearable_log.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "custom_runtime.h" +#include "custom_utils.h" + +// #include "safemodemanager/include/SafeModeManagerModelC.h" + +namespace OHOS { +extern "C" { +void uapi_dev_runtime_set_bloodoxygen_storage_status(uint8_t status); +void uapi_dev_runtime_set_heartrate_storage_status(uint8_t status); + +void save_heart_data() { + // printf("save_heart_data\r\n"); + OHOS::HealthService::GetInstance()->SaveDailyHeartRate(); + return; +} + +void save_heart_maxmin() { + // printf("save_heart_maxmin\r\n"); + uint16_t max_heart_data = + OHOS::HeartModel::GetInstance()->GetShowMaxHeartdata(); + uint16_t min_heart_data = + OHOS::HeartModel::GetInstance()->GetShowMinHeartdata(); + + OHOS::HealthService::GetInstance()->SaveHeartMaxMin(max_heart_data, + min_heart_data); + return; +} +void save_blood_oxygen_data() { + OHOS::BloodOxygenData data; + data.SPO2 = OHOS::BloodOxygenModel::GetInstance()->GetSPO2data(); + data.timestamp = OHOS::BloodOxygenModel::GetInstance()->GetCheckTime(); + // 进行血氧存储 如果处于读取 + if (uapi_dev_runtime_get_bloodoxygen_storage_status()) { + // printf("save_blood_oxygen_data is reading\n"); + //进行延迟 + LOS_Msleep(100); + if (uapi_dev_runtime_get_bloodoxygen_storage_status()) { + // printf("save_blood_oxygen_data is reading again\n"); + //重新发送该消息 + do_custom_fileoperate_service_check_msg( + CUSTOM_FILEOPERATE_MSG_TYPE_BLOODXYGEN_SAVE, nullptr, 0); + return; + } + } + HealthService::GetInstance()->UpdateHealthData(data); + // printf("save_blood_oxygen_data success\n"); + return; +} + +void save_heart_rate_data() { + OHOS::HeartRateData data; + data.Heart = OHOS::HeartModel::GetInstance()->GetHeartdata(); + data.timestamp = OHOS::HeartModel::GetInstance()->GetCheckTime(); + // 进行心率存储 如果处于读取 + if (uapi_dev_runtime_get_heartrate_storage_status()) { + // printf("save_heart_rate_data is reading\n"); + //进行延迟 + LOS_Msleep(100); + if (uapi_dev_runtime_get_heartrate_storage_status()) { + // printf("save_heart_rate_data is reading again\n"); + //重新发送该消息 + do_custom_fileoperate_service_check_msg( + CUSTOM_FILEOPERATE_MSG_TYPE_HEARTRATE_SAVE, nullptr, 0); + return; + } + } + HealthService::GetInstance()->UpdateHealthData(data); + // printf("save_heart_rate_data success\n"); + return; +} +//进行心率列表保存 +void save_heart_list() { HealthService::GetInstance()->SaveDailyHeartRate(); } +} + +//判断时间戳是否为今日 +bool IsTimestampToday(uint32_t timestamp) { + // 获取当前时间 + struct tm currentTm; + time_t seconds; + time(&seconds); + localtime_r(&seconds, ¤tTm); + // 将给定时间戳转换为 tm 结构 + struct tm *timestampTm = + localtime(reinterpret_cast(×tamp)); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "当前年月日:%d-%d-%d", + currentTm.tm_year + 1900, currentTm.tm_mon + 1, + currentTm.tm_mday); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "给定时间戳:%d-%d-%d", + timestampTm->tm_year + 1900, timestampTm->tm_mon + 1, + timestampTm->tm_mday); + // 比较年、月和日 + if ((currentTm.tm_year == timestampTm->tm_year && + currentTm.tm_mon == timestampTm->tm_mon && + currentTm.tm_mday == timestampTm->tm_mday)) { + return true; + } else { + return false; + } +} + +static HealthService *g_pHealthService = nullptr; +/*获取日期*/ +std::string GetCurrentDate() { + char date[9]; + uapi_get_YYMMDD_Time(date, '\0'); + return std::string(date); +#if 0 + time_t now = time(0); + tm *ltm = localtime(&now); + char date[9]; // MM/DD/YYYY format + strftime(date, sizeof(date), "%m%d%Y", ltm); // Use "%m%d%Y" for MMDDYYYY format + return std::string(date); +#endif +} +// static char *JSON_F_buf=NULL; + +HealthService::HealthService() { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HealthService::HealthService"); + g_pHealthService = this; +} +HealthService::~HealthService() { g_pHealthService = nullptr; } +HealthService *HealthService::GetInstance() { + static HealthService instance; + return &instance; +} + +static constexpr const char *HEALTH_JSON_PATH = "/user/userdata/health/"; +static constexpr const char *HEALTH_JSON_PATH_HEART = + "/user/userdata/health/heart/"; +static constexpr const char *HEALTH_JSON_PATH_OXYGEN = + "/user/userdata/health/oxygen/"; +const char *GET_HEALTH_JSON_PATH_C_STR_HEART() { + return HEALTH_JSON_PATH_HEART; +} +const char *GET_HEALTH_JSON_PATH_C_STR_OXYGEN() { + return HEALTH_JSON_PATH_OXYGEN; +} +/* --------------------------------- 文件IO操作 + * --------------------------------- */ +/*创建文件夹*/ +bool HealthService::CreateHealthFolder() { + struct stat info; + if (stat(HEALTH_JSON_PATH, &info) != 0) { + if (mkdir(HEALTH_JSON_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mkdir HEALTH_JSON_PATH is error"); + return false; + } + } + if (stat(HEALTH_JSON_PATH_HEART, &info) != 0) { + if (mkdir(HEALTH_JSON_PATH_HEART, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != + 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "mkdir HEALTH_JSON_PATH_HEART is error"); + return false; + } + } + if (stat(HEALTH_JSON_PATH_OXYGEN, &info) != 0) { + if (mkdir(HEALTH_JSON_PATH_OXYGEN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != + 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "mkdir HEALTH_JSON_PATH_OXYGEN is error"); + return false; + } + } + + return true; +} + +/*生成bin*/ +std::string GetBinFilePath(uint8_t type) { + std::string currentDate = GetCurrentDate(); + const char *healthTypePath = (type == HEALTH_TYPE_HEART) + ? HEALTH_JSON_PATH_HEART + : HEALTH_JSON_PATH_OXYGEN; + + return healthTypePath + currentDate + ".bin"; +} + +/* --------------------------------- json操作 --------------------------------- + */ +static constexpr const char *HEART_JSON_PATH = + "/user/userdata/health/heart.json"; +static constexpr const char *BLOOD_JSON_PATH = + "/user/userdata/health/blood.json"; + +// 读取血氧数据 +BloodOxygenData *HealthService::ReadBloodOxygenData() { + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create health folder"); + return nullptr; + } + + // 读取文件 + std::ifstream inFile(BLOOD_JSON_PATH); + if (!inFile.is_open()) { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Failed to open JSON file"); + return nullptr; + } + + // 读取文件内容到字符串 + std::stringstream buffer; + buffer << inFile.rdbuf(); + std::string jsonDataString = buffer.str(); + const char *jsonData = jsonDataString.c_str(); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "jsonData: %s", jsonData); + + // 关闭文件 + inFile.close(); + + if (jsonDataString.empty()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonDataString is empty"); + return nullptr; + } + + cJSON *oxygen_root = cJSON_Parse(jsonData); + if (oxygen_root == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to parse JSON data"); + return nullptr; + } + + BloodOxygenData *data = new BloodOxygenData(); + + cJSON *value_item = cJSON_GetObjectItem(oxygen_root, "value"); + cJSON *timestamp_item = cJSON_GetObjectItem(oxygen_root, "timestamp"); + + // 检查是否存在必要字段,并验证数据类型 + if (value_item && cJSON_IsNumber(value_item) && timestamp_item && + cJSON_IsNumber(timestamp_item)) { + data->SPO2 = value_item->valueint; + data->timestamp = timestamp_item->valuedouble; + + // 进一步验证数据的合理性 + if (data->SPO2 < 0 || data->SPO2 > 100) // 血氧饱和度范围是0-100 + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid SPO2 value: %d", + data->SPO2); + cJSON_Delete(oxygen_root); + delete data; + return nullptr; + } + } else { + // 读取的数据异常 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Missing or invalid data fields"); + cJSON_Delete(oxygen_root); + delete data; + return nullptr; + } + + cJSON_Delete(oxygen_root); + return data; +} + +// 读取心率数据 +void HealthService::ReadHeartRateData(HeartRateData &data) { + data.timestamp = heart_time; + data.Heart = heart_rate; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "heart_time: %d, heart_rate: %d", + data.timestamp, data.Heart); +} + +// 保存血氧数据X +bool HealthService::UpdateHealthData(const BloodOxygenData &data) { + // 配置血氧存储状态 + uapi_dev_runtime_set_bloodoxygen_storage_status(1); + + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return false; + } + + // 判断文件是否存在,不存在即创建并打开以输出模式 + std::ofstream outFile(BLOOD_JSON_PATH, std::ios::trunc); + if (!outFile.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to create or open JSON file for writing"); + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return false; + } + + // 创建一个 JSON 对象 + cJSON *oxygen_root = cJSON_CreateObject(); + if (oxygen_root == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create JSON object"); + outFile.close(); + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return false; + } + + cJSON_AddItemToObject(oxygen_root, "value", cJSON_CreateNumber(data.SPO2)); + cJSON_AddItemToObject(oxygen_root, "timestamp", + cJSON_CreateNumber(data.timestamp)); + + char *jsonData = cJSON_Print(oxygen_root); + if (jsonData == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to generate JSON data"); + cJSON_Delete(oxygen_root); // 释放内存 + outFile.close(); + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return false; + } + + // 写入 JSON 数据到文件 + outFile << jsonData; + + // 释放资源 + cJSON_Delete(oxygen_root); + free(jsonData); + outFile.close(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHealthData SPO2 JSON is ok"); + + /* 存储bin文件[协议使用] */ + std::string binFilePath = GetBinFilePath(HEALTH_TYPE_OXYGEN); + FILE *fp = fopen(binFilePath.c_str(), "ab+"); + if (fp == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to open binary file for writing"); + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return false; + } + + // 写入数据 + if (fwrite(&data.timestamp, sizeof(data.timestamp), 1, fp) != 1 || + fwrite(&data.SPO2, sizeof(data.SPO2), 1, fp) != 1) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to write data to binary file"); + fclose(fp); + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return false; + } + + fclose(fp); + + uapi_dev_runtime_set_bloodoxygen_storage_status(0); // 恢复状态 + return true; +} + +// 清空健康数据 +bool HealthService::CleanHealthData() { + //清空心率数组 + ClearHourlyHeartRates(); + //进行数据存储 + do_custom_fileoperate_service_check_msg( + CUSTOM_FILEOPERATE_MSG_TYPE_HEART_DATA_LIST, nullptr, 0); + // SaveDailyHeartRate(); + + HeartModel::GetInstance()->ClearDisplayData(); + // BloodOxygenModel::GetInstance()->ClearDisplayData(); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CleanHealthData is ok"); + return true; +} + +HealthState HealthService::GetHealthCurrent() { return healthState_; } +void HealthService::SetHealthCurrent(HealthState healthState) { + healthState_ = healthState; +} +/* ------------------------------- 心率当天历史数据处理 + * ------------------------------ */ +static constexpr const char *HEART_DATA_PATH = + "/user/userdata/health/heart_history.bin"; + +//清空数组 +void HealthService::ClearHourlyHeartRates() { + for (int i = 0; i < MAX_HOURS; ++i) { + dailyHeartRates[i].Heart = 0; + dailyHeartRates[i].timestamp = 0; + } +} + +// 更新心率列表项 +void HealthService::UpdateHourlyHeartRate(time_t timestamp, + uint16_t heartRate) { + struct tm *timeInfo = localtime(×tamp); + uint16_t hour = static_cast(timeInfo->tm_hour); + + if (hour < MAX_HOURS && heartRate > 0) { + + // 更新当前小时的心率和时间戳 + dailyHeartRates[hour].Heart = heartRate; + dailyHeartRates[hour].timestamp = timestamp; + + currenthour = hour; + + // 从当前小时的下一个小时开始,清除后续所有已记录的值 + if (hour != 23) { + for (int i = hour + 1; i < MAX_HOURS; ++i) { + dailyHeartRates[i].Heart = 0; + dailyHeartRates[i].timestamp = 0; + } + } + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHourlyHeartRate is ok"); + } else { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Invalid hour or heart rate value %d", hour); + } +} + +// 获取指定小时的心率 +uint16_t HealthService::GetHourlyHeartRate(uint16_t hour) { + if (hour < MAX_HOURS) { + return dailyHeartRates[hour].Heart; // 默认为 0 如果未更新 + } + return 0; // 或者返回一个异常值 +} +//获取指定小时的时间戳 +time_t HealthService::GetHourlyTimestamp(uint16_t hour) { + if (hour < MAX_HOURS) { + return dailyHeartRates[hour].timestamp; // 默认为 0 如果未更新 + } + return 0; // 或者返回一个异常值 +} + +// 获取当前小时 +uint16_t HealthService::GetCurrentHour() { return currenthour; } +/* +心率最大最小值存储 +关机存储 +*/ +#define HEART_MAX_MIN_PATH "/user/userdata/health/heart_max_min.bin" +// 保存最大最小值 +bool HealthService::SaveHeartMaxMin(uint16_t max, uint16_t min) { + std::ofstream outFile(HEART_MAX_MIN_PATH, std::ios::binary | std::ios::trunc); + if (!outFile.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file"); + return false; + } + + outFile.write(reinterpret_cast(&max), sizeof(max)); + if (!outFile) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to write max value"); + return false; + } + + outFile.write(reinterpret_cast(&min), sizeof(min)); + if (!outFile) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to write min value"); + return false; + } + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SaveHeartMaxMin is ok max %d, min %d", + max, min); + return true; +} +// 加载最大最小值 +void HealthService::LoadHeartMaxMin(uint16_t &max, uint16_t &min) { + max = heart_max; + if (heart_min == 255) + min = 0; + else + min = heart_min; +} + +//进行消息发送 +void HealthService::send_heart_save() { + do_custom_fileoperate_service_check_msg( + CUSTOM_FILEOPERATE_MSG_TYPE_HEARTRATE_SAVE, nullptr, 0); +} +void HealthService::send_blood_save() { + do_custom_fileoperate_service_check_msg( + CUSTOM_FILEOPERATE_MSG_TYPE_BLOODXYGEN_SAVE, nullptr, 0); +} + +//获取list文件 +uint32_t HealthService::GetListTime() { return lastLoadTime; } + +std::string HealthService::formatTime(uint32_t time) { + char labelTime[20]; + if (uapi_get_TIME_STR(time, labelTime, '.', ':', DATE_TIME_DEFULL) != + ERRCODE_SUCC) { + return "--"; // 默认值 + } + return labelTime; // 成功获取时间 +} + +/********************************************************************************************/ +/******************************************************************************************* + */ +//存储心率 +bool HealthService::UpdateHealthData(const HeartRateData &data) { + // 配置心率存储状态 + uapi_dev_runtime_set_heartrate_storage_status(1); + + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); + uapi_dev_runtime_set_heartrate_storage_status(0); // 恢复状态 + return false; + } + + if (data.timestamp < 0 || (!IsTimestampToday(data.timestamp))) { + uapi_dev_runtime_set_heartrate_storage_status(0); // 恢复状态 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid timestamp %d", + data.timestamp); + return false; + } + if (!save_bin_heart(data)) { // 存储bin文件[协议使用] + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveDailyHeartRate failed"); + uapi_dev_runtime_set_heartrate_storage_status(0); // 恢复状态 + return false; + } + + uapi_dev_runtime_set_heartrate_storage_status(0); // 恢复状态 + return true; +} +//存储bin文件 +bool HealthService::save_bin_heart(const HeartRateData &data) { + /* 存储 bin 文件 [协议使用] */ + std::string binFilePath = GetBinFilePath(HEALTH_TYPE_HEART); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "save_bin_heart binFilePath %s", + binFilePath.c_str()); + FILE *fp = fopen(binFilePath.c_str(), "ab+"); + if (fp == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to open binary file for writing"); + return false; + } + + // 写入数据 + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "sizeof(HeartRateData) %d", sizeof(HeartRateData)); + if ((fwrite(&data.timestamp, sizeof(data.timestamp), 1, fp) != 1) || (fwrite(&data.Heart, sizeof(data.Heart), 1, fp) != 1)) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to write data to binary file"); + fclose(fp); + return false; + } + + fclose(fp); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "Saved heart data: timestamp = %d, Heart = %d", data.timestamp, + data.Heart); + return true; +} +// 加载心率数据 24小时数据 +bool HealthService::LoadDailyHeartRate() { + ClearHourlyHeartRates(); // 清空数组 赋0操作 + std::string binFilePath = GetBinFilePath(HEALTH_TYPE_HEART); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "LoadDailyHeartRate"); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "binFilePath %s", binFilePath.c_str()); + + // 配置心率存储状态 + uapi_dev_runtime_set_heartrate_storage_status(1); + + std::ifstream ifs(binFilePath, std::ios::binary); + if (!ifs.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to open binary file for reading"); + uapi_dev_runtime_set_heartrate_storage_status(0); + return false; + } + + HeartRateData data; + + // 选取每个小时的最新数据 + while (true) { + // 先读取时间戳 + if (!ifs.read(reinterpret_cast(&data.timestamp), sizeof(data.timestamp))) { + break; // 如果读取失败,退出循环 + } + + // 再读取心率值 + if (!ifs.read(reinterpret_cast(&data.Heart), sizeof(data.Heart))) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to read heart rate value"); + break; // 如果读取失败,退出循环 + } + + // 检查时间戳是否为当天 + if (IsTimestampToday(data.timestamp)) { + // 计算当前小时 + time_t rawTime = static_cast(data.timestamp); + struct tm *timeInfo = localtime(&rawTime); + int hour = timeInfo->tm_hour; // 获取小时数 + + // 更新每小时最新心率数据 + if (dailyHeartRates[hour].timestamp < data.timestamp) { + dailyHeartRates[hour].Heart = data.Heart; // 更新最新数据 + dailyHeartRates[hour].timestamp = data.timestamp; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "hour %d %d %d", hour, + data.timestamp, data.Heart); + } + + // 更新最高、最低心率 + if (data.Heart > heart_max) { + heart_max = data.Heart; + } + if (data.Heart < heart_min) { + heart_min = data.Heart; + } + // 更新最新心率数据 + heart_time = data.timestamp; + heart_rate = data.Heart; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "Loaded heart data: timestamp = %d, Heart = %d", + data.timestamp, data.Heart); + } else { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, + "error data: timestamp = %d, Heart = %d", data.timestamp, + data.Heart); + } + } + + // 打印list内容 + // for (int i = 0; i < MAX_HOURS; i++) { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "dailyHeartRates[%d] %d %d", i, + // dailyHeartRates[i].timestamp, dailyHeartRates[i].Heart); + // } + + uapi_dev_runtime_set_heartrate_storage_status(0); + return true; +} +std::string HealthService::get_heart_data() { + std::string binFilePath = GetBinFilePath(HEALTH_TYPE_HEART); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "binFilePath %s", binFilePath.c_str()); + + std::ifstream ifs(binFilePath, std::ios::binary); // 以二进制读取模式打开文件 + if (!ifs.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to open binary file for reading"); + return "Error: Unable to open file \n"; // 返回错误信息 + } + + std::stringstream result; + result << "file: " << binFilePath << "\n"; + HeartRateData data; + + // 读取数据直到文件结束 + while (ifs.read(reinterpret_cast(&data), sizeof(HeartRateData))) { + // 检查时间戳的有效性 + if (data.timestamp < 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid timestamp read: %d", + data.timestamp); + continue; // 跳过无效的数据 + } + + // 将数据格式化为字符串,拼接到结果中 + result << formatTime(data.timestamp) << "," << std::to_string(data.Heart) + << "\n"; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "get_heart_data %d %d", + data.timestamp, data.Heart); + } + + if (ifs.bad()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Error reading data from binary file"); + return "Error: Reading error \n"; // 返回读取错误信息 + } + + return result.str().empty() ? "No data found \n" + : result.str(); // 检查是否读取到数据 +} + +// 存储血氧数据 +// bool HealthService::save_bin_blood(const BloodOxygenData &bloodoxygen) { +// /* 存储bin文件[协议使用] */ +// std::string binFilePath = GetBinFilePath(HEALTH_TYPE_HEART); +// FILE *fp = fopen(binFilePath.c_str(), "ab+"); +// if (fp == NULL) { +// WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, +// "Failed to open binary file for writing"); +// return false; +// } +// WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "binFilePath %s", +// binFilePath.c_str()); + +// if (fwrite(&bloodoxygen, sizeof(bloodoxygen), 1, fp) != 1) { +// WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, +// "Failed to write data to binary file"); +// fclose(fp); +// return false; +// } +// fclose(fp); +// WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "save_bin_blood is ok"); +// return true; +// } +} // namespace OHOS diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.h new file mode 100644 index 000000000..9028f3933 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/health_service/health_service.h @@ -0,0 +1,131 @@ +/*** + * @Date: 2024-06-14 11:34:19 + * @LastEditors: Caisking 3449750381@qq.com + * @LastEditTime: 2024-07-30 17:45:59 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/health_service/health_service.h + */ + +#ifndef HEART_SERVICE_H +#define HEART_SERVICE_H + +#include "stdio.h" +#include "string" + +#include +#include +#include +#include + +#define HEART_MAX_POINTS 360 +#define MSG_SAVE_TEST 0 +namespace OHOS +{ + const char *GET_HEALTH_JSON_PATH_C_STR_HEART(); + const char *GET_HEALTH_JSON_PATH_C_STR_OXYGEN(); + + typedef enum { + HEALTH_TYPE_HEART, + HEALTH_TYPE_OXYGEN, + } HEALTH_TYPE; + +#pragma pack(push, 1) // 设置对齐为1字节 + typedef struct + { + uint32_t timestamp; // 最近一次检测时间 + uint8_t SPO2; // 血氧值 + } BloodOxygenData; + typedef struct + { + uint32_t timestamp; // 最近一次检测时间 + uint8_t Heart; // 心率值 + } HeartRateData; +#pragma pack(pop) // 恢复默认对齐 + // 检查类 + typedef enum + { + BLOOD_CHECK, + HEART_CHECK, + CHARGE, + } CheckClass; + + // 检查结果 + typedef enum + { + HIGH, + LOW + } CheckResult; + + // 健康状态 + typedef struct + { + CheckClass checkType; // 检查类型 + CheckResult resultStatus; // 结果状态 + uint16_t checkResult; // 检查结果 + } HealthState; + + class HealthService + { + public: + HealthService(); + ~HealthService(); + static HealthService *GetInstance(void); + bool CreateHealthFolder(); + bool LoadJsonData(uint8_t type); // 加载json + BloodOxygenData *ReadBloodOxygenData(); // 读取血氧数据 + void ReadHeartRateData( HeartRateData &data); // 读取心率数据 + bool UpdateHealthData(const HeartRateData &data); // 更新心率数据 + bool UpdateHealthData(const BloodOxygenData &data); + void ReleaseJsonData(uint8_t type); // 释放json + bool UpdateJsonData(uint8_t type); // 更新json + bool CleanHealthData(); + + /*健康状态*/ + HealthState GetHealthCurrent(); + void SetHealthCurrent(HealthState healthState); + + /* + 当天24个小时的心率处理 + -心率数组 每个小时存储最新的值 但是没有小时只有一个值 + -开机读取 + -关机存储 + */ + bool SaveDailyHeartRate(); + bool LoadDailyHeartRate(); + void UpdateHourlyHeartRate(time_t timestamp, uint16_t heartRate); + uint16_t GetHourlyHeartRate(uint16_t hour); + time_t GetHourlyTimestamp(uint16_t hour); + void ClearHourlyHeartRates(); + uint16_t GetCurrentHour(); + uint32_t GetListTime(); + + bool SaveHeartMaxMin(uint16_t max, uint16_t min); + void LoadHeartMaxMin(uint16_t &max, uint16_t &min); + + void send_heart_save(); + void send_blood_save(); + + std::string get_heart_data(); + std::string get_blood_data(); + std::string formatTime(uint32_t time); + + bool save_bin_heart(const HeartRateData &heart); + bool save_bin_blood(const BloodOxygenData &bloodoxygen); + + private: + //曲线显示数据 + static const int MAX_HOURS = 24; + HeartRateData dailyHeartRates[MAX_HOURS]; + //最大最小心率 + uint8_t heart_max = 0; + uint8_t heart_min = 255; + //最新一次检测的时间与心率值 + uint32_t heart_time = 0; + uint8_t heart_rate = 0; + + //健康状态 + HealthState healthState_; + time_t lastLoadTime; // 记录最后加载的时间 + uint16_t currenthour = 0; + }; +} +#endif // HEALTH_MODEL_H \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartModel.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartModel.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartModel.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartModel.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartPresenter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartPresenter.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartPresenter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartPresenter.h new file mode 100644 index 000000000..e69de29bb diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartView.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/heart_blood/set_heart/SetHeartView.h new file mode 100644 index 000000000..e69de29bb -- 2.17.1