mcu_hi3321_watch/tjd/ui/common/TjdDialModelTime.cpp
2025-05-26 20:15:20 +08:00

255 lines
8.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*----------------------------------------------------------------------------
* Copyright (c) TJD Technologies Co., Ltd. 2025. All rights reserved.
*
* Description: TjdDialModelTime.cpp
*
* Author: luziquan@ss-tjd.com
*
* Create: 2025-03-19
*--------------------------------------------------------------------------*/
#include "TjdDialModelTime.h"
#include "DialModelTime.h"
#include "RegisterDialModel.h"
#include "TjdUiMultiLanguageExt.h"
#include "animator/easing_equation.h"
#include "common/task.h"
#include "service_gsensor.h"
#include "sql_setting.h"
#include "sql_weather.h"
#include "sys/time.h"
#include <vector>
namespace std {
template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi)
{
return (v < lo) ? lo : (hi < v) ? hi : v;
}
} // namespace std
namespace TJD {
// clang-format off
#define REGIST_DIAL_MODULE_AM_PM(type, func) static OHOS::RegisterDialModel(TJD_AM_PM)(type, func)
#define REGIST_DIAL_MODULE_GSENSOR_ROTATE(type, func) static OHOS::RegisterDialModel(TJD_GSENSOR_ROTATE)(type, func)
#define REGIST_DIAL_MODULE_WEATHER(type, func) static OHOS::RegisterDialModel(TJD_WEATHER)(type, func)
#define REGIST_DIAL_MODULE_TEMPERATURE(type, func) static OHOS::RegisterDialModel(TJD_TEMPERATURE)(type, func)
#define REGIST_DIAL_MODULE_TEMPERATURE_TYPE(type, func) static OHOS::RegisterDialModel(TJD_TEMPERATURE_TYPE)(type, func)
#define REGIST_DIAL_MODULE_TEMPERATURE_MAX(type, func) static OHOS::RegisterDialModel(TJD_TEMPERATURE_MAX)(type, func)
#define REGIST_DIAL_MODULE_TEMPERATURE_MIN(type, func) static OHOS::RegisterDialModel(TJD_TEMPERATURE_MIN)(type, func)
#define REGIST_DIAL_MODULE_WEEK_MULTILINGUAL(type, func) static OHOS::RegisterDialModel(TJD_WEEK_MULTILINGUAL)(type, func)
REGIST_DIAL_MODULE_AM_PM(OHOS::DialDataType::TJD_AM_PM, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_GSENSOR_ROTATE(OHOS::DialDataType::TJD_GSENSOR_ROTATE, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_WEATHER(OHOS::DialDataType::TJD_WEATHER, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_TEMPERATURE(OHOS::DialDataType::TJD_TEMPERATURE, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_TEMPERATURE_TYPE(OHOS::DialDataType::TJD_TEMPERATURE_TYPE, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_TEMPERATURE_MAX(OHOS::DialDataType::TJD_TEMPERATURE_MAX, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_TEMPERATURE_MIN(OHOS::DialDataType::TJD_TEMPERATURE_MIN, TjdDialModelTime::GetInstance());
REGIST_DIAL_MODULE_WEEK_MULTILINGUAL(OHOS::DialDataType::TJD_WEEK_MULTILINGUAL, TjdDialModelTime::GetInstance());
// clang-format on
class RotateCalculator : OHOS::Task
{
public:
RotateCalculator()
: isInit_(false), accumulatedAngle_(0.0f), displayAngle_(0.0f), targetAccumulated_(0.0f),
startAccumulated_(0.0f), deltaAngle_(0.0f), curTime_(0), durationTime_(DURATION_TIME), period_(50)
{}
~RotateCalculator() override {}
static RotateCalculator &GetInstance()
{
static RotateCalculator instance;
return instance;
}
bool IsInit() { return isInit_; }
void Init() override
{
OHOS::Task::Init();
isInit_ = true;
}
void Deinit() override
{
OHOS::Task::Deinit();
isInit_ = false;
accumulatedAngle_ = 0.0f;
displayAngle_ = 0.0f;
targetAccumulated_ = 0.0f;
startAccumulated_ = 0.0f;
deltaAngle_ = 0.0f;
curTime_ = 0;
}
void ProcessGsensor(const float *axAcc, uint16_t frames)
{
std::vector<float> axAccVec(axAcc, axAcc + frames);
auto axAccMax = *std::max_element(axAccVec.begin(), axAccVec.end());
auto axAccMin = *std::min_element(axAccVec.begin(), axAccVec.end());
int16_t axAccAbs = static_cast<int16_t>(std::abs(axAccMax - axAccMin));
// printf("axAccMax:%f, axAccMin:%f, axAccAbs:%d\n", axAccMax, axAccMin, axAccAbs);
if (axAccAbs <= 30) {
return;
}
int16_t angle = OHOS::EasingEquation::CircEaseOut(0, 3600, axAccAbs, 100);
SetRotate(static_cast<float>(angle));
}
void Callback() override
{
if (curTime_ >= durationTime_) {
factor_ = factor_ * 0.99f;
accumulatedAngle_ += factor_;
displayAngle_ = fmod(accumulatedAngle_, 360.0f);
// printf("slow accumulatedAngle_:%f, displayAngle_:%f, factor_:%f\n", accumulatedAngle_, displayAngle_,
// factor_);
return;
}
float t = curTime_ / (float)durationTime_;
float currentSpeed = (2.0f - 2.0f * t) * deltaAngle_ / durationTime_;
factor_ = currentSpeed * period_;
curTime_ += period_;
accumulatedAngle_ += factor_;
displayAngle_ = fmod(accumulatedAngle_, 360.0f);
// printf("Normal accumulatedAngle_:%f, displayAngle_:%f, factor_:%f\n", accumulatedAngle_, displayAngle_,
// factor_);
}
// 设置绝对滚动值
void SetRotate(float deltaAngle)
{
targetAccumulated_ += deltaAngle; // 直接叠加增量角度
startAccumulated_ = accumulatedAngle_;
deltaAngle_ = targetAccumulated_ - startAccumulated_;
curTime_ = 0;
factor_ = (2.0f * deltaAngle_ / durationTime_) * period_; // 初始化速度
}
float GetRotateAngle() { return displayAngle_; }
void SetRotateFactor(float factor) { factor_ = factor; }
private:
static constexpr uint16_t DURATION_TIME = 5000;
bool isInit_;
float accumulatedAngle_; // 实际累计角度(含多圈)
float displayAngle_; // 显示角度0-360
float targetAccumulated_; // 目标累计角度
float startAccumulated_; // 动画起点累计角度
float deltaAngle_; // 本次动画需要转动的增量
uint16_t curTime_;
uint16_t durationTime_;
uint16_t period_;
float factor_;
};
TjdDialModelTime::TjdDialModelTime() {}
TjdDialModelTime *TjdDialModelTime::GetInstance()
{
static TjdDialModelTime instance;
return &instance;
}
void TjdDialModelTime::Unload()
{
if (RotateCalculator::GetInstance().IsInit()) {
RotateCalculator::GetInstance().Deinit();
}
}
bool TjdDialModelTime::GetDialFloatData(OHOS::DialDataType &type, float &out)
{
if (tblock_ == nullptr) {
UpdateTime();
}
switch (type) {
case OHOS::DialDataType::TJD_WEEK_MULTILINGUAL:
if (TjdUiMultiLanguageExt::GetCurrentLanguage() == TjdUiLanguageId::LANGUAGE_ID_CHS) {
out = static_cast<float>(tblock_->tm_wday);
} else {
out = static_cast<float>(tblock_->tm_wday) + 7;
}
break;
case OHOS::DialDataType::TJD_AM_PM:
out = (tblock_->tm_hour >= 12 ? 1 : 0);
break;
case OHOS::DialDataType::TJD_GSENSOR_ROTATE:
out = GetRotateAngle();
break;
case OHOS::DialDataType::TJD_WEATHER:
out = static_cast<float>(sql_weather_get_forecast_protocol_value(0));
break;
case OHOS::DialDataType::TJD_TEMPERATURE:
out = static_cast<float>(sql_weather_get_now_temperature());
break;
case OHOS::DialDataType::TJD_TEMPERATURE_TYPE:
out = static_cast<float>(sql_weather_get_temper_unit());
break;
case OHOS::DialDataType::TJD_TEMPERATURE_MAX:
out = static_cast<float>(sql_weather_get_forecast_temperature_max(0));
break;
case OHOS::DialDataType::TJD_TEMPERATURE_MIN:
out = static_cast<float>(sql_weather_get_forecast_temperature_min(0));
break;
default:
return false;
}
return true;
}
bool TjdDialModelTime::GetDialTextData(OHOS::DialDataType &type, std::string *&out, int16_t &strNum)
{
if (tblock_ == nullptr) {
UpdateTime();
}
switch (type) {
default:
return false;
}
return true;
}
bool TjdDialModelTime::GetDialFloatData(OHOS::DialDataType &type, float *&out, int16_t len)
{
if (tblock_ == nullptr) {
UpdateTime();
}
switch (type) {
case OHOS::DialDataType::TJD_AM_PM:
// out = static_cast<float>(tblock_->tm_hour >= 12 ? 1.0 : 0.0);
break;
default:
return false;
}
return true;
}
void TjdDialModelTime::UpdateTime()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
tblock_ = localtime(&tv.tv_sec);
}
float TjdDialModelTime::GetRotateAngle()
{
RotateCalculator &retateControl = RotateCalculator::GetInstance();
if (!retateControl.IsInit()) {
retateControl.Init();
retateControl.SetRotate(0.0f);
}
// 新增Gsensor数据获取
uint16_t frames = tjd_service_gs_get_fifo_count(GSEN_SERVICE_PRODUCTION);
gsensor_xyz_info *xyzInfo = (gsensor_xyz_info *)malloc(sizeof(gsensor_xyz_info) * frames);
tjd_service_gs_get_xyz_fifo(GSEN_SERVICE_PRODUCTION, xyzInfo, frames);
float axAcc[32] = {0}; //单位m/s^2
for (int i = 0; i < frames; i++) {
axAcc[i] = (xyzInfo[i].gsensor_y.raw_data * 0.00239);
}
retateControl.ProcessGsensor(axAcc, frames);
return retateControl.GetRotateAngle();
}
} // namespace TJD