--- /dev/null
+\r
+#include "heart_blood/BloodCardView.h"\r
+#include "common/image_cache_manager.h"\r
+#include "UiConfig.h"\r
+#include "ui_resource_image.h"\r
+#include <ui_scroll_view.h>\r
+#include "components/ui_button.h"\r
+#include "MainViewSample.h"\r
+#include "components/ui_view_group.h"\r
+#include "DialModelSPO2.h"\r
+#include "DialModelHeartRate.h"\r
+\r
+#include "UiConfig.h"\r
+#include "uicomponents/UIComponents.h"\r
+#include "MainPresenterSample.h"\r
+\r
+#include "bloodoxygen/include/BloodResultPresenter.h"\r
+#include "bloodoxygen/include/BloodOxygenModel.h"\r
+namespace OHOS\r
+{\r
+ static BloodCardView *g_pBloodCardView{nullptr};\r
+\r
+ BloodCardView::BloodCardView()\r
+ {\r
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BloodCardView::BloodCardView");\r
+ SetPosition(0, 0, HORIZONTAL_RESOLUTION, VERTICAL_RESOLUTION);\r
+ g_pBloodCardView = this;\r
+ }\r
+\r
+ BloodCardView::~BloodCardView()\r
+ {\r
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BloodCardView::~BloodCardView");\r
+ DeInit();\r
+ g_pBloodCardView = nullptr;\r
+ }\r
+\r
+ BloodCardView *BloodCardView::GetInstance()\r
+ {\r
+ return g_pBloodCardView;\r
+ }\r
+\r
+ /* -------------------------------------------------------------------------- */\r
+ void BloodCardView::UpSPO2Text()\r
+ {\r
+ if (bloodLabel == nullptr || timeLabel == nullptr)\r
+ return;\r
+ \r
+ // 更新血氧数据\r
+ uint16_t spo2 = BloodOxygenModel::GetInstance()->GetSPO2data();\r
+ if (spo2 != 0) // 判断是否为默认数据\r
+ {\r
+ // 更新数据\r
+ std::string bloodoxygenStr = std::to_string(spo2) + "%";\r
+ bloodLabel->SetText(bloodoxygenStr.c_str());\r
+\r
+ // 获取时间差\r
+ uint32_t time = BloodResultPresenter::GetInstance()->GetCurrentTime();\r
+ uint32_t check_time = BloodOxygenModel::GetInstance()->GetCheckTime();\r
+ int time_diff = BloodResultPresenter::GetInstance()->GetTDOA(time, check_time);\r
+\r
+ if (time_diff == 0)\r
+ {\r
+ timeLabel->SetTextId(STR_CHECKNEW);\r
+ }\r
+ else if (time_diff <= 60)\r
+ {\r
+ UpdateLabel(timeLabel, time_diff, STR_CHECKTIME);\r
+ }\r
+ else\r
+ {\r
+ timeLabel->SetTextId(STR_CHECKLONG);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ bloodLabel->SetText("--");\r
+ timeLabel->SetTextId(STR_CHECKNO);\r
+ }\r
+ }\r
+\r
+ /* -------------------------------------------------------------------------- */\r
+ /***\r
+ * @description:\r
+ * @return 添加按键是否成功\r
+ */\r
+ bool BloodCardView::AddButton()\r
+ {\r
+ InitButtonExt(checkButton, 118, 336, 230, 80, MAIN_CLICK_BLOOD, STR_CHECK, 30);\r
+ checkButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xffFF5A36); // 设置按键颜色\r
+ // 设置按键监听\r
+ UIView::OnClickListener *clickListener = (UIView::OnClickListener *)OHOS::MainPresenterSample::GetInstance();\r
+ checkButton->SetOnClickListener(clickListener);\r
+\r
+ Add(checkButton);\r
+ return true;\r
+ }\r
+ /***\r
+ * @description:\r
+ * @return 初始化标签是否成功\r
+ */\r
+ bool BloodCardView::InitLable()\r
+ {\r
+ /*初始化title*/\r
+ InitRollLabel(titleLabel, 83, 50, 300, 35, "title", STR_BLOOD, DEFAULT_VECTOR_FONT_FILENAME, 30);\r
+ /*初始化血氧值label*/\r
+ InitUILabel(bloodLabel, 83, 22, 300, 300, "bloodtext", "--", DEFAULT_VECTOR_FONT_FILENAME, 120);\r
+ /*初始化检测时间*/\r
+ InitRollLabel(timeLabel, 53, 260, 360, 35, "time", STR_CHECKNO, DEFAULT_VECTOR_FONT_FILENAME, 30);\r
+ // 设置来回滚动属性\r
+ timeLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION);\r
+ timeLabel->SetRollSpeed(23);\r
+\r
+ UpSPO2Text();\r
+\r
+ Add(titleLabel);\r
+ Add(bloodLabel);\r
+ Add(timeLabel);\r
+\r
+ return true;\r
+ }\r
+ /***\r
+ * @description:\r
+ * @return 初始化背景是否成功\r
+ */\r
+ bool BloodCardView::Initbackground()\r
+ {\r
+\r
+ background = new UIImageView();\r
+\r
+ background->SetPosition(0, 0); // widget's left position and top position\r
+ background->Resize(466, 466); // widget's width and height\r
+ background->SetViewId("image1"); // Set style\r
+\r
+ Add(background);\r
+ return true;\r
+ }\r
+ /***\r
+ * @description:\r
+ * @return 是否初始化成功\r
+ */\r
+ bool BloodCardView::InitView()\r
+ {\r
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "bool BloodCardView::InitView()");\r
+ if (!Initbackground())\r
+ {\r
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Initbackground error!\n");\r
+ };\r
+ if (!InitLable())\r
+ {\r
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "InitLable error!\n");\r
+ };\r
+ if (!AddButton())\r
+ {\r
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AddButton error!\n");\r
+ };\r
+ // SetCoverable(true);\r
+ return true;\r
+ }\r
+ /***\r
+ * @description:\r
+ * @return 删除组件\r
+ */\r
+ void BloodCardView::DeInit()\r
+ {\r
+ UnLoadBloodImageRes();\r
+ RemoveAll();\r
+ if (background != nullptr)\r
+ {\r
+ delete background;\r
+ background = nullptr;\r
+ }\r
+ if (bloodLabel != nullptr)\r
+ {\r
+ delete bloodLabel;\r
+ bloodLabel = nullptr;\r
+ }\r
+ if (timeLabel != nullptr)\r
+ {\r
+ delete timeLabel;\r
+ timeLabel = nullptr;\r
+ }\r
+ if (titleLabel != nullptr)\r
+ {\r
+ delete titleLabel;\r
+ titleLabel = nullptr;\r
+ }\r
+ }\r
+ /* -------------------------------------------------------------------------- */\r
+ /*预加载血氧图片资源*/\r
+ void BloodCardView::PreLoadBloodImageRes(void)\r
+ {\r
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::PreLoadBloodImageRes");\r
+ if (!resLoadStatus)\r
+ {\r
+ ImageInfo *image = ImageCacheManager::GetInstance().LoadOneInMultiRes(BLOODOXYGEN_BACKGOUND, BLOOD_IAMGES);\r
+ if (image == nullptr)\r
+ {\r
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingView::LoadTrainingImage fail");\r
+ return;\r
+ }\r
+ background->SetSrc(image);\r
+ resLoadStatus = true;\r
+ }\r
+ }\r
+\r
+ /*卸载血氧图片资源*/\r
+ void BloodCardView::UnLoadBloodImageRes(void)\r
+ {\r
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::UnLoadBloodImageRes");\r
+ if (resLoadStatus)\r
+ {\r
+ ImageInfo *img = nullptr;\r
+ background->SetSrc(img);\r
+ ImageCacheManager::GetInstance().UnloadOneInMultiRes(BLOODOXYGEN_BACKGOUND, BLOOD_IAMGES);\r
+ resLoadStatus = false;\r
+ }\r
+ }\r
+\r
+ void BloodCardView::PreLoad(void)\r
+ {\r
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::PreLoad");\r
+ if (!viewiInitStatus)\r
+ {\r
+ InitView();\r
+ viewiInitStatus = true;\r
+ }\r
+ PreLoadBloodImageRes();\r
+ }\r
+\r
+ void BloodCardView::UnLoad(void)\r
+ {\r
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BloodCardView::UnLoad");\r
+ UnLoadBloodImageRes();\r
+ }\r
+ /* -------------------------------------------------------------------------- */\r
+}\r
--- /dev/null
+/***\r
+ * @Date: 2024-06-28 16:08:09\r
+ * @LastEditors: Caisking 3449750381@qq.com\r
+ * @LastEditTime: 2024-07-29 11:48:50\r
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/BloodCardView.h\r
+ */\r
+/***\r
+ * @Date: 2024-06-26 16:13:19\r
+ * @LastEditors: Caisking 3449750381@qq.com\r
+ * @LastEditTime: 2024-06-26 16:52:01\r
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/heart_blood/BloodCardView.h\r
+ */\r
+\r
+#ifndef _Blood_CARD_VIEW_H\r
+#define _Blood_CARD_VIEW_H\r
+\r
+\r
+#include "View.h"\r
+#include <ui_scroll_view.h>\r
+#include "components/ui_view_group.h"\r
+#include "components/ui_label.h"\r
+#include "components/ui_label_ext.h"\r
+#include "components/ui_image_view.h"\r
+#include "components/ui_button.h"\r
+#include "components/ui_image_animator.h"\r
+#include "components/ui_label_button_ext.h"\r
+#include "components/ui_card_page.h"\r
+#include "components/ui_label_button_ext.h"\r
+\r
+namespace OHOS\r
+{\r
+\r
+#define CHECK "buttoncheck"\r
+\r
+ class BloodCardView : public UICardPage\r
+ {\r
+\r
+ public:\r
+ BloodCardView();\r
+ virtual ~BloodCardView();\r
+ static BloodCardView *GetInstance(void);\r
+\r
+ bool InitView();\r
+ void DeInit();\r
+\r
+ bool AddButton();\r
+ bool InitLable();\r
+ bool Initbackground();\r
+\r
+ void PreLoad(void) override;\r
+ void UnLoad(void) override;\r
+\r
+ void UpSPO2Text();\r
+\r
+ private:\r
+ void PreLoadBloodImageRes(void);\r
+ void UnLoadBloodImageRes(void);\r
+\r
+ private:\r
+ UIView::OnDragListener *draglistener{nullptr};\r
+ BloodCardView(BloodCardView &&) = delete;\r
+ BloodCardView &operator=(BloodCardView &&) = delete;\r
+\r
+ UIImageView *background = nullptr;\r
+ UIButton *warnButton = nullptr;\r
+ UILabelButton *monitorButton = nullptr;\r
+ UILabelExt *titleLabel = nullptr;\r
+ UILabelExt *timeLabel = nullptr;\r
+ UILabel *bloodLabel = nullptr;\r
+\r
+ UILabelButtonExt *checkButton{nullptr};\r
+\r
+ bool viewiInitStatus{false};\r
+ bool resLoadStatus{false};\r
+\r
+ int bloodoxygen;\r
+ };\r
+} // namespace OHOS\r
+#endif // Blood_PRESENTER_H\r
--- /dev/null
+/***
+ * @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 <fstream>
+#include "iostream"
+#include <sstream>
+#include <string>
+#include <cstdlib>
+#include <ctime>
+#include "wearable_log.h"
+#include "cmsis_os.h"
+#include "securec.h"
+#include "broadcast_service.h"
+#include "graphic_service.h"
+#include <chrono>
+#include <thread>
+#include <sys/time.h>
+
+#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<CheckAbnormalView>::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
--- /dev/null
+/***
+ * @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<CheckAbnormalView>,
+ 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
--- /dev/null
+/***
+ * @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 <ui_scroll_view.h>
+#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_);
+ }
+}
--- /dev/null
+/***
+ * @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<CheckAbnormalPresenter>
+ {
+ 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
--- /dev/null
+/***
+ * @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 <fstream>
+#include "iostream"
+#include <sstream>
+#include <string>
+#include <cstdlib>
+#include <ctime>
+#include "wearable_log.h"
+#include "cmsis_os.h"
+#include "securec.h"
+#include "broadcast_service.h"
+#include "graphic_service.h"
+#include <chrono>
+#include <thread>
+#include <sys/time.h>
+
+#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<CheckInvalidView>::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
--- /dev/null
+/***
+ * @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<CheckInvalidView>,
+ 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
--- /dev/null
+/***
+ * @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 <ui_scroll_view.h>
+#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<CheckInvalidPresenter>::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);
+ }
+
+}
--- /dev/null
+/***
+ * @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<CheckInvalidPresenter>
+ {
+ 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
--- /dev/null
+data{
+ "heart_latest_data": {
+ "value": 0,
+ "timestamp": 0
+ },
+ "heart_data_list": [
+ {
+ "value": 0,
+ "timestamp": 0
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+#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 <cstdint>
+#include <ctime>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <sys/stat.h>
+
+#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<const time_t *>(×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<uint16_t>(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<const char *>(&max), sizeof(max));
+ if (!outFile) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to write max value");
+ return false;
+ }
+
+ outFile.write(reinterpret_cast<const char *>(&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<char *>(&data.timestamp), sizeof(data.timestamp))) {
+ break; // 如果读取失败,退出循环
+ }
+
+ // 再读取心率值
+ if (!ifs.read(reinterpret_cast<char *>(&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<time_t>(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<char *>(&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
--- /dev/null
+/***
+ * @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 <fstream>
+#include <ctime>
+#include <cstdint>
+#include <string>
+
+#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