map/das-dn/inc/iec101.h
2024-07-08 10:27:17 +08:00

884 lines
36 KiB
C++

#ifndef _ZJD_IEC101_PROCESS_H_
#define _ZJD_IEC101_PROCESS_H_
#include "portproc.h"
#include "iec_101_104_lib.h"
#include <semaphore.h>
#define IEC101S_IDLE 0
#define IEC101S_SYNC 1
#define IEC101S_INFO 2
#define IEC101_STX1 0x10
#define IEC101_STX2 0x68
#define IEC101_ETX 0x16
typedef enum {
IEC60870_LINK_LAYER_BALANCED = 0,
IEC60870_LINK_LAYER_UNBALANCED = 1
} enumIEC101_LinkLayerMode;
typedef enum {
LL_STATE_IDLE,
LL_STATE_ERROR,
LL_STATE_BUSY,
LL_STATE_AVAILABLE
} enumIEC101_LinkLayerState;
typedef enum {
PLL_IDLE,
PLL_EXECUTE_REQUEST_STATUS_OF_LINK,
PLL_EXECUTE_RESET_REMOTE_LINK,
PLL_LINK_LAYERS_AVAILABLE,
PLL_EXECUTE_SERVICE_SEND_CONFIRM,
PLL_EXECUTE_SERVICE_REQUEST_RESPOND,
PLL_SECONDARY_LINK_LAYER_BUSY /* Only required in balanced link layer */
} enumIEC101_PrimaryLinkLayerState;
typedef struct {
int addressLength; /* 0/1/2 bytes */
int timeoutForACK; /* timeout for ACKs in ms */
int timeoutRepeat; /* timeout for repeating messages when no ACK received in ms */
BOOLEAN useSingleCharACK; /* use single char ACK for ACK (FC=0) or RESP_NO_USER_DATA (FC=9) */
} struIEC101_LinkLayerParameters;
typedef struct {
BOOLEAN dir; /* DIR bit to be used when messages are sent in balanced mode */
BYTE mode;
struIEC101_LinkLayerParameters linkLayerParameters;
} struIEC101_LinkLayer;
typedef struIEC101_LinkLayer* pIEC101_LinkLayer;
typedef struct {
int sizeOfTypeId; /* size of the type id (default = 1 - don't change) */
int sizeOfVSQ; /* don't change */
int sizeOfCOT; /* size of COT (1/2 - default = 2 -> COT includes OA) */
int originatorAddress; /* originator address (OA) to use (0-255) */
int sizeOfCA; /* size of common address (CA) of ASDU (1/2 - default = 2) */
int sizeOfIOA; /* size of information object address (IOA) (1/2/3 - default = 3) */
int maxSizeOfASDU; /* maximum size of the ASDU that is generated - the maximum maximum value is 249 for IEC 104 and 254 for IEC 101 */
} struIEC101_AppLayerParameters;
typedef struIEC101_AppLayerParameters* pIEC101_AppLayerParameters;
typedef struct {
enumIEC101_LinkLayerState state; /* user visible state */
enumIEC101_PrimaryLinkLayerState primaryState; /* internal PLL state machine state */
BOOLEAN hasMessageToSend; /* indicates if an app layer message is ready to be sent */
BYTE buffer[256];
int bufferLength;
int address;
QWORD lastSendTime;
QWORD originalSendTime;
BOOLEAN requestClass1Data;
BOOLEAN requestClass2Data;
BOOLEAN dontSendMessages;
BOOLEAN waitingForResponse;
BOOLEAN sendLinkLayerTestFunction;
BOOLEAN nextFcb;
} struIEC101_LinkLayerSlaveConnection;
typedef struct {
struIEC101_LinkLayerSlaveConnection slaveConnection;
} struIEC101_LinkLayerPrimaryUnbalanced;
typedef struct {
enumIEC101_LinkLayerState state; /* state information for user */
enumIEC101_PrimaryLinkLayerState primaryState; /* internal PLL state machine state */
BYTE buffer[256];
int bufferLength;
BOOLEAN waitingForResponse;
BOOLEAN sendLinkLayerTestFunction;
BOOLEAN nextFcb;
QWORD lastSendTime;
QWORD originalSendTime;
QWORD lastReceivedMsg;
int otherStationAddress;
int idleTimeout; /* connection timeout in ms */
} struIEC101_LinkLayerPrimaryBalanced;
typedef struIEC101_LinkLayerPrimaryBalanced* pIEC101_LinkLayerPrimaryBalanced;
typedef struct {
BOOLEAN expectedFcb; /* expected value of next frame count bit (FCB) */
} struIEC101_LinkLayerSecondaryBalanced;
typedef struIEC101_LinkLayerSecondaryBalanced* pIEC101_LinkLayerSecondaryBalanced;
typedef struct {
//enumIEC101_LinkLayerState state;
BOOLEAN expectedFcb; /* expected value of next frame count bit (FCB) */
struIEC101_LinkLayerParameters linkLayerParameters;
//QWORD lastReceivedMsg;
//int idleTimeout; /* connection timeout in ms */
} struIEC101_LinkLayerSecondaryUnbalanced;
typedef struIEC101_LinkLayerSecondaryUnbalanced* pIEC101_LinkLayerSecondaryUnbalanced;
typedef struct {
short size;
BYTE buffer[256];
} struIEC101_QueueElement;
typedef struIEC101_QueueElement* pIEC101_QueueElement;
class CIEC101_Queue
{
public:
CIEC101_Queue()
{
initialize(-1);
}
CIEC101_Queue(int maxQueueSize)
{
initialize(maxQueueSize);
}
virtual ~CIEC101_Queue()
{
dispose();
};
private:
int m_size;
int m_entryCounter;
int m_lastMsgIndex;
int m_firstMsgIndex;
pIEC101_QueueElement m_elements;
sem_t m_queueLock;
public:
inline void initialize(int maxQueueSize)
{
m_entryCounter = 0;
m_firstMsgIndex = 0;
m_lastMsgIndex = 0;
m_size = maxQueueSize;
int queueSize = maxQueueSize;
if (maxQueueSize == -1) queueSize = DATABASE_YXBW_NUM;
m_elements = new struIEC101_QueueElement[queueSize];
m_size = queueSize;
sem_init(&m_queueLock, 0, 1);
}
inline void dispose(void)
{
sem_destroy(&m_queueLock);
delete [] m_elements;
}
inline void lock(void)
{
sem_wait(&m_queueLock);
}
inline void unlock(void)
{
sem_post(&m_queueLock);
}
inline void enqueue(BYTE* buffer, int msgSize)
{
lock();
int nextIndex;
BOOLEAN removeEntry = FALSE;
if (m_entryCounter == 0)
{
m_firstMsgIndex = 0;
nextIndex = 0;
}
else
{
nextIndex = m_lastMsgIndex + 1;
}
if (nextIndex == m_size) nextIndex = 0;
if (m_entryCounter == m_size) removeEntry = TRUE;
if (removeEntry == FALSE)
{
m_lastMsgIndex = nextIndex;
m_entryCounter++;
}
else
{
m_lastMsgIndex = nextIndex;
int firstIndex = nextIndex + 1;
if (firstIndex == m_size) firstIndex = 0;
m_firstMsgIndex = firstIndex;
}
memcpy(m_elements[nextIndex].buffer, buffer, msgSize);
m_elements[nextIndex].size = msgSize;
unlock();
}
inline pIEC101_QueueElement dequeue(void)
{
if (m_entryCounter != 0)
{
int currentIndex = m_firstMsgIndex;
m_firstMsgIndex = (currentIndex + 1) % m_size;
m_entryCounter--;
return &m_elements[currentIndex];
}
return NULL;
}
inline BOOLEAN isFull(void)
{
return (m_entryCounter == m_size);
}
inline BOOLEAN isEmpty(void)
{
return (m_entryCounter == 0);
}
void flush(void)
{
lock();
m_entryCounter = 0;
m_firstMsgIndex = 0;
m_lastMsgIndex = 0;
unlock();
}
};
class CIEC101ProcessItem : public CPortProcessItem
{
public:
struIEC101_LinkLayerPrimaryUnbalanced primaryLinkUnbalanced;
struIEC101_LinkLayerPrimaryBalanced primaryLinkBalanced;
struIEC101_LinkLayerSecondaryBalanced secondaryLinkBalanced;
struIEC101_LinkLayerSecondaryUnbalanced secondaryLinkUnbalanced;
struIEC101_AppLayerParameters applicationlParameters;
int address; //own address
int common_address;
//平衡模式下主协议的数据列表
CIEC101_Queue userDataQueue;
//从协议下的数据列表
CIEC101_Queue userDataClass1Queue;
CIEC101_Queue userDataClass2Queue;
public:
BOOLEAN end_of_initialisation;
BOOLEAN clock_synchronized_start;
BOOLEAN clock_synchronized_finish;
BOOLEAN interrogation_start;
BOOLEAN interrogation_yx_fin;
BOOLEAN interrogation_yc_fin;
BOOLEAN interrogation_finish;
BOOLEAN pulse_start;
BOOLEAN pulse_fin;
DWORD apdu_t4_begin;
DWORD apdu_t5_begin;
DWORD background_scan_begin;
int total_yx;
int total_yc;
int total_ym;
int total_yk;
int yx_pos;
int yc_pos;
int ym_pos;
int call_type;
BYTE yk_value;
YCBWBuffer ycbws;
YXBWBuffer yxbws;
EventBuffer events;
int yx_start_address;
int yc_start_address;
int ym_start_address;
public:
CIEC101ProcessItem();
virtual ~CIEC101ProcessItem();
public:
void Attach(int uid, int phy_addr = 0, int common_addr = 0, int originatorAddress = 0);
void Release(void);
inline void setAppLayerParameters(int sizeOfCOT = 1, int sizeOfCA = 1, int sizeOfIOA = 2, int maxSizeOfASDU = 254)
{
applicationlParameters.sizeOfTypeId = 1;
applicationlParameters.sizeOfVSQ = 1;
applicationlParameters.sizeOfCOT = sizeOfCOT;
applicationlParameters.sizeOfCA = sizeOfCA;
applicationlParameters.sizeOfIOA = sizeOfIOA;
applicationlParameters.maxSizeOfASDU = maxSizeOfASDU;
}
inline void setAppLayerIOABase(int yx = 0, int yc = 0, int ym = 0)
{
yx_start_address = IEC_101_104_YX_START_ADDR;
yc_start_address = IEC_101_104_YC_START_ADDR;
ym_start_address = IEC_101_104_YM_START_ADDR;
if (yx > 0) yx_start_address = yx;
if (yc > 0) yc_start_address = yc;
if (ym > 0) ym_start_address = ym;
}
};
class CIEC101Process : public CPortProcess
{
public:
enum
{
llSecUnbalanced,
llSecBalanced,
llPriBalanced,
llPriUnbalanced,
};
public:
int m_nNeedCount;
int m_nState;
DWORD m_nCount;
DWORD m_nSendPoint;
DWORD m_nCurFrame;
short m_nTimeout;
struIEC101Option m_option;
struIEC101_LinkLayer m_linkLayer;
time_t last_sec;
public:
int apdu_t4_max;
int apdu_t5_max;
BOOLEAN use_cycle_interrogation_command;
public:
CIEC101Process();
virtual ~CIEC101Process();
CPortProcessItem *CreateItem(int ord);
void DestroyItem(int ord, BOOLEAN bDeleted = FALSE);
BOOLEAN OnPreCreate(int id);
virtual BOOLEAN Run(void);
virtual BOOLEAN OnTimer(void);
void GetItemYXBWs(CIEC101ProcessItem* pItem);
void GetItemEvents(CIEC101ProcessItem* pItem);
void GetItemYCBWs(CIEC101ProcessItem* pItem);
virtual int OnPackageReceived(BYTE* pBuf, int count, int ord = -1);
private:
virtual void LinkLayerSecondaryBalanced_ReceivedMessage(BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, int address, BYTE* msg, int userDataStart, int userDataLength) {};
virtual void LinkLayerSecondaryUnbalanced_ReceivedMessage(BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, int address, BYTE* msg, int userDataStart, int userDataLength) {};
virtual void LinkLayerPrimaryBalanced_ReceivedMessage(BYTE fc, BOOLEAN dir, BOOLEAN dfc, int address, BYTE* msg, int userDataStart, int userDataLength);
virtual void LinkLayerPrimaryBalanced_resetIdleTimeout() {};
virtual void LinkLayerPrimaryUnbalanced_ReceivedMessage(BYTE fc, BOOLEAN acd, BOOLEAN dfc, int address, BYTE* msg, int userDataStart, int userDataLength) {};
inline void SendMessage(const BYTE* msg, int msgSize)
{
DisplayTxData((BYTE *)msg, msgSize, TRUE);
WriteData(msg, msgSize);
m_nSendPoint = system32.ticks;
}
public:
inline int LinkLayer_getBroadcastAddress(void)
{
if (m_linkLayer.linkLayerParameters.addressLength == 1)
{
return 255;
}
else if (m_linkLayer.linkLayerParameters.addressLength == 2)
{
return 65535;
}
return 0;
}
inline int ASDU_initialize(BYTE* pBuf, pIEC101_AppLayerParameters parameters, BYTE typeId, BOOLEAN isSequence, BYTE cot, int oa, int ca, BOOLEAN isTest = FALSE, BOOLEAN isNegative = FALSE)
{
BYTE* encodedData = pBuf;
encodedData[0] = (BYTE)typeId;
if (isSequence) encodedData[1] = 0x80;
else encodedData[1] = 0;
encodedData[2] = (BYTE)(cot & 0x3f);
if (isTest) encodedData[2] |= 0x80;
if (isNegative) encodedData[2] |= 0x40;
int caIndex;
if (parameters->sizeOfCOT > 1)
{
encodedData[3] = (BYTE)oa;
caIndex = 4;
}
else caIndex = 3;
encodedData[caIndex] = ca % 0x100;
if (parameters->sizeOfCA > 1) encodedData[caIndex + 1] = ca / 0x100;
return (caIndex + parameters->sizeOfCA);
}
inline int InformationObject_setObjectAddress(pIEC101_AppLayerParameters parameters, BYTE* buffer, int ioa, BOOLEAN isSequence)
{
if (!isSequence)
{
buffer[0] = (BYTE)(ioa & 0xff);
if (parameters->sizeOfIOA > 1)
{
buffer[1] = (BYTE)((ioa / 0x100) & 0xff);
}
if (parameters->sizeOfIOA > 2)
{
buffer[2] = (BYTE)((ioa / 0x10000) & 0xff);
}
return parameters->sizeOfIOA;
}
return 0;
}
inline TypeID ASDU_getTypeID(BYTE* asdu)
{
return (TypeID)(asdu[0]);
}
inline void ASDU_setTypeID(BYTE* asdu, TypeID typeId)
{
asdu[0] = (BYTE)typeId;
}
inline BOOLEAN ASDU_isTest(BYTE* asdu)
{
if ((asdu[2] & 0x80) == 0x80) return TRUE;
return FALSE;
}
inline void ASDU_setTest(BYTE*asdu, BOOLEAN value)
{
if (value) asdu[2] |= 0x80;
asdu[2] &= ~(0x80);
}
inline BOOLEAN ASDU_isNegative(BYTE* asdu)
{
if ((asdu[2] & 0x40) == 0x40) return TRUE;
return FALSE;
}
inline void ASDU_setNegative(BYTE* asdu, BOOLEAN value)
{
if (value) asdu[2] |= 0x40;
else asdu[2] &= ~(0x40);
}
inline int ASDU_getOA(pIEC101_AppLayerParameters parameters, BYTE* asdu)
{
if (parameters->sizeOfCOT < 2) return -1;
return (int)asdu[3];
}
inline BYTE ASDU_getCOT(BYTE* asdu)
{
return (BYTE)(asdu[2] & 0x3f);
}
inline void ASDU_setCOT(BYTE* asdu, BYTE value)
{
BYTE cot = asdu[2] & 0xc0;
cot += ((int)value) & 0x3f;
asdu[2] = cot;
}
inline int ASDU_getCA(pIEC101_AppLayerParameters parameters, BYTE* asdu)
{
int caIndex = 2 + parameters->sizeOfCOT;
int ca = asdu[caIndex];
if (parameters->sizeOfCA > 1) ca += (asdu[caIndex + 1] * 0x100);
return ca;
}
inline void ASDU_setCA(pIEC101_AppLayerParameters parameters, BYTE* asdu, int ca)
{
int caIndex = 2 + parameters->sizeOfCOT;
int setCa = ca;
/* Check if CA is in range and adjust if not */
if (ca < 0) setCa = 0;
else
{
if (parameters->sizeOfCA == 1)
{
if (ca > 255) setCa = 255;
}
else if (parameters->sizeOfCA > 1)
{
if (ca > 65535) setCa = 65535;
}
}
if (parameters->sizeOfCA == 1)
{
asdu[caIndex] = (BYTE)setCa;
}
else
{
asdu[caIndex] = (BYTE) (setCa % 0x100);
asdu[caIndex + 1] = (BYTE) (setCa / 0x100);
}
}
inline int ASDU_getNumberOfElements(BYTE* asdu)
{
return (asdu[1] & 0x7f);
}
inline void ASDU_setNumberOfElements(BYTE* asdu, int value)
{
asdu[1] += value;
}
inline void ASDU_addNumberOfElements(BYTE* asdu)
{
asdu[1] ++;
}
inline BOOLEAN ASDU_isSequence(BYTE* asdu)
{
if ((asdu[1] & 0x80) != 0) return TRUE;
else return FALSE;
}
inline void ASDU_setSequence(BYTE* asdu, BOOLEAN isSequence)
{
if (isSequence) asdu[1] |= 0x80;
else asdu[1] &= 0x7f;
}
inline int ASDU_getIOA(pIEC101_AppLayerParameters parameters, BYTE* asdu)
{
int ioa = asdu[0];
if (parameters->sizeOfIOA > 1) ioa += (asdu[1] * 0x100);
if (parameters->sizeOfIOA > 2) ioa += (asdu[2] * 0x10000);
return ioa;
}
void SendSingleCharCharacter(void);
void SendFixedFrame(BYTE fc, int address, BOOLEAN prm, BOOLEAN dir, BOOLEAN acd /*FCB*/, BOOLEAN dfc /*FCV*/);
void SendVariableLengthFrame(BYTE fc, int address, BOOLEAN prm, BOOLEAN dir, BOOLEAN acd, BOOLEAN dfc, BYTE* userData, int userDataLength);
public:
inline BOOLEAN IsClass1DataAvailable(CIEC101ProcessItem* pItem)
{
return (pItem->userDataClass1Queue.isEmpty() == FALSE);
}
inline pIEC101_QueueElement GetClass1Data(CIEC101ProcessItem* pItem)
{
pIEC101_QueueElement element = NULL;
pItem->userDataClass1Queue.lock();
element = pItem->userDataClass1Queue.dequeue();
pItem->userDataClass1Queue.unlock();
return element;
}
inline BOOLEAN IsClass2DataAvailable(CIEC101ProcessItem* pItem)
{
return (pItem->userDataClass2Queue.isEmpty() == FALSE);
}
inline pIEC101_QueueElement GetClass2Data(CIEC101ProcessItem* pItem)
{
pIEC101_QueueElement element;
pItem->userDataClass2Queue.lock();
element = pItem->userDataClass2Queue.dequeue();
pItem->userDataClass2Queue.unlock();
return element;
}
inline virtual pIEC101_QueueElement ApplicationLayer_GetUserData(CIEC101ProcessItem* pItem)
{
if (m_linkLayer.mode == llPriBalanced)
{
pIEC101_QueueElement element;
pItem->userDataQueue.lock();
element = pItem->userDataQueue.dequeue();
pItem->userDataQueue.unlock();
return element;
}
else
{
if (IsClass1DataAvailable(pItem)) return GetClass1Data(pItem);
else if (IsClass2DataAvailable(pItem)) return GetClass2Data(pItem);
}
return NULL;
}
inline void llpb_setNewState(pIEC101_LinkLayerPrimaryBalanced pItem, enumIEC101_LinkLayerState newState)
{
if (newState != pItem->state)
{
pItem->state = newState;
}
}
void LinkLayerPrimaryBalanced_runStateMachine(CIEC101ProcessItem *pItem);
};
class CIEC101PrimaryProcess : public CIEC101Process
{
public:
CIEC101PrimaryProcess() {};
virtual ~CIEC101PrimaryProcess() {};
private:
virtual void LinkLayerPrimaryBalanced_resetIdleTimeout() {};
virtual void LinkLayerPrimaryUnbalanced_ReceivedMessage(BYTE fc, BOOLEAN acd, BOOLEAN dfc, int address, BYTE* msg, int userDataStart, int userDataLength) {};
public:
virtual BOOLEAN Master_isChannelReady(int address) { return FALSE; };
virtual void Master_sendLinkLayerTestFunction(void) {};
inline void Master_sendInterrogationCommand(CIEC101ProcessItem* pItem, BYTE cot, QualifierOfInterrogation qoi)
{
BYTE asdu[260];
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_IC_NA_1, FALSE, cot, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
ASDU_addNumberOfElements(asdu);
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], 0, FALSE);
asdu[len++] = qoi;
Master_sendASDU(pItem, asdu, len);
}
inline void Master_sendCounterInterrogationCommand(CIEC101ProcessItem* pItem, BYTE cot, QualifierOfCIC qcc)
{
BYTE asdu[260];
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_CI_NA_1, FALSE, cot, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
ASDU_addNumberOfElements(asdu);
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], 0, FALSE);
asdu[len++] = qcc;
Master_sendASDU(pItem, asdu, len);
}
inline void Master_sendClockSyncCommand(CIEC101ProcessItem* pItem)
{
BYTE asdu[260];
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_CS_NA_1, FALSE, IEC_101_104_COT_ACT, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
ASDU_addNumberOfElements(asdu);
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], 0, FALSE);
len += unionCP56TimeToBuf(&asdu[len], system32.now);
Master_sendASDU(pItem, asdu, len);
}
#if 0
void Master_sendReadCommand(CIEC101ProcessItem* pItem, int ca, int ioa)
{
struStaticASDU _asdu;
ASDU asdu = ASDU_initializeStatic(&_asdu, &(self->alParameters), FALSE, IEC_101_104_COT_REQ, self->alParameters.originatorAddress, ca, FALSE, FALSE);
struct sReadCommand _io;
InformationObject io = (InformationObject) ReadCommand_create(&_io, ioa);
ASDU_addInformationObject(asdu, io);
Master_sendASDU(pItem, asdu, len);
}
void Master_sendTestCommand(CIEC101ProcessItem* pItem, int ca)
{
BYTE asdu[260];
int len = ASDU_initialize(&asdu, &(pItem->applicationlParameters), FALSE, IEC_101_104_COT_ACT, pItem->applicationlParameters.originatorAddress, ca, FALSE, FALSE);
struct sTestCommand _io;
InformationObject io = (InformationObject) TestCommand_create(&_io);
ASDU_addInformationObject(asdu, io);
Master_sendASDU(pItem, asdu, len);
}
void Master_sendProcessCommand(CIEC101ProcessItem* pItem, BYTE cot, int ca, InformationObject command)
{
BYTE asdu[260];
int len = ASDU_initialize(&asdu, &(pItem->applicationlParameters), FALSE, cot, pItem->applicationlParameters.originatorAddress, ca, FALSE, FALSE);
ASDU_addInformationObject(asdu, command);
Master_sendASDU(pItem, asdu, len);
}
#endif
inline BOOLEAN isBroadcastAddress(CIEC101ProcessItem* pItem, int address)
{
if (m_linkLayer.linkLayerParameters.addressLength == 1)
{
return (address == 255);
}
else if (m_linkLayer.linkLayerParameters.addressLength == 2)
{
return (address == 65535);
}
return FALSE;
}
virtual void Master_sendASDU(CIEC101ProcessItem*, BYTE*, int) {};
BOOLEAN OnReceiveSingle_point_information(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveSingle_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveSingle_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveDouble_point_information(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveDouble_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveDouble_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_normalised(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_scaled(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_short_floating_point(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_normalised_without_quality(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_normalised_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_scaled_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_short_floating_point_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_normalised_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_scaled_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveMeasured_value_short_floating_point_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveIntegrated_totals(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveInterrogation_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveClock_synchronisation_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveCounter_Interrogation_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveSingle_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveDouble_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveSet_point_command_normalized(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveSet_point_command_scaled(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
BOOLEAN OnReceiveSet_point_command_short_floating(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot);
void PrimaryApplicationLayer_UserData(CIEC101ProcessItem* pItem, int slaveAddress, BYTE* msg, int start, int length)
{
BYTE *asdu = msg + start;
BYTE tid = ASDU_getTypeID(asdu);
BYTE cot = ASDU_getCOT(asdu);
BOOLEAN isSequence = ASDU_isSequence(asdu);
BOOLEAN isNegative = ASDU_isNegative(asdu);
BOOLEAN isTest = ASDU_isTest(asdu);
int num = ASDU_getNumberOfElements(asdu);
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
BYTE *pData = asdu + parameters->sizeOfTypeId + parameters->sizeOfVSQ + parameters->sizeOfCOT + parameters->sizeOfCA;
switch (tid)
{
case M_SP_NA_1:
OnReceiveSingle_point_information(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_SP_TA_1:
OnReceiveSingle_point_information_with_time_tag(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_DP_NA_1:
OnReceiveDouble_point_information(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_DP_TA_1:
OnReceiveDouble_point_information_with_time_tag(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_NA_1:
OnReceiveMeasured_value_normalised(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_TA_1:
OnReceiveMeasured_value_normalised_with_time_tag(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_NB_1:
OnReceiveMeasured_value_scaled(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_TB_1:
OnReceiveMeasured_value_scaled_with_time_tag(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_NC_1:
OnReceiveMeasured_value_short_floating_point(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_TC_1:
OnReceiveMeasured_value_short_floating_point_with_time_tag(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_ND_1:
OnReceiveMeasured_value_normalised_without_quality(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_SP_TB_1:
OnReceiveSingle_point_information_with_time_tag_cp56time2a(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_DP_TB_1:
OnReceiveDouble_point_information_with_time_tag_cp56time2a(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_TD_1:
OnReceiveMeasured_value_normalised_with_time_tag_cp56time2a(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_TE_1:
OnReceiveMeasured_value_scaled_with_time_tag_cp56time2a(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_ME_TF_1:
OnReceiveMeasured_value_short_floating_point_with_time_tag_cp56time2a(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_IT_NA_1:
OnReceiveIntegrated_totals(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_SC_NA_1:
OnReceiveSingle_command(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_DC_NA_1:
OnReceiveDouble_command(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_SE_NA_1:
OnReceiveSet_point_command_normalized(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_SE_NB_1:
OnReceiveSet_point_command_scaled(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_SE_NC_1:
OnReceiveSet_point_command_short_floating(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_IC_NA_1:
OnReceiveInterrogation_command(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_CS_NA_1:
OnReceiveClock_synchronisation_command(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case C_CI_NA_1:
OnReceiveCounter_Interrogation_command(pItem, pData, isSequence, isNegative, isTest, num, cot);
break;
case M_EI_NA_1:
pItem->end_of_initialisation = TRUE;
break;
default:
vLog(LOG_WARN, "Unit(%d) typedid is: %s, cot is: %d, and element number is: %d\n", pItem->GetUnitID(), val_to_str(tid, iec_101_104_asdu_types, "unknow(%d)"), cot, num);
break;
}
}
BOOLEAN GetYKFrame(CIEC101ProcessItem* pItem, int ord = -1);
BOOLEAN GetYTFrame(CIEC101ProcessItem* pItem, int ord = -1);
};
class CIEC101SecondaryProcess : public CIEC101Process
{
public:
CIEC101SecondaryProcess() {};
virtual ~CIEC101SecondaryProcess() {};
public:
BOOLEAN MakeYKFrame(CIEC101ProcessItem* pItem);
BOOLEAN MakeYTFrame(CIEC101ProcessItem* pItem);
BOOLEAN Receive_Interrogation_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //总召唤
BOOLEAN Receive_Clock_synchronisation_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //时钟同步
BOOLEAN Receive_Counter_interrogation_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //累积量
BOOLEAN Receive_Reset_process_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //复位进程
BOOLEAN Receive_Single_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //单点令
BOOLEAN Receive_Double_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //单点令
BOOLEAN Receive_Set_point_command_normalized(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //设定规一化值命令
BOOLEAN Receive_Set_point_command_scaled(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //设定标度化值命令
BOOLEAN Receive_Set_point_command_short_floating(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot); //设定短浮点值命令
BOOLEAN Send_End_of_initialisation(CIEC101ProcessItem* pItem);
BOOLEAN Send_Single_point_information(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Single_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Single_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Double_point_information(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Double_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Double_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Measured_value_normalised(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Measured_value_scaled(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Measured_value_short_floating_point(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Measured_value_normalised_without_quality(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_Integrated_totals(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_SPONT);
BOOLEAN Send_FrameInterrogation(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_ACTTREM);
BOOLEAN Send_FrameCounterInterrogation(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_ACTTREM);
BOOLEAN Send_Test_command(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_ACTTREM);
BOOLEAN Send_Test_command_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE cause_of_transimission = IEC_101_104_COT_ACTTREM);
public:
BOOLEAN ApplicationLayer_ReceivedData(CIEC101ProcessItem* pItem, BYTE* msg, BOOLEAN isBroadcast, int userDataStart, int userDataLength);
inline BOOLEAN Slave_isClass1QueueFull(CIEC101ProcessItem* pItem)
{
return pItem->userDataClass1Queue.isFull();
}
inline void Slave_enqueueUserDataClass1(CIEC101ProcessItem* pItem, BYTE* asdu, int msgSize)
{
pItem->userDataClass1Queue.enqueue(asdu, msgSize);
}
inline BOOLEAN Slave_isClass2QueueFull(CIEC101ProcessItem* pItem)
{
return pItem->userDataClass2Queue.isFull();
}
inline void Slave_enqueueUserDataClass2(CIEC101ProcessItem* pItem, BYTE* asdu, int msgSize)
{
pItem->userDataClass2Queue.enqueue(asdu, msgSize);
}
inline void Slave_flushQueues(CIEC101ProcessItem* pItem)
{
pItem->userDataClass1Queue.flush();
pItem->userDataClass2Queue.flush();
}
private:
inline BOOLEAN isSingleCommandChecked(BYTE yk_type, BYTE relay_type, BYTE value)
{
if (yk_type != USE_YK_SC) return FALSE;
if (relay_type)
{
if (relay_type == 1)
{ //Only on
if (!value) return FALSE;
}
else
{ //Only off
if (value) return FALSE;
}
}
return TRUE;
}
};
#endif //_ZJD_IEC101_PROCESS_H_