* @Date: 2024-04-15 11:46:23
* @LastEditors: Caisking 3449750381@qq.com
* @LastEditTime: 2024-04-15 15:09:35
- * @FilePath: /sdk/application/wearable/fd230app/nativeui/traing/src/TraingModel.cpp
+ * @FilePath:
+ * /sdk/application/wearable/fd230app/nativeui/traing/src/TraingModel.cpp
*/
#include "traing/include/TraingModel.h"
+#include "cmsis_os.h"
+#include "custom_utils.h"
+#include "thread_adapter.h"
+#include "traing/training_card/include/TraingCardPresenter.h"
#include "uicomponents/UIComponents.h"
#include "wearable_log.h"
-#include <iostream>
-#include <string>
-#include "custom_utils.h"
#include <cmsis_os2.h>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
#include <service/graphic_service.h>
-#include "thread_adapter.h"
#include <sstream>
-#include <iomanip>
-#include <fstream>
-#include "cmsis_os.h"
-#include "traing/training_card/include/TraingCardPresenter.h"
+#include <string>
+#include "ConfigModel.h"
+#include "bleEvent.h"
+#include "bletest.h"
#include "broadcast_feature.h"
#include "broadcast_service.h"
-#include "bletest.h"
-#include "ConfigModel.h"
+#include "custom_runtime.h"
+#include "power_display_service.h"
#include "samgr_lite.h"
+#include "traingrecord/include/TraingRecordModel.h"
#include "vibrator_service.h"
-#include <mutex>
+#include <algorithm>
+#include <filesystem>
+#include <fstream>
+#include <limits.h>
+#include <list>
#include <memory>
-#include "bleEvent.h"
-#include "power_display_service.h"
+#include <mutex>
+#include <numeric>
+#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <filesystem>
-#include <algorithm>
-#include <fstream>
-#include <limits.h>
-#include <list>
-#include "samgr_lite.h"
#include <vector>
-#include <queue>
-#include <numeric>
-#include "custom_runtime.h"
-#include "traingrecord/include/TraingRecordModel.h"
-
-#define MAX_FILE_PATH_LENGTH 128
-#define TRAINING_DATA_DIRECTORY "user/userdata/sport/"
-#define TRAINING_RECORD_FILE "user/userdata/sport/Record.json"
-#define MAX_DATA_COUNT 10
-
-#define TIMER 1
-#define BLETEST 0
-#define HARD_OFF 1
-#define READTEST 0
-
-#define MAX_HEART_RATE 220
-#define AGE_THRESHOLD 59
-#define LOW_INTENSITY_THRESHOLD 59
-#define MEDIUM_INTENSITY_LOWER_THRESHOLD 60
-#define MEDIUM_INTENSITY_UPPER_THRESHOLD 69
-#define HIGH_INTENSITY_LOWER_THRESHOLD 70
-#define HIGH_INTENSITY_UPPER_THRESHOLD 79
-
-#define MAXSPORTID 176
extern "C" errcode_t uapi_get_timestampe_ms(uint32_t *tm);
#ifdef __cplusplus
-extern "C"
-{
+extern "C" {
#endif
- static void Notify(void *args, const Topic topic, Request *request);
-
- using namespace OHOS;
-
- Subscriber TraingSubscirber = {
- .identity = NULL,
- .args = NULL,
- .Notify = Notify,
- };
-
- void TraingSubscribeTopic(Topic topic)
- {
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "stepsubscribeTopic, topic=%u", topic);
- BroadcastApi *broadcastApi = NULL;
- IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME, BROADCAST_FEATURE_NAME);
- if (api == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stepsubscribeTopic, GetFeatureApi failed");
- return;
- }
- int result = api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi);
- if (result != 0 || broadcastApi == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stepsubscribeTopic, QueryInterface failed");
- return;
- }
- broadcastApi->SubscribeTopic((IUnknown *)broadcastApi, topic, &TraingSubscirber);
- broadcastApi->Release((IUnknown *)broadcastApi);
- }
+static void Notify(void *args, const Topic topic, Request *request);
+
+using namespace OHOS;
+
+Subscriber TraingSubscirber = {
+ .identity = NULL,
+ .args = NULL,
+ .Notify = Notify,
+};
+
+void TraingSubscribeTopic(Topic topic) {
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "stepsubscribeTopic, topic=%u", topic);
+ BroadcastApi *broadcastApi = NULL;
+ IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME,
+ BROADCAST_FEATURE_NAME);
+ if (api == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "stepsubscribeTopic, GetFeatureApi failed");
+ return;
+ }
+ int result =
+ api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi);
+ if (result != 0 || broadcastApi == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "stepsubscribeTopic, QueryInterface failed");
+ return;
+ }
+ broadcastApi->SubscribeTopic((IUnknown *)broadcastApi, topic,
+ &TraingSubscirber);
+ broadcastApi->Release((IUnknown *)broadcastApi);
+}
- void TraingUnsubscribeTopic(Topic topic)
- {
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TraingUnsubscribeTopic, topic=%u", topic);
- BroadcastApi *broadcastApi = NULL;
- IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME, BROADCAST_FEATURE_NAME);
- if (api == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingUnsubscribeTopic, GetFeatureApi failed");
- return;
- }
- int result = api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi);
- if (result != 0 || broadcastApi == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingUnsubscribeTopic, QueryInterface failed");
- return;
- }
- broadcastApi->UnsubscribeTopic((IUnknown *)broadcastApi, topic, &TraingSubscirber);
- broadcastApi->Release((IUnknown *)broadcastApi);
- }
- int flag = 0;
- static void Notify(void *args, const Topic topic, Request *request)
- {
- UNUSED(args);
- UNUSED(topic);
- if (request == NULL)
- {
- return;
- }
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "request %d\r\n", request->msgId);
- if (request->msgId == TOPIC_EVENT_ACTIVITY_UPDATE)
- {
+void TraingUnsubscribeTopic(Topic topic) {
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TraingUnsubscribeTopic, topic=%u",
+ topic);
+ BroadcastApi *broadcastApi = NULL;
+ IUnknown *api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE_NAME,
+ BROADCAST_FEATURE_NAME);
+ if (api == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "TraingUnsubscribeTopic, GetFeatureApi failed");
+ return;
+ }
+ int result =
+ api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi);
+ if (result != 0 || broadcastApi == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "TraingUnsubscribeTopic, QueryInterface failed");
+ return;
+ }
+ broadcastApi->UnsubscribeTopic((IUnknown *)broadcastApi, topic,
+ &TraingSubscirber);
+ broadcastApi->Release((IUnknown *)broadcastApi);
+}
+int flag = 0;
+static void Notify(void *args, const Topic topic, Request *request) {
+ UNUSED(args);
+ UNUSED(topic);
+ if (request == NULL) {
+ return;
+ }
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "request %d\r\n", request->msgId);
+ if (request->msgId == TOPIC_EVENT_ACTIVITY_UPDATE) {
#if BLETEST
- if (!flag)
- {
- training_ble *traingbleInfo = new training_ble();
- traingbleInfo->sportType = 1;
- traingbleInfo->controlmd = 0;
- TraingCardPresenter::GetInstance()->send_sport_cmd(traingbleInfo);
- delete traingbleInfo;
- flag = 1;
- }
-#endif
- cywee_activity_result_t *cyweeInfo = new cywee_activity_result_t();
- int rets = memcpy_s(cyweeInfo, sizeof(cywee_activity_result_t), (cywee_activity_result_t *)request->data, request->len);
- if (rets != EOK)
- {
- delete cyweeInfo; // 处理内存分配失败的情况
- cyweeInfo = NULL;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "memcpy_s cywee_activity_result_t fail ret = %d", rets);
- return;
- }
- TraingModel::GetInstance()->AnalysisData(cyweeInfo);
- delete cyweeInfo; // 释放内存
- }
- if (request->msgId == TOPIC_EVENT_ACTIVITY_EXTRA_INFO_UPDATE)
- {
- cywee_activity_result_extre_info_t *cyweeInfo_ext = new cywee_activity_result_extre_info_t();
- int rets = memcpy_s(cyweeInfo_ext, sizeof(cywee_activity_result_extre_info_t), (cywee_activity_result_extre_info_t *)request->data, request->len);
- if (rets != EOK)
- {
- delete cyweeInfo_ext; // 处理内存分配失败的情况
- cyweeInfo_ext = NULL;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "memcpy_s cywee_activity_result_extre_info_t fail ret = %d", rets);
- return;
- }
- TraingModel::GetInstance()->AnalysisExtraData(cyweeInfo_ext);
- delete cyweeInfo_ext; // 释放内存
- }
- if(request->msgId == TOPIC_EVENT_HEARTRATE_UPDATA)
- {
- uint8_t heart = *((u_int8_t*)(request->data)); // 进行类型转换
- TraingModel::GetInstance()->AnalysisHeartData(heart);
- }
- if (request->msgId == TOPIC_EVENT_BLE_TRAINING)
- {
- training_ble *traingbleInfo = new training_ble();
- int rets = memcpy_s(traingbleInfo, sizeof(training_ble), (training_ble *)request->data, request->len);
- if (rets != EOK)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "memcpy_s cywee_activity_result_t fail ret = %d", rets);
- return;
- }
- TraingCardPresenter::GetInstance()->send_sport_cmd(traingbleInfo);
- delete traingbleInfo;
- }
+ if (!flag) {
+ training_ble *traingbleInfo = new training_ble();
+ traingbleInfo->sportType = 1;
+ traingbleInfo->controlmd = 0;
+ TraingCardPresenter::GetInstance()->send_sport_cmd(traingbleInfo);
+ delete traingbleInfo;
+ flag = 1;
}
+#endif
+ cywee_activity_result_t *cyweeInfo = new cywee_activity_result_t();
+ int rets = memcpy_s(cyweeInfo, sizeof(cywee_activity_result_t),
+ (cywee_activity_result_t *)request->data, request->len);
+ if (rets != EOK) {
+ delete cyweeInfo; // 处理内存分配失败的情况
+ cyweeInfo = NULL;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "memcpy_s cywee_activity_result_t fail ret = %d", rets);
+ return;
+ }
+ TraingModel::GetInstance()->AnalysisData(cyweeInfo);
+ delete cyweeInfo; // 释放内存
+ }
+ if (request->msgId == TOPIC_EVENT_ACTIVITY_EXTRA_INFO_UPDATE) {
+ cywee_activity_result_extre_info_t *cyweeInfo_ext =
+ new cywee_activity_result_extre_info_t();
+ int rets = memcpy_s(
+ cyweeInfo_ext, sizeof(cywee_activity_result_extre_info_t),
+ (cywee_activity_result_extre_info_t *)request->data, request->len);
+ if (rets != EOK) {
+ delete cyweeInfo_ext; // 处理内存分配失败的情况
+ cyweeInfo_ext = NULL;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "memcpy_s cywee_activity_result_extre_info_t fail ret = %d",
+ rets);
+ return;
+ }
+ TraingModel::GetInstance()->AnalysisExtraData(cyweeInfo_ext);
+ delete cyweeInfo_ext; // 释放内存
+ }
+ if (request->msgId == TOPIC_EVENT_HEARTRATE_UPDATA) {
+ uint8_t heart = *((u_int8_t *)(request->data)); // 进行类型转换
+ TraingModel::GetInstance()->AnalysisHeartData(heart);
+ }
+ if (request->msgId == TOPIC_EVENT_BLE_TRAINING) {
+ training_ble *traingbleInfo = new training_ble();
+ int rets = memcpy_s(traingbleInfo, sizeof(training_ble),
+ (training_ble *)request->data, request->len);
+ if (rets != EOK) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "memcpy_s cywee_activity_result_t fail ret = %d", rets);
+ return;
+ }
+ TraingCardPresenter::GetInstance()->send_sport_cmd(traingbleInfo);
+ delete traingbleInfo;
+ }
+}
#ifdef __cplusplus
}
#endif
-namespace OHOS
-{
+namespace OHOS {
#if TIMER
- // 声明定时器变量
- static osTimerId_t g_startCounting = NULL; // 定时器
- static constexpr uint64_t MS_ONE_SECONDS = 1000;
- static int g_motionTimes{0};
- static constexpr int32 NUM_TEN = 10;
- static constexpr int16 ERROR = 0;
- static constexpr int16 SUCCESS = 1;
- static constexpr int16 NUM_TIME_MIN = 60;
- static constexpr int16 NUM_TIME_HOUR = 3600;
- static constexpr int32 NUM_TIME_DAY = 86400;
+// 声明定时器变量
+static osTimerId_t g_startCounting = NULL; // 定时器
+static constexpr uint64_t MS_ONE_SECONDS = 1000;
+static int g_motionTimes{0};
+static constexpr int32 NUM_TEN = 10;
+static constexpr int16 ERROR = 0;
+static constexpr int16 SUCCESS = 1;
+static constexpr int16 NUM_TIME_MIN = 60;
+static constexpr int16 NUM_TIME_HOUR = 3600;
+static constexpr int32 NUM_TIME_DAY = 86400;
#endif
- SportData *sportdata = new SportData();
- TraingModel ::TraingModel()
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::TraingModel()");
- // sportdata->Initialize(); // 初始化结构体
- }
- TraingModel ::~TraingModel()
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::~TraingModel()");
- TraingUnsubscribeTopic(TOPIC_EVENT_ACTIVITY_UPDATE); // 取消订阅
- TraingUnsubscribeTopic(TOPIC_EVENT_BLE_TRAINING);
- TraingUnsubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA);
- TraingUnsubscribeTopic(TOPIC_EVENT_ACTIVITY_EXTRA_INFO_UPDATE);
- }
- TraingModel *TraingModel::GetInstance(void)
- {
- static TraingModel instance;
- return &instance;
- }
-
- void TraingModel ::Init()
- {
- TraingSubscribeTopic(TOPIC_EVENT_ACTIVITY_UPDATE); // 进行消息订阅
- TraingSubscribeTopic(TOPIC_EVENT_BLE_TRAINING);
- TraingSubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA);
- TraingSubscribeTopic(TOPIC_EVENT_ACTIVITY_EXTRA_INFO_UPDATE);
- }
- /*设置运动类型*/
- void TraingModel::SetSportType(Exercisetype type)
- {
- sportType_ = type;
- }
- /*结束数据icon*/
- std::string sportImages[8] = {
- FITNESS_54_IMAGE,
- DANCE_54_IMAGE,
- REST_54_IMAGE,
- BALL_54_IMAGE,
- SWIMMING_54_IMAGE,
- ICE_54_IMAGE,
- LIMIT_54_IMAGE,
- OTHER_54_IMAGE,
- };
- /*训练记录Icon*/
- std::string sportIcons[8] = {
- FITNESS_IMAGE,
- DANCE_IMAGE,
- REST_IMAGE,
- BALL_IMAGE,
- SWIMMING_IMAGE,
- ICE_IMAGE,
- LIMIT_IMAGE,
- OTHER_IMAGE,
- };
- /*获取训练Id->协议*/
- int TraingModel::GetBleSportId(Exercisetype sporttype, UIResourceTextId id)
- {
- int offset = 0;
-
- switch (sporttype)
- {
- case Exercisetype::FITNESS: // 0~57
- offset = 0;
- break;
- case Exercisetype::DANCE: // 0~9
- offset = 58;
- break;
- case Exercisetype::LEISURE: // 0~23
- offset = 58 + 10;
- break;
- case Exercisetype::BALL: // 0~28
- offset = 58 + 10 + 24;
- break;
- case Exercisetype::WATER: // 0~23
- offset = 58 + 10 + 24 + 29;
- break;
- case Exercisetype::ICE: // 0~11
- offset = 58 + 10 + 24 + 29 + 24;
- break;
- case Exercisetype::EXTREME: // 0~9
- offset = 58 + 10 + 24 + 29 + 24 + 12;
- break;
- case Exercisetype::OTHER: // 0~8
- offset = 58 + 10 + 24 + 29 + 24 + 12 + 10;
- break;
- default:
- offset = 0;
- break;
- }
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " offset %d id %d", offset, id);
- return id - offset;
- }
- /*获取运动类型图片*/
- std::string TraingModel::GetSportType(Exercisetype sporttype)
- {
- int index = static_cast<int>(sporttype);
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportType index %d", index);
- return sportImages[index];
- }
- /*获取运动类型icon*/
- std::string TraingModel::GetSportIcon(Exercisetype sporttype)
- {
- int index = static_cast<int>(sporttype);
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportIcon index %d", index);
- return sportIcons[static_cast<int>(sporttype)];
- }
- /*设置运动Id*/
- void TraingModel::SetSportEvent(UIResourceTextId id)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " SetSportType %d", sportId_);
- IsSpecialSport(id); // 设置特殊性
- sportId_ = id;
- }
- /*获取运动Id*/
- UIResourceTextId TraingModel::GetSportEvent()
- {
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportEvent %d", sportId_);
- return sportId_;
- }
- /*获取运动项目*/
- ExerciseClass TraingModel::GetSportId()
- {
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportType %d", sportId_);
- // 设置结构体里面的运动类型
- sportdata->sportId = sportId_;
- sportdata->sportType = sportType_;
-
- switch (sportId_)
- {
- // 室外跑步 室外走路
- case UIResourceTextId::STR_EXERCISE_OUTDOORRUNNING:
- case UIResourceTextId::STR_EXERCISE_OUTDOORWALKING:
- return ExerciseClass::OUTDOOR;
-
- // 室内跑步 室内走路
- case UIResourceTextId::STR_EXERCISE_INDOORRUNNING:
- case UIResourceTextId::STR_EXERCISE_INDOORWALKING:
- return ExerciseClass::INDOOR;
-
- // 跑步机
- case UIResourceTextId::STR_EXERCISE_TREADMILL:
- case UIResourceTextId::STR_EXERCISE_STROLLMACHINE:
- return ExerciseClass::TREADMILL;
-
- // 自由训练
- default:
- return ExerciseClass::FREE_TRAINING;
- }
- }
- /*判断是否为特殊运动*/
- void TraingModel::IsSpecialSport(UIResourceTextId sportId_)
- {
- switch (sportId_)
- {
- case UIResourceTextId::STR_EXERCISE_OUTDOORRUNNING: // 室外跑步 室外走路
- case UIResourceTextId::STR_EXERCISE_OUTDOORWALKING:
- case UIResourceTextId::STR_EXERCISE_INDOORRUNNING: // 室内跑步 室内走路
- case UIResourceTextId::STR_EXERCISE_INDOORWALKING:
- case UIResourceTextId::STR_EXERCISE_TREADMILL: // 跑步机
- case UIResourceTextId::STR_EXERCISE_STROLLMACHINE:
- isspecialsport_ = true;
- break;
- default: // 自由训练
- isspecialsport_ = false;
- break;
- }
- }
-
- bool TraingModel::GetIsSpecial()
- {
- return isspecialsport_;
- }
- /*获取目标字符串*/
- std::string TraingModel::GetTagStr()
- {
- /*
- 通用目标配置: 时长、卡路里
- 不通用目标配置: 步数、距离
+SportData *sportdata = new SportData();
+TraingModel ::TraingModel() {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::TraingModel()");
+ // sportdata->Initialize(); // 初始化结构体
+}
+TraingModel ::~TraingModel() {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::~TraingModel()");
+ TraingUnsubscribeTopic(TOPIC_EVENT_ACTIVITY_UPDATE); // 取消订阅
+ TraingUnsubscribeTopic(TOPIC_EVENT_BLE_TRAINING);
+ TraingUnsubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA);
+ TraingUnsubscribeTopic(TOPIC_EVENT_ACTIVITY_EXTRA_INFO_UPDATE);
+}
+TraingModel *TraingModel::GetInstance(void) {
+ static TraingModel instance;
+ return &instance;
+}
- 如果配置项是特殊目标
- -> 普通训练: 无训练目标
- -> 特殊训练: 有训练目标
- */
+void TraingModel ::Init() {
+ TraingSubscribeTopic(TOPIC_EVENT_ACTIVITY_UPDATE); // 进行消息订阅
+ TraingSubscribeTopic(TOPIC_EVENT_BLE_TRAINING);
+ TraingSubscribeTopic(TOPIC_EVENT_HEARTRATE_UPDATA);
+ TraingSubscribeTopic(TOPIC_EVENT_ACTIVITY_EXTRA_INFO_UPDATE);
+}
+/*设置运动类型*/
+void TraingModel::SetSportType(Exercisetype type) { sportType_ = type; }
+/*结束数据icon*/
+std::string sportImages[8] = {
+ FITNESS_54_IMAGE, DANCE_54_IMAGE, REST_54_IMAGE, BALL_54_IMAGE,
+ SWIMMING_54_IMAGE, ICE_54_IMAGE, LIMIT_54_IMAGE, OTHER_54_IMAGE,
+};
+/*训练记录Icon*/
+std::string sportIcons[8] = {
+ FITNESS_IMAGE, DANCE_IMAGE, REST_IMAGE, BALL_IMAGE,
+ SWIMMING_IMAGE, ICE_IMAGE, LIMIT_IMAGE, OTHER_IMAGE,
+};
+/*获取训练Id->协议*/
+int TraingModel::GetBleSportId(Exercisetype sporttype, UIResourceTextId id) {
+ int offset = 0;
+
+ switch (sporttype) {
+ case Exercisetype::FITNESS: // 0~57
+ offset = 0;
+ break;
+ case Exercisetype::DANCE: // 0~9
+ offset = 58;
+ break;
+ case Exercisetype::LEISURE: // 0~23
+ offset = 58 + 10;
+ break;
+ case Exercisetype::BALL: // 0~28
+ offset = 58 + 10 + 24;
+ break;
+ case Exercisetype::WATER: // 0~23
+ offset = 58 + 10 + 24 + 29;
+ break;
+ case Exercisetype::ICE: // 0~11
+ offset = 58 + 10 + 24 + 29 + 24;
+ break;
+ case Exercisetype::EXTREME: // 0~9
+ offset = 58 + 10 + 24 + 29 + 24 + 12;
+ break;
+ case Exercisetype::OTHER: // 0~8
+ offset = 58 + 10 + 24 + 29 + 24 + 12 + 10;
+ break;
+ default:
+ offset = 0;
+ break;
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " offset %d id %d", offset, id);
+ return id - offset;
+}
+/*获取运动类型图片*/
+std::string TraingModel::GetSportType(Exercisetype sporttype) {
+ int index = static_cast<int>(sporttype);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportType index %d", index);
+ return sportImages[index];
+}
+/*获取运动类型icon*/
+std::string TraingModel::GetSportIcon(Exercisetype sporttype) {
+ int index = static_cast<int>(sporttype);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportIcon index %d", index);
+ return sportIcons[static_cast<int>(sporttype)];
+}
+/*设置运动Id*/
+void TraingModel::SetSportEvent(UIResourceTextId id) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " SetSportType %d", sportId_);
+ IsSpecialSport(id); // 设置特殊性
+ sportId_ = id;
+}
+/*获取运动Id*/
+UIResourceTextId TraingModel::GetSportEvent() {
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportEvent %d", sportId_);
+ return sportId_;
+}
+/*获取运动项目*/
+ExerciseClass TraingModel::GetSportId() {
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " GetSportType %d", sportId_);
+ // 设置结构体里面的运动类型
+ sportdata->sportId = sportId_;
+ sportdata->sportType = sportType_;
+
+ switch (sportId_) {
+ // 室外跑步 室外走路
+ case UIResourceTextId::STR_EXERCISE_OUTDOORRUNNING:
+ case UIResourceTextId::STR_EXERCISE_OUTDOORWALKING:
+ // return ExerciseClass::OUTDOOR; 统一使用室内
+
+ // 室内跑步 室内走路
+ case UIResourceTextId::STR_EXERCISE_INDOORRUNNING:
+ case UIResourceTextId::STR_EXERCISE_INDOORWALKING:
+ return ExerciseClass::INDOOR;
+
+ // 跑步机
+ case UIResourceTextId::STR_EXERCISE_TREADMILL:
+ case UIResourceTextId::STR_EXERCISE_STROLLMACHINE:
+ return ExerciseClass::TREADMILL;
+
+ // 自由训练
+ default:
+ return ExerciseClass::FREE_TRAINING;
+ }
+}
+/*判断是否为特殊运动*/
+void TraingModel::IsSpecialSport(UIResourceTextId sportId_) {
+ switch (sportId_) {
+ case UIResourceTextId::STR_EXERCISE_OUTDOORRUNNING: // 室外跑步 室外走路
+ case UIResourceTextId::STR_EXERCISE_OUTDOORWALKING:
+ case UIResourceTextId::STR_EXERCISE_INDOORRUNNING: // 室内跑步 室内走路
+ case UIResourceTextId::STR_EXERCISE_INDOORWALKING:
+ case UIResourceTextId::STR_EXERCISE_TREADMILL: // 跑步机
+ case UIResourceTextId::STR_EXERCISE_STROLLMACHINE:
+ isspecialsport_ = true;
+ break;
+ default: // 自由训练
+ isspecialsport_ = false;
+ break;
+ }
+}
- std::string tagStr;
+bool TraingModel::GetIsSpecial() { return isspecialsport_; }
+/*获取目标字符串*/
+std::string TraingModel::GetTagStr() {
+ /*
+ 通用目标配置: 时长、卡路里
+ 不通用目标配置: 步数、距离
- switch (sportTagType_)
- {
- case ExerciseTag::Duration:
- tagStr = std::to_string(sportTag_) + " min"; // 时长目标
- break;
+ 如果配置项是特殊目标
+ -> 普通训练: 无训练目标
+ -> 特殊训练: 有训练目标
+ */
- case ExerciseTag::Calories:
- tagStr = std::to_string(sportTag_) + " kcal"; // 卡路里目标
- break;
+ std::string tagStr;
- case ExerciseTag::Steps:
- case ExerciseTag::Distance:
- if (isspecialsport_) // 检查是否为特殊训练
- {
- // 只在特殊训练模式下使用步数和距离目标
- if (sportTagType_ == ExerciseTag::Steps)
- {
- tagStr = std::to_string(sportTag_) + " steps"; // 步数目标
- }
- else
- {
- tagStr = std::to_string(sportTag_) + " km"; // 距离目标
- }
- }
- else
- {
- tagStr = ""; // 普通训练下不使用目标
- }
- break;
+ switch (sportTagType_) {
+ case ExerciseTag::Duration:
+ tagStr = std::to_string(sportTag_) + " min"; // 时长目标
+ break;
- default:
- tagStr = ""; // 未知目标类型
- break;
- }
+ case ExerciseTag::Calories:
+ tagStr = std::to_string(sportTag_) + " kcal"; // 卡路里目标
+ break;
- return tagStr;
- }
- /*设置运动状态*/
- void TraingModel::SetSportState(ExerciseState state)
- {
- if (state != ExerciseState::General)
- {
- /*运动开始并且是app发起的运动*/
- if (Openingway == true && state != ExerciseState::End)
- {
- sendtraningstatedata(static_cast<uint8_t>(state), sportdata->duration);
- }
- }
- sportState_ = state;
- }
- /*获取运动状态*/
- ExerciseState TraingModel::GetSportState()
- {
- return sportState_;
- }
- // 计算平均心率的函数
- double CalculateAverageHeartRate(const std::vector<int> &heartRates)
+ case ExerciseTag::Steps:
+ case ExerciseTag::Distance:
+ if (isspecialsport_) // 检查是否为特殊训练
{
- if (heartRates.size() <= 2)
- {
- // 如果心率数据点少于等于2,无法去掉最高和最低值
- return 0.0; // 或者返回心率的平均值
- }
-
- // 创建一个副本以避免修改原始数据
- std::vector<int> sortedHeartRates = heartRates;
-
- // 排序
- std::sort(sortedHeartRates.begin(), sortedHeartRates.end());
-
- // 去掉一个最高值和一个最低值
- sortedHeartRates.erase(sortedHeartRates.begin()); // 去掉最低值
- sortedHeartRates.pop_back(); // 去掉最高值
-
- // 计算剩余心率的平均值
- double sum = 0;
- for (int rate : sortedHeartRates)
- {
- sum += rate;
- }
-
- return sum / sortedHeartRates.size(); // 返回平均值
+ // 只在特殊训练模式下使用步数和距离目标
+ if (sportTagType_ == ExerciseTag::Steps) {
+ tagStr = std::to_string(sportTag_) + " steps"; // 步数目标
+ } else {
+ tagStr = std::to_string(sportTag_) + " km"; // 距离目标
+ }
+ } else {
+ tagStr = ""; // 普通训练下不使用目标
}
- /*分析数据*/
- void TraingModel::AnalysisData(cywee_activity_result_t *cyweeInfo)
- {
- // 不同的运动类型解析不同的数据
- // 通用数据
- sportdata->steps = cyweeInfo->steps;
- sportdata->distance = cyweeInfo->distance;
- sportdata->calories = cyweeInfo->calories;
+ break;
- // sportdata->cdc = cyweeInfo->step_frequency;
- // sportdata->std = cyweeInfo->step_length;
+ default:
+ tagStr = ""; // 未知目标类型
+ break;
+ }
- sportdata->pc = cyweeInfo->pace;
-
- // 更新最慢配速
- if (sportdata->spc < sportdata->pc)
- {
- sportdata->spc = sportdata->pc;
- }
-
-
-
- // 计算平均心率
- if (sportdata->heart > 50)
- {
- sportdata->avgheart = Averageheartrate(sportdata->heart);
- }
-
- // 心率提醒
- int maxHeartRate = ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_TRAINING_HEART_MAX);
- if (sportdata->heart >= maxHeartRate)
- {
- uapi_set_screen_on_api(); // 亮屏检测
- if (true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb() && (!uapi_sleep_mode_flag_get()))
- {
- ui_api_vibrate_once_func();
- }
- TraingCardView::GetInstance()->SetPopupViewStatus(HeartPopup, true);
- }
-
- // 训练目标检查
- if (sportdata->tag && !Gettagstuats)
- {
- sportdata->goaldegree = GetGoaldegree();
-
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "sportdata->goaldegree %d", sportdata->goaldegree);
- if (sportdata->goaldegree == 100)
- {
- // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "currentdata%d", currentdata);
- uapi_set_screen_on_api(); // 亮屏检测
- if (true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb())
- {
- ui_api_vibrate_once_func();
- }
- TraingCardView::GetInstance()->SetPopupViewStatus(GetTagPopup, true);
- TraingCardView::GetInstance()->GetAnimator()->Start();
- Gettagstuats = true;
- }
- }
+ return tagStr;
+}
+/*设置运动状态*/
+void TraingModel::SetSportState(ExerciseState state) {
+ if (state != ExerciseState::General) {
+ /*运动开始并且是app发起的运动*/
+ if (Openingway == true && state != ExerciseState::End) {
+ sendtraningstatedata(static_cast<uint8_t>(state), sportdata->duration);
+ }
+ }
+ sportState_ = state;
+}
+/*获取运动状态*/
+ExerciseState TraingModel::GetSportState() { return sportState_; }
+// 计算平均心率的函数
+double CalculateAverageHeartRate(const std::vector<int> &heartRates) {
+ if (heartRates.size() <= 2) {
+ // 如果心率数据点少于等于2,无法去掉最高和最低值
+ return 0.0; // 或者返回心率的平均值
+ }
+
+ // 创建一个副本以避免修改原始数据
+ std::vector<int> sortedHeartRates = heartRates;
+
+ // 排序
+ std::sort(sortedHeartRates.begin(), sortedHeartRates.end());
+
+ // 去掉一个最高值和一个最低值
+ sortedHeartRates.erase(sortedHeartRates.begin()); // 去掉最低值
+ sortedHeartRates.pop_back(); // 去掉最高值
+
+ // 计算剩余心率的平均值
+ double sum = 0;
+ for (int rate : sortedHeartRates) {
+ sum += rate;
+ }
+
+ return sum / sortedHeartRates.size(); // 返回平均值
+}
+/*分析数据*/
+void TraingModel::AnalysisData(cywee_activity_result_t *cyweeInfo) {
+ // 不同的运动类型解析不同的数据
+ // 通用数据
+ sportdata->steps = cyweeInfo->steps;
+ sportdata->distance = cyweeInfo->distance;
+ sportdata->calories = cyweeInfo->calories;
+
+ // sportdata->cdc = cyweeInfo->step_frequency;
+ // sportdata->std = cyweeInfo->step_length;
+
+ sportdata->pc = cyweeInfo->pace;
+
+ // 更新最慢配速
+ if (sportdata->spc < sportdata->pc) {
+ sportdata->spc = sportdata->pc;
+ }
+
+ // 计算平均心率
+ if (sportdata->heart > 50) {
+ sportdata->avgheart = Averageheartrate(sportdata->heart);
+ }
+
+ // 心率提醒
+ int maxHeartRate = ConfigModel::GetInstance()->get_configData_int(
+ ConfigModel::CONFIGMODEL_ITEM_TRAINING_HEART_MAX);
+ if (sportdata->heart >= maxHeartRate) {
+ uapi_set_screen_on_api(); // 亮屏检测
+ if (true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb() &&
+ (!uapi_sleep_mode_flag_get())) {
+ ui_api_vibrate_once_func();
+ }
+ TraingCardView::GetInstance()->SetPopupViewStatus(HeartPopup, true);
+ }
+
+ // 训练目标检查
+ if (sportdata->tag && !Gettagstuats) {
+ sportdata->goaldegree = GetGoaldegree();
+
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "sportdata->goaldegree %d",
+ sportdata->goaldegree);
+ if (sportdata->goaldegree == 100) {
+ // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "currentdata%d", currentdata);
+ uapi_set_screen_on_api(); // 亮屏检测
+ if (true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb()) {
+ ui_api_vibrate_once_func();
+ }
+ TraingCardView::GetInstance()->SetPopupViewStatus(GetTagPopup, true);
+ TraingCardView::GetInstance()->GetAnimator()->Start();
+ Gettagstuats = true;
}
+ }
+}
#if 0
int avg_step_freq;//平均步频
int distance_motion;//体感距离
#endif
- /*分析activity extra info数据*/
- void TraingModel::AnalysisExtraData(cywee_activity_result_extre_info_t *cyweeInfo)
- {
- sportdata->apc = cyweeInfo->avg_pace;
- sportdata->fpc = cyweeInfo->max_pace;
- sportdata->cdc = cyweeInfo->avg_step_freq;
- sportdata->std = cyweeInfo->avg_step_len * 100; // 前者cm 后者m
- }
- /*分析运动心率数据*/
- void TraingModel::AnalysisHeartData(u_int8_t hrs)
- {
- sportdata->heart = hrs;
- SetIntensity(sportdata->heart); // 设置训练强度
- }
-
- /*打印函数*/
- void TraingModel::printf_data(SportData *data)
- {
- /*打印测试一下数据*/
- printf("\r\n****************************************\r\n");
- printf("Sport type: %d\n", data->sportType);
- printf("Sport ID: %d\n", data->sportId);
- printf("Start date: %s\n", data->start_date.c_str());
- printf("Start time: %s\n", data->start_time.c_str());
- printf("End time: %s\n", data->end_time.c_str());
- printf("Goal degree: %d\n", data->goaldegree);
- printf("Duration: %d\n", data->duration);
- printf("Distance: %d\n", data->distance);
- printf("Average heart rate: %d\n", data->avgheart);
- printf("Steps: %d\n", data->steps);
- printf("Intensity: %d\n", data->intensity);
- printf("\r\n****************************************\r\n");
- }
- /*获取数据*/
- SportData *TraingModel::GetSportdata()
- {
- // printf_data(sportdata);
- return sportdata;
- }
- /* 设置训练数据[为训练记录准备] */
- void TraingModel::SetSportdata(SportData *data)
- {
- if (data != nullptr && sportdata != nullptr)
- {
- sportdata->sportType = data->sportType;
- sportdata->sportId = data->sportId;
- sportdata->start_date = data->start_date;
- sportdata->start_time = data->start_time;
- sportdata->end_time = data->end_time;
- sportdata->goaldegree = data->goaldegree;
- sportdata->duration = data->duration;
- sportdata->distance = data->distance;
- sportdata->avgheart = data->avgheart;
- sportdata->steps = data->steps;
- sportdata->intensity = data->intensity;
- sportdata->apc = data->apc;
- sportdata->fpc = data->fpc;
- sportdata->spc = data->spc;
- sportdata->std = data->std;
- sportdata->cdc = data->cdc;
- printf_data(data);
- IsSpecialSport(sportdata->sportId); // 配置训练特殊性
- }
- }
- /*获取训练卡路里*/
- int TraingModel::GetCal()
- {
- return sportdata->calories;
- }
- /*获取训练目标*/
- int TraingModel::GetSportTag()
- {
- return sportdata->tag;
- }
- /*获取训练项目类型*/
- ExerciseTag TraingModel::GetSportTagtype()
- {
- return sportdata->sportTagType;
- }
- /*重置训练配置*/
- void TraingModel::ResetSharedTrainingData()
- {
- sportdata->Reset(); // 重置结构体
- heartRateData.clear(); // 清空心率数据
- recentHeartRates.clear();
- delayed.clear(); // 重置 delayed 字典
-
- while (!maxHeap.empty())
- { // 清空最大堆
- maxHeap.pop();
- }
- while (!minHeap.empty())
- { // 清空最小堆
- minHeap.pop();
- }
-
- totalHeartRate = 0;
- countHeartRate = 0;
+/*分析activity extra info数据*/
+void TraingModel::AnalysisExtraData(
+ cywee_activity_result_extre_info_t *cyweeInfo) {
+ sportdata->apc = cyweeInfo->avg_pace;
+ sportdata->fpc = cyweeInfo->max_pace;
+ sportdata->cdc = cyweeInfo->avg_step_freq;
+ sportdata->std = cyweeInfo->avg_step_len * 100; // 前者cm 后者m
+}
+/*分析运动心率数据*/
+void TraingModel::AnalysisHeartData(u_int8_t hrs) {
+ sportdata->heart = hrs;
+ SetIntensity(sportdata->heart); // 设置训练强度
+}
- Gettagstuats = false; // 重置训练达标标志位
- Openstate = true; // 开启运动开始标志位
- }
+/*打印函数*/
+void TraingModel::printf_data(SportData *data) {
+ /*打印测试一下数据*/
+ printf("\r\n****************************************\r\n");
+ printf("Sport type: %d\n", data->sportType);
+ printf("Sport ID: %d\n", data->sportId);
+ printf("Start date: %s\n", data->start_date.c_str());
+ printf("Start time: %s\n", data->start_time.c_str());
+ printf("End time: %s\n", data->end_time.c_str());
+ printf("Goal degree: %d\n", data->goaldegree);
+ printf("Duration: %d\n", data->duration);
+ printf("Distance: %d\n", data->distance);
+ printf("Average heart rate: %d\n", data->avgheart);
+ printf("Steps: %d\n", data->steps);
+ printf("Intensity: %d\n", data->intensity);
+ printf("\r\n****************************************\r\n");
+}
+/*获取数据*/
+SportData *TraingModel::GetSportdata() {
+ // printf_data(sportdata);
+ return sportdata;
+}
+/* 设置训练数据[为训练记录准备] */
+void TraingModel::SetSportdata(SportData *data) {
+ if (data != nullptr && sportdata != nullptr) {
+ sportdata->sportType = data->sportType;
+ sportdata->sportId = data->sportId;
+ sportdata->start_date = data->start_date;
+ sportdata->start_time = data->start_time;
+ sportdata->end_time = data->end_time;
+ sportdata->goaldegree = data->goaldegree;
+ sportdata->duration = data->duration;
+ sportdata->distance = data->distance;
+ sportdata->avgheart = data->avgheart;
+ sportdata->steps = data->steps;
+ sportdata->intensity = data->intensity;
+ sportdata->apc = data->apc;
+ sportdata->fpc = data->fpc;
+ sportdata->spc = data->spc;
+ sportdata->std = data->std;
+ sportdata->cdc = data->cdc;
+ printf_data(data);
+ IsSpecialSport(sportdata->sportId); // 配置训练特殊性
+ }
+}
+/*获取训练卡路里*/
+int TraingModel::GetCal() { return sportdata->calories; }
+/*获取训练目标*/
+int TraingModel::GetSportTag() { return sportdata->tag; }
+/*获取训练项目类型*/
+ExerciseTag TraingModel::GetSportTagtype() { return sportdata->sportTagType; }
+/*重置训练配置*/
+void TraingModel::ResetSharedTrainingData() {
+ sportdata->Reset(); // 重置结构体
+ heartRateData.clear(); // 清空心率数据
+
+ ClearPaceTable(); //重置配速数据
+ ClearHeartTable(); // 清空心率数据
+
+ recentHeartRates.clear();
+ delayed.clear(); // 重置 delayed 字典
+
+ while (!maxHeap.empty()) { // 清空最大堆
+ maxHeap.pop();
+ }
+ while (!minHeap.empty()) { // 清空最小堆
+ minHeap.pop();
+ }
+
+ totalHeartRate = 0;
+ countHeartRate = 0;
+ heartcount = 0;
+
+ Gettagstuats = false; // 重置训练达标标志位
+ Openstate = true; // 开启运动开始标志位
+}
- /*设置运动开始与结束*/
- void TraingModel::SetTimestamp()
- {
- uint32_t time;
- if (uapi_get_timestampe_ss(&time) != ERRCODE_SUCC)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to get timestamp");
- return;
- }
+/*设置运动开始与结束*/
+void TraingModel::SetTimestamp() {
+ uint32_t time;
+ if (uapi_get_timestampe_ss(&time) != ERRCODE_SUCC) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to get timestamp");
+ return;
+ }
- ExerciseState currentState = GetSportState(); // 获取当前运动状态
+ ExerciseState currentState = GetSportState(); // 获取当前运动状态
- // 增加标志位互斥保障"开始"和"结束"的唯一性操作
- if (currentState == ExerciseState::Start && !Startstate)
- {
- // 设置训练 runtime 为 1 训练中
- uapi_dev_runtime_set_train_status(1);
+ // 增加标志位互斥保障"开始"和"结束"的唯一性操作
+ if (currentState == ExerciseState::Start && !Startstate) {
+ // 设置训练 runtime 为 1 训练中
+ uapi_dev_runtime_set_train_status(1);
- ResetSharedTrainingData(); // 重置共享训练数据
+ ResetSharedTrainingData(); // 重置共享训练数据
- printf("SetTimestamp::time:%u \r\n", time);
- sportdata->starttime = time;
- sportdata->sportType = sportType_; // 训练类型
- sportdata->sportId = sportId_;
- IsSpecialSport(sportdata->sportId); // 配置运动特殊性状态
+ printf("SetTimestamp::time:%u \r\n", time);
+ sportdata->starttime = time;
+ sportdata->sportType = sportType_; // 训练类型
+ sportdata->sportId = sportId_;
+ IsSpecialSport(sportdata->sportId); // 配置运动特殊性状态
- if (sportTag_) // 有值才设置[训练目标]
- {
- sportdata->sportTagType = sportTagType_;
- sportdata->tag = sportTag_;
- }
+ if (sportTag_) // 有值才设置[训练目标]
+ {
+ sportdata->sportTagType = sportTagType_;
+ sportdata->tag = sportTag_;
+ }
- (Openingway == true) ? (printf("app发起运动\n")) : (printf("手表发起运动\n"));
+ (Openingway == true) ? (printf("app发起运动\n"))
+ : (printf("手表发起运动\n"));
- // 设置起始日期和时间
- SetStartDateTime();
+ // 设置起始日期和时间
+ SetStartDateTime();
- Startstate = true;
- Endstate = false; // 确保"开始"和"结束"状态互斥
+ Startstate = true;
+ Endstate = false; // 确保"开始"和"结束"状态互斥
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "开始运动");
- }
- else if (currentState == ExerciseState::End && !Endstate)
- {
- // 设置训练 runtime 为 0 训练结束
- uapi_dev_runtime_set_train_status(0);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "开始运动");
+ } else if (currentState == ExerciseState::End && !Endstate) {
+ // 设置训练 runtime 为 0 训练结束
+ uapi_dev_runtime_set_train_status(0);
- sportdata->endtime = time;
+ sportdata->endtime = time;
- SetEndTime();
+ SetEndTime();
- sportState_ = ExerciseState::General;
- Openstate = false; // 关闭运动标志位
+ sportState_ = ExerciseState::General;
+ Openstate = false; // 关闭运动标志位
- // 记录运动数据
- RecordSportData();
+ // 记录运动数据
+ RecordSportData();
- Startstate = false;
- Endstate = true;
+ Startstate = false;
+ Endstate = true;
#if 0
// 重置训练目标 [发生在训练前]
sportTag_ = 0;
sportTagType_ = ExerciseTag::UNKNOW;
#endif
- /*运动结束并且是手表发起的运动*/
- if (Openingway == false)
- {
- sendtraningstateend();
- }
- /*运动结束并且是app发起的运动*/
- else
- {
- sendtraningstatedata(0, sportdata->duration);
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "结束运动");
- }
- }
- /*设置开始时间*/
- void TraingModel::SetStartDateTime()
- {
- std::string startDate, startTime;
-
- if (!GetFormattedDate(startDate, "Failed to get start date"))
- return;
- if (!GetFormattedTime(startTime, "Failed to get start time"))
- return;
-
- sportdata->start_date = startDate;
- sportdata->start_time = startTime;
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "sportdata->start_time [%s]\r\n", sportdata->start_time.c_str());
- }
- /*设置结束时间*/
- void TraingModel::SetEndTime()
- {
- std::string endTime;
-
- if (GetFormattedTime(endTime, "Failed to get end time"))
- {
- sportdata->end_time = endTime;
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "sportdata->end_time [%s]\r\n", sportdata->end_time.c_str());
- }
- /*获取日期字符串*/
- bool TraingModel::GetFormattedDate(std::string &dateOutput, const char *errorMsg)
- {
- char *date = (char *)malloc(9 * sizeof(char)); // 分配内存给start_date
- if (uapi_get_YYMMDD_Time(date, '/') != ERRCODE_SUCC)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s", errorMsg);
- free(date);
- return false;
- }
- dateOutput = std::string(date);
- free(date); // 释放内存
- return true;
- }
- /*获取时间字符串*/
- bool TraingModel::GetFormattedTime(std::string &timeOutput, const char *errorMsg)
- {
- char *time = (char *)malloc(9 * sizeof(char)); // 分配内存给start_time
- if (uapi_get_HHMMSS_Time(time, ':', true) != ERRCODE_SUCC)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s", errorMsg);
- free(time);
- return false;
- }
- timeOutput = std::string(time);
- free(time); // 释放内存
- return true;
- }
- /*保存数据*/
- void TraingModel::RecordSportData()
- {
-#if READTEST
- if (SaveSportData() == false)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSportData error!");
- }
-#else
- if (MomentumFlag)
- {
- // GetGoaldegree(); // 设置目标完成度
- if (SaveSportData())
- {
- TraingRecordModel::GetInstance().SetJsonStatus(true);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSportData ok!");
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSportData error!");
- }
- }
-#endif
- }
- // 获取训练时长时间
- std::string TraingModel::GetTrainingTime()
- {
- int hour = sportdata->duration / NUM_TIME_HOUR;
- int min = (sportdata->duration % NUM_TIME_HOUR) / NUM_TIME_MIN;
- int sec = (sportdata->duration % NUM_TIME_HOUR) % NUM_TIME_MIN;
-
- std::ostringstream oss;
- oss << std::setfill('0') << std::setw(2) << hour << ":" << std::setw(2) << min << ":" << std::setw(2) << sec;
-
- std::string triningtime = oss.str();
- return triningtime;
- }
- /*解析时间戳 返回例如:13:00:22*/
- std::string TraingModel::AnalysisTimestamp(uint64_t timestamp)
- {
- // 将时间戳转换为小时、分钟、秒
- int hours = timestamp / 3600000; // 1小时 = 3600000毫秒
- int minutes = (timestamp % 3600000) / 60000; // 1分钟 = 60000毫秒
- int seconds = (timestamp % 60000) / 1000; // 1秒 = 1000毫秒
-
- // 将小时、分钟、秒转换为字符串
- std::string hoursStr = std::to_string(hours);
- std::string minutesStr = std::to_string(minutes);
- std::string secondsStr = std::to_string(seconds);
-
- // 格式化输出为 HH:MM:SS
- std::stringstream ss;
- ss << std::setfill('0') << std::setw(2) << hoursStr << ":" << std::setw(2) << minutesStr << ":" << std::setw(2) << secondsStr;
-
- return ss.str();
- }
- int TraingModel::CalculateAverageHeartRate(int newHeartRate)
- {
- // 将新的心率添加到数据列表
- heartRateData.push_back(newHeartRate);
- totalHeartRate += newHeartRate;
- countHeartRate++;
-
- // 将新的心率插入到堆中
- maxHeap.push(newHeartRate);
- minHeap.push(newHeartRate);
-
- // 如果超过窗口大小,移除最早的心率
- if (heartRateData.size() > windowSize)
- {
- int oldestRate = heartRateData[0];
- totalHeartRate -= oldestRate;
- countHeartRate--;
-
- // 将老旧值从列表中移除
- heartRateData.erase(heartRateData.begin());
-
- // 标记老旧值为待删除
- delayed[oldestRate]++;
- }
-
- // 清理堆中的老旧值
- while (!maxHeap.empty() && delayed[maxHeap.top()] > 0)
- {
- delayed[maxHeap.top()]--;
- maxHeap.pop();
- }
-
- while (!minHeap.empty() && delayed[minHeap.top()] > 0)
- {
- delayed[minHeap.top()]--;
- minHeap.pop();
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "新心率: %d, 当前心率总和: %d, 心率计数: %d",
- newHeartRate, totalHeartRate, countHeartRate);
-
- // 如果心率数量少于 3,直接返回当前的平均值
- if (countHeartRate < 3)
- {
- return totalHeartRate / countHeartRate; // 无法去除最大最小值
- }
-
- // 取出当前未被删除的最大和最小的心率
- int maxRate = maxHeap.top();
- int minRate = minHeap.top();
-
- // 进行去极值后的平均计算
- int average = (totalHeartRate - maxRate - minRate) / (countHeartRate - 2);
-
- // 打印计算结果
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "去极值后的平均心率: %d (去掉最大值: %d, 去掉最小值: %d)",
- average, maxRate, minRate);
-
- return average;
- }
- // 显示心率
- int TraingModel::CalculateFilteredHeartRate(int newHeartRate)
- {
- // 将新的心率添加到最近心率列表
- recentHeartRates.push_back(newHeartRate);
-
- // 如果超过窗口大小,移除最早的心率
- if (recentHeartRates.size() > windowSize)
- {
- recentHeartRates.erase(recentHeartRates.begin());
- }
-
- // 计算当前窗口中的平均心率
- int total = std::accumulate(recentHeartRates.begin(), recentHeartRates.end(), 0);
-
- // 打印当前窗口的平均心率
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "过滤后当前窗口的平均心率: %d",
- (total / recentHeartRates.size()));
-
- return total / recentHeartRates.size(); // 返回计算后的平均值
- }
- int TraingModel::Averageheartrate(int newHeartRate)
- {
- if (totalHeartRate == 0)
- {
- totalHeartRate = newHeartRate;
- }
- totalHeartRate = (totalHeartRate + newHeartRate) / 2;
-
- return totalHeartRate;
- }
- // 设置训练目标类型以及训练目标
- void TraingModel::SetSportTag(ExerciseTag tagtpye, int tag)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "tagtpye[%d] tag[%d]", tagtpye, tag);
- sportTagType_ = tagtpye;
- sportTag_ = tag;
- }
-
- /* 设置训练强度 */
- void TraingModel::SetIntensity(int heart)
- {
- // sportdata->intensity = active_state;
-#if 1
- /*
- 训练强度
- 220-年龄=最高心率
-
- 分为四个强度区间
- 较低强度=最高心率*59%以下
- 中等强度=最高心率*60%~69%
- 高等强度=最高心率*70%~79%
- 超高强度=最高心率*80%以上
- */
- int age = ConfigModel::GetInstance()->GetUserAge();
- int maxHeartRate = MAX_HEART_RATE - age;
-
- // 确保最大心率为正值
- if (maxHeartRate <= 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "maxHeartRate %d is error", maxHeartRate);
- return;
- }
-
- // 将 heart 转换为 double 以避免整数除法
- double heartRateAsDouble = static_cast<double>(heart);
- double intensityPercentage = (heartRateAsDouble / (double)maxHeartRate) * 100;
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "heart: %d, maxHeartRate: %d, intensityPercentage: %.2f", heart, maxHeartRate, intensityPercentage);
-
- if (intensityPercentage < LOW_INTENSITY_THRESHOLD)
- {
- // 较低强度
- sportdata->intensity = LOW_INTENSITY;
- }
- else if (intensityPercentage >= MEDIUM_INTENSITY_LOWER_THRESHOLD && intensityPercentage <= MEDIUM_INTENSITY_UPPER_THRESHOLD)
- {
- // 中等强度
- sportdata->intensity = MEDIUM_INTENSITY;
- }
- else if (intensityPercentage >= HIGH_INTENSITY_LOWER_THRESHOLD && intensityPercentage <= HIGH_INTENSITY_UPPER_THRESHOLD)
- {
- // 高等强度
- sportdata->intensity = HIGH_INTENSITY;
- }
- else
- {
- // 超高强度
- sportdata->intensity = VERY_HIGH_INTENSITY;
- }
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "maxHeartRate: %d, heartRate: %d, intensityPercentage: %.2f", maxHeartRate, heart, intensityPercentage);
-#endif
- }
- /*获取训练强度STR*/
- UIResourceTextId TraingModel::GetIntensity()
- {
- switch (sportdata->intensity)
- {
- case LOW_INTENSITY:
- return UIResourceTextId::STR_LOWER_STRENGTH;
- break;
- case MEDIUM_INTENSITY:
- return UIResourceTextId::STR_MEDIUM_STRENGTH;
- break;
- case HIGH_INTENSITY:
- return UIResourceTextId::STR_HIGH_STRENGTH;
- break;
- case VERY_HIGH_INTENSITY:
- return UIResourceTextId::STR_ULTRA_HIGH_STRENGTH;
- break;
- default:
- return UIResourceTextId::STR_LOWER_STRENGTH;
- break;
- }
- }
- /*获取当前的目标值*/
- int TraingModel::GetSportTagData()
- {
- if (sportdata->tag)
- {
- // 根据设置的训练目标类型去对应相对的数据
- switch (sportdata->sportTagType)
- {
- case ExerciseTag::Duration:
- return int(sportdata->duration / 60); // 时间是秒需要转换为目标的分钟
- break;
- case ExerciseTag::Calories:
- return sportdata->calories; //卡路里是kcal
- break;
- case ExerciseTag::Distance:
- return int(sportdata->distance / 1000); //距离是米需要转换为km
- break;
- case ExerciseTag::Steps:
- return sportdata->steps; //步数是步
- break;
- default:
- break;
- }
- }
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Not set Sport_Tag!");
- return 0; // 添加默认返回值
- }
- //获取运动时长
- int TraingModel::GetDuration() { return sportdata->duration; }
- /*获取训练类型Id*/
- UIResourceTextId TraingModel::GetSportTypeId(Exercisetype type)
- {
- // 根据设置的训练类型去对应相对的数据
- switch (type)
- {
- // 健身类
- case Exercisetype::FITNESS:
- return STR_EXERCISE_LIST;
- // 舞蹈类
- case Exercisetype::DANCE:
- return STR_DANCING_LIST;
- // 休闲运动
- case Exercisetype::LEISURE:
- return STR_RECREATIONAL_LIST;
- // 球类
- case Exercisetype::BALL:
- return STR_BALL_LIST;
- // 水上运动
- case Exercisetype::WATER:
- return STR_WATER_LIST;
- // 冰上运动
- case Exercisetype::ICE:
- return STR_ICE_LIST;
- // 极限运动
- case Exercisetype::EXTREME:
- return STR_EXTREME_LIST;
- // 其他
- case Exercisetype::OTHER:
- return STR_OTHER_LIST;
- default:
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Not ExerciseClass type!");
- break;
- }
-
- return STR_EXERCISE_LIST; // 添加默认返回值[健身类]
- }
- /*打印存储数据*/
- void TraingModel::printTrainingData(const Trainingdata &data)
- {
- printf("Trainingdata:\n");
- printf("src: %d\n", data.src);
- printf("bt: %u\n", data.bt);
- printf("ty: %u\n", data.ty);
- printf("st: %u\n", data.st);
- printf("sp: %u\n", data.sp);
- printf("tgt: %u\n", data.tgt);
- printf("tg: %u\n", data.tg);
- printf("pg: %u\n", data.pg);
- printf("du: %u\n", data.du);
- printf("ca: %u\n", data.ca);
- printf("di: %u\n", data.di);
- printf("hr: %u\n", data.hr);
- printf("stp: %u\n", data.stp);
- printf("ti: %u\n", data.ti);
- printf("cir: %u\n", data.cir);
- printf("alt: %u\n", data.alt);
- }
- /*获取训练目标完成百分比*/
- int TraingModel::GetGoaldegree()
- {
- if (sportTag_ == 0)
- {
- return 0;
- }
- int currentdata = GetSportTagData();
- float completeness = (static_cast<float>(currentdata) / sportdata->tag) * 100;
-
- return round(completeness); // 四舍五入
- }
- /*
- uint32_t src; // 训练来源:0 - 手表开启的训练,1 - APP开启的训练
- uint32_t bt; // 运动类型:0 - 健身类,1 - 舞蹈类,2 - 休闲运动,3 - 球类,4 - 水上项目,5 - 冰上项目,6 - 极限运动,7 - 其他
- uint32_t ty; // 训练类型:自由训练
- uint32_t st; // 开始时间戳(单位:秒)
- uint32_t sp; // 结束时间戳(单位:秒)
- uint32_t tgt; // 训练目标类型:0 - 距离,1 - 卡路里,2 - 时间,3 - 步数
- uint32_t tg; // 训练目标值:路程(单位:米),卡路里(单位:kcal),时间(单位:分钟),步数(单位:步)
- uint32_t pg; // 目标完成度(单位:%)
- uint32_t du; // 训练总时长(单位:秒)
- uint32_t ca; // 消耗卡路里(单位:kcal)
- uint32_t di; // 完成的距离(单位:米)
- uint32_t hr; // 平均心率
- uint32_t stp; // 步数
- uint32_t ti; // 训练强度:0 - 较低强度,1 - 中等强度,2 - 高等强度,3 - 超高强度
- uint32_t cir; // 圈数
- uint32_t alt; // 最高海拔高度
- */
- /*保存数据*/
- bool TraingModel::SaveSportData()
- {
- Trainingdata data;
- data.src = Openingway;
- data.bt = static_cast<uint32_t>(sportdata->sportType);
- data.ty = static_cast<uint32_t>(GetBleSportId(sportdata->sportType, sportdata->sportId));
- data.st = static_cast<uint32_t>(sportdata->starttime);
- data.sp = static_cast<uint32_t>(sportdata->endtime);
- data.tgt = static_cast<uint32_t>(sportdata->sportTagType);
- data.tg = static_cast<uint32_t>(sportdata->tag);
- data.pg = static_cast<uint32_t>(sportdata->goaldegree);
- data.du = static_cast<uint32_t>(sportdata->duration);
- data.ca = static_cast<uint32_t>(sportdata->calories * 10);
- data.di = static_cast<uint32_t>(sportdata->distance);
- data.hr = static_cast<uint32_t>(sportdata->avgheart);
- data.stp = static_cast<uint32_t>(sportdata->steps);
- data.ti = static_cast<uint32_t>(sportdata->intensity);
- /*230目前不支持【圈数】【最高海拔高度】*/
- data.cir = 0;
- data.alt = 0;
- /*配速相关还未处理 暂时保存0*/
- data.apc = static_cast<uint32_t>(sportdata->apc);
- data.fpc = static_cast<uint32_t>(sportdata->fpc);
- data.spc = static_cast<uint32_t>(sportdata->spc);
- data.std = static_cast<uint32_t>(sportdata->std);
- data.cdc = static_cast<uint32_t>(sportdata->cdc);
-
- // 保存数据到bin
- if (write_Trainingdata_data(data) != 1)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "write_Trainingdata_data is error!");
- // return false;
- }
- // 保存数据到json
- if (SaveDataToJson(sportdata) != true)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveDataToJson is error!");
- return false;
- }
-/*json读取测试*/
-#if READTEST
- SportData *sportDataArray = LoadDataFormJson();
- if (sportDataArray != nullptr)
- {
- int dataCount = 0;
- for (int i = 0; i < MAX_DATA_COUNT; i++) // 最多只有10条数据
- {
- SportData sportData = sportDataArray[i];
- printf("Sport type: %d\n", sportData.sportType);
- printf("Sport ID: %d\n", sportData.sportId);
- printf("Start date: %s\n", sportData.start_date.c_str());
- printf("Start time: %d\n", sportData.starttime);
- printf("End time: %d\n", sportData.endtime);
- printf("Goal degree: %d\n", sportData.goaldegree);
- printf("Duration: %d\n", sportData.duration);
- printf("Distance: %d\n", sportData.distance);
- printf("Average heart rate: %d\n", sportData.avgheart);
- printf("Steps: %d\n", sportData.steps);
- printf("Intensity: %d\n", sportData.intensity);
-
- dataCount++;
- }
-
- delete[] sportDataArray; // 记得释放内存
- }
-#endif
-/*bin 读取测试*/
-#if 0
- Trainingdata *readdata{nullptr};
- int i = 0;
- while (readdata = read_Trainingdata_data("2024_04_25", i))
- {
- if (readdata == NULL)
- return;
- printTrainingData(*readdata);
- // delete readdata;
- free(readdata);
- i++;
- }
-#endif
- return true;
- // delete data;
- }
- /*设置进入方式*/
- void TraingModel::SetEntryType(ENTEYTYPE type)
- {
- entey_type = type;
- }
- /*获取进入方式*/
- ENTEYTYPE TraingModel::GetEntryType()
- {
- return entey_type;
- }
- /*设置开启方式*/
- void TraingModel::SetSportOpenWay(bool way)
- {
- Openingway = way;
- }
- /*设置运动是否开始*/
- void TraingModel::SetSportOpenState(bool state)
- {
- Openstate = state;
- }
- /*获取运动是否开始*/
- bool TraingModel::GetSportOpenState()
- {
- return Openstate;
+ /*运动结束并且是手表发起的运动*/
+ if (Openingway == false) {
+ sendtraningstateend();
}
- /*获取运动时长*/
- uint32_t TraingModel::GetSportTime()
- {
- return sportdata->duration;
+ /*运动结束并且是app发起的运动*/
+ else {
+ sendtraningstatedata(0, sportdata->duration);
}
- /*获取训练量是否达标*/
- bool TraingModel::GetMomentum() {
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "结束运动");
+ }
+}
+/*设置开始时间*/
+void TraingModel::SetStartDateTime() {
+ std::string startDate, startTime;
+
+ if (!GetFormattedDate(startDate, "Failed to get start date"))
+ return;
+ if (!GetFormattedTime(startTime, "Failed to get start time"))
+ return;
+
+ sportdata->start_date = startDate;
+ sportdata->start_time = startTime;
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "sportdata->start_time [%s]\r\n",
+ sportdata->start_time.c_str());
+}
+/*设置结束时间*/
+void TraingModel::SetEndTime() {
+ std::string endTime;
+
+ if (GetFormattedTime(endTime, "Failed to get end time")) {
+ sportdata->end_time = endTime;
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "sportdata->end_time [%s]\r\n",
+ sportdata->end_time.c_str());
+}
+/*获取日期字符串*/
+bool TraingModel::GetFormattedDate(std::string &dateOutput,
+ const char *errorMsg) {
+ char *date = (char *)malloc(9 * sizeof(char)); // 分配内存给start_date
+ if (uapi_get_YYMMDD_Time(date, '/') != ERRCODE_SUCC) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s", errorMsg);
+ free(date);
+ return false;
+ }
+ dateOutput = std::string(date);
+ free(date); // 释放内存
+ return true;
+}
+/*获取时间字符串*/
+bool TraingModel::GetFormattedTime(std::string &timeOutput,
+ const char *errorMsg) {
+ char *time = (char *)malloc(9 * sizeof(char)); // 分配内存给start_time
+ if (uapi_get_HHMMSS_Time(time, ':', true) != ERRCODE_SUCC) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s", errorMsg);
+ free(time);
+ return false;
+ }
+ timeOutput = std::string(time);
+ free(time); // 释放内存
+ return true;
+}
+/*保存数据*/
+void TraingModel::RecordSportData() {
+#if READTEST
+ if (SaveSportData() == false) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSportData error!");
+ }
+#else
+ if (MomentumFlag) {
+ // GetGoaldegree(); // 设置目标完成度
+ if (SaveSportData()) {
+ TraingRecordModel::GetInstance().SetJsonStatus(true);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSportData ok!");
+ } else {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSportData error!");
+ }
+ }
+#endif
+}
+// 获取训练时长时间
+std::string TraingModel::GetTrainingTime() {
+ int hour = sportdata->duration / NUM_TIME_HOUR;
+ int min = (sportdata->duration % NUM_TIME_HOUR) / NUM_TIME_MIN;
+ int sec = (sportdata->duration % NUM_TIME_HOUR) % NUM_TIME_MIN;
+
+ std::ostringstream oss;
+ oss << std::setfill('0') << std::setw(2) << hour << ":" << std::setw(2) << min
+ << ":" << std::setw(2) << sec;
+
+ std::string triningtime = oss.str();
+ return triningtime;
+}
+/*解析时间戳 返回例如:13:00:22*/
+std::string TraingModel::AnalysisTimestamp(uint64_t timestamp) {
+ // 将时间戳转换为小时、分钟、秒
+ int hours = timestamp / 3600000; // 1小时 = 3600000毫秒
+ int minutes = (timestamp % 3600000) / 60000; // 1分钟 = 60000毫秒
+ int seconds = (timestamp % 60000) / 1000; // 1秒 = 1000毫秒
+
+ // 将小时、分钟、秒转换为字符串
+ std::string hoursStr = std::to_string(hours);
+ std::string minutesStr = std::to_string(minutes);
+ std::string secondsStr = std::to_string(seconds);
+
+ // 格式化输出为 HH:MM:SS
+ std::stringstream ss;
+ ss << std::setfill('0') << std::setw(2) << hoursStr << ":" << std::setw(2)
+ << minutesStr << ":" << std::setw(2) << secondsStr;
+
+ return ss.str();
+}
+int TraingModel::CalculateAverageHeartRate(int newHeartRate) {
+ // 将新的心率添加到数据列表
+ heartRateData.push_back(newHeartRate);
+ totalHeartRate += newHeartRate;
+ countHeartRate++;
+
+ // 将新的心率插入到堆中
+ maxHeap.push(newHeartRate);
+ minHeap.push(newHeartRate);
+
+ // 如果超过窗口大小,移除最早的心率
+ if (heartRateData.size() > windowSize) {
+ int oldestRate = heartRateData[0];
+ totalHeartRate -= oldestRate;
+ countHeartRate--;
+
+ // 将老旧值从列表中移除
+ heartRateData.erase(heartRateData.begin());
+
+ // 标记老旧值为待删除
+ delayed[oldestRate]++;
+ }
+
+ // 清理堆中的老旧值
+ while (!maxHeap.empty() && delayed[maxHeap.top()] > 0) {
+ delayed[maxHeap.top()]--;
+ maxHeap.pop();
+ }
+
+ while (!minHeap.empty() && delayed[minHeap.top()] > 0) {
+ delayed[minHeap.top()]--;
+ minHeap.pop();
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "新心率: %d, 当前心率总和: %d, 心率计数: %d", newHeartRate,
+ totalHeartRate, countHeartRate);
+
+ // 如果心率数量少于 3,直接返回当前的平均值
+ if (countHeartRate < 3) {
+ return totalHeartRate / countHeartRate; // 无法去除最大最小值
+ }
+
+ // 取出当前未被删除的最大和最小的心率
+ int maxRate = maxHeap.top();
+ int minRate = minHeap.top();
+
+ // 进行去极值后的平均计算
+ int average = (totalHeartRate - maxRate - minRate) / (countHeartRate - 2);
+
+ // 打印计算结果
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "去极值后的平均心率: %d (去掉最大值: %d, 去掉最小值: %d)",
+ average, maxRate, minRate);
+
+ return average;
+}
+// 显示心率
+int TraingModel::CalculateFilteredHeartRate(int newHeartRate) {
+ // 将新的心率添加到最近心率列表
+ recentHeartRates.push_back(newHeartRate);
+
+ // 如果超过窗口大小,移除最早的心率
+ if (recentHeartRates.size() > windowSize) {
+ recentHeartRates.erase(recentHeartRates.begin());
+ }
+
+ // 计算当前窗口中的平均心率
+ int total =
+ std::accumulate(recentHeartRates.begin(), recentHeartRates.end(), 0);
+
+ // 打印当前窗口的平均心率
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "过滤后当前窗口的平均心率: %d",
+ (total / recentHeartRates.size()));
+
+ return total / recentHeartRates.size(); // 返回计算后的平均值
+}
+int TraingModel::Averageheartrate(int newHeartRate) {
+ heartcount++;
+ totalHeartRate += newHeartRate;
+ return totalHeartRate / heartcount; // 返回计算的平均值
+}
+// 设置训练目标类型以及训练目标
+void TraingModel::SetSportTag(ExerciseTag tagtpye, int tag) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "tagtpye[%d] tag[%d]", tagtpye, tag);
+ sportTagType_ = tagtpye;
+ sportTag_ = tag;
+}
+
+/* 设置训练强度 */
+void TraingModel::SetIntensity(int heart) {
+ // sportdata->intensity = active_state;
+#if 1
+ /*
+ 训练强度
+ 220-年龄=最高心率
+
+ 分为四个强度区间
+ 较低强度=最高心率*59%以下
+ 中等强度=最高心率*60%~69%
+ 高等强度=最高心率*70%~79%
+ 超高强度=最高心率*80%以上
+ */
+ int age = ConfigModel::GetInstance()->GetUserAge();
+ int maxHeartRate = MAX_HEART_RATE - age;
+
+ // 确保最大心率为正值
+ if (maxHeartRate <= 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "maxHeartRate %d is error",
+ maxHeartRate);
+ return;
+ }
+
+ // 将 heart 转换为 double 以避免整数除法
+ double heartRateAsDouble = static_cast<double>(heart);
+ double intensityPercentage = (heartRateAsDouble / (double)maxHeartRate) * 100;
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,
+ "heart: %d, maxHeartRate: %d, intensityPercentage: %.2f", heart,
+ maxHeartRate, intensityPercentage);
+
+ if (intensityPercentage < LOW_INTENSITY_THRESHOLD) {
+ // 较低强度
+ sportdata->intensity = LOW_INTENSITY;
+ } else if (intensityPercentage >= MEDIUM_INTENSITY_LOWER_THRESHOLD &&
+ intensityPercentage <= MEDIUM_INTENSITY_UPPER_THRESHOLD) {
+ // 中等强度
+ sportdata->intensity = MEDIUM_INTENSITY;
+ } else if (intensityPercentage >= HIGH_INTENSITY_LOWER_THRESHOLD &&
+ intensityPercentage <= HIGH_INTENSITY_UPPER_THRESHOLD) {
+ // 高等强度
+ sportdata->intensity = HIGH_INTENSITY;
+ } else {
+ // 超高强度
+ sportdata->intensity = VERY_HIGH_INTENSITY;
+ }
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,
+ "maxHeartRate: %d, heartRate: %d, intensityPercentage: %.2f",
+ maxHeartRate, heart, intensityPercentage);
+#endif
+}
+/*获取训练强度STR*/
+UIResourceTextId TraingModel::GetIntensity() {
+ switch (sportdata->intensity) {
+ case LOW_INTENSITY:
+ return UIResourceTextId::STR_LOWER_STRENGTH;
+ break;
+ case MEDIUM_INTENSITY:
+ return UIResourceTextId::STR_MEDIUM_STRENGTH;
+ break;
+ case HIGH_INTENSITY:
+ return UIResourceTextId::STR_HIGH_STRENGTH;
+ break;
+ case VERY_HIGH_INTENSITY:
+ return UIResourceTextId::STR_ULTRA_HIGH_STRENGTH;
+ break;
+ default:
+ return UIResourceTextId::STR_LOWER_STRENGTH;
+ break;
+ }
+}
+/*获取当前的目标值*/
+int TraingModel::GetSportTagData() {
+ if (sportdata->tag) {
+ // 根据设置的训练目标类型去对应相对的数据
+ switch (sportdata->sportTagType) {
+ case ExerciseTag::Duration:
+ return int(sportdata->duration / 60); // 时间是秒需要转换为目标的分钟
+ break;
+ case ExerciseTag::Calories:
+ return sportdata->calories; //卡路里是kcal
+ break;
+ case ExerciseTag::Distance:
+ return int(sportdata->distance / 1000); //距离是米需要转换为km
+ break;
+ case ExerciseTag::Steps:
+ return sportdata->steps; //步数是步
+ break;
+ default:
+ break;
+ }
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Not set Sport_Tag!");
+ return 0; // 添加默认返回值
+}
+//获取运动时长
+int TraingModel::GetDuration() { return sportdata->duration; }
+/*获取训练类型Id*/
+UIResourceTextId TraingModel::GetSportTypeId(Exercisetype type) {
+ // 根据设置的训练类型去对应相对的数据
+ switch (type) {
+ // 健身类
+ case Exercisetype::FITNESS:
+ return STR_EXERCISE_LIST;
+ // 舞蹈类
+ case Exercisetype::DANCE:
+ return STR_DANCING_LIST;
+ // 休闲运动
+ case Exercisetype::LEISURE:
+ return STR_RECREATIONAL_LIST;
+ // 球类
+ case Exercisetype::BALL:
+ return STR_BALL_LIST;
+ // 水上运动
+ case Exercisetype::WATER:
+ return STR_WATER_LIST;
+ // 冰上运动
+ case Exercisetype::ICE:
+ return STR_ICE_LIST;
+ // 极限运动
+ case Exercisetype::EXTREME:
+ return STR_EXTREME_LIST;
+ // 其他
+ case Exercisetype::OTHER:
+ return STR_OTHER_LIST;
+ default:
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Not ExerciseClass type!");
+ break;
+ }
+
+ return STR_EXERCISE_LIST; // 添加默认返回值[健身类]
+}
+/*打印存储数据*/
+void TraingModel::printTrainingData(const Trainingdata &data) {
+ printf("Trainingdata:\n");
+ printf("src: %d\n", data.src);
+ printf("bt: %u\n", data.bt);
+ printf("ty: %u\n", data.ty);
+ printf("st: %u\n", data.st);
+ printf("sp: %u\n", data.sp);
+ printf("tgt: %u\n", data.tgt);
+ printf("tg: %u\n", data.tg);
+ printf("pg: %u\n", data.pg);
+ printf("du: %u\n", data.du);
+ printf("ca: %u\n", data.ca);
+ printf("di: %u\n", data.di);
+ printf("hr: %u\n", data.hr);
+ printf("stp: %u\n", data.stp);
+ printf("ti: %u\n", data.ti);
+ printf("cir: %u\n", data.cir);
+ printf("alt: %u\n", data.alt);
+}
+/*获取训练目标完成百分比*/
+int TraingModel::GetGoaldegree() {
+ if (sportTag_ == 0) {
+ return 0;
+ }
+ int currentdata = GetSportTagData();
+ float completeness = (static_cast<float>(currentdata) / sportdata->tag) * 100;
+
+ return round(completeness); // 四舍五入
+}
+/*
+ uint32_t src; // 训练来源:0 - 手表开启的训练,1 - APP开启的训练
+ uint32_t bt; // 运动类型:0 - 健身类,1 - 舞蹈类,2 - 休闲运动,3 - 球类,4
+ - 水上项目,5 - 冰上项目,6 - 极限运动,7 - 其他 uint32_t ty; //
+ 训练类型:自由训练 uint32_t st; // 开始时间戳(单位:秒) uint32_t sp; //
+ 结束时间戳(单位:秒) uint32_t tgt; // 训练目标类型:0 - 距离,1 - 卡路里,2
+ - 时间,3 - 步数 uint32_t tg; //
+ 训练目标值:路程(单位:米),卡路里(单位:kcal),时间(单位:分钟),步数(单位:步)
+ uint32_t pg; // 目标完成度(单位:%)
+ uint32_t du; // 训练总时长(单位:秒)
+ uint32_t ca; // 消耗卡路里(单位:kcal)
+ uint32_t di; // 完成的距离(单位:米)
+ uint32_t hr; // 平均心率
+ uint32_t stp; // 步数
+ uint32_t ti; // 训练强度:0 - 较低强度,1 - 中等强度,2 - 高等强度,3 -
+ 超高强度 uint32_t cir; // 圈数 uint32_t alt; // 最高海拔高度
+*/
+/*保存数据*/
+bool TraingModel::SaveSportData() {
+ Trainingdata data;
+ data.src = Openingway;
+ data.bt = static_cast<uint32_t>(sportdata->sportType);
+ data.ty = static_cast<uint32_t>(
+ GetBleSportId(sportdata->sportType, sportdata->sportId));
+ data.st = static_cast<uint32_t>(sportdata->starttime);
+ data.sp = static_cast<uint32_t>(sportdata->endtime);
+ data.tgt = static_cast<uint32_t>(sportdata->sportTagType);
+ data.tg = static_cast<uint32_t>(sportdata->tag);
+ data.pg = static_cast<uint32_t>(sportdata->goaldegree);
+ data.du = static_cast<uint32_t>(sportdata->duration);
+ data.ca = static_cast<uint32_t>(sportdata->calories * 10);
+ data.di = static_cast<uint32_t>(sportdata->distance);
+ data.hr = static_cast<uint32_t>(sportdata->avgheart);
+ data.stp = static_cast<uint32_t>(sportdata->steps);
+ data.ti = static_cast<uint32_t>(sportdata->intensity);
+ /*230目前不支持【圈数】【最高海拔高度】*/
+ data.cir = 0;
+ data.alt = 0;
+ /*配速相关还未处理 暂时保存0*/
+ data.apc = static_cast<uint32_t>(sportdata->apc);
+ data.fpc = static_cast<uint32_t>(sportdata->fpc);
+ data.spc = static_cast<uint32_t>(sportdata->spc);
+ data.std = static_cast<uint32_t>(sportdata->std);
+ data.cdc = static_cast<uint32_t>(sportdata->cdc);
+
+ // 保存数据到bin
+ if (write_Trainingdata_data(data) != 1) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "write_Trainingdata_data is error!");
+ // return false;
+ }
+ // 保存数据到json
+ if (SaveDataToJson(sportdata) != true) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveDataToJson is error!");
+ return false;
+ }
+ if (isspecialsport_) {
+ //保存心率表
+ if (SaveHeartTable() != true) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveHeartRateData is error!");
+ return false;
+ }
+ //保存速度表
+ if (SavePaceTable() != true) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveSpeedData is error!");
+ return false;
+ }
+ }
+
+ return true;
+ // delete data;
+}
+/*设置进入方式*/
+void TraingModel::SetEntryType(ENTEYTYPE type) { entey_type = type; }
+/*获取进入方式*/
+ENTEYTYPE TraingModel::GetEntryType() { return entey_type; }
+/*设置开启方式*/
+void TraingModel::SetSportOpenWay(bool way) { Openingway = way; }
+/*设置运动是否开始*/
+void TraingModel::SetSportOpenState(bool state) { Openstate = state; }
+/*获取运动是否开始*/
+bool TraingModel::GetSportOpenState() { return Openstate; }
+/*获取运动时长*/
+uint32_t TraingModel::GetSportTime() { return sportdata->duration; }
+/*获取训练量是否达标*/
+bool TraingModel::GetMomentum() {
#if 0
int caldata = TraingModel::GetInstance()->GetCal();
/*判断是否产生至少1Kcald的运动量*/
MomentumFlag = false;
}
#endif
- int duration = sportdata->duration;
- //判断运动时间是否大于1分钟
- if (duration >= 60) {
- MomentumFlag = true;
- } else {
- MomentumFlag = false;
- }
- return MomentumFlag;
- }
- /*发送实时数据*/
- void TraingModel::SendLiveData()
- {
- msg_get_train_data_info_t data;
- memset(&data, 0, sizeof(msg_get_train_data_info_t));
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "sportdata->starttime %d \r\n", sportdata->starttime);
- data.st = sportdata->starttime;
- data.hr = sportdata->heart;
- data.ca = sportdata->calories;
- data.di = sportdata->distance;
- data.stp = sportdata->steps;
- data.ti = sportdata->intensity;
- data.pc = sportdata->pc;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SendLiveData Begin!");
- sendtraningdata(&data); // 发送数据函数
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SendLiveData Stop!");
- }
- /* -------------------------------- 运动识别发起处理 -------------------------------- */
- void TraingModel::set_sport_config(UIResourceTextId id)
- {
- if (id >= MAXSPORTID)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "id is error");
- return;
- }
- // 开始训练 ->不返回
- NativeAbility::GetInstance().ChangeSlice(VIEW_TRAININGCRAD);
- // 配置运动项
- SetSportEvent(id);
- // 获取运动项目
- ExerciseClass type = GetSportId();
- // 开启对应的运动
- TraingCardPresenter::GetInstance()->OpenSensor(type);
- // 设置为手表开启运动
- SetSportOpenWay(false);
- }
+ int duration = sportdata->duration;
+ //判断运动时间是否大于1分钟
+ if (duration >= 60) {
+ MomentumFlag = true;
+ } else {
+ MomentumFlag = false;
+ }
+ return MomentumFlag;
+}
+/*配速表与心率表相关*/
+//清空心率表
+void TraingModel::ClearHeartTable() {
+ heartRateTable.clear(); // 清空心率数据表
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Heart Rate Table Cleared.\r\n");
+}
+//清空配速表
+void TraingModel::ClearPaceTable() {
+ paceTable.clear(); // 清空配速数据表
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Pace Table Cleared.\r\n");
+}
+// 添加心率数据
+bool TraingModel::AddHeartRateData(uint32_t timestamp, uint16_t heartRate) {
+ // 检查重复时间戳
+ for (const auto &entry : heartRateTable) {
+ if (entry.timestamp == timestamp) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "时间戳重复无法添加数据 AddHeartRateData is error!");
+ return false; // 返回重复
+ }
+ }
+
+ if (heartRateTable.size() >= MAX_ENTRIES) {
+ WEARABLE_LOGE(
+ WEARABLE_LOG_MODULE_APP,
+ "达到最大心率数据条目限制 无法添加新的数据 AddHeartRateData is error!");
+ return false; // 返回条目满了
+ }
+
+ HeartRateEntry newEntry = {timestamp, heartRate};
+ heartRateTable.push_back(newEntry);
+ return true; // 返回成功
+}
+
+// 添加配速数据
+bool TraingModel::AddPaceData(uint32_t timestamp, uint16_t pace) {
+ // 检查重复时间戳
+ for (const auto &entry : paceTable) {
+ if (entry.timestamp == timestamp) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "时间戳重复无法添加数据 AddPaceData is error!"); // 修正这里
+ return false; // 返回重复
+ }
+ }
+
+ if (paceTable.size() >= MAX_ENTRIES) {
+ WEARABLE_LOGE(
+ WEARABLE_LOG_MODULE_APP,
+ "达到配速数据条目限制 无法添加新的数据 AddPaceData is error!");
+ return false; // 返回条目满了
+ }
+
+ PaceEntry newEntry = {timestamp, pace};
+ paceTable.push_back(newEntry);
+ return true; // 返回成功
+}
+
+// 保存心率表
+bool TraingModel::SaveHeartTable() {
+ CreateDirectoryIfNotExists(TRAINING_HEART_FILE);
+
+ size_t heartRateCount = heartRateTable.size();
+ if (heartRateCount == 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "心率表为空,无法保存。");
+ return false;
+ }
+
+ std::string filePath =
+ TRAINING_HEART_FILE + std::to_string(sportdata->starttime) + ".bin";
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveHeartTable filePath: %s",
+ filePath.c_str());
+ std::ofstream heartRateFile(filePath, std::ios::binary);
+ if (!heartRateFile) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "无法打开文件: %s",
+ filePath.c_str());
+ return false; // 返回失败
+ }
+
+ // 存储表数据
+ heartRateFile.write(reinterpret_cast<const char *>(&heartRateCount),
+ sizeof(heartRateCount));
+ if (!heartRateFile.write(
+ reinterpret_cast<const char *>(heartRateTable.data()),
+ heartRateCount * sizeof(HeartRateEntry))) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "写入心率数据失败。");
+ return false; // 返回失败
+ }
+
+ heartRateFile.close();
+
+ return true; // 返回成功
+}
+
+// 保存配速表
+bool TraingModel::SavePaceTable() {
+ CreateDirectoryIfNotExists(TRAINING_PACE_FILE);
+
+ size_t paceCount = paceTable.size();
+ if (paceCount == 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "配速表为空,无法保存。");
+ return false;
+ }
+
+ std::string filePath =
+ TRAINING_PACE_FILE + std::to_string(sportdata->starttime) + ".bin";
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SavePaceTable filePath: %s",
+ filePath.c_str());
+ std::ofstream paceFile(filePath, std::ios::binary);
+ if (!paceFile) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "无法打开文件: %s",
+ filePath.c_str());
+ return false; // 返回失败
+ }
+
+ paceFile.write(reinterpret_cast<const char *>(&paceCount), sizeof(paceCount));
+ if (!paceFile.write(reinterpret_cast<const char *>(paceTable.data()),
+ paceCount * sizeof(PaceEntry))) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "写入配速数据失败。");
+ return false; // 返回失败
+ }
+
+ paceFile.close();
+
+ return true; // 返回成功
+}
+// 返回心率表路径
+std::string TraingModel::GetHeartTablePath(uint32_t timestamp) {
+ // 首先检查完全匹配的时间戳
+ std::string exactFilePath =
+ TRAINING_HEART_FILE + std::to_string(timestamp) + ".bin";
+ if (IsFileAccessibleAndNotEmpty(exactFilePath)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "找到心率表: %s",
+ exactFilePath.c_str());
+ return exactFilePath; // 返回完全匹配的文件路径
+ }
+
+ // 如果未找到,检查时间戳相差1到2秒的文件
+ for (int i = -2; i <= 2; ++i) {
+ uint32_t checkTimestamp = timestamp + i;
+ std::string filePath =
+ TRAINING_HEART_FILE + std::to_string(checkTimestamp) + ".bin";
+ if (IsFileAccessibleAndNotEmpty(filePath)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "找到心率表: %s",
+ filePath.c_str());
+ return filePath; // 返回找到的文件路径
+ }
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "未找到与时间戳相关的心率表。");
+ return ""; // 未找到文件
+}
+
+// 返回配速表路径
+std::string TraingModel::GetPaceTablePath(uint32_t timestamp) {
+ // 首先检查完全匹配的时间戳
+ std::string exactFilePath =
+ TRAINING_PACE_FILE + std::to_string(timestamp) + ".bin";
+ if (IsFileAccessibleAndNotEmpty(exactFilePath)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "找到配速表: %s",
+ exactFilePath.c_str());
+ return exactFilePath; // 返回完全匹配的文件路径
+ }
+
+ // 如果未找到,检查时间戳相差1到2秒的文件
+ for (int i = -2; i <= 2; ++i) {
+ uint32_t checkTimestamp = timestamp + i;
+ std::string filePath =
+ TRAINING_PACE_FILE + std::to_string(checkTimestamp) + ".bin";
+ if (IsFileAccessibleAndNotEmpty(filePath)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "找到配速表: %s",
+ filePath.c_str());
+ return filePath; // 返回找到的文件路径
+ }
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "未找到与时间戳相关的配速表。");
+ return ""; // 未找到文件
+}
+/*发送实时数据*/
+void TraingModel::SendLiveData() {
+ msg_get_train_data_info_t data;
+ memset(&data, 0, sizeof(msg_get_train_data_info_t));
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "sportdata->starttime %d \r\n",
+ sportdata->starttime);
+ data.st = sportdata->starttime;
+ data.hr = sportdata->heart;
+ data.ca = sportdata->calories;
+ data.di = sportdata->distance;
+ data.stp = sportdata->steps;
+ data.ti = sportdata->intensity;
+ data.pc = sportdata->pc;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SendLiveData Begin!");
+ sendtraningdata(&data); // 发送数据函数
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SendLiveData Stop!");
+}
+/* -------------------------------- 运动识别发起处理
+ * -------------------------------- */
+void TraingModel::set_sport_config(UIResourceTextId id) {
+ if (id >= MAXSPORTID) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "id is error");
+ return;
+ }
+ // 开始训练 ->不返回
+ NativeAbility::GetInstance().ChangeSlice(VIEW_TRAININGCRAD);
+ // 配置运动项
+ SetSportEvent(id);
+ // 获取运动项目
+ ExerciseClass type = GetSportId();
+ // 开启对应的运动
+ TraingCardPresenter::GetInstance()->OpenSensor(type);
+ // 设置为手表开启运动
+ SetSportOpenWay(false);
+}
/* -------------------------------------------------------------------------- */
#if TIMER
- /* 时间显示 */
- std::string TraingModel::DisplayMotionDuration()
- {
- motionDuration.clear();
+#include <chrono>
+#include <iomanip>
+#include <sstream>
+#include <string>
- if (g_motionTimes >= NUM_TIME_DAY)
- {
- g_motionTimes = 0;
- }
- if (g_motionTimes != 0)
- {
- sportdata->duration = g_motionTimes; // 训练时长
- /*判断是否开启自动获取*/
- if (ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_TRANING_AUTO))
- {
- freq = ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_TRANING_FREQ);
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "freq is %d\r\n", freq); // 获取实时数据频率
- if (sportdata->duration % freq == 0)
- {
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SendLiveData is OK\r\n");
- SendLiveData(); // 发送实时数据
- }
- }
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "duration:[%d] g_motionTimes[%d]\r\n", sportdata->duration, g_motionTimes);
- }
+std::string TraingModel::DisplayMotionDuration() {
+ // 清空 motionDuration
+ motionDuration.clear();
+
+ // 重置运动次数
+ if (g_motionTimes >= NUM_TIME_DAY) {
+ g_motionTimes = 0;
+ }
+
+ // 计算和格式化运动时长
+ int hours = g_motionTimes / NUM_TIME_HOUR;
+ int minutes = (g_motionTimes % NUM_TIME_HOUR) / NUM_TIME_MIN;
+ int seconds = g_motionTimes % NUM_TIME_MIN;
+
+ std::ostringstream oss;
+ oss << std::setfill('0') << std::setw(2) << hours << ":" << std::setw(2)
+ << minutes << ":" << std::setw(2) << seconds;
+
+ motionDuration = oss.str();
+
+ // 获取当前时间(以微秒为单位)
+ uint32_t currentTime = static_cast<uint32_t>(
+ std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count());
+
+ // 记录和检查上一次调用的时间
+ static uint32_t lastCallTime = 0;
+ if (currentTime - lastCallTime < 1000000) { // 小于1秒
+ return motionDuration;
+ }
+ lastCallTime = currentTime; // 更新最后调用时间
+
+ // 如果 g_motionTimes 不为零,进行计算和数据存储
+ if (g_motionTimes > 0) {
+ sportdata->duration = g_motionTimes; // 设置训练时长
+
+ // 检查并发送实时数据
+ SendLiveDataIfNecessary();
+
+ // 每分钟进行配速和心率数据存储
+ StoreDataIfMinutePassed();
+ }
+
+ return motionDuration; // 返回格式化的运动时长
+}
- int hour = g_motionTimes / NUM_TIME_HOUR;
- int min = (g_motionTimes % NUM_TIME_HOUR) / NUM_TIME_MIN;
- int sec = (g_motionTimes % NUM_TIME_HOUR) % NUM_TIME_MIN;
+// 检查并发送实时数据
+void TraingModel::SendLiveDataIfNecessary() {
+ // 检查自动获取的配置
+ if (ConfigModel::GetInstance()->get_configData_int(
+ ConfigModel::CONFIGMODEL_ITEM_TRANING_AUTO)) {
- std::ostringstream oss;
- oss << std::setfill('0') << std::setw(2) << hour << ":" << std::setw(2) << min << ":" << std::setw(2) << sec;
+ freq = ConfigModel::GetInstance()->get_configData_int(
+ ConfigModel::CONFIGMODEL_ITEM_TRANING_FREQ);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "freq is %d\r\n", freq);
+
+ // 发送实时数据
+ if (sportdata->duration % freq == 0) {
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SendLiveData is OK\r\n");
+ SendLiveData(); // 发送实时数据
+ }
+ }
+}
- motionDuration = oss.str();
- return motionDuration;
+// 每分钟进行配速和心率数据存储
+void TraingModel::StoreDataIfMinutePassed() {
+ if (sportdata->duration % 60 == 0) {
+ uint32_t timestamp;
+ if (uapi_get_timestampe_ss(×tamp) == ERRCODE_SUCC) {
+ AddHeartRateData(timestamp, sportdata->heart);
+ AddPaceData(timestamp, sportdata->apc);
}
+ }
+
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "duration:[%d] g_motionTimes[%d]\r\n",
+ sportdata->duration, g_motionTimes);
+}
#ifdef __cplusplus
- extern "C"
- {
+extern "C" {
#endif
- /* 定时器回调函数 */
- void TraingTimerCallback()
- {
- g_motionTimes++;
+/* 定时器回调函数 */
+void TraingTimerCallback() {
+ g_motionTimes++;
#if 0
TraingCardPresenter *gTraingCardPresenter = TraingCardPresenter::GetInstance();
if (gTraingCardPresenter == nullptr)
}
gTraingCardPresenter->ModifiesTime();
#endif
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TraingTimerCallback\r\n");
- }
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TraingTimerCallback\r\n");
+}
- /* 开启定时器 */
- void InitTimer(void)
- {
- if (g_startCounting != NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::TraingTimer already exists!!");
- return;
- }
- g_startCounting = osTimerNew((osTimerFunc_t)TraingTimerCallback, osTimerPeriodic, NULL, NULL);
- if (g_startCounting == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::TraingTimer osTimerNew failed!!");
- return;
- }
- int tick = osMs2Tick(MS_ONE_SECONDS);
- osStatus_t retTimer = osTimerStart(g_startCounting, tick);
- if (retTimer != osOK)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::TraingTimer osTimerStart failed, ret = %lx!!", retTimer);
- if (g_startCounting != NULL)
- {
- retTimer = osTimerDelete(g_startCounting);
- if (retTimer != osOK)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::osTimerDelete failed, ret = %lx!!", retTimer);
- return;
- }
- g_startCounting = NULL;
- }
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "InitTimer!");
- return;
- }
- }
- /* 关闭定时器 */
- void DisableTimer(void)
- {
- if (g_startCounting != NULL)
- {
- osTimerStop(g_startCounting);
- osStatus_t ret = osTimerDelete(g_startCounting);
- if (ret != osOK)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScanTimerCallback osTimerDelete failed, ret = %lx!!", ret);
- return;
- }
- g_startCounting = NULL;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "g_motionTimes:%d\r\n", sportdata->duration);
- g_motionTimes = 0;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DisableTimer!");
- }
- }
- /* 暂停定时器 */
- void PauseTimer(void)
- {
- // 检查定时器是否存在
- if (g_startCounting != NULL)
- {
- // 暂停定时器,但不删除它
- osStatus_t ret = osTimerStop(g_startCounting);
- if (ret != osOK)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StopWatch_PauseTimer osTimerStop failed, ret = %lx!!", ret);
- }
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "PauseTimer!");
- }
- }
+/* 开启定时器 */
+void InitTimer(void) {
+ if (g_startCounting != NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "TraingModel::TraingTimer already exists!!");
+ return;
+ }
+ g_startCounting = osTimerNew((osTimerFunc_t)TraingTimerCallback,
+ osTimerPeriodic, NULL, NULL);
+ if (g_startCounting == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "TraingModel::TraingTimer osTimerNew failed!!");
+ return;
+ }
+ int tick = osMs2Tick(MS_ONE_SECONDS);
+ osStatus_t retTimer = osTimerStart(g_startCounting, tick);
+ if (retTimer != osOK) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "TraingModel::TraingTimer osTimerStart failed, ret = %lx!!",
+ retTimer);
+ if (g_startCounting != NULL) {
+ retTimer = osTimerDelete(g_startCounting);
+ if (retTimer != osOK) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "TraingModel::osTimerDelete failed, ret = %lx!!",
+ retTimer);
+ return;
+ }
+ g_startCounting = NULL;
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "InitTimer!");
+ return;
+ }
+}
+/* 关闭定时器 */
+void DisableTimer(void) {
+ if (g_startCounting != NULL) {
+ osTimerStop(g_startCounting);
+ osStatus_t ret = osTimerDelete(g_startCounting);
+ if (ret != osOK) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "ScanTimerCallback osTimerDelete failed, ret = %lx!!", ret);
+ return;
+ }
+ g_startCounting = NULL;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "g_motionTimes:%d\r\n",
+ sportdata->duration);
+ g_motionTimes = 0;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DisableTimer!");
+ }
+}
+/* 暂停定时器 */
+void PauseTimer(void) {
+ // 检查定时器是否存在
+ if (g_startCounting != NULL) {
+ // 暂停定时器,但不删除它
+ osStatus_t ret = osTimerStop(g_startCounting);
+ if (ret != osOK) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "StopWatch_PauseTimer osTimerStop failed, ret = %lx!!",
+ ret);
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "PauseTimer!");
+ }
+}
- /*恢复定时器*/
- void ResumeTimer(void)
- {
- // 检查定时器是否存在
- if (g_startCounting != NULL)
- {
- int tick = osMs2Tick(MS_ONE_SECONDS);
- // 恢复定时器
- osStatus_t ret = osTimerStart(g_startCounting, tick);
- if (ret != osOK)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ResumeTimer osTimerStart failed, ret = %lx!!", ret);
- }
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ResumeTimer!");
- }
- }
+/*恢复定时器*/
+void ResumeTimer(void) {
+ // 检查定时器是否存在
+ if (g_startCounting != NULL) {
+ int tick = osMs2Tick(MS_ONE_SECONDS);
+ // 恢复定时器
+ osStatus_t ret = osTimerStart(g_startCounting, tick);
+ if (ret != osOK) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "ResumeTimer osTimerStart failed, ret = %lx!!", ret);
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ResumeTimer!");
+ }
+}
#ifdef __cplusplus
- }
+}
#endif
#endif
- /* ---------------------------------- 数据存储 ---------------------------------- */
- static int32 SaveTraingDataToFile(void)
- {
- time_t now = time(nullptr);
- struct tm *timeinfo = localtime(&now);
- char filename[20];
- strftime(filename, sizeof(filename), "%Y%m%d.bin", timeinfo);
-
- uint32 size = sizeof(Trainingdata);
+/* ---------------------------------- 数据存储
+ * ---------------------------------- */
+static int32 SaveTraingDataToFile(void) {
+ time_t now = time(nullptr);
+ struct tm *timeinfo = localtime(&now);
+ char filename[20];
+ strftime(filename, sizeof(filename), "%Y%m%d.bin", timeinfo);
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SaveTraingDataToFile !!");
-
- char filePath[20];
- sprintf(filePath, "%s%s", TRAINING_DATA_DIRECTORY, filename);
-
- std::ofstream fd(filePath, std::ios::binary);
- if (!fd.is_open())
- {
- if (mkdir(TRAINING_DATA_DIRECTORY, S_IRWXU) != 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create directory");
- return 0;
- }
+ uint32 size = sizeof(Trainingdata);
- fd.open(filePath, std::ios::binary);
- if (!fd.is_open())
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file for write");
- return 0;
- }
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SaveTraingDataToFile !!");
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Directory created successfully!!");
- }
+ char filePath[20];
+ sprintf(filePath, "%s%s", TRAINING_DATA_DIRECTORY, filename);
- fd.write(reinterpret_cast<const char *>(&sportdata), size);
- fd.close();
- return 1;
+ std::ofstream fd(filePath, std::ios::binary);
+ if (!fd.is_open()) {
+ if (mkdir(TRAINING_DATA_DIRECTORY, S_IRWXU) != 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create directory");
+ return 0;
}
- static std::vector<Trainingdata> LoadTrainingDataFromTodayFile()
- {
- std::vector<Trainingdata> trainingRecords;
-
- time_t now = time(nullptr);
- struct tm *timeinfo = localtime(&now);
- char filename[20];
- strftime(filename, sizeof(filename), "%Y%m%d.bin", timeinfo);
- // 找到训练文件夹里面的当天文件
- char filePath[20];
- sprintf(filePath, "%s%s", TRAINING_DATA_DIRECTORY, filename);
-
- std::ifstream fd(filePath, std::ios::binary);
- if (!fd.is_open())
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open today's file");
- return trainingRecords; // Return an empty vector if file open fails
- }
- // 读取训练信息
- while (!fd.eof())
- {
- Trainingdata record;
- fd.read(reinterpret_cast<char *>(&record), sizeof(Trainingdata));
- if (fd.gcount() == sizeof(Trainingdata))
- {
- trainingRecords.push_back(record);
- }
- }
+ fd.open(filePath, std::ios::binary);
+ if (!fd.is_open()) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file for write");
+ return 0;
+ }
- fd.close();
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Directory created successfully!!");
+ }
- return trainingRecords;
- }
+ fd.write(reinterpret_cast<const char *>(&sportdata), size);
+ fd.close();
+ return 1;
+}
+static std::vector<Trainingdata> LoadTrainingDataFromTodayFile() {
+ std::vector<Trainingdata> trainingRecords;
+
+ time_t now = time(nullptr);
+ struct tm *timeinfo = localtime(&now);
+ char filename[20];
+ strftime(filename, sizeof(filename), "%Y%m%d.bin", timeinfo);
+ // 找到训练文件夹里面的当天文件
+ char filePath[20];
+ sprintf(filePath, "%s%s", TRAINING_DATA_DIRECTORY, filename);
+
+ std::ifstream fd(filePath, std::ios::binary);
+ if (!fd.is_open()) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open today's file");
+ return trainingRecords; // Return an empty vector if file open fails
+ }
+
+ // 读取训练信息
+ while (!fd.eof()) {
+ Trainingdata record;
+ fd.read(reinterpret_cast<char *>(&record), sizeof(Trainingdata));
+ if (fd.gcount() == sizeof(Trainingdata)) {
+ trainingRecords.push_back(record);
+ }
+ }
+
+ fd.close();
+
+ return trainingRecords;
+}
#ifdef __cplusplus
- extern "C"
- {
+extern "C" {
#endif
- // 获得数据个数
- static int get_Trainingdata_data_num(FILE *fp)
- {
- long size = 0;
- if (fp != NULL)
- {
- fseek(fp, 0, SEEK_END); // 将文件指针移动到文件末尾
- size = ftell(fp); // 获取当前文件指针位置,即文件大小
- fseek(fp, 0, SEEK_SET); // 将文件指针移回文件开头
- }
- int num = size / sizeof(Trainingdata);
- return num;
- }
- int write_Trainingdata_data(Trainingdata data)
- {
- char file_path[MAX_FILE_PATH_LENGTH] = {0};
- char timeday[12] = {0};
- uapi_get_YYMMDD_Time(timeday, '_');
- sprintf_s(file_path, sizeof(file_path), "%s%s.bin", TRAINING_PATH, timeday); // 防止越界
-
- // Check if the directory exists, if not, create it
- struct stat st = {0};
- if (stat(TRAINING_PATH, &st) == -1)
- {
- mkdir(TRAINING_PATH, 0700);
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s", file_path);
- FILE *fp = fopen(file_path, "ab+");
- if (fp == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file for append");
- fp = fopen(file_path, "wb+");
- if (fp == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file for write");
- return -1; // Return an error code to indicate file open failure
- }
- }
-
- int ret = fwrite((void *)&data, sizeof(Trainingdata), 1, fp);
- if (ret != 1)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "fwrite_data error! %d", ret);
- fclose(fp);
- return -1; // Return an error code on write failure
- }
-
- fclose(fp); // Close the file after writing data
- return 1; // Return success code
- }
- // 读数据
- Trainingdata *read_Trainingdata_data(char *timedata, uint16_t offset)
- {
- char file_path[128] = {0};
- sprintf_s(file_path, sizeof(file_path), "%s%s.bin", TRAINING_PATH, timedata); // 防止越界
-
- FILE *fp = fopen(file_path, "rb+");
- if (fp == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "file is NULL");
- return NULL;
- }
- Trainingdata *data = (Trainingdata *)malloc(sizeof(Trainingdata));
- if (data == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Trainingdata malloc is error");
- fclose(fp);
- return NULL;
- }
- if (get_Trainingdata_data_num(fp) <= offset)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "file is NULL %d", get_Trainingdata_data_num(fp));
- free(data); // 修复内存泄漏
- fclose(fp);
- return NULL;
- }
- fseek(fp, sizeof(Trainingdata) * offset, SEEK_SET);
- fread((void *)data, sizeof(Trainingdata), 1, fp);
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "%d", data->src);
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "%d %d ", offset, sizeof(Trainingdata));
- fseek(fp, 0, SEEK_SET);
-
- fclose(fp);
- return data;
- }
+// 获得数据个数
+static int get_Trainingdata_data_num(FILE *fp) {
+ long size = 0;
+ if (fp != NULL) {
+ fseek(fp, 0, SEEK_END); // 将文件指针移动到文件末尾
+ size = ftell(fp); // 获取当前文件指针位置,即文件大小
+ fseek(fp, 0, SEEK_SET); // 将文件指针移回文件开头
+ }
+ int num = size / sizeof(Trainingdata);
+ return num;
+}
+int write_Trainingdata_data(Trainingdata data) {
+ char file_path[MAX_FILE_PATH_LENGTH] = {0};
+ char timeday[12] = {0};
+ uapi_get_YYMMDD_Time(timeday, '_');
+ sprintf_s(file_path, sizeof(file_path), "%s%s.bin", TRAINING_PATH,
+ timeday); // 防止越界
+
+ // Check if the directory exists, if not, create it
+ struct stat st = {0};
+ if (stat(TRAINING_PATH, &st) == -1) {
+ mkdir(TRAINING_PATH, 0700);
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s", file_path);
+ FILE *fp = fopen(file_path, "ab+");
+ if (fp == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file for append");
+ fp = fopen(file_path, "wb+");
+ if (fp == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file for write");
+ return -1; // Return an error code to indicate file open failure
+ }
+ }
+
+ int ret = fwrite((void *)&data, sizeof(Trainingdata), 1, fp);
+ if (ret != 1) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "fwrite_data error! %d", ret);
+ fclose(fp);
+ return -1; // Return an error code on write failure
+ }
+
+ fclose(fp); // Close the file after writing data
+ return 1; // Return success code
+}
+// 读数据
+Trainingdata *read_Trainingdata_data(char *timedata, uint16_t offset) {
+ char file_path[128] = {0};
+ sprintf_s(file_path, sizeof(file_path), "%s%s.bin", TRAINING_PATH,
+ timedata); // 防止越界
+
+ FILE *fp = fopen(file_path, "rb+");
+ if (fp == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "file is NULL");
+ return NULL;
+ }
+ Trainingdata *data = (Trainingdata *)malloc(sizeof(Trainingdata));
+ if (data == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Trainingdata malloc is error");
+ fclose(fp);
+ return NULL;
+ }
+ if (get_Trainingdata_data_num(fp) <= offset) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "file is NULL %d",
+ get_Trainingdata_data_num(fp));
+ free(data); // 修复内存泄漏
+ fclose(fp);
+ return NULL;
+ }
+ fseek(fp, sizeof(Trainingdata) * offset, SEEK_SET);
+ fread((void *)data, sizeof(Trainingdata), 1, fp);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "%d", data->src);
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "%d %d ", offset,
+ sizeof(Trainingdata));
+ fseek(fp, 0, SEEK_SET);
+
+ fclose(fp);
+ return data;
+}
#ifdef __cplusplus
- }
+}
#endif
- /* -------------------------------------------------------------------------- */
- /*检查是否存在数据*/
- bool TraingModel::CheckDataJson()
- {
- // 读取record.json文件
- std::ifstream file(TRAINING_RECORD_FILE);
-
- // 检查文件是否打开成功
- if (!file.is_open())
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Unable to open file");
- return false;
- }
-
- // 检查文件是否为空
- file.seekg(0, std::ios::end);
- if (file.tellg() == 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File is empty");
- file.close();
- return false;
- }
-
- // 解析json
- std::vector<SportData> sportDataVector;
- if(!LoadDataFormJson(sportDataVector))
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LoadDataFormJson is error");
- file.close();
- return false;
- }
-
- // 关闭文件
- file.close();
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckDataJson is ok");
- return true;
- }
+/* -------------------------------------------------------------------------- */
+/*检查是否存在数据*/
+bool TraingModel::CheckDataJson() {
+ // 读取record.json文件
+ std::ifstream file(TRAINING_RECORD_FILE);
+
+ // 检查文件是否打开成功
+ if (!file.is_open()) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Unable to open file");
+ return false;
+ }
+
+ // 检查文件是否为空
+ file.seekg(0, std::ios::end);
+ if (file.tellg() == 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File is empty");
+ file.close();
+ return false;
+ }
+
+ // 解析json
+ std::vector<SportData> sportDataVector;
+ if (!LoadDataFormJson(sportDataVector)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LoadDataFormJson is error");
+ file.close();
+ return false;
+ }
+
+ // 关闭文件
+ file.close();
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckDataJson is ok");
+ return true;
+}
#if 1
- bool TraingModel::SaveDataToJson(SportData *data)
- {
- FILE *fp;
- char *jsonStr = NULL;
- // 创建sport文件夹
- CreateDirectoryIfNotExists(TRAINING_DATA_DIRECTORY);
-
- // 读取现有的 JSON 数据
- fp = fopen(TRAINING_RECORD_FILE, "r");
- cJSON *data_root = NULL;
- cJSON *dataArray = NULL;
-
- if (fp != NULL)
- {
- fseek(fp, 0, SEEK_END);
- long fileSize = ftell(fp);
- fseek(fp, 0, SEEK_SET);
-
- jsonStr = (char *)malloc(fileSize + 1);
- if (jsonStr != nullptr)
- {
- if (fread(jsonStr, fileSize, 1, fp) == 1)
- {
- data_root = cJSON_Parse(jsonStr);
- if (data_root != NULL)
- {
- dataArray = cJSON_GetObjectItem(data_root, "data");
- }
- }
- }
- fclose(fp);
- }
-
- if (dataArray == NULL)
- {
- data_root = cJSON_CreateObject();
- cJSON_AddItemToObject(data_root, "data", cJSON_CreateArray());
- dataArray = cJSON_GetObjectItem(data_root, "data");
- }
-
- // 创建或更新数据节点
- cJSON *sportData = cJSON_CreateObject();
- cJSON_AddNumberToObject(sportData, "sportTypeId", int(data->sportType)); // 训练项目类 Id
- cJSON_AddNumberToObject(sportData, "sportId", data->sportId); // 训练项目 Id
- cJSON_AddStringToObject(sportData, "startDate", (data->start_date).c_str()); // 训练开始日期字符串
- cJSON_AddStringToObject(sportData, "startTime", (data->start_time).c_str()); // 训练开始时间
- cJSON_AddStringToObject(sportData, "endTime", (data->end_time).c_str()); // 训练结束时间
- cJSON_AddNumberToObject(sportData, "goalDegree", data->goaldegree); // 训练目标完成度
- cJSON_AddNumberToObject(sportData, "duration", data->duration); // 训练时长(秒)
- cJSON_AddNumberToObject(sportData, "distance", data->distance); // 训练距离
- cJSON_AddNumberToObject(sportData, "avgHeartRate", data->avgheart); // 训练平均心率
- cJSON_AddNumberToObject(sportData, "steps", data->steps); // 训练步数
- cJSON_AddNumberToObject(sportData, "intensity", data->intensity); // 训练强度
- cJSON_AddNumberToObject(sportData, "apc", data->apc); // 训练平均配速
- cJSON_AddNumberToObject(sportData, "cdc", data->cdc); // 训练步频
- cJSON_AddNumberToObject(sportData, "std", data->std); // 训练步幅
-
- // 添加运动数据节点到数组并限制数量
- cJSON_AddItemToArray(dataArray, sportData);
- while (cJSON_GetArraySize(dataArray) > MAX_DATA_COUNT)
- {
- cJSON_DeleteItemFromArray(dataArray, 0);
- }
-
- // 将更新后的 JSON 数据写入文件
- char *jsonStrNew = cJSON_Print(data_root);
- fp = fopen(TRAINING_RECORD_FILE, "w");
- if (fp != NULL)
- {
- fwrite(jsonStrNew, strlen(jsonStrNew), 1, fp);
- fclose(fp);
+bool TraingModel::SaveDataToJson(SportData *data) {
+ FILE *fp;
+ char *jsonStr = NULL;
+ // 创建sport文件夹
+ CreateDirectoryIfNotExists(TRAINING_DATA_DIRECTORY);
+
+ // 读取现有的 JSON 数据
+ fp = fopen(TRAINING_RECORD_FILE, "r");
+ cJSON *data_root = NULL;
+ cJSON *dataArray = NULL;
+
+ if (fp != NULL) {
+ fseek(fp, 0, SEEK_END);
+ long fileSize = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ jsonStr = (char *)malloc(fileSize + 1);
+ if (jsonStr != nullptr) {
+ if (fread(jsonStr, fileSize, 1, fp) == 1) {
+ data_root = cJSON_Parse(jsonStr);
+ if (data_root != NULL) {
+ dataArray = cJSON_GetObjectItem(data_root, "data");
}
-
- // 释放资源
- cJSON_Delete(data_root);
- free(jsonStr);
- cJSON_free(jsonStrNew);
-
- return true;
+ }
}
+ fclose(fp);
+ }
+
+ if (dataArray == NULL) {
+ data_root = cJSON_CreateObject();
+ cJSON_AddItemToObject(data_root, "data", cJSON_CreateArray());
+ dataArray = cJSON_GetObjectItem(data_root, "data");
+ }
+
+ // 创建或更新数据节点
+ cJSON *sportData = cJSON_CreateObject();
+ cJSON_AddNumberToObject(sportData, "sportTypeId",
+ int(data->sportType)); // 训练项目类 Id
+ cJSON_AddNumberToObject(sportData, "sportId", data->sportId); // 训练项目 Id
+ cJSON_AddStringToObject(sportData, "startDate",
+ (data->start_date).c_str()); // 训练开始日期字符串
+ cJSON_AddStringToObject(sportData, "startTime",
+ (data->start_time).c_str()); // 训练开始时间
+ cJSON_AddStringToObject(sportData, "endTime",
+ (data->end_time).c_str()); // 训练结束时间
+ cJSON_AddNumberToObject(sportData, "goalDegree",
+ data->goaldegree); // 训练目标完成度
+ cJSON_AddNumberToObject(sportData, "duration",
+ data->duration); // 训练时长(秒)
+ cJSON_AddNumberToObject(sportData, "distance", data->distance); // 训练距离
+ cJSON_AddNumberToObject(sportData, "avgHeartRate",
+ data->avgheart); // 训练平均心率
+ cJSON_AddNumberToObject(sportData, "steps", data->steps); // 训练步数
+ cJSON_AddNumberToObject(sportData, "intensity", data->intensity); // 训练强度
+ cJSON_AddNumberToObject(sportData, "apc", data->apc); // 训练平均配速
+ cJSON_AddNumberToObject(sportData, "cdc", data->cdc); // 训练步频
+ cJSON_AddNumberToObject(sportData, "std", data->std); // 训练步幅
+
+ // 添加运动数据节点到数组并限制数量
+ cJSON_AddItemToArray(dataArray, sportData);
+ while (cJSON_GetArraySize(dataArray) > MAX_DATA_COUNT) {
+ cJSON_DeleteItemFromArray(dataArray, 0);
+ }
+
+ // 将更新后的 JSON 数据写入文件
+ char *jsonStrNew = cJSON_Print(data_root);
+ fp = fopen(TRAINING_RECORD_FILE, "w");
+ if (fp != NULL) {
+ fwrite(jsonStrNew, strlen(jsonStrNew), 1, fp);
+ fclose(fp);
+ }
+
+ // 释放资源
+ cJSON_Delete(data_root);
+ free(jsonStr);
+ cJSON_free(jsonStrNew);
+
+ return true;
+}
#endif
#if 0
bool TraingModel::SaveDataToJson(SportData *data)
return true;
}
#endif
- /* 加载训练数据函数 */
- bool TraingModel::LoadDataFormJson(std::vector<SportData>& sportDataVector)
- {
- std::ifstream file(TRAINING_RECORD_FILE);
- if (!file.is_open())
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file");
- return false;
- }
-
- std::string jsonData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
- file.close();
-
- cJSON *root = cJSON_Parse(jsonData.c_str());
- if (root == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to parse JSON: %s", cJSON_GetErrorPtr());
- return false;
- }
-
- cJSON *dataArray = cJSON_GetObjectItem(root, "data");
- if (dataArray == NULL ||!cJSON_IsArray(dataArray))
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid or missing 'data' array in JSON");
- cJSON_Delete(root);
- return false;
- }
-
- int dataCount = cJSON_GetArraySize(dataArray);
- if (dataCount == 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "error dataCount is 0");
- cJSON_Delete(root);
- return false;
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "dataCount is %d", dataCount);
-
- for (int i = 0; i < dataCount; i++)
- {
- cJSON *item = cJSON_GetArrayItem(dataArray, i);
- if (item == NULL)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid item at index %d", i);
- continue; // 跳过无效项目
- }
-
- SportData sportData;
- bool isValid = true; // 用于标记 sportData 是否有效
-
- // 检查并获取每个字段,确保其存在且类型正确
- if (cJSON *sportTypeIdItem = cJSON_GetObjectItem(item, "sportTypeId"); sportTypeIdItem && cJSON_IsNumber(sportTypeIdItem))
- sportData.sportType = (Exercisetype)sportTypeIdItem->valueint;
- else
- isValid = false;
-
- if (cJSON *sportIdItem = cJSON_GetObjectItem(item, "sportId"); sportIdItem && cJSON_IsNumber(sportIdItem))
- sportData.sportId = (UIResourceTextId)sportIdItem->valueint;
- else
- isValid = false;
-
- if (cJSON *startDateItem = cJSON_GetObjectItem(item, "startDate"); startDateItem && cJSON_IsString(startDateItem))
- sportData.start_date = startDateItem->valuestring;
- else
- isValid = false;
-
- if (cJSON *startTimeItem = cJSON_GetObjectItem(item, "startTime"); startTimeItem && cJSON_IsString(startTimeItem))
- sportData.start_time = startTimeItem->valuestring;
- else
- isValid = false;
-
- if (cJSON *endTimeItem = cJSON_GetObjectItem(item, "endTime"); endTimeItem && cJSON_IsString(endTimeItem))
- sportData.end_time = endTimeItem->valuestring;
- else
- isValid = false;
-
- if (cJSON *goalDegreeItem = cJSON_GetObjectItem(item, "goalDegree"); goalDegreeItem && cJSON_IsNumber(goalDegreeItem))
- sportData.goaldegree = goalDegreeItem->valueint;
- else
- isValid = false;
-
- if (cJSON *durationItem = cJSON_GetObjectItem(item, "duration"); durationItem && cJSON_IsNumber(durationItem))
- sportData.duration = durationItem->valueint;
- else
- isValid = false;
-
- if (cJSON *distanceItem = cJSON_GetObjectItem(item, "distance"); distanceItem && cJSON_IsNumber(distanceItem))
- sportData.distance = distanceItem->valueint;
- else
- isValid = false;
-
- if (cJSON *avgHeartRateItem = cJSON_GetObjectItem(item, "avgHeartRate"); avgHeartRateItem && cJSON_IsNumber(avgHeartRateItem))
- sportData.avgheart = avgHeartRateItem->valueint;
- else
- isValid = false;
-
- if (cJSON *stepsItem = cJSON_GetObjectItem(item, "steps"); stepsItem && cJSON_IsNumber(stepsItem))
- sportData.steps = stepsItem->valueint;
- else
- isValid = false;
-
- if (cJSON *intensityItem = cJSON_GetObjectItem(item, "intensity"); intensityItem && cJSON_IsNumber(intensityItem))
- sportData.intensity = intensityItem->valueint;
- else
- isValid = false;
-
- if (cJSON *apcItem = cJSON_GetObjectItem(item, "apc"); apcItem && cJSON_IsNumber(apcItem))
- sportData.apc = apcItem->valueint;
- else
- isValid = false;
-
- if (cJSON *cdcItem = cJSON_GetObjectItem(item, "cdc"); cdcItem && cJSON_IsNumber(cdcItem))
- sportData.cdc = cdcItem->valueint;
- else
- isValid = false;
-
- if (cJSON *stdItem = cJSON_GetObjectItem(item, "std"); stdItem && cJSON_IsNumber(stdItem))
- sportData.std = stdItem->valueint;
- else
- isValid = false;
-
- // 只有在所有字段都有效的情况下才添加 sportData 到向量中
- if (isValid)
- {
- sportDataVector.push_back(sportData);
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid data in item %d", i);
- }
- }
-
- cJSON_Delete(root);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LoadDataFormJson is ok");
- return true;
- }
+/* 加载训练数据函数 */
+bool TraingModel::LoadDataFormJson(std::vector<SportData> &sportDataVector) {
+ std::ifstream file(TRAINING_RECORD_FILE);
+ if (!file.is_open()) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file");
+ return false;
+ }
+
+ std::string jsonData((std::istreambuf_iterator<char>(file)),
+ std::istreambuf_iterator<char>());
+ file.close();
+
+ cJSON *root = cJSON_Parse(jsonData.c_str());
+ if (root == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to parse JSON: %s",
+ cJSON_GetErrorPtr());
+ return false;
+ }
+
+ cJSON *dataArray = cJSON_GetObjectItem(root, "data");
+ if (dataArray == NULL || !cJSON_IsArray(dataArray)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "Invalid or missing 'data' array in JSON");
+ cJSON_Delete(root);
+ return false;
+ }
+
+ int dataCount = cJSON_GetArraySize(dataArray);
+ if (dataCount == 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "error dataCount is 0");
+ cJSON_Delete(root);
+ return false;
+ }
+
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "dataCount is %d", dataCount);
+
+ for (int i = 0; i < dataCount; i++) {
+ cJSON *item = cJSON_GetArrayItem(dataArray, i);
+ if (item == NULL) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid item at index %d", i);
+ continue; // 跳过无效项目
+ }
+
+ SportData sportData;
+ bool isValid = true; // 用于标记 sportData 是否有效
+
+ // 检查并获取每个字段,确保其存在且类型正确
+ if (cJSON *sportTypeIdItem = cJSON_GetObjectItem(item, "sportTypeId");
+ sportTypeIdItem && cJSON_IsNumber(sportTypeIdItem))
+ sportData.sportType = (Exercisetype)sportTypeIdItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *sportIdItem = cJSON_GetObjectItem(item, "sportId");
+ sportIdItem && cJSON_IsNumber(sportIdItem))
+ sportData.sportId = (UIResourceTextId)sportIdItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *startDateItem = cJSON_GetObjectItem(item, "startDate");
+ startDateItem && cJSON_IsString(startDateItem))
+ sportData.start_date = startDateItem->valuestring;
+ else
+ isValid = false;
+
+ if (cJSON *startTimeItem = cJSON_GetObjectItem(item, "startTime");
+ startTimeItem && cJSON_IsString(startTimeItem))
+ sportData.start_time = startTimeItem->valuestring;
+ else
+ isValid = false;
+
+ if (cJSON *endTimeItem = cJSON_GetObjectItem(item, "endTime");
+ endTimeItem && cJSON_IsString(endTimeItem))
+ sportData.end_time = endTimeItem->valuestring;
+ else
+ isValid = false;
+
+ if (cJSON *goalDegreeItem = cJSON_GetObjectItem(item, "goalDegree");
+ goalDegreeItem && cJSON_IsNumber(goalDegreeItem))
+ sportData.goaldegree = goalDegreeItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *durationItem = cJSON_GetObjectItem(item, "duration");
+ durationItem && cJSON_IsNumber(durationItem))
+ sportData.duration = durationItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *distanceItem = cJSON_GetObjectItem(item, "distance");
+ distanceItem && cJSON_IsNumber(distanceItem))
+ sportData.distance = distanceItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *avgHeartRateItem = cJSON_GetObjectItem(item, "avgHeartRate");
+ avgHeartRateItem && cJSON_IsNumber(avgHeartRateItem))
+ sportData.avgheart = avgHeartRateItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *stepsItem = cJSON_GetObjectItem(item, "steps");
+ stepsItem && cJSON_IsNumber(stepsItem))
+ sportData.steps = stepsItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *intensityItem = cJSON_GetObjectItem(item, "intensity");
+ intensityItem && cJSON_IsNumber(intensityItem))
+ sportData.intensity = intensityItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *apcItem = cJSON_GetObjectItem(item, "apc");
+ apcItem && cJSON_IsNumber(apcItem))
+ sportData.apc = apcItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *cdcItem = cJSON_GetObjectItem(item, "cdc");
+ cdcItem && cJSON_IsNumber(cdcItem))
+ sportData.cdc = cdcItem->valueint;
+ else
+ isValid = false;
+
+ if (cJSON *stdItem = cJSON_GetObjectItem(item, "std");
+ stdItem && cJSON_IsNumber(stdItem))
+ sportData.std = stdItem->valueint;
+ else
+ isValid = false;
+
+ // 只有在所有字段都有效的情况下才添加 sportData 到向量中
+ if (isValid) {
+ sportDataVector.push_back(sportData);
+ } else {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid data in item %d", i);
+ }
+ }
+
+ cJSON_Delete(root);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LoadDataFormJson is ok");
+ return true;
+}
-}
\ No newline at end of file
+} // namespace OHOS
\ No newline at end of file