void UpdateBatteryColor(void);
/*配置文件*/
void SetDialPath(std::string dialpath);
- bool InitialConfig(int Id);
+
/*配置函数*/
bool InitBackground(const char *filename);
bool InitTimeView(TimeDisplayPosition type); // 时间
bool InitBatteryView(BatteryDisplayType type); // 电量
bool InitColor(ColorTypeSet type); // 颜色
- /*返回文件夹路径*/
- std::string GetSaveDir(int Id);
+
private:
void InitStepValue();
bool InitClock(void);
bool LoadClockImage(Image *view, uint32_t resId);
bool LoadClockImage(UIImageView *view, uint32_t resId);
- void CreateDirectoryIfNotExists(const std::string &path);
+
/*表盘背景*/
UIImageView *curFace{nullptr};
dialFile.clear();
dialFile = dialpath;
}
- /*
- 从配置文件读取设置
- 配置文件名:表盘ID
- 第一个字节:电池图标样式
- 第二个字节:时间label位置
- 第三个字节:字体颜色
- */
- bool MainClockView::InitialConfig(int Id)
- {
- std::string filename = APP_CUSTOM_DIAL_PATH + std::to_string(Id) + ".bin";
-
- // 打开文件
- std::ifstream configFile(filename, std::ios::binary);
- if (!configFile.is_open())
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Unable to open config file: %s", filename.c_str());
- return false; // 文件打开失败
- }
-
- // 读取配置
- char settings[3]; // 读取3个字节
- configFile.read(settings, sizeof(settings));
- if (configFile.gcount() != sizeof(settings))
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to read config file or insufficient file content!");
- configFile.close();
- return false; // 读取失败
- }
-
- // 为成员变量赋值
- batterySetting = static_cast<BatteryDisplayType>(settings[0]); // 第一个字节:电池图标样式
- timePosition = static_cast<TimeDisplayPosition>(settings[1]); // 第二个字节:时间label位置
- colorType = static_cast<ColorTypeSet>(settings[2]); // 第三个字节:字体颜色
-
- // 关闭文件
- configFile.close();
-
- return true; // 成功读取配置
- }
- /*
- 获取存储文件夹
- Id(0~4)通过ID返回对应的文件夹路径
- 0
- 1
- 2
- 3
- 4
- */
- /*创建文件夹*/
- void MainClockView::CreateDirectoryIfNotExists(const std::string &path)
- {
- struct stat info;
- if (stat(path.c_str(), &info) != 0)
- {
- if (mkdir(path.c_str(), 0755) != 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Could not create directory %s. Errno: %d", path.c_str(), errno);
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Created directory: %s", path.c_str());
- }
- }
- else if (info.st_mode & S_IFDIR)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Directory already exists: %s", path.c_str());
- }
- }
- /*获取文件夹路径*/
- std::string MainClockView::GetSaveDir(int Id)
- {
- // 首先检查Id是否在0~4的范围内
- if (Id < 0 || Id > 4)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Id must be between 0 and 4.");
- return ""; // 或者返回一个空字符串
- }
-
- std::string folderPath = std::string(APP_CUSTOM_DIAL_PATH) + "/" + std::to_string(Id); // 修复这一行
- CreateDirectoryIfNotExists(folderPath); // 确保目录存在
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Directory is %s", folderPath.c_str());
-
- return folderPath; // 返回目录路径
- }
bool MainClockView::InitClock(void)
{
#include "health_service.h"\r
#include "custom_utils.h"\r
#include "ppg_service.h"\r
+#include "custom_runtime.h"\r
+#include <iostream>\r
+#include <memory>\r
\r
#ifdef __cplusplus\r
extern "C"\r
{\r
UNUSED(args);\r
UNUSED(topic);\r
+\r
+ /*训练过程中 不需要判断数据准确性 不需要存储心率数据*/\r
+ if (uapi_dev_runtime_get_train_status() == 1)\r
+ return;\r
+\r
if (request == nullptr)\r
{\r
return;\r
return;\r
}\r
#endif\r
- uint16_t preheart = *(uint16_t *)request->data;\r
+ uint16_t preheart = *reinterpret_cast<uint16_t *>(request->data);\r
// 筛选出正常数据\r
if (preheart > HEART_RATE_LIMIT_LOWER && preheart <= HEART_RATE_LIMIT_UPPER)\r
{\r
if (heartInfo == nullptr)\r
{\r
WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[Notify] malloc fail");\r
+ return;\r
}\r
heartInfo->index = index_;\r
heartInfo->maxX = index_;\r
\r
void HeartModel::UpHeartdata(uint16_t heart)\r
{\r
+ /*训练过程中 不需要判断数据准确性 不需要存储心率数据*/\r
+ if (uapi_dev_runtime_get_train_status() == 1)\r
+ return;\r
+\r
Show_Heart_ = heart;\r
if (Show_Heart_ != 0)\r
{\r
data->timestamp = HeartPresenter::GetInstance()->GetCurrentTime();\r
WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, " Save %d %d", data->Heart, data->timestamp);\r
SetCheckTime(data->timestamp);\r
- HealthService::GetInstance()->UpdateHealthData(*data);\r
+ HealthService::GetInstance()->UpdateHealthData(*data); // 心率数据存储\r
// 关闭自动检测心率 如果有其他高级心率检测在进行,则不会进行关闭[低优先级]\r
HeartModel::GetInstance()->Heart_Control(HeartState::End, HeartCheck::PASSIVITY);\r
}\r
#endif
MainClockView *clock = new MainClockView();
clock->SetDialPath(setting.dialFullName);
- clock->InitialConfig(setting.dialId);
+ // clock->InitialConfig(setting.dialId); //配置文件
return clock;
}
UICardPage *MainViewSample::InitWatchFacePage(void)
DEFULTDIAL,
DOWNLOADDIAL,
};
+ struct DialLayout
+ {
+ uint8_t dialId;
+ uint8_t batteryDisplay; // 电池配置
+ uint8_t timeDisplay; // 时间位置
+ uint8_t colorTypeSet; // 颜色配置
+ };
class SetDialModel
{
public:
uint16_t GetDialIdFromName(const std::string &dialName);
void PrintRegisteredDials(const std::unordered_map<uint16_t, std::string> &dials);
int GetAllDialIDs(char *allidStr);
+
+ /*表盘map文件*/
bool readDialfile();
bool saveDialfile();
+ /*自定义表盘配置文件*/
+ bool saveDialConfig(const DialLayout &layout);
+ bool loadDialConfig(int Id, DialLayout &layout);
+ /*获取存储自定义表盘文件夹路径*/
std::string GetSaveDir(int Id);
+ /*【判断文件夹是否存在 不存在创建】*/
+ void CreateDirectoryIfNotExists(const std::string &path);
private:
- void CreateDirectoryIfNotExists(const std::string &path);
void LoadAllDialFromRam(void);
void LoadAllDialFromFs(void);
void LoadAllDialFromDefult(void);
#include <string>
#include <sstream>
#include <iomanip>
+#include <iostream>
+#include <fstream>
#include <stdio.h>
-#include "NativeAbility.h"
-#include "UiConfig.h"
#include <sys/stat.h>
+#include <unistd.h>
+#include "NativeAbility.h"
+#include "clock/include/MainClockView.h"
namespace OHOS
{
// 定义特殊Id
}
}
- void SetDialModel::CreateDirectoryIfNotExists(const std::string &path)
- {
- struct stat info;
- if (stat(path.c_str(), &info) != 0)
- {
- if (mkdir(path.c_str(), 0755) != 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Could not create directory %s. Errno: %d", path.c_str(), errno);
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Created directory: %s", path.c_str());
- }
- }
- else if (info.st_mode & S_IFDIR)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Directory already exists: %s", path.c_str());
- }
- }
-
- std::string SetDialModel::GetSaveDir(int Id)
- {
- // 首先检查Id是否在0~4的范围内
- if (Id < 0 || Id > 4)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Id must be between 0 and 4.");
- return ""; // 或者返回一个空字符串
- }
- CreateDirectoryIfNotExists(std::string(APP_CUSTOM_DIAL_PATH));
- std::string folderPath = std::string(APP_CUSTOM_DIAL_PATH) + "/" + std::to_string(Id); // 修复这一行
- CreateDirectoryIfNotExists(folderPath); // 确保目录存在
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Directory is %s", folderPath.c_str());
-
- return folderPath; // 返回目录路径
- }
-
/*加载所有表盘*/
void SetDialModel::LoadAllDial()
{
}
return 0;
}
+ /* --------------------------------- 自定义表盘配置 -------------------------------- */
+ // 保存自定义表盘配置到文件
+ bool SetDialModel::saveDialConfig(const DialLayout &layout)
+ {
+ std::string filename = APP_CUSTOM_DIAL_PATH + std::to_string(layout.dialId) + ".bin";
+
+ // 创建或打开文件
+ std::ofstream configFile(filename, std::ios::binary | std::ios::out | std::ios::trunc);
+ if (!configFile.is_open())
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Unable to open config file for writing: %s", filename.c_str());
+ return false; // 文件打开失败
+ }
+
+ // 将结构体的三个数据按1个字节的存储到文件
+ configFile.put(static_cast<char>(layout.batteryDisplay)); // 第一字节:电池图标样式
+ configFile.put(static_cast<char>(layout.timeDisplay)); // 第二字节:时间label位置
+ configFile.put(static_cast<char>(layout.colorTypeSet)); // 第三字节:字体颜色
+
+ // 关闭文件
+ configFile.close();
+ return true; // 成功写入配置
+ }
+
+ /*
+ 从配置文件读取设置
+ 配置文件名:表盘ID
+ 第一个字节:电池图标样式
+ 第二个字节:时间label位置
+ 第三个字节:字体颜色
+ */
+ bool SetDialModel::loadDialConfig(int Id, DialLayout &layout)
+ {
+ std::string filename = APP_CUSTOM_DIAL_PATH + std::to_string(Id) + ".bin";
+
+ // 打开文件
+ std::ifstream configFile(filename, std::ios::binary);
+ if (!configFile.is_open())
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Unable to open config file for reading: %s", filename.c_str());
+ return false; // 文件打开失败
+ }
+
+ // 读取配置
+ char settings[3]; // 读取3个字节
+ configFile.read(settings, sizeof(settings));
+ if (configFile.gcount() != sizeof(settings))
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to read config file or insufficient file content!");
+ configFile.close();
+ return false; // 读取失败
+ }
+
+ // 为成员变量赋值
+ layout.batteryDisplay = static_cast<BatteryDisplayType>(settings[0]); // 电池图标样式
+ layout.timeDisplay = static_cast<TimeDisplayPosition>(settings[1]); // 时间label位置
+ layout.colorTypeSet = static_cast<ColorTypeSet>(settings[2]); // 字体颜色
+
+ // 关闭文件
+ configFile.close();
+ return true; // 成功读取配置
+ }
+
+ /*创建文件夹*/
+ void SetDialModel::CreateDirectoryIfNotExists(const std::string &path)
+ {
+ struct stat info;
+ if (stat(path.c_str(), &info) != 0)
+ {
+ if (mkdir(path.c_str(), 0755) != 0)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Could not create directory %s. Errno: %d", path.c_str(), errno);
+ }
+ else
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Created directory: %s", path.c_str());
+ }
+ }
+ else if (info.st_mode & S_IFDIR)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Directory already exists: %s", path.c_str());
+ }
+ }
+
+ /*
+ 获取存储文件夹
+ Id(0~4)通过ID返回对应的文件夹路径
+ 0
+ 1
+ 2
+ 3
+ 4
+ */
+ std::string SetDialModel::GetSaveDir(int Id)
+ {
+ // 首先检查Id是否在0~4的范围内
+ if (Id < 0 || Id > 4)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Id must be between 0 and 4.");
+ return ""; // 或者返回一个空字符串
+ }
+ // 检查 APP_CUSTOM_DIAL_PATH 是否存在
+ CreateDirectoryIfNotExists(APP_CUSTOM_DIAL_PATH);
+
+ std::string folderPath = std::string(APP_CUSTOM_DIAL_PATH) + "/" + std::to_string(Id); // 修复这一行
+ CreateDirectoryIfNotExists(folderPath); // 确保目录存在
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Directory is %s", folderPath.c_str());
+
+ return folderPath; // 返回目录路径
+ }
}
#include <vector>
#include <queue>
#include <numeric>
+#include "custom_runtime.h"
#include "traingrecord/include/TraingRecordModel.h"
#define MAX_FILE_PATH_LENGTH 128
{
// 不同的运动类型解析不同的数据
// 通用数据
-
sportdata->steps = cyweeInfo->steps;
- sportdata->distance = cyweeInfo->distance;
+ sportdata->distance = cyweeInfo->distance; // 只赋值一次
sportdata->calories = cyweeInfo->calories;
sportdata->cdc = cyweeInfo->step_frequency;
sportdata->std = cyweeInfo->step_length;
sportdata->pc = cyweeInfo->pace;
- sportdata->distance = cyweeInfo->distance;
- /*最慢配速*/
+
+ // 更新最慢配速
if (sportdata->spc < sportdata->pc)
{
sportdata->spc = sportdata->pc;
sportdata->heart = cyweeInfo->hrs;
SetIntensity(sportdata->heart); // 设置训练强度
- if (cyweeInfo->hrs > 50)
+
+ // 计算平均心率
+ if (sportdata->heart > 50)
{
- // sportdata->heart = CalculateFilteredHeartRate(cyweeInfo->hrs); // 处理显示心率
- // sportdata->avgheart = CalculateAverageHeartRate(cyweeInfo->hrs); // 处理正常的平均心率
sportdata->avgheart = Averageheartrate(sportdata->heart);
}
- // 达到最高心率进行心率提醒弹窗
- if (sportdata->heart >= ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_TRAINING_HEART_MAX))
+ // 心率提醒
+ int maxHeartRate = ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_TRAINING_HEART_MAX);
+ if (sportdata->heart >= maxHeartRate)
{
uapi_set_screen_on_api(); // 亮屏检测
custom_VibratorFunc(VibratorType::VIBRATOR_TYPE_TWO); // 震动提醒
TraingCardView::GetInstance()->SetPopupViewStatus(HeartPopup, true);
}
-#if 0
- // sportdata->duration = cyweeInfo->duration;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "normal sportdata->calories[%d],sportdata->heart[%d] \r\n", sportdata->calories, sportdata->heart);
- switch (type)
- {
- case ExerciseClass::OUTDOOR:
- case ExerciseClass::INDOOR:
- sportdata->distance = cyweeInfo->distance;
- sportdata->steps = cyweeInfo->steps;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "indoor sportdata->distance[%d],sportdata->steps[%d] \r\n", sportdata->distance, sportdata->steps);
- break;
- case ExerciseClass::FREE_TRAINING:
- break;
- default:
- break;
- }
-#endif
- /* -------------------------------------------------------------------------- */
- // 首先需要判断有没有设置训练目标,并且保障弹窗只出现一次
- if (sportdata->tag && (!Gettagstuats))
+
+ // 训练目标检查
+ if (sportdata->tag && !Gettagstuats)
{
- // 根据设置的训练目标类型去对应相对的数据
int currentdata = GetSportTagData();
if (currentdata >= sportdata->tag)
{
// 增加标志位互斥保障"开始"和"结束"的唯一性操作
if (currentState == ExerciseState::Start && !Startstate)
{
+ // 设置训练 runtime 为 1 训练中
+ uapi_dev_runtime_set_train_status(1);
+
ResetSharedTrainingData(); // 重置共享训练数据
printf("SetTimestamp::time:%u \r\n", time);
}
else if (currentState == ExerciseState::End && !Endstate)
{
+ // 设置训练 runtime 为 0 训练结束
+ uapi_dev_runtime_set_train_status(0);
+
sportdata->endtime = time;
SetEndTime();
-<dial title="maoamo" description="招财猫" size="466 466" version="1.0" preview_img="./instance/108/maomao.png">\r
+<dial title="maomao" description="招财猫" size="466 466" version="1.0" preview_img="./instance/108/maomao.png">\r
<!-- 背景 -->\r
<static_img id="back_ground" position="0 0" img_name="./instance/108/MAIN_FACE_IMAGE.png"></static_img>\r
\r