#include <map>
#include <string>
+#ifdef SUPPORT_PPG_SERVICE
+#include "ppg_hal.h"
+#include "ppg_service.h"
+#endif
+
namespace OHOS {
static BPMainPresenter *g_pBPMainPresenter = nullptr;
int16_t current = mainView->GetCurrentViewId();
if (current == BP_MEASURING_VIEW || current == BP_CALIBRATING_VIEW) {
ResumeProgressSession();
+ SetScreenAlwaysOnForBp(true);
}
}
}
return viewId == BP_MEASURING_VIEW || viewId == BP_CALIBRATING_VIEW;
}
+/** 请求停止确认 */
void BPMainPresenter::RequestStopConfirm(int16_t fromView) {
BPMainView *mainView = BPMainView::GetInstance();
if (mainView == nullptr) {
mainView->ChangeView(fromView, BP_CALIB_STOP_VIEW);
}
+/** 处理滑动返回 */
bool BPMainPresenter::HandleSwipeBack() {
BPMainView *mainView = BPMainView::GetInstance();
if (mainView == nullptr) {
return true;
}
+/** 进度定时器回调 */
void BPMainPresenter::ProgressTimerThunk(void *arg) {
auto *self = static_cast<BPMainPresenter *>(arg);
if (self == nullptr) {
GraphicService::GetInstance()->PostGraphicEvent([self]() { self->OnProgressTick(); });
}
+/** 开始进度会话 */
void BPMainPresenter::StartProgressSession(BPProgressMode mode) {
StopProgressSession();
progressMode_ = mode;
progressDataReceived_ = false;
progressPaused_ = false;
UpdateProgressUi(0);
+ StartPpgSession(mode);
+ uapi_set_screen_on_api();
+ SetScreenAlwaysOnForBp(true);
const uint32_t tick = GetOSTick(static_cast<int32_t>(kProgressTickMs));
progressTimer_ = new GraphicTimer(static_cast<int32_t>(tick), ProgressTimerThunk, this, true);
void BPMainPresenter::ResumeProgressSession() { progressPaused_ = false; }
+/** 停止进度会话 */
void BPMainPresenter::StopProgressSession() {
+ SetScreenAlwaysOnForBp(false);
+ StopPpgSession();
if (progressTimer_ != nullptr) {
progressTimer_->Stop();
delete progressTimer_;
progressPaused_ = false;
}
+/** 判断血压读数是否有效 */
+bool BPMainPresenter::IsValidBpReading(int sbp, int dbp) {
+ return sbp >= 60 && sbp <= 250 && dbp >= 40 && dbp <= 150 && sbp > dbp;
+}
+
+/** 开始PPG会话 */
+void BPMainPresenter::StartPpgSession(BPProgressMode mode) {
+#ifdef SUPPORT_PPG_SERVICE
+ BPModel *model = BPModel::GetInstance();
+ if (mode == BPProgressMode::Calibrate) {
+ int sbp = static_cast<int>(model->GetInputSbp());
+ int dbp = static_cast<int>(model->GetInputDbp());
+ ppg_set_bp_cali_data(&sbp, &dbp);
+ ppg_bp_start(0);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] ppg cali start sbp=%d dbp=%d", sbp, dbp);
+ } else if (mode == BPProgressMode::Measure) {
+ ppg_bp_start(1);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] ppg measure start");
+ }
+#else
+ (void)mode;
+#endif
+}
+
+/** 停止PPG会话 */
+void BPMainPresenter::StopPpgSession() {
+#ifdef SUPPORT_PPG_SERVICE
+ if (progressMode_ != BPProgressMode::None) {
+ ppg_bp_stop();
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] ppg stop");
+ }
+#endif
+}
+
+void BPMainPresenter::SetScreenAlwaysOnForBp(bool enable) {
+ if (enable) {
+ if (!screenAlwaysOnForBp_) {
+ ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
+ screenAlwaysOnForBp_ = true;
+ }
+ return;
+ }
+ if (screenAlwaysOnForBp_) {
+ ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
+ screenAlwaysOnForBp_ = false;
+ }
+}
+
+/** 轮询PPG结果 */
+bool BPMainPresenter::PollPpgResult() {
+#ifdef SUPPORT_PPG_SERVICE
+ int sbp = 0;
+ int dbp = 0;
+ ppg_get_bp(&sbp, &dbp);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] PollPpgResult mode=%d sbp=%d dbp=%d",
+ static_cast<int>(progressMode_), sbp, dbp);
+
+ if (progressMode_ == BPProgressMode::Measure) {
+ if (!IsValidBpReading(sbp, dbp)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] measure poll invalid sbp=%d dbp=%d", sbp, dbp);
+ return false;
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] measure result sbp=%d dbp=%d", sbp, dbp);
+ NotifyMeasureComplete(static_cast<uint8_t>(sbp), static_cast<uint8_t>(dbp));
+ return true;
+ }
+
+ if (progressMode_ == BPProgressMode::Calibrate) {
+ /* 校准模式:算法产出 NoCal 值即表示本轮回合采集完成 */
+ if (sbp <= 0 || dbp <= 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] cali poll no result sbp=%d dbp=%d", sbp, dbp);
+ return false;
+ }
+ BPModel *model = BPModel::GetInstance();
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "[BP] cali algorithm done, use input sbp=%d dbp=%d (algo nocall %d/%d)",
+ model->GetInputSbp(), model->GetInputDbp(), sbp, dbp);
+ NotifyCalibrationComplete(model->GetInputSbp(), model->GetInputDbp());
+ return true;
+ }
+#else
+ (void)0;
+#endif
+ return false;
+}
+
void BPMainPresenter::UpdateProgressUi(int percent) {
if (progressMode_ == BPProgressMode::Measure) {
BPMeasuringView *view = BPMeasuringView::GetInstance();
}
}
+/** 进度定时器回调 */
void BPMainPresenter::OnProgressTick() {
if (progressPaused_ || progressDataReceived_ || progressMode_ == BPProgressMode::None) {
return;
UpdateProgressUi(progressPercent_);
if (progressPercent_ >= kProgressMaxPercent && !progressDataReceived_) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] progress 100%%, poll ppg result");
+ if (PollPpgResult()) {
+ return;
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BP] poll failed, goto timeout");
lastTimeoutMode_ = progressMode_;
OnProgressTimeout();
}
}
+/** 进度超时回调 */
void BPMainPresenter::OnProgressTimeout() {
StopProgressSession();
BPMainView *mainView = BPMainView::GetInstance();
}
}
+/** 通知校准完成 */
void BPMainPresenter::NotifyCalibrationComplete(uint8_t sbp, uint8_t dbp) {
if (progressDataReceived_) {
return;
CompleteCalibrationFlow(sbp, dbp);
}
+/** 通知测量完成 */
void BPMainPresenter::NotifyMeasureComplete(uint8_t sbp, uint8_t dbp) {
if (progressDataReceived_) {
return;
}
}
+/** 开始测量流程 */
void BPMainPresenter::StartMeasureFlow(BPMainView *mainView) {
int16_t hide = mainView->GetCurrentViewId();
mainView->ChangeView(hide, BP_MEASURING_VIEW);
StartProgressSession(BPProgressMode::Measure);
}
+/** 开始校准流程 */
void BPMainPresenter::StartCalibrationFlow(BPMainView *mainView, uint8_t round) {
BPModel *model = BPModel::GetInstance();
model->SetCalibrationRound(round);
mainView->ChangeView(hide, BP_VALUE_INPUT_VIEW);
}
+/** 处理点击事件 */
bool BPMainPresenter::OnClick(UIView &view, const ClickEvent &event) {
UNUSED(event);
std::string viewId = view.GetViewId();
mainView->ChangeView(BP_ENTRY_VIEW, BP_INSTRUCTION_VIEW, BP_INSTRUCTION_TYPE_SEAT);
return true;
}
+ /** 处理值输入事件 */
if (viewId == BP_CLICK_VALUE_NEXT) {
BPValueInputView *inputView = BPValueInputView::GetInstance();
if (inputView != nullptr && inputView->GetSbpPicker() != nullptr &&
mainView->ChangeView(BP_VALUE_INPUT_VIEW, BP_VALUE_CONFIRM_VIEW);
return true;
}
+ /** 处理值确认事件 */
if (viewId == BP_CLICK_VALUE_CONFIRM) {
if (model->GetInputSbp() > model->GetInputDbp()) {
mainView->ChangeView(BP_VALUE_CONFIRM_VIEW, BP_CALIBRATING_VIEW);
mainView->ChangeView(current, BP_ENTRY_VIEW);
return true;
}
+ /** 处理重试事件 */
if (viewId == BP_CLICK_RETRY) {
if (current == BP_ABNORMAL_VIEW) {
if (lastTimeoutMode_ == BPProgressMode::Calibrate) {
ECGMainPresenter::ECGMainPresenter() { g_pECGMainPresenter = this; }
ECGMainPresenter::~ECGMainPresenter() {
+ SetScreenAlwaysOnForEcg(false);
StopMeasureTimer();
StopContactGoodTimer();
g_pECGMainPresenter = nullptr;
void ECGMainPresenter::OnResume(void) {
RootView::GetInstance()->SetOnKeyActListener(this);
+ ECGMainView *mainView = ECGMainView::GetInstance();
+ if (mainView != nullptr && mainView->GetCurrentViewId() == ECG_MEASURING_VIEW) {
+ SetScreenAlwaysOnForEcg(true);
+ }
}
void ECGMainPresenter::OnStop(void) {
+ SetScreenAlwaysOnForEcg(false);
StopMeasureTimer();
StopContactGoodTimer();
}
void ECGMainPresenter::StartMeasureTimer() {
StopMeasureTimer();
+ uapi_set_screen_on_api();
+ SetScreenAlwaysOnForEcg(true);
g_ecgMeasureTimer =
osTimerNew((osTimerFunc_t)ECGMeasureTimerCallback, osTimerPeriodic, nullptr, nullptr);
if (g_ecgMeasureTimer != nullptr) {
}
void ECGMainPresenter::StopMeasureTimer() {
+ SetScreenAlwaysOnForEcg(false);
if (g_ecgMeasureTimer != nullptr) {
osTimerStop(g_ecgMeasureTimer);
osTimerDelete(g_ecgMeasureTimer);
}
}
+void ECGMainPresenter::SetScreenAlwaysOnForEcg(bool enable) {
+ if (enable) {
+ if (!screenAlwaysOnForEcg_) {
+ ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
+ screenAlwaysOnForEcg_ = true;
+ }
+ return;
+ }
+ if (screenAlwaysOnForEcg_) {
+ ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
+ screenAlwaysOnForEcg_ = false;
+ }
+}
+
void ECGMainPresenter::StartMeasureFlow(ECGMainView *mainView) {
ShowWaitContact(mainView);
}