/*
 * @Description: OTA模块-svc层
 * @Author: yangsw
 * @Date: 2021-06-21 10:39:07
 * @LastEditTime: 2023-03-04 14:05:28
 * @LastEditors: Lida
 * @Reference:
 */
#include "svc_ota.h"
#include "../../flash/svc/svc_flash.h"
#include "../../log/svc/svc_log.h"
#include "../../cloud/svc/svc_cloud.h"
#include "../../cloud/svc/svc_cloud_protocol.h"
#include "../../util/util_data.h"
#include "../../util/util_crc.h"
#include "../../timer/svc/svc_timer.h"
#include "../../ir/svc/svc_ir_protocol.h"
#include "../../lcd/svc/svc_lcd.h"
void IWDG_Config(void);

static S_Ota s_ota;

/**
 * @brief: OTA开始
 * @param  {void}
 * @return {void}
 * @note:
 * @see:
 */
void Svc_Ota_Start(void)
{
    s_ota.u16PackNum = 0;
    s_ota.u32FirmwareLen = 0;
    s_ota.u8Err = 0;
    s_ota.u8Result = 0;
    // s_ota.s_para.u8otaFlag = 1;
}

/**
 * @brief: 获取OTA相关数据
 * @param  {void}
 * @return {S_Ota*} OTA相关数据
 * @note:
 * @see:
 */
S_Ota *Svc_Ota_Get_Data(void)
{
    return &s_ota;
}

/**
 * @brief: 保存固件参数
 * @param  {void}
 * @return {E_Result_State} 执行结果
 * @note:
 * @see:
 */
E_Result_State Save_Firmware_Para(void)
{
    S_Ota_Para s_ota_para;
    gw_u8 *ptr = (gw_u8 *)&s_ota_para;
    gw_u8 *ptr1 = (gw_u8 *)&s_ota.s_para;
    s_ota.s_para.u8Sig = 0xF5;
    s_ota.s_para.u8IsNewFirmware = 1;
    // s_ota.s_para.u32FirmwareLen=s_ota.u32FirmwareLen;
    s_ota.s_para.u8Sum = Util_Data_Check_Sum(ptr1, (gw_u32)&s_ota.s_para.u8Sum - (gw_u32)&s_ota.s_para);
    if (Svc_Flash_Write(ptr1, OTA_FIRMWARE_PARA_ADDR, sizeof(S_Ota_Para)) == E_STATE_ERROR)
    { // flash写入异常
        return E_STATE_ERROR;
    }
    Svc_Flash_Read(ptr, OTA_FIRMWARE_PARA_ADDR, sizeof(S_Ota_Para));
    if (memcmp(&s_ota.s_para, ptr, sizeof(S_Ota_Para)))
    {
        Svc_Log_Printf(LOG_ERROR, "%s->write fail", __FUNCTION__);
        return E_STATE_ERROR;
    }
    Svc_Log_Printf(LOG_DEBUG, "%s->Save_Firmware_Para  Ok", __FUNCTION__);
    return E_STATE_SUCCESS;
}

/**
 * @brief: OTA写固件到flash
 * @return {E_Result_State} 执行结果
 * @note:
 * @see:
 * @param {gw_u8} *pu8Data OTA数据
 * @param {gw_u16} u16PackNum 数据包编号
 * @param {gw_u16} u16Len 数据长度
 */
E_Result_State Svc_Ota_Write_Firmware(gw_u8 *pu8Data, gw_u16 u16PackNum, gw_u16 u16Len)
{
    gw_u32 u32Addr;
    // gw_u32 u16CurLen;
    // gw_s32 u16RemainLen;
    gw_u16 u16WriteLen;
    if (u16Len <= 0)
    { // 单包长度异常
        s_ota.u8Err++;
        Svc_Log_Printf(LOG_ERROR, "packge len err!");
        return E_STATE_ERROR;
    }
    if (u16PackNum != s_ota.u16PackNum)
    { // 升级包编号异常
        s_ota.u8Err++;
        Svc_Log_Printf(LOG_ERROR, "packge err!");
        return E_STATE_ERROR;
    }
    // u16CurLen=OTA_PACKGE_SIZE*u16PackNum;
    if (s_ota.u32CurLen >= s_ota.s_para.u32FirmwareLen)
    { // 固件长度异常
        s_ota.u8Err++;
        Svc_Log_Printf(LOG_ERROR, "%s->firmware len err");
        return E_STATE_ERROR;
    }
    // u16RemainLen=s_ota.s_para.u32FirmwareLen-u16CurLen;
    if (s_ota.u32RemainLen <= OTA_PACKGE_SIZE)
    { // 剩余固件长度小于单包长，表示已经是最后一包数据了
        u16WriteLen = s_ota.u32RemainLen;
    }
    else
    {
        u16WriteLen = u16Len;
    }
    u32Addr = OTA_FIRMWARE_ADDR + s_ota.u32CurLen; // OTA_FIRMWARE_ADDR+
    // Svc_Log_Printf(LOG_INFO,"u32Addr=0x%08x",u32Addr);
    if (Svc_Flash_Write_Ota(pu8Data, u32Addr, u16WriteLen) == E_STATE_ERROR)
    { // flash写入异常
        s_ota.u8Err++;
        Svc_Log_Printf(LOG_ERROR, "%s->write fail", __FUNCTION__);
        return E_STATE_ERROR;
    }
    S_Flash_Data *ps_flash_data;
    ps_flash_data = Svc_Flash_Get_Data();
    S_Flash_Device_Security *ps_security;
    ps_security = &ps_flash_data->s_security;
    // s_ota.u16Crc=Util_Crc16_Cut(s_ota.u16Crc,pu8Data,u16WriteLen);//计算固件crc
    // Svc_Log_Printf(LOG_INFO,"s_ota.u32RemainLen=%u",s_ota.u32RemainLen);
    if (s_ota.u32RemainLen <= OTA_PACKGE_SIZE)
    { // 升级完成OTA_PACKGE_SIZE
        if (Save_Firmware_Para() == E_STATE_SUCCESS)
        {                       // 保存固件参数
            s_ota.u8Result = 1; // 写入参数到flash成功才表示升级成功
        }
        s_ota.u16PackNum = 0;
        s_ota.startflag = 0;
        Svc_Ota_Clear_Event(E_OTA_EVENT_REQUEST_OTA_DATA);
        ps_security->main_version = s_ota.s_para.u8softversion[0];
        ps_security->sub_version = s_ota.s_para.u8softversion[1];
        // 保存数据到flash
        Svc_Flash_Write_Device_Security(ps_security);
        Svc_Log_Printf(LOG_INFO, "ota finish");
        Bsp_Iwdg_Feed();
        Svc_Timer_Delay_Ms(3000);//等待OTA升级成功命令上报到服务器
        /*MCU复位*/
        WWDG_Config();
        while (1)
            ; // 等待看门狗复位
    }
    else
    { // 升级未完成，读下一包数据

        s_ota.u16PackNum = u16PackNum + 1;
        Svc_Ota_Post_Event(E_OTA_EVENT_REQUEST_OTA_DATA);
    }
    Svc_Lcd_Display_OTA_Process(s_ota.u16PackNum);
    Svc_Log_Printf(LOG_INFO, "firmwareCurLen=%u,firmwareTotalLen:%u", s_ota.u32CurLen, s_ota.s_para.u32FirmwareLen);
    return E_STATE_SUCCESS;
}

void WWDG_Config(void)
{
    /* Enable LSI clock */
    RCC_ClocksType temp;
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_WWDG, ENABLE);
    RCC_GetClocksFreqValue(&temp);
    WWDG_SetPrescalerDiv(WWDG_PRESCALER_DIV8);
    WWDG_SetWValue(80);
    WWDG_Enable(127);
    WWDG_SetCnt(127);
}

void WWDG_FeedDog(void)
{
    WWDG_SetCnt(127);
}

/**
 * @brief: ota事件推送
 * @return {void}
 * @note:
 * @see:
 * @param {E_Cloud_Event} cloud_event 需要推送的事件
 */
void Svc_Ota_Post_Event(E_OTA_Event_Enum ota_event)
{
    S_Ota *s_ota;
    s_ota = Svc_Ota_Get_Data();
    s_ota->ota_event |= ota_event;
}

/**
 * @brief: ota事件清除
 * @return {void}
 * @note:
 * @see:
 * @param {E_Cloud_Event} cloud_event 需要清除的事件
 */
void Svc_Ota_Clear_Event(E_OTA_Event_Enum ota_event)
{
    S_Ota *s_ota;
    s_ota = Svc_Ota_Get_Data();
    /*清除云事件*/
    s_ota->ota_event &= ~ota_event;
    /*清除正在发送的云事件*/
    s_ota->e_ota_sending_event = E_OTA_EVENT_NO;
}

/**
 * @brief: 获取处于等待处理的最高优先级事件
 * @param  {void}
 * @return {E_Cloud_Event}  处于等待处理的最高优先级事件
 * @note:
 * @see:
 */
E_OTA_Event_Enum Svc_Ota_Get_Pending_Event(void)
{
    S_Ota *s_ota;
    s_ota = Svc_Ota_Get_Data();
    if ((s_ota->ota_event & E_OTA_EVENT_REQUEST_OTA) == E_OTA_EVENT_REQUEST_OTA)
    {
        return E_OTA_EVENT_REQUEST_OTA;
    }
    if ((s_ota->ota_event & E_OTA_EVENT_REQUEST_OTA_DATA) == E_OTA_EVENT_REQUEST_OTA_DATA)
    {
        return E_OTA_EVENT_REQUEST_OTA_DATA;
    }
    return E_OTA_EVENT_NO;
}

/**
 * @brief: 锁定事件，该事件状态转为发送中
 * @return {void}
 * @note: 事件被锁定后，会触发该事件的数据上报，直到该事件解锁
 * @see:
 * @param {E_Cloud_Event} cloud_event 待锁定的事件
 */
void Svc_Ota_Lock_Event(E_OTA_Event_Enum ota_event)
{
    S_Ota *s_ota;
    s_ota = Svc_Ota_Get_Data();
    s_ota->e_ota_sending_event = ota_event;
}

/**
 * @brief:检查事件是否改变
 * @return {E_Result_Check} 检查结果
 * @note: 当待检查的事件和正在发送的事件不一致时，说明事件发生了变化，可能是优先级更高的事件插入
 * @see:
 * @param {E_Cloud_Event} e_event 待检查的事件
 */
E_Result_Check Svc_Ota_Event_Is_Changed(E_OTA_Event_Enum ota_event)
{
    S_Ota *s_ota;
    s_ota = Svc_Ota_Get_Data();
    if (s_ota->e_ota_sending_event != ota_event)
    {
        return E_CHECK_OK;
    }
    return E_CHECK_FAIL;
}
