/* 104专用无状态编解码:APCI检查及I/S/U帧构造;ASDU公共头见IEC60870_Codec。 */ #ifndef IEC104_CODEC_H #define IEC104_CODEC_H #include "IEC104_Types.h" #ifdef __cplusplus extern "C" { #endif /* IEC-104 帧类型。 */ typedef enum { IEC104_FRAME_TYPE_I = 0, IEC104_FRAME_TYPE_S, IEC104_FRAME_TYPE_U } IEC104_FrameType_t; /* U 帧控制域首字节;ACT 为请求,CON 为对应确认。 * 编码入口用int接收待校验值,不依赖本枚举的存储宽度。 */ typedef enum { IEC104_U_STARTDT_ACT = 0x07, IEC104_U_STARTDT_CON = 0x0B, IEC104_U_STOPDT_ACT = 0x13, IEC104_U_STOPDT_CON = 0x23, IEC104_U_TESTFR_ACT = 0x43, IEC104_U_TESTFR_CON = 0x83 } IEC104_UFrameFunction_t; /* 完整APDU中APCI控制信息及ASDU位置的解析结果;各字段是否有效由frame_type决定。 */ typedef struct { IEC104_FrameType_t frame_type; /* I、S或U帧 */ uint16_t send_number; /* I帧的N(S) */ uint16_t receive_number; /* I帧或S帧的N(R) */ uint8_t u_function; /* U帧功能码 */ const uint8_t *asdu; /* I帧中的ASDU首地址 */ uint16_t asdu_len; /* I帧中的ASDU长度 */ } IEC104_ApciInfo_t; /** * 功能:根据 IEC-104 控制域首字节识别 I、S 或 U 帧。 * 输入参数:control——控制域首字节。 * 输出参数:无。 * 返回值:对应的 IEC104_FrameType_t 帧类型。 * 说明:仅按控制域低位分类,不验证保留位、U功能码或帧长度;完整APCI检查由Parse_APCI执行。 */ extern IEC104_FrameType_t IEC104_Get_Frame_Type(uint8_t control); /** * 功能:检查完整APDU的外层长度和APCI控制域,解析控制信息及ASDU位置。 * 输入参数:frame——完整APDU首地址;frame_len——完整APDU长度。 * 输出参数:apci——解析成功时写入帧类型、序号、U功能码和ASDU位置。 * 返回值:解析成功返回1,否则返回0且不保证apci中的内容。 * 说明:I帧要求ASDU长度至少为IEC104_ASDU_HEADER_LEN,不足时返回0;不解析公共头字段或信息对象。 * apci->asdu直接指向frame内部,其有效期不超过frame缓冲区有效期。 */ extern int IEC104_Parse_APCI(const uint8_t *frame, uint16_t frame_len, IEC104_ApciInfo_t *apci); /** * 功能:根据发送序号、接收序号和ASDU构造一个完整的I帧APDU。 * 输入参数:buf——输出缓冲区;send_seq——N(S);recv_seq——N(R); * asdu——完整ASDU首地址;asdu_len——ASDU长度,范围为6..249。 * 输出参数:buf——成功时写入完整I帧。 * 返回值:成功返回APDU总长度,参数非法返回-1。 * 说明:调用方必须保证buf至少具有IEC104_APCI_LEN+asdu_len字节空间; * 本函数不读取或修改IEC104_LinkState_t。调用方须保存recv_seq,并在 * 完整发送后把它作为实际N(R)提交给链路状态。 */ extern int IEC104_Build_Iframe(uint8_t *buf, uint16_t send_seq, uint16_t recv_seq, const uint8_t *asdu, int asdu_len); /** * 功能:根据接收序号构造一个完整的S帧APDU。 * 输入参数:buf——输出缓冲区;recv_seq——待编码的N(R),范围为0..32767。 * 输出参数:buf——成功时写入6字节S帧。 * 返回值:成功返回IEC104_APCI_LEN,参数非法返回-1。 * 说明:调用方必须保证buf至少具有IEC104_APCI_LEN字节空间; * 本函数不读取或修改IEC104_LinkState_t。调用方须保存recv_seq,并在 * 完整发送后把它作为实际N(R)提交给链路状态。 */ extern int IEC104_Build_Sframe(uint8_t *buf, uint16_t recv_seq); /** * 功能:根据U帧功能码构造一个完整的U帧APDU。 * 输入参数:buf——输出缓冲区;function——待校验的整数功能码,只允许六种U帧功能值。 * 输出参数:buf——成功时写入6字节U帧,参数检查失败时不写入。 * 返回值:成功返回IEC104_APCI_LEN,参数或功能码非法返回-1。 * 说明:调用方必须保证buf至少具有IEC104_APCI_LEN字节空间; * buf非NULL且功能码合法时固定返回6,容量由调用方保证,本函数无法检查。 * function使用int,短枚举配置下也能拒绝0x107等非法值;调用方不要预先收窄未校验值。 * 本函数不处理U帧状态转换或网络发送。 */ extern int IEC104_Build_Uframe(uint8_t *buf, int function); #ifdef __cplusplus } #endif #endif /* IEC104_CODEC_H */