255 lines
8.9 KiB
C++
255 lines
8.9 KiB
C++
/*----------------------------------------------------------------------------
|
||
* 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
|