/**
 * @file i2c_mcu.c
 * @brief MCU I2C通信模块，实现与MCU的I2C通信功能，包括初始化、写入、读取和写后读操作。
 * @details 本模块通过I2C总线与MCU通信，使用ESP32 GPIO15(SCL)和GPIO16(SDA)作为I2C引脚，通信速率为100kHz。
 *          所有通信均以6字节为单位进行收发，写操作和读操作均遵循I2C协议。
 */

#include "i2c_mcu.h"
#include "i2c_master.h"
#include "driver/i2c.h"
#include "esp_log.h"
#include <string.h>
#include "parameter.h"


static const char *TAG = "I2C_MCU";

#define I2C_MASTER_TIMEOUT_MS       1000    // I2C通信超时时间，单位毫秒
#define MCU_SLAVE_ADDR              0x33    // MCU从机地址，7位地址

// 静态变量，供内部使用
static float s_temp_disp = 25.0f;
static int s_fault_code = 0;
static int s_roomcard_detect = -1;  // 房卡检测状态：1=在位，0=不在位，-1=未初始化
static int s_last_roomcard_status = -1;  // 上次房卡状态，用于检测状态变化
static float s_last_valid_temp = 25.0f;  // 上次有效的温度值，用于防抖判断
static int s_temp_change_count = 2;       // 温度变化计数器，用于3次连续判断，初始值设置为2，第一次启动减少等待时间
static float s_pending_temp = 25.0f;      // 待确认的温度值
//static uint8_t s_beep_onoff = 0;


/**
 * @brief 增强的MCU I2C通信初始化
 * @details 使用渐进式初始化策略，包含MCU上电稳定时间、通信验证和错误恢复机制
 * @return esp_err_t 成功返回ESP_OK，失败返回ESP_FAIL
 */
esp_err_t i2c_mcu_init(void) {
    uint8_t write_data[6] = {0x04, 0x0A, 0x0B, 0x00, 0x00, 0x00};  // 初始化数据包
    uint8_t read_data[6] = {0};  // 用于存储读取的数据
    esp_err_t ret;
    int retry = 0;
    const int max_retries = 5;  // 增加重试次数
    
    ESP_LOGI(TAG, "开始MCU I2C通信初始化...");
    
    // MCU上电稳定时间：等待MCU完全启动并稳定
    ESP_LOGI(TAG, "等待MCU上电稳定...");
    vTaskDelay(pdMS_TO_TICKS(500));  // 增加到500ms，确保MCU稳定
    
    while (retry < max_retries) {
        ESP_LOGI(TAG, "MCU初始化尝试 %d/%d", retry + 1, max_retries);
        
        // 渐进式延时：每次重试前增加延时
        if (retry > 0) {
            uint32_t delay_ms = 200 + retry * 100;  // 200ms, 300ms, 400ms...
            ESP_LOGI(TAG, "重试前延时 %lu ms，等待MCU稳定", (unsigned long)delay_ms);
            vTaskDelay(pdMS_TO_TICKS(delay_ms));
        }
        
        // 尝试写入初始化命令
        ret = i2c_mcu_write(write_data);
        if (ret == ESP_OK) {
            // 写入成功，等待MCU处理
            vTaskDelay(pdMS_TO_TICKS(100));  // 增加处理时间
            
            // 尝试读取响应
            ret = i2c_mcu_read(read_data);
            if (ret == ESP_OK) {
                // 验证响应数据
                if (read_data[0] == 0x04 && read_data[1] == 0x0A && read_data[2] == 0x0B) {
                    ESP_LOGI(TAG, "MCU初始化成功 (重试%d次)", retry);
                    ESP_LOGI(TAG, "MCU响应数据: %02X %02X %02X %02X %02X %02X", 
                             read_data[0], read_data[1], read_data[2], 
                             read_data[3], read_data[4], read_data[5]);
                return ESP_OK;
                } else {
                    ESP_LOGW(TAG, "MCU响应数据不匹配: %02X %02X %02X (期望: 04 0A 0B)", 
                             read_data[0], read_data[1], read_data[2]);
                }
            } else {
                ESP_LOGW(TAG, "MCU读取失败: %s", esp_err_to_name(ret));
            }
        } else {
            ESP_LOGW(TAG, "MCU写入失败: %s", esp_err_to_name(ret));
        }
        
        retry++;
        
        // 在重试过程中，每两次失败后尝试短暂的恢复操作
        if (retry % 2 == 0 && retry < max_retries) {
            ESP_LOGW(TAG, "连续失败，执行短暂恢复操作");
            vTaskDelay(pdMS_TO_TICKS(300));
        }
    }
    
    ESP_LOGE(TAG, "MCU初始化最终失败，已重试%d次", max_retries);
    ESP_LOGE(TAG, "可能原因：1) MCU未上电 2) I2C总线异常 3) MCU固件问题");
    return ESP_FAIL;
}

/**
 * @brief 增强的I2C写入函数，包含智能重试和错误恢复
 * @details 在通信失败时自动重试，并在连续失败时尝试总线恢复
 * @param data 指向6字节数据的指针
 * @return esp_err_t 成功返回ESP_OK，失败返回错误码
 */
esp_err_t i2c_mcu_write(const uint8_t *data) {
    if (!data) return ESP_ERR_INVALID_ARG;
    
    esp_err_t ret;
    int retry_count = 0;
    const int max_retries = 3;
    const int recovery_threshold = 2; // 连续失败2次后尝试恢复
    
    while (retry_count < max_retries) {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (MCU_SLAVE_ADDR << 1) | I2C_MASTER_WRITE, true);
        i2c_master_write(cmd, data, 6, true);
    i2c_master_stop(cmd);
        
        ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
        
    if (ret == ESP_OK) {
            if (retry_count > 0) {
                ESP_LOGI(TAG, "写入MCU成功(重试%d次): %02X %02X %02X %02X %02X %02X", 
                         retry_count, data[0], data[1], data[2], data[3], data[4], data[5]);
            } else {
                    // ESP_LOGD(TAG, "写入MCU成功: %02X %02X %02X %02X %02X %02X",
    //          data[0], data[1], data[2], data[3], data[4], data[5]);
            }
            return ESP_OK;
        }
        
        retry_count++;
        ESP_LOGW(TAG, "写入MCU失败(第%d次): 错误码=%d, 数据=%02X %02X %02X %02X %02X %02X", 
                 retry_count, ret, data[0], data[1], data[2], data[3], data[4], data[5]);
        
        // 在达到恢复阈值时尝试总线恢复
        if (retry_count == recovery_threshold) {
            ESP_LOGW(TAG, "连续失败%d次，尝试I2C总线恢复", recovery_threshold);
            extern esp_err_t i2c_master_init(void); // 重新初始化I2C
            i2c_master_init();
            vTaskDelay(pdMS_TO_TICKS(50));
    } else {
            // 渐进式延时：第一次失败延时较短，后续逐渐增加
            uint32_t delay_ms = 50 + (retry_count - 1) * 50;
            vTaskDelay(pdMS_TO_TICKS(delay_ms));
        }
    }
    
    ESP_LOGE(TAG, "写入MCU最终失败: 错误码=%d, 已重试%d次", ret, max_retries);
    return ret;
}

/**
 * @brief 增强的I2C读取函数，包含智能重试和多种读取模式
 * @details 优先尝试读取7字节（丢弃第1字节），失败时尝试6字节模式，包含重试机制
 * @param data 指向存储读取数据的6字节数组的指针
 * @return esp_err_t 成功返回ESP_OK，失败返回错误码
 */
esp_err_t i2c_mcu_read(uint8_t *data) {
    if (!data) return ESP_ERR_INVALID_ARG;
    
    esp_err_t ret;
    int retry_count = 0;
    const int max_retries = 3;
    uint8_t temp_buf[7] = {0};
    
    while (retry_count < max_retries) {
        // 方法1：尝试读取7字节，丢弃第1字节
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (MCU_SLAVE_ADDR << 1) | I2C_MASTER_READ, true);
        i2c_master_read(cmd, temp_buf, 7, I2C_MASTER_LAST_NACK);
    i2c_master_stop(cmd);
        ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
        
    if (ret == ESP_OK) {
            // 7字节读取成功，丢弃第1字节，保留后6字节
        memcpy(data, &temp_buf[1], 6);
            if (retry_count > 0) {
                ESP_LOGI(TAG, "读取MCU成功(7字节，重试%d次): %02X %02X %02X %02X %02X %02X", 
                         retry_count, data[0], data[1], data[2], data[3], data[4], data[5]);
            } else {
                // ESP_LOGD(TAG, "读取MCU成功(7字节): %02X %02X %02X %02X %02X %02X", 
                //          data[0], data[1], data[2], data[3], data[4], data[5]);
            }
        return ESP_OK;
        }
        
        ESP_LOGW(TAG, "7字节读取失败(第%d次): %s", retry_count + 1, esp_err_to_name(ret));
        
        // 方法2：尝试直接读取6字节
        memset(data, 0, 6);  // 清空缓冲区
        i2c_cmd_handle_t cmd2 = i2c_cmd_link_create();
        i2c_master_start(cmd2);
        i2c_master_write_byte(cmd2, (MCU_SLAVE_ADDR << 1) | I2C_MASTER_READ, true);
        i2c_master_read(cmd2, data, 6, I2C_MASTER_LAST_NACK);
        i2c_master_stop(cmd2);
        esp_err_t ret2 = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd2, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd2);
        
        if (ret2 == ESP_OK) {
            if (retry_count > 0) {
                ESP_LOGI(TAG, "读取MCU成功(6字节，重试%d次): %02X %02X %02X %02X %02X %02X", 
                         retry_count, data[0], data[1], data[2], data[3], data[4], data[5]);
            } else {
                // ESP_LOGD(TAG, "读取MCU成功(6字节): %02X %02X %02X %02X %02X %02X", 
                //          data[0], data[1], data[2], data[3], data[4], data[5]);
            }
            return ESP_OK;
        }
        
        ESP_LOGW(TAG, "6字节读取也失败(第%d次): %s", retry_count + 1, esp_err_to_name(ret2));
        
        retry_count++;
        
        // 渐进式延时
        if (retry_count < max_retries) {
            uint32_t delay_ms = 50 + retry_count * 30;  // 50ms, 80ms, 110ms
            vTaskDelay(pdMS_TO_TICKS(delay_ms));
        }
    }
    
    ESP_LOGE(TAG, "读取MCU最终失败，已重试%d次", max_retries);
    return ESP_FAIL;  // 返回通用失败码
}

/**
 * @brief 写后读操作（先写6字节，再读6字节）
 * @details 本函数封装了先写入数据再读取数据的操作，简化外部调用流程。
 * @param write_data 指向写入数据的6字节数组的指针
 * @param read_data 指向存储读取数据的6字节数组的指针
 * @return esp_err_t 成功返回ESP_OK，失败返回错误码
 */
esp_err_t i2c_mcu_write_read(uint8_t *write_data, uint8_t *read_data) {
    if (!write_data || !read_data) return ESP_ERR_INVALID_ARG;
    esp_err_t ret = i2c_mcu_write(write_data);
    if (ret != ESP_OK) return ret;
    vTaskDelay(pdMS_TO_TICKS(10));  // 短暂延时确保MCU处理完成
    return i2c_mcu_read(read_data);
}

/**
 * @brief  驱动MCU蜂鸣器响一声
 * @note   通过I2C向MCU写入固定数据包 {0x02, 0x0A, 0x07, 0x28, 0x32, 0x00}
 * @note   02H寄存器，PA端口，07：对应MM32的PA8，28：4KHz，32：50%占空比
 * @retval ESP_OK 成功，其他失败
 */
int i2c_mcu_beep(void)
{
    //s_beep_onoff = 0;  // 先将状态恢复为0，避免重复触发
    uint8_t beep_cmd[6] = {0x02, 0x0A, 0x08, 0x32, 0x02, 0x00};
    return i2c_mcu_write(beep_cmd);
}

/**
 * @brief 获取NTC1温度及故障状态
 * @param[out] fault 非NULL时，返回NTC1故障状态（1=故障，0=正常）
 * @return float 温度值（摄氏度），故障时返回-1000.0f
 */
float i2c_mcu_get_ntc1_temp(int *fault)
{
    uint8_t write_data[6] = {0x04, 0x0A, 0x0B, 0x00, 0x00, 0x00};
    uint8_t read_data[6] = {0};
    int retry = 0;
    if (fault) *fault = 0;
    while (retry < 3) {
        if (i2c_mcu_write(write_data) == ESP_OK) {
            vTaskDelay(pdMS_TO_TICKS(50));
            if (i2c_mcu_read(read_data) == ESP_OK) {
                if (read_data[0] == write_data[0] && read_data[1] == write_data[1] && read_data[2] == write_data[2]) {
                    uint16_t adc_value = ((read_data[3] & 0x0F) << 8) | read_data[4];
                    // ESP_LOGI(TAG, "NTC1温度解析 - 原始数据: %02X %02X, ADC: 0x%04X (%d)", 
                    //          read_data[3], read_data[4], adc_value, adc_value);
                    
                    if (adc_value == 0x0FFF || adc_value == 0x0000) {
                        if (fault) *fault = 1;
                        return -1000.0f;
                    }
                    int temp_x1 = GetTemp(adc_value, 1);
                    ESP_LOGI(TAG, "NTC2温度计算 - temp_x1: %d (%.1f°C)", temp_x1, temp_x1/10.0f);
                    
                    // 修正温度范围检查：-200°C到200°C（即-2000到2000）
                    if (temp_x1 > 1000 || temp_x1 < -400) {
                        // ESP_LOGE(TAG, "NTC2温度超出范围 - temp_x1: %d, 应在-2000到2000之间", temp_x1);
                        if (fault) *fault = 1;
                        return -1000.0f;
                    }

                    if(temp_x1 > -400 && temp_x1 <= 0)
                    {
                        temp_x1 = 0;
                    }

                    if(temp_x1 < 1000 && temp_x1 >= 700)
                    {
                        temp_x1 = 700;
                    }
                    return temp_x1 / 10.0f;
                }
            }
        }
        retry++;
    }
    if (fault) *fault = 1;
    return -1000.0f;
}

/**
 * @brief 获取NTC2温度及故障状态
 * @param[out] fault 非NULL时，返回NTC2故障状态（1=故障，0=正常）
 * @return float 温度值（摄氏度），故障时返回-1000.0f
 */
float i2c_mcu_get_ntc2_temp(int *fault)
{
    uint8_t write_data[6] = {0x04, 0x0A, 0x0C, 0x00, 0x00, 0x00}; // NTC2命令
    uint8_t read_data[6] = {0};
    int retry = 0;
    if (fault) *fault = 0;
    while (retry < 3) {
        if (i2c_mcu_write(write_data) == ESP_OK) {
            vTaskDelay(pdMS_TO_TICKS(50));
            if (i2c_mcu_read(read_data) == ESP_OK) {
                if (read_data[0] == write_data[0] && read_data[1] == write_data[1] && read_data[2] == write_data[2]) {
                    uint16_t adc_value = ((read_data[3] & 0x0F) << 8) | read_data[4];
                    // ESP_LOGI(TAG, "NTC2温度解析 - 原始数据: %02X %02X, ADC: 0x%04X (%d)", 
                    //          read_data[3], read_data[4], adc_value, adc_value);
                    
                    if (adc_value == 0x0FFF || adc_value == 0x0000) {
                        if (fault) *fault = 1;
                        return -1000.0f;
                    }
                    int temp_x1 = GetTemp(adc_value, 2);
                    ESP_LOGI(TAG, "NTC2温度计算 - temp_x1: %d (%.1f°C)", temp_x1, temp_x1/10.0f);
                    
                    // 修正温度范围检查：-200°C到200°C（即-2000到2000）
                    if (temp_x1 > 1000 || temp_x1 < -400) {
                        // ESP_LOGE(TAG, "NTC2温度超出范围 - temp_x1: %d, 应在-2000到2000之间", temp_x1);
                        if (fault) *fault = 1;
                        return -1000.0f;
                    }

                    if(temp_x1 > -400 && temp_x1 <= 0)
                    {
                        temp_x1 = 0;
                    }

                    if(temp_x1 < 1000 && temp_x1 >= 700)
                    {
                        temp_x1 = 700;
                    }
                    return temp_x1 / 10.0f;
                }
            }
        }
        retry++;
    }
    if (fault) *fault = 1;
    return -1000.0f;
}

/**
 * @brief NTC温度换算核心函数
 * @param adc_value 12位ADC原始值
 * @return float 实际温度（摄氏度）
 */
int GetTemp(uint16_t adc_value, uint8_t ntc_num)
{
    float T2 = (273.15f + 25.0f);
    float Bx = 4250.0f;
    float Ka = 273.15f;
    float r_ntc;
    double temp_buff;
    int16_t ret_temp;

    if(ntc_num == 1)
    {
        Bx = 4250.0f;
    }
    else if(ntc_num == 2)
    {
        Bx = 3977.0f;
    }

    r_ntc = 0x0fff - adc_value;
    r_ntc = adc_value / r_ntc;
    r_ntc *= 100;

    temp_buff = r_ntc / 100;
    temp_buff = log(temp_buff);
    temp_buff /= Bx;
    temp_buff = (1 / T2) + temp_buff;
    temp_buff = 1 / temp_buff;
    temp_buff -= Ka;

    ret_temp = (int)(temp_buff * 10);

    return ret_temp;
}

/**
 * @brief 获取用于显示的温度值和错误码，支持校准、补偿、单位转换和范围限制
 *        采集结果存入全局变量f_temp_disp和f_fault_code，LVGL等模块直接读取即可
 * @param[out] temp_disp 返回显示温度（float*，保留1位小数，可为NULL）
 * @param[out] fault_code 返回错误码（int*，0=无故障，1=ntc1故障，2=ntc2故障，可为NULL）
 * @return 0=正常，1=ntc1故障，2=ntc2故障
 */
int temp_display(float *temp_disp, int *fault_code) {
    float tcomp = (-3.5f); // 补偿温度，如需补偿请直接修改此处
    float tntc = 0.0f;
    int fault = 0;
    int ex_input = GetExternal_Input(); // 读取外部传感器选择参数

    // 选择ntc1或ntc2采集温度
    if (ex_input == 1) {
        tntc = i2c_mcu_get_ntc2_temp(&fault);
        if (fault) {
            s_temp_disp = 999.9f;
            s_fault_code = 2;
            // 故障时重置防抖状态
            s_last_valid_temp = 25.0f;  // 重置为默认值
            s_temp_change_count = 2;     // 重置计数器
            s_pending_temp = 25.0f;      // 重置待确认温度
            // 添加故障日志打印
            ESP_LOGE(TAG, "温度采集故障 - 传感器: NTC2, 错误码: %d, 显示温度: %.1f", 
                     s_fault_code, s_temp_disp);
            if (temp_disp) *temp_disp = s_temp_disp;
            if (fault_code) *fault_code = s_fault_code;
            return 2;
        }
    } else {
        tntc = i2c_mcu_get_ntc1_temp(&fault);
        if (fault) {
            s_temp_disp = 999.9f;
            s_fault_code = 1;
            // 故障时重置防抖状态
            s_last_valid_temp = 25.0f;  // 重置为默认值
            s_temp_change_count = 2;     // 重置计数器
            s_pending_temp = 25.0f;      // 重置待确认温度
            // 添加故障日志打印
            ESP_LOGE(TAG, "温度采集故障 - 传感器: NTC1, 错误码: %d, 显示温度: %.1f", 
                     s_fault_code, s_temp_disp);
            if (temp_disp) *temp_disp = s_temp_disp;
            if (fault_code) *fault_code = s_fault_code;
            return 1;
        }
    }

    // 获取校准温度（始终按摄氏度处理）
    uint16_t unit = Gettemperature_unit(); // 获取温度单位参数
    float tcal;
    if (unit == 1) {
        tcal = GetTemp_calibration() / 2.0f;
    } else {
        tcal = GetTemp_calibration();
    }

    if (ex_input != 1)
    {
        tcomp = (-3.7f);
    }
    else
    {
        tcomp = (0.0f);
    }
    float td = tntc + tcal + tcomp;     // 公式：Td = Tntc(摄氏度) + Tcal(摄氏度) + Tcomp(摄氏度)

    // 限定摄氏度显示范围
    if (td < 0.0f) td = 0.0f;
    if (td > 70.0f) td = 70.0f;

    // 保留1位小数
    td = ((int)(td * 10 + 0.5f)) / 10.0f;

    // 温度防抖处理：3次连续判断机制，设定±0.2°C的变动阈值
    float temp_diff = td - s_last_valid_temp;
    if (temp_diff < 0) temp_diff = -temp_diff;  // 取绝对值
    
    if (temp_diff <= 0.2f) {
        // 温度变化小于等于±0.2°C，重置计数器并保持原值
        if (s_temp_change_count > 0) {
            ESP_LOGD(TAG, "温度防抖：新温度%.1f°C，差值%.1f°C ≤ 0.2°C，重置计数器(%d→0)，保持原值%.1f°C", 
                     td, temp_diff, s_temp_change_count, s_temp_disp);
        }
        s_temp_change_count = 0;  // 重置计数器
        s_pending_temp = 25.0f;   // 重置待确认温度
    } else {
        // 温度变化超过±0.2°C，开始或继续计数
        s_temp_change_count++;
        s_pending_temp = td;  // 记录待确认的温度值
        
        ESP_LOGD(TAG, "温度变化检测：新温度%.1f°C，差值%.1f°C > 0.2°C，计数器: %d/3", 
                 td, temp_diff, s_temp_change_count);
        
        if (s_temp_change_count >= 3) {
            // 连续3次温度变化超过阈值，确认更新
            s_last_valid_temp = s_pending_temp;  // 更新有效温度值
            s_temp_disp = s_pending_temp;        // 更新显示温度
            s_temp_change_count = 0;             // 重置计数器
            s_pending_temp = 25.0f;              // 重置待确认温度
            
            // ESP_LOGI(TAG, "温度更新确认：连续3次变化超过0.2°C，更新显示温度为%.1f°C", s_temp_disp);
        }
    }
    
    s_fault_code = 0;

    // 添加详细日志打印用于调试分析
    // ESP_LOGI(TAG, "温度采集成功 - 传感器: %s, 原始温度: %.1f°C, 校准值: %.1f°C, 最终摄氏度: %.1f°C, 错误码: %d", 
    //          (ex_input == 1) ? "NTC2" : "NTC1",
    //          tntc,
    //          tcal,
    //          s_temp_disp,
    //          s_fault_code);

    if (temp_disp) *temp_disp = s_temp_disp;
    if (fault_code) *fault_code = s_fault_code;
    return 0;
}

// 获取温度显示值（根据当前温度单位进行转换）
float get_temp_disp(void) {
    uint16_t unit = Gettemperature_unit(); // 获取当前温度单位设置
    float display_temp = s_temp_disp; // s_temp_disp存储的是摄氏度值

    /*puxin 20250718*/
    /*错误直接输出错误代码*/
    if(s_temp_disp == 999.9f)
    return s_temp_disp;
    
    if (unit == 1) {
        // 华氏度模式：将摄氏度转换为华氏度
        display_temp = s_temp_disp * 9.0f / 5.0f + 32.0f;
        
        // 限定华氏度显示范围
        if (display_temp < 32.0f) display_temp = 32.0f;
        if (display_temp > 158.0f) display_temp = 158.0f;
    } else {
        // 摄氏度模式：直接使用原值（已在temp_display中限制过范围）
        display_temp = s_temp_disp;
    }
    
    // 保留1位小数
    display_temp = ((int)(display_temp * 10 + 0.5f)) / 10.0f;
    
    return display_temp;
}

// 获取温度故障码（静态变量s_fault_code的getter）0:无故障，1:ntc1故障，2:ntc2故障
int get_fault_code(void) {
    return s_fault_code;
}

// 获取摄氏度温度值（静态变量s_temp_disp的getter，始终返回摄氏度）
float get_celsius_temp(void) {
    return s_temp_disp;
}

/**
 * @brief 房卡检测函数，通过NTC2通道的ADC原始值判断房卡在位状态
 * @details 通过获取NTC2通道的原始ADC值来判断房卡状态：
 *          - ADC > 0x03FF (1023)：房卡不在位（返回0）
 *          - ADC < 100：房卡在位（返回1）
 *          - 其他情况：保持上次状态
 * @return int 房卡状态：1=在位，0=不在位，-1=通信失败
 */
 int check_roomcard(void)
 {
     uint8_t write_data[6] = {0x04, 0x0A, 0x0C, 0x00, 0x00, 0x00}; // NTC2命令
     uint8_t read_data[6] = {0};
     int retry = 0;
     
     while (retry < 3) {
         if (i2c_mcu_write(write_data) == ESP_OK) {
             vTaskDelay(pdMS_TO_TICKS(100));
             if (i2c_mcu_read(read_data) == ESP_OK) {
                 if (read_data[0] == write_data[0] && read_data[1] == write_data[1] && read_data[2] == write_data[2]) {
                     uint16_t adc_value = ((read_data[3] & 0x0F) << 8) | read_data[4];
                     int new_status = s_roomcard_detect;  // 默认保持当前状态
                     
                     // 判断房卡状态
                     if (adc_value > 0x03FF) {
                         // ADC > 1023，房卡不在位
                         new_status = 0;
                     } else if (adc_value < 100) {
                         // ADC < 100，房卡在位
                         new_status = 1;
                     }
                     // 其他情况保持上次状态
                     
                     // 检查状态是否发生变化或首次检测
                     if (new_status != s_last_roomcard_status || s_roomcard_detect == -1) {
                         ESP_LOGI(TAG, "房卡检测 - 原始数据: %02X %02X, ADC: 0x%04X (%d)", 
                                  read_data[3], read_data[4], adc_value, adc_value);
                         
                         if (new_status == 0) {
                             ESP_LOGI(TAG, "房卡检测结果：不在位 (ADC: %d > 1023)", adc_value);
                         } else if (new_status == 1) {
                             ESP_LOGI(TAG, "房卡检测结果：在位 (ADC: %d < 100)", adc_value);
                         } else {
                             ESP_LOGW(TAG, "房卡检测结果：中间状态 (ADC: %d)，保持上次状态: %d", 
                                     adc_value, s_roomcard_detect);
                         }

                        //  if((new_status != s_last_roomcard_status) && (s_roomcard_detect != -1))
                        //  {
                        //     if(new_status == 0)
                        //     {
                        //         GetSetPoint();
                        //     }
                        //  }
                         
                         // 更新状态
                         s_roomcard_detect = new_status;
                         s_last_roomcard_status = new_status;
                     }
                     
                     return s_roomcard_detect;
                 }
             }
         }
         retry++;
     }
     
     ESP_LOGE(TAG, "房卡检测失败：通信错误");
     return -1;  // 通信失败
 }
 
 /**
  * @brief 获取房卡检测状态
  * @return int 房卡状态：1=在位，0=不在位，0xFF=无房卡功能
  */
 int get_roomcard_detect(void)
 {
     // 检查外部输入参数，只有当GetExternal_Input()=2时才进行房卡检测
     int ex_input = GetExternal_Input();
     if (ex_input != 2) {
         //ESP_LOGW(TAG, "房卡检测跳过：外部输入参数=%d，需要=2", ex_input);
         return 0xFF;  // 返回0xFF表示外部输入参数不匹配
     }else{
        return s_roomcard_detect;
     }
 }


/**
 * @brief 设置背光亮度（百分比）
 * @param led_pwm 背光亮度百分比（0~100，十进制）
 * @return ESP_OK成功，其他失败
 */
int i2c_mcu_set_backlight(uint8_t led_pwm)
{
    if (led_pwm > 100) led_pwm = 100; // 限制最大值
    uint8_t cmd[6] = {0x02, 0x0A, 0x06, 0x0F, led_pwm, 0x00};  // 0x02寄存器，PA端口，0x06：对应MM32的PA6，0x0F：1.5KHz
    return i2c_mcu_write(cmd);
}

/**
 * @brief WiFi使能控制，供上层调用
 * @param en 1=使能WiFi（高电平），0=去使能（低电平）
 * @return ESP_OK成功，其他失败
 */
int i2c_mcu_wifi_en(uint8_t en)
{
    uint8_t cmd[6] = {0x01, 0x0A, 0x03, (en ? 0x01 : 0x00), 0x00, 0x00};  // 0x01寄存器，PA端口，0x03：对应MM32的PA3，0x01：使能WiFi，0x00：去使能WiFi
    return i2c_mcu_write(cmd);
}

/**
 * @brief 继电器K5/VC1控制，供上层调用
 * @param on 1=接通继电器，0=断开继电器
 * @return ESP_OK成功，其他失败
 */
int i2c_mcu_relay_K5(uint8_t on)
{
    uint8_t cmd[6] = {0x01, 0x0A, 0x02, (on ? 0x01 : 0x00), 0x00, 0x00};
    return i2c_mcu_write(cmd);
}

/**
 * @brief 继电器K4/VC2控制，供上层调用
 * @param on 1=接通继电器，0=断开继电器
 * @return ESP_OK成功，其他失败
 */
int i2c_mcu_relay_K4(uint8_t on)
{
    uint8_t cmd[6] = {0x01, 0x0A, 0x0F, (on ? 0x01 : 0x00), 0x00, 0x00};
    return i2c_mcu_write(cmd);
}

/**
 * @brief 继电器K3控制，供上层调用
 * @param on 1=接通继电器，0=断开继电器
 * @return ESP_OK成功，其他失败
 */
int i2c_mcu_relay_K3(uint8_t on)
{
    uint8_t cmd[6] = {0x01, 0x0A, 0x0A, (on ? 0x01 : 0x00), 0x00, 0x00};
    return i2c_mcu_write(cmd);
}

/**
 * @brief 风阀百分比控制，供上层调用
 * @param pid_ao1 百分比（0~100，十进制）
 * @return ESP_OK成功，其他失败
 * FC-7RS-485该功能改变为继电器
 */
int i2c_mcu_ao1(uint8_t pid_ao1)
{
    //if (pid_ao1 > 100) pid_ao1 = 100;
    uint8_t cmd[6] = {0x01, 0x0A, 0x07, (pid_ao1 > 0 ? 0x01 : 0x00), 0x00, 0x00};  // 0x02寄存器，PA端口，0x07：MM32的PA7，0x0F：1.5KHz,pid_ao1为输出百分比
    return i2c_mcu_write(cmd);
}

/**
 * @brief 风阀百分比控制，供上层调用
 * @param pid_ao2 百分比（0~100，十进制）
 * @return ESP_OK成功，其他失败
 * FC-7RS-485该功能改变为继电器
 */
int i2c_mcu_ao2(uint8_t pid_ao2)
{
    //if (pid_ao2 > 100) pid_ao2 = 100;
    uint8_t cmd[6] = {0x01, 0x0A, 0x09, (pid_ao2 > 0 ? 0x01 : 0x00), 0x00, 0x00};  // 0x02寄存器，PA端口，0x09：MM32的PA9，0x0F：1.5KHz,pid_ao2为输出百分比
    return i2c_mcu_write(cmd);
}
/**
 * @brief 风阀百分比控制，供上层调用
 * @param pid_ao3 百分比（0~100，十进制）
 * @return ESP_OK成功，其他失败
 */
int i2c_mcu_ao3(uint8_t pid_ao3)
{
    // 获取管路选项
    uint16_t pipe_option = GetPipe_option();
    uint8_t k3_state = 0; // 默认K3继电器关闭
    
    // 根据管路选项和pid_ao3值决定K3继电器的状态
    if (pipe_option == 0) {
        // 单管路模式：K3继电器始终关闭
        k3_state = 0;
        ESP_LOGI(TAG, "AO3 - 单管路模式，K3继电器关闭");
    } else if (pipe_option == 1) {
        // 双管路模式：根据pid_ao3值决定K3继电器状态
        k3_state = (pid_ao3 > 0) ? 1 : 0;
        ESP_LOGI(TAG, "AO3 - 双管路模式，K3继电器状态: %d (AO3: %d)", k3_state, pid_ao3);
    } else {
        // 未知管路选项，默认K3继电器关闭
        k3_state = 0;
        ESP_LOGW(TAG, "AO3 - 未知管路选项: %d，默认K3继电器关闭", pipe_option);
    }
    
    // 设置K3继电器
    // int ret = i2c_mcu_relay_K3(k3_state);
    // if (ret != ESP_OK) {
    //     ESP_LOGE(TAG, "AO3继电器K3控制失败: %d, 状态: %d", ret, k3_state);
    //     return ret;
    // }
    
    ESP_LOGI(TAG, "AO3设置完成 - 管路选项: %d, K3: %d, AO3: %d", pipe_option, k3_state, pid_ao3);
    
    // 然后调用AO2输出，传入pid_ao3的值
    return i2c_mcu_ao2(pid_ao3);
}



/**
 * @brief 设置蜂鸣器开关状态
 * @param onoff 0=关闭蜂鸣器，1=开启蜂鸣器
 */
// void set_beep_onoff(uint8_t onoff) {
//     s_beep_onoff = onoff ? 1 : 0;  // 确保值只能是0或1
    
//     // 如果设置为开启蜂鸣器，触发system_control事件
//     if (s_beep_onoff == 1) {
//         // 这里可以添加对system_control的事件触发
//         // 但为了保持向后兼容，暂时保持原有接口不变
//     }
// }

// uint8_t get_beep_onoff(void) {
//     return s_beep_onoff;
// }