/**
* @file MSCP_APP_API.h
* @brief 平台为应用提供的接口
* @details 一些由平台实现，由应用调用的各种API
* @author GT-BU 平台软件组
* @date 2021.3.1
* @version V1.0
* @copyright TCT
* @note 本文件采用doxygen格式编写，用于生成平台对外接口说明书
*/
#ifndef MSCP_APP_API_H
#define MSCP_APP_API_H
#include "CM_Types.h"
#include "MSCP_APP_Interface.h"
#include "PFM_Cfg.h"
#ifdef __cplusplus
extern "C"
{
#endif



    /**
    * @brief 接收应用报文
    * @param[in] ch 指定接收通道 \n
    * @ref ENUM_MSG_OUTNET_SAFE 外网安全通信通道 \n
    * @ref ENUM_MSG_INNET_SAFE  内网安全通信通道 \n
    * @ref ENUM_MSG_INNET_RAW   内网透传通信通道 \n
    * @ref 其它 预留
    * @param[out] *pSrcName 源设备ID
    * @param[out] *pSrcLogicID 源逻辑ID \n
    * @ref 0 默认值(源设备不适用逻辑ID时) \n
    * @ref 其它 有效值
    * @param[out] *pLifeTime 报文剩余有效期
    * @param[out] rxBuf[] 收到的应用报文数组
    * @param[out] *pRxLen 收到的应用报文长度
    * @param[in] rxSize 接收应用报文的缓冲区（rxBuf）大小，应不小于可能收到的最长应用报文长度
    * @return 函数执行结果
    * - 1 成功
    * - 0 失败(输入非法)
    * @note
    * 每次调用获得一条完整的应用报文
    * 应用每周期应持续调用本函数直到获得的报文长度 *pRxLen == 0
    */
    CM_UINT8 MSCP_AppRecvMsg(IN ENUM_MSCP_MSG_CHN_T ch,
        OUT CM_UINT16* pSrcName, OUT CM_UINT16* pSrcLogicID, OUT CM_UINT8* pLifeTime,
        OUT CM_UINT8* rxBuf, OUT CM_UINT32* pRxLen, IN CM_UINT32 rxSize);

    /**
    * @brief 发送应用报文
    * @param[in] ch 指定发送通道 \n
    * @ref ENUM_MSG_OUTNET_SAFE 外网安全通信通道 \n
    * @ref ENUM_MSG_INNET_SAFE  内网安全通信通道 \n
    * @ref ENUM_MSG_INNET_RAW   内网透传通信通道 \n
    * @ref 其它 预留
    * @param[in] dstName 目的设备ID
    * @param[out] dstLogicID 目的逻辑ID \n
    * @ref 0 默认值(源设备不适用逻辑ID时) \n
    * @ref 其它 有效值
    * @param[out] txBuf[] 发送的应用报文数组
    * @param[out] txLen 发送的应用报文长度
    * @return 函数执行结果
    * - 1 成功
    * - 0 失败(输入非法)
    * @note
    * 每次调用发送一条完整的应用报文
    * 应用每周期可多次调用本函数从而发送多个应用报文，
    * 注意总发送长度不要超过周期通信总量限制
    */
    CM_UINT8 MSCP_AppSendMsg(IN ENUM_MSCP_MSG_CHN_T ch, IN CM_UINT16 dstName,
        IN CM_UINT16 dstLogicID, IN const CM_UINT8* txBuf, IN CM_UINT32 txLen);

    /**
    * @brief 断开指定的外网安全通信链接
    * @param[in] devID 设备ID
    * @param[in] logicID 逻辑ID
    * @return 执行结果
    * - 1 成功
    * - 0 失败
    */
    CM_UINT8 MSCP_Outnet_Disconnect(CM_UINT16 devID, CM_UINT16 logicID);
	
	/**
	* @brief 接收外网透传报文
	* @param rxBuf 收到的应用报文数组
	* @param rxSize 接收应用报文的缓冲区（rxBuf）大小，应不小于可能收到的最长应用报文长度
	* @return 收到的应用报文长度
	* @details
	* 每次调用获得一条完整的应用报文
	* 每周期应持续调用本函数直到获得的报文长度 *pRxLen == 0
	*/
	CM_UINT32 MSCP_OutnetRaw_AppRecv(OUT CM_UINT8* rxBuf, IN CM_UINT32 rxSize);
	
	/**
	* @brief 发送外网透传报文
	* @param txBuf 发送的应用报文数组
	* @param txLen 发送的应用报文长度
	* @param dstName 目的设备ID
	* @param dstLogicID 目的逻辑ID
	* @param type 类型
	* @return 函数执行结果
	* - 1 成功
	* - 0 失败(输入非法)
	* @details
	* 每次调用发送一条完整的应用报文
	* 每周期可多次调用本函数从而发送多个应用报文，
	* 注意总发送长度不要超过周期通信总量限制*/
	CM_UINT8 MSCP_OutnetRaw_AppSend(IN const CM_UINT8* txBuf, IN CM_UINT32 txLen, IN CM_UINT16 dstName, IN CM_UINT16 dstLogicID, CM_UINT16 type);
    /**
    * @brief 接收内网透传报文
    * @param ch 通道ID
    * @param pSrcName 源设备ID
    * @param rxBuf 收到的应用报文数组
    * @param rxSize 接收应用报文的缓冲区（rxBuf）大小，应不小于可能收到的最长应用报文长度
    * @return 收到的应用报文长度
    * @details
    * 每次调用获得一条完整的应用报文
    * 每周期应持续调用本函数直到获得的报文长度 *pRxLen == 0
    */
    CM_UINT32 MSCP_InnetRaw_AppRecv(IN CM_INT32 ch, OUT CM_UINT16* pSrcName, OUT CM_UINT8* rxBuf, IN CM_UINT32 rxSize);
    /**
    * @brief 快速接收内网透传报文
    * @param ch 通道ID
    * @param pSrcName 源设备ID
    * @param rxBuf 收到的应用报文数组二级指针
    * @return 收到的应用报文长度
    * @details
    * 每次调用获得一条完整的应用报文
    * 每周期应持续调用本函数直到获得的报文长度 *pRxLen == 0
    */
    CM_UINT32 MSCP_InnetRaw_AppRecv_Fast(IN CM_INT32 ch, OUT CM_UINT16* pSrcName, const OUT CM_UINT8** rxBuf);
    /**
    * @brief 接收内网透传辅助信息
    * @param ch 通道ID
    * @param MainInfoBuf 本机辅助信息数组指针
    * @param PeerInfoBuf 邻机辅助信息数组指针
    * @param rxSize		  接收缓冲区长度
    * @param PeerInfoLen 邻机辅助信息报文长度
    * @return 收到的本机辅助信息报文长度
    * @details
    * 每周期调用一次，可获得全部辅助信息，再根据对应长度（8字节或12字节）解析时间戳或序列号
    */
    CM_UINT32 MSCP_InnetRawHelpInfo_AppRecv(IN CM_INT32 ch, OUT CM_UINT8* MainInfoBuf,OUT CM_UINT8* PeerInfoBuf,IN CM_INT16 rxSize,OUT CM_UINT16 *PeerInfoLen);
    /**
    * @brief 发送内网透传报文
    * @param ch 通道ID
    * @param dstName 目的设备ID
    * @param txBuf 发送的应用报文数组
    * @param txLen 发送的应用报文长度
    * @return 函数执行结果
    * - 1 成功
    * - 0 失败(输入非法)
    * @details
    * 每次调用发送一条完整的应用报文
    * 每周期可多次调用本函数从而发送多个应用报文，
    * 注意总发送长度不要超过周期通信总量限制
    */
    CM_UINT8 MSCP_InnetRaw_AppSend(IN CM_INT32 ch, IN CM_UINT16 dstName, IN const CM_UINT8* txBuf, IN CM_UINT32 txLen);

    /*
	* @brief 获取上一周期的本系热备状态
	* @return 本系热备状态
	* - ENUM_2x2_OFFLINE 离线
	* - ENUM_2x2_PRE_MASTER 预升主
	* - ENUM_2x2_MASTER 主系
	* - ENUM_2x2_SLAVE 备系
	* @note
	* 宕机状态下应用逻辑不会被执行，
	* 所以应用本函数不可能返回“宕机”。
	* 其它状态下周期应用逻辑都会被执行，
	* 但只有“主系”状态下本机的输出才会被真实输出，
	* 在“离线”和“备系”状态下且本周期收到有效跟随数据时，
	* 将在周期应用逻辑执行之前进行跟随数据覆盖。
	*/
	ENUM_2x2_STATE_T MSCP_GetLastLocal2x2State(void);

	/**
	* @brief 获取对系上一周期的热备状态
	* @return 对系热备状态
	* - ENUM_2x2_SHUTDOWN 宕机
	* - ENUM_2x2_OFFLINE 离线
	* - ENUM_2x2_PRE_MASTER 预升主
	* - ENUM_2x2_MASTER 主系
	* - ENUM_2x2_SLAVE 备系
	* @note
	* 与对系通信中断时默认对系状态为“宕机”
	*/
	ENUM_2x2_STATE_T MSCP_GetLastPartner2x2State(void);

    /**
    * @brief 设置跟随数据
    * @param[in] Data[] 跟随数据数组
    * @param[in] Len 跟随数据长度
    * @return 函数执行结果
    * - 1 成功
    * - 0 失败(输入非法)
    * @note
    * 无论本系是否为主，应用都应当每周期设置一次跟随数据；
    * 本系非主时平台不会发送该数据，但会用于双系一致性的校验。
    * 跟随数据量最大为1024*1000字节。
    * @see :: APP_API_FollowUp
    */
    CM_UINT8 MSCP_SetFollowData(IN const CM_UINT8 Data[], IN CM_UINT32 Len);

    /**
    * @brief 获取系统周期号
    * @return 当前的系统周期号
    * @note
    * 一个固定周期自增的周期号；
    * 对于2x2系统，2x2双系的周期号会被自动同步到与主系一致。
    */
    CM_UINT32 MSCP_GetSysCount(void);

    /**
    * @brief 获取本机外网ID
    * @return 本机外网ID
    * @note 1字节类型+1字节ID，大端格式，来自INI配置文件。
    */
    CM_UINT16 MSCP_GetOutnetID(void);

    /**
    * @brief 获取本机内网ID
    * @return 本机内网ID
    * @note 1字节类型+1字节ID，大端格式，来自INI配置文件。
    */
    CM_UINT16 MSCP_GetInnetID(void);

    /**
    * @brief 获取板卡ID
    * @return 本机的板卡ID
    * @note 板卡ID的宏定义参见本文件头部
    */
    CM_UINT8 MSCP_GetBoardID(void);

    /**
	* @brief 获取CPUID
	* @return CPUID
	* @details
	* CPUID根据配置文件确定
	*/
    CM_UINT8 MSCP_GetCpuID(void);

    /**
    * @brief 获取平台软件版本号和MD5码
    * @param[out] version 软件版本号
    * @param[out] md5 软件md5码
    */
    void MSCP_GetBaseWareVer(OUT CM_UINT8 version[4]);

    /*注意CM_UINT64需要用%lld打印*/
    CM_UINT64 MSCP_GetTick(void);
    /**
    * @brief 获取UTC基准时间
    * @return 初始化记录UTC时间的us数
    * @details 从周期开始初始化固定值，不受时钟同步等操作的影响。
    */
    CM_UINT64 MSCP_GetUTCTick(void);
    /**
    * @brief 重写pSerial函数指针(串口扩展版使用),二次开发手册限制初始化时设置。
    */
    void MSCP_SetSerial(SERIAL_ID_FUNC p);
    /**
    * @brief 重写设备id和红蓝网通信情况。
    * @param p 注册的函数指针 取值范围(如果无需获取可以为NULL,如果获取则非空)
    */
    void MSCP_SetSrcId(STATUS_COMMUNICATION_FUNC p);
    /**
    * @brief 变量内存自检注册初始化
    * @param pMemAddr注册变量的首地址
    * 		 dataLen 注册变量的大小
    */
    void MSCP_MemCheck_Register(CM_UINT8 *pMemAddr,CM_UINT32 dataLen);

    /**
    * @brief 初始化协议参数
    * @param inParamLen 长度
    * 		 inParam 指针
    */
    void MSCP_ParamData(CM_UINT8* pParam,CM_UINT32 ParamLen);

    /**
    * @brief 设置内网协议p_gSfpInnetPara
    * @param p_gSfpInnetPara 指针
    */
    void MSCP_SetSfpInnetPara(CM_UINT8* pSfpInnetData);

    /**
    * @brief 初始化应用函数入口
    */
    void MSCP_SetAppFunc(pSetAppfunc pApp1, pSetAppfunc pApp2, pSetAppfunc pApp3, pSetAppfunc pApp4, pSetAppfunc pApp5);


	/**
	* @brief 获取CPU合计使用率
	* @return 返回CPU合计使用率，范围为0到100
	*/
	CM_FLOAT32 MSCP_GetCpuTotalUsage(void);

	/**
	* @brief 获取指定CPU使用率
	* @param 获取指定CPU使用率,值的范围为0到5
	* @return 返回指定CPU使用率，范围为0到100
	*/
	CM_FLOAT32 MSCP_GetCpuAppointUsage(CM_UINT8 CpuIndex);
	
	/**
	* @brief 获取板卡温度
	* @return 返回板卡温度
	*/
	CM_FLOAT64 MSCP_GetTemperature(void);

	/**
	* @brief 设置板卡温度范围
	* @param MinTemperature 最低温度
	* @param MinTemperature 最高温度
	* @return 函数执行结果
	* - 1 成功
	* - 0 失败
	*/
	CM_UINT8 MSCP_SetTemperature(CM_FLOAT32 MinTemperature , CM_FLOAT32 MaxTemperature);

    /**
    * @brief 记录日志（格式化字符串）
    * @param[in] fmt... 按格式化字符串描述的记录日志
    * @note 单条字符串的最大长度不超过1000字节
    */
#define MSCP_LogMsg(fmt, ...) MSCP_APP_LOG_MSG(__FILE__,__FUNCTION__,(CM_INT32)__LINE__,(fmt), ##__VA_ARGS__)
    /* 函数实现 */
    void MSCP_APP_LOG_MSG(IN const CM_CHAR *filename, IN const CM_CHAR *func, IN CM_INT32 line, IN const CM_CHAR* fmt, ...);

    /**
    * @brief 记录日志（二进制）
    * @param[in] buf[] 二进制日志数组
    * @param[in] len 二进制日志长度
    * @note 单条二进制日志长度不超过1024*50字节
    */
#define MSCP_LogBin(buf,len)  MSCP_APP_LOG_BIN(__FILE__,__FUNCTION__,(CM_INT32)__LINE__,(buf),(len))
    /* 函数实现 */
    void MSCP_APP_LOG_BIN(IN const CM_CHAR* filename, IN const CM_CHAR* func, IN CM_INT32 line, IN const CM_UINT8* Buf, IN CM_UINT32 Len);
    /**
    * @brief 内网透传解析功能-注册函数
    * @param RAW_ALGORITHM *p_Fun 注册函数
    * @return 无
    * @details 注册数组，需要注册8个函数，如果不需要解析请注册NULL。
    * @details 此函数应尽快执行完毕（耗时可能会引起丢包），并且不允许加打印。
    */
    void MSCP_InnetRaw_analysisFun(RAW_ALGORITHM *p_Fun);
    /**
    * @brief 获取本机通用IP地址
    * @param 无
    * @return IP地址 inet_addr
    * @details 此函数仅允许在初始化阶段使用
    */
    CM_UINT32 MSCP_GetLocal_ComIp(void);
    /**
    * @brief 获取本机通用扩展IP地址
    * @param 无
    * @return IP地址
    * @details 此函数仅允许在初始化阶段使用
    */
    CM_UINT32 MSCP_GetLocal_ComExtendIp(void);
	/**
	* @brief 应用2取交换
	* @param pMyData 本机数据指针
	* @param DataLen 本机数据长度
	* @param pPeerData 邻机数据指针
	* @param DataSize 邻机数据缓冲区大小
	* @return 收到的邻机数据长度
	*/
	CM_INT32 MSCP_APP_2oo2(IN const CM_UINT8 * pMyData, IN CM_INT32 DataLen, OUT CM_UINT8 * pPeerData, IN CM_UINT32 DataSize);
	/**
	* @brief 获取板卡运行状态
	* @return 板卡运行状态
    * - ENUM_BOARDSTATE_ERROR = 0,   未知状态
	* - ENUM_BOARDSTATE_RUN = 1,     运行状态
	* - ENUM_BOARDSTATE_EXIT = 2,    退出运营状态
	* - ENUM_BOARDSTATE_UPDATE = 3,  故障可更新文件状态
	* - ENUM_BOARDSTATE_DEFAULT = 4, 故障不可更新文件状态
	*/
	ENUM_BOARD_STATE_T MSCP_GetBoardState(void);

	/**
	* @brief 设置板卡运行状态
	* @param state 板卡运行状态
    * - ENUM_BOARDSTATE_ERROR = 0,   未知状态
	* - ENUM_BOARDSTATE_RUN = 1,     运行状态
	* - ENUM_BOARDSTATE_EXIT = 2,    退出运营状态
	* - ENUM_BOARDSTATE_UPDATE = 3,  故障可更新文件状态
	* - ENUM_BOARDSTATE_DEFAULT = 4, 故障不可更新文件状态
	*/
	void MSCP_SetBoardState(ENUM_BOARD_STATE_T state);

	/**
	* @brief 应用将应用版本号写入平台
	* @param APP_VERSION 版本号 取值范围:非空
	*/
    void MSCP_SetAppVersion(IN CM_UINT8 APP_VERSION[]);

    /**
    * @brief 应用将FS版本号写入平台
    * @param FS_VERSION FS数据版本号 取值范围:非空
    */
    void MSCP_SetFsVersion(IN CM_UINT8 FS_VERSION[]);

    /**
    * @brief 应用将Scade版本号写入平台
    * @param SCADE_VERSION Scade数据版本号 取值范围:非空
    */
    void MSCP_SetScadeVersion(IN CM_UINT8 SCADE_VERSION[]);

    /**
    * @brief 获取平台暂存的红蓝网设备信息
    * @param RedBuf 红网缓冲区 取值范围:非空
    * @param BlueBuf 篮网缓冲区 取值范围：非空
    * @details RCI用于获取平台暂存的红蓝网设备信息,长度大于等于16*18
    */
    void MSCP_GetRciTempBuf(OUT CM_UINT16* RedBuf, OUT CM_UINT16* BlueBuf);

    /**
    * @brief 获得是否为在因为切系后,主系降为离线的3周期内的标志。
    * @return 是否为切系后的5周期
    * - 0 不在切系后的5周期内
    * - 1 在切系后的5周期内
    * @details 此切系状态用于应用获取到离线时判断原因
    */
    CM_UINT8 MSCP_2x2_GetSwitchFlag(void);

    /**
	* @brief 应用配置ip、端口、使能等可配置变量
	* @param app_data 应用配置结构体 取值范围:非空
	* @details 此配置用来代替main_base.ini
	*/
    void MSCP_Set_APP_ConfigData(STRU_APP_CFG_T *app_data);

    /**
    * @brief 获取安全通道链路状态
    * @return 安全通道链路状态
    */
    CM_UINT8 MSCP_GetLnkStatus(CM_UINT8 destType,CM_UINT8 destId,CM_UINT16 logId);

    /**
    * @brief 读取插箱板卡id
    * @return 返回插箱板卡id 取值范围：0~0xFF
    * @details 其中高4位bits为插箱id 低四位bits为板卡id
    */
    CM_UINT8 MSCP_GetDrvBoardID(void);
	
	/**
	* @brief 接收外网心跳报文（自检信息）
	* @param rxBuf 收到的应用报文数组
	* @param rxSize 接收应用报文的缓冲区（rxBuf）大小，应不小于可能收到的最长应用报文长度
	* @return 收到的应用报文长度
	* @details
	* 每次调用获得一条完整的应用报文
	* 每周期应持续调用本函数直到获得的报文长度 *pRxLen == 0
	*/
	CM_UINT32 MSCP_OutNetHeart_AppRecv(OUT CM_UINT8* rxBuf, IN CM_UINT32 rxSize);

	/**
	* @brief 获取两系输入io状态
	* @return ENUM_CM_TRUE 成功，ENUM_CM_FALSE 失败
	*/
	ENUM_CM_RETURN MSCP_2x2_GetLastIoInput(OUT CM_UINT8* ioInput,CM_UINT16 size);
	/**
	* @brief 设置捕获信号(初始化调用)
	*/
	void MSCP_SetSignal(CM_INT32 SIGNAL);
	/**
	* @brief 设置应用运行步骤(周期中调用)
	*/
	void MSCP_SetAppCheck(CM_INT32 appCheck);
#ifdef __cplusplus
}
#endif
#endif
