/*---------------------------------------------------------------------------- * 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 namespace std { template 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 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(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(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(tblock_->tm_wday); } else { out = static_cast(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(sql_weather_get_forecast_protocol_value(0)); break; case OHOS::DialDataType::TJD_TEMPERATURE: out = static_cast(sql_weather_get_now_temperature()); break; case OHOS::DialDataType::TJD_TEMPERATURE_TYPE: out = static_cast(sql_weather_get_temper_unit()); break; case OHOS::DialDataType::TJD_TEMPERATURE_MAX: out = static_cast(sql_weather_get_forecast_temperature_max(0)); break; case OHOS::DialDataType::TJD_TEMPERATURE_MIN: out = static_cast(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(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