729 lines
24 KiB
C++
729 lines
24 KiB
C++
#include "TjdUiAppSportModel.h"
|
||
#include "TjdUiAppSportPage.h"
|
||
#include "TjdUiAppSportView.h"
|
||
#include "rtc_api.h"
|
||
#include "service_charger.h"
|
||
#include "service_hrsensor.h"
|
||
#include "sql_setting.h"
|
||
#include "sys_config.h"
|
||
#include <algorithm>
|
||
#include <dirent.h>
|
||
#include <fs_user_common.h>
|
||
#include <fstream>
|
||
#include <regex>
|
||
#include <sstream>
|
||
#include <stdio.h>
|
||
#include <unistd.h>
|
||
#include "rtc_api.h"
|
||
|
||
using namespace OHOS;
|
||
|
||
#define ENABLE_PRINT_INFO 1
|
||
#if ENABLE_PRINT_INFO
|
||
#define static_print_info(...) sys_ui_log_i(__VA_ARGS__) // 一般信息打印宏控制
|
||
#define static_print_warn(...) sys_ui_log_w(__VA_ARGS__) // 警告信息打印一般常开
|
||
#define static_print_error(...) sys_ui_log_e(__VA_ARGS__) // 错误信息打印一般常开
|
||
#define static_print_debug(...) sys_ui_log_d(__VA_ARGS__) // 调试信息打印
|
||
#else
|
||
#define static_print_info(...)
|
||
#define static_print_warn(...)
|
||
#define static_print_error(...)
|
||
#define static_print_debug(...)
|
||
#endif
|
||
|
||
namespace TJD {
|
||
#define SUCCESS 1
|
||
#define ERROR 0
|
||
#define SPORT_DATA_PATHA_NAME "/system/tjd_sport/sport_data.json"
|
||
bool TjdUiAppSportModel::GetGpsPositioningStatus(void) { return false; }
|
||
|
||
SportingData_t TjdUiAppSportModel::GetServiceSportData()
|
||
{
|
||
SportingData_t sportingData;
|
||
sportingData = tjd_service_sport_get_data();
|
||
return sportingData;
|
||
}
|
||
|
||
void TjdUiAppSportModel::RemoveFile(const char *filepath)
|
||
{
|
||
if (remove(filepath) != 0) {
|
||
static_print_info("RemoveFile删除文件失败: %s\n", filepath);
|
||
} else {
|
||
static_print_info("RemoveFile 删除文件成功: %s\n", filepath);
|
||
}
|
||
}
|
||
|
||
const char *TjdUiAppSportModel::RecordSportData() // 命名格式:sport_2024-8-20_15-54-23.json
|
||
{
|
||
static_print_info("TjdUiAppSportModel::RecordSportData\n");
|
||
struct rtc_time localTime = {0};
|
||
rtc_class_ops *rtc = tjd_driver_rtc_get_ops();
|
||
rtc->get_rtc_time(&localTime);
|
||
|
||
std::ostringstream formattedFileName;
|
||
formattedFileName << "sport_record_" << localTime.tm_year << "-" << std::setw(1) << std::setfill('0')
|
||
<< localTime.tm_mon << "-" << std::setw(1) << std::setfill('0') << localTime.tm_mday << "_"
|
||
<< std::setw(2) << std::setfill('0') << localTime.tm_hour << "-" << std::setw(2)
|
||
<< std::setfill('0') << localTime.tm_min << "-" << std::setw(2) << std::setfill('0')
|
||
<< localTime.tm_sec << ".json";
|
||
|
||
static_print_info("sport data record to fileName: %s\n", formattedFileName.str().c_str());
|
||
std::string DirPath(TJD_FS_DIR_SPORT);
|
||
url_ = DirPath + "/" + formattedFileName.str();
|
||
static_print_info("filePath: %s\n", url_.c_str());
|
||
|
||
StoreSportData(url_.c_str());
|
||
|
||
return url_.c_str();
|
||
}
|
||
|
||
std::string TjdUiAppSportModel::RenameSportDataFile(const std::string &oldFilePath)
|
||
{
|
||
struct rtc_time localTime = {0};
|
||
rtc_class_ops *rtc = tjd_driver_rtc_get_ops();
|
||
rtc->get_rtc_time(&localTime);
|
||
|
||
// 构造新的文件名
|
||
std::ostringstream formattedFileName;
|
||
formattedFileName << "sport_record_" << localTime.tm_year << "-" << std::setw(1) << std::setfill('0')
|
||
<< localTime.tm_mon << "-" << std::setw(1) << std::setfill('0') << localTime.tm_mday << "_"
|
||
<< std::setw(2) << std::setfill('0') << localTime.tm_hour << "-" << std::setw(2)
|
||
<< std::setfill('0') << localTime.tm_min << "-" << std::setw(2) << std::setfill('0')
|
||
<< localTime.tm_sec << ".json";
|
||
|
||
std::string DirPath(TJD_FS_DIR_SPORT);
|
||
std::string newFilePath = DirPath + "/" + formattedFileName.str();
|
||
|
||
// 尝试重命名文件
|
||
if (std::rename(oldFilePath.c_str(), newFilePath.c_str()) == 0) {
|
||
static_print_info("file rename success\n");
|
||
} else {
|
||
static_print_info("file rename fail\n");
|
||
}
|
||
|
||
return newFilePath;
|
||
printf("oldFilePath: %s\n", oldFilePath.c_str());
|
||
printf("newFilePath: %s\n", newFilePath.c_str());
|
||
}
|
||
|
||
void TjdUiAppSportModel::StoreSportData(const char *url)
|
||
{
|
||
auto sportingView = SportingView::GetInstance();
|
||
uint64_t timestamp = 0;
|
||
tjd_driver_rtc_get_ops()->get_timestamp(×tamp);
|
||
cJSON *jsonData = cJSON_CreateObject();
|
||
cJSON_AddNumberToObject(jsonData, "SportIconIndex", TjdUiAppSportView::currentIconIndex_ + 1);
|
||
cJSON_AddNumberToObject(jsonData, "StartTime", timestamp);
|
||
cJSON_AddNumberToObject(jsonData, "Time", 5);
|
||
cJSON_AddNumberToObject(jsonData, "GPS_Status", GPSGetData().valid);
|
||
cJSON_AddStringToObject(jsonData, "SportTime", sportingView->sportingRtcLabel_.GetText());
|
||
cJSON_AddStringToObject(jsonData, "HeartRate", sportingView->heartRateLabel_.GetText());
|
||
cJSON_AddStringToObject(jsonData, "Calories", sportingView->caloriesLabel_.GetText());
|
||
|
||
switch (SportingView::sportType) {
|
||
case SPORT_TYPE_1:
|
||
cJSON_AddStringToObject(jsonData, "Distance", sportingView->distanceLabel_.GetText());
|
||
cJSON_AddStringToObject(jsonData, "Speed", "00'00''");
|
||
cJSON_AddStringToObject(jsonData, "Step", sportingView->stepLabel_.GetText());
|
||
cJSON_AddStringToObject(jsonData, "Frequency", "0.0");
|
||
break;
|
||
case SPORT_TYPE_2:
|
||
cJSON_AddStringToObject(jsonData, "Distance", sportingView->distanceLabel_.GetText());
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// 创建运动轨迹数组
|
||
cJSON *trackArray = cJSON_CreateArray();
|
||
|
||
// 将运动轨迹数组添加到 JSON 对象
|
||
cJSON_AddItemToObject(jsonData, "Position", trackArray);
|
||
|
||
FILE *outputFile = fopen(url, "w");
|
||
if (outputFile) {
|
||
char *jsonString = cJSON_Print(jsonData);
|
||
|
||
if (jsonString) {
|
||
fprintf(outputFile, "%s", jsonString);
|
||
free(jsonString);
|
||
}
|
||
fclose(outputFile); // 关闭文件
|
||
} else {
|
||
static_print_info("无法打开文件进行写入\n");
|
||
}
|
||
|
||
cJSON_Delete(jsonData);
|
||
}
|
||
|
||
void TjdUiAppSportModel::UpdateSportData(const char *url)
|
||
{
|
||
// printf("TjdUiAppSportModel::UpdateSportData,url:%s\n", url);
|
||
auto sportingView = SportingView::GetInstance();
|
||
// 打开文件并读取内容
|
||
FILE *inputFile = fopen(url, "r");
|
||
if (!inputFile) {
|
||
static_print_info("无法打开文件进行读取\n");
|
||
return;
|
||
}
|
||
|
||
fseek(inputFile, 0, SEEK_END);
|
||
long fileSize = ftell(inputFile);
|
||
fseek(inputFile, 0, SEEK_SET);
|
||
|
||
char *fileContent = (char *)malloc(fileSize + 1);
|
||
fread(fileContent, 1, fileSize, inputFile);
|
||
fileContent[fileSize] = '\0';
|
||
fclose(inputFile);
|
||
|
||
cJSON *jsonData = cJSON_Parse(fileContent);
|
||
free(fileContent);
|
||
|
||
if (!jsonData) {
|
||
static_print_info("解析 JSON 失败\n");
|
||
return;
|
||
}
|
||
|
||
// 更新指定键的值
|
||
cJSON_ReplaceItemInObject(jsonData, "SportTime",
|
||
cJSON_CreateString(std::string(sportingView->sportingRtcLabel_.GetText()).c_str()));
|
||
|
||
cJSON_ReplaceItemInObject(jsonData, "HeartRate",
|
||
cJSON_CreateString(std::string(sportingView->heartRateLabel_.GetText()).c_str()));
|
||
|
||
cJSON_ReplaceItemInObject(jsonData, "Calories",
|
||
cJSON_CreateString(std::string(sportingView->caloriesLabel_.GetText()).c_str()));
|
||
|
||
Time time = TjdUiAppSportView::GetInstance()->GetCurrentTime(sportingView->sportingRtcLabel_.GetText());
|
||
uint32_t totalTime = time.hours * 3600 + time.minutes * 60 + time.seconds;
|
||
|
||
cJSON_ReplaceItemInObject(jsonData, "Time", cJSON_CreateNumber(totalTime));
|
||
|
||
float distance = std::stof(std::string(SportingView::GetInstance()->distanceLabel_.GetText()));
|
||
uint32_t step = std::stoi(std::string(SportingView::GetInstance()->stepLabel_.GetText()));
|
||
|
||
// 根据运动类型更新其他键值
|
||
switch (SportingView::sportType) {
|
||
case SPORT_TYPE_1:
|
||
cJSON_ReplaceItemInObject(jsonData, "Distance",
|
||
cJSON_CreateString(std::string(sportingView->distanceLabel_.GetText()).c_str()));
|
||
if (distance) {
|
||
float pace = totalTime / distance / 60.0;
|
||
|
||
int minutes = static_cast<int>(pace);
|
||
int seconds = static_cast<int>((pace - minutes) * 60);
|
||
|
||
// 创建带单引号的目标字符串
|
||
stringstream finalStr;
|
||
finalStr << minutes << "'" << setw(2) << setfill('0') << seconds << "\"";
|
||
cJSON_ReplaceItemInObject(jsonData, "Speed", cJSON_CreateString(finalStr.str().c_str()));
|
||
|
||
} else
|
||
cJSON_ReplaceItemInObject(jsonData, "Speed", cJSON_CreateString("00'00\""));
|
||
|
||
cJSON_ReplaceItemInObject(jsonData, "Step",
|
||
cJSON_CreateString(std::string(sportingView->stepLabel_.GetText()).c_str()));
|
||
|
||
if (distance) {
|
||
// 计算步频
|
||
float frequency = distance * 1000 / step;
|
||
|
||
std::ostringstream oss;
|
||
oss << std::fixed << std::setprecision(1) << frequency; // 保留2位小数
|
||
|
||
cJSON_ReplaceItemInObject(jsonData, "Frequency",
|
||
cJSON_CreateString(oss.str().c_str())); // 需要改
|
||
} else
|
||
cJSON_ReplaceItemInObject(jsonData, "Frequency", cJSON_CreateString("0.0"));
|
||
|
||
break;
|
||
case SPORT_TYPE_2:
|
||
cJSON_ReplaceItemInObject(
|
||
jsonData, "Distance",
|
||
cJSON_CreateString(std::string(std::string(sportingView->distanceLabel_.GetText()) + std::string(" ") +
|
||
std::string(sportingView->distanceUnitLabel_.GetText()))
|
||
.c_str()));
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// 将更新后的 JSON 数据写回文件
|
||
FILE *outputFile = fopen(url, "w");
|
||
if (outputFile) {
|
||
char *jsonString = cJSON_Print(jsonData);
|
||
if (jsonString) {
|
||
fprintf(outputFile, "%s", jsonString);
|
||
free(jsonString);
|
||
}
|
||
fclose(outputFile); // 关闭文件
|
||
} else {
|
||
static_print_info("无法打开文件进行写入\n");
|
||
}
|
||
|
||
cJSON_Delete(jsonData); // 释放 JSON 对象
|
||
}
|
||
|
||
void TjdUiAppSportModel::AddDataToArry(const char *url, double newLatitude, double newLongitude)
|
||
{
|
||
// 打开文件并读取内容
|
||
FILE *inputFile = fopen(url, "r");
|
||
if (!inputFile) {
|
||
static_print_info("AddDataToArry Failed\n");
|
||
return;
|
||
}
|
||
|
||
// 获取文件大小
|
||
fseek(inputFile, 0, SEEK_END);
|
||
long fileSize = ftell(inputFile);
|
||
fseek(inputFile, 0, SEEK_SET);
|
||
|
||
// 读取文件内容到字符串
|
||
char *fileContent = (char *)malloc(fileSize + 1);
|
||
fread(fileContent, 1, fileSize, inputFile);
|
||
fileContent[fileSize] = '\0'; // 添加字符串结束符
|
||
fclose(inputFile); // 关闭文件
|
||
|
||
// 解析 JSON 数据
|
||
cJSON *jsonData = cJSON_Parse(fileContent);
|
||
free(fileContent); // 释放内存
|
||
|
||
if (!jsonData) {
|
||
static_print_info("解析 JSON 失败\n");
|
||
return;
|
||
}
|
||
|
||
// 查找运动轨迹数组
|
||
cJSON *trackArray = cJSON_GetObjectItem(jsonData, "Position");
|
||
if (!trackArray || !cJSON_IsArray(trackArray)) {
|
||
static_print_info("运动轨迹数组不存在或不是数组类型\n");
|
||
cJSON_Delete(jsonData); // 释放 JSON 对象
|
||
return;
|
||
}
|
||
|
||
// 添加新的轨迹点
|
||
cJSON *newTrackPoint = cJSON_CreateObject();
|
||
cJSON_AddNumberToObject(newTrackPoint, "latitude", isnan(newLatitude)? 0 : newLatitude);
|
||
cJSON_AddNumberToObject(newTrackPoint, "longitude", isnan(newLongitude)? 0 : newLongitude);
|
||
cJSON_AddItemToArray(trackArray, newTrackPoint); // 添加新轨迹点到数组
|
||
|
||
// 将修改后的 JSON 数据写回文件
|
||
FILE *outputFile = fopen(url, "w");
|
||
if (outputFile) {
|
||
char *jsonString = cJSON_Print(jsonData);
|
||
if (jsonString) {
|
||
fprintf(outputFile, "%s", jsonString);
|
||
free(jsonString);
|
||
}
|
||
fclose(outputFile); // 关闭文件
|
||
} else {
|
||
static_print_info("无法打开文件进行写入\n");
|
||
}
|
||
|
||
cJSON_Delete(jsonData); // 释放 JSON 对象
|
||
}
|
||
|
||
std::vector<std::string> TjdUiAppSportModel::SearchAndRecordFilepath()
|
||
{
|
||
std::string path = TJD_FS_DIR_SPORT;
|
||
std::vector<std::string> fileList;
|
||
struct dirent *entry;
|
||
DIR *dp = opendir(path.c_str());
|
||
|
||
if (dp == nullptr) {
|
||
static_print_info("SearchAndRecordFilepath 无法打开目录");
|
||
return fileList;
|
||
}
|
||
|
||
while ((entry = readdir(dp)) != nullptr) {
|
||
std::string filename = entry->d_name;
|
||
// 检查文件名是否以 "sport_record_" 开头且以 ".json" 结尾
|
||
if (filename.rfind("sport_record_", 0) == 0 && filename.size() > 5 &&
|
||
filename.compare(filename.size() - 5, 5, ".json") == 0) {
|
||
fileList.push_back(path + "/" + filename);
|
||
}
|
||
}
|
||
|
||
closedir(dp);
|
||
|
||
std::sort(fileList.begin(), fileList.end(), [](const std::string &a, const std::string &b) {
|
||
size_t startA = a.find_last_of('_') + 1;
|
||
size_t startB = b.find_last_of('_') + 1;
|
||
std::string timeA = a.substr(startA, 19);
|
||
std::string timeB = b.substr(startB, 19);
|
||
return timeA < timeB;
|
||
});
|
||
|
||
// 输出文件数量和路径
|
||
static_print_info("文件数量: %d\n", fileList.size());
|
||
for (const auto &file : fileList) {
|
||
static_print_info("filePath: %s\n", file.c_str());
|
||
}
|
||
|
||
return fileList;
|
||
}
|
||
|
||
// 创建JSON对象
|
||
cJSON *TjdUiAppSportModel::CreateSportsJson(SportInfo *dataArry, int count)
|
||
{
|
||
cJSON *root = cJSON_CreateArray();
|
||
|
||
for (int i = 0; i < count; ++i) {
|
||
cJSON *sport = cJSON_CreateObject();
|
||
cJSON_AddNumberToObject(sport, "sportTypeId", dataArry[i].sportTypeId);
|
||
cJSON_AddNumberToObject(sport, "typeIndex", dataArry[i].index);
|
||
cJSON_AddBoolToObject(sport, "state", dataArry[i].state);
|
||
cJSON_AddItemToArray(root, sport);
|
||
}
|
||
|
||
return root;
|
||
}
|
||
|
||
// 保存JSON到文件
|
||
void TjdUiAppSportModel::SaveJsonToFile(const char *filename, cJSON *json)
|
||
{
|
||
char *jsonString = cJSON_Print(json);
|
||
if (jsonString) {
|
||
FILE *file = fopen(filename, "w");
|
||
if (file) {
|
||
fprintf(file, "%s", jsonString);
|
||
fclose(file);
|
||
} else {
|
||
fprintf(stderr, "Failed to open file for writing.\n");
|
||
}
|
||
free(jsonString);
|
||
} else {
|
||
fprintf(stderr, "Failed to print JSON.\n");
|
||
}
|
||
}
|
||
|
||
cJSON *TjdUiAppSportModel::ReadAndParseJson(const char *fliePath)
|
||
{
|
||
char *json_string = ReadFileToString(fliePath);
|
||
if (json_string == NULL) {
|
||
fprintf(stderr, "Failed to read file\n");
|
||
// return nullptr;
|
||
}
|
||
|
||
cJSON *json = ParseJson(json_string);
|
||
return json;
|
||
}
|
||
|
||
// 与ReadAndParseJson配套使用,使用完需要释放json内存
|
||
char *TjdUiAppSportModel::KeyValueAnalysis(cJSON *json, const char *key) // 键值解析
|
||
{
|
||
cJSON *target_json = cJSON_GetObjectItem(json, key);
|
||
|
||
if (cJSON_IsString(target_json) && target_json->valuestring != NULL) {
|
||
printf("KeyValueAnalysis = %s: %s\n", key, target_json->valuestring);
|
||
}
|
||
|
||
return target_json->valuestring;
|
||
}
|
||
|
||
std::vector<Coordinate>
|
||
TjdUiAppSportModel::TrackAnalysis(cJSON *json) // 与ReadAndParseJson配套使用,减少读取文件系统次数
|
||
{
|
||
std::vector<Coordinate> coordinates;
|
||
cJSON *track = cJSON_GetObjectItem(json, "Position");
|
||
if (cJSON_IsArray(track)) {
|
||
printf("%s========:\n", "Position");
|
||
int track_size = cJSON_GetArraySize(track);
|
||
printf(" 轨迹点数量: %d\n", track_size);
|
||
|
||
coordinates.reserve(track_size); // 提前为 vector 预分配空间,避免多次重新分配
|
||
|
||
for (int i = 0; i < track_size; i++) {
|
||
cJSON *coord = cJSON_GetArrayItem(track, i);
|
||
cJSON *latitude = cJSON_GetObjectItem(coord, "latitude");
|
||
cJSON *longitude = cJSON_GetObjectItem(coord, "longitude");
|
||
|
||
if (cJSON_IsNumber(latitude) && cJSON_IsNumber(longitude)) {
|
||
Coordinate coord_point;
|
||
coord_point.latitude = latitude->valuedouble;
|
||
coord_point.longitude = longitude->valuedouble;
|
||
coordinates.push_back(coord_point);
|
||
}
|
||
}
|
||
}
|
||
// 释放 JSON 对象
|
||
// cJSON_Delete(json);
|
||
|
||
return coordinates;
|
||
}
|
||
|
||
/// @brief 创建JSON对象并保存到文件
|
||
void TjdUiAppSportModel::CreateJsonAndSaveToFile(SportInfo *dataArry, uint8_t count)
|
||
{
|
||
cJSON *sportsJson = CreateSportsJson(dataArry, count);
|
||
SaveJsonToFile(SPORT_DATA_PATHA_NAME, sportsJson);
|
||
cJSON_Delete(sportsJson); // 记得释放内存
|
||
}
|
||
|
||
// 读取文件内容到字符串
|
||
char *TjdUiAppSportModel::ReadFileToString(const char *filename)
|
||
{
|
||
FILE *file = fopen(filename, "r");
|
||
if (file == NULL)
|
||
return NULL;
|
||
|
||
fseek(file, 0, SEEK_END);
|
||
long length = ftell(file);
|
||
fseek(file, 0, SEEK_SET);
|
||
|
||
char *buffer = (char *)malloc(length + 1);
|
||
if (buffer == NULL) {
|
||
fclose(file);
|
||
return NULL;
|
||
}
|
||
|
||
fread(buffer, 1, length, file);
|
||
buffer[length] = '\0'; // Null-terminate the string
|
||
|
||
fclose(file);
|
||
return buffer;
|
||
}
|
||
|
||
// 解析JSON字符串
|
||
cJSON *TjdUiAppSportModel::ParseJson(const char *json_string) { return cJSON_Parse(json_string); }
|
||
|
||
// 转换JSON到SportInfo数组
|
||
SportInfo *TjdUiAppSportModel::JsonToSportInfo(const cJSON *json, size_t *count)
|
||
{
|
||
if (!cJSON_IsArray(json))
|
||
return NULL;
|
||
|
||
*count = cJSON_GetArraySize(json);
|
||
SportInfo *sports = (SportInfo *)malloc(*count * sizeof(SportInfo));
|
||
if (sports == NULL)
|
||
return NULL;
|
||
|
||
for (size_t i = 0; i < *count; ++i) {
|
||
cJSON *item = cJSON_GetArrayItem(json, i);
|
||
if (!cJSON_IsObject(item))
|
||
continue;
|
||
|
||
cJSON *index = cJSON_GetObjectItemCaseSensitive(item, "typeIndex");
|
||
cJSON *state = cJSON_GetObjectItemCaseSensitive(item, "state");
|
||
|
||
if (cJSON_IsNumber(index) && cJSON_IsBool(state)) {
|
||
sports[i].index = static_cast<SportTypeIndex>(index->valueint);
|
||
sports[i].state = state->valueint;
|
||
}
|
||
}
|
||
return sports;
|
||
}
|
||
|
||
// 读取文件内容并转换JSON到SportInfo数组
|
||
SportInfo *TjdUiAppSportModel::ReadFileAndTransformToJson()
|
||
{
|
||
char *json_string = ReadFileToString(SPORT_DATA_PATHA_NAME);
|
||
if (json_string == NULL) {
|
||
fprintf(stderr, "Failed to read file\n");
|
||
return nullptr;
|
||
}
|
||
|
||
cJSON *json = ParseJson(json_string);
|
||
free(json_string); // No longer needed after parsing
|
||
|
||
if (json == NULL) {
|
||
fprintf(stderr, "Failed to parse JSON\n");
|
||
return nullptr;
|
||
}
|
||
|
||
size_t count = 0;
|
||
SportInfo *sportsData = JsonToSportInfo(json, &count);
|
||
cJSON_Delete(json); // Clean up after parsing
|
||
|
||
if (sportsData == NULL) {
|
||
fprintf(stderr, "Failed to convert JSON to SportInfo\n");
|
||
return nullptr;
|
||
}
|
||
|
||
return sportsData;
|
||
}
|
||
|
||
// 修改SportInfo数组中指定运动项目的状态: 0:未添加 1:已添加
|
||
void TjdUiAppSportModel::ChangeOneSportState(cJSON *jsonArray, int typeIndex, bool new_state)
|
||
{
|
||
if (jsonArray == NULL) {
|
||
fprintf(stderr, "Failed to parse JSON\n");
|
||
return;
|
||
}
|
||
int array_size = cJSON_GetArraySize(jsonArray);
|
||
for (int i = 0; i < array_size; i++) {
|
||
cJSON *item = cJSON_GetArrayItem(jsonArray, i);
|
||
// if (item == NULL) {
|
||
// static_print_info("Failed to get JSON array item\n");
|
||
// continue;
|
||
// }
|
||
cJSON *index = cJSON_GetObjectItem(item, "typeIndex");
|
||
// if (index == NULL || index->type != cJSON_Number) {
|
||
// static_print_info("Invalid or missing 'typeIndex' item\n");
|
||
// continue;
|
||
// }
|
||
if (index && index->valueint == typeIndex) {
|
||
cJSON *state = cJSON_GetObjectItem(item, "state");
|
||
if (state == NULL) {
|
||
static_print_info("Invalid or missing 'state' item\n");
|
||
continue;
|
||
}
|
||
cJSON_ReplaceItemInObject(item, "state", cJSON_CreateBool(new_state));
|
||
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
void TjdUiAppSportModel::ReadAndChangeSportState(int typeIndex, bool new_state)
|
||
{
|
||
char *json_string = ReadFileToString(SPORT_DATA_PATHA_NAME);
|
||
|
||
cJSON *json = cJSON_Parse(json_string);
|
||
if (json == NULL) {
|
||
fprintf(stderr, "Failed to parse JSON\n");
|
||
return;
|
||
}
|
||
|
||
ChangeOneSportState(json, typeIndex, new_state);
|
||
SaveJsonToFile(SPORT_DATA_PATHA_NAME, json);
|
||
cJSON_Delete(json);
|
||
free(json_string);
|
||
}
|
||
|
||
void TjdUiAppSportModel::SqlSetGoalSportCalorie(int calorie) { /*sql_fit_set_goal_sport_calorie(calorie);*/ }
|
||
|
||
void TjdUiAppSportModel::SetIfSportSuspend(bool state) { tjd_service_sport_set_if_suspend(state); }
|
||
|
||
void TjdUiAppSportModel::GPSServiceOpen(void) { tjd_service_gps_open(); }
|
||
|
||
void TjdUiAppSportModel::GPSServiceClose(void) { tjd_service_gps_close(); }
|
||
|
||
gnss_data_t TjdUiAppSportModel::GPSGetData(void)
|
||
{
|
||
gnss_data_t rmc_data;
|
||
tjd_service_gps_get_data(&rmc_data);
|
||
|
||
return rmc_data;
|
||
}
|
||
|
||
uint8_t TjdUiAppSportModel::SetDistancePopUpRemind(std::string distStr)
|
||
{
|
||
tjd_service_sport_set_if_popup(false);
|
||
service_reset_sport_pop_up_flag();
|
||
service_set_pop_up_flag(SPORT_POPUP_MSG_TYPE_DISTANCE, true);
|
||
|
||
size_t pos = distStr.find_first_of("0123456789");
|
||
std::string numberStr = distStr.substr(pos, distStr.size() - pos - 1);
|
||
int distance = std::stoi(numberStr);
|
||
service_set_goal_sport_dist(distance);
|
||
// sql_fit_set_goal_sport_dist(0);// 用于调试测试
|
||
// static_print_info("=====distance goal = %d", distance);
|
||
return SUCCESS;
|
||
}
|
||
|
||
uint8_t TjdUiAppSportModel::SetTimePopUpRemind(std::string timeStr)
|
||
{
|
||
tjd_service_sport_set_if_popup(false);
|
||
service_reset_sport_pop_up_flag();
|
||
service_set_pop_up_flag(SPORT_POPUP_MSG_TYPE_TIME, true);
|
||
std::regex pattern("(\\d{2})H(\\d{2})min");
|
||
std::smatch matches;
|
||
if (std::regex_match(timeStr, matches, pattern)) {
|
||
// 提取小时和分钟
|
||
int hours = std::stoi(matches[1].str());
|
||
int minutes = std::stoi(matches[2].str());
|
||
int seconds = hours * 3600 + minutes * 60;
|
||
service_set_sport_goal_time(seconds);
|
||
static_print_info("======set sport goal time %d=====\n", seconds);
|
||
return SUCCESS;
|
||
}
|
||
|
||
return ERROR;
|
||
}
|
||
|
||
uint8_t TjdUiAppSportModel::SetCaloriesPopUpRemind(std::string calStr)
|
||
{
|
||
tjd_service_sport_set_if_popup(false);
|
||
service_reset_sport_pop_up_flag();
|
||
service_set_pop_up_flag(SPORT_POPUP_MSG_TYPE_CALORIES, true);
|
||
// std::string calStr = "100Kcal"; // 用于调试测试
|
||
std::string numberStr;
|
||
|
||
for (char ch : calStr) {
|
||
if (std::isdigit(ch)) {
|
||
numberStr += ch;
|
||
} else {
|
||
break; // 遇到非数字字符则停止
|
||
}
|
||
}
|
||
|
||
int calories = std::stoi(numberStr);
|
||
service_set_goal_sport_calorie(calories);
|
||
// static_print_info("=====calories goal = %d", calories);
|
||
return SUCCESS;
|
||
}
|
||
|
||
void TjdUiAppSportModel::SetSportEndRemindType(uint8_t type) { tjd_service_sport_set_end_remind_type(type); }
|
||
|
||
void TjdUiAppSportModel::SetSportType(uint8_t type) { tjd_service_sport_set_sport_type(type); }
|
||
|
||
uint8_t TjdUiAppSportModel::GetCurHeartRateValue(void) { return tjd_service_hrsensor_get_cur_hrvalue(); }
|
||
|
||
uint8_t TjdUiAppSportModel::GetBatteryValue(void) { return tjd_service_charger_get_battery(); }
|
||
|
||
uint32_t TjdUiAppSportModel::GetMotionOutTime(void) { return sql_setting_get_motion_out_time(); }
|
||
|
||
uint8_t TjdUiAppSportModel::SportHeartRateControlHandler(SportingAction action, void *param)
|
||
{
|
||
uint8_t ret = 0;
|
||
hr_api_info_t hr_api_info = {HR_SERVICE_UI_SPORT, 0xffffffff};
|
||
service_hrs_api *hrsensorInfo = tjd_service_hrs_get_ops();
|
||
|
||
switch (action) {
|
||
case SportingAction::Start:
|
||
hrsensorInfo->open(hr_api_info);
|
||
break;
|
||
case SportingAction::Stop:
|
||
hrsensorInfo->close();
|
||
break;
|
||
case SportingAction::GetStatus:
|
||
// ret = HeartRateGetWearStatus();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
void GetGnssGsvDataProcess(const struct minmea_sentence_gsv *frame)
|
||
{
|
||
// clang-format on
|
||
for (int i = 0; i < 4; i++) {
|
||
if (i == 0) {
|
||
TjdUiAppSportModel::GetInstance()->SetMaxSnr(frame->sats[0].snr);
|
||
}
|
||
|
||
if (frame->sats[i].snr > TjdUiAppSportModel::GetInstance()->GetMaxSnr()) {
|
||
TjdUiAppSportModel::GetInstance()->SetMaxSnr(frame->sats[i].snr);
|
||
}
|
||
printf("snr: %d\n", frame->sats[i].snr);
|
||
}
|
||
}
|
||
|
||
void TjdUiAppSportModel::RegisterGnssChangedCB(void)
|
||
{
|
||
gnss_service_cb_t gnssServiceCb = {.service_changed_cb = nullptr,
|
||
.rmc_status_cb = nullptr,
|
||
.gsv_status_cb = GetGnssGsvDataProcess,
|
||
.zda_status_cb = nullptr,
|
||
.gga_status_cb = nullptr,
|
||
.vtg_status_cb = nullptr};
|
||
register_gnss_changed_cb(&gnssServiceCb);
|
||
}
|
||
|
||
void TjdUiAppSportModel::UnregisterGnssChangedCB(void) { unregister_gnss_changed_cb(); }
|
||
|
||
} // namespace TJD
|