/*
 * @Author: mbw
 * @Date: 2024-11-30 15:46:21
 * @LastEditors: mbw && 1600520629@qq.com
 * @LastEditTime: 2025-04-25 08:41:52
 * @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_ml307.c
 * @Description:
 *
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
 */
#include <at_device_ml307.h>
#include "drv_gpio.h"
#include "bsp_ml307.h"
#include "user_sys.h"
#include "bsp_flash.h"
#include "stddef.h"
#include "bsp_rtc.h"
#include "bsp_bt.h"
#include "bsp_mq.h"
#include "user_sys.h"
#include "bsp_rtc.h"

#define LOG_TAG "ml307"
#include <at_log.h>

#if IOT_MODULE_SWITCH == 1
#define ML307_THREAD_STACK_SIZE      (4096 + 2048)
#define ML307_RECV_THREAD_STACK_SIZE (4096 + 2048)
#define ML307_LIFE_THREAD_STACK_SIZE (4096)
#define ML307_THREAD_PRIORITY        25
#define ML307_THREAD_TICKS           50
#define ML307_RECV_THREAD_PRIORITY   24
#define ML307_RECV_THREAD_TICKS      10

#define ML307_LIFE_THREAD_PRIORITY   26
#define ML307_LIFE_THREAD_TICKS      10

// static rt_uint32_t ml307_status = 0;
ALIGN(RT_ALIGN_SIZE)
static char ml307_thread_stack[ML307_THREAD_STACK_SIZE];
static struct rt_thread ml307_thread;

ALIGN(RT_ALIGN_SIZE)
static char ml307_recv_thread_stack[ML307_RECV_THREAD_STACK_SIZE];
static struct rt_thread ml307_recv_thread;

ALIGN(RT_ALIGN_SIZE)
static char ml307_life_thread_stack[ML307_LIFE_THREAD_STACK_SIZE];
static struct rt_thread ml307_life_thread;

struct rt_event at_device_event;
rt_sem_t ml307_recv_sem;
rt_sem_t ml307_recv_msg_sem; // 用于接收信号
rt_sem_t ml307_disconnect_sem;
static rt_timer_t ml307_timer;        // 上报心跳
static rt_timer_t ml307_upload_timer; // 更新本地时间定时器
static rt_timer_t ml307_error_timer;  // 上电失败情况下启动定时器

rt_uint8_t ml307_power_down_flag;
rt_uint8_t ml307_connect_sever_flag;
rt_uint8_t ml307_send_error_flag;
rt_uint8_t ml307_conncet_tcp_flag;
rt_uint8_t ml307_disconnect_pdp_flag;       // PDP断开连接标志
rt_uint8_t ml307_disconnect_retry_flag = 0; // 用于判断是否已经启动了重连，如果启动，不需要每次都进入
Ml307EventIndex ml307_event_index;

Ml307Event ml307_current_evnet = kMl307PowerOnEvent; // 默认上电事件
Ml307Event ml307_latest_evnet  = kMl307PowerOnEvent; // 最新传入的事件

rt_uint8_t power_on_send_flag = 0;
rt_mutex_t ml307_mutex;

extern valve_data valve[MAX_VALVE_NUM];

int BSP_Ml307_Init(struct Ml307_Ops *ops, rt_uint8_t version);
int BSP_Ml307_Update(struct Ml307_Ops *ops, rt_uint8_t device_type, rt_uint8_t event_type);
int Ml307_Send_Data(struct Ml307_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type);
int Data_Resp(struct Ml307_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type, char *data, rt_uint8_t res);
// int Ml307_Recv_Data(struct Ml307_Ops *ops, char *data);

static struct DataBody body;
static struct Ml307DataFrame frame;
static struct Ml307RecvData ml307_recv;

struct Ml307_Ops ml307_ops = {
    .body        = &body,
    .frame       = &frame,
    .recv        = &ml307_recv,
    .init        = BSP_Ml307_Init,
    .update_data = BSP_Ml307_Update,
    .send        = Ml307_Send_Data,
    .Resp        = Data_Resp,
    // .Recv        = Ml307_Recv_Data,//，没用到
};

static struct at_device_ml307 _dev = {
    ML307_SAMPLE_DEIVCE_NAME,
    ML307_SAMPLE_CLIENT_NAME,

    ML307_ENABLE_3_8_V,
    ML307_PWR_PIN,
    ML307_RST_PIN,
    ML307_USIM_DECT_PIN,
    ML307_SAMPLE_RECV_BUFF_LEN,
};

static rt_uint32_t ml307_event_flags[kMl307MaxEventcnt] = {0};
static rt_bool_t ml307_event_initialized                = RT_FALSE; // 是否初始化完成

typedef enum
{
    kMl307PriorityLowest,  // 4、优先级最低（定时心跳、浓度异常、报警触发、报警解除、传感器故障触发 传感器故障解除）
    kMl307PriorityMedium,  // 2、优先级第三高 自检触发
    kMl307PriorityHigh,    // 1、优先级第二高  掉电
    kMl307PriorityHighest, // 0 优先级最高(设备上电时的定时心跳)
} Ml307Priority;

typedef struct
{
    Ml307Event event_flag;
    Ml307Priority priority;
    const char *event_name;
    int (*send_func)(struct at_device *device, void *param);
} Ml307EventInfo;

static void Ml307_Set_Event(Ml307Event event_type)
{
    if (event_type < kMl307MaxEventcnt)
    {
        ml307_event_flags[event_type] = (1 << event_type);
    }
}

void Ml307_Event_Init(void)
{
    rt_err_t ret = rt_event_init(&at_device_event, "ml307_event", RT_IPC_FLAG_PRIO);
    if (ret == RT_EOK)
    {
        ml307_event_initialized = RT_TRUE;
        for (Ml307Event event = kMl307HeartbeatEvent; event < kMl307MaxEventcnt; event++)
        {
            Ml307_Set_Event(event);
        }
    }
    else
    {
        LOG_E("ml307_event init failed!");
    }
}

rt_uint32_t Ml307_Get_Event_Flag(Ml307Event event_type)
{
    if (event_type < kMl307MaxEventcnt)
    {
        return ml307_event_flags[event_type];
    }
    return 0;
}

void Ml307_Send_Event(Ml307Event event_type)
{
    ml307_event_index.last_event    = ml307_event_index.current_event;
    ml307_event_index.current_event = event_type;
    ml307_latest_evnet              = event_type;
    if (ml307_event_initialized == RT_TRUE)
    {
        if ((ml307_event_index.current_event != kMl307PowerOnEvent) && (ml307_event_index.current_event != kMl307PowerDownEvent))
        {
            if (power_on_send_flag)
            {
                rt_event_send(&at_device_event, Ml307_Get_Event_Flag(event_type));
            }
        }
        else
        {
            rt_event_send(&at_device_event, Ml307_Get_Event_Flag(event_type));
        }
    }
    else
    {
        LOG_E("ml307_event_initialized is false");
    }
}

// 定义定时器回调函数
static void Ml307_Ht_Timer_Cb(void *parameter)
{

    Ml307_Send_Event(kMl307HeartbeatEvent);
}

static void Ml307_Error_Timer_Cb(void *parameter)
{
    if (power_on_send_flag) // 上电成功时，停止定时器
    {
        rt_timer_stop(ml307_error_timer);
    }
    else
    {
        Ml307_Send_Event(kMl307PowerOnEvent);
    }
}

int _Pack_Send(struct Ml307_Ops *ops, char *buf)
{
    char ml307_send_buf[1024] = {0}; // 发送缓冲区，用于存储最终发送的数据
                                     //    char byteArr1[512];             // 转换成字节值
    unsigned short crc16 = 0;        // 存储CRC16校验和

    struct at_device *device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, ML307_SAMPLE_DEIVCE_NAME);
    ASSERT(device);
    crc16 = crc1021(buf, rt_strlen(buf));
    LOG_D("buf: %s", buf);
    LOG_D("crc16: %X", crc16);
    // 将数据、校验和及尾部标识添加到发送缓冲区中
    if (rt_snprintf(ml307_send_buf, sizeof(ml307_send_buf),
                    "%s%04X%02X%02X%02X",
                    buf,
                    crc16,
                    ops->frame->tail[0],
                    ops->frame->tail[1],
                    ops->frame->tail[2]) >= sizeof(ml307_send_buf))
    {
        // 发生缓冲区溢出
        LOG_E("Buffer overflow in ml307_send_buf");
        return -RT_ERROR;
    }
    // 打印调试信息
    // LOG_D("ml307_send_buf: %s", ml307_send_buf);
    rt_uint16_t data_len = rt_strlen(ml307_send_buf);
    // 通过AT指令发送数据给ML307模块
    if (at_send_data(device, ml307_send_buf, data_len / 2) != RT_EOK)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

/**
 * @brief 发送数据到ml307模块
 *
 * 本函数根据提供的数据和参数构建一个格式化字符串，计算其CRC16校验和，
 * 然后将该字符串发送给ML307模块
 *@param version 协议版本
 * @param data 要发送的十六进制数据字符串
 * @param len 数据字符串的十六进制数据格式长度
 * @param data_num 数据编号
 * @param cmd_num 命令编号
 * @return int 返回0表示成功，非零表示失败
 */
static int _Send_Handle(struct Ml307_Ops *ops, rt_size_t data_num, rt_size_t cmd_num, const char *data)
{
    // 临时缓冲区，用于格式化数据
    char data_buf[1024] = {0};
    rt_size_t data_len  = rt_strlen(data);

    // 格式化数据，构建发送给ML307模块的数据包
    rt_int32_t len = rt_snprintf(data_buf, sizeof(data_buf),
                                 "%02X%02X%02X%02X%04X%04X%02X%04X%s",
                                 ops->frame->header[0],
                                 ops->frame->header[1],
                                 ops->frame->header[2],
                                 ops->frame->version,     // 协议版本
                                 ops->frame->manufacture, // 制造商ID
                                 data_num,
                                 cmd_num,
                                 data_len / 2,
                                 data);
    if (len < 0 || len >= sizeof(data_buf))
    {
        LOG_E("Send Data buffer overflow");
        return -RT_ERROR;
    }

    // LOG_D("data_buf: %s", data_buf);

    return _Pack_Send(ops, data_buf);
}

// 初始化函数
int BSP_Ml307_Init(struct Ml307_Ops *ops, rt_uint8_t version)
{
    if (ops->frame == RT_NULL)
    {
        LOG_E("Memory allocation failed");
        return -RT_ENOMEM;
    }
    rt_memset(ops->frame, 0, sizeof(struct Ml307DataFrame));

    ops->frame->header[0] = 0x4A;
    ops->frame->header[1] = 0x54;
    ops->frame->header[2] = 0x30;

    ops->frame->version     = version;
    ops->frame->manufacture = DEVICE_MANUFACTURE;

    ops->frame->tail[0] = 0x42;
    ops->frame->tail[1] = 0x4A;
    ops->frame->tail[2] = 0x51;

    return RT_EOK;
}

int _Update_Valve_Data(struct Ml307_Ops *ops)
{
    ops->body->valve_num = Flash_Get_Valve_Num();
    if (ops->body->valve_num == 0) // 确保至少有一个阀门数据体
    {
        LOG_D("No valve data");
        rt_memset(&ops->body->valve_data, 0, sizeof(struct valve_t)); // 直接全部发送0
    }
    else
    {
        LOG_D("valve_num: %d", ops->body->valve_num);
        rt_memcpy(&ops->body->valve_data[0], &valve[0], sizeof(struct valve_t));
        rt_memset(&valve[0].valve_connct_status, 0, (sizeof(struct valve_t) - 7)); // 清空阀门包数据，等待下次更新,如果没更新说明断开了
    }
    return RT_EOK;
}

// 更新函数
int BSP_Ml307_Update(struct Ml307_Ops *ops, rt_uint8_t device_type, rt_uint8_t event_type)
{

    ops->body->device_type = device_type;
    ops->body->event_type  = event_type;
    ops->body->hw          = (rt_uint8_t)Flash_Get_SysCfg(kHwVerId);
    ops->body->sw          = (rt_uint8_t)Flash_Get_SysCfg(kSwVerId);
    rt_memcpy(ops->body->imei, &ml307, sizeof(ml307_sys_info)); // 直接赋值结构体数据
    ops->body->gas_voltage              = Get_Gas_VoltageAdcInt1000x();
    ops->body->product_work_temperature = 0x32;
    ops->body->work_duration            = work_duration;
    ops->body->device_status            = device_state_flag;
    ops->body->valve_num                = Flash_Get_Valve_Num();
    _Update_Valve_Data(ops);

    return RT_EOK;
}

int Ml307_Send_Data(struct Ml307_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type)
{
    rt_size_t lenght    = 0;
    int ret             = 0;
    char data_buf[1024] = {0};
    char temp[3]; // 临时缓冲区，用于存储每个字节的十六进制表示

    if (ops == NULL || ops->body == NULL)
    {
        // 处理 ops 或 ops->body 为 NULL 的情况
        return RT_ERROR; // 或者抛出异常，返回错误码等
    }

    if (sizeof(struct DataBody) == 0)
    {
        data_buf[0] = '\0'; // 确保 data_buf 被正确初始化
        return RT_ERROR;
    }

    rt_memset(ops->body, 0, sizeof(struct DataBody));
    rt_mutex_take(ml307_mutex, RT_WAITING_FOREVER);
    ret = ml307_ops.update_data(ops, device_type, event_type);
    if (ret == RT_EOK)
    {
        if (ops->body->valve_num == 0)
        {
            lenght = (sizeof(struct DataBody) - (MAX_VALVE_NUM - 1) * sizeof(struct valve_t)); // 至少要发送一个阀门数据体
        }
        else
        {
            lenght = (sizeof(struct DataBody) - (MAX_VALVE_NUM - ops->body->valve_num) * sizeof(struct valve_t)); // 至少要发送一个阀门数据体
        }
        for (int i = 0; i < lenght; i++)
        {
            rt_snprintf(temp, sizeof(temp), "%02X", ((rt_uint8_t *)ops->body)[i]);
            rt_memcpy(data_buf + i * 2, temp, 2);
        }
        ret = _Send_Handle(ops, data_num, cmd, data_buf);
        if (ret != RT_EOK)
        {
            ret = -ret;
        }
    }
    rt_mutex_release(ml307_mutex);
    return ret;
}

int Data_Resp(struct Ml307_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type, char *data, rt_uint8_t res)
{
    if (ml307_conncet_tcp_flag != 1)
    {
        LOG_E("ml307_conncet_tcp_flag error");
        return -RT_ERROR;
    }

    char data_buf[512] = {0};

    rt_int32_t len = rt_snprintf(data_buf, sizeof(data_buf), "%02X%02X%30s%02X", device_type, event_type, data, res);
    if (len < 0 || len >= sizeof(data_buf))
    {
        LOG_E("Resp Data buffer overflow");
        return -RT_ERROR;
    }
    // LOG_D("data_buf: %s", data_buf);
    return _Send_Handle(ops, data_num, cmd, data_buf);
}

#if 0
int Ml307_Recv_Data(struct Ml307_Ops *ops, char *data)
{
    // ops->body = (struct DataBody *)rt_malloc(sizeof(struct DataBody));
    // rt_memset(ops->body, 0, sizeof(struct DataBody));
    // rt_free(ops->body);
    return RT_EOK;
}
#endif

/***************************************发送处理函数************************************************ */
/**
 * 处理定时心跳事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Heartbeat(struct at_device *device, void *param)
{

    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    int ret                     = 0;

    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }
    ret = device->class->device_ops->control(device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
    if (ret != RT_EOK)
    {
        LOG_E("ml307 get signal failed\n");
        return -RT_ERROR;
    }
    ret = ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_DATA_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_HEARTBEAT);
    if (ret != RT_EOK)
    {
        LOG_E("ml307 send data failed\n");
        return ret;
    }

    return RT_EOK;
}

/**
 * 处理时间校准事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Time_Calibration(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }
    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_TIME_CALIBRATION, DEVICE_TYPE_ML307, EVENT_TYPE_TIME_CALIBRATION))
    {
        LOG_E("ml307 send cmd[%X] failed\n", CMD_TYPE_TIME_CALIBRATION);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理报警事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Alarm(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }
    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_ALARM))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_ALARM);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理报警恢复事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Alarm_Recover(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_ALARM_RECOVER))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_ALARM_RECOVER);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理故障事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Fault(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_FAULT))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_FAULT);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理故障恢复事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Fault_Recover(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_FAULT_RECOVER))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_FAULT_RECOVER);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理自检事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Self_Check(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_SELF_CHECK))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_SELF_CHECK);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理消音事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Silence(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_SILENCE))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_SILENCE);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理异常事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Exception(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_EXCEPTION))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_EXCEPTION);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理电磁阀状态改变事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Valve_Status(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_VALVE_STATUS))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_VALVE_STATUS);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理风扇状态改变事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Fan_Status(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_FAN_STATUS))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_FAN_STATUS);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理温度异常事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Temp_Anomaly(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_TEMP_ANOMALY))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_TEMP_ANOMALY);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理上电事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Power_On(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_POWER_ON))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_POWER_ON);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理断电事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Power_Off(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_POWER_OFF))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_POWER_OFF);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理阀门连接事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Valve_Connect(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_VALVE_CONNECT))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_VALVE_CONNECT);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理阀门断开事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Valve_Disconnect(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_VALVE_DISCONNECT))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_VALVE_DISCONNECT);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 * 处理设备故障事件
 * @param device 设备结构体指针
 * @param param 操作结构体指针
 * @return 操作结果
 */
int Ml307_Send_Device_Failure(struct at_device *device, void *param)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    if ((device == RT_NULL) || (ml307_ops == RT_NULL))
    {
        LOG_E("ml307 param error\n");
        return RT_ERROR;
    }

    if (ml307_ops->send(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_DEVICE_FAILURE))
    {
        LOG_E("ml307 send cmd[%X] failed\n", EVENT_TYPE_DEVICE_FAILURE);
        return -RT_ERROR;
    }
    return RT_EOK;
}
/*这个【4、优先级最低当同时触发后，相同服务直接合并】暂时还没想好怎么做，
思路感觉就是得重新开一个线程，然后再开一个任务队列，将所有的事件，发送到任务队列
在线程中，对任务队列进行查看并处理，看目前都有哪些事件，是处于那个优先级得，如果是最低优先级，就只发送一帧数据就行了，
如果是不同优先级，按照优先级顺序发送事件，但感觉这样会使得程序更复杂，本来发送就很快，感觉没必要这样搞*/
const Ml307EventInfo ml307_event_info[] = {
    {kMl307PowerOnEvent, kMl307PriorityHighest, "上电心跳事件", Ml307_Send_Power_On},
    {kMl307PowerDownEvent, kMl307PriorityHigh, "掉电事件", Ml307_Send_Power_Off},
    {kMl307ValveConnectEvent, kMl307PriorityMedium, "阀门连接事件", Ml307_Send_Valve_Connect},
    {KMl307ValveDisconnectEvent, kMl307PriorityMedium, "阀门断开事件", Ml307_Send_Valve_Disconnect},
    {kMl307SelfCheckEvent, kMl307PriorityMedium, "自检事件", Ml307_Send_Self_Check},
    {kMl307HeartbeatEvent, kMl307PriorityLowest, "定时心跳事件", Ml307_Send_Heartbeat},
    {kMl307TempAnomalyEvent, kMl307PriorityLowest, "温度异常事件", Ml307_Send_Temp_Anomaly},
    {kMl307AlarmEvent, kMl307PriorityLowest, "报警触发事件", Ml307_Send_Alarm},
    {kMl307AlarmRcyEvent, kMl307PriorityLowest, "报警解除事件", Ml307_Send_Alarm_Recover},
    {kMl307FaultEvent, kMl307PriorityLowest, "传感器故障事件", Ml307_Send_Fault},
    {kMl307FaultRcyEvent, kMl307PriorityLowest, "传感器故障解除事件", Ml307_Send_Fault_Recover},
    {kMl307TimeCalibrationEvent, kMl307PriorityLowest, "时间校准事件", Ml307_Send_Time_Calibration},
    {kMl307SilenceEvent, kMl307PriorityLowest, "消音事件", Ml307_Send_Silence},
    // {kMl307ExceptionEvent, kMl307PriorityLowest, "异常事件", Ml307_Send_Exception},
    {kMl307ValveStatusEvent, kMl307PriorityLowest, "电磁阀状态改变事件", Ml307_Send_Valve_Status},
    {kMl307FanStatusEvent, kMl307PriorityLowest, "风机状态改变事件", Ml307_Send_Fan_Status},
    {kMl307DeviceFailureEvent, kMl307PriorityLowest, "设备失效事件", Ml307_Send_Device_Failure}};

Ml307Priority Get_Event_Priority(Ml307Event event_type)
{
    for (size_t i = 0; i < sizeof(ml307_event_info) / sizeof(ml307_event_info[0]); i++)
    {
        if (ml307_event_info[i].event_flag == event_type)
        {
            return ml307_event_info[i].priority;
        }
    }
    return kMl307PriorityLowest;
}

/**
 * 处理ML307设备的事件
 * @param ml307_recv_event 接收到的ML307事件标志
 * @return
 */
int Ml307_Process_Events(Ml307Event ml307_recv_event, struct at_device *device, void *param)
{
    rt_uint8_t cnt             = 0;
    rt_err_t ret               = RT_EOK;
    rt_uint8_t max_retry_count = (rt_uint8_t)Flash_Get_SysCfg(kIotRetryId);

    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
    const Ml307EventInfo *event = RT_NULL;

    for (size_t i = 0; i < sizeof(ml307_event_info) / sizeof(Ml307EventInfo); ++i)
    {
        // 检查当前事件是否在接收到的事件标志中
        if (ml307_recv_event == ml307_event_info[i].event_flag)
        {
            event = &ml307_event_info[i];
            break;
        }
    }
    if (event) // 处理该事件
    {
        // 打印事件的名称

        ml307_current_evnet = event->event_flag;
        for (size_t i = 0; i < max_retry_count; i++)
        {
            if (ml307_conncet_tcp_flag)
            {
                if (event->send_func)
                {
#ifdef TEST_ENABLE
                    RTC_ShowTime(); // 每次发送打印下时间，容易定位问题
#endif
                    LOG_D("%s上报, cnt :%d", event->event_name, cnt);

                    int result = event->send_func(device, ml307_ops);
                    if (result != RT_EOK)
                    {
                        LOG_E("ml307 send failed\n");
                        ret = RT_ERROR;
                        continue;
                    }
                    else
                    {
                        if (rt_sem_take(ml307_recv_msg_sem, 8000) == RT_EOK)
                        {
                            LOG_D("收到回复\n");
                            ml307_connect_sever_flag = 1;
                            ret                      = RT_EOK; // 函数执行完毕，返回0
                            break;
                        }
                        else
                        {
                            // 收不到说明在平台未注册或者信号不行,此时ml307_connect_sever_flag 为0，但ml307_conncet_tcp_flag = 1；此时不发起重连，等待事件触发就行
                            ret = RT_ERROR;
                        }
                    }
                }
            }
            else
            {
                ret = RT_ERROR;
            }
            if (event->priority < Get_Event_Priority(ml307_latest_evnet)) // 查看当前事件和新传入的事件的优先级哪个高，如果有高的直接退出处理高优先级的
            {
                LOG_W("有更高优先级的事件进入,退出当前处理\n");
                ret = RT_EOK;
                break;
            }
            rt_thread_mdelay(IMEI_Delay());
        }
    }
    if (rt_strcmp(event->event_name, "掉电事件") == RT_EOK)
    {
        LOG_D("掉电处理TCP");
        if (device->class->device_ops->control(device, AT_DEVICE_CTRL_NET_DISCONN, RT_NULL) == RT_EOK)
        {
            LOG_D("关闭TCP");
        }

        rt_pin_write(_dev.pwr_en_pin, PIN_LOW); // 断开3_8v供电
        LOG_D("关闭模组");
        ml307_power_down_flag = 1;
        ret                   = RT_EOK;
    }
    else
    {
        if (ret != RT_EOK)
        {
            ml307_connect_sever_flag = 0;
            ml307_conncet_tcp_flag   = 0;
            if (!ml307_disconnect_retry_flag)
            {
                LOG_D("断网,启动重连\n");
                rt_sem_release(ml307_disconnect_sem);
            }
            LOG_D("断网,等待连接中......\n");
        }
    }

    return ret;
}

// 比较帧头和帧尾
int Compare_HeaderToTail(struct Ml307_Ops *ops)
{
    // 比较帧头
    for (int i = 0; i < 3; i++)
    {
        if (ops->frame->header[i] != ops->recv->header[i])
        {
            LOG_E("ops->frame->header[%x] != ops->recv->header[%x]\n", ops->frame->header[i], ops->recv->header[i]);

            return -1;
        }
    }

    // 比较帧尾
    for (int i = 0; i < 3; i++)
    {
        if (ops->frame->tail[i] != ops->recv->tail[i])
        {
            LOG_E("ops->frame->tail[%x] != ops->recv->tail[%x]\n", ops->frame->tail[i], ops->recv->tail[i]);

            return -2;
        }
    }
    if (ops->recv->recv_data.res_num != RESPONSE_CODE_SUCCESS) // 判断是否为成功响应
    {
        LOG_E("ops->recv->recv_data.res_num[%x] != RESPONSE_CODE_SUCCESS\n", ops->recv->recv_data.res_num);

        return -3;
    }
    return RT_EOK;
}

void Handle_Server_Reply(struct Ml307_Ops *ops)
{
    if ((ops->recv->recv_data.event_type >= EVENT_TYPE_HEARTBEAT) &&
        (ops->recv->recv_data.event_type <= INSTRUCTION_DOWN_VALVE_REMOVE))
    {
        LOG_D("服务器响应成功,响应码:[%02X]\n", ops->recv->recv_data.event_type);
        rt_sem_release(ml307_recv_msg_sem);
    }
    else
    {
        LOG_E("服务器响应失败,响应码:[%02X]\n", ops->recv->recv_data.event_type);
    }
}

void Handle_Self_Check(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发自检指令\n");
    char imei[16] = {0};
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    LOG_D("imei:%s\n", imei);
    _Self_Check_Mode();
    rt_thread_mdelay(100);

    char temp[32] = "0";
    String2Hex(temp, imei); // 将字符串转为十六进制字符串
    LOG_D("temp: %s", temp);
    Send_Laser_Alarm_Event(kSelfCheckEvent);
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_SELF_CHECK, temp, RESPONSE_CODE_SUCCESS);

    Send_Laser_Alarm_Event(kNormalDetectionEvents); // 先返回正常状态，然后跳转到所处的状态
}

void Handle_Mute(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发消音指令\n");

    char imei[16] = {0};
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    char temp[32] = "0";
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    Send_Laser_Alarm_Event(KMuteEvent);
    rt_thread_mdelay(100);
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_MUTE, temp, RESPONSE_CODE_SUCCESS);
}

/*关阀  52-阀门编号（1byte）+ MAC地址（6byte）+ 补零字节  = 15byte    如果内容全部为0，则默认为关闭有线阀门*/
rt_err_t Handle_Close_Valve(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发关闭阀门指令\n");
    int i                                         = 0;
    rt_uint8_t data[FLASH_VALVE_MAC_ADDR_LEN + 1] = {0};
    rt_uint8_t mac_addr[6]                        = {0};
    char imei[16]                                 = {0};
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    char temp[32] = "0";
    String2Hex(temp, imei); // 将字符串转为十六进制字符串
    rt_memcpy(data, (ops->recv->recv_data.res_data + 8), FLASH_VALVE_MAC_ADDR_LEN + 1);
    LOG_D("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x data[6] = %x", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
    if ((data[0] > 0) && (data[0] < MAX_VALVE_NUM)) // 不为零则说明关闭无线阀门
    {
        rt_uint8_t cnt = Flash_Get_Valve_Num();
        if (cnt == 0)
        {
            LOG_E("没有设置无线阀门\n");
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
            return RT_ERROR;
        }
        else
        {
            LOG_D("无线阀门编号：%d\n", data[0]);
            if (Flash_Get_Mac_Addr(mac_addr, data[0]) != RT_EOK)
            {
                LOG_E("获取无线阀门mac地址失败\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
                return RT_ERROR;
            }
            LOG_D("mac_addr[0] = %x mac_addr[1] = %x mac_addr[2] = %x mac_addr[3] = %x mac_addr[4] = %x, mac_addr[5] = %x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
            /*对两个数组进行比较，如果值不同则退出*/
            for (; i < FLASH_VALVE_MAC_ADDR_LEN; i++)
            {
                if (mac_addr[i] != data[i + 1])
                {
                    LOG_E("mac_addr[%d][%x]!= data[%d][%x]\n", i, mac_addr[i], i + 1, data[i + 1]);

                    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);

                    return RT_ERROR;
                }
            }
            if (i == FLASH_VALVE_MAC_ADDR_LEN)
            {
                LOG_D("mac地址匹配成功,执行关阀动作\n");
                if (Bt_Valve_Handler(kValveCmdCtr, data[0], &data[1]) != RT_EOK)
                {
                    LOG_E("关阀失败\n");
                    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
                    return RT_ERROR;
                }
                if (rt_sem_take(&bt_ctr_sem, 10000) != RT_EOK) // 等待十秒获取信号量
                {
                    LOG_E("获取信号量失败\n");
                    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
                    return RT_ERROR;
                }
                else
                {
                    LOG_D("关阀成功\n");
                    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_SUCCESS);
                    return RT_EOK;
                }
            }
            else
            {
                LOG_E("mac地址匹配失败\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
            }
        }
    }
    else
    {
        LOG_D("关闭有线阀门\n");
        // TODO:此处需要增加关阀有线阀门的逻辑
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_SUCCESS);
        return RT_EOK;
    }
}

void Handle_Open_Valve(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发打开阀门指令\n");

    char imei[16] = {0};
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    char temp[32] = "0";
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    // // rt_uint8_t ret = BSP_Set_Emv_Status(1);
    // emv_state_flag = 1; // 电磁阀动作
    // rt_thread_mdelay(20);
    // emv_state_flag = 0;

    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_OPEN_VALVE, temp, RESPONSE_CODE_SUCCESS);
}

void Handle_Open_Relay(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发打开继电器指令\n");

    char imei[16] = {0};
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    char temp[32] = "0";
    String2Hex(temp, imei); // 将字符串转为十六进制字符串
    // relay_state_flag = 1;
    rt_thread_mdelay(10);
    // rt_uint8_t ret = BSP_Set_Relay_Status(0);
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_OPEN_RELAY, temp, RESPONSE_CODE_SUCCESS);
}

void Handle_Close_Relay(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发关闭继电器指令\n");

    char imei[16] = {0};
    char temp[32] = "0";

    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    // relay_state_flag = 0;
    rt_thread_mdelay(100);
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_RELAY, temp, RESPONSE_CODE_SUCCESS);
}

void Handle_Query_Params(struct Ml307_Ops *ops)
{
    rt_uint8_t data[10] = {0};
    char str[64]        = {0};
    LOG_D("服务器下发查询系统参数\n");

    rt_memcpy(data, (rt_uint8_t *)FLASH_HW_VER_ADDR, sizeof(sys_config_info) - 50);
    LOG_D("hw_ver:%02x sw_ver:%02x alarm_low:%02x alarm_high:%02x temp_alarm:%02x iot_upload_cycle:%dmin retry:%02x emagnetic:%02X relay_switch:%02X\n",
          data[0], data[1], data[2], data[3], data[4], ((data[5]) | (data[6] << 8)), data[7], data[8], data[9]);

    rt_sprintf(str, "0000000000%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
               data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9]);
    rt_thread_mdelay(100); // 释放下线程
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_QUERY_PARAMS, str, RESPONSE_CODE_SUCCESS);
}

int Handle_Config_Params(struct Ml307_Ops *ops)
{
    char data_buf[32]         = {0};
    rt_uint8_t recv_data[16]  = {0};
    rt_uint8_t flash_info[16] = {0};
    char imei[16]             = {0};
    char temp[32]             = "0";

    LOG_D("服务器下发配置参数\n");

    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    rt_memset(data_buf, '0', 32);
    rt_memcpy(recv_data, (ops->recv->recv_data.res_data + 5), sizeof(sys_config_info) - 50);
    rt_memcpy(flash_info, (rt_uint8_t *)FLASH_HW_VER_ADDR, sizeof(sys_config_info) - 50);

    LOG_D("hw_ver:%02x sw_ver:%02x alarm_low:%02x alarm_high:%02x temp_alarm:%02x iot_upload_cycle:%d min retry:%02x emagnetic:%02X relay_switch:%02X\n",
          flash_info[0], flash_info[1], flash_info[2], flash_info[3], flash_info[4], (flash_info[5] | (flash_info[6] << 8)), flash_info[7], flash_info[8], recv_data[9]);
    LOG_D("recv_data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n",
          recv_data[0], recv_data[1], recv_data[2], recv_data[3], recv_data[4],
          recv_data[5], recv_data[6], recv_data[7], recv_data[8], recv_data[9],
          recv_data[10], recv_data[11], recv_data[12], recv_data[13], recv_data[14], recv_data[15]);
    LOG_D("data:%s\n", data_buf);

    for (rt_uint8_t i = 0; i < (sizeof(sys_config_info) - 50); i++)
    {
        LOG_D("recv_data[%d] = %d", i, recv_data[i]);
        if (recv_data[i] != flash_info[i])
        {
            if ((recv_data[2] > 25) || (recv_data[2] < 5)) /*家报的报警设定值应在5%~25%之间*/
            {
                if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_ACTION_FAILURE) == RT_EOK)
                {
                    LOG_W("recv_data[3] :%d", recv_data[3]);
                    LOG_W("配置参数超出范围，请核实后重试\n");
                }
                return RT_EOK;
            }
            else // 如果没有超出，再写入信息
            {
                if (BSP_Flash_Write_Info(recv_data, sizeof(sys_config_info) - 50) != 0)
                {
                    rt_uint16_t iot_upload_time = (uint16_t)Flash_Get_SysCfg(kIotUploadCycleId);
                    unsigned long timeout       = iot_upload_time * 60 * RT_TICK_PER_SECOND;
                    rt_timer_control(ml307_timer, RT_TIMER_CTRL_SET_TIME, (void *)&timeout); // 更新上报周期
                    LOG_D("上报周期由%dmin更新为%dmin", ((flash_info[5] << 8) | flash_info[6]), iot_upload_time);
                    if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_SUCCESS) == RT_EOK)
                    {
                        LOG_D("配置参数写入成功\n");
                    }
                    return RT_EOK;
                }
                else
                {
                    LOG_D("配置参数写入失败\n");
                    if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_ACTION_FAILURE) == RT_EOK)
                    {
                        LOG_D("写入失败响应成功\n");
                    }
                    return RT_ERROR;
                }
            }
        }
    }
    if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_SUCCESS) == RT_EOK)
    {
        LOG_D("配置参数没有变化\n");
    }
    return RT_EOK;
}

void Handle_Time_Calibration_Data(struct Ml307_Ops *ops)
{
    rt_uint8_t data[10] = {0};
    TsRtcDateTime rtc_dt;
    char imei[16] = {0};
    char temp[32] = "0";

    LOG_D("时间校准数据\n");

    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    rt_memcpy(data, ops->recv->recv_data.res_data, sizeof(data));

    // 提取后4个字节作为时间戳
    time_t timestamp = (data[6] << 24) | (data[7] << 16) | (data[8] << 8) | data[9];
    Timestamp_To_Rtc_DateTime(timestamp, &rtc_dt);
    // 打印结果
    LOG_I("时间: %04d-%02d-%02d %02d:%02d:%02d (星期%d)\n",
          rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second, rtc_dt.week);
    RTC_SetTime(rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, 0); /* Setup Time */
    rt_thread_mdelay(100);                                                             // 释放下线程
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_TIME_CALIBRATION, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_TIME_CALIBRATION, temp, RESPONSE_CODE_SUCCESS);
}

// 下发修改服务器地址指令
void Handle_Sever_Addr_Set(struct Ml307_Ops *ops)
{
    flash_sever_info sever_info = {0};
    rt_uint8_t data[6]          = {0};
    char imei[16]               = {0};
    char temp[32]               = "0";

    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串
    rt_memcpy(data, (ops->recv->recv_data.res_data + 9), FLASH_SERVER_LEN);
    LOG_D("data[%d] = %x data[%d] = %x data[%d] = %x data[%d] = %x data[%d] = %x data[%d] = %x", 0, data[0], 1, data[1], 2, data[2], 3, data[3], 4, data[4], 5, data[5]);
    Flash_Set_Sever_Data(data);
    if (Flash_Get_Sever_Data(&sever_info) == RESET)
    {
        LOG_E("服务器地址修改失败\n");
    }
    else
    {
        LOG_D("服务器地址修改成功\n");
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_SEVER_ADDR, temp, RESPONSE_CODE_SUCCESS);
    }
}

/*新增阀门设备*/
rt_err_t Handle_Valve_Add(struct Ml307_Ops *ops)
{
    LOG_D("服务器下发注册阀门指令\n");
    rt_uint8_t data[7] = {0};
    char imei[16]      = {0};
    char temp[32]      = "0";
    rt_uint8_t cnt     = Flash_Get_Valve_Num();
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    if (cnt >= 1)
    {
        LOG_E("阀门设备数量超过最大值\n");
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
        return RT_ERROR;
    }
    // 无阀门数据时添加，有阀门数据时不添加
    if (cnt >= 0 && cnt < MAX_VALVE_NUM)
    {
        rt_memcpy(data, (ops->recv->recv_data.res_data + 8), FLASH_VALVE_MAC_ADDR_LEN + 1);
        if (data[0] > 1)
        {
            LOG_E("阀门设备数量超过最大值[1]\n");
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_OTHER_ERROR);
            return RT_ERROR;
        }

        LOG_D("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x data[6] = %x", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);

        valve[data[0] - 1].valve_id = data[0];                                       // 更新阀门ID
        rt_memcpy(valve[data[0] - 1].valve_mac, &data[1], FLASH_VALVE_MAC_ADDR_LEN); // 更新MAC地址
        if (Bt_Valve_Handler(kValveCmdReg, data[0], &data[1]) != RT_EOK)             // 更新蓝牙端mac地址
        {
            LOG_E("新增阀门设备失败\n");
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
            return RT_ERROR;
        }
        if (rt_sem_take(&bt_reg_sem, 10000) != RT_EOK) // 等待十秒获取信号量
        {
            LOG_E("获取信号量失败\n");
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
            return RT_ERROR;
        }
        else
        {
            if (Flash_Set_Mac_Addr(&data[1], data[0]) == RESET)
            {
                LOG_E("阀门设备写入FLash失败\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
                return RT_ERROR;
            }
            LOG_D("新增阀门设备成功\n");
            Flash_Set_Valve_Num(cnt + 1);
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_SUCCESS);
            return RT_EOK;
        }
    }
    return RT_EOK;
}

/*更换阀门设备*/
rt_err_t Handle_Valve_Replace(struct Ml307_Ops *ops)
{
    size_t i                                      = 0;
    rt_uint8_t data[13]                           = {0};
    rt_uint8_t mac_addr[FLASH_VALVE_MAC_ADDR_LEN] = {0};
    char imei[16]                                 = {0};
    char temp[32]                                 = "0";
    LOG_I("服务器下发更换阀门设备");
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串
    rt_memcpy(data, (ops->recv->recv_data.res_data + 2), (2 * FLASH_VALVE_MAC_ADDR_LEN + 1));
    LOG_HEX("data", 16, data, sizeof(data));
    /*设备编号（1byte）+ 新MAC地址（6）+ 旧阀门MAC地址（6） + 补零字节= 15byte*/
    if (Flash_Get_Mac_Addr(mac_addr, data[0]) == RT_EOK)
    {
        for (; i < FLASH_VALVE_MAC_ADDR_LEN; i++)
        {
            if (mac_addr[i] != data[i + 7])
            {
                LOG_E("旧阀门地址错误\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_OTHER_ERROR);
                return RT_ERROR;
            }
        }
        LOG_D("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x data[6] = %x data[7] = %x data[8] = %x data[9] = %x data[10] = %x data[11] = %x data[12] = %x",
              data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12]);
        if (i == FLASH_VALVE_MAC_ADDR_LEN)
        {
            if (Bt_Valve_Handler(kValveCmdRep, data[0], &data[1]) != RT_EOK)
            {
                LOG_E("更换阀门设备失败\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_ACTION_FAILURE);
                return RT_ERROR;
            }
            if (rt_sem_take(&bt_rep_sem, 10000) != RT_EOK) // 等待十秒获取信号量
            {
                LOG_E("获取更换阀门信号量失败\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
                return RT_ERROR;
            }
            else
            {
                if (Flash_Set_Mac_Addr(&data[1], data[0]) == RESET)
                {
                    LOG_E("更换阀门设备失败\n");
                    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_ACTION_FAILURE);
                    return RT_ERROR;
                }
                LOG_D("更换阀门设备成功\n");
                ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_SUCCESS);
                return RT_EOK;
            }
        }
        else
        {
            LOG_E("旧阀门MAC地址错误\n");
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_OTHER_ERROR);
            return RT_ERROR;
        }
    }
    else
    {
        LOG_E("该阀门设备错误\n");
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_PARSE_FAIL);
    }
    return RT_EOK;
}

/*移除阀门设备*/
rt_err_t Handle_Remove_Valve(struct Ml307_Ops *ops)
{
    rt_uint8_t data[8] = {0};
    char imei[16]      = {0};
    char temp[32]      = "0";
    rt_uint8_t cnt     = Flash_Get_Valve_Num();
    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串

    LOG_I("接收到服务器下发移除阀门指令");
#if 1
    if (cnt == 0)
    {
        LOG_W("阀门设备数量为0\n");
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_SUCCESS); // 如果本地无阀门信息，直接返回成功

        return RT_EOK;
    }
    rt_memcpy(data, (ops->recv->recv_data.res_data + 8), FLASH_VALVE_MAC_ADDR_LEN + 1);
    LOG_D("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
    if (Bt_Valve_Handler(kValveCmdRem, data[0], &data[1]) != RT_EOK)
    {
        LOG_E("移除阀门设备失败\n");
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_ACTION_FAILURE);

        return RT_ERROR;
    }
    if (rt_sem_take(&bt_rem_sem, 10000) != RT_EOK) // 等待十秒获取信号量
    {
        LOG_E("获取移除阀门信号量失败\n");
        ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_ACTION_FAILURE);
        return RT_ERROR;
    }
    else
    {
        rt_memset(&data[1], 0, 6);
        if (Flash_Set_Mac_Addr(&data[1], data[0]) == RESET)
        {
            LOG_E("移除阀门设备失败\n");
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_ACTION_FAILURE);

            return RT_ERROR;
        }
        else
        {
            LOG_D("移除阀门设备成功\n");
            Flash_Set_Valve_Num(cnt - 1);
            ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_SUCCESS);

            return RT_EOK;
        }
    }
#endif
}

void Handle_Error(struct Ml307_Ops *ops, rt_err_t ret)
{
    LOG_E("数据帧解析失败，错误码: %d", ret);

    char imei[16] = {0};
    char temp[32] = "0";

    Get_IotImei(imei, FLASH_IOT_IMEI_LEN);
    String2Hex(temp, imei); // 将字符串转为十六进制字符串
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, ops->recv->cmd, temp, RESPONSE_CODE_PARSE_FAIL);
}

void Handle_Instruction_Down(struct Ml307_Ops *ops)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)ops;

    switch (ml307_ops->recv->recv_data.event_type)
    {
        case INSTRUCTION_DOWN_SELF_CHECK:
            Handle_Self_Check(ml307_ops);
            break;
        case INSTRUCTION_DOWN_MUTE:
            Handle_Mute(ml307_ops);
            break;
        case INSTRUCTION_DOWN_CLOSE_VALVE:
            Handle_Close_Valve(ml307_ops);
            break;
        case INSTRUCTION_DOWN_OPEN_VALVE:
            Handle_Open_Valve(ml307_ops);
            break;
        case INSTRUCTION_DOWN_OPEN_RELAY:
            Handle_Open_Relay(ml307_ops);
            break;
        case INSTRUCTION_DOWN_CLOSE_RELAY:
            Handle_Close_Relay(ml307_ops);
            break;
        case INSTRUCTION_DOWN_QUERY_PARAMS:
            Handle_Query_Params(ml307_ops);
            break;
        case INSTRUCTION_DOWN_CONFIG_PARAMS:
            Handle_Config_Params(ml307_ops);
            break;
        case INSTRUCTION_DOWN_TIME_CALIBRATION:
            Handle_Time_Calibration_Data(ml307_ops);
            break;
        case INSTRUCTION_DOWN_SEVER_ADDR:
            Handle_Sever_Addr_Set(ml307_ops);
            break;
        case INSTRUCTION_DOWN_VALVE_ADD:
            Handle_Valve_Add(ml307_ops);
            break;
        case INSTRUCTION_DOWN_VALVE_REPLACE:
            Handle_Valve_Replace(ml307_ops);
            break;
        case INSTRUCTION_DOWN_VALVE_REMOVE:
            Handle_Remove_Valve(ml307_ops);
            break;
    }
}

void Handle_Time_Calibration(struct Ml307_Ops *ops)
{
    rt_uint8_t data[10] = {0};
    LOG_D("服务器下发时间校准数据\n");
    rt_memcpy(data, ops->recv->recv_data.res_data, sizeof(data));
    TsRtcDateTime rtc_dt;
    // 提取后4个字节作为时间戳
    time_t timestamp = (data[6] << 24) | (data[7] << 16) | (data[8] << 8) | data[9];
    Timestamp_To_Rtc_DateTime(timestamp, &rtc_dt);
    // 打印结果
    LOG_I("时间: %04d-%02d-%02d %02d:%02d:%02d (星期%d)\n",
          rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second, rtc_dt.week);
    RTC_SetTime(rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second); /* Setup Time */
    ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_TIME_CALIBRATION, ML307_DEFIENE_DATA, RESPONSE_CODE_SUCCESS);
}

void Handle_Cmd_Type(struct Ml307_Ops *ops)
{
    struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)ops;

    switch (ml307_ops->recv->cmd)
    {
        case CMD_TYPE_SERVER_REPLY:
            Handle_Server_Reply(ml307_ops);
            break;
        case CMD_TYPE_INSTRUCTION_DOWN:
            Handle_Instruction_Down(ml307_ops);
            break;
        case CMD_TYPE_TIME_CALIBRATION:
            Handle_Time_Calibration(ml307_ops);
            break;
        default:
            ml307_ops->Resp(ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, ops->recv->cmd, ML307_DEFIENE_DATA, RESPONSE_CODE_PARSE_FAIL);
            break;
    }
}

void Analyze_Recv_Frame(struct at_device *device, struct Ml307_Ops *ops)
{
    rt_err_t ret = RT_EOK;

    ret = Compare_HeaderToTail(ops);
    if (ret == RT_EOK)
    {
        Handle_Cmd_Type(ops);
    }
    else
    {
        Handle_Error(ops, ret);
    }
}

/*
上电模式
发送一包数据后，转换到检测模式 120分钟发送一次数据
当有事件发生时，发送一包事件数据包
*/
static void Ml307_Send_Thread_Entry(void *param)
{
    rt_err_t result = RT_EOK;
    rt_uint32_t ml307_recv_event;
    LOG_D("ml307 thread entry\n");

    struct Ml307_Ops *ops         = (struct Ml307_Ops *)param;
    struct at_device_ml307 *ml307 = &_dev;
    struct at_device *device      = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, ml307->device_name);
    RT_ASSERT(device);

    if (ops->init(ops, PROTOCOL_VERSION) != RT_EOK)
    {
        LOG_E("ml307 init failed\n");
    }
    else
    {
        LOG_D("ml307 init success\n");
        rt_completion_wait(&ml307_init_complate, RT_WAITING_FOREVER); // wait for ml307 init finish
        Ml307_Send_Event(kMl307PowerOnEvent);
    }
    while (1)
    {
        result = rt_event_recv(&at_device_event,
                               Ml307_Get_Event_Flag(kMl307PowerOnEvent) |
                                   Ml307_Get_Event_Flag(kMl307HeartbeatEvent) |
                                   Ml307_Get_Event_Flag(kMl307SelfCheckEvent) |
                                   Ml307_Get_Event_Flag(kMl307SilenceEvent) |
                                   Ml307_Get_Event_Flag(kMl307ExceptionEvent) |
                                   Ml307_Get_Event_Flag(kMl307ValveStatusEvent) |
                                   Ml307_Get_Event_Flag(kMl307FanStatusEvent) |
                                   Ml307_Get_Event_Flag(kMl307TempAnomalyEvent) |
                                   Ml307_Get_Event_Flag(kMl307PowerOnEvent) |
                                   Ml307_Get_Event_Flag(kMl307PowerDownEvent) |
                                   Ml307_Get_Event_Flag(kMl307AlarmEvent) |
                                   Ml307_Get_Event_Flag(kMl307AlarmRcyEvent) |
                                   Ml307_Get_Event_Flag(kMl307FaultEvent) |
                                   Ml307_Get_Event_Flag(kMl307FaultRcyEvent) |
                                   Ml307_Get_Event_Flag(kMl307DeviceFailureEvent) |
                                   Ml307_Get_Event_Flag(kMl307TimeCalibrationEvent) |
                                   Ml307_Get_Event_Flag(kMl307ValveConnectEvent) |
                                   Ml307_Get_Event_Flag(KMl307ValveDisconnectEvent),
                               RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                               RT_WAITING_FOREVER, &ml307_recv_event); // 这个事件一般是设备端发生了变化，发送到服务器时调用

        if (result == RT_EOK)
        {
            if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307PowerOnEvent))
            {
                result = Ml307_Process_Events(kMl307PowerOnEvent, device, ops); // 当上电心跳包发送不成功时，其他事件不启动
                if (result)
                {
                    power_on_send_flag = 0;
                    rt_timer_start(ml307_error_timer); // 启动重连定时器， 3min一次，直到发送成功
                    LOG_E("ml307 send data failed result = [%d]\n", result);
                }
                else
                {
                    power_on_send_flag = 1;
                    rt_timer_start(ml307_timer);        // 当上电心跳包发送成功时, 开始心跳包周期发送
                    rt_timer_start(ml307_upload_timer); // 周期修改时间更新
                }
            }
            else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307PowerDownEvent))
            {
                result = Ml307_Process_Events(kMl307PowerDownEvent, device, ops);
                if (result)
                {
                    LOG_E("ml307 send data failed result = [%d]\n", result);
                }
                ml307_event_initialized = RT_FALSE; // 当接收到掉电事件时，不再接收其他事件
            }
            if (power_on_send_flag)
            {
                if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307HeartbeatEvent))
                {
                    result = Ml307_Process_Events(kMl307HeartbeatEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307ValveConnectEvent))
                {
                    result = Ml307_Process_Events(kMl307ValveConnectEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(KMl307ValveDisconnectEvent))
                {
                    result = Ml307_Process_Events(KMl307ValveDisconnectEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307TimeCalibrationEvent))
                {
                    Time_Calibration(device);
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307AlarmEvent))
                {
                    result = Ml307_Process_Events(kMl307AlarmEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307AlarmRcyEvent))
                {
                    result = Ml307_Process_Events(kMl307AlarmRcyEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307FaultEvent))
                {
                    if (device_state_flag != 1) // 当设备失效时，只上报失效信息
                    {
                        result = Ml307_Process_Events(kMl307FaultEvent, device, ops);
                        if (result)
                        {
                            LOG_E("ml307 send data failed result = [%d]\n", result);
                        }
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307FaultRcyEvent))
                {
                    result = Ml307_Process_Events(kMl307FaultRcyEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307SelfCheckEvent))
                {
                    result = Ml307_Process_Events(kMl307SelfCheckEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307SilenceEvent))
                {
                    result = Ml307_Process_Events(kMl307SilenceEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307ExceptionEvent))
                {
                    result = Ml307_Process_Events(kMl307ExceptionEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307ValveStatusEvent))
                {
                    result = Ml307_Process_Events(kMl307ValveStatusEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307FanStatusEvent))
                {
                    result = Ml307_Process_Events(kMl307FanStatusEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307TempAnomalyEvent))
                {
                    result = Ml307_Process_Events(kMl307TempAnomalyEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
                else if (ml307_recv_event & Ml307_Get_Event_Flag(kMl307DeviceFailureEvent))
                {
                    result = Ml307_Process_Events(kMl307DeviceFailureEvent, device, ops);
                    if (result)
                    {
                        LOG_E("ml307 send data failed result = [%d]\n", result);
                    }
                }
            }
        }
    }
}

static void Ml307_Recv_Thread_Entry(void *parameter)
{
    struct Ml307_Ops *ops         = (struct Ml307_Ops *)parameter;
    struct at_device_ml307 *ml307 = &_dev;
    struct at_device *device      = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, ml307->device_name);
    RT_ASSERT(device);

    LOG_D("ml307 recv thread entry\n");

    while (1)
    {
        if (rt_sem_take(ml307_recv_sem, RT_WAITING_FOREVER) == RT_EOK)
        {
            Analyze_Recv_Frame(device, ops);
        }
    }
}

static void Ml307_Life_Thread_Entry(void *parameter)
{
    struct at_device_ml307 *ml307 = &_dev;
    struct at_device *device      = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, ml307->device_name);
    RT_ASSERT(device);
    rt_err_t result         = RT_ETIMEOUT;
    rt_uint32_t delay_n     = 0;
    at_response_t resp      = RT_NULL;
    rt_uint32_t retry_delay = 8000;
    LOG_D("ml307_life_thread entry\n");

    while (1)
    {
        result = rt_sem_take(ml307_disconnect_sem, RT_WAITING_FOREVER);
        if (result == RT_EOK)
        {
            if (!ml307_conncet_tcp_flag)
            {
                LOG_D("重连网络中...\n");
                ml307_connect_sever_flag = 0;
                resp                     = at_create_resp(128, 0, 5000);
                if (resp == RT_NULL)
                {
                    LOG_E("No memory for response structure!");
                    at_delete_resp(resp);
                    result = -RT_ETIMEOUT;
                    goto __exit;
                }
                if (device->class->device_ops->control(device, AT_DEVICE_CTRL_NET_DISCONN, RT_NULL) == RT_EOK)
                {
                    rt_thread_mdelay(RT_TICK_PER_SECOND); // 这里如果有TCP连接，先关掉TCP,没有返回错误无所谓
                }
                if (device->class->device_ops->control(device, AT_DEVICE_CTRL_POWER_OFF, RT_NULL) == RT_EOK)
                {
                    if (device->class->device_ops->control(device, AT_DEVICE_CTRL_POWER_ON, RT_NULL) == RT_EOK)
                    {
                        LOG_D("AT device power on success");
                        rt_thread_mdelay(RT_TICK_PER_SECOND / 2);
                        /* disable echo */
                        LOG_D("AT");
                        if (at_client_obj_wait_connect(device->client, 10000) != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /* disable echo */
                        LOG_D("ATE0");
                        if (at_obj_exec_cmd(device->client, resp, "ATE0") != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /*disable sleep mode */
                        if (at_obj_exec_cmd(device->client, resp, "AT+MLPMCFG=\"sleepmode\",0,1") != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /*设置包模式*/
                        if (at_obj_exec_cmd(device->client, resp, "AT+MIPCFG=\"encoding\",0,1,1") != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /*设置包模式*/
                        if (at_obj_exec_cmd(device->client, resp, "AT+MIPCFG=\"autofree\",0,0") != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /*设置心跳包*/
                        if (at_obj_exec_cmd(device->client, resp, "AT+MIPTKA=0,1,120,60,1") != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /* Define PDP Context */
                        rt_uint8_t i = 0;
                        for (i = 0; i < 5; i++)
                        {
                            if (at_obj_exec_cmd(device->client, resp, "AT+CGDCONT=1,\"IPV4V6\",\"cmnet\"") == RT_EOK)
                            {
                                LOG_D("%s device Define PDP Context Success.", device->name);
                                break;
                            }
                            rt_thread_mdelay(1000);
                        }
                        if (i == 5)
                        {
                            LOG_E("%s device Define PDP Context failed.", device->name);
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /* check SIM card */
                        for (i = 0; i < 60; i++)
                        {
                            if (at_obj_exec_cmd(device->client, resp, "AT+CPIN?") == RT_EOK)
                            {
                                char code[8] = {0};
                                if (at_resp_parse_line_args_by_kw(resp, "+CPIN:", "+CPIN: %s", code) > 0)
                                {
                                    if (rt_strcmp(code, "READY") == 0)
                                    {
                                        LOG_D("%s device SIM card detection success.", device->name);
                                        break;
                                    }
                                    else
                                    {
                                        LOG_E("%s device SIM card detection failed.", device->name);
                                        result = -RT_ERROR;
                                        goto __exit;
                                    }
                                }
                            }
                            rt_thread_mdelay(3000);
                        }
                        if (i == 60)
                        {
                            LOG_E("%s device SIM card detection failed.", device->name);
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        /* check the GPRS network is registered */
                        for (i = 0; i < 60; i++)
                        {
                            if (at_obj_exec_cmd(device->client, resp, "AT+CEREG?") == RT_EOK)
                            {
                                int link_stat = 0;

                                if (at_resp_parse_line_args_by_kw(resp, "+CEREG:", "+CEREG: %*d,%d", &link_stat) > 0)
                                {
                                    if ((link_stat == 1) || (link_stat == 5))
                                    {
                                        LOG_D("%s device GPRS is registered", device->name);
                                        break;
                                    }
                                }
                            }
                            rt_thread_mdelay(1000);
                        }
                        if (i == 60)
                        {
                            LOG_E("%s device GPRS is register failed", device->name);
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        if (at_obj_exec_cmd(device->client, resp, "AT+MIPCALL=1,1") != RT_EOK)
                        {
                            result = -RT_ERROR;
                            goto __exit;
                        }
                        if (device->class->device_ops->control(device, AT_DEVICE_CTRL_NET_CONN, RT_NULL) == RT_EOK)
                        {
                            LOG_D("重连网络成功\n");
                            ml307_conncet_tcp_flag      = 1;
                            delay_n                     = 0;
                            ml307_disconnect_retry_flag = 0;
                            at_delete_resp(resp);
                            retry_delay = 8000; // 重置重连延迟时间
                            rt_thread_mdelay(100);
                            Ml307_Send_Event(kMl307HeartbeatEvent);
                        }
                        else
                        {
                            result = -RT_ETIMEOUT;
                            goto __exit;
                        }
                    }
                    else
                    {
                        result = -RT_ETIMEOUT;
                        goto __exit;
                    }
                }
                else
                {
                    result = -RT_ETIMEOUT;
                    goto __exit;
                }
            }
            else
            {
                ml307_disconnect_retry_flag = 0;
            }
        }
        else
        {
            delay_n = 0;
            result  = -RT_ETIMEOUT;
            goto __exit;
        }
    __exit:
        if (result != RT_EOK)
        {
            if (resp != RT_NULL)
            {
                at_delete_resp(resp);
            }
            ml307_disconnect_retry_flag = 1;
            LOG_D("联网错误,等待%dms后重连", retry_delay);
            rt_thread_mdelay(retry_delay);
            retry_delay = MIN(retry_delay * 2, 1800000); // 最大延迟30min
            delay_n++;
            if (delay_n >= 21) // 连续重连大于1小时都不行，则重启设备
            {
                Flash_Set_WorkDuration(work_duration);
                rt_thread_mdelay(100);
                reboot();
            }
            ml307_conncet_tcp_flag = 0;
            rt_sem_release(ml307_disconnect_sem);
        }
    }
}

static void Ml307_Upload_Timer_Cb(void *parameter)
{
    Ml307_Send_Event(kMl307TimeCalibrationEvent); // 更新下时间
}

int BSP_Ml307_Thread_Init(void)
{
    rt_err_t ret;
    Ml307_Event_Init();
    rt_uint32_t iot_upload_time = (uint32_t)Flash_Get_SysCfg(kIotUploadCycleId);
    rt_uint32_t timeout         = 0;

    if (iot_upload_time > 24 * 60 * 60 * RT_TICK_PER_SECOND)
    {
        timeout = 24 * 60 * 60 * RT_TICK_PER_SECOND;
        LOG_E("iot_upload_time > 24 * 60 * 60 * RT_TICK_PER_SECOND");
    }
    else
    {
        timeout = (iot_upload_time * 60 * RT_TICK_PER_SECOND);
        if (timeout >= RT_TICK_MAX / 2) // 超了就直接默认值
        {
            timeout = 60 * 60 * RT_TICK_PER_SECOND;
        }
    }

    LOG_I("上报服务器周期：%d分钟", iot_upload_time);

    ml307_mutex = rt_mutex_create("ml307_mutex", RT_IPC_FLAG_FIFO);
    if (ml307_mutex == RT_NULL)
    {
        LOG_E("ml307_mutex create failed");
    }
    ml307_recv_sem = rt_sem_create("ml307_recv", 0, RT_IPC_FLAG_PRIO);
    if (ml307_recv_sem == RT_NULL)
    {
        LOG_E("ml307_recv_sem create failed");
    }
    ml307_recv_msg_sem = rt_sem_create("ml307_recv_heart", 0, RT_IPC_FLAG_PRIO);
    if (ml307_recv_msg_sem == RT_NULL)
    {
        LOG_E("ml307_recv_msg_sem create failed");
    }
    ml307_disconnect_sem = rt_sem_create("ml307_life", 0, RT_IPC_FLAG_PRIO);
    if (ml307_disconnect_sem == RT_NULL)
    {
        LOG_E("ml307_disconnect_sem create failed");
    }
    // 创建定时器
    ml307_timer = rt_timer_create("heartbeat",
                                  Ml307_Ht_Timer_Cb,       // 回调函数
                                  RT_NULL,                 // 参数
                                  timeout,                 // 定时周期（120分钟）
                                  RT_TIMER_FLAG_PERIODIC); // 周期性定时器

    if (ml307_timer == RT_NULL)
    {
        rt_kprintf("创建定时器失败\n");
        return -1;
    }
    ml307_error_timer  = rt_timer_create("ml307_error_timer",
                                         Ml307_Error_Timer_Cb,
                                         RT_NULL,
                                         3 * 60 * RT_TICK_PER_SECOND, // （3分钟）
                                         RT_TIMER_FLAG_PERIODIC);
    ml307_upload_timer = rt_timer_create("ml307_upload_timer",
                                         Ml307_Upload_Timer_Cb,
                                         RT_NULL,
                                         24 * 60 * RT_TICK_PER_SECOND, //
                                         RT_TIMER_FLAG_PERIODIC);
    ret                = rt_thread_init(&ml307_thread,
                                        "ml307_send_thread",
                                        Ml307_Send_Thread_Entry,
                                        &ml307_ops,
                                        &ml307_thread_stack[0],
                                        sizeof(ml307_thread_stack),
                                        ML307_THREAD_PRIORITY,
                                        ML307_THREAD_TICKS);
    rt_thread_startup(&ml307_thread);

    ret = rt_thread_init(&ml307_recv_thread,
                         "ml307_recv_thread",
                         Ml307_Recv_Thread_Entry,
                         &ml307_ops,
                         &ml307_recv_thread_stack[0],
                         sizeof(ml307_recv_thread_stack),
                         ML307_RECV_THREAD_PRIORITY,
                         ML307_RECV_THREAD_TICKS);
    rt_thread_startup(&ml307_recv_thread);

    ret = rt_thread_init(&ml307_life_thread,
                         "ml307_life_thread",
                         Ml307_Life_Thread_Entry,
                         &ml307_ops,
                         &ml307_life_thread_stack[0],
                         sizeof(ml307_life_thread_stack),
                         ML307_LIFE_THREAD_PRIORITY,
                         ML307_LIFE_THREAD_TICKS);
    rt_thread_startup(&ml307_life_thread);

    return ret;
}
// INIT_APP_EXPORT(BSP_Ml307_Thread_Init);

int ml307_device_register(void)
{
    struct at_device_ml307 *ml307 = &_dev;

    return at_device_register(&(ml307->device),
                              ml307->device_name,
                              ml307->client_name,
                              AT_DEVICE_CLASS_ML307,
                              (void *)ml307);
}
// INIT_DEVICE_EXPORT(ml307_device_register);

#endif // IOT_MODULE_SWITCH
