/******************************************************************************
 * @file      protocol_mqtt_bcu.c
 * @brief     protocol_mqtt_bcu
 * @version   V1.0
 * @author    Gary Wangk
 * @copyright
 ******************************************************************************/

#include "protocol_mqtt_bcu.h"
#include "iso_check.h"
#include "soc_calculate.h"
#include "sop_calculate.h"
#include "version_manager.h"
#include "dido_manager.h"
#include "fault_manager.h"
#include "flash_manager.h"
#include "comm_manager.h"
#include "hv_adc_manager.h"
#include "eeprom_manager.h"
#include "signal_manager.h"
#include "statistic_manager.h"
#include "bmu_manager.h"
#include "protocol_comm.h"
#include "drv_qfc41d.h"

extern char deviceSN[17];

uint32_t bms_get_baseInfo(uint16_t input)
{
    uint32_t tmp;
    uint16_t bms_stu = 0;

    if(bms_get_run_status() == kRunStatus_Init)
    {
        bms_stu = 0;
    }
    else if(bms_get_run_status() == kRunStatus_Standby)
    {
        bms_stu |= 0x1;
    }
    else if(bms_get_run_status() == kRunStatus_Chg)
    {
        bms_stu |= 0x2;
    }
    else if(bms_get_run_status() == kRunStatus_Dis)
    {
        bms_stu |= 0x3;
    }
    if(bms_get_signal(kSignalIdx_ForbidChg) == kSignalStatus_High)
    {
        bms_stu |= 0x10;
    }
    if(bms_get_signal(kSignalIdx_ForbidDis) == kSignalStatus_High)
    {
        bms_stu |= 0x20;
    }

    switch(input)
    {
    case 1:
        tmp = bms_get_statistic_data(kStatisticData_TotalVolt);
        return tmp;
    case 2:
        tmp = bms_get_show_current();
        return tmp;
    case 3:
        tmp = bms_get_soc() / 100;
        return tmp;
    case 4:
        tmp = bms_get_soh() / 100;
        return tmp;
    case 5:
        tmp = bms_get_soc() / 100;
        return tmp;
    case 6:
        tmp = get_eeprom_data(kEep_RatedTotalVolt,kEepromDataType_Full);
        return tmp;
    case 7:
        tmp = get_eeprom_data(kEep_RatedCapacity,kEepromDataType_Full);
        return tmp;
    case 8:
        tmp = (uint32_t)bms_get_soc()*get_eeprom_data(kEep_RatedCapacity, kEepromDataType_Full)/10000;
        return tmp;
    case 9:
        tmp = get_eeprom_data(kEep_RatedCapacity, kEepromDataType_Full)*get_eeprom_data(kEep_RatedTotalVolt, kEepromDataType_Full)/10000;
        return tmp;
    case 10:
        tmp = (uint32_t)bms_get_soc() * get_eeprom_data(kEep_RatedCapacity, kEepromDataType_Full)/10000*get_eeprom_data(kEep_RatedTotalVolt, kEepromDataType_Full)/10000;
        return tmp;
    case 11:
        tmp = bms_get_bmu_num();   //电池总数
        return tmp;
    case 12:
        tmp = bms_get_bmu_online_num();
        return tmp;
    case 13:
        tmp = bms_get_cell_num();  //电芯总数
        return tmp;
    case 14:
        tmp = bms_get_statistic_data(kStatisticData_OnlineCellNum);
        return tmp;
    case 15:
        tmp = bms_get_temp_num();  //温感总数
        return tmp;
    case 16:
        tmp = bms_get_statistic_data(kStatisticData_OnlineTempNum);
        return tmp;
    case 17:
        tmp = bms_get_sop_data(kSopData_DisCur);
        return tmp;
    case 18:
        tmp = (uint32_t)bms_get_sop_data(kSopData_DisCur)*get_eeprom_data(kEep_RatedTotalVolt, kEepromDataType_Full)/10000;
        return tmp;
    case 19:
        tmp = bms_get_sop_data(kSopData_ChgCur);
        return tmp;
    case 20:
        tmp = (uint32_t)bms_get_sop_data(kSopData_ChgCur)*get_eeprom_data(kEep_RatedTotalVolt, kEepromDataType_Full)/10000;
        return tmp;
    case 21:
        tmp = bms_get_iso_data(kIsoData_PosRes);
        return tmp;
    case 22:
        tmp = bms_get_iso_data(kIsoData_NegRes);
        return tmp;
    case 23:
        tmp = bms_get_statistic_data(kStatisticData_AvgVolt);
        return tmp;
    case 24:
        tmp = bms_get_statistic_data(kStatisticData_VoltDiff);
        return tmp;
    case 25:
        tmp = bms_get_statistic_data(kStatisticData_MaxVolt);
        return tmp;
    case 26:
        tmp = bms_get_statistic_data(kStatisticData_MaxVoltBmuIdx) + 1;
        return tmp;
    case 27:
        tmp = bms_get_statistic_data(kStatisticData_MaxVoltIdx) + 1;
        return tmp;
    case 28:
        tmp = bms_get_statistic_data(kStatisticData_MinVolt);
        return tmp;
    case 29:
        tmp = bms_get_statistic_data(kStatisticData_MinVoltBmuIdx) + 1;
        return tmp;
    case 30:
        tmp = bms_get_statistic_data(kStatisticData_MinVoltIdx) + 1;
        return tmp;
    case 31:
        tmp = bms_get_statistic_data(kStatisticData_AvgTemp);
        return tmp;
    case 32:
        tmp = bms_get_statistic_data(kStatisticData_TempDiff);
        return tmp;
    case 33:
        tmp = bms_get_statistic_data(kStatisticData_MaxTemp);
        return tmp;
    case 34:
        tmp = bms_get_statistic_data(kStatisticData_MaxTempBmuIdx) + 1;
        return tmp;
    case 35:
        tmp = bms_get_statistic_data(kStatisticData_MaxTempIdx) + 1;
        return tmp;
    case 36:
        tmp = bms_get_statistic_data(kStatisticData_MinTemp);
        return tmp;
    case 37:
        tmp = bms_get_statistic_data(kStatisticData_MinTempBmuIdx) + 1;
        return tmp;
    case 38:
        tmp = bms_get_statistic_data(kStatisticData_MinTempIdx) + 1;
        return tmp;
    case 39:
        tmp = (uint16_t)bms_get_cumulate_data(kCumulateData_DayChgCap);
        return tmp;
    case 40:
        tmp = (uint16_t)bms_get_cumulate_data(kCumulateData_DayChgEnergy);
        return tmp;
    case 41:
        tmp = (uint16_t)bms_get_cumulate_data(kCumulateData_DayDisCap);
        return tmp;
    case 42:
        tmp = (uint16_t)bms_get_cumulate_data(kCumulateData_DayDisEnergy);
        return tmp;
    case 43:
        tmp = (uint16_t)bms_get_cumulate_data(kCumulateData_DayChgTime);
        return tmp;
    case 44:
        tmp = (uint16_t)bms_get_cumulate_data(kCumulateData_DayDisTime);
        return tmp;
    case 45:
        tmp = bms_get_cumulate_data(kCumulateData_AccChgCap);
        return tmp;
    case 46:
        tmp = bms_get_cumulate_data(kCumulateData_AccChgEnergy);
        return tmp;
    case 47:
        tmp = bms_get_cumulate_data(kCumulateData_AccDisCap);
        return tmp;
    case 48:
        tmp = bms_get_cumulate_data(kCumulateData_AccDisEnergy);
        return tmp;
    case 49:
        tmp = bms_get_cumulate_data(kCumulateData_AccChgTime);
        return tmp;
    case 50:
        tmp = bms_get_cumulate_data(kCumulateData_AccDisTime);
        return tmp;
    case 51:
        tmp = bms_stu;
        return tmp;
		case 52:
        tmp = bms_get_do_status_by_type(kDoType_PreChg);
        return tmp;
		case 53:
        tmp = bms_get_do_status_by_type(kDoType_Dis);
        return tmp;
		case 54:
        tmp = bms_get_do_status_by_type(kDoType_Chg);
        return tmp;
		case 55:
        tmp = 1;
        return tmp;
    default:
        return 0;
    }
}

uint32_t bms_get_fault_level_1(uint16_t input)
{
    uint32_t tmp = 0;

    switch(input)
    {
    case 1:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 2))  //一级单体过压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 2:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 3))  //一级单体欠压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 3:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 4))  //一级单体过温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 4:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 5))  //一级单体低温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 5:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 6))  //一级单体压差
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 6:
        if (bms_get_run_status() == kRunStatus_Chg)
        {
            if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 8))  //一级充电电流过大
            {
                tmp = 1;
            }
            else
            {
                tmp = 0;
            }
        }
        return tmp;
    case 7:
        if (bms_get_run_status() == kRunStatus_Dis)
        {
            if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 8))  //一级放电电流过大
            {
                tmp = 1;
            }
            else
            {
                tmp = 0;
            }
        }
        return tmp;
    case 8:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 14))  //一级SOC过低
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 9:
        tmp = 0; //一级SOC差异过大
        return tmp;
    case 10:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 15))  //一级绝缘过低
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 11:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 0))  //一级总压过压--组端过压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 12:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_First), 1))  //一级总压欠压--组端欠压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    case 13:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(1, kFaultLevel_First), 12))  //1级极柱过温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 14:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 9))  //高压异常
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 15:
        tmp = get_eeprom_data(kEep_TempNum, kEepromDataType_Full);
        return tmp;
    case 16:
        tmp = bms_get_statistic_data(kStatisticData_OnlineTempNum);
				return tmp;
        break;
    default:
        return 0;
    }
}

uint32_t bms_get_fault_level_2(uint16_t input)
{
    uint32_t tmp = 0;

    switch(input)
    {
    case 1:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 2))  //2级单体过压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 2:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 3))  //2级单体欠压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 3:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 4))  //2级单体过温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 4:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 5))  //2级单体低温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 5:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 6))  //2级单体压差
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 6:
        if (bms_get_run_status() == kRunStatus_Chg)
        {
            if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 8))  //2级充电电流过大
            {
                tmp = 1;
            }
            else
            {
                tmp = 0;
            }
        }
        return tmp;
    case 7:
        if (bms_get_run_status() == kRunStatus_Dis)
        {
            if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 8))  //2级放电电流过大
            {
                tmp = 1;
            }
            else
            {
                tmp = 0;
            }
        }
        return tmp;
    case 8:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 14))  //2级SOC过低
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 9:
        tmp = 0; //一级SOC差异过大
        return tmp;
    case 10:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 15))  //2级绝缘过低
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 11:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 0))  //2级总压过压--组端过压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 12:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Second), 1))  //2级总压欠压--组端欠压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    case 13:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(1, kFaultLevel_Second), 12))  //2级极柱过温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 14:
        tmp = bms_get_statistic_data(kStatisticData_OnlineCellNum);
        return tmp;
    case 15:
        tmp = get_eeprom_data(kEep_TempNum, kEepromDataType_Full);
        return tmp;
    case 16:
        tmp = bms_get_statistic_data(kStatisticData_OnlineTempNum);
        break;
    default:
        return 0;
    }
}

uint32_t bms_get_fault_level_3(uint16_t input)
{
    uint32_t tmp = 0;

    switch(input)
    {
    case 1:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 2))  //3级单体过压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 2:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 3))  //3级单体欠压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 3:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 4))  //3级单体过温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 4:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 5))  //3级单体低温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 5:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 6))  //3级单体压差
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 6:
        if (bms_get_run_status() == kRunStatus_Chg)
        {
            if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 8))  //3级充电电流过大
            {
                tmp = 1;
            }
            else
            {
                tmp = 0;
            }
        }
        return tmp;
    case 7:
        if (bms_get_run_status() == kRunStatus_Dis)
        {
            if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 8))  //3级放电电流过大
            {
                tmp = 1;
            }
            else
            {
                tmp = 0;
            }
        }
        return tmp;
    case 8:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 14))  //3级SOC过低
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 9:
        tmp = 0; //一级SOC差异过大
        return tmp;
    case 10:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 15))  //3级绝缘过低
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 11:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 0))  //3级总压过压--组端过压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 12:  
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(0, kFaultLevel_Third), 1))  //3级总压欠压--组端欠压
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    case 13:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(1, kFaultLevel_Third), 12))  //3级极柱过温
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
        return tmp;
    case 14:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(1, kFaultLevel_Third), 0))  //继电器粘连
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    case 15:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(2, kFaultLevel_Third), 9))  //极限故障
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    case 16:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(1, kFaultLevel_Third), 1))  //预充故障
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    case 17:
        if (KIT_GET_BIT_32(bms_get_fault_single_bit(2, kFaultLevel_Third), 10))  //开路故障
        {
            tmp = 1;
        }
        else
        {
            tmp = 0;
        }
				return tmp;
    default:
        return 0;
    }
}

//把这个请按照数据模型填充完毕
const devPointMap bms_points[] = {
		{"BCU_1", 0, 55, bms_get_baseInfo}, // 设备在线
    {"BCU_2", 0, 0, bms_get_total_alarm}, // 总告警
    {"BCU_3", 0, 0, bms_get_total_fault}, // 总故障
    {"BCU_4", 0, 1, bms_get_fault_level_1}, // 单体过压告警一级
    {"BCU_5", 0, 2, bms_get_fault_level_1}, // 单体欠压告警一级
    {"BCU_6", 0, 3, bms_get_fault_level_1}, // 单体过温告警一级
    {"BCU_7", 0, 4, bms_get_fault_level_1}, // 单体低温告警一级
    {"BCU_8", 0, 5, bms_get_fault_level_1}, // 单体压差告警一级
    {"BCU_9", 0, 6, bms_get_fault_level_1}, // 充电过流告警一级
    {"BCU_10", 0, 7, bms_get_fault_level_1}, // 放电过流告警一级
    {"BCU_11", 0, 8, bms_get_fault_level_1}, // SOC过低告警一级
    {"BCU_12", 0, 9, bms_get_fault_level_1}, // SOC差异过大告警一级
    {"BCU_13", 0, 10, bms_get_fault_level_1}, // 绝缘过低告警一级

    {"BCU_14", 0, 1, bms_get_fault_level_2}, // 单体过压告警二级
    {"BCU_15", 0, 2, bms_get_fault_level_2}, // 单体欠压告警二级
    {"BCU_16", 0, 3, bms_get_fault_level_2}, // 单体过温告警二级
    {"BCU_17", 0, 4, bms_get_fault_level_2}, // 单体低温告警二级
    {"BCU_18", 0, 5, bms_get_fault_level_2}, // 单体压差告警二级
    {"BCU_19", 0, 6, bms_get_fault_level_2}, // 充电过流告警二级
    {"BCU_20", 0, 7, bms_get_fault_level_2}, // 放电过流告警二级
    {"BCU_21", 0, 8, bms_get_fault_level_2}, // SOC过低告警二级
    {"BCU_22", 0, 9, bms_get_fault_level_2}, // SOC差异过大告警二级
    {"BCU_23", 0, 10, bms_get_fault_level_2}, // 绝缘过低告警二级

    {"BCU_24", 0, 1, bms_get_fault_level_3}, // 单体过压告警三级
    {"BCU_25", 0, 2, bms_get_fault_level_3}, // 单体欠压告警三级
    {"BCU_26", 0, 3, bms_get_fault_level_3}, // 单体过温告警三级
    {"BCU_27", 0, 4, bms_get_fault_level_3}, // 单体低温告警三级
    {"BCU_28", 0, 5, bms_get_fault_level_3}, // 单体压差告警三级
    {"BCU_29", 0, 6, bms_get_fault_level_3}, // 充电过流告警三级
    {"BCU_30", 0, 7, bms_get_fault_level_3}, // 放电过流告警三级
    {"BCU_31", 0, 8, bms_get_fault_level_3}, // SOC过低告警三级
    {"BCU_32", 0, 9, bms_get_fault_level_3}, // SOC差异过大告警三级
    {"BCU_33", 0, 10, bms_get_fault_level_3}, // 绝缘过低告警三级

    {"BCU_34", 0, 0, NULL}, // 电芯温度极限告警
    {"BCU_35", 0, 0, NULL}, // 电芯电压极限告警
    {"BCU_36", 0, 0, NULL}, // 簇间环流1级告警
    {"BCU_37", 0, 0, NULL}, // 簇间环流2级告警
    {"BCU_38", 0, 0, NULL}, // 簇间环流3级告警
    {"BCU_39", 0, 0, NULL}, // 簇间电流差1级告警
    {"BCU_40", 0, 0, NULL}, // 簇间电流差2级告警
		
    {"BCU_41", 1, 0, NULL}, // 簇间电流差3级告警
    {"BCU_42", 1, 11, bms_get_fault_level_1}, // 组端过压1级告警
    {"BCU_43", 1, 11, bms_get_fault_level_2}, // 组端过压2级告警
    {"BCU_44", 1, 11, bms_get_fault_level_3}, // 组端过压3级告警
    {"BCU_45", 1, 12, bms_get_fault_level_1}, // 组端欠压1级告警
    {"BCU_46", 1, 12, bms_get_fault_level_2}, // 组端欠压2级告警
    {"BCU_47", 1, 12, bms_get_fault_level_3}, // 组端欠压3级告警
    {"BCU_48", 1, 13, bms_get_fault_level_1}, // 极柱过温1级告警
    {"BCU_49", 1, 13, bms_get_fault_level_2}, // 极柱过温2级告警
    {"BCU_50", 1, 13, bms_get_fault_level_3}, // 极柱过温3级告警

    {"BCU_51", 1, 0, NULL}, // AFE温感排线异常
    {"BCU_52", 1, 0, NULL}, // AFE电压排线异常
    {"BCU_53", 1, 0, NULL}, // 与电池簇通信告警
    {"BCU_54", 1, 0, NULL}, // 主从通讯告警
		
    {"BCU_55", 1, 0, NULL}, // 熔丝故障
    {"BCU_56", 1, 0, NULL}, // 断路器故障
    {"BCU_57", 1, 0, NULL}, // 空调故障
    {"BCU_58", 1, 0, NULL}, // 消防设备故障
    {"BCU_59", 1, 0, NULL}, // 消防火警
    {"BCU_60", 1, 0, NULL}, // 消防喷洒
    {"BCU_61", 1, 0, NULL}, // AFE故障
    {"BCU_62", 1, 14, bms_get_fault_level_1}, // 高压异常
    {"BCU_63", 1, 16, bms_get_fault_level_3}, // 预充告警
    {"BCU_64", 1, 17, bms_get_fault_level_3}, // 开路故障
		
    {"BCU_65", 1, 14, bms_get_fault_level_3}, // 继电器粘连告警
    {"BCU_66", 1, 15, bms_get_fault_level_3}, // 电池极限故障
		
		{"BCU_67", 1, 52, bms_get_baseInfo}, // 预充继电器
    {"BCU_68", 1, 53, bms_get_baseInfo}, // 总正继电器
    {"BCU_69", 1, 54, bms_get_baseInfo}, // 总负继电器
		
		{"BCU_101", 1, 1, bms_get_baseInfo}, // 总压
		{"BCU_102", 1, 2, bms_get_baseInfo}, // 总电流
		{"BCU_103", 1, 3, bms_get_baseInfo}, // SOC
		{"BCU_104", 1, 4, bms_get_baseInfo}, // SOH
		{"BCU_105", 1, 5, bms_get_baseInfo}, // SOE
		{"BCU_106", 1, 6, bms_get_baseInfo}, // 额定总压
		{"BCU_107", 1, 7, bms_get_baseInfo}, // 额定容量
		{"BCU_108", 1, 8, bms_get_baseInfo}, // 剩余容量
		{"BCU_109", 1, 9, bms_get_baseInfo}, // 额定电量
		{"BCU_110", 1, 10, bms_get_baseInfo}, // 剩余电量
		{"BCU_111", 1, 11, bms_get_baseInfo}, // 从机总数(BMU)
		
		{"BCU_112", 2, 12, bms_get_baseInfo}, // 在线从机总数(BMU)
		{"BCU_113", 2, 13, bms_get_baseInfo}, // 电池总数
		{"BCU_114", 2, 14, bms_get_baseInfo}, // 在线电池总数
		{"BCU_115", 2, 15, bms_get_baseInfo}, // 温感总数
		{"BCU_116", 2, 16, bms_get_baseInfo}, // 在线温感总数
		{"BCU_117", 2, 17, bms_get_baseInfo}, // 最大允许放电电流
		{"BCU_118", 2, 18, bms_get_baseInfo}, // 最大允许放电功率
		{"BCU_119", 2, 19, bms_get_baseInfo}, // 最大允许充电电流
		{"BCU_120", 2, 20, bms_get_baseInfo}, // 最大允许充电功率
		{"BCU_121", 2, 21, bms_get_baseInfo}, // 正极绝缘阻值
		{"BCU_122", 2, 22, bms_get_baseInfo}, // 负极绝缘阻值
		{"BCU_123", 2, 23, bms_get_baseInfo}, // 单体平均电压
		{"BCU_124", 2, 24, bms_get_baseInfo}, // 单体最大压差
		{"BCU_125", 2, 25, bms_get_baseInfo}, // 最高单体电压
		{"BCU_126", 2, 26, bms_get_baseInfo}, // 最高单体电压从机号
		{"BCU_127", 2, 27, bms_get_baseInfo}, // 最高单体电压编号
		{"BCU_128", 2, 28, bms_get_baseInfo}, // 最低单体电压
		{"BCU_129", 2, 29, bms_get_baseInfo}, // 最低单体电压从机号
		{"BCU_130", 2, 30, bms_get_baseInfo}, // 最低单体电压编号
		{"BCU_131", 2, 31, bms_get_baseInfo}, // 单体平均温度
		{"BCU_132", 2, 32, bms_get_baseInfo}, // 最大温差
		{"BCU_133", 2, 33, bms_get_baseInfo}, // 最高单体温度
		{"BCU_134", 2, 34, bms_get_baseInfo}, // 最高单体温度从机号
		{"BCU_135", 2, 35, bms_get_baseInfo}, // 最高单体温度编号
		{"BCU_136", 2, 36, bms_get_baseInfo}, // 最低单体温度
		{"BCU_137", 2, 37, bms_get_baseInfo}, // 最低单体温度从机号
		{"BCU_138", 2, 38, bms_get_baseInfo}, // 最低单体温度编号
		{"BCU_139", 2, 39, bms_get_baseInfo}, // 日充电容量
		{"BCU_140", 2, 40, bms_get_baseInfo}, // 日充电电量
		{"BCU_141", 2, 41, bms_get_baseInfo}, // 日放电容量
		{"BCU_142", 2, 42, bms_get_baseInfo}, // 日放电电量
		{"BCU_143", 2, 43, bms_get_baseInfo}, // 日充电时间
		{"BCU_144", 2, 44, bms_get_baseInfo}, // 日放电时间
		{"BCU_145", 2, 45, bms_get_baseInfo}, // 累计充电容量
		{"BCU_146", 2, 46, bms_get_baseInfo}, // 累计充电电量
		{"BCU_147", 2, 47, bms_get_baseInfo}, // 累计放电容量
		{"BCU_148", 2, 48, bms_get_baseInfo}, // 累计放电电量
		{"BCU_149", 2, 49, bms_get_baseInfo}, // 累计充电时间
		{"BCU_150", 2, 50, bms_get_baseInfo}, // 累计放电时间
		{"BCU_151", 2, 51, bms_get_baseInfo}, // BCU工作状态
		
//    {"BCU_67", 1, 1, bms_get_baseInfo}, // 总压
//    {"BCU_68", 1, 2, bms_get_baseInfo}, // 总电流
//    {"BCU_69", 1, 3, bms_get_baseInfo}, // SOC
//    {"BCU_70", 1, 4, bms_get_baseInfo}, // SOH
//    {"BCU_71", 1, 5, bms_get_baseInfo}, // SOE
//    {"BCU_72", 1, 6, bms_get_baseInfo}, // 额定总压
//    {"BCU_73", 1, 7, bms_get_baseInfo}, // 额定容量
//    {"BCU_74", 1, 8, bms_get_baseInfo}, // 剩余容量
//    {"BCU_75", 1, 9, bms_get_baseInfo}, // 额定电量
//    {"BCU_76", 1, 10, bms_get_baseInfo}, // 剩余电量
//    {"BCU_77", 1, 11, bms_get_baseInfo}, // 从机总数(BMU)
//    {"BCU_78", 1, 12, bms_get_baseInfo}, // 在线从机总数(BMU)
//    {"BCU_79", 1, 13, bms_get_baseInfo}, // 电池总数
//    {"BCU_80", 1, 14, bms_get_baseInfo}, // 在线电池总数
//    {"BCU_81", 1, 15, bms_get_baseInfo}, // 温感总数

//    {"BCU_82", 2, 16, bms_get_baseInfo}, // 在线温感总数
//    {"BCU_83", 2, 17, bms_get_baseInfo}, // 最大允许放电电流
//    {"BCU_84", 2, 18, bms_get_baseInfo}, // 最大允许放电功率
//    {"BCU_85", 2, 19, bms_get_baseInfo}, // 最大允许充电电流
//    {"BCU_86", 2, 20, bms_get_baseInfo}, // 最大允许充电功率
//    {"BCU_87", 2, 21, bms_get_baseInfo}, // 正极绝缘阻值
//    {"BCU_88", 2, 22, bms_get_baseInfo}, // 负极绝缘阻值
//    {"BCU_89", 2, 23, bms_get_baseInfo}, // 单体平均电压
//    {"BCU_90", 2, 24, bms_get_baseInfo}, // 单体最大压差
//    {"BCU_91", 2, 25, bms_get_baseInfo}, // 最高单体电压
//    {"BCU_92", 2, 26, bms_get_baseInfo}, // 最高单体电压从机号
//    {"BCU_93", 2, 27, bms_get_baseInfo}, // 最高单体电压编号
//    {"BCU_94", 2, 28, bms_get_baseInfo}, // 最低单体电压
//    {"BCU_95", 2, 29, bms_get_baseInfo}, // 最低单体电压从机号
//    {"BCU_96", 2, 30, bms_get_baseInfo}, // 最低单体电压编号
//    {"BCU_97", 2, 31, bms_get_baseInfo}, // 单体平均温度
//    {"BCU_98", 2, 32, bms_get_baseInfo}, // 最大温差
//    {"BCU_99", 2, 33, bms_get_baseInfo}, // 最高单体温度
//    {"BCU_100", 2, 34, bms_get_baseInfo}, // 最高单体温度从机号
//    {"BCU_101", 2, 35, bms_get_baseInfo}, // 最高单体温度编号
//    {"BCU_102", 2, 36, bms_get_baseInfo}, // 最低单体温度
//    {"BCU_103", 2, 37, bms_get_baseInfo}, // 最低单体温度从机号
//    {"BCU_104", 2, 38, bms_get_baseInfo}, // 最低单体温度编号
//    {"BCU_105", 2, 39, bms_get_baseInfo}, // 日充电容量
//    {"BCU_106", 2, 40, bms_get_baseInfo}, // 日充电电量
//    {"BCU_107", 2, 41, bms_get_baseInfo}, // 日放电容量
//    {"BCU_108", 2, 42, bms_get_baseInfo}, // 日放电电量
//    {"BCU_109", 2, 43, bms_get_baseInfo}, // 日充电时间
//    {"BCU_110", 2, 44, bms_get_baseInfo}, // 日放电时间
//    {"BCU_111", 2, 45, bms_get_baseInfo}, // 累计充电容量
//    {"BCU_112", 2, 46, bms_get_baseInfo}, // 累计充电电量
//    {"BCU_113", 2, 47, bms_get_baseInfo}, // 累计放电容量
//    {"BCU_114", 2, 48, bms_get_baseInfo}, // 累计放电电量
//    {"BCU_115", 2, 49, bms_get_baseInfo}, // 累计充电时间
//    {"BCU_116", 2, 50, bms_get_baseInfo}, // 累计放电时间
//    {"BCU_117", 2, 51, bms_get_baseInfo}, // BCU工作状态
};

const int bms_point_count = sizeof(bms_points) / sizeof(bms_points[0]);

/*
    const char* key;                		// JSON 中的键，比如 "BCU_"后面不带数字，数据后面通过BCU_pointId组合
    uint16_t pointId;						// 用于记录开始的测点号，见bcu模型
	uint16_t startCellIndex;				// 开始的电压序号（入参）
	uint16_t endCellIndex;					// 结束的电压序号（入参）
    uint32_t (*get_val)(uint16_t);          // 对应值的获取函数
*/
const devCellPointMap bms_volt_points[] =
{
    {"BCU_", 191, 0, 39, bms_get_cell_volt}, // 1号~40号电池电压
    {"BCU_", 191, 40, 79, bms_get_cell_volt}, // 41号~80号电池电压
    {"BCU_", 191, 80, 119, bms_get_cell_volt}, // 81号~120号电池电压
    {"BCU_", 191, 120, 159, bms_get_cell_volt}, // 121号~160号电池电压
    {"BCU_", 191, 160, 199, bms_get_cell_volt}, // 161号~200号电池电压
    {"BCU_", 191, 200, 239, bms_get_cell_volt}, // 201号~240号电池电压
    {"BCU_", 191, 240, 279, bms_get_cell_volt}, // 241号~280号电池电压
    {"BCU_", 191, 280, 319, bms_get_cell_volt}, // 281号~320号电池电压
    {"BCU_", 191, 320, 359, bms_get_cell_volt}, // 321号~360号电池电压
    {"BCU_", 191, 360, 399, bms_get_cell_volt}, // 361号~400号电池电压
};

const devCellPointMap bms_temp_points[] =
{
    {"BCU_", 611, 0, 39, bms_get_cell_temp}, // 1号~40号电池温度
    {"BCU_", 611, 40, 79, bms_get_cell_temp}, // 41号~80号电池温度
    {"BCU_", 611, 80, 99, bms_get_cell_temp}, // 81号~100号电池温度
};

const int bms_volt_count = sizeof(bms_volt_points) / sizeof(devCellPointMap);
const int bms_temp_count = sizeof(bms_temp_points) / sizeof(devCellPointMap);


void protocol_build_json(uint16_t groupId, uint32_t time) 
{
		int val = 0;
	
    cJSON* root = cJSON_CreateObject();

    // 添加时间戳
    cJSON_AddNumberToObject(root, "timeStamp", time);

    // devData 数组（仅包含一个设备对象）
    cJSON* devDataArr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "devData", devDataArr);

    // 设备对象
    cJSON* deviceObj = cJSON_CreateObject();
    cJSON_AddItemToArray(devDataArr, deviceObj);

    // 仅添加关键字段
    cJSON_AddStringToObject(deviceObj, "devType", "4");
    cJSON_AddStringToObject(deviceObj, "devName", "BCU");
    cJSON_AddStringToObject(deviceObj, "devId", "001");
    cJSON_AddStringToObject(deviceObj, "sn", deviceSN);
    cJSON_AddNumberToObject(deviceObj, "currentPack", groupId);	
    cJSON_AddNumberToObject(deviceObj, "totalPack", 16);

		cJSON* dataObj = cJSON_CreateObject();
    cJSON_AddItemToObject(deviceObj, "data", dataObj);

		for (int i = 0; i < bms_point_count; ++i)
    {
        const devPointMap* point = &bms_points[i];
        if(point->groupId == groupId)
        {
            if (point->get_val != NULL)
            {
                val = point->get_val(point->input);
            }
            else
            {
                val = 0; // 默认值
            }
						cJSON_AddNumberToObject(dataObj, point->key, val);
//					cJSON_AddNumberToObject(dataObj, point->key, 0);
        }
			//cJSON_AddNumberToObject(deviceObj, point->key, val); @wangk  放在这分组功能失效
    }


    char* json_str = cJSON_PrintUnformatted(root);
    if (json_str) 
    {
        drv_mqtt_publish_no_respose(json_str, strlen(json_str));
				bsp_task_delay_ms(100);
        cJSON_free(json_str);
    } 

    cJSON_Delete(root);
}

void protocol_build_volt_json(uint8_t i, uint32_t time)
{
	const devCellPointMap* item = &bms_volt_points[i];
    int val = 0;
    char key[10] = {0};
		uint8_t groupId = i + 3;
		
    cJSON* root = cJSON_CreateObject();

    cJSON_AddNumberToObject(root, "timeStamp", time);

    // devData 数组
    cJSON* devDataArr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "devData", devDataArr);

    // 构建每一个设备项
    cJSON* deviceObj = cJSON_CreateObject();
    cJSON_AddItemToArray(devDataArr, deviceObj);

    cJSON_AddStringToObject(deviceObj, "devType", "4");
    cJSON_AddStringToObject(deviceObj, "devName", "BCU");
    cJSON_AddStringToObject(deviceObj, "devId", "001");
    cJSON_AddStringToObject(deviceObj, "sn", deviceSN);
		cJSON_AddNumberToObject(deviceObj, "currentPack", groupId);  // 当前包数
    cJSON_AddNumberToObject(deviceObj, "totalPack", 16);       // 总包数

    // 构建 data 对象
    cJSON* dataObj = cJSON_CreateObject();
    cJSON_AddItemToObject(deviceObj, "data", dataObj);


    for (int i = item->startCellIndex; i <= item->endCellIndex; ++i)
    {
				sprintf(key,"%s%d",item->key,item->pointId + i);
        if (item->get_val != NULL)
        {
            val = item->get_val(i);
        }
        else
        {
            val = 0; // 默认值
        }
        cJSON_AddNumberToObject(dataObj, key, val);
//			cJSON_AddNumberToObject(dataObj, key, 0);
    }

    // 转为 JSON 字符串
    char* json_str = cJSON_PrintUnformatted(root);
    if (json_str)
    {
        drv_mqtt_publish_no_respose(json_str, strlen(json_str));
				bsp_task_delay_ms(100);
        cJSON_free(json_str);
    }

    cJSON_Delete(root);
}

void protocol_build_temp_json(uint8_t i, uint32_t time)
{
		const devCellPointMap* item = &bms_temp_points[i];
    int val = 0;
    char key[10] = {0};
		uint8_t groupId = i + 13;
		
    cJSON* root = cJSON_CreateObject();

    cJSON_AddNumberToObject(root, "timeStamp", time);

    // devData 数组
    cJSON* devDataArr = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "devData", devDataArr);

    // 构建每一个设备项
    cJSON* deviceObj = cJSON_CreateObject();
    cJSON_AddItemToArray(devDataArr, deviceObj);

    cJSON_AddStringToObject(deviceObj, "devType", "4");
    cJSON_AddStringToObject(deviceObj, "devName", "BCU");
    cJSON_AddStringToObject(deviceObj, "devId", "001");
    cJSON_AddStringToObject(deviceObj, "sn", deviceSN);
		cJSON_AddNumberToObject(deviceObj, "currentPack", groupId);  // 当前包数
    cJSON_AddNumberToObject(deviceObj, "totalPack", 16);       // 总包数

    // 构建 data 对象
    cJSON* dataObj = cJSON_CreateObject();
    cJSON_AddItemToObject(deviceObj, "data", dataObj);


    for (int i = item->startCellIndex; i <= item->endCellIndex; ++i)
    {
				sprintf(key,"%s%d",item->key,item->pointId + i);
        if (item->get_val != NULL)
        {
            val = item->get_val(i);
        }
        else
        {
            val = 0; // 默认值
        }
        cJSON_AddNumberToObject(dataObj, key, val);
//			cJSON_AddNumberToObject(dataObj, key, 0);
    }

    // 转为 JSON 字符串
    char* json_str = cJSON_PrintUnformatted(root);
    if (json_str)
    {
        drv_mqtt_publish_no_respose(json_str, strlen(json_str));
				bsp_task_delay_ms(100);
        cJSON_free(json_str);
    }

    cJSON_Delete(root);
}

void publish_all_bms_groups()
{
    uint8_t max_group = 0;
		uint8_t i = 0;
		uint32_t timeTemp = 0;
	
		timeTemp = drv_rtc_get_tick();
    for (i = 0; i < bms_point_count; i++)
    {
        if (bms_points[i].groupId > max_group)
        {
            max_group = bms_points[i].groupId;
        }
    }

    for (uint8_t g = 0; g <= max_group; g++)
    {
        protocol_build_json(g, timeTemp);
    }
	
    for (i = 0; i < bms_volt_count; i++)
    {
        protocol_build_volt_json(i, timeTemp);
    }
	
    for (i = 0; i < bms_temp_count; i++)
    {
        protocol_build_temp_json(i, timeTemp);
    }
	
}

void mqtt_publish_bms_data(uint32_t basetime)
{
    static uint32_t mqtt_cycle_tick  = 0;
		//static uint16_t mqtt_init_count = 0;
		static uint8_t mqtt_init_flag = 1;
		static uint8_t sub_read_control_flag = 1;
    static uint8_t groupMax = 0;

    mqtt_cycle_tick += basetime;
		
    if(mqtt_cycle_tick > 1000)
    {
//				if (!drv_at_send_cmd("AT+QSTAST", "+QSTAST:STATION_UP", WIFI_TIMEOUT))
//				{
//						mqtt_init_flag = 1;
//				}
//				
//				if (mqtt_init_flag == 1)
//				{	
//						if (drv_mqtt_connect() == 0)
//						{
//								mqtt_init_flag = 0;
//						}
//				}
				// 定期检测是否连接mqtt服务器成功
				if (!drv_at_send_cmd("AT+QMTCONN?", "3\0", WIFI_TIMEOUT)) 
				{
						drv_mqtt_connect();
				}
//				else  //@wangk add 5-16,这段注释可以证明上述if起作用了，只有检测没有连接到mqtt的时候，才会执行连接函数，避免消耗资源
//				{
//						drv_mqtt_publish_no_respose("1", 1);
//				}

				if (sub_read_control_flag == 1) 
				{
						char control_topic[44];  
						char read_topic[44];     
						char mqtt_sub_cmd[128];  

						snprintf(control_topic, sizeof(control_topic), "bluesun/bms/control/%s", deviceSN);
						snprintf(read_topic, sizeof(read_topic), "bluesun/bms/read/%s", deviceSN);

						snprintf(mqtt_sub_cmd, sizeof(mqtt_sub_cmd), "AT+QMTSUB=0,1,\"%s\",0,\"%s\",0", control_topic, read_topic);

						// 发送命令
						if (drv_at_send_cmd(mqtt_sub_cmd, "OK", WIFI_TIMEOUT)) 
						{
								sub_read_control_flag = 0;  // 成功订阅后清除标志
						}
				}
				
				
				// 定期检测是否蓝牙断连
				if (!drv_at_send_cmd("AT+QBLESTAT", "ADVERTISING\0", WIFI_TIMEOUT)) 
				{
						if (!drv_at_send_cmd("AT+QBLESTAT", "CONNECTED\0", WIFI_TIMEOUT)) 
						{
								drv_ble_init();
						}
				}
//				else   //@wangk add 5-20,这段注释可以证明上述if起作用了，解决蓝牙小概率会消失的问题
//				{
//						drv_mqtt_publish_no_respose("2", 1);
//				}

			
				
//				drv_wireless_send_string("AT+QMTPUB=0,1,2,0,\"BCU01\",17,\"Hello from FC41D!\"");
        mqtt_cycle_tick = 0;
        publish_all_bms_groups();

    }

}

