/*
 ******************************************************************************
 * @file   sensor_service_ui.h
 * @author Sifli software development team
 ******************************************************************************
 */
/*
 * @attention
 * Copyright (c) 2019 - 2024,  Sifli Technology
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Sifli integrated circuit
 *    in a product or a software update for such product, must reproduce the above
 *    copyright notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of Sifli nor the names of its contributors may be used to endorse
 *    or promote products derived from this software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Sifli integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY SIFLI TECHNOLOGY "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL SIFLI TECHNOLOGY OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "sensor_service.h"

#if defined (BF0_HCPU) || defined (SENSOR_IN_HCPU)  || defined (BSP_USING_PC_SIMULATOR)

#include "app_rt_db.h"
#include "sensor_nvm.h"
#ifdef BSP_BLE_SIBLES
    #include "data_unit.h"
#endif
#if defined(APP_POPUP_USED)
    #include "popup_fwk.h"
#endif
#include "lv_obj_datasubs.h"
#include "app_comm.h"
#include "app_nvm.h"
#include "app_thread.h"

#if defined (RT_USING_SENSOR)
void sensor_rt_data_step_notify(comm_msg_t *msg)
{
    step_info_t *step = (step_info_t *)msg->data;
    step_info_t *step_db = (step_info_t *) app_rt_info_get(RT_STEP);
    float data = step->distance;

    rt_kprintf("sensor_rt_data_step_notify step_db = %d, distance = %d\n", step_db->distance, step->distance);

    if (step_db->step != step->step && step->step != 0)
    {
        app_rt_info_notify("rt_step", LV_EVENT_REFRESH, &step->step, sizeof(step_db->step), NULL);
    }
    else if (step->step == 0)
    {
        step->step = step_db->step;
    }

    if (step_db->distance != step->distance && step->distance != 0)
    {
#ifdef BSP_BLE_SIBLES
        data = data_unit_convert_distance((float)step->distance / 1000, unit_distance_KM);
#endif
        app_rt_info_notify("rt_step_distance", LV_EVENT_REFRESH, &step->distance, sizeof(step_db->distance), NULL);
    }
    else if (step->distance == 0)
    {
        step->distance = step_db->distance;
    }

    if (step_db->calories != step->calories && step->calories != 0)
    {
        app_rt_info_notify("rt_step_calories", LV_EVENT_REFRESH, &step->calories, sizeof(uint32_t), NULL);
    }
    else if (step->calories == 0)
    {
        step->calories = step_db->calories;
    }

    if (step_db->active_type != step->active_type && step->active_type != 0)
    {
        app_rt_info_notify("rt_step_active_type", LV_EVENT_REFRESH, &step->active_type, sizeof(uint8_t), NULL);
    }
    else if (step->active_type == 0)
    {
        step->active_type = step_db->active_type;
    }

    if (step_db->step_frequency != step->step_frequency && step->step_frequency != 0)
    {
        app_rt_info_notify("rt_step_freq", LV_EVENT_REFRESH, &step->step_frequency, sizeof(float), NULL);
    }
    else if (step->step_frequency == 0)
    {
        step->step_frequency = step_db->step_frequency;
    }

    if (step_db->step_length != step->step_length && step->step_length != 0)
    {
        app_rt_info_notify("rt_step_length", LV_EVENT_REFRESH, &step->step_length, sizeof(float), NULL);
    }
    else if (step->step_length == 0)
    {
        step->step_length = step_db->step_length;
    }

    if (step_db->pace != step->pace && step->pace != 0)
    {
        app_rt_info_notify("rt_step_pace", LV_EVENT_REFRESH, &step->pace, sizeof(float), NULL);
    }
    else if (step->pace == 0)
    {
        step->pace = step_db->pace;
    }
}

void sensor_rt_data_temp_notify(comm_msg_t *msg)
{
    rt_kprintf("%s\n", __func__);
    temp_info_t *temp = (temp_info_t *)msg->data;
    temp_info_t *temp_db = app_rt_info_get(RT_TEMP);

    if (temp_db->temperature != temp->temperature)
    {
        app_rt_info_notify("rt_temp", LV_EVENT_REFRESH, &temp->temperature, sizeof(int16_t), NULL);
    }
}

void sensor_rt_data_hr_notify(comm_msg_t *msg)
{
    hr_info_t *hr = (hr_info_t *)msg->data;
    hr_info_t *hr_db = app_rt_info_get(RT_HR);

    if (hr_db->hr != hr->hr && hr->hr != 0)
    {
        app_rt_info_notify("rt_hr", LV_EVENT_REFRESH, &hr->hr, sizeof(uint8_t), NULL);
    }

    if (hr_db->timestamp != hr->timestamp)
    {
        app_rt_info_notify("rt_hr_timestamp", LV_EVENT_REFRESH, &hr->timestamp, sizeof(uint32_t), NULL);
    }
}
void sensor_rt_data_spo2_notify(comm_msg_t *msg)
{
    spo2_info_t *spo2 = (spo2_info_t *)msg->data;
    spo2_info_t *spo2_db = (spo2_info_t *)app_rt_info_get(RT_SPO2);

    if (spo2_db->spo2 != spo2->spo2)
    {
        app_rt_info_notify("rt_spo2", LV_EVENT_REFRESH, &spo2->spo2, sizeof(uint8_t), NULL);
    }
}
void sensor_rt_data_bp_notify(comm_msg_t *msg)
{
    bp_info_t *bp = (bp_info_t *)msg->data;
    bp_info_t *bp_db = (bp_info_t *)app_rt_info_get(RT_BP);

    if (bp_db->bp_h != bp->bp_h)
    {
        app_rt_info_notify("rt_bp_higj", LV_EVENT_REFRESH, &bp->bp_h, sizeof(uint8_t), NULL);
    }

    if (bp_db->bp_l != bp->bp_l)
    {
        app_rt_info_notify("rt_bp_low", LV_EVENT_REFRESH, &bp->bp_l, sizeof(uint8_t), NULL);
    }
}
void sensor_rt_data_sport_notify(comm_msg_t *msg)
{
    gsensor_pedo_info_t *sport = (gsensor_pedo_info_t *)msg->data;
    gsensor_pedo_info_t *sport_db = (gsensor_pedo_info_t *)app_rt_info_get(RT_SPORT);
    float data = sport->main_info.distance;

    if (sport_db->active_mode != sport->active_mode)
    {
        app_rt_info_notify("rt_sport_active_mode", LV_EVENT_REFRESH, &sport->active_mode, sizeof(uint32_t), NULL);
    }

    if (sport_db->main_info.step != sport->main_info.step && sport->main_info.step != 0)
    {
        app_rt_info_notify("rt_sport_step", LV_EVENT_REFRESH, &sport->main_info.step, sizeof(uint32_t), NULL);
    }
    else if (sport->main_info.step == 0)
    {
        sport->main_info.step = sport_db->main_info.step;
    }

    if (sport_db->main_info.distance != sport->main_info.distance && sport->main_info.distance != 0)
    {
#ifdef BSP_BLE_SIBLES
        data = data_unit_convert_distance(sport->main_info.distance / 1000, unit_distance_KM);//The distance unit is meter from sensor
#endif
        app_rt_info_notify("rt_sport_distance", LV_EVENT_REFRESH, &data, sizeof(float), NULL);
    }
    else if (sport->main_info.distance == 0)
    {
        sport->main_info.distance = sport_db->main_info.distance;
    }

    if (sport_db->main_info.cal != sport->main_info.cal && sport->main_info.cal != 0)
    {
        app_rt_info_notify("rt_sport_calories", LV_EVENT_REFRESH, &sport->main_info.cal, sizeof(float), NULL);
    }
    else if (sport->main_info.cal == 0)
    {
        sport->main_info.cal = sport_db->main_info.cal;
    }

    if (sport_db->main_info.step_frequency != sport->main_info.step_frequency && sport->main_info.step_frequency != 0)
    {
        app_rt_info_notify("rt_sport_step_freq", LV_EVENT_REFRESH, &sport->main_info.step_frequency, sizeof(float), NULL);
    }
    else if (sport->main_info.step_frequency == 0)
    {
        sport->main_info.step_frequency = sport_db->main_info.step_frequency;
    }

    if (sport_db->main_info.step_length != sport->main_info.step_length && sport->main_info.step_length != 0)
    {
        app_rt_info_notify("rt_sport_step_length", LV_EVENT_REFRESH, &sport->main_info.step_length, sizeof(float), NULL);
    }
    else if (sport->main_info.step_length == 0)
    {
        sport->main_info.step_length = sport_db->main_info.step_length;
    }

    if (sport_db->main_info.pace != sport->main_info.pace && sport->main_info.pace != 0)
    {
        app_rt_info_notify("rt_sport_step_pace", LV_EVENT_REFRESH, &sport->main_info.pace, sizeof(float), NULL);
    }
    else if (sport->main_info.pace == 0)
    {
        sport->main_info.pace = sport_db->main_info.pace;
    }

    if (sport_db->extra_info.av_step_frequency != sport->extra_info.av_step_frequency && sport->extra_info.av_step_frequency != 0)
    {
        app_rt_info_notify("rt_sport_av_step_freq", LV_EVENT_REFRESH, &sport->extra_info.av_step_frequency, sizeof(float), NULL);
    }
    else if (sport->extra_info.av_step_frequency == 0)
    {
        sport->extra_info.av_step_frequency = sport_db->extra_info.av_step_frequency;
    }

    if (sport_db->extra_info.av_step_length != sport->extra_info.av_step_length && sport->extra_info.av_step_length != 0)
    {
        app_rt_info_notify("rt_sport_av_step_length", LV_EVENT_REFRESH, &sport->extra_info.av_step_length, sizeof(float), NULL);
    }
    else if (sport->extra_info.av_step_length == 0)
    {
        sport->extra_info.av_step_length = sport_db->extra_info.av_step_length;
    }

    if (sport_db->extra_info.av_pace != sport->extra_info.av_pace && sport->extra_info.av_pace != 0)
    {
        app_rt_info_notify("rt_sport_av_step_pace", LV_EVENT_REFRESH, &sport->extra_info.av_pace, sizeof(float), NULL);
    }
    else if (sport->extra_info.av_pace == 0)
    {
        sport->extra_info.av_pace = sport_db->extra_info.av_pace;
    }

    if (sport_db->extra_info.max_step_frequency != sport->extra_info.max_step_frequency && sport->extra_info.max_step_frequency != 0)
    {
        app_rt_info_notify("rt_sport_max_step_freq", LV_EVENT_REFRESH, &sport->extra_info.max_step_frequency, sizeof(float), NULL);
    }
    else if (sport->extra_info.max_step_frequency == 0)
    {
        sport->extra_info.max_step_frequency = sport_db->extra_info.max_step_frequency;
    }

    if (sport_db->extra_info.max_pace != sport->extra_info.max_pace && sport->extra_info.max_pace != 0)
    {
        app_rt_info_notify("rt_sport_max_step_pace", LV_EVENT_REFRESH, &sport->extra_info.max_pace, sizeof(float), NULL);
    }
    else if (sport->extra_info.max_pace == 0)
    {
        sport->extra_info.max_pace = sport_db->extra_info.max_pace;
    }

    if (sport_db->extra_info.max_vo2 != sport->extra_info.max_vo2 && sport->extra_info.max_vo2 != 0)
    {
        app_rt_info_notify("rt_sport_max_vo2", LV_EVENT_REFRESH, &sport->extra_info.max_vo2, sizeof(float), NULL);
    }
    else if (sport->extra_info.max_vo2 == 0)
    {
        sport->extra_info.max_vo2 = sport_db->extra_info.max_vo2;
    }

    if (sport_db->extra_info.hrr_intensity != sport->extra_info.hrr_intensity && sport->extra_info.hrr_intensity != 0)
    {
        app_rt_info_notify("rt_sport_hrr_intensity", LV_EVENT_REFRESH, &sport->extra_info.hrr_intensity, sizeof(float), NULL);
    }
    else if (sport->extra_info.hrr_intensity == 0)
    {
        sport->extra_info.hrr_intensity = sport_db->extra_info.hrr_intensity;
    }

    if (sport_db->extra_info.hrr_zone != sport->extra_info.hrr_zone && sport->extra_info.hrr_zone != 0)
    {
        app_rt_info_notify("rt_sport_hrr_zone", LV_EVENT_REFRESH, &sport->extra_info.hrr_zone, sizeof(float), NULL);
    }
    else if (sport->extra_info.hrr_zone == 0)
    {
        sport->extra_info.hrr_zone = sport_db->extra_info.hrr_zone;
    }

    if (sport_db->extra_info.uncalibration_distance != sport->extra_info.uncalibration_distance && sport->extra_info.uncalibration_distance != 0)
    {
        app_rt_info_notify("rt_sport_uncalibration_distance", LV_EVENT_REFRESH, &sport->extra_info.uncalibration_distance, sizeof(float), NULL);
    }
    else if (sport->extra_info.uncalibration_distance == 0)
    {
        sport->extra_info.uncalibration_distance = sport_db->extra_info.uncalibration_distance;
    }
}

void sensor_his_data_spo2_notify(comm_msg_t *msg)
{
    spo2_info_t *data = (spo2_info_t *)msg->data;
    uint16_t num = msg->data_len / sizeof(spo2_info_t);
    uint8_t max, min, ave;
    uint32_t totle = 0;

    uint8_t *history_spo2_array = rt_malloc(num);
    rt_memset(history_spo2_array, 0, num);

    max = data->spo2;
    min = data->spo2;
    for (uint16_t i = 0; i < num; i++)
    {
        totle += data[i].spo2;
        history_spo2_array[i] = data[i].spo2;
        min = min < data[i].spo2 ? min : data[i].spo2;
        max = max > data[i].spo2 ? max : data[i].spo2;
    }
    ave = (uint8_t)(totle / num);
    app_rt_info_notify("his_spo2_today_array", LV_EVENT_REFRESH, history_spo2_array, num, NULL);
    app_rt_info_notify("his_spo2_last", LV_EVENT_REFRESH, &data->spo2, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_spo2_last_timestamp", LV_EVENT_REFRESH, &data->timestamp, sizeof(uint32_t), NULL);
    app_rt_info_notify("his_spo2_today_ave", LV_EVENT_REFRESH, &max, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_spo2_today_max", LV_EVENT_REFRESH, &min, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_spo2_today_min", LV_EVENT_REFRESH, &ave, sizeof(uint8_t), NULL);

    rt_free(history_spo2_array);
}

void sensor_his_data_bp_notify(comm_msg_t *msg)
{
    bp_info_t *data = (bp_info_t *)msg->data;
    uint16_t num = msg->data_len / sizeof(bp_info_t);
    uint8_t max_h, min_h, ave_h, max_l, min_l, ave_l;
    uint32_t totle_h = 0;
    uint32_t totle_l = 0;

    uint8_t *history_bp_h_array = rt_malloc(num);
    rt_memset(history_bp_h_array, 0, num);
    uint8_t *history_bp_l_array = rt_malloc(num);
    rt_memset(history_bp_l_array, 0, num);

    max_h = data->bp_h;
    min_h = data->bp_h;
    max_l = data->bp_l;
    min_l = data->bp_l;
    for (uint16_t i = 0; i < num; i++)
    {
        totle_h += data[i].bp_h;
        totle_l += data[i].bp_l;
        history_bp_h_array[i] = data[i].bp_h;
        history_bp_l_array[i] = data[i].bp_l;
        min_h = min_h < data[i].bp_h ? min_h : data[i].bp_h;
        max_h = max_h > data[i].bp_h ? max_h : data[i].bp_h;
        min_l = min_l < data[i].bp_l ? min_l : data[i].bp_l;
        max_l = max_l > data[i].bp_l ? max_l : data[i].bp_l;
    }
    ave_h = (uint8_t)(totle_h / num);
    ave_l = (uint8_t)(totle_l / num);
    app_rt_info_notify("his_bp_h_today_array", LV_EVENT_REFRESH, history_bp_h_array, num, NULL);
    app_rt_info_notify("his_bp_h_last", LV_EVENT_REFRESH, &data->bp_h, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_bp_h_last_timestamp", LV_EVENT_REFRESH, &data->timestamp, sizeof(uint32_t), NULL);
    app_rt_info_notify("his_bp_h_today_ave", LV_EVENT_REFRESH, &max_h, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_bp_h_today_max", LV_EVENT_REFRESH, &min_h, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_bp_h_today_min", LV_EVENT_REFRESH, &ave_h, sizeof(uint8_t), NULL);

    app_rt_info_notify("his_bp_l_today_array", LV_EVENT_REFRESH, history_bp_l_array, num, NULL);
    app_rt_info_notify("his_bp_l_last", LV_EVENT_REFRESH, &data->bp_l, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_bp_l_last_timestamp", LV_EVENT_REFRESH, &data->timestamp, sizeof(uint32_t), NULL);
    app_rt_info_notify("his_bp_l_today_ave", LV_EVENT_REFRESH, &max_l, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_bp_l_today_max", LV_EVENT_REFRESH, &min_l, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_bp_l_today_min", LV_EVENT_REFRESH, &ave_l, sizeof(uint8_t), NULL);

    rt_free(history_bp_h_array);
    rt_free(history_bp_l_array);
}
#endif

void sensor_his_data_hr_notify(comm_msg_t *msg)
{
    hr_day_info_t *hr_day = (hr_day_info_t *)msg->data;
    char str[16] = {0};
    hr_day_range_t hr_rang = {0};

    uint32_t totle = 0;
    uint16_t dot_num = 0;

    uint8_t *hr_array = rt_malloc(DAY_HR_MAX_COUNT * sizeof(uint8_t));
    uint16_t hr_array_len = DAY_HR_MAX_COUNT * sizeof(uint8_t);
    rt_memset(hr_array, 0, hr_array_len);

    hr_rang.max_hr = hr_day->info[0].hr;
    hr_rang.min_hr = hr_day->info[0].hr;
    for (uint16_t i = 0; i < hr_day->total_num; i++)
    {
        totle += hr_day->info[i].hr;
        struct tm *time_info = localtime((time_t *)&hr_day->info[i].timestamp);
        if (dot_num != (lv_coord_t)((time_info->tm_hour * 60 + time_info->tm_min) / 30))
        {
            dot_num = (lv_coord_t)((time_info->tm_hour * 60 + time_info->tm_min) / 30);
            hr_array[dot_num] = hr_day->info[i].hr;
            hr_rang.min_hr = hr_rang.min_hr < hr_day->info[i].hr ? hr_rang.min_hr : hr_day->info[i].hr;
            hr_rang.max_hr = hr_rang.max_hr > hr_day->info[i].hr ? hr_rang.max_hr : hr_day->info[i].hr;
        }
    }

    hr_rang.ave = (uint8_t)(totle / hr_day->total_num);

    if (hr_rang.max_hr && hr_rang.min_hr)
    {
        snprintf(str, sizeof(str) - 1, "%d-%d", hr_rang.min_hr, hr_rang.max_hr);
    }
    else
    {
        snprintf(str, sizeof(str) - 1, "- -");
    }
    app_rt_info_notify("his_hr_last", LV_EVENT_REFRESH, &hr_day->info[hr_day->total_num - 1].hr, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_hr_last_timestamp", LV_EVENT_REFRESH, &hr_day->info[hr_day->total_num - 1].timestamp, sizeof(uint32_t), NULL);
    app_rt_info_notify("his_hr_today_ave", LV_EVENT_REFRESH, &hr_rang.ave, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_hr_today_max", LV_EVENT_REFRESH, &hr_rang.max_hr, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_hr_today_min", LV_EVENT_REFRESH, &hr_rang.min_hr, sizeof(uint8_t), NULL);
    app_rt_info_notify("his_hr_today_range", LV_EVENT_REFRESH, &hr_rang, sizeof(hr_day_range_t), NULL);
    app_rt_info_notify("his_hr_today_array", LV_EVENT_REFRESH, hr_array, hr_array_len, NULL);
    rt_free(hr_array);
}

int sensors_no_wakeup_msg_process_in_gui_thread_cb(comm_msg_t *msg)
{
    uint16_t msg_id = (uint16_t) msg->user_data;

    if (SENSOR_APP_TODAY_ID_BEGIN < msg_id && msg_id < SENSOR_APP_TODAY_ID_END)
    {
        switch (msg_id)
        {
        case SENSOR_APP_TODAY_HR_IND:
        {
            //sensor_his_data_hr_notify(msg);
            lv_obj_datasubs_notify(NULL, msg_id, msg->data, msg->data_len, NULL);
            break;
        }
        case SENSOR_APP_TODAY_BP_IND:
        {
            break;
        }
        case SENSOR_APP_TODAY_SPO2_IND:
        {
            break;
        }
        default:
            ;
        }
    }
    else if (SENSOR_APP_FACTORY_MODE_RSP == msg_id)
    {
        lv_obj_datasubs_notify(NULL, SENSOR_APP_FACTORY_MODE_RSP, msg->data, sizeof(asl_info_t), NULL);
        //TBD...;
    }
    else if (SENSOR_APP_RT_ID_BEGIN < msg_id && msg_id < SENSOR_APP_RT_ID_END)
    {
        switch (msg_id)
        {
#if defined (RT_USING_SENSOR)
        case SENSOR_APP_RT_STEP_INFO_IND:
        {
            sensor_rt_data_step_notify(msg);
            app_rt_info_update(RT_STEP, (void *)msg->data, msg->data_len);
            break;
        }
        case SENSOR_APP_RT_HR_INFO_IND:
        {
            sensor_rt_data_hr_notify(msg);
            app_rt_info_update(RT_HR, (void *)msg->data, msg->data_len);
            lv_obj_datasubs_notify(NULL, msg_id, NULL, 0, NULL);
            break;
        }
        case SENSOR_APP_RT_SPO2_INFO_IND:
        {
            sensor_rt_data_spo2_notify(msg);
            app_rt_info_update(RT_SPO2, (void *)msg->data, msg->data_len);
            break;
        }
        case SENSOR_APP_RT_BP_INFO_IND:
        {
            sensor_rt_data_bp_notify(msg);
            app_rt_info_update(RT_BP, (void *)msg->data, msg->data_len);
            break;
        }
        case SENSOR_APP_RT_TEMP_INFO_IND:
        {
            sensor_rt_data_temp_notify(msg);
            app_rt_info_update(RT_TEMP, (void *)msg->data, msg->data_len);
            break;
        }
        case SENSOR_APP_RT_SPORT_INFO_ID:
        {
            sensor_rt_data_sport_notify(msg);
            app_rt_info_update(RT_SPORT, (void *)msg->data, msg->data_len);
            break;
        }
        case SENSOR_APP_RT_MAG_INFO_ID:
        {
            /*to bed add sensor_rt_data_mag_notify(msg)*/;
            mag_info_t *mag_info = (mag_info_t *)msg->data;
            if (mag_info->uracy == 3)
            {
                rt_kprintf("app recieve mag data: azimuth = %f, pitch = %f, roll = %f ;\n", mag_info->azimuth, mag_info->pitch, mag_info->roll);
                app_rt_info_update(RT_MAG, (void *)msg->data, msg->data_len);
            }
            break;
        }
        case SENSOR_APP_RT_ASL_INFO_ID:
        {
            /*process asl data*/
            asl_info_t *asl_info = (asl_info_t *)msg->data;
            app_rt_info_update(RT_ASL, (void *)msg->data, msg->data_len);
            if (app_screen_light_adjust_is_timeout() && gui_is_active())
            {
                uint8_t level = app_get_backlight_level_by_lux(asl_info->light);
                if (nvm_sys_get(lcd_light) != level)
                {
                    app_lcd_backlight_set(level);
                    rt_kprintf("app recieve asl value = %d, lcd_light %d\n", asl_info->light, level);
                }
                lv_obj_datasubs_notify(NULL, SENSOR_APP_RT_ASL_INFO_ID, msg->data, sizeof(asl_info_t), NULL);
            }
            break;
        }
#endif

        case SENSOR_APP_RT_GPS_INFO_ID:
        {
#if defined (RT_USING_GPS)
            app_rt_info_update(RT_GPS, (void *)msg->data, msg->data_len);
#endif
            app_rt_info_notify("gps_info", LV_EVENT_REFRESH, (uint8_t *)msg->data, msg->data_len, NULL);
            break;
        }
        default:
            ;
        }
    }
    else
    {
        ;
    }

    return 0;
}

int sensors_msg_process_in_bg_thread_cb(comm_msg_t *msg)
{
    uint16_t msg_id = (uint16_t) msg->user_data;

    if (SENSOR_APP_HISTORY_ID_BEGIN < msg_id && msg_id < SENSOR_APP_HISTORY_ID_END)
    {
        nvm_history_write(msg_id, time(RT_NULL), msg->data, msg->data_len);
    }
    else
    {
        ;
    }

    return 0;
}

int sensors_wakeup_msg_process_in_gui_thread_cb(comm_msg_t *msg)
{
    uint16_t msg_id = (uint16_t) msg->user_data;

    if (SENSOR_APP_EVENT_ID_BEGIN < msg_id && msg_id < SENSOR_APP_EVENT_ID_END)
    {
#if defined(APP_POPUP_USED)
        popup_run("remind", (void *)msg->data);
#endif
    }
    else if (SENSOR_APP_TEST_RANDOM_IND == msg_id)
    {
#ifdef RT_USING_FINSH
        extern void test_cmd(int argc, char argv[][50]);
        char cmd[][50] = {"test", "random", "-e", "-life_time", "10"};
        uint32_t life_time = *(uint32_t *) msg->data;
        if (0 == life_time || UINT32_MAX == life_time)
            life_time = 10 + rand() % 50; //10s .. 1min
        sprintf(cmd[4], "%d", life_time);
        test_cmd(5, cmd);
#endif
    }

    return 0;
}


#ifdef RT_USING_FINSH
#include "app_thread.h"
int sim_sensor(int argc, const char *argv[])
{
    if (argc < 2) return 0;
    void *data = NULL;
    uint32_t data_len = 0;
    if (0 == strcmp(argv[1], "step"))
    {
        step_info_t info = {0};
        info.calories = 1000;
        info.distance = 2000;
        info.step = 4200;
        data = &info;
        data_len = sizeof(info);
        send_msg_to_gui_thread(data, data_len, sensors_no_wakeup_msg_process_in_gui_thread_cb, SENSOR_APP_RT_STEP_INFO_IND, NEED_WAKEUP_UI | CAN_BE_DISCARDED);

    }
    else if (0 == strcmp(argv[1], "hr"))
    {
        hr_info_t info = {0};
        info.hr = 120;
        info.rhr = 80;
        data = &info;
        data_len = sizeof(info);
        send_msg_to_gui_thread(data, data_len, sensors_no_wakeup_msg_process_in_gui_thread_cb, SENSOR_APP_RT_HR_INFO_IND, NEED_WAKEUP_UI | CAN_BE_DISCARDED);
    }
    return 0;
}
MSH_CMD_EXPORT(sim_sensor, sim sensor data);
#endif

#endif
