
#include "cfg_protocol.h"
#include "uart_dev.h"
#include "inFlash.h"
#include "parameter.h"
#include "string.h"
#include "chargControlEnum.h"
#include "pDebug.h"

#define cfgBuffLen 200
static uint8_t configBuff[cfgBuffLen];
static uint8_t cfigLen = 0;

/* 配置文件中的部分数据放大倍数 */
#define enlargeScale 100

/**
  * @brief  向配置文件buff中存入一个数据
  * @param  c 数据
  * @retval     
  *
  */
void inConfigBuff(uint8_t c)
{
    if (cfigLen < cfgBuffLen) {
        configBuff[cfigLen] = c;
        cfigLen++;
    }
}

/**
  * @brief  向配置文件buff中丢掉一个数据
  * @param  
  * @retval     
  *
  */
void outConfigBuff(void)
{
    if (cfigLen > 0) {
        cfigLen--;
        memcpy(configBuff, configBuff + 1, cfigLen);
        // memcpy(configBuff, configBuff + 1, sizeof(configBuff) - 1);
    }
}

/**
  * @brief  modbus的crc校验
  * @param  *arr_buff   需要校验的数据
  *         len         数据长度
  * @retval crc         校验的结果
  */
uint16_t checkModebusCrc(uint8_t *arr_buff, uint8_t len)
{
    uint16_t crc = 0xFFFF;
    uint16_t i, j;
    for (j = 0; j < len; ++j) {
        crc = crc ^ (*arr_buff++);
        for (i = 0; i < 8; ++i) {
            if ((crc&0x0001) > 0) {
                crc = crc >> 1;
                crc = crc ^ 0xa001;
            }
            else {
                crc = crc >> 1;
            }
        }
    }
    return crc;
}

/**
  * @brief  清空配置文件buff
  * @param  
  * @retval     
  *
  */
void zeroConfigBuff(void)
{
    cfigLen = 0;
}

/**
 * @brief   判断接收到的配置文件数据是否正确，正确的话存入flash中
 * @param   None
 * @retval  None
 *
 */
void read_and_process_config_data(void)
{
    recv_config_info *pack = (recv_config_info *)configBuff;
    static config_info save_configInfo;
    while (cfigLen >= RECV_CONFIG_INFO) {
        /* 判断起始标志是否正确 */
        debug_printf(" start_Flag : 0x%x, 0x%x \n", pack->start_Flag[0], pack->start_Flag[1]);
        if (pack->start_Flag[0] != g_cfgParameter.startFlagSL[0]
                || pack->start_Flag[1] != g_cfgParameter.startFlagSL[1]) {
            // debug(" start_Flag : 0x%x, 0x%x \n", pack->start_Flag[0], pack->start_Flag[1]);
            goto err;
        }
        
//         /* 判断接入节点类型是否正确 */
//         save_configInfo.Access_Node_Type = (uint16_t)pack->Access_Node_Type[0] << 8
//                                             | (uint16_t)pack->Access_Node_Type[1];
//         if (save_configInfo.Access_Node_Type != POWERBOX) {
//             // debug(" Access_Node_Type : 0x%x \n", save_configInfo.Access_Node_Type);
//             goto err;
//         }

//         /* 判断通信方式是否正确 */
//         save_configInfo.Communication_Methods = (uint16_t)pack->Communication_Methods[0] << 8
//                                                 | (uint16_t)pack->Communication_Methods[1];
// //        if (temp_u16 != RS485 || temp_u16 != RJ45) {
//         if (save_configInfo.Communication_Methods != RS485) {
//             debug(" Communication_Methods : 0x%x \n", save_configInfo.Communication_Methods);
//             goto err;
//         }

        /* 判断波特率是否正确 */
        save_configInfo.gw485_Baud = (uint32_t)pack->gw485_Baud[0] << 24
                                    | (uint32_t)pack->gw485_Baud[1] << 16
                                    | (uint32_t)pack->gw485_Baud[2] << 8
                                    | (uint32_t)pack->gw485_Baud[3];
//        debug(" gw485_Baud : 0x%x, %d \n", save_configInfo.gw485_Baud, save_configInfo.gw485_Baud);
        if (save_configInfo.gw485_Baud != 9600
             && save_configInfo.gw485_Baud != 115200) {
            // debug(" gw485_Baud : %d\n", save_configInfo.gw485_Baud);
            goto err;
        }

        save_configInfo.bat485_Baud = (uint32_t)pack->bat485_Baud[0] << 24
                                    | (uint32_t)pack->bat485_Baud[1] << 16
                                    | (uint32_t)pack->bat485_Baud[2] << 8
                                    | (uint32_t)pack->bat485_Baud[3];
        if (save_configInfo.bat485_Baud != 9600
             && save_configInfo.bat485_Baud!= 115200
             && save_configInfo.bat485_Baud!= 0) {
            // debug(" bat485_Baud : 0x%x, %d \n", save_configInfo.bat485_Baud, save_configInfo.bat485_Baud);
            goto err;
        }

        /* 判断汇源协议类型是否正确 */
        if (pack->protocolType != 0x01 && pack->protocolType != 0x02) {
            // debug(" protocolType : 0x%x \n", pack->protocolType);
            goto err;
        }

        /* 判断通信协议类型是否正确 */
        if (pack->CommunicationProtocolType != 0x00
             && pack->CommunicationProtocolType != 0x01) {
            // debug(" CommunicationProtocolType : 0x%x \n", pack->CommunicationProtocolType);
            goto err;
        }


        /* 判断电源盒类型是否正确 */
        if (pack->onlyPower != 0x00 && pack->onlyPower != 0x01) {
            // debug(" onlyPower : 0x%x \n", pack->onlyPower);
            goto err;
        }

        /* 判断恒压充电阈值是否正确 */
        save_configInfo.constantVoltageV =
                (float)(pack->ConstantVoltageV[0] << 8 | pack->ConstantVoltageV[1]) / enlargeScale;
        if (!((save_configInfo.constantVoltageV < 14.4f && save_configInfo.constantVoltageV > 13.5f)
                || save_configInfo.constantVoltageV == 0)) {
            // debug(" constantVoltageV : %f \n", save_configInfo.constantVoltageV);
            goto err;
        }

        /* 判断浮充充电阈值是否正确 */
        save_configInfo.floatI = (float)(pack->FloatI[0] << 8 | pack->FloatI[1]) / enlargeScale;
        if (save_configInfo.floatI > 0.2f || save_configInfo.floatI < 0) {
            // debug(" floatI : %f \n", save_configInfo.floatI);
            goto err;
        }

        /* 判断太阳能板开路启动电压是否正确 */
        save_configInfo.startSolarOpenCircuitV =
                (float)(pack->startSolarOpenCircuitV[0] << 8 | pack->startSolarOpenCircuitV[1]) / enlargeScale;
        if (!((save_configInfo.startSolarOpenCircuitV < 24 && save_configInfo.startSolarOpenCircuitV > 14)
            || save_configInfo.startSolarOpenCircuitV == 0)) {
            // debug(" startSolarOpenCircuitV : %f \n", save_configInfo.startSolarOpenCircuitV);
            goto err;
        }

        /* 判断太阳能板关闭电压是否正确 */
        save_configInfo.stopSolarOpenCircuitV =
                (float)(pack->stopSolarOpenCircuitV[0] << 8 | pack->stopSolarOpenCircuitV[1]) / enlargeScale;
        if (!((save_configInfo.stopSolarOpenCircuitV > 17 && save_configInfo.stopSolarOpenCircuitV < 13)
                || save_configInfo.stopSolarOpenCircuitV == 0)) {
            // debug(" stopSolarOpenCircuitV : %f \n", save_configInfo.stopSolarOpenCircuitV);
            goto err;
        }

        /* 判断恒压充电时的输出电压是否正确 */
        save_configInfo.constantVoltageChargeV =
                (float)(pack->constantVoltageChargeV[0] << 8 | pack->constantVoltageChargeV[1]) / enlargeScale;
        if (!((save_configInfo.constantVoltageChargeV < 14.6f && save_configInfo.constantVoltageChargeV > 14)
            || save_configInfo.constantVoltageChargeV == 0)) {
            // debug(" constantVoltageChargeV : %f \n", save_configInfo.constantVoltageChargeV);
            goto err;
        }

        /* 判断浮充充电时的输出电压是否正确 */
        save_configInfo.FloatChargeV =
                (float)(pack->FloatChargeV[0] << 8 | pack->FloatChargeV[1]) / enlargeScale;
        if (!((save_configInfo.FloatChargeV < 14.4f && save_configInfo.FloatChargeV > 13.8f)
            || save_configInfo.FloatChargeV == 0)) {
            // debug(" FloatChargeV : %f \n", save_configInfo.FloatChargeV);
            goto err;
        }

        /* 判断mos管停止工作温度是否正确 */
        save_configInfo.HighSideMosTemperature_stop =
                (float)(pack->HighSideMosTemperature_stop[0] << 8 | pack->HighSideMosTemperature_stop[1]) / enlargeScale;
        if (save_configInfo.HighSideMosTemperature_stop < 50 && save_configInfo.HighSideMosTemperature_stop != 0) {
            // debug(" HighSideMosTemperature_stop : %f \n", save_configInfo.HighSideMosTemperature_stop);
            goto err;
        }

        /* 判断mos管降低工作功率工作温度是否正确 */
        save_configInfo.HighSideMosTemperature_end =
                (float)(pack->HighSideMosTemperature_end[0] << 8 | pack->HighSideMosTemperature_end[1]) / enlargeScale;
        if (save_configInfo.HighSideMosTemperature_end < 40  && save_configInfo.HighSideMosTemperature_end != 0) {
            // debug(" HighSideMosTemperature_end : %f \n", save_configInfo.HighSideMosTemperature_end);
            goto err;
        }

        /* 判断mos管完全恢复工作温度是否正确 */
        save_configInfo.HighSideMosTemperature_start =
                (float)(pack->HighSideMosTemperature_start[0] << 8 | pack->HighSideMosTemperature_start[1]) / enlargeScale;
        if (save_configInfo.HighSideMosTemperature_start > 70 && save_configInfo.HighSideMosTemperature_start != 0) {
            debug(" HighSideMosTemperature_start : %d \n", save_configInfo.HighSideMosTemperature_start);
            goto err;
        }

        // /* 判断启动任务中太阳能板开路电压检测间隔时间是否正确 */
        // save_configInfo.checkSolarOpenCircuitVTime =
        //         pack->checkSolarOpenCircuitVTime[0] << 8 | pack->checkSolarOpenCircuitVTime[1];
        // if (save_configInfo.checkSolarOpenCircuitVTime > 1800 || save_configInfo.checkSolarOpenCircuitVTime < 5) {
        //     debug(" checkSolarOpenCircuitVTime : %d \n", save_configInfo.checkSolarOpenCircuitVTime);
        //     goto err;
        // }

        // /* 判断传感器运行再次注册的间隔是否正确 */
        // save_configInfo.sensorEnableBroadcastTime =
        //         pack->sensorEnableBroadcastTime[0] << 8 | pack->sensorEnableBroadcastTime[1];
        // if (save_configInfo.sensorEnableBroadcastTime > 60 || save_configInfo.sensorEnableBroadcastTime < 10) {
        //     debug(" sensorEnableBroadcastTime : %d \n", save_configInfo.sensorEnableBroadcastTime);
        //     goto err;
        // }

        /* 判断出现短路保护后延长该段时间再次检测是否短路，仍然短路则关闭输出的间隔是否正确 */
        save_configInfo.outputAgainFlagTime =
                pack->outputAgainFlagTime[0] << 8 | pack->outputAgainFlagTime[1];
        if (!((save_configInfo.outputAgainFlagTime < 30 && save_configInfo.outputAgainFlagTime > 5)
            || save_configInfo.outputAgainFlagTime == 0)) {
            // debug(" outputAgainFlagTime : %d \n", save_configInfo.outputAgainFlagTime);
            goto err;
        }

        /* 判断出现过载后，在该间隔时间中多次（2次）出现过载，则关闭输出的间隔是否正确 */
        save_configInfo.excessiveLoadFlagTime =
                pack->excessiveLoadFlagTime[0] << 8 | pack->excessiveLoadFlagTime[1];
        if (!((save_configInfo.excessiveLoadFlagTime < 90 && save_configInfo.excessiveLoadFlagTime > 20)
            || save_configInfo.excessiveLoadFlagTime == 0)) {
            // debug(" excessiveLoadFlagTime : %d \n", save_configInfo.excessiveLoadFlagTime);
            goto err;
        }

        /* 判断出现过载过载保护后，在该间隔段时间后，再次尝试输出的间隔是否正确 */
        save_configInfo.eLAgainTime = pack->eLAgainTime[0] << 8 | pack->eLAgainTime[1];
        if (save_configInfo.eLAgainTime > 3000 || save_configInfo.eLAgainTime < 1000) {
            debug(" eLAgainTime : %d \n", save_configInfo.eLAgainTime);
            goto err;
        }

        /* crc校验 */
        save_configInfo.crc = pack->crc[0] << 8 | pack->crc[1];
        if (save_configInfo.crc != checkModebusCrc(configBuff, RECV_CONFIG_INFO - 3)) {
            debug(" crc : %x%x \n", pack->crc[0], pack->crc[1]);
            debug(" checkModebusCrc : %x \n", checkModebusCrc(configBuff, RECV_CONFIG_INFO));
            goto err;
        }


        /* 结束标志 */
        if (pack->end_Flag != 0x16) {
            debug(" end_Flag : %x \n", pack->end_Flag);
            goto err;
        }

//        debug("address : 0x %x %x %x %x %x %x %x\n", pack->address[0]
//                , pack->address[1], pack->address[2], pack->address[3]
//                , pack->address[4], pack->address[5], pack->address[6]);
        config_info temp_configInfo;
        read_config_info(&temp_configInfo);

        if (pack->address[0] != 0xFF
            || pack->address[1] != 0xFF
            || pack->address[2] != 0xFF
            || pack->address[3] != 0xFF
            || pack->address[4] != 0xFF
            || pack->address[5] != 0xFF
            || pack->address[6] != 0xFF) {
            save_configInfo.address[0]          = pack->address[0];
            save_configInfo.address[1]          = pack->address[1];
            save_configInfo.address[2]          = pack->address[2];
            save_configInfo.address[3]          = pack->address[3];
            save_configInfo.address[4]          = pack->address[4];
            save_configInfo.address[5]          = pack->address[5];
            save_configInfo.address[6]          = pack->address[6];
//            debug("address : 0x %x %x %x %x %x %x %x\n", save_configInfo.address[0]
//                    , save_configInfo.address[1], save_configInfo.address[2], save_configInfo.address[3]
//                    , save_configInfo.address[4], save_configInfo.address[5], save_configInfo.address[6]);
        } else {
            save_configInfo.address[0]          = temp_configInfo.address[0];
            save_configInfo.address[1]          = temp_configInfo.address[1];
            save_configInfo.address[2]          = temp_configInfo.address[2];
            save_configInfo.address[3]          = temp_configInfo.address[3];
            save_configInfo.address[4]          = temp_configInfo.address[4];
            save_configInfo.address[5]          = temp_configInfo.address[5];
            save_configInfo.address[6]          = temp_configInfo.address[6];
        }

        if (pack->hardwareID[0] != 0xFF
            || pack->hardwareID[1] != 0xFF
            || pack->hardwareID[2] != 0xFF
            || pack->hardwareID[3] != 0xFF
            || pack->hardwareID[4] != 0xFF
            || pack->hardwareID[5] != 0xFF) {
            save_configInfo.hardwareID[0]       = pack->hardwareID[0];
            save_configInfo.hardwareID[1]       = pack->hardwareID[1];
            save_configInfo.hardwareID[2]       = pack->hardwareID[2];
            save_configInfo.hardwareID[3]       = pack->hardwareID[3];
            save_configInfo.hardwareID[4]       = pack->hardwareID[4];
            save_configInfo.hardwareID[5]       = pack->hardwareID[5];
        } else {
            save_configInfo.hardwareID[0]       = temp_configInfo.hardwareID[0];
            save_configInfo.hardwareID[1]       = temp_configInfo.hardwareID[1];
            save_configInfo.hardwareID[2]       = temp_configInfo.hardwareID[2];
            save_configInfo.hardwareID[3]       = temp_configInfo.hardwareID[3];
            save_configInfo.hardwareID[4]       = temp_configInfo.hardwareID[4];
            save_configInfo.hardwareID[5]       = temp_configInfo.hardwareID[5];
        }

        if (pack->communicationID[0] != 0xFF
            || pack->communicationID[1] != 0xFF
            || pack->communicationID[2] != 0xFF
            || pack->communicationID[3] != 0xFF) {
            save_configInfo.communicationID[0]  = pack->communicationID[0];
            save_configInfo.communicationID[1]  = pack->communicationID[1];
            save_configInfo.communicationID[2]  = pack->communicationID[2];
            save_configInfo.communicationID[3]  = pack->communicationID[3];
        } else {
            save_configInfo.communicationID[0]  = temp_configInfo.communicationID[0];
            save_configInfo.communicationID[1]  = temp_configInfo.communicationID[1];
            save_configInfo.communicationID[2]  = temp_configInfo.communicationID[2];
            save_configInfo.communicationID[3]  = temp_configInfo.communicationID[3];
        }

        save_configInfo.protocolType        = pack->protocolType;

        save_configInfo.CommunicationProtocolType = pack->CommunicationProtocolType;

        save_configInfo.onlyPower           = pack->onlyPower;
       

        save_configInfo.crc = checkModebusCrc((uint8_t *)&save_configInfo, CONFIG_INFO_SIZE - 2);
        // save_backups_config_info(&save_configInfo);
        // save_config_info(&save_configInfo);
        saveConfigInfo(&save_configInfo);

        // memset(config_buff, 0, sizeof(config_buff));
        zeroConfigBuff();

        // /* 返回更改配置文件成功 */
        // SL_Mppt_SOther_pack SUpdateProfile_pack = {0};

        // SUpdateProfile_pack.start_Flag[0] = g_otherParameter.startFlagSL[0];
        // SUpdateProfile_pack.start_Flag[1] = g_otherParameter.startFlagSL[1];

        // SUpdateProfile_pack.address[0] = save_configInfo.address[0];
        // SUpdateProfile_pack.address[1] = save_configInfo.address[1];
        // SUpdateProfile_pack.address[2] = save_configInfo.address[2];
        // SUpdateProfile_pack.address[3] = save_configInfo.address[3];
        // SUpdateProfile_pack.address[4] = save_configInfo.address[4];
        // SUpdateProfile_pack.address[5] = save_configInfo.address[5];
        // SUpdateProfile_pack.address[6] = save_configInfo.address[6];

        // SUpdateProfile_pack.function_Code = SL_Function_Code_Update_Profile;

        // SUpdateProfile_pack.state = 0x01;

        // uint16_t crc = CheckFuncSL((uint8_t *)&SUpdateProfile_pack, SL_MPPT_SOTHER_PACK_SIZE - 3);
        // SUpdateProfile_pack.check_Bit_H = crc >> 8;
        // SUpdateProfile_pack.check_Bit_L = crc;

        // SUpdateProfile_pack.end_Flag = g_otherParameter.endFlagSL;

        // while (1) {
        //     if (!Check_485_bus_busy(g_gw485_uart4_handle)) {
        //         uart_dev_write(g_gw485_uart4_handle, (uint8_t *)&SUpdateProfile_pack, SL_MPPT_SOTHER_PACK_SIZE);
        //         USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
        //         break;
        //     }
        //     Delay_Ms(randomDelay());
        // }
        uart_dev_write(g_gw485_uart2_handle, "hello world\n", sizeof("hello world\n"));

        /* 复位 */
        NVIC_SystemReset();

        err:
            // config_buff_pos--;
            // memcpy(config_buff, config_buff + 1, sizeof(config_buff) - 1);
            outConfigBuff();
    }
}

