/*
 * @Author       : stark1898y 1658608470@qq.com
 * @Date         : 2024-06-18 15:48:01
 * @LastEditors: mbw && 1600520629@qq.com
 * @LastEditTime: 2024-12-17 15:52:30
 * @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_mq.c
 * @Description  :
 *
 * Copyright (c) 2024 by yzy, All Rights Reserved.
 */
/*
 * @Author       : yzy
 * @Date         : 2023-01-30 15:40:07
 * @LastEditors  : stark1898y 1658608470@qq.com
 * @LastEditTime : 2023-09-19 16:25:03
 * @FilePath     : \JT-DT-YD1F01_RTT_Nano\bsp\src\bsp_mq.c
 * @Description  :
 *
 * Copyright (c) 2023 by yzy, All Rights Reserved.
 */
#include "bsp_mq.h"
#include "bsp_adc.h"
#include "bsp_flash.h"
#include "bsp_rtc.h"
#include "user_sys.h"
#include "finsh.h"



#define LOG_TAG     "bsp_mq"          // 该模块对应的标签。不定义时，默认：NO_TAG
#define LOG_LVL     LOG_LVL_DBG     // 该模块对应的日志输出级别。不定义时，默认：调试级别
#include <ulog.h>                   // 必须在 LOG_TAG 与 LOG_LVL 下面


ALIGN(RT_ALIGN_SIZE)
static char sensor_thread_stack[GAS_SNESOR_THREAD_STACK_SIZE];
static struct rt_thread Sensor_Thread;

TsSensor_t Sensor_device;

uint16_t Get_Gas_VoltageInt1000x(void)
{
    uint16_t voltage = (Get_ADC_Average(kGasAdc) * 3.3 / 4096) * MQ_VOLTAGE_RATIO * 1000;
   LOG_D("Get_Gas_VoltageInt1000x = %04d", voltage);
    return voltage;
}

uint16_t Get_Gas_VoltageAdcInt1000x(void)
{
    rt_uint16_t voltage_adc = (Get_ADC_Average(kGasAdc) * 3.3 / 4096) * 1000;
//    LOG_D("Get_Gas_VoltageAdcInt1000x = %04d", voltage_adc);
    return voltage_adc;
}

#ifdef TEST_ENABLE
static void TEST_Get_Gas_VoltageInt1000x(void)
{
    LOG_D("Get_Gas_VoltageInt1000x = %04d", Get_Gas_VoltageInt1000x());
}
MSH_CMD_EXPORT(TEST_Get_Gas_VoltageInt1000x, TEST_Get_Gas_VoltageInt1000x);
#endif

static uint8_t Sensor_Count(const rt_uint8_t *buffer, uint8_t value, uint8_t size)
{
    uint8_t count = 0;
    for (uint8_t i = 0; i < size; i++)
    {
        if (buffer[i] == value)
        {
            count++;
        }
    }
    return count;
}

static void Sensor_HandleAlarm(uint8_t count, uint8_t *flag, uint8_t threshold)
{
    if (count > threshold && *flag == 0)
    {
        Sensor_device.detection_flag = kSensorAlarm;
        Send_Laser_Alarm_Event(kAlarmEvent);
        *flag = 1;
    }
    else if (*flag == 1 && count < threshold)
    {
        *flag = 0;
        Send_Laser_Alarm_Event(kAlarmRcyEvent);
    }
}

static void Sensor_HandleFault(uint8_t count, uint8_t *flag, uint8_t threshold)
{
    if (count > threshold && *flag != 1)
    {
        *flag = 1;
        Sensor_device.detection_flag = kSensorFault;
        Send_Laser_Alarm_Event(kFaultEvent);
    }
    else if (*flag == 1 && count < threshold)
    {
        *flag = 0;
        Send_Laser_Alarm_Event(kFaultRcyEvent);
    }
}

static uint8_t Sensor_CheckData(void)
{
    static rt_uint8_t alarm_count = 0, fault_count = 0;
    static rt_uint8_t alarm_flag = 0, fault_flag = 0;
    static rt_uint8_t index = 0;
    static rt_uint8_t alarm_status_buffer[SENSOR_SAMPLING_TIMS] = {0};
    static rt_uint8_t fault_buf[SENSOR_SAMPLING_TIMS] = {0};
    rt_uint16_t voltage = Get_Gas_VoltageAdcInt1000x();

    alarm_status_buffer[index] = ((voltage > Sensor_device.alarm_value) && (voltage < MQ_VOLTAGE_HIGH_LIMIT)) ? kSensorAlarm : kSensorNormal;
    fault_buf[index] = ((voltage < MQ_VOLTAGE_LOW_LIMIT) || (voltage > MQ_VOLTAGE_HIGH_LIMIT)) ? kSensorFault : kSensorNormal;
    index++;
    if (index >= SENSOR_SAMPLING_TIMS)
    {
        index = 0;
    }
    
    alarm_count = Sensor_Count(alarm_status_buffer, kSensorAlarm, SENSOR_SAMPLING_TIMS);
    fault_count = Sensor_Count(fault_buf, kSensorFault, SENSOR_SAMPLING_TIMS);

    Sensor_HandleAlarm(alarm_count, &alarm_flag, SENSOR_SAMPLING_TIMS / 2 + 1);
    Sensor_HandleFault(fault_count, &fault_flag, SENSOR_SAMPLING_TIMS / 2 + 1);

    return RT_EOK;
}

// TODO: 寿命检测
uint8_t IS_EndOfLife(void)
{
    if (RTC_GetCounter() >= Sensor_device.expiration_seconds)
    {
        Sensor_device.end_of_life = 1;
    }
    return Sensor_device.end_of_life;
}

// MQ检测线程函数
static void Sensor_detection_thread_entry(void *param)
{
     TuFlashProductTimeLimitFrame LimitTime;
    if (Flash_GetProductTimeLimit(&LimitTime, kExpirationTimeId) == READY)
    {
        // 计算出 到期时间对应的RTC秒数
        Sensor_device.expiration_seconds = DateTime2Seconds(LimitTime.Struct.year,
                                                   LimitTime.Struct.month, LimitTime.Struct.day, LimitTime.Struct.hour,
                                                   LimitTime.Struct.minute, LimitTime.Struct.second);
        LOG_D("device_expiration_time:%04d-%02d-%02d,%02d:%02d",
              LimitTime.Struct.year, LimitTime.Struct.month, LimitTime.Struct.day,
              LimitTime.Struct.hour, LimitTime.Struct.minute, LimitTime.Struct.second);
    }

    if (Flash_GetNum_Records(kRecordSensoEndOfLife) == 1)
    {
        Sensor_device.end_of_life = 1;
        LOG_W("寿命已到期");
        TotalRecords.sensor_failure++;
    }
    // 寿命到期检测
    if (IS_EndOfLife())
    {
        if (Flash_GetNum_Records(kRecordSensoEndOfLife) == 0)
        {
            Flash_Write_Record(kRecordSensoEndOfLife);
        }
    }
    while (1)
    {
        if (SysControl.status > kPreheatingEvent)
        {
            Sensor_CheckData();
        }
        rt_thread_mdelay(1000);
    }
}

int BSP_MQ_Init(void)
{
    Sensor_device.alarm_value = Flash_Get_SysCfg(kAlarmLValueId);
    LOG_D("报警阈值为:%d", Sensor_device.alarm_value);
    rt_thread_init(&Sensor_Thread,  //可以用定时器做，没必要线程
                    "sensor_thread",
                    Sensor_detection_thread_entry,
                    RT_NULL,
                    &sensor_thread_stack[0],
                    sizeof(sensor_thread_stack),
                    GAS_SENSOR_THREAD_PRIORITY, GAS_SENSOR_THREAD_TIMESLICE);
    rt_thread_startup(&Sensor_Thread);

    return 0;
}
#ifdef RT_USING_COMPONENTS_INIT
INIT_DEVICE_EXPORT(BSP_MQ_Init);
#endif

#ifdef TEST_ENABLE
static void TEST_MQ_EndOfLife(void)
{
    Sensor_device.end_of_life = 1;
}
MSH_CMD_EXPORT(TEST_MQ_EndOfLife, TEST_MQ_EndOfLife);
#endif

