feat(lib60870): 导入 IEC 60870-5-101/103/104 协议栈

- 从原工程 src/protocol/lib60870 完整复制(科大智能,2022)
- 9 个头文件 + 8 个源文件,~16K 行
- 新增 cbb_compat.h: u8/u16/u32/f32/BOOL 类型别名
- 新增 myIec60870.h: 聚合入口
- makefile: -include cbb_compat.h 注入类型定义
- makefile: -Wno-implicit-function-declaration (gb103.c 已知问题)
- copy_headers.sh: 注册 myIec60870.h
This commit is contained in:
ypc 2026-07-08 15:45:49 +08:00
parent 802e3c3f31
commit a0b85f4bba
22 changed files with 16117 additions and 1 deletions

View File

@ -69,5 +69,6 @@ copy_module "libcomm" "myComm.h"
# 协议模块protocol/ # 协议模块protocol/
# ================================================================ # ================================================================
copy_proto_module "libmodbus" "myModbus.h" copy_proto_module "libmodbus" "myModbus.h"
copy_proto_module "lib60870" "myIec60870.h"
echo "=== done ===" echo "=== done ==="

View File

@ -0,0 +1,33 @@
include ./../../../linux.mk
L := $(notdir $(realpath $(CURDIR)/..))
M := lib60870
O := $(LIB_REL)/$(M).a
S := $(SRC_ROOT_DIR)/$(L)/lib60870/src
I := -I$(SRC_ROOT_DIR)/$(L)/lib60870/inc
B := $(CURDIR)/$(M)/obj
SRCS := $(wildcard $(S)/*.c)
OBJS := $(patsubst $(S)/%.c, $(B)/%.o, $(SRCS))
F := $(C_FLAGS) $(I)
F += -include cbb_compat.h
F += -Wno-implicit-function-declaration
.PHONY: all
all:
@mkdir -p $(ROOT_DIR)/release/inc
@$(MAKE) $(O)
$(O): $(OBJS)
@mkdir -p $(dir $@)
$(AR) rcs $@ $^
@echo "[$(M)] built"
$(B)/%.o: $(S)/%.c
@mkdir -p $(dir $@)
$(CC) $(F) -c $< -o $@
.PHONY: clean
clean:
rm -rf $(B) $(O)
.PHONY: rebuild
rebuild: clean all

View File

@ -1,4 +1,4 @@
SUBDIRS := ./libmodbus SUBDIRS := ./libmodbus ./lib60870
define make_subdir define make_subdir
for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done
endef endef

View File

@ -0,0 +1,283 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: ASDU.h
: V1.0
: 20220407
:
: 101104ASUD域相关数据处理
:
:
1. : 20220407
:
*******************************************************************************/
#ifndef __ASDU_H
#define __ASDU_H
/**************************************文件包含*******************************/
#include <stdio.h>
#include "lib60870_common.h"
#include "lib60870_public.h"
#include "lib60870_process.h"
#include "gb101.h"
/**************************************宏定义*********************************/
#define MAX_FLOATYC_CNT 48
#define INTYC_MAX_CNT 80
#define MAX_Yx_CNT 127
#define MAX_Dd_CNT 48
#define MAX_Param_CNT 4
#define MAX_COS_CNT 60
/************************************数据结构定义*****************************/
typedef union
{
/*带品质描述词的单点信息*/
struct
{
unsigned char ucSPI: 1; /*0=开 1=合*/
unsigned char ucRES: 3; /*备用*/
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
unsigned char ucIV : 1; /*0=有效 1=无效*/
} SIQ;
/*带品质描述词的双点信息*/
struct
{
unsigned char ucDPI: 2; /*0=不确定或中间状态 1=确定状态开 2=确定状态合 3=不确定*/
unsigned char ucRES: 2; /*备用*/
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
unsigned char ucIV : 1; /*0=有效 1=无效*/
} DIQ;
/*品质描述词*/
struct
{
unsigned char ucOV : 1; /*0=未溢出 1=溢出*/
unsigned char ucRES: 3; /*备用*/
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
unsigned char ucIV : 1; /*0=有效 1=无效*/
} QDS;
/*继电保护设备事件的品质描述词*/
struct
{
unsigned char ucRES: 3; /*备用*/
unsigned char ucEI : 1; /*0=动作时间有效 1=动作时间无效*/
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
unsigned char ucIV : 1; /*0=有效 1=无效*/
} QDP;
/*带瞬变状态指示的值*/
struct
{
unsigned char ucI7 : 7; /*瞬变状态*/
unsigned char ucBS1: 1; /*0=动作时间有效 1=动作时间无效*/
} VTI;
/*单命令*/
struct
{
unsigned char ucSCS: 1; /*0=开 1=合*/
unsigned char ucRES: 1; /*备用*/
unsigned char ucQU : 5; /*0=无另外定义 1=短脉冲持续时间 2=长脉冲持续时间 3=持续输出*/
unsigned char ucSE : 1; /*0=执行 1=选择*/
} SCO;
/*双命令*/
struct
{
unsigned char ucDCS: 2; /*0=不允许 1=开 2=合 3=不允许*/
unsigned char ucQU : 5; /*0=无另外定义 1=短脉冲持续时间 2=长脉冲持续时间 3=持续输出*/
unsigned char ucSE : 1; /*0=执行 1=选择*/
} DCO;
/*步调节命令*/
struct
{
unsigned char ucRCS: 2; /*0=不允许 1=降一步 2=升一步 3=不允许*/
unsigned char ucQU : 5; /*0=无另外定义 1=短脉冲持续时间 2=长脉冲持续时间 3=持续输出*/
unsigned char ucSE : 1; /*0=执行 1=选择*/
} RCO;
/*初始化原因*/
struct
{
unsigned char ucUI7: 7; /*0=当地电源合上 1=当地手动复位 2=远方复位*/
unsigned char ucBS1: 1; /*0=未改变当地参数初始化 1=改变当地参数初始化*/
} COI;
/*设定命令限定词*/
struct
{
unsigned char ucQL: 7; /*0=缺省*/
unsigned char ucSE: 1; /*0=执行 1=选择*/
} QOS;
unsigned char ucBits;
} ASDU_CMD_T;
/**************************************数据声明******************************/
/**************************************内部函数声明***************************/
unsigned char DecodeASDUCheck(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_M_EI_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_IC_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_CI_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_CS_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_RP_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_TS_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_F_FR_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_SR_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_RR_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_RS_NA(CS10x *pstSelf);
unsigned char DecodeCheck_C_WS_NA(CS10x *pstSelf);
unsigned char DecodeCheck_M_SPDP_NA(CS10x *pstSelf);
unsigned char DecodeCheck_M_ME_NANBNC(CS10x *pstSelf);
unsigned char DecodeCheck_M_IT_NB(CS10x *pstSelf);
unsigned char DecodeCheck_M_IT_TC(CS10x *pstSelf);
unsigned char DecodeCheck_C_SCDC_NA(CS10x *pstSelf);
unsigned char DecodeCheck_M_FT_NA(CS10x *pstSelf);
unsigned char DecodeCheck_M_DPSP_TB(CS10x *pstSelf);
unsigned char DecodeCheck_F_SR_NA(CS10x *pstSelf);
unsigned char DecodeCheck_C_CD_NA(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_RS_NA_NANWANG(CS10x *pstSelf);
unsigned char DecodeCheck_C_WS_NA_YZ(CS10x *pstSelf);
unsigned char DecodeCheck_C_WS_NA_GH(CS10x *pstSelf, unsigned char *pucPayload);
unsigned char DecodeCheck_C_SP_NA(CS10x *pstSelf);
void Do_SetTime(CS10x *pstSelf, unsigned short usReason);
void Do_Summon(CS10x *pstSelf, unsigned short usReason);
void Do_DdSummon(CS10x *pstSelf, unsigned short usReason);
void Do_Reset_Process(CS10x *pstSelf, unsigned short usReason);
void Do_DataTest(CS10x *pstSelf, unsigned short usReason);
void Do_InitEnd(CS10x *pstSelf, unsigned short usReason);
void Do_Yx(CS10x *pstSelf, unsigned short usReason);
void Do_Yc(CS10x *pstSelf, unsigned short usReason);
void Do_DdNoTime(CS10x *pstSelf, unsigned short usReason);
void Do_DdWithTime(CS10x *pstSelf, unsigned short usReason);
void Do_YKPro(CS10x *pstSelf, unsigned short usReason);
void Do_SOE(CS10x *pstSelf);
void Do_FaultEvent(CS10x *pstSelf);
void Do_FilePro_Slave(CS10x *pstSelf, unsigned char ucType, unsigned char *pucBuf, unsigned short usFileDateLen);
void Do_FilePro_Master(CS10x *pstSelf, unsigned char ucType, unsigned char *pucBuf);
void Do_FilePro(CS10x *pstSelf, unsigned short usReason);
void Do_Anomaly(CS10x *pstSelf, unsigned short usReason);
void Do_ChgConst(CS10x *pstSelf, unsigned short usReason);
void Do_ReadConst(CS10x *pstSelf, unsigned short usReason);
void Do_ParamPreread(CS10x *pstSelf, unsigned short usReason);
void Do_ParamPreset(CS10x *pstSelf, unsigned short usReason);
unsigned short CS10x_Send_Yx(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_SummonYx(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_COS(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_Yc(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_SummonYc(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ChangeYc(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_SOE(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_FaultEvent(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_DdData(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_SummonDd_Data(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_TimeDd_Data(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_SynTime(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_Summon(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_DdSummon(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ResetProcess(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_DataTest(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_InitEnd(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_FilePro(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ChgConst(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ReadConst(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ParamPreread(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ParamPreset(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_Yk(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_DdSummon_Data(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_Anomaly(CS10x *pstSelf, unsigned int param);
unsigned short CS10x_Send_Update(CS10x *pstSelf, unsigned int uiParam);
void Do_Update(CS10x *pstSelf, unsigned short usReason);
unsigned short GetPayloadOffset(CS10x *pstSelf);
void CheckFileDiff(CS10x *pstSelf);
unsigned short DecodeAsduMember(CS10x *pstSelf, unsigned char * pucAsdu, unsigned short usAsduSz);
unsigned short GetTaskTItype(CS10x *pstSelf, unsigned short usDataType);
/************************************外部接口函数声明*************************/
extern unsigned short GB10x_EncodeAsdu(CS10xHandle_t pstSelf, unsigned char * pucBuf);
extern void DecodeAsduInfoObj(CS10x *pstSelf);
extern unsigned short EncodeAsdu(CS10x *pstSelf);
extern void DoAckFrame(CS10x *pstSelf);
/********************************文件传输接口**************************************/
void Revc_ReadFS_CallDir_S(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //召唤目录
void Revc_ReadFS_AckCallDir_M(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //召唤目录确认
void Revc_ReadFS_SelectFile_S(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件激活
void Revc_ReadFS_AckSelectFile_M(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件激活确认
void Revc_ReadFS_CallFileSeg_M(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件数据
void Revc_ReadFS_AckFileSeg_S(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件数据响应
void Recv_WriteFS_SelectFile_S(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet);
void Recv_WriteFS_AckSelectFile_M(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet);
void Recv_WriteFS_DownFileSeg_S(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet, unsigned short usFileDateLen);
void Recv_WriteFS_AckDownFileSeg_M(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet);
unsigned short Send_ReadFS_CallDir_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
unsigned short Send_ReadFS_AckCallDir_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
unsigned short Send_ReadFS_SelectFile_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
unsigned short Send_ReadFS_AckSelectFile_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
unsigned short Send_ReadFS_CallFileSeg_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
unsigned short Send_ReadFS_AckFileSeg_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
unsigned short Send_WriteFS_SelectFile_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
unsigned short Send_WriteFS_AckSelectFile_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
unsigned short Send_WriteFS_DownFileSeg_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
unsigned short Send_WriteFS_AckDownFileSeg_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
void Do_ObtainDelay(CS10x *pstSelf, unsigned short usReason);
unsigned short CS10x_Send_ObtainDelay(CS10x *pstSelf, unsigned int uiParam);
void Do_ParamRead_NanWang(CS10x *pstSelf, unsigned short usReason);
unsigned short CS10x_Send_ParamRead_NanWang(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ParamRdResponse_NanWang(CS10x *pstSelf, unsigned int uiParam);
unsigned short CS10x_Send_ParamSolidify_NanWang(CS10x *pstSelf, unsigned int uiParam);
void Do_ParamPreset_NanWang(CS10x *pstSelf, unsigned short usReason);
void DoParamSolidify_NanWang(CS10x *pstSelf, unsigned short usReason);
unsigned short CS10x_Send_ParamPreset_NanWang(CS10x *pstSelf, unsigned int uiParam);
void Do_ParamWrite_Nanwang(CS10x *pstSelf, unsigned short usReason);
unsigned short CS10x_Send_ParamWrite_Nanwang(CS10x *pstSelf, unsigned int uiParam);
#endif

View File

@ -0,0 +1,25 @@
/*
* cbb_compat.h CBB
*
* CBB lib60870使 u8/u16/u32/s16/s32/f32/BOOL/TRUE/FALSE
* / ostype.h
* gcc -include CBB
*/
#ifndef _CBB_COMPAT_H_
#define _CBB_COMPAT_H_
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef int16_t s16;
typedef int32_t s32;
typedef float f32;
typedef bool BOOL;
#define TRUE true
#define FALSE false
#endif /* _CBB_COMPAT_H_ */

View File

@ -0,0 +1,106 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: gb101.h
: V1.0
: 20220323
:
: gb101.c的头文件
:
:
1. : 20220323
:
******************************************************************************/
#ifndef __GB101_H
#define __GB101_H
/**************************************文件包含*******************************/
#include <stdlib.h>
#include <stdio.h>
#include "lib60870_common.h"
#include "lib60870_public.h"
#include "lib60870_process.h"
#include "Asdu.h"
/**************************************宏定义*********************************/
#define START_CODE_101_LONG 0x68 //101规约长帧头
#define START_CODE_101_SHORT 0x10 //101规约短帧头
#define TAIL_CODE_101 0x16 //101规约报文尾
#define HEAD_LEN_101 7 //101规约ASDU前的字节长度 包含控制域及2字节地址
#define SHORT_LEN_S 5 //公共地址单字节时101短帧长度
#define SHORT_LEN 6 //公共地址双字节时101短帧长度
#define HEAD_TAIL_LEN 6 //101规约长帧头尾总长度
#define HEAD_LEN 4 //101规约长帧头长度
#define RESET_LINK 0 //复位链路
#define TEST_LINK 2 //测试帧
#define ACK_LINK 0 //确认帧
#define DATA_SEND 3 //长帧的功能码
#define NONE_DATA 4 //无回答数据
#define REQUEST_LINK 9 //请求链路状态
#define LINKSTATUS 11 //请求链路状态回复帧
#define FCVOFF 0 //FCB位无效
#define FCVON 1 //FCB位有效
#define PRM_MASTER 1 //启动站 这里与主站 终端有区别
#define PRM_SLAVE 0 //从动站 这里与主站 终端有区别
#define WAITTIME_101 10000 //短帧等待最大超时时间
#define TIMEOUT 3000 //101短帧超时重发时间
#define RESENDCNT_MAX 5 //重发次数
#define REINITTIME 300000 //5min重发初始化
/************************************数据结构定义*****************************/
/**
* @brief 101
*/
typedef union
{
struct //上行 低位在上
{
unsigned char FC : 4;
unsigned char DFC : 1;
unsigned char RES : 1;
unsigned char PRM : 1;
unsigned char DIR : 1;
} bits_up;
struct //下行
{
unsigned char FC : 4;
unsigned char FCV : 1;
unsigned char FCB : 1;
unsigned char PRM : 1;
unsigned char DIR : 1;
} bits_down;
unsigned char control;
} CONTROL101;
/**************************************数据声明******************************/
/**************************************内部函数声明***************************/
char GB101_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen);
void GB101_LongFrame(CS10xHandle_t pstSelf, unsigned char *pucFrameStart);
void GB101_ShortFrame(CS10xHandle_t pstSelf, unsigned char *pucFrameStart);
char GB101_EncodeFrame(CS10xHandle_t pstSelf);
char GB101_EncodeOther(CS10xHandle_t pstSelf);
void GB101_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap);
void GB101_Resend(CS10xHandle_t pstSelf, unsigned short usGap);
void GB101_Link_Init(CS10xHandle_t pstSelf, unsigned short usGap);
unsigned short GB101_EncodeFrameHead(CS10xHandle_t pstSelf, VIec101Frame * pstFrame);
void GB101_EncodeFrameTail(CS10xHandle_t pstSelf, VIec101Frame *pstFrame);
void GB101_Summon(CS10xHandle_t pstSelf);
void GB101_TimeSyn(CS10xHandle_t pstSelf);
void GB101_Heart(CS10xHandle_t pstSelf, unsigned short usGap);
void GB101_SendAck(CS10xHandle_t pstSelf);
void GB101_SendLinkStatus(CS10xHandle_t pstSelf);
void GB101_SendResetLink(CS10xHandle_t pstSelf);
void GB101_SendRequestLink(CS10xHandle_t pstSelf);
void GB101_SendTestLink(CS10xHandle_t pstSelf);
unsigned char GB101_Control(CS10xHandle_t pstSelf, unsigned char ucPRM, unsigned char ucFCV, unsigned char ucFC);
/************************************外部接口函数声明*************************/
extern void CS10x_101Init(CS10xHandle_t pstSelf, CS10x_SendCb cb, void *arg, CS10x_Type enType);
#endif

View File

@ -0,0 +1,353 @@
/*
* IEC103Type.h
*/
#ifndef IEC103TYPE_H_
#define IEC103TYPE_H_
//#include "ostype.h"
#include "lib60870_common.h"
typedef enum
{
CS103_TYPE_S = 0, /*CS103 从*/
CS103_TYPE_M, /*CS103 主*/
}CS103_Type;
enum ASDU_TYPE
{
ASDU_1 = 0x01,
ASDU_2 = 0x02,
ASDU_10 = 0x0A,
ASDU_40 = 0x28,
ASDU_41 = 0x29,
ASDU_42 = 0x2A,
ASDU_43 = 0x2B,
ASDU_44 = 0x2C,
ASDU_45 = 0x2D,
ASDU_46 = 0x2E,
ASDU_50 = 0x32,
};
enum CMD_SEND
{
CMD_RESET_CON = 1,
CMD_RESET_NUM,
CMD_RESET_TIMESTAMP, //对时
CMD_RESET_EVENT, //复归命令
CMD_SETTING_DOWNLOAD, //定值下载
CMD_SETTING_MODIFY, //定值修改
CMD_YK, //遥控功能
CMD_GET_ALL,
CMD_GET_DATA_LV1, //获取一级数据
CMD_GET_DATA_LV2, //获取二级数据
CMD_GET_SINGLE_SETTING_VALUE, //获取单个条目值
CMD_GENERAL_READ_YX_GROUP_VALUE,
CMD_GENERAL_READ_YC_GROUP_VALUE,
};
//标志位在报文中的位置
#define CODE_POSI 4 //控制域
#define TYP_POSI 6 //类型标识
#define VSQ_POSI 7 //可变结构限定词
#define COT_POSI 8 //传送原因
#define ADDR_POSI 9 //设备地址
#define FUN_POSI 10 //功能类型
#define INF_POSI 11 //信息序号
#define RII_POSI 12 //返回信息标识符
#define DPI_POSI 12 //双点信息
#define RET_POSI 13 //相对时间 表示装置启动到该元件动作的相对时间,毫秒
#define FAN_POSI 15 //故障序号
#define ASDU_1_TIMESTAMP 13 //ASDU1中四字节时间起始位置
#define ASDU_2_TIMESTAMP 17 //ASDU2中四字节时间起始位置
#define GROUP_POSI 14 //组号
#define TNTRY_POSI 15 //条目号
#define KOD_POSI 16 //描述的类别
#define GDD_POSI 17 //通用分类数据描述
#define GID_POSI 20 //通用分类标识数据
#define NGD_POSI 13 //通用分类数据集数目
#define START_10H 0x10 //固定长度报文启动字符
#define START_68H 0x68 //可变长度报文启动字符
#define END_16H 0x16 //结束字符
#define FCB_1 0x20 //帧计数位
#define FCV_1 0x10 //帧计数有效位
#define ACD_1 0x20 //有一级数据上送
#define PRA_1 0x40 //启动报文位 主到从
#define KOD_1 0x01 //描述类别 1为实际值
//功能码定义
#define FNA_S2C_RESET_CON 0 //复位通信功能码
#define FNA_S2C_RESET_NUM 7 //复位帧计数位功能码
#define FNA_S2C_POSTDATA_3 3 //传送数据(发送/确认帧)
#define FNA_S2C_POSTDATA_4 4 //传送数据(发送/无回答帧)
#define FNA_S2C_GETDATA_LV1 10 //召唤一级数据功能码
#define FNA_S2C_GETDATA_LV2 11 //召唤二级数据功能码
//ASDU号定义
#define ASDU6_TIMESTAMP 6 // 对时
#define ASDU7_GETALL 7 // 总召唤,遥信
#define ASDU20_RESET 20 // 复归
#define ASDU21_GETGROUP 21 // 总召唤,要测
#define ASDU10_SETTING 10 // 定值
#define ASDU20_RESET 20 // 复归
#define ASDU21_GETGROUP 21 // 总召唤,遥测
#define ASDU60 60 // 遥控
//COT传送原因定义
//控制方向
#define COT_S2C_TIMESTAMP 8 //时间同步
#define COT_S2C_GETALL_START 9 //总查询(总召唤)的启动
#define COT_S2C_REMOTE 0x0c //远方操作
#define COT_S2C_COMMON_ORDER 0x14 //一般命令
#define COT_S2C_GENERAL_WRITE 0x28 //通用分类写命令
#define COT_S2C_GENERAL_READ 0x2A //通用分类读命令
//FUN定义
#define FUN_GLB 0xFF //全局功能类型
#define FUN_GEN 0xFE //通用分类服务功能类型
//INF定义
#define INF_RESET_ORDER 0x13 //复归命令,所有装置相同
#define INF_READ_GROUP 0xF1 //读一个组的全部条目的值或者属性
#define INF_READ_EBTRY 0xF4 //读一个条目的值或者属性
#define INF_CONFIRM_WRITE 0xF9 //带确认的写条目
#define INF_EXEC_WRITE 0xFA //带执行的写条目
#define MAX_SIZE 1024
typedef struct {
u8 fcb; // 桢记数位
u8 fcv; // 桢记数有效位
} IEC103CodeS2C;
typedef union
{
u32 uValue;
f32 fValue;
u8 buf[4];
}UnionConvert4Byte;
typedef union
{
s16 value;
u16 uValue;
u8 buf[2];
}UnionConvert2Byte;
typedef struct
{
//通用分类标识序号GIN
u8 groupNo; //组号
u8 entryNo; //条目号
//描述的类别KOD
u8 kod; //1为实际值
//通用分类数据描述GDD
u8 datatype; //数据类型
u8 datasize; //数据宽度
u8 number:7, //数目
cont:1; //后续状态位
}stDataUnit; //通用分类数据单元
typedef struct
{
u16 msec; //毫秒
u8 min:6, //分钟
res1:1, //备用
iv:1; //IV=0为有效 =1为无效
u8 hour:7, //小时
su:1; //su夏时制标志
u8 day:5, //日
dayofweek:3; //未采用
u8 month:4, //月
res2:4; //备用
u8 year:7, //年
res3:1; //备用
}stTime7Byte;
// 带品质描述词的被测量(MEA)
typedef struct {
union {
s16 mval:13, // 带符号规一化定点数最高位符合位数据位占12位
res:1, // 备用位:未用(常为0)
er:1, // 差错位:0-有效1-无效
ov:1; // 溢出位:0-无溢出1-溢出
s16 wVal;
}mea;
}MEA;
/**
* \brief GetLayerSt
* \param
*
* \return
*/
typedef s32 (*CS103_SendCb) (u8 *buf, u16 usLen, void *arg);
/**
* \brief SetValue
* \param
*
* \return
*/
typedef s32 (*CS103_SetValue) (u8 ucFun, u8 ucInf, f32 fVal, void *pParam);
/**
* \brief SetStatus
* \param
*
* \return
*/
typedef s32 (*CS103_SetStatus) (u8 ucFun, u8 ucInf, u8 ucSt, void *pParam);
/**
* \brief AddSOE SOE信息
* \param
*
* \return
*/
typedef s32 (*CS103_AddSOE) (u8 ucFun, u8 ucInf, u8 ucSt, stTime7Byte *pTime, void *pParam);
typedef struct {
void *pUsrData; /*用户自定义数据接口*/
u16 usFirstNum;
u16 usTaskID;
VFLAGS stTaskFlags;
IEC103CodeS2C stIEC103CodeS2C; /*103控制域主到从*/
u8 ucAddr; /*从站地址*/
u8 ucReSend_Num; /*重发次数*/
u16 usReSend_Gap; /*重发间隔*/
u32 ulSummon_Gap; /*总召间隔*/ //参数关联
u32 ulSyn_Gap; /*同步间隔*/ //参数关联
// u32 ulHeart_Gap; /*心跳间隔*/ //参数关联
u32 ulSend_Gap; /*数据发送间隔参数*/
// u32 ulHeart_Tcn; /* 心跳累计时间计数 */
u32 ulSummon_Tcn; /* 定时总招时间计数 */
u32 ulTimeSyn_Tcn; /* 定时对时时间计数 */
u8 usResend_Ncn; /* 重发次数计数 */
u16 usResend_Tcn; /* 重发间隔时间计数 */
BOOL bIsResetConEnd; /*复位通信*/
BOOL bIsResetNumEnd; //复位帧计数位
BOOL bIsGetAllEnd; //总召唤
u8 ucIDCount;
u8 ucYcGroupNum;
u8 ucYxGroupNum;
u8 ucGroupNo;
u8 ucEntryNo;
u8 ucYkFun;
u8 ucYkInf;
u8 ucYkSE;
u8 ucYkACT;
u8 ucYkDCS;
u8 ucYkQU;
CS10x_Send_Cb SendCb; /*数据发送接口*/
CS10x_GetTime GetTime; /*获取事件*/
/*对外提供数据*/
CS103_SetValue SetValue; /*规约更新应用数据*/
CS103_SetStatus SetStatus; /*规约更新应用状态*/
CS103_AddSOE AddSOE; /*添加SOE信息*/
struct VCommBuf stRecvBuf; /*接收数据缓冲区*/
struct VCommBuf stSendBuf; /*发送数据缓冲区*/
}CS103;
/**
* @brief
*
* @param self
* @param pstParam
*/
void CS103_SetAddr(CS103 *self, u8 ucAddr);
/**
* @brief
*
* @param self
* @param pstParam
*/
void CS103_SetSummonGap(CS103 *self, u32 ulGap);
/**
* @brief
*
* @param self
* @param pstParam
*/
void CS103_SetSynTimeGap(CS103 *self, u32 ulGap);
/**
* @brief 101
* @param self
* @param pstParam
*/
void CS103_ResendGap(CS103 *self, u16 usGap);
/**
* @brief 101
* @param self
* @param pstParam
*/
void CS103_ResendCnt(CS103 *self, u8 ucCnt);
/**
* @brief
*
* @param self
* @param cb
*/
void CS103_GetTimeHandler(CS103 *self, CS10x_GetTime cb);
/**
* @brief
*
* @param self
* @param cb
*/
void CS103_SetValueHandler(CS103 *self, CS103_SetValue cb);
/**
* @brief
*
* @param self
* @param cb
*/
void CS103_SetStatusHandler(CS103 *self, CS103_SetStatus cb);
/**
* @brief SOE处理函数
*
* @param self
* @param cb
*/
void CS103_AddSOEHandler(CS103 *self, CS103_AddSOE cb);
CS103 *CS103_Init(CS103_SendCb cb, void *arg, CS103_Type type);
void CS103_Destory(CS103 *self);
BOOL CS103_DoRecv(CS103 *self, u8 *pBuf, u16 usLen);
void CS103_TimerHandle(CS103 *self, u16 usGap);
#endif /* IEC103TYPE_H_ */

View File

@ -0,0 +1,75 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: gb104.h
: V1.0
: 20220323
:
: gb104.c的头文件
:
:
1. : 20220323
:
******************************************************************************/
#ifndef __GB104_H
#define __GB104_H
/**************************************文件包含*******************************/
#include <stdlib.h>
#include <stdio.h>
#include "lib60870_common.h"
#include "lib60870_public.h"
#include "lib60870_process.h"
#include "Asdu.h"
/**************************************宏定义*********************************/
#define START_CODE 0x68
#define FRM_I 0
#define FRM_S 1
#define FRM_U 3
#define MAX_FRAME_COUNTER 0x7fff
#define COUNTER_LIMIT 0x8000
#define STARTDT_ACT 0x07
#define STARTDT_CON 0x0B
#define STOPDT_ACT 0x13
#define STOPDT_CON 0x23
#define TESTFR_ACT 0x43
#define TESTFR_CON 0x83
#define T0_TimeHandle 0
#define T1_TimeHandle 1
#define T2_TimeHandle 2
#define T3_TimeHandle 3
/************************************数据结构定义*****************************/
/**
* @brief
*/
/**************************************数据声明******************************/
/**************************************内部函数声明***************************/
char GB104_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen);
void GB104_Preprocessor(CS10xHandle_t pstSelf);
void DoSFrame(CS10xHandle_t pstSelf);
void DoUFrame(CS10xHandle_t pstSelf);
char GB104_EncodeFrame(CS10xHandle_t pstSelf);
char GB104_EncodeOther(CS10xHandle_t pstSelf);
unsigned short GB104_EncodeApci(CS10xHandle_t pstSelf, unsigned char ucFrameType, VIec104Frame * pstFrame);
void GB104_EncodeApduLen(CS10xHandle_t pstSelf, VIec104Frame * pstApdu);
void GB104_FrameTimerHdl(CS10xHandle_t pstSelf, VIec104Frame * pstApdu);
void GB104_SendAck(CS10xHandle_t pstSelf);
void SendUFrame(CS10xHandle_t pstSelf, unsigned char ucType);
void StopTimer(CS10xHandle_t pstSelf, unsigned short usTimerId);
void StartTimer(CS10xHandle_t pstSelf, unsigned short usTimerId);
void GB104_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap);
bool Check_IEC_104(unsigned char* pstBuf, unsigned short uslen);
/************************************外部接口函数声明*************************/
extern void CS10x_104Init(CS10xHandle_t pstSelf, CS10x_SendCb cb, void *arg, CS10x_Type enType);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
#ifndef __LIB60870_INC_H__
#define __LIB60870_INC_H__
#include <stdint.h>
#include <stdbool.h>
#include <string.h> //字符串处理
#include <stdio.h>
#define IEC_LOBYTE(w) ((unsigned char)(w))
#define IEC_HIBYTE(w) ((unsigned char)((unsigned short)(w) >> 8))
#define IEC_MAKEWORD(low, high) ((unsigned short)((unsigned char)(low) | (((unsigned short)((unsigned char)(high))) << 8)))
#ifndef IEC_PRINT
#define IEC_PRINT(fmt, args...)
#endif
#endif

View File

@ -0,0 +1,47 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: lib60870_process.h
: V1.0
: 20220407
:
: lib60870_process.c的头文件 101104
:
:
1. : 20220407
:
******************************************************************************/
#ifndef __LIB60870_PROCESS_H
#define __LIB60870_PROCESS_H
/**************************************文件包含*******************************/
#include <stdlib.h>
#include <stdio.h>
#include "lib60870_common.h"
#include "Asdu.h"
/**************************************宏定义*********************************/
/************************************数据结构定义*****************************/
/**
* @brief
*/
/**************************************数据声明******************************/
/**************************************内部函数声明***************************/
/************************************外部接口函数声明*************************/
extern void CheckUpdate_SoeEvent(CS10xHandle_t pstSelf);
extern void CheckSOE_SendInfo(CS10xHandle_t pstSelf);
extern void CheckFaultEvent_SendInfo(CS10xHandle_t pstSelf);
extern void CheckTimeDd_SendInfo(CS10xHandle_t pstSelf);
extern void CheckDiturbYc_SendInfo(CS10xHandle_t pstSelf);
extern void CheckUpdate_DiturbYcEvent(CS10xHandle_t pstSelf);
extern void CS10x_M_Scheduled(CS10xHandle_t pstSelf, unsigned short usGap);
extern void CS10x_M_Finish(CS10xHandle_t pstSelf);
extern void PollFileTransTask(CS10xHandle_t pstSelf);
extern void CheckSummonSlaveDelay(CS10xHandle_t pstSelf, unsigned short usGap);
#endif

View File

@ -0,0 +1,64 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: lib60870_public.h
: V1.0
: 20220407
:
: lib60870_public.c的头文件 101104
:
:
1. : 20220407
:
******************************************************************************/
#ifndef __LIB60870_PUBLIC_H
#define __LIB60870_PUBLIC_H
/**************************************文件包含*******************************/
#include <stdlib.h>
#include <stdio.h>
#include "lib60870_common.h"
/**************************************宏定义*********************************/
#define TAG_TPYE_BOOL 1 //布尔
#define TAG_TPYE_INT 2 //整形
#define TAG_TPYE_STR 4 //字符串
#define TAG_TPYE_UTINY 32 //无符号小整形
#define TAG_TPYE_SHORT 33 //短整形
#define TAG_TPYE_UINT 35 //无符号整形
#define TAG_TPYE_LONG 36 //长整形
#define TAG_TPYE_ULONG 37 //无符号长整形
#define TAG_TPYE_FLOAT 38 //单精度浮点
#define TAG_TPYE_DOUBLE 39 //双精度浮点
#define TAG_TPYE_TINY 43 //小整形
#define TAG_TPYE_USHORT 45 //无符号短整形
/************************************数据结构定义*****************************/
/**
* @brief
*/
/**************************************数据声明*******************************/
/**************************************内部函数声明***************************/
/************************************外部接口函数声明*************************/
extern unsigned char CS10x_SendTask(CS10xHandle_t pstSelf);
extern void SetSendTask(CS10xHandle_t pstSelf, unsigned int uiFlagNo, unsigned short usParam_low, unsigned short usParam_hig);
extern void SetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
extern unsigned int GetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
extern void ClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
extern int CheckClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
extern void ClearAllTaskflgs(CS10xHandle_t pstSelf);
extern unsigned char checksum_8(unsigned char *pucBuf, unsigned char ucLen);
extern int CheckParamTagAndLen(unsigned char ucTag, unsigned char ucLen);
extern unsigned char CP56Time2a_Pack2Buf(unsigned char *pucOutBuf, const __CP56Time2a *pstCp56);
extern unsigned char CP56Time2a_GetFromBuf(const unsigned char *pucInBuf, __CP56Time2a *pstCp56);
extern unsigned char IntBytes_Pack2Buf(unsigned char *pucOutBuf, unsigned int uiVal, unsigned char ucSize);
extern unsigned int IntBytes_GetFromBuf(const unsigned char *pucInBuf, unsigned char ucSize);
extern unsigned char Float_Pack2Buf(unsigned char *pucOutBuf, float fVal);
extern float Float_GetFromBuf(const unsigned char *pucInBuf);
extern unsigned char U16_Pack2Buf(unsigned char *pucOutBuf, unsigned short usVal);
extern unsigned short U16_GetFromBuf(const unsigned char *pucInBuf);
#endif

View File

@ -0,0 +1,75 @@
#ifndef _MD5_H_
#define _MD5_H_
#include <stdint.h>
typedef unsigned char *POINTER;
typedef uint16_t UINT2;
typedef uint32_t UINT4;
#define MD5_BIT16 0x10
#define MD5_BIT32 0x20
#define PROTO_LIST(list) list
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
typedef struct _MD5_CTX
{
UINT4 state[4];
UINT4 count[2];
unsigned char buffer[64];
} MD5_CTX;
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac);\
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000
void StartMD5(MD5_CTX * context);
void EncodeMD5(MD5_CTX * context, unsigned char * input, int len);
void GetMD5(MD5_CTX * context, unsigned char * result);
void GetMD5String(MD5_CTX * context, char * result, unsigned char mode);
#endif //_MD5_H_

View File

@ -0,0 +1,30 @@
/**
* @file myIec60870.h
* @brief IEC 60870-5-101/103/104
* @details 2022
*
* #include "myIec60870.h" IEC 60870
*/
#ifndef _MY_IEC60870_H_
#define _MY_IEC60870_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "lib60870_common.h" /* 公共数据结构、回调函数类型、CS10xHandle_t */
#include "lib60870_public.h" /* 任务管理、校验、CP56Time2a 编解码 */
#include "lib60870_process.h" /* 协议处理主流程 */
#include "lib60870_inc.h" /* 内部参数宏定义 */
#include "Asdu.h" /* ASDU 域数据编解码 */
#include "gb104.h" /* IEC 60870-5-104 协议实现 */
#include "gb101.h" /* IEC 60870-5-101 协议实现 */
#include "gb103.h" /* IEC 60870-5-103 协议实现 */
#include "md5.h" /* MD5 辅助 */
#ifdef __cplusplus
}
#endif
#endif /* _MY_IEC60870_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,747 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: gb104.c
: V1.0
: 20220323
:
: 104
:
:
1. : 20220323
:
*******************************************************************************/
/*************************************文件包含*********************************/
#include "gb104.h"
/***************************************static函数声明*******************************/
static unsigned char GB104_GetOneFrame(CS10xHandle_t pstSelf, unsigned char *pucFramePt, unsigned short usLastLen, unsigned short *pusSearchLen);
static void GB104_DecodeOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf) ; //解析单帧数据
/*************************************外部接口函数*****************************/
/**
* @brief 使
* @param[in] pstSelf-
* @param[in] cb-
* @param[in] arg-
* @param[in] enType-
* @param[out]
* @return
*/
void CS10x_104Init(CS10xHandle_t pstSelf, CS10x_SendCb pcb, void *arg, CS10x_Type enType)
{
pstSelf->eCS10x_Type = enType;
pstSelf->pfnSendCb = pcb;
pstSelf->pUsrData = arg;
pstSelf->pfnDecodeProcess = GB104_DecodeProcess;
pstSelf->pfnEncodeFrame = GB104_EncodeFrame;
pstSelf->pfnEncodeOther = GB104_EncodeOther;
pstSelf->pfnTimerManager = GB104_TimerOut;
if(enType == CS104_TYPE_M) //主模式注册轮询文件传输任务函数
{
pstSelf->pfnPollFileTransTask = PollFileTransTask;
pstSelf->uiTransTimerMax = TRANS_TIMEOUT_MAX / TRANS_SCH_GAP;
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USACT, 0); //此处需修改
}
/*默认初始化参数*/
pstSelf->usYcType = YC_TYPE_ME_NC;
pstSelf->usYxType = YX_TYPE_M_SP;
pstSelf->usYkType = YK_TYPE_C_SC;
pstSelf->usDdType = DD_TYPE_IT_NB;
pstSelf->usAsduPublicAddr = 1;
/*应用参数*/
pstSelf->stAppParameters.iSzOfLinkAddr = 2;
pstSelf->stAppParameters.iSzOfTypeId = 1;
pstSelf->stAppParameters.iSzOfVSQ = 1;
pstSelf->stAppParameters.iSzOfCOT = 2;
pstSelf->stAppParameters.iSzOfCA = 2;
pstSelf->stAppParameters.iSzOfIOA = 3;
pstSelf->stAppParameters.iLinkAddr = 1;
pstSelf->stAppParameters.iPublicAddr = 1;
/*总招对时时间*/
pstSelf->uiSummon_Gap = 300000; /*300秒*/
pstSelf->uiSyn_Gap = 300000; /*300秒*/
pstSelf->uiSend_Gap = 100; /*100ms*/
/*104*/
pstSelf->stAPCIParameters.iT0 = 10;
pstSelf->stAPCIParameters.iT1 = 12;
pstSelf->stAPCIParameters.iT2 = 8;
pstSelf->stAPCIParameters.iT3 = 15;
pstSelf->stAPCIParameters.iK = 12;
pstSelf->stAPCIParameters.iW = 8;
pstSelf->ucMultiFrameEn = 0; //104多帧发送使能
pstSelf->usFaultEnable = 1; //故障事件使能
pstSelf->ucSenSoeEa = 1; //发送SOE使能
pstSelf->ucSenCosEa = 1; //发送COS使能
pstSelf->ucYKEndFrame = 1; //遥控结束帧投入
pstSelf->ucOffLineSoeReissueEn = 1;//离线SOE补发使能
pstSelf->ucReadFileVSQ = 0; //读文件数据传输VSQ状态值
pstSelf->ucPreSetContType = 0; /* 默认为正常参数预置流程*/
#ifdef IEC_DEBUG_MSG
IEC_PRINT("Create IEC104 %s\n", enType == CS104_TYPE_M ? "主站" : "从站");
#endif
return;
}
/*************************************内部调用函数*****************************/
/**
* @brief 104
* @param[in] pstself-
* @param[in] pucBuf-
* @param[in] usLen-
* @param[out]
* @return
*/
char GB104_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen)
{
unsigned short usFramePos = 0; //一条报文中含有多帧104时表示每帧起始在报文中起始位置
unsigned short usSearchLen = 0; //本次查找返回的报文的长度(包括错误帧)
do //拆分多帧报文并解析
{
if(GB104_GetOneFrame(pstSelf, pucBuf + usFramePos, usLen - usFramePos, &usSearchLen)) //查找单帧报文
{
GB104_DecodeOneFrame(pstSelf, pstSelf->stPubBuf.pBuf); //解析单帧
usFramePos += usSearchLen; //报文解析起始位置更新
}
else
{
break;
}
} while(usFramePos < usLen); //越界判断
return 0;
}
/**
* @brief
* @param[in] pstSelf-
* @param[in] *pucFramePt-
* @param[in] usLastLen-
* @param[out] *pusSearchLen-
* @return 0 1
*/
static unsigned char GB104_GetOneFrame(CS10xHandle_t pstSelf, unsigned char *pucFramePt, unsigned short usLastLen, unsigned short *pusSearchLen)
{
if(Check_IEC_104(pucFramePt, usLastLen) == 0) //核对104报文
{
*pusSearchLen = usLastLen;
return 0;
}
else
{
pstSelf->stPubBuf.usWritePtr = pucFramePt[1] + 2; //单帧报文全部长度
memcpy(pstSelf->stPubBuf.pBuf, pucFramePt, pstSelf->stPubBuf.usWritePtr);//拷贝当前帧到公共缓存待解析
*pusSearchLen = pstSelf->stPubBuf.usWritePtr; //更新指针偏移
}
return 1;
}
/**
* @brief
* @param[in] pstSelf-
* @param[in] pucBuf-
* @param[in]
* @param[out]
* @return
*/
static void GB104_DecodeOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf) //解析单帧数据
{
unsigned char ucContolParam = 0;
StartTimer(pstSelf, T3_TimeHandle); // receive any I,U,S frame, to start T3
ucContolParam = pucBuf[2]; //控制帧 单帧报文第三位控制帧区分报文类型
switch(ucContolParam & 0x03)
{
case FRM_I:
GB104_Preprocessor(pstSelf); //I帧信息
break;
case FRM_S:
DoSFrame(pstSelf); //确认帧信息
break;
case FRM_U:
DoUFrame(pstSelf); //控制帧信息
break;
default:
GB104_Preprocessor(pstSelf);
break;
}
if(pstSelf->usSendNum > pstSelf->usAckSendNum && (pstSelf->usSendNum - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
{
pstSelf->bContinueSendFlag = 0;
StartTimer(pstSelf, T1_TimeHandle);
if((pstSelf->usSendNum - pstSelf->usAckSendNum) >= 2 * pstSelf->stAPCIParameters.iK)
{
pstSelf->ucInitStatus = 0;
if(pstSelf->pfnLinkClose)
{
pstSelf->pfnLinkClose(pstSelf->pUsrData);
}
}
}
else if((pstSelf->usSendNum < pstSelf->usAckSendNum) && (pstSelf->usSendNum + COUNTER_LIMIT - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
{
pstSelf->bContinueSendFlag = 0;
StartTimer(pstSelf, T1_TimeHandle);
if((pstSelf->usSendNum + COUNTER_LIMIT - pstSelf->usAckSendNum) >= 2 * pstSelf->stAPCIParameters.iK)
{
pstSelf->ucInitStatus = 0;
if(pstSelf->pfnLinkClose)
{
pstSelf->pfnLinkClose(pstSelf->pUsrData);
}
}
}
else
{
pstSelf->bContinueSendFlag = 1;
}
}
/**
* @brief 104
* @param[in] pstSelf-
* @param[out]
* @return
*/
void GB104_Preprocessor(CS10xHandle_t pstSelf)
{
unsigned short usAckNum = 0;
unsigned short usRecvNum = 0;
VIec104Frame *pstReceive = (VIec104Frame *)pstSelf->stPubBuf.pBuf;
/*未进行初始化时,不响应数据*/
if(pstSelf->ucInitStatus != 1)
{
if((pstSelf->eCS10x_Type == CS104_TYPE_S) || ((pstSelf->eCS10x_Type == CS104_TYPE_M) && (pstReceive->byASDU[0] != M_EI_NA)))
{
return;
}
}
StartTimer(pstSelf, T2_TimeHandle); // when Receve I frame, start T2
StopTimer(pstSelf, T1_TimeHandle); // stop T1
/*处理APCI信息 */
usAckNum = IEC_MAKEWORD(pstReceive->byControl3, pstReceive->byControl4);
usRecvNum = IEC_MAKEWORD(pstReceive->byControl1, pstReceive->byControl2);
usAckNum >>= 1; //最低位不是收发序列号
usRecvNum >>= 1;
pstSelf->usRecvNum = usRecvNum + 1;
pstSelf->usAckSendNum = usAckNum;
DoAckFrame(pstSelf);// 检查扰动遥测和SOE
// 判断终端是否需要给主站回复确认帧
if((pstSelf->usRecvNum - pstSelf->usAckRecvNum) > pstSelf->stAPCIParameters.iW)
{
SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0);
}
/*处理ASDU元素*/
DecodeAsduMember(pstSelf, pstReceive->byASDU, pstReceive->byAPDULen - 4);
/*处理ASDU信息体*/
DecodeAsduInfoObj(pstSelf);
return;
}
/**
* @brief 104S帧解析
* @param[in] pstSelf-
* @param[out]
* @return
*/
void DoSFrame(CS10xHandle_t pstSelf)
{
/*未进行初始化时,不响应数据*/
if(pstSelf->ucInitStatus != 1)
{
return;
}
unsigned short usAckNum = 0; //序列号
VIec104Frame *pstReceive = NULL;
pstReceive = (VIec104Frame *)pstSelf->stPubBuf.pBuf;
StopTimer(pstSelf, T1_TimeHandle);
usAckNum = IEC_MAKEWORD(pstReceive->byControl3, pstReceive->byControl4);
pstSelf->usAckSendNum = usAckNum >> 1;
if(pstSelf->eCS10x_Type == CS104_TYPE_S) //作为从站时
{
DoAckFrame(pstSelf);
if(pstSelf->pfnAckFrameNotification)
{
pstSelf->pfnAckFrameNotification();
}
}
return;
}
/**
* @brief 104U帧解析处理函数
* @param[in] pstSelf-
* @param[out]
* @return
*/
void DoUFrame(CS10xHandle_t pstSelf)
{
VIec104Frame *pstReceive = NULL;
pstReceive = (VIec104Frame *)pstSelf->stPubBuf.pBuf;
switch(pstReceive->byControl1)
{
case STARTDT_ACT: //收到启动链路
ClearAllTaskflgs(pstSelf);
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USTCON, 0);
SetSendTask(pstSelf, TSKID_InitFinish, COT_INIT, 0);
pstSelf->bContinueSendFlag = 1;
pstSelf->ucInitStatus = 1;
break;
case STOPDT_ACT: //收到断开链路
ClearAllTaskflgs(pstSelf);
SetSendTask(pstSelf, TSKID_StopLink, TSK_PARM_USTCON, 0);
break;
case TESTFR_ACT: //收到测试
/*仅初始化完成,响应测试帧*/
if(pstSelf->ucInitStatus == 1)
{
SetSendTask(pstSelf, TSKID_UTest, TSK_PARM_USTCON, 0);
}
break;
case STARTDT_CON: //启动链路响应
StopTimer(pstSelf, T0_TimeHandle);
pstSelf->bContinueSendFlag = 1;
ClearTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink); //主模式复位启动链路发送标志
break;
case STOPDT_CON: //断开链路响应
pstSelf->bContinueSendFlag = false;
StopTimer(pstSelf, T0_TimeHandle);
StopTimer(pstSelf, T1_TimeHandle);
StopTimer(pstSelf, T2_TimeHandle);
StopTimer(pstSelf, T3_TimeHandle);
if(pstSelf->pfnLinkClose)
{
pstSelf->pfnLinkClose(pstSelf->pUsrData);
}
break;
case TESTFR_CON:
break;
default:
break;
}
return;
}
/*************104组帧接口函数*********/
/**
* @brief 104I帧组帧函数
* @param[in] pstSelf-
* @param[out]
* @return
*/
char GB104_EncodeFrame(CS10xHandle_t pstSelf)
{
pstSelf->stSendBuf.usReadPtr = 0;
VIec104Frame * pstApdu = (VIec104Frame *)pstSelf->stSendBuf.pBuf;
pstSelf->stSendBuf.usWritePtr += GB104_EncodeApci(pstSelf, FRM_I, pstApdu);
pstSelf->stSendBuf.usWritePtr += GB10x_EncodeAsdu(pstSelf, (unsigned char *)pstApdu + pstSelf->stSendBuf.usWritePtr);
GB104_EncodeApduLen(pstSelf, pstApdu);
GB104_FrameTimerHdl(pstSelf, pstApdu);
return 0;
}
/**
* @brief 104 U帧S帧
* @param[in] stSelf-
* @param[out]
* @return
*/
char GB104_EncodeOther(CS10xHandle_t pstSelf)
{
switch(pstSelf->byTaskFlagId)
{
//启动链路发起及响应
case TSKID_StartLink:
pstSelf->uiaTaskParam[TSKID_StartLink] = TSK_PARM_NONE;
if(pstSelf->eCS10x_Type == CS104_TYPE_S)
{
SendUFrame(pstSelf, STARTDT_CON);
}
else if(pstSelf->eCS10x_Type == CS104_TYPE_M)
{
SendUFrame(pstSelf, STARTDT_ACT);
pstSelf->usSendNum = 0;
pstSelf->usRecvNum = 0;
pstSelf->usAckRecvNum = 0;
pstSelf->usAckRecvNum = 0;
StartTimer(pstSelf, T0_TimeHandle);
}
break;
//断开链路发起及响应
case TSKID_StopLink:
pstSelf->uiaTaskParam[TSKID_StopLink] = TSK_PARM_NONE;
if(pstSelf->eCS10x_Type == CS104_TYPE_S)
{
SendUFrame(pstSelf, STOPDT_CON);
}
else if(pstSelf->eCS10x_Type == CS104_TYPE_M)
{
SendUFrame(pstSelf, STOPDT_ACT);
}
break;
// TEST发起及响应
case TSKID_UTest:
if((pstSelf->uiaTaskParam[TSKID_UTest] & 0xFF) == TSK_PARM_USTCON)
{
SendUFrame(pstSelf, TESTFR_CON);
}
else if((pstSelf->uiaTaskParam[TSKID_UTest] & 0xFF) == TSK_PARM_USACT)
{
SendUFrame(pstSelf, TESTFR_ACT);
}
pstSelf->uiaTaskParam[TSKID_UTest] = TSK_PARM_NONE;
break;
//应答 S帧
case TSKID_Ack:
pstSelf->uiaTaskParam[TSKID_Ack] = TSK_PARM_NONE;
GB104_SendAck(pstSelf);
break;
default:
break;
}
return 0;
}
/**
* @brief 104ASDU域确认前处理函数
* @param[in] stSelf-
* @param[in] ucFrameType-
* @param[out]
* @return
*/
unsigned short GB104_EncodeApci(CS10xHandle_t pstSelf, unsigned char ucFrameType, VIec104Frame * pstFrame)
{
unsigned short usSendNum = 0;
unsigned short usRecvNum = 0;
pstSelf->usSendNum %= (MAX_FRAME_COUNTER + 1);
pstSelf->usRecvNum %= (MAX_FRAME_COUNTER + 1);
usSendNum = pstSelf->usSendNum << 1;
usRecvNum = pstSelf->usRecvNum << 1;
if(NULL == pstFrame)
{
return 0;
}
pstFrame->byStartCode = START_CODE;
switch(ucFrameType)
{
case FRM_I:
pstFrame->byControl1 = IEC_LOBYTE(usSendNum);
pstFrame->byControl2 = IEC_HIBYTE(usSendNum);
pstFrame->byControl3 = IEC_LOBYTE(usRecvNum);
pstFrame->byControl4 = IEC_HIBYTE(usRecvNum);
pstSelf->usAckRecvNum = pstSelf->usRecvNum;
break;
case FRM_S:
pstFrame->byControl1 = FRM_S;
pstFrame->byControl2 = 0;
pstFrame->byControl3 = IEC_LOBYTE(usRecvNum);
pstFrame->byControl4 = IEC_HIBYTE(usRecvNum);
pstSelf->usAckRecvNum = pstSelf->usRecvNum;
break;
case FRM_U:
pstFrame->byControl1 = FRM_U;
pstFrame->byControl2 = 0;
pstFrame->byControl3 = 0;
pstFrame->byControl4 = 0;
break;
default:
break;
}
return APCI_LEN;
}
/**
* @brief 104ASDU域确认前处理函数
* @param[in] stSelf-
* @param[in] ucFrameType-
* @param[out]
* @return
*/
void GB104_EncodeApduLen(CS10xHandle_t pstSelf, VIec104Frame * pstApdu)
{
pstApdu->byAPDULen = pstSelf->stSendBuf.usWritePtr - 2;
return;
}
/**
* @brief 104ASDU域确认后处理函数
* @param[in] stSelf-
* @param[out]
* @return
*/
void GB104_FrameTimerHdl(CS10xHandle_t pstSelf, VIec104Frame * pstApdu)
{
if((pstApdu->byControl1 & 0x1) == FRM_I)
{
/*仅存储I帧*/
// SaveSendFrame(pstSelf, pstSelf->usSendNum, pstSelf->stSendBuf.usWritePtr, pstSelf->stSendBuf.pBuf);
StopTimer(pstSelf, T2_TimeHandle); // when send I frame, stop T2
pstSelf->usSendNum++;
if(pstSelf->usSendNum >= COUNTER_LIMIT)
{
pstSelf->usSendNum = 0;
}
if(pstSelf->usSendNum > pstSelf->usAckSendNum && (pstSelf->usSendNum - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
{
pstSelf->bContinueSendFlag = 0;
StartTimer(pstSelf, T1_TimeHandle);
}
else if((pstSelf->usSendNum < pstSelf->usAckSendNum) && (pstSelf->usSendNum + COUNTER_LIMIT - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
{
pstSelf->bContinueSendFlag = 0;
StartTimer(pstSelf, T1_TimeHandle);
}
}
return;
}
/**
* @brief 104S帧组帧函数
* @param[in] stSelf-
* @param[out]
* @return
*/
void GB104_SendAck(CS10xHandle_t pstSelf)
{
VIec104Frame *pstApdu = (VIec104Frame *)pstSelf->stSendBuf.pBuf;
pstSelf->stSendBuf.usWritePtr += GB104_EncodeApci(pstSelf, FRM_S, pstApdu);
GB104_EncodeApduLen(pstSelf, pstApdu);
GB104_FrameTimerHdl(pstSelf, pstApdu);
StopTimer(pstSelf, T2_TimeHandle); // when send S frame, stop T2
return;
}
/**
* @brief 104U帧组帧函数
* @param[in] stSelf-
* @param[in] ucType-U帧类型
* @param[out]
* @return
*/
void SendUFrame(CS10xHandle_t pstSelf, unsigned char ucType)
{
VIec104Frame *pstApdu = (VIec104Frame *)pstSelf->stSendBuf.pBuf;
pstSelf->stSendBuf.usWritePtr += GB104_EncodeApci(pstSelf, FRM_U, pstApdu);
pstApdu->byControl1 |= ucType;
GB104_EncodeApduLen(pstSelf, pstApdu);
GB104_FrameTimerHdl(pstSelf, pstApdu);
return;
}
/***************104规约计时******************/
/**
* @brief 104
* @param[in] pstSelf-
* @param[in] usGap-ms
* @param[out]
* @return
*/
void GB104_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap)
{
if(pstSelf->stM_vTimer[0].bRun)
{
pstSelf->stM_vTimer[0].uiCounter -= usGap;
if(pstSelf->stM_vTimer[0].uiCounter < usGap) //建立连接超时
{
#ifdef IEC_DEBUG_MSG
IEC_PRINT("iec104 slave T0 timeout,close TCP!\n");
#endif
// to do:when T1 timeout,close tcp connect
ClearAllTaskflgs(pstSelf);
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USACT, 0);
if(pstSelf->pfnLinkClose)
{
pstSelf->pfnLinkClose(pstSelf->pUsrData);
}
}
}
if(pstSelf->stM_vTimer[1].bRun)
{
pstSelf->stM_vTimer[1].uiCounter -= usGap;
if(pstSelf->stM_vTimer[1].uiCounter < usGap) //发送数据超时
{
#ifdef IEC_DEBUG_MSG
IEC_PRINT("iec104 slave T1 timeout,close TCP!\n");
#endif
StopTimer(pstSelf, T1_TimeHandle);
if(pstSelf->eCS10x_Type == CS104_TYPE_M)
{
// to do:when T1 timeout,close tcp connect
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USACT, 0);
}
else if(pstSelf->eCS10x_Type == CS104_TYPE_S)
{
pstSelf->ucInitStatus = 0; // 初始化完成状态
if(pstSelf->pfnLinkClose)
{
pstSelf->pfnLinkClose(pstSelf->pUsrData);
}
}
}
}
if(pstSelf->stM_vTimer[2].bRun)
{
pstSelf->stM_vTimer[2].uiCounter -= usGap;
if(pstSelf->stM_vTimer[2].uiCounter < usGap) //无数据报文超时给应答
{
// to do:when T2 timeout, send S frame
SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0);
StopTimer(pstSelf, T2_TimeHandle);
}
}
if(pstSelf->stM_vTimer[3].bRun)
{
pstSelf->stM_vTimer[3].uiCounter -= usGap;
if(pstSelf->stM_vTimer[3].uiCounter < usGap) //无数据超时测试帧
{
// to do:when T3 timeout
if(pstSelf->ucInitStatus == 1)
{
SetSendTask(pstSelf, TSKID_UTest, TSK_PARM_USACT, 0);
}
StopTimer(pstSelf, T3_TimeHandle);
}
}
}
/**
* @brief
* @param[in] pstSelf-
* @param[in] usTimerId-ID
* @param[out]
* @return
*/
void StopTimer(CS10xHandle_t pstSelf, unsigned short usTimerId)
{
if(usTimerId > T3_TimeHandle)
{
return;
}
pstSelf->stM_vTimer[usTimerId].bRun = 0;
pstSelf->stM_vTimer[usTimerId].uiCounter = 0;
}
/**
* @brief
* @param[in] pstSelf-
* @param[in] usTimerId-ID
* @param[out]
* @return
*/
void StartTimer(CS10xHandle_t pstSelf, unsigned short usTimerId)
{
if(usTimerId > T3_TimeHandle)
{
return;
}
pstSelf->stM_vTimer[usTimerId].bRun = 1;
if(usTimerId == T0_TimeHandle)
{
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT0 * 1000;
}
else if(usTimerId == T1_TimeHandle)
{
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT1 * 1000;
}
else if(usTimerId == T2_TimeHandle)
{
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT2 * 1000;
}
else if(usTimerId == T3_TimeHandle)
{
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT3 * 1000;
}
}
/**
* @brief
* @param pucBuf
* @param uslen
* @return true 104
* @return false
*/
bool Check_IEC_104(unsigned char* pucBuf, unsigned short uslen)
{
if(pucBuf[0] != 0x68) //包头必须68
{
return false;
}
if(pucBuf[1] + 2 > uslen) //缺帧
{
return false;
}
else if(pucBuf[1] + 2 < uslen) //连帧
{
if(pucBuf[pucBuf[1] + 2] != 0x68) //连包 检查下一帧报文是否0x68开头
{
return false;
}
}
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,440 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: lib60870_process.c
: V1.0
: 20220407
:
: 101104
:
:
1. : 20220407
:
*******************************************************************************/
/*************************************文件包含*********************************/
#include "lib60870_process.h"
/***************************************数据定义*******************************/
/*************************************外部接口函数*****************************/
/**
* @brief SOE指针
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CheckUpdate_SoeEvent(CS10xHandle_t pstSelf)
{
if(pstSelf->usSoeSendNoAckNum)
{
if(NULL != pstSelf->pfnUpdata_SOE_Pout)
{
pstSelf->pfnUpdata_SOE_Pout(pstSelf->pUsrData, pstSelf->usSoeSendNoAckNum);
pstSelf->usCosSendNoAckNum -= pstSelf->usSoeSendNoAckNum;
pstSelf->usSoeSendNoAckNum = 0;
}
}
if(pstSelf->usEventSendNoAckNum)
{
if(NULL != pstSelf->pfnUpdata_FaultEvent_Pout)
{
pstSelf->pfnUpdata_FaultEvent_Pout(pstSelf->pUsrData, pstSelf->usEventSendNoAckNum);
pstSelf->usEventSendNoAckNum = 0;
}
}
if(pstSelf->usDduSendNoAckNum)
{
if(NULL != pstSelf->pfnUpdata_TimeDdu_Pout)
{
pstSelf->pfnUpdata_TimeDdu_Pout(pstSelf->pUsrData, pstSelf->usDduSendNoAckNum);
pstSelf->usDduSendNoAckNum = 0;
}
}
}
/**
* @brief
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CheckUpdate_DiturbYcEvent(CS10xHandle_t pstSelf)
{
if(pstSelf->usDiturbYcSendNoAckNum)
{
if(NULL != pstSelf->pfnUpdata_DiturbYc_Pout)
{
pstSelf->pfnUpdata_DiturbYc_Pout(pstSelf->pUsrData, pstSelf->usDiturbYcSendNoAckNum);
pstSelf->usDiturbYcSendNoAckNum = 0;
}
}
}
/**
* @brief SOE待发送数量
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CheckSOE_SendInfo(CS10xHandle_t pstSelf)
{
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
{
return;
}
if(NULL == pstSelf->pfnGetSOE_SendNum)
{
return;
}
/* 链路未初始化完成,不进行任务调度*/
if(1 != pstSelf->ucInitStatus)
{
pstSelf->usSoeSendSetup = 0;
return;
}
/*cos-soe处理*/
pstSelf->usSoeSendNum = pstSelf->pfnGetSOE_SendNum(pstSelf->pUsrData);
if(0 == pstSelf->usSoeSendSetup)
{
if(pstSelf->ucOffLineSoeReissueEn)
{
pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
}
else
{
pstSelf->pfnUpdata_SOE_Pout(pstSelf->pUsrData, pstSelf->usSoeSendNum);
pstSelf->usSoeSendNum = 0;
pstSelf->usCosSendNoAckNum = 0;
}
pstSelf->usSoeSendSetup = 1;
}
if(pstSelf->usSoeSendNum)
{
if(pstSelf->usSoeSendNum != pstSelf->usSoeSendNoAckNum)
{
if(pstSelf->usSoeSendNum > pstSelf->usCosSendNoAckNum)
{
// 发送SOE/COS使能参数
if(pstSelf->ucSenCosEa == 0)
{
pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
}
else
{
SetSendTask(pstSelf, TSKID_SendCOS, COT_SPONT, 0); //正常发送COS
}
}
else
{
// 发送SOE/COS使能参数
pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
if(pstSelf->ucSenSoeEa == 0)
{
pstSelf->usSoeSendNoAckNum = pstSelf->usSoeSendNum;
}
else
{
SetSendTask(pstSelf, TSKID_SendSOE, COT_SPONT, 0); //正常发送SOE
}
}
}
}
else
{
pstSelf->usSoeSendNoAckNum = 0;
pstSelf->usCosSendNoAckNum = 0;
}
}
/**
* @brief
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CheckFaultEvent_SendInfo(CS10xHandle_t pstSelf)
{
unsigned short usEventSendNum = 0;
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
{
return;
}
if(NULL == pstSelf->pfnGetEvent_SendNum)
{
return;
}
/* 链路未初始化完成,不进行任务调度*/
if(1 != pstSelf->ucInitStatus)
{
return;
}
/* 故障事件处理*/
if(pstSelf->usFaultEnable)
{
usEventSendNum = pstSelf->pfnGetEvent_SendNum(pstSelf->pUsrData);
if(usEventSendNum)
{
if(usEventSendNum != pstSelf->usEventSendNoAckNum)
{
SetSendTask(pstSelf, TSKID_FaultSoe, COT_SPONT, 0); // 第一次重启补发SOE
}
}
else
{
pstSelf->usEventSendNoAckNum = 0;
}
}
}
/**
* @brief
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CheckTimeDd_SendInfo(CS10xHandle_t pstSelf)
{
unsigned short usTimeDdSendNum = 0;
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
{
return;
}
if(NULL == pstSelf->pfnGetTimeDdu_SendNum)
{
return;
}
/* 链路未初始化完成,不进行任务调度*/
if(1 != pstSelf->ucInitStatus)
{
return;
}
/* 电度数据处理*/
usTimeDdSendNum = pstSelf->pfnGetTimeDdu_SendNum(pstSelf->pUsrData);
if(usTimeDdSendNum)
{
if(usTimeDdSendNum != pstSelf->usDduSendNoAckNum)
{
SetSendTask(pstSelf, TSKID_DdTimeData, COT_SPONT, 0); // 第一次重启补发SOE
}
}
else
{
pstSelf->usDduSendNoAckNum = 0;
}
}
/**
* @brief
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CheckDiturbYc_SendInfo(CS10xHandle_t pstSelf)
{
unsigned short usDiturbYcSendNum = 0;
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
{
return;
}
if(NULL == pstSelf->pfnGetDiturbYc_SendNum)
{
return;
}
usDiturbYcSendNum = pstSelf->pfnGetDiturbYc_SendNum(pstSelf->pUsrData); //获取数据表中待发的数量
if(usDiturbYcSendNum)
{
/*未初始化完成,直接清空缓冲*/
if((0 == pstSelf->ucInitStatus) && (NULL != pstSelf->pfnUpdata_DiturbYc_Pout))
{
pstSelf->pfnUpdata_DiturbYc_Pout(pstSelf->pUsrData, usDiturbYcSendNum);
}
else
{
SetSendTask(pstSelf, TSKID_YcDisturb, COT_SPONT, 0); //正常发送扰动遥测
}
}
}
/**
* @brief
* @param[in] pstSelf-
* @param[out]
* @return
*/
void PollFileTransTask(CS10xHandle_t pstSelf)
{
int ret;
if(NULL == pstSelf->pfnCheckTransFileObj ||
NULL == pstSelf->pfnCheckTransTimeOut)
{
return ;
}
if(GetTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink)
|| pstSelf->bContinueSendFlag == false)
{
//IEC_PRINT("主模式下, 存在U帧激活任务, 直接返回\n");
return ;
}
if(pstSelf->ucTransStatus != FILE_ST_IDLE) //主模式每次传输目录/文件完成, 置位传输状态
{
ret = pstSelf->pfnCheckTransTimeOut(pstSelf->pUsrData);
if(ret < 0)
{
return ;
}
else
{
pstSelf->ucTransStatus = FILE_ST_IDLE;
ClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FilePro);// 直接清空上次文件传输任务
}
}
ret = pstSelf->pfnCheckTransFileObj(&pstSelf->stRdSet, pstSelf->pUsrData);
if(ret == TRANS_DIR)
{
SetSendTask(pstSelf, TSKID_FilePro, FILE_ST_RD_DIR, 0);
pstSelf->ucTransStatus = FILE_ST_RD_DIR;
}
else if(ret == TRANS_FILE)
{
SetSendTask(pstSelf, TSKID_FilePro, FILE_ST_RD_FILE_ACT, 0);
pstSelf->ucTransStatus = FILE_ST_RD_FILE_ACT;
}
else
{
}
}
/**
* @brief M端对S端初始化后总召及对时处理
* @param[in] pstSelf-
* @param[out]
* @return
*/
void CS10x_M_Scheduled(CS10xHandle_t pstSelf, unsigned short usGap)
{
if(CS104_TYPE_M == pstSelf->eCS10x_Type || CS101_TYPE_M == pstSelf->eCS10x_Type) //主站
{
if(pstSelf->uiSummon_Gap) //总召间隔
{
pstSelf->uiSummon_Tcn += usGap;
if(pstSelf->uiSummon_Tcn >= pstSelf->uiSummon_Gap)
{
SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
pstSelf->uiSummon_Tcn = 0;
}
}
if(pstSelf->uiESummon_Gap) //总召间隔
{
pstSelf->uiESummon_Tcn += usGap;
if(pstSelf->uiESummon_Tcn >= pstSelf->uiESummon_Gap)
{
SetSendTask(pstSelf, TSKID_DdSummon, COT_ACT, 0);
pstSelf->uiESummon_Tcn = 0;
}
}
if(pstSelf->uiSyn_Gap) //同步间隔
{
pstSelf->uiTimeSyn_Tcn += usGap;
if(pstSelf->uiTimeSyn_Tcn >= pstSelf->uiSyn_Gap)
{
pstSelf->uiTimeSyn_Tcn = 0;
SetSendTask(pstSelf, TSKID_TimeSyn, COT_ACT, 0);
}
}
if(pstSelf->pfnPollFileTransTask != NULL)
{
pstSelf->pfnPollFileTransTask(pstSelf);
}
}
}
/**
* @brief /
* @param[in] pstSelf-
* @param[in] usGap-(ms)
* @return
*/
void CheckSummonSlaveDelay(CS10xHandle_t pstSelf, unsigned short usGap)
{
if(pstSelf->uiSummonSlaveDelayRemain == 0)
{
return;
}
if(pstSelf->uiSummonSlaveDelayRemain > usGap)
{
pstSelf->uiSummonSlaveDelayRemain -= usGap;
}
else
{
/* 延迟时间到,触发遥信上送 */
pstSelf->uiSummonSlaveDelayRemain = 0;
SetSendTask(pstSelf, TSKID_SummonYx, COT_INTROGEN, pstSelf->ucSummonSlaveQoi);
}
}
/**
* @brief
* @return
*/
void CS10x_M_Finish(CS10xHandle_t pstSelf)
{
pstSelf->ucInitStatus = 1;
/*101主站模式*/
if(CS101_TYPE_M == pstSelf->eCS10x_Type) //主站
{
SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
pstSelf->ucInitStatus = 1;
pstSelf->uiInit_Tcn = 0;
pstSelf->uiInit_Resend_Ncn = 0;
pstSelf->ucRxLinkStatusFlag = 0;
pstSelf->ucRxLinkRequestFlag = 0;
pstSelf->ucRxAckFlag = 0;
pstSelf->ucRxLinkResetFlag = 0;
}
else if(CS104_TYPE_M == pstSelf->eCS10x_Type)
{
SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
pstSelf->ucInitStatus = 1;
}
}
/***************************************内部函数*******************************/

View File

@ -0,0 +1,788 @@
/******************************************************************************
(C), 2013-2023,
******************************************************************************
: lib60870_public.c
: V1.0
: 20220407
:
: 101104
:
:
1. : 20220407
:
*******************************************************************************/
/*************************************文件包含*********************************/
#include "lib60870_public.h"
/***************************************数据定义*******************************/
/*************************************外部接口函数*****************************/
/**
* @brief
* @param[in] pstSelf-
* @param[out]
* @return
*/
unsigned char CS10x_SendTask(CS10xHandle_t pstSelf)
{
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ReSend)) //重发标识
{
pstSelf->byTaskFlagId = TSKID_ReSend;
return RESEND_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_Anomaly)) //异常帧
{
pstSelf->byTaskFlagId = TSKID_Anomaly;
return LONG_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_Ack)) //回复应答帧
{
pstSelf->byTaskFlagId = TSKID_Ack;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_RequestLink)) // 101规约请求链路状态
{
pstSelf->byTaskFlagId = TSKID_RequestLink;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ResetLink)) // 101规约重置链路
{
pstSelf->byTaskFlagId = TSKID_ResetLink;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_MResponse)) // 101规约链路状态回复帧
{
pstSelf->byTaskFlagId = TSKID_MResponse;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_HeartBeat)) // 101规约心跳
{
pstSelf->byTaskFlagId = TSKID_HeartBeat;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink)) // 104规约启动链路
{
pstSelf->byTaskFlagId = TSKID_StartLink;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_StopLink)) // 104规约断开链路
{
pstSelf->byTaskFlagId = TSKID_StopLink;
return SHORT_TYPE;
}
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_UTest)) // 104规约U帧TEST
{
pstSelf->byTaskFlagId = TSKID_UTest;
return SHORT_TYPE;
}
/*规约不允许发送长帧,则直接返回*/
if(CS104_TYPE_S == pstSelf->eCS10x_Type || CS104_TYPE_M == pstSelf->eCS10x_Type)
{
if(false == pstSelf->bContinueSendFlag)
{
return 0;
}
}
else
{
if(pstSelf->uiResend_Tcn)
{
return 0;
}
}
/*初始化完成*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_InitFinish))
{
pstSelf->byTaskFlagId = TSKID_InitFinish;
return LONG_TYPE;
}
/*遥控命令报文*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_YkProcess))
{
pstSelf->byTaskFlagId = TSKID_YkProcess;
return LONG_TYPE;
}
/*COS信息*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SendCOS))
{
pstSelf->byTaskFlagId = TSKID_SendCOS;
return LONG_TYPE;
}
/*事件顺序记录 SOE*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SendSOE))
{
pstSelf->byTaskFlagId = TSKID_SendSOE;
return LONG_TYPE;
}
/* 总招遥信响应遥信 */
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SummonYx))
{
pstSelf->byTaskFlagId = TSKID_SummonYx;
return LONG_TYPE;
}
/* 总招遥测响应遥测 */
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SummonYc))
{
pstSelf->byTaskFlagId = TSKID_SummonYc;
return LONG_TYPE;
}
/*总召响应*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SummonResponse))
{
pstSelf->byTaskFlagId = TSKID_SummonResponse;
return LONG_TYPE;
}
/* 故障事件 */
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FaultSoe))
{
pstSelf->byTaskFlagId = TSKID_FaultSoe;
return LONG_TYPE;
}
/*时钟同步报文*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_TimeSyn))
{
pstSelf->byTaskFlagId = TSKID_TimeSyn;
return LONG_TYPE;
}
/*扰动数据*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_YcDisturb))
{
pstSelf->byTaskFlagId = TSKID_YcDisturb;
return LONG_TYPE;
}
/*延时获得命令*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ObtainDelay))
{
pstSelf->byTaskFlagId = TSKID_ObtainDelay;
return LONG_TYPE;
}
/*复位进程*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ResetProcess))
{
pstSelf->byTaskFlagId = TSKID_ResetProcess;
return LONG_TYPE;
}
/*文件数据响应*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FilePro))
{
pstSelf->byTaskFlagId = TSKID_FilePro;
return LONG_TYPE;
}
/*电能量数据发送*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DdData))
{
pstSelf->byTaskFlagId = TSKID_DdData;
return LONG_TYPE;
}
/*总召电能量*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DdSummon))
{
pstSelf->byTaskFlagId = TSKID_DdSummon;
return LONG_TYPE;
}
/*总召电能量*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DdTimeData))
{
pstSelf->byTaskFlagId = TSKID_DdTimeData;
return LONG_TYPE;
}
/*修改参数定值区*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ChgConst))
{
pstSelf->byTaskFlagId = TSKID_ChgConst;
return LONG_TYPE;
}
/*读取参数定值区*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ReadConst))
{
pstSelf->byTaskFlagId = TSKID_ReadConst;
return LONG_TYPE;
}
/*读取定值参数*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamPreread))
{
pstSelf->byTaskFlagId = TSKID_ParamPreread;
return LONG_TYPE;
}
/*读取定值参数-南网*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamRead_NanWang))
{
pstSelf->byTaskFlagId = TSKID_ParamRead_NanWang;
return LONG_TYPE;
}
/*设置定值参数*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamPrewrite))
{
pstSelf->byTaskFlagId = TSKID_ParamPrewrite;
return LONG_TYPE;
}
/*写参数定值-南网(类型标识 55*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamWrite_NanWang))
{
pstSelf->byTaskFlagId = TSKID_ParamWrite_NanWang;
return LONG_TYPE;
}
/*读定值参数响应传输-南网*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamReadResponse_NanWang))
{
pstSelf->byTaskFlagId = TSKID_ParamReadResponse_NanWang;
return LONG_TYPE;
}
/*参数预置-南网*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamPreset_NanWang))
{
pstSelf->byTaskFlagId = TSKID_ParamPreset_NanWang;
return LONG_TYPE;
}
/*固化定值参数-南网*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamSolidify_NanWang))
{
pstSelf->byTaskFlagId = TSKID_ParamSolidify_NanWang;
return LONG_TYPE;
}
/*启动升级*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_UpdateStart))
{
pstSelf->byTaskFlagId = TSKID_UpdateStart;
return LONG_TYPE;
}
/*执行升级*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_UpdateExe))
{
pstSelf->byTaskFlagId = TSKID_UpdateExe;
return LONG_TYPE;
}
/*长帧测试*/
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DataTest))
{
pstSelf->byTaskFlagId = TSKID_DataTest;
return LONG_TYPE;
}
return 0;
}
/**
* @brief
* @param[in] pstSelf-
* @param[in] uiFlagNo-ID
* @param[in] usParam_low-2cot usParam_hig 2
* @param[out]
* @return
*/
void SetSendTask(CS10xHandle_t pstSelf, unsigned int uiFlagNo, unsigned short usParam_low, unsigned short usParam_hig)
{
SetTaskFlag(&pstSelf->stTaskFlags, uiFlagNo);
pstSelf->uiaTaskParam[uiFlagNo] = usParam_hig;
pstSelf->uiaTaskParam[uiFlagNo] = (pstSelf->uiaTaskParam[uiFlagNo] << 16) + usParam_low;
return;
}
/***************************************************************
* @brief SetTaskFlag
pFlags缓冲区内的第FlagNo个位置位成1
* @param[in] pstFlags
uiFlagNo
* @return
***************************************************************/
void SetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
{
unsigned int uiByteNo = 0; // FlagNo所处的字节号
unsigned int uiBitNo = 0; // FlagNo在字节内所处的位号
if(uiFlagNo >= MAX_FLAGNO) //越界
{
return;
}
uiByteNo = uiFlagNo >> 3;
uiBitNo = uiFlagNo & 0x7;
// pstFlags->Flag[uiByteNo] |= aBitSelect[uiBitNo];
pstFlags->ucFlag[uiByteNo] |= (1 << uiBitNo);
}
/***************************************************************
* @brief GetTaskFlag
pFlags缓冲区内的第FlagNo个位置的状态位
* @param[in] pstFlags
uiFlagNo
* @return 1 0
***************************************************************/
unsigned int GetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
{
// 设置每个模块的标志
unsigned int uiByteNo = 0; // FlagNo所处的字节号
unsigned int uiBitNo = 0; // FlagNo在字节内所处的位号
unsigned char *pucFlag = (unsigned char *)pstFlags; //
uiByteNo = uiFlagNo >> 3; //第5到8位
uiBitNo = uiFlagNo & 7; //取低三位
return (pucFlag[uiByteNo] & (1 << uiBitNo));
}
/***************************************************************
* @brief ClearTaskFlag
pFlags缓冲区内的第FlagNo个位置位成0
* @param[in] pstFlags
uiFlagNo
* @return
***************************************************************/
void ClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
{
unsigned int uiByteNo = 0;
unsigned int uiBitNo = 0;
if(uiFlagNo >= MAX_FLAGNO)
{
return;
}
uiByteNo = uiFlagNo >> 3;
uiBitNo = uiFlagNo & 0x7;
pstFlags->ucFlag[uiByteNo] &= ~(1 << uiBitNo);
}
/***************************************************************
* @brief CheckClearTaskFlag
dwFlagNo位有效
1,0
* @param[in] pstFlags
* uiFlagNo
* @return 1 uiFlagNo位有效
0 uiFlagNo位无效
***************************************************************/
int CheckClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
{
if(!GetTaskFlag(pstFlags, uiFlagNo))
{
return 0;
}
ClearTaskFlag(pstFlags, uiFlagNo);
return 1;
}
/**
* @brief
* @param[in] pstSelf
* @param[out]
* @return
*/
void ClearAllTaskflgs(CS10xHandle_t pstSelf)
{
pstSelf->stRecvBuf.usWritePtr = 0;
pstSelf->stRecvBuf.usReadPtr = 0;
pstSelf->stSendBuf.usWritePtr = 0;
pstSelf->stSendBuf.usReadPtr = 0;
memset(&pstSelf->stTaskFlags, 0, sizeof(VFLAGS)); //任务
memset(pstSelf->uiaTaskParam, 0, MAX_FLAGNO * sizeof(unsigned short)); //任务参数
pstSelf->byTaskFlagId = 0;
pstSelf->ucInitStatus = 0; // 初始化完成状态
pstSelf->ucFirstAct = 0;
pstSelf->uiFrameTmCnt = 0;
pstSelf->uiHeart_Tcn = 0;
pstSelf->uiSummon_Tcn = 0;
pstSelf->uiESummon_Tcn = 0;
pstSelf->uiTimeSyn_Tcn = 0;
pstSelf->usYxSendNum = 0;
pstSelf->usYcSendNum = 0;
pstSelf->usDisTurbYcSendNum = 0;
pstSelf->usDdSendNum = 0;
pstSelf->usSoeSendNum = 0;
pstSelf->usSoeSendNoAckNum = 0; /*Soe发送未确认数量*/
pstSelf->usCosSendNoAckNum = 0;
pstSelf->usEventSendNoAckNum = 0; /*事件发送未确认数量*/
pstSelf->usDduSendNoAckNum = 0;
pstSelf->usDiturbYcSendNoAckNum = 0;
pstSelf->usSoeSendSetup = 0;
pstSelf->usDdSummonSetup = 0;
pstSelf->ucParamFlag = 0;
pstSelf->usParamSendNum = 0;
pstSelf->ucPmPresetFlag = 0;
pstSelf->uiPmPresetTimeout = 0;
pstSelf->ucTransStatus = 0;
pstSelf->uiTransTimerCur = 0;
pstSelf->uiTransTimerMax = 0;
pstSelf->bContinueSendFlag = 0;
pstSelf->ucInitStep = 0;
pstSelf->ucSelf_FCB = 0;
pstSelf->ucRxAckFlag = 0;
pstSelf->ucRxLinkStatusFlag = 0;
pstSelf->ucRxLinkRequestFlag = 0;
pstSelf->ucRxLinkResetFlag = 0;
pstSelf->ucRxInitFinishFlag = 0;
pstSelf->ucHeart_Resend_Flag = 0;
pstSelf->ucFileTransFrame = 0;
pstSelf->usFileNoneAckNum = 0;
pstSelf->usResend_Ncn = 0;
pstSelf->uiResend_Tcn = 0;
pstSelf->uiRelink_Tcn = 0;
pstSelf->uiInit_Tcn = 0;
pstSelf->uiReInit_Tcn = 0;
pstSelf->uiInit_Resend_Ncn = 0;
pstSelf->usSendNum = 0; /*Send Counter */
pstSelf->usRecvNum = 0; /*Receive Counter*/
pstSelf->usAckSendNum = 0; /*Receive Ack Counter*/
pstSelf->usAckRecvNum = 0; /*Have Ack Receive Counter*/
pstSelf->stM_vTimer[0].bRun = 0;
pstSelf->stM_vTimer[1].bRun = 0;
pstSelf->stM_vTimer[2].bRun = 0;
pstSelf->stM_vTimer[3].bRun = 0;
pstSelf->uiSummonSlaveDelayRemain = 0;
pstSelf->ucSummonSlaveQoi = 0;
}
/**
* @brief 8
* @param[in] pucBuf-
* @param[in] ucLen-
* @param[out]
* @return
*/
unsigned char checksum_8(unsigned char *pucBuf, unsigned char ucLen)
{
unsigned char ucSum = 0;
unsigned char uci = 0;
for(uci = 0; uci < ucLen; uci++)
{
ucSum += pucBuf[uci];
}
ucSum = ucSum & 0xff;
return ucSum;
}
/**
* @brief Check比对Tag类型与长度关系
*
* @param ucTag
* @param ucLen
* @return int
*/
int CheckParamTagAndLen(unsigned char ucTag, unsigned char ucLen)
{
bool bResult = true;
switch(ucTag)
{
case TAG_TPYE_BOOL:
case TAG_TPYE_TINY:
case TAG_TPYE_UTINY:
if(ucLen != 1)
{
bResult = false;
}
break;
case TAG_TPYE_SHORT:
case TAG_TPYE_USHORT:
if(ucLen != 2)
{
bResult = false;
}
break;
case TAG_TPYE_INT:
case TAG_TPYE_UINT:
case TAG_TPYE_FLOAT:
if(ucLen != 4)
{
bResult = false;
}
break;
case TAG_TPYE_LONG:
case TAG_TPYE_ULONG:
case TAG_TPYE_DOUBLE:
if(ucLen != 8)
{
bResult = false;
}
break;
case TAG_TPYE_STR:
if(ucLen > 64)
{
bResult = false;
}
break;
default:
bResult = false;
break;
}
return bResult;
}
/*
* Prototype : CP56Time2a_Pack2Buf
* Description : Cp56时间到缓冲
* @param[in] : unsigned char *pucOutBuf
* @param[in] : const __CP56Time2a *pstCp56
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/6
* Author : wqw
* Modification : Created function
*
*/
unsigned char CP56Time2a_Pack2Buf(unsigned char *pucOutBuf, const __CP56Time2a *pstCp56)
{
if(NULL == pstCp56)
{
memset(pucOutBuf, 0, 7);
}
else
{
pucOutBuf[0] = pstCp56->ucLMs;
pucOutBuf[1] = pstCp56->ucHMs;
pucOutBuf[2] = pstCp56->ucMin;
pucOutBuf[3] = pstCp56->ucHour;
pucOutBuf[4] = pstCp56->ucWeek;
pucOutBuf[5] = pstCp56->ucMonth;
pucOutBuf[6] = pstCp56->ucYear;
}
return 7;
}
/*
* Prototype : CP56Time2a_GetFromBuf
* Description : Cp56时间
* @param[in] : const unsigned char *pucInBuf
* @param[in] : __CP56Time2a *pstCp56
* @param[out] : None
* @Return : 0= 1=
*
*
*
* History :
* 1.Date : 2023/6/6
* Author : wqw
* Modification : Created function
*
*/
unsigned char CP56Time2a_GetFromBuf(const unsigned char *pucInBuf, __CP56Time2a *pstCp56)
{
if(NULL == pstCp56)
{
return 0;
}
pstCp56->ucLMs = pucInBuf[0];
pstCp56->ucHMs = pucInBuf[1];
pstCp56->ucMin = pucInBuf[2];
pstCp56->ucHour = pucInBuf[3];
pstCp56->ucWeek = pucInBuf[4];
pstCp56->ucMonth = pucInBuf[5];
pstCp56->ucYear = pucInBuf[6];
return 1;
}
/*
* Prototype : IntBytes_Pack2Buf
* Description : Int数据
* @param[in] : unsigned char *pucOutBuf
* @param[in] : unsigned int uiVal
* @param[in] : unsigned char ucSize
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/6
* Author : wqw
* Modification : Created function
*
*/
unsigned char IntBytes_Pack2Buf(unsigned char *pucOutBuf, unsigned int uiVal, unsigned char ucSize)
{
if(0 == ucSize || ucSize > 4)
{
return 0;
}
for(unsigned char i = 0; i < ucSize; i++)
{
pucOutBuf[i] = uiVal;
uiVal >>= 8;
}
return ucSize;
}
/*
* Prototype : IntBytes_GetFromBuf
* Description : Int数据
* @param[in] : const unsigned char *pucInBuf
* @param[in] : unsigned char ucSize
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/6
* Author : wqw
* Modification : Created function
*
*/
unsigned int IntBytes_GetFromBuf(const unsigned char *pucInBuf, unsigned char ucSize)
{
unsigned int uiVal = 0;
if(0 == ucSize || ucSize > 4)
{
return 0;
}
for(unsigned char i = 0; i < ucSize; i++)
{
uiVal |= ((unsigned int)pucInBuf[i] << (i * 8));
}
return uiVal;
}
/*
* Prototype : Float_Pack2Buf
* Description :
* @param[in] : unsigned char *pucOutBuf
* @param[in] : float fVal
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/12
* Author : wqw
* Modification : Created function
*
*/
unsigned char Float_Pack2Buf(unsigned char *pucOutBuf, float fVal)
{
memcpy(pucOutBuf, &fVal, 4);
return 4;
}
/*
* Prototype : Float_GetFromBuf
* Description :
* @param[in] : const unsigned char *pucInBuf
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/12
* Author : wqw
* Modification : Created function
*
*/
float Float_GetFromBuf(const unsigned char *pucInBuf)
{
float fVal = 0;
memcpy(&fVal, pucInBuf, 4);
return fVal;
}
/*
* Prototype : U16_Pack2Buf
* Description :
* @param[in] : unsigned char *pucOutBuf
* @param[in] : unsigned short usVal
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/12
* Author : wqw
* Modification : Created function
*
*/
unsigned char U16_Pack2Buf(unsigned char *pucOutBuf, unsigned short usVal)
{
memcpy(pucOutBuf, &usVal, 2);
return 2;
}
/*
* Prototype : U16_GetFromBuf
* Description :
* @param[in] : const unsigned char *pucInBuf
* @param[out] : None
* @Return :
*
*
*
* History :
* 1.Date : 2023/6/12
* Author : wqw
* Modification : Created function
*
*/
unsigned short U16_GetFromBuf(const unsigned char *pucInBuf)
{
unsigned short usVal = 0;
memcpy(&usVal, pucInBuf, 2);
return usVal;
}
/***************************************内部函数*******************************/

View File

@ -0,0 +1,347 @@
//#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
#include "md5.h"
static void MD5Transform PROTO_LIST((UINT4 [4], unsigned char [64]));
static void MD5_memcpy PROTO_LIST((POINTER, POINTER, unsigned int));
static void MD5_memset PROTO_LIST((POINTER, int, unsigned int));
static void MD5Init PROTO_LIST((MD5_CTX *));
static void MD5Update PROTO_LIST((MD5_CTX *, unsigned char *, unsigned int));
static void MD5Final PROTO_LIST((unsigned char [16], MD5_CTX *));
static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST((UINT4 *, unsigned char *, unsigned int));
static unsigned char PADDING[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static void MD5Init(MD5_CTX *context)
{
context->count[0] = context->count[1] = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
static void MD5Update(
MD5_CTX *context, /* context */
unsigned char *input, /* input block */
unsigned int inputLen /* length of input block */
)
{
unsigned int i, index, partLen;
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
if((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
{
context->count[1]++;
}
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
if(inputLen >= partLen)
{
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform(context->state, context->buffer);
for(i = partLen; i + 63 < inputLen; i += 64)
{
MD5Transform(context->state, &input[i]);
}
index = 0;
}
else
{
i = 0;
}
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen - i);
}
static void MD5Final(
unsigned char digest[16], /* message digest */
MD5_CTX *context /* context */
)
{
unsigned char bits[8] = {0};
unsigned int index = 0, padLen = 0;
Encode(bits, context->count, 8);
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update(context, PADDING, padLen);
MD5Update(context, bits, 8);
Encode(digest, context->state, 16);
MD5_memset((POINTER)context, 0, sizeof(*context));
}
static void MD5Transform(
UINT4 state[4],
unsigned char block[64]
)
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode(x, block, 64);
/* Round 1 */
FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
MD5_memset((POINTER)x, 0, sizeof(x));
}
static void Encode(
unsigned char *output,
UINT4 *input,
unsigned int len
)
{
unsigned int i, j;
for(i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char)(input[i] & 0xff);
output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
static void Decode(
UINT4 *output,
unsigned char *input,
unsigned int len
)
{
unsigned int i = 0, j = 0;
for(i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j + 1]) << 8) |
(((UINT4)input[j + 2]) << 16) | (((UINT4)input[j + 3]) << 24);
}
static void MD5_memcpy(
POINTER output,
POINTER input,
unsigned int len
)
{
unsigned int i = 0;
for(i = 0; i < len; i++)
{
output[i] = input[i];
}
}
static void MD5_memset(
POINTER output,
int value,
unsigned int len
)
{
unsigned int i = 0;
for(i = 0; i < len; i++)
{
((char *)output)[i] = (char)value;
}
}
void StartMD5(MD5_CTX *context)
{
MD5Init(context);
}
void EncodeMD5(MD5_CTX *context, unsigned char *input, int len)
{
MD5Update(context, input, len);
}
void GetMD5(MD5_CTX *context, unsigned char *result)
{
if(result == NULL)
{
return;
}
MD5Final(result, context);
}
void GetMD5String(MD5_CTX *context, char *result, unsigned char mode)
{
unsigned char digest[16] = {0};
char output1[33] = {0};
if(result == NULL)
{
return;
}
MD5Final(digest, context);
for(int i = 0; i < 16; i++)
{
sprintf(&(output1[2 * i]), "%02x", (unsigned char)digest[i]);
sprintf(&(output1[2 * i + 1]), "%02x", (unsigned char)(digest[i] << 4));
}
if(mode == MD5_BIT32)
for(int i = 0; i < 32; i++)
{
result[i] = output1[i];
}
else if(mode == MD5_BIT16)
for(int i = 0; i < 16; i++)
{
result[i] = output1[8 + i];
}
}
/* ²âÊÔÓà */
#if 0
char *MD5String(char *string)
{
MD5_CTX context = {0};
unsigned char digest[16] = {0};
char output1[33] = {0};
static char output[33] = {""};
unsigned int len = strlen(string);
int i = 0;
MD5Init(&context);
MD5Update(&context, (unsigned char *)string, len);
MD5Final(digest, &context);
for(i = 0; i < 16; i++)
{
sprintf(&(output1[2 * i]), "%02x", (unsigned char)digest[i]);
sprintf(&(output1[2 * i + 1]), "%02x", (unsigned char)(digest[i] << 4));
}
for(i = 0; i < 32; i++)
{
output[i] = output1[i];
}
return output;
}
static void StringAddOne(char *orstring)
{
unsigned int len = 0;
int i = 0, n = 0;
len = strlen(orstring);
n = len - 1;
for(i = n; i >= 0; i--)
{
if(orstring[i] == '9')
{
orstring[i] = 'A';
break;
}
else if(orstring[i] == 'Z')
{
orstring[i] = 'a';
break;
}
else if(orstring[i] == 'z')
{
orstring[i] = '0';
continue;
}
else
{
orstring[i] += 1;
}
break;
}
}
bool MD5Check(char *md5string, char *string)
{
return strcmp(md5string, MD5String(string)) == 0;
}
#endif