104 lines
4.6 KiB
C
104 lines
4.6 KiB
C
/* 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 */
|