代码理解
IEC104NASlave.h窗口协议从站头文件
已注释过内容不再注释,请参考
C++代码审阅–ice104协议从站(1)
C++代码审阅–ice104协议从站(2)
C++代码审阅–ice104协议从站(3)
C++代码审阅–ice104协议从站(4)
C++代码审阅–ice104协议从站(5)
后面几篇内容只需了解iec104协议基础知识即可理解,请看以下链接
电力IEC104规约协议解读(含源码下载)
// IEC104Slave.h: interface for the CIEC104Slave class.
//
//
#if !defined(AFX_IEC104SLAVE_H__6ABA0560_80B1_434F_A483_2DE49824F75C__INCLUDED_)
#define AFX_IEC104SLAVE_H__6ABA0560_80B1_434F_A483_2DE49824F75C__INCLUDED_
#include <winsock2.h>
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
struct APCI{ // U-Format
unsigned char start; // 起始字节
unsigned char len; // 帧长度
unsigned char field1; // 控制域1-4
unsigned char field2;
unsigned char field3;
unsigned char field4;
};
struct ASDU_header{ // 数据单元标识
unsigned char type; // 类型标识
unsigned char qual; // 可变结构限定词
unsigned char tx_cause_1; // 传送原因
unsigned char tx_cause_2;
unsigned char commom_asdu_1; // 公共地址
unsigned char commom_asdu_2;
};
struct ASDU{
struct ASDU_header header; // 数据单元标识
unsigned char data[243]; // 信息体
};
struct APDU{
struct APCI apci;
struct ASDU asdu;
};
// 激活命令
#define CMD_STARTV 0x04
#define CMD_STOPV 0x10
#define CMD_TESTV 0x40
// 确认命令
#define CMD_STARTC 0x08
#define CMD_STOPC 0x20
#define CMD_TESTC 0x80
/* Location Which Bytes In ASDU Buffer */
#define NA_STARTQUALIFIER 9 // 限定符在ASDU中的起始位置
#define NA_IEC_104_QCC_POSITION 9 // QCC--FRZ冻结:1(1:冻结不复位,2:冻结复位,3:计数器复位) 请求RQT:5
#define NA_IEC_104_TIME_POSITION 9
// 在buf中传输原因, 公共地址, 信息体地址的位置
#define NA_STARTREASON 8
#define NA_STARTASDUADDRESS 10
#define NA_STARTINFORMATION 12
#define NA_IEC104_GROUP_BEGIN 21 // 分组召唤起始标识号
#define NA_IEC104_GROUP_END 36 // 分组召唤的结束标识号
#define NA_IEC_104_REASONBYTE 2 // 传送原因 占2个字节
#define NA_IEC_104_ASDUADDRESSBYTE 2 // 公共地址 占2个字节
#define NA_IEC_104_INFORMATIONBYTE 3 // 信息体地址 占2个字节
#define NA_IEC_104_TOTAL_YX_TIMES 8 // 遥信数据的组数 一共288个数据,分8组,每组36个
#define NA_IEC_104_ONCE_YX 36
#define NS_IEC_104_ONCE_YX_BYTES 120/8
#define NA_IEC_104_TOTAL_YC_TIMES 60 // 36 59
#define NA_IEC_104_ONCE_YC 50 // 80 50 最后一次发一个数据
#define NA_IEC_104_TOTAL_YM_TIMES 0
#define NA_IEC_104_ONCE_YM 20 // 电度量数据一共是20个数据,每个数据4个字节,可以加一个描述位
#define NS_IEC104_MAX_K 12
#define NS_IEC104_MAX_W 8
class CIEC104Slave
{
public:
char LastError[100];
public:
// SOCKET server;
SOCKET client;
sockaddr_in from;
BYTE ALLYXData[288];
// BYTE ALLYCData[5902];
DWORD ALLYMData[20];
WORD ALLYCData[2951];
int RxCounter; // 接收序号
int LastAckTx;
int TxCounter; // 发送序号
int LastAckRx;
unsigned char AsduQualifier; // 标识是总召唤还是分组召唤限定符
unsigned char TransmitReason[2];
unsigned char CommonAsduAddress[2];
unsigned char InformationObject[3];
unsigned char Qcc;
unsigned char FreezeSign;
unsigned char PulseGroup;
unsigned char YkYtType;
unsigned char YkInformation,YkReason,YkWhat;
unsigned short YkObject;
unsigned short ReceiveYkId;
unsigned char YkCellAction;
// unsigned short SendMeNumber; // 发送序号
// unsigned char ReceiveHimNumber[2]; // 接收序号
int T0; // time-out of connection establishment (reconnection) TCP连接建立的超时时间
int T1; // time-out of send or test APDUs (wait ack). RTU(服务器)端启动U格式测试过程后等待U格式测试应答的超时时间
int T2; // time-out for ack in case of no data messages (T2 < T1). S格式的超时时间
int T3; // time-out for sending TESFR in case of long idle state. 没有实际的数据交换时,任何一端启动U格式测试过程的最大间隔时间
int K; // maximum difference N(R) and N(S)
int W; // lastest ack after receiving W I-Format message.
int timer_Connect; // associated of T0 param
//bool timer_Connectflag;
int timer_Confirm; // associated of T1 param
//bool timer_Confirmflag;
int timer_S_Ack; // associated of T2 param
bool timer_S_Ackflag;
int timer_U_Test; // associated of T3 param
bool timer_U_Testflag;
unsigned char TimeSave[8]; // 存储接收到的时间数据
public:
void NAIec104ProcessHistoryEnd(BYTE *msgbuf, unsigned int len);
void NAIec104ProcessHistory(BYTE *msgbuf, unsigned int len);
void NAIec104ProcessGTEnd();
void NAIec104ProcessGT();
void MyMemcpy(void * dest, void *src, int len);
void SetAllYMData( DWORD *ymBuf, int ymLen);
void SetAllYCData(WORD *ycBuf, int ycLen);
void SetAllYXData(BYTE *yxBuf, int yxLen);
void startT2Timer();
void SetParams(int t0=30, int t1=15, int t2=10, int t3=20, int k=12, int w=8);
void NAIec104YCACK(BYTE *msgbuf, unsigned int len);
void NAIec104YXACK(BYTE *msgbuf, unsigned int len);
void NAIec104YTACK(BYTE *msgbuf, unsigned int len);
void NAIec104YKEXEACK(BYTE *msgbuf, unsigned int len);
void NAIec104YKDeactACK(BYTE *msgbuf, unsigned int len);
void NAIec104YKACK(BYTE *msgbuf, unsigned int len);
void ReturnALLYMData();
void NAIec104ProcessPulseAll();
void NAIec104ProcessPulseEnd();
void NAIec104ProcessPulseAck();
void ReturnAllYCData();
void ReturnAllYXData();
void InterrogationComplete();
void InterrogationConfirm();
void NAIec104ProcessTime();
void NAIec104ProcessYkYt();
void NAIec104InterrogationAll(); // 总召唤
void ProcessFormatU(APCI *p);
int Send_I_Msg(BYTE *msgbuf, unsigned int len);
int Send_S_Msg();
int ProcessFormatI(BYTE *msgbuf, unsigned int len);
BOOL GetSockConnectStatus();
int Send_U_Msg(int cmd);
void slave_stop();
int slave_start();
bool Connected;
static DWORD WINAPI RxHandler(LPVOID lpParam);
static DWORD WINAPI TimerHandler(LPVOID lpParam); // 处理超时
static DWORD WINAPI DealIFrameHandler(LPVOID lpParam); // 未收到S确认帧时等待处理
static DWORD WINAPI DealNOIFrameResponseS(LPVOID lpParam); // 未被确认的 I 帧最大数目 k
static DWORD WINAPI ListeThr(LPVOID lpParam);
virtual void OnRxMsg(BYTE *msgbuf, unsigned int len){};
virtual void OnTxMsg(BYTE *msgbuf, unsigned int len){};
virtual void OnUpdateTime(int nType, BOOL isInvalid = FALSE){};
virtual void OnUpdateRemainTime(int nType, int nRemainSecond, BOOL isInvalid = FALSE){};
virtual void OnUpdateWnd(){};
CIEC104Slave();
virtual ~CIEC104Slave();
};
#endif // !defined(AFX_IEC104SLAVE_H__6ABA0560_80B1_434F_A483_2DE49824F75C__INCLUDED_)