4221 lines
159 KiB
C++
4221 lines
159 KiB
C++
#include "iec101.h"
|
||
|
||
CIEC101ProcessItem::CIEC101ProcessItem()
|
||
{
|
||
end_of_initialisation = FALSE;
|
||
background_scan_begin = 0;
|
||
|
||
call_type = 0;
|
||
interrogation_start = FALSE; //总召启动
|
||
interrogation_yx_fin = FALSE; //遥信发送完毕
|
||
interrogation_yc_fin = FALSE; //遥测发送完毕
|
||
|
||
pulse_start = FALSE;
|
||
pulse_fin = FALSE;
|
||
|
||
clock_synchronized_start = FALSE;
|
||
clock_synchronized_finish = FALSE;
|
||
interrogation_start = FALSE;
|
||
interrogation_finish = FALSE;
|
||
|
||
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;
|
||
|
||
//LinkLayerPrimaryBalanced_init
|
||
primaryLinkBalanced.primaryState = PLL_IDLE;
|
||
primaryLinkBalanced.state = LL_STATE_IDLE;
|
||
primaryLinkBalanced.waitingForResponse = FALSE;
|
||
primaryLinkBalanced.sendLinkLayerTestFunction = FALSE;
|
||
primaryLinkBalanced.nextFcb = TRUE;
|
||
primaryLinkBalanced.idleTimeout = 5000;
|
||
primaryLinkBalanced.otherStationAddress = 0;
|
||
|
||
//LinkLayerSecondaryBalanced_init
|
||
secondaryLinkBalanced.expectedFcb = TRUE;
|
||
|
||
//LinkLayerSecondaryUnbalanced_init
|
||
secondaryLinkUnbalanced.expectedFcb = TRUE;
|
||
|
||
applicationlParameters.sizeOfTypeId = 1;
|
||
applicationlParameters.sizeOfVSQ = 1;
|
||
applicationlParameters.sizeOfCOT = 1;
|
||
applicationlParameters.originatorAddress = 0;
|
||
applicationlParameters.sizeOfCA = 1;
|
||
applicationlParameters.sizeOfIOA = 2;
|
||
applicationlParameters.maxSizeOfASDU = 254;
|
||
|
||
memset(&ycbws, 0, sizeof(ycbws));
|
||
memset(&yxbws, 0, sizeof(yxbws));
|
||
memset(&events, 0, sizeof(events));
|
||
}
|
||
|
||
CIEC101ProcessItem::~CIEC101ProcessItem()
|
||
{
|
||
|
||
}
|
||
|
||
void CIEC101ProcessItem::Attach(int uid, int physicsAddress /* = 0 */, int commonAddress /* = 0 */, int originatorAddress /* = 0 */)
|
||
{
|
||
CPortProcessItem::Attach(uid, physicsAddress, commonAddress, originatorAddress);
|
||
}
|
||
|
||
void CIEC101ProcessItem::Release(void)
|
||
{
|
||
CPortProcessItem::Release();
|
||
}
|
||
|
||
CIEC101Process::CIEC101Process()
|
||
{
|
||
apdu_t4_max = 0; //t4的最大值(设定)
|
||
apdu_t5_max = 0; //t5的最大值(设定)
|
||
|
||
m_linkLayer.linkLayerParameters.addressLength = 1;
|
||
m_linkLayer.linkLayerParameters.useSingleCharACK = TRUE;
|
||
m_linkLayer.linkLayerParameters.timeoutForACK = 200;
|
||
m_linkLayer.linkLayerParameters.timeoutRepeat = 1000;
|
||
}
|
||
|
||
CIEC101Process::~CIEC101Process()
|
||
{
|
||
}
|
||
|
||
CPortProcessItem *CIEC101Process::CreateItem(int ord)
|
||
{
|
||
return dynamic_cast<CPortProcessItem *>(new CIEC101ProcessItem);
|
||
}
|
||
|
||
void CIEC101Process::DestroyItem(int ord, BOOLEAN bDeleted /* = FALSE */)
|
||
{
|
||
CIEC101ProcessItem *pItem = (CIEC101ProcessItem *)GetItem(ord);
|
||
if (pItem != NULL && !bDeleted)
|
||
{
|
||
delete pItem;
|
||
return CPortProcess::DestroyItem(ord, TRUE);
|
||
}
|
||
|
||
return CPortProcess::DestroyItem(ord, bDeleted);
|
||
}
|
||
|
||
BOOLEAN CIEC101Process::OnPreCreate(int id)
|
||
{
|
||
if (!CPortProcess::OnPreCreate(id)) return FALSE;
|
||
|
||
if (GetOption(&m_option, sizeof(m_option)))
|
||
{
|
||
m_linkLayer.linkLayerParameters.addressLength = m_option.addressLength;
|
||
m_linkLayer.linkLayerParameters.useSingleCharACK = m_option.useSingleCharACK;
|
||
m_linkLayer.linkLayerParameters.timeoutForACK = m_option.timeoutForACK;
|
||
m_linkLayer.linkLayerParameters.timeoutRepeat = m_option.timeoutRepeat;
|
||
|
||
apdu_t4_max = m_option.t4;
|
||
apdu_t5_max = m_option.t5;
|
||
use_cycle_interrogation_command = m_option.use_cycle_interrogation_command;
|
||
}
|
||
m_nTimeout = GetTimeout();
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101Process::Run(void)
|
||
{
|
||
int i;
|
||
BOOLEAN bFailed;
|
||
BYTE checkSum;
|
||
BYTE buffer[512];
|
||
|
||
if (!CPortProcess::Run()) return FALSE;
|
||
|
||
memset(buffer, 0, sizeof(buffer));
|
||
if (m_nNeedCount < 1) m_nNeedCount = 1;
|
||
if (GetDataCount() < m_nNeedCount) return TRUE;
|
||
|
||
if (!GetData(buffer, m_nNeedCount))
|
||
{
|
||
vLog(LOG_ERROR, "%s GetData error!\n", __FILE__);
|
||
}
|
||
FeedDog();
|
||
bFailed = FALSE;
|
||
if (buffer[0] == 0xe5)
|
||
{
|
||
DropData(1);
|
||
DisplayRxData(buffer, 1, TRUE);
|
||
OnPackageReceived(buffer, 1);
|
||
m_nCurFrame = 0;
|
||
m_nNeedCount = 1;
|
||
m_nState = IEC101S_IDLE;
|
||
return TRUE;
|
||
}
|
||
if (m_nState == IEC101S_INFO)
|
||
{
|
||
if (buffer[0] == IEC101_STX2)
|
||
{
|
||
checkSum = buffer[m_nNeedCount - 2];
|
||
if (checkSum != GetCheckSum8(&buffer[4], buffer[1]))
|
||
{
|
||
DisplayRxData(buffer, m_nNeedCount, FALSE);
|
||
bFailed = TRUE;
|
||
}
|
||
else
|
||
{
|
||
DropData(m_nNeedCount);
|
||
DisplayRxData(buffer, m_nNeedCount, TRUE);
|
||
if (OnPackageReceived(buffer, m_nNeedCount) >= 0)
|
||
{
|
||
m_nCurFrame = 0;
|
||
}
|
||
m_nNeedCount = 1;
|
||
m_nState = IEC101S_IDLE;
|
||
}
|
||
}
|
||
else if (buffer[0] == IEC101_STX1)
|
||
{
|
||
checkSum = buffer[m_nNeedCount - 2];
|
||
if (checkSum != GetCheckSum8(&buffer[1], (m_nNeedCount - 3)))
|
||
{
|
||
DisplayRxData(buffer, m_nNeedCount, FALSE);
|
||
bFailed = TRUE;
|
||
}
|
||
else
|
||
{
|
||
DropData(m_nNeedCount);
|
||
DisplayRxData(buffer, m_nNeedCount, TRUE);
|
||
if (OnPackageReceived(buffer, m_nNeedCount) >= 0)
|
||
{
|
||
m_nCurFrame = 0;
|
||
}
|
||
m_nNeedCount = 1;
|
||
m_nState = IEC101S_IDLE;
|
||
}
|
||
}
|
||
}
|
||
else if (m_nState == IEC101S_SYNC)
|
||
{
|
||
if (buffer[0] == IEC101_STX2 && buffer[3] == IEC101_STX2 && buffer[1] == buffer[2])
|
||
{
|
||
m_nNeedCount = buffer[1] + 6;
|
||
m_nState = IEC101S_INFO;
|
||
}
|
||
else if (buffer[0] == IEC101_STX1 && buffer[m_nNeedCount - 1] == IEC101_ETX)
|
||
{
|
||
m_nState = IEC101S_INFO;
|
||
}
|
||
else
|
||
{
|
||
m_nNeedCount = 1;
|
||
bFailed = TRUE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (IEC101_STX2 == buffer[0])
|
||
{
|
||
m_nNeedCount = 4;
|
||
m_nState = IEC101S_SYNC;
|
||
}
|
||
else if (IEC101_STX1 == buffer[0])
|
||
{
|
||
m_nNeedCount = m_linkLayer.linkLayerParameters.addressLength + 4;
|
||
m_nState = IEC101S_SYNC;
|
||
}
|
||
else
|
||
{
|
||
m_nNeedCount = 1;
|
||
bFailed = TRUE;
|
||
}
|
||
}
|
||
if (bFailed)
|
||
{
|
||
for (i = 0; i < m_nNeedCount; i++)
|
||
{
|
||
if (buffer[i] == IEC101_STX1 || buffer[i] == IEC101_STX2)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (i == 0) i = 1;
|
||
if (i > 0)
|
||
{
|
||
DropData(i);
|
||
DisplayRxData(buffer, i, FALSE);
|
||
}
|
||
m_nState = IEC101S_IDLE;
|
||
m_nNeedCount = 1;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101Process::OnTimer(void)
|
||
{
|
||
if (!CPortProcess::OnTimer()) return FALSE;
|
||
|
||
m_nCount++;
|
||
|
||
if (m_nCurFrame != 0)
|
||
{
|
||
if (m_nSendPoint && (m_nSendPoint + m_nTimeout) <= system32.ticks)
|
||
{ //0.5 second command time out
|
||
m_nSendPoint = 0;
|
||
m_nCurFrame = 0;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
int CIEC101Process::OnPackageReceived(BYTE* pBuf, int msgSize, int /* ord = -1 */)
|
||
{
|
||
int userDataLength = 0;
|
||
int userDataStart = 0;
|
||
BYTE c = 0;
|
||
int csStart = 0;
|
||
int csIndex = 0;
|
||
int address = 0;
|
||
BOOLEAN prm = TRUE;
|
||
int fc = 0;
|
||
BOOLEAN isAck = FALSE;
|
||
|
||
BYTE* msg = (BYTE *)pBuf;
|
||
if (msg[0] == IEC101_STX2)
|
||
{
|
||
if (msg[1] != msg[2])
|
||
{
|
||
vLog(LOG_ERROR, "ERROR: L fields differ!\n");
|
||
return -1;
|
||
}
|
||
userDataLength = (int)msg[1] - m_linkLayer.linkLayerParameters.addressLength - 1;
|
||
userDataStart = 5 + m_linkLayer.linkLayerParameters.addressLength;
|
||
csStart = 4;
|
||
csIndex = userDataStart + userDataLength;
|
||
if (msgSize != (userDataStart + userDataLength + 2 /* CS + END */))
|
||
{
|
||
vLog(LOG_ERROR, "ERROR: Invalid message length\n");
|
||
return -1;
|
||
}
|
||
c = msg[4];
|
||
if (m_linkLayer.linkLayerParameters.addressLength > 0) address += msg[5];
|
||
if (m_linkLayer.linkLayerParameters.addressLength > 1) address += msg [6] * 0x100;
|
||
}
|
||
else if (msg[0] == IEC101_STX1)
|
||
{
|
||
c = msg[1];
|
||
csStart = 1;
|
||
csIndex = 2 + m_linkLayer.linkLayerParameters.addressLength;
|
||
if (m_linkLayer.linkLayerParameters.addressLength > 0) address += msg[2];
|
||
if (m_linkLayer.linkLayerParameters.addressLength > 1) address += msg[3] * 0x100;
|
||
}
|
||
else if (msg[0] == 0xe5)
|
||
{
|
||
isAck = TRUE;
|
||
fc = LL_FC_00_ACK;
|
||
prm = FALSE; /* single char ACK is only sent by secondary station */
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_ERROR, "Received unexpected message type!\n");
|
||
return -1;
|
||
}
|
||
if (isAck == FALSE)
|
||
{ /* parse C field bits */
|
||
fc = c & 0x0f;
|
||
prm = ((c & 0x40) == 0x40);
|
||
if (prm)
|
||
{ /* we are secondary link layer */
|
||
//本程序为IEC101从协议。
|
||
BOOLEAN fcb = ((c & 0x20) == 0x20);
|
||
BOOLEAN fcv = ((c & 0x10) == 0x10);
|
||
if (m_linkLayer.mode == llSecBalanced)
|
||
{
|
||
LinkLayerSecondaryBalanced_ReceivedMessage(fc, FALSE, fcb, fcv, address, msg, userDataStart, userDataLength);
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_DEBUG, "No secondary link layer available!\n");
|
||
}
|
||
if (m_linkLayer.mode == llPriBalanced)
|
||
{
|
||
LinkLayerPrimaryBalanced_resetIdleTimeout();
|
||
}
|
||
}
|
||
else
|
||
{ /* we are primary link layer */
|
||
//本程序为IEC101主协议。
|
||
BOOLEAN dir = ((c & 0x80) == 0x80); /* DIR - direction for balanced transmission */
|
||
BOOLEAN dfc = ((c & 0x10) == 0x10); /* DFC - Data flow control */
|
||
|
||
if (m_linkLayer.mode == llPriBalanced || m_linkLayer.mode == llSecBalanced)
|
||
{
|
||
LinkLayerPrimaryBalanced_ReceivedMessage(fc, dir, dfc, address, msg, userDataStart, userDataLength);
|
||
}
|
||
else if (m_linkLayer.mode == llPriUnbalanced)
|
||
{
|
||
BOOLEAN acd = ((c & 0x20) == 0x20); /* ACD - access demand for class 1 data - for unbalanced transmission */
|
||
LinkLayerPrimaryUnbalanced_ReceivedMessage(fc, acd, dfc, address, msg, userDataStart, userDataLength);
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_DEBUG, "No primary link layer available!\n");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{ /* Single byte ACK */
|
||
//本程序为IEC101主协议。
|
||
if (m_linkLayer.mode == llPriBalanced || m_linkLayer.mode == llSecBalanced)
|
||
{
|
||
LinkLayerPrimaryBalanced_ReceivedMessage(LL_FC_00_ACK, FALSE, FALSE, -1, NULL, 0, 0);
|
||
}
|
||
else if (m_linkLayer.mode == llPriUnbalanced)
|
||
{
|
||
LinkLayerPrimaryUnbalanced_ReceivedMessage(LL_FC_00_ACK, FALSE, FALSE, -1, NULL, 0, 0);
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_DEBUG, "No primary link layer available!\n");
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
//平衡方式主协议接收到从站报文
|
||
void CIEC101Process::LinkLayerPrimaryBalanced_ReceivedMessage(BYTE fc, BOOLEAN dir, BOOLEAN dfc, int address, BYTE* msg, int userDataStart, int userDataLength)
|
||
{
|
||
UNUSED(dir);
|
||
//UNUSED(address);
|
||
UNUSED(msg);
|
||
UNUSED(userDataStart);
|
||
UNUSED(userDataLength);
|
||
|
||
CIEC101ProcessItem* pItem;
|
||
if (address == -1) pItem = (CIEC101ProcessItem *)GetCurItem();
|
||
else
|
||
{
|
||
int uid = GetUnitByAddr((BYTE *)&address, m_linkLayer.linkLayerParameters.addressLength);
|
||
if (uid < 0 || uid >= UNIT_NUM) return;
|
||
pItem = (CIEC101ProcessItem *)GetItem(GetOrderByUnitID(uid));
|
||
}
|
||
if (pItem == NULL)
|
||
{
|
||
vLog(LOG_DEBUG, "PLL RECV - response from unknown slave %i\n", address);
|
||
return;
|
||
}
|
||
|
||
pIEC101_LinkLayerPrimaryBalanced self = &(pItem->primaryLinkBalanced);
|
||
enumIEC101_PrimaryLinkLayerState primaryState = self->primaryState;
|
||
enumIEC101_PrimaryLinkLayerState newState = primaryState;
|
||
|
||
self->lastReceivedMsg = getTimeInMs();
|
||
if (dfc)
|
||
{
|
||
switch (self->primaryState)
|
||
{
|
||
case PLL_EXECUTE_REQUEST_STATUS_OF_LINK:
|
||
case PLL_EXECUTE_RESET_REMOTE_LINK:
|
||
newState = PLL_EXECUTE_REQUEST_STATUS_OF_LINK;
|
||
break;
|
||
case PLL_EXECUTE_SERVICE_SEND_CONFIRM:
|
||
case PLL_SECONDARY_LINK_LAYER_BUSY:
|
||
newState = PLL_SECONDARY_LINK_LAYER_BUSY;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
llpb_setNewState(self, LL_STATE_BUSY);
|
||
self->primaryState = newState;
|
||
return;
|
||
}
|
||
switch (fc)
|
||
{
|
||
case LL_FC_00_ACK:
|
||
//vLog(LOG_DEBUG, "PLL - RECV FC 00 - ACK\n");
|
||
if (primaryState == PLL_EXECUTE_RESET_REMOTE_LINK)
|
||
{
|
||
newState = PLL_LINK_LAYERS_AVAILABLE;
|
||
llpb_setNewState(self, LL_STATE_AVAILABLE);
|
||
}
|
||
else if (primaryState == PLL_EXECUTE_SERVICE_SEND_CONFIRM)
|
||
{
|
||
if (self->sendLinkLayerTestFunction)
|
||
{
|
||
self->sendLinkLayerTestFunction = FALSE;
|
||
}
|
||
newState = PLL_LINK_LAYERS_AVAILABLE;
|
||
llpb_setNewState(self, LL_STATE_AVAILABLE);
|
||
}
|
||
self->waitingForResponse = FALSE;
|
||
break;
|
||
case LL_FC_01_NACK:
|
||
//vLog(LOG_DEBUG, "PLL - RECV FC 01 - NACK\n");
|
||
if (primaryState == PLL_EXECUTE_SERVICE_SEND_CONFIRM)
|
||
{
|
||
newState = PLL_SECONDARY_LINK_LAYER_BUSY;
|
||
llpb_setNewState(self, LL_STATE_BUSY);
|
||
}
|
||
break;
|
||
case LL_FC_08_RESP_USER_DATA:
|
||
//vLog(LOG_DEBUG, "PLL - RECV FC 08 - RESP USER DATA\n");
|
||
newState = PLL_IDLE;
|
||
llpb_setNewState(self, LL_STATE_ERROR);
|
||
break;
|
||
case LL_FC_09_RESP_NACK_NO_DATA:
|
||
//vLog(LOG_DEBUG, "PLL - RECV FC 09 - RESP NACK - NO DATA\n");
|
||
newState = PLL_IDLE;
|
||
llpb_setNewState(self, LL_STATE_ERROR);
|
||
break;
|
||
case LL_FC_11_STATUS_OF_LINK_OR_ACCESS_DEMAND:
|
||
//vLog(LOG_DEBUG, "PLL - RECV FC 11 - STATUS OF LINK\n");
|
||
if (primaryState == PLL_EXECUTE_REQUEST_STATUS_OF_LINK)
|
||
{
|
||
vLog(LOG_DEBUG, "PLL - SEND FC 00 - RESET REMOTE LINK\n");
|
||
SendFixedFrame(LL_FC_00_RESET_REMOTE_LINK, self->otherStationAddress, TRUE, m_linkLayer.dir, FALSE, FALSE);
|
||
self->lastSendTime = getTimeInMs();
|
||
self->waitingForResponse = TRUE;
|
||
newState = PLL_EXECUTE_RESET_REMOTE_LINK;
|
||
llpb_setNewState(self, LL_STATE_BUSY);
|
||
}
|
||
else
|
||
{ /* illegal message in this state */
|
||
newState = PLL_IDLE;
|
||
llpb_setNewState(self, LL_STATE_ERROR);
|
||
}
|
||
break;
|
||
case LL_FC_14_SERVICE_NOT_FUNCTIONING:
|
||
case LL_FC_15_SERVICE_NOT_IMPLEMENTED:
|
||
//vLog(LOG_DEBUG, "PLL - link layer service not functioning/not implemented in secondary station\n");
|
||
if (self->sendLinkLayerTestFunction)
|
||
{
|
||
self->sendLinkLayerTestFunction = FALSE;
|
||
}
|
||
if (primaryState == PLL_EXECUTE_SERVICE_SEND_CONFIRM)
|
||
{
|
||
newState = PLL_LINK_LAYERS_AVAILABLE;
|
||
llpb_setNewState(self, LL_STATE_AVAILABLE);
|
||
}
|
||
break;
|
||
default:
|
||
//vLog(LOG_DEBUG, "UNEXPECTED SECONDARY LINK LAYER MESSAGE\n");
|
||
break;
|
||
}
|
||
//vLog(LOG_DEBUG, "PLL RECV - old state: %i new state %i\n", primaryState, newState);
|
||
self->primaryState = newState;
|
||
}
|
||
|
||
void CIEC101Process::SendSingleCharCharacter(void)
|
||
{
|
||
BYTE singleCharAck[] = {0xe5};
|
||
SendMessage(singleCharAck, 1);
|
||
|
||
m_nCurFrame = 1;
|
||
}
|
||
|
||
void CIEC101Process::SendFixedFrame(BYTE fc, int address, BOOLEAN prm, BOOLEAN dir, BOOLEAN acd /*FCB*/, BOOLEAN dfc /*FCV*/)
|
||
{
|
||
BYTE buffer[16];
|
||
int bufPos = 0;
|
||
int addressLength = m_linkLayer.linkLayerParameters.addressLength;
|
||
|
||
buffer[bufPos++] = IEC101_STX1; /* START */
|
||
BYTE c = fc & 0x0f;
|
||
if (prm) c += 0x40;
|
||
if (dir) c += 0x80;
|
||
if (acd) c += 0x20;
|
||
if (dfc) c += 0x10;
|
||
buffer[bufPos++] = c;
|
||
if (addressLength > 0)
|
||
{
|
||
buffer [bufPos++] = (BYTE)(address & 0xFF);
|
||
if (addressLength > 1)
|
||
{
|
||
buffer [bufPos++] = (BYTE) ((address >> 4) & 0xFF);
|
||
}
|
||
}
|
||
BYTE checksum = 0;
|
||
int i;
|
||
for (i = 1; i < bufPos; i++) checksum += buffer[i];
|
||
buffer[bufPos++] = checksum;
|
||
buffer[bufPos++] = IEC101_ETX; /* END */
|
||
//vLog(LOG_DEBUG, "Send fixed frame (fc=%i)\n", fc);
|
||
SendMessage(buffer, bufPos);
|
||
|
||
m_nCurFrame = 2;
|
||
}
|
||
|
||
void CIEC101Process::SendVariableLengthFrame(BYTE fc, int address, BOOLEAN prm, BOOLEAN dir, BOOLEAN acd, BOOLEAN dfc, BYTE* userData, int userDataLength)
|
||
{
|
||
BYTE buffer[280];
|
||
int addressLength = m_linkLayer.linkLayerParameters.addressLength;
|
||
|
||
buffer[0] = IEC101_STX2; /* START */
|
||
buffer[3] = IEC101_STX2; /* START */
|
||
BYTE c = fc & 0x0f;
|
||
if (prm) c += 0x40;
|
||
if (dir) c += 0x80;
|
||
if (acd) c += 0x20;
|
||
if (dfc) c += 0x10;
|
||
buffer [4] = c;
|
||
int bufPos = 5;
|
||
if (addressLength > 0)
|
||
{
|
||
buffer [bufPos++] = (BYTE)(address & 0xFF);
|
||
if (addressLength > 1)
|
||
{
|
||
buffer[bufPos++] = (BYTE)((address >> 4) & 0xFF);
|
||
}
|
||
}
|
||
int l = 1 + addressLength + userDataLength;
|
||
if (l > 255) return;
|
||
buffer[1] = (BYTE)l;
|
||
buffer[2] = (BYTE)l;
|
||
int i;
|
||
for (i = 0; i < userDataLength; i++) buffer[bufPos++] = userData[i];
|
||
BYTE checksum = 0;
|
||
for (i = 4; i < bufPos; i++) checksum += buffer[i];
|
||
buffer[bufPos++] = checksum;
|
||
buffer[bufPos++] = IEC101_ETX; /* END */
|
||
//vLog(LOG_DEBUG, "Send variable frame (fc=%i, size=%i)\n", (int) fc, bufPos);
|
||
SendMessage(buffer, bufPos);
|
||
|
||
m_nCurFrame = 3;
|
||
}
|
||
|
||
void CIEC101Process::GetItemYXBWs(CIEC101ProcessItem* pItem)
|
||
{
|
||
int i, uid, count;
|
||
int yxbw_point;
|
||
BOOLEAN yxbw_value;
|
||
BYTE yxbw_qds;
|
||
|
||
if (NULL == pItem) return;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return;
|
||
if (NULL == pItem->yxbws.data) return;
|
||
count = pItem->yxbws.count;
|
||
if (count < 0 || count >= DATABASE_YXBW_NUM) count = 0;
|
||
int max_count = DATABASE_YXBW_NUM - count;
|
||
for (i = 0; i < max_count; i++)
|
||
{
|
||
yxbw_point = GetUnitYXBW(uid, yxbw_value, yxbw_qds);
|
||
if (yxbw_point < 0) break;
|
||
if (count >= DATABASE_YXBW_NUM) break;
|
||
pItem->yxbws.data[count].order = yxbw_point;
|
||
pItem->yxbws.data[count].value = yxbw_value;
|
||
pItem->yxbws.data[count].qds = yxbw_qds;
|
||
count++;
|
||
}
|
||
pItem->yxbws.count = count;
|
||
}
|
||
|
||
void CIEC101Process::GetItemEvents(CIEC101ProcessItem* pItem)
|
||
{
|
||
int i, uid, count;
|
||
int soe_point;
|
||
BOOLEAN soe_value;
|
||
BYTE soe_qds;
|
||
unionCP56Time soe_time;
|
||
|
||
if (NULL == pItem) return;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return;
|
||
if (NULL == pItem->events.data) return;
|
||
count = pItem->events.count;
|
||
if (count < 0 || count >= DATABASE_SOE_NUM) count = 0;
|
||
int max_count = DATABASE_SOE_NUM - count;
|
||
for (i = 0; i < max_count; i++)
|
||
{
|
||
soe_point = GetUnitSOE(uid, soe_value, soe_qds, soe_time);
|
||
if (soe_point < 0) break;
|
||
pItem->events.data[count].order = soe_point;
|
||
pItem->events.data[count].value = soe_value;
|
||
pItem->events.data[count].qds = soe_qds;
|
||
memcpy(&pItem->events.data[count].ct, &soe_time, sizeof(soe_time));
|
||
count++;
|
||
}
|
||
pItem->events.count = count;
|
||
}
|
||
|
||
void CIEC101Process::GetItemYCBWs(CIEC101ProcessItem* pItem)
|
||
{
|
||
int i, uid, count;
|
||
|
||
if (NULL == pItem) return;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return;
|
||
if (NULL == pItem->ycbws.data) return;
|
||
count = pItem->ycbws.count;
|
||
if (count < 0 || count >= pItem->total_yc) count = 0;
|
||
for (i = 0; i < pItem->total_yc; i++)
|
||
{
|
||
if (TRUE == IsUnitYCBW(uid, i))
|
||
{ //有变位产生
|
||
pItem->ycbws.data[count].order = i;
|
||
pItem->ycbws.data[count].value = GetUnitYC(uid, i);
|
||
pItem->ycbws.data[count].flVal = GetUnitYCReal(uid, i);
|
||
pItem->ycbws.data[count].qds = GetUnitYCQDS(uid, i);
|
||
ClearUnitYCBW(uid, i);
|
||
count++;
|
||
}
|
||
}
|
||
pItem->ycbws.count = count;
|
||
}
|
||
|
||
void CIEC101Process::LinkLayerPrimaryBalanced_runStateMachine(CIEC101ProcessItem *pItem)
|
||
{
|
||
QWORD currentTime = getTimeInMs();
|
||
|
||
pIEC101_LinkLayerPrimaryBalanced self = &(pItem->primaryLinkBalanced);
|
||
enumIEC101_PrimaryLinkLayerState primaryState = self->primaryState;
|
||
enumIEC101_PrimaryLinkLayerState newState = primaryState;
|
||
|
||
switch (primaryState)
|
||
{
|
||
case PLL_IDLE:
|
||
self->waitingForResponse = FALSE;
|
||
self->originalSendTime = 0;
|
||
self->lastSendTime = 0;
|
||
self->sendLinkLayerTestFunction = FALSE;
|
||
newState = PLL_EXECUTE_REQUEST_STATUS_OF_LINK;
|
||
break;
|
||
case PLL_EXECUTE_REQUEST_STATUS_OF_LINK:
|
||
if (self->waitingForResponse)
|
||
{
|
||
if (self->lastSendTime > currentTime)
|
||
{ /* last sent time not plausible! */
|
||
self->lastSendTime = currentTime;
|
||
}
|
||
if (currentTime > (self->lastSendTime + m_linkLayer.linkLayerParameters.timeoutForACK))
|
||
{
|
||
SendFixedFrame(LL_FC_09_REQUEST_LINK_STATUS, self->otherStationAddress, TRUE, m_linkLayer.dir, FALSE, FALSE);
|
||
self->lastSendTime = currentTime;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL - SEND RESET REMOTE LINK\n");
|
||
SendFixedFrame(LL_FC_00_RESET_REMOTE_LINK, self->otherStationAddress, TRUE, m_linkLayer.dir, FALSE, FALSE);
|
||
self->lastSendTime = currentTime;
|
||
self->waitingForResponse = TRUE;
|
||
newState = PLL_EXECUTE_RESET_REMOTE_LINK;
|
||
}
|
||
break;
|
||
case PLL_EXECUTE_RESET_REMOTE_LINK:
|
||
if (self->waitingForResponse)
|
||
{
|
||
if (currentTime > (self->lastSendTime + m_linkLayer.linkLayerParameters.timeoutForACK))
|
||
{
|
||
self->waitingForResponse = FALSE;
|
||
newState = PLL_IDLE;
|
||
llpb_setNewState(self, LL_STATE_ERROR);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
newState = PLL_LINK_LAYERS_AVAILABLE;
|
||
llpb_setNewState(self, LL_STATE_AVAILABLE);
|
||
}
|
||
break;
|
||
case PLL_LINK_LAYERS_AVAILABLE:
|
||
if (self->lastReceivedMsg > currentTime)
|
||
{
|
||
/* last received message not plausible */
|
||
self->lastReceivedMsg = currentTime;
|
||
}
|
||
if ((currentTime - self->lastReceivedMsg) > (unsigned int)self->idleTimeout)
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL - Idle timeout detected. Send link layer test function\n");
|
||
self->sendLinkLayerTestFunction = TRUE;
|
||
}
|
||
if (self->sendLinkLayerTestFunction)
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL - SEND TEST LINK\n");
|
||
SendFixedFrame(LL_FC_02_TEST_FUNCTION_FOR_LINK, self->otherStationAddress, TRUE, m_linkLayer.dir, self->nextFcb, TRUE);
|
||
self->nextFcb = !(self->nextFcb);
|
||
self->lastSendTime = currentTime;
|
||
self->originalSendTime = self->lastSendTime;
|
||
newState = PLL_EXECUTE_SERVICE_SEND_CONFIRM;
|
||
}
|
||
else
|
||
{
|
||
/* provide a buffer where the application layer can encode the user data */
|
||
pIEC101_QueueElement element = ApplicationLayer_GetUserData(pItem);
|
||
if (element)
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL: SEND USER DATA CONFIRMED\n");
|
||
memcpy(self->buffer, element->buffer, element->size); self->bufferLength = element->size;
|
||
SendVariableLengthFrame(LL_FC_03_USER_DATA_CONFIRMED, self->otherStationAddress, TRUE, m_linkLayer.dir, self->nextFcb, TRUE, element->buffer, element->size);
|
||
self->nextFcb = !(self->nextFcb);
|
||
self->lastSendTime = currentTime;
|
||
self->originalSendTime = self->lastSendTime;
|
||
self->waitingForResponse = TRUE;
|
||
newState = PLL_EXECUTE_SERVICE_SEND_CONFIRM;
|
||
}
|
||
}
|
||
break;
|
||
case PLL_EXECUTE_SERVICE_SEND_CONFIRM:
|
||
if (currentTime > (self->lastSendTime + m_linkLayer.linkLayerParameters.timeoutForACK))
|
||
{
|
||
if (currentTime > (self->originalSendTime + m_linkLayer.linkLayerParameters.timeoutRepeat))
|
||
{
|
||
vLog(LOG_DEBUG, "TIMEOUT: ASDU not confirmed after repeated transmission\n");
|
||
newState = PLL_IDLE;
|
||
llpb_setNewState(self, LL_STATE_ERROR);
|
||
}
|
||
else
|
||
{
|
||
//vLog(LOG_DEBUG, "TIMEOUT: ASDU not confirmed\n");
|
||
if (self->sendLinkLayerTestFunction)
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL - repeat send test function\n");
|
||
SendFixedFrame(LL_FC_02_TEST_FUNCTION_FOR_LINK, self->otherStationAddress, TRUE, m_linkLayer.dir, !(self->nextFcb), TRUE);
|
||
}
|
||
else
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL - repeat last ASDU\n");
|
||
SendVariableLengthFrame(LL_FC_03_USER_DATA_CONFIRMED, self->otherStationAddress, TRUE, m_linkLayer.dir, !(self->nextFcb), TRUE, self->buffer, self->bufferLength);
|
||
}
|
||
self->lastSendTime = currentTime;
|
||
}
|
||
}
|
||
break;
|
||
case PLL_SECONDARY_LINK_LAYER_BUSY:
|
||
break;
|
||
default:
|
||
break;
|
||
|
||
}
|
||
if (primaryState != newState)
|
||
{
|
||
//vLog(LOG_DEBUG, "PLL - old state: %i new state: %i\n", primaryState, newState);
|
||
}
|
||
self->primaryState = newState;
|
||
}
|
||
|
||
///
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSingle_point_information(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //单点遥信
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_BACK == cot || IEC_101_104_COT_SPONT == cot ||
|
||
IEC_101_104_COT_REQ == cot || IEC_101_104_COT_RETREM == cot ||
|
||
IEC_101_104_COT_RETLOC == cot || IEC_101_104_COT_INTERROGATION == cot ||
|
||
IEC_101_104_COT_INRO1 == cot || IEC_101_104_COT_INRO2 == cot ||
|
||
IEC_101_104_COT_INRO3 == cot || IEC_101_104_COT_INRO4 == cot ||
|
||
IEC_101_104_COT_INRO5 == cot || IEC_101_104_COT_INRO6 == cot ||
|
||
IEC_101_104_COT_INRO7 == cot || IEC_101_104_COT_INRO8 == cot ||
|
||
IEC_101_104_COT_INRO9 == cot || IEC_101_104_COT_INRO10 == cot ||
|
||
IEC_101_104_COT_INRO11 == cot || IEC_101_104_COT_INRO12 == cot ||
|
||
IEC_101_104_COT_INRO13 == cot || IEC_101_104_COT_INRO14 == cot ||
|
||
IEC_101_104_COT_INRO15 == cot || IEC_101_104_COT_INRO16 == cot ||
|
||
IEC_101_104_COT_PER_CYC == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
value = (*pData & 0x01) == 0x01 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, FALSE, qds);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址自动生成YXBW信号
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = (*pData & 0x01) == 0x01 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, TRUE, qds);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSingle_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带时标的单点遥信
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = (*pData & 0x01) == 0x01 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, TRUE, qds);
|
||
SetUnitSOE(uid, point, value, st);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveDouble_point_information(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //双点遥信
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_BACK == cot || IEC_101_104_COT_SPONT == cot ||
|
||
IEC_101_104_COT_REQ == cot || IEC_101_104_COT_RETREM == cot ||
|
||
IEC_101_104_COT_RETLOC == cot || IEC_101_104_COT_INTERROGATION == cot ||
|
||
IEC_101_104_COT_INRO1 == cot || IEC_101_104_COT_INRO2 == cot ||
|
||
IEC_101_104_COT_INRO3 == cot || IEC_101_104_COT_INRO4 == cot ||
|
||
IEC_101_104_COT_INRO5 == cot || IEC_101_104_COT_INRO6 == cot ||
|
||
IEC_101_104_COT_INRO7 == cot || IEC_101_104_COT_INRO8 == cot ||
|
||
IEC_101_104_COT_INRO9 == cot || IEC_101_104_COT_INRO10 == cot ||
|
||
IEC_101_104_COT_INRO11 == cot || IEC_101_104_COT_INRO12 == cot ||
|
||
IEC_101_104_COT_INRO13 == cot || IEC_101_104_COT_INRO14 == cot ||
|
||
IEC_101_104_COT_INRO15 == cot || IEC_101_104_COT_INRO16 == cot ||
|
||
IEC_101_104_COT_PER_CYC == cot )
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
value = (*pData & 0x03) == 0x02 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0);
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, FALSE, qds);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址自动生成YXBW信号
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = (*pData & 0x03) == 0x02 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0);
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, TRUE, qds);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveDouble_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带时标的双点遥信
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = (*pData & 0x03) == 0x02 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, TRUE, qds);
|
||
SetUnitSOE(uid, point, value, st);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_normalised(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //测量值,归一化值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_PER_CYC == cot || IEC_101_104_COT_BACK == cot ||
|
||
IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot ||
|
||
IEC_101_104_COT_INTERROGATION == cot || IEC_101_104_COT_INRO1 == cot ||
|
||
IEC_101_104_COT_INRO2 == cot || IEC_101_104_COT_INRO3 == cot ||
|
||
IEC_101_104_COT_INRO4 == cot || IEC_101_104_COT_INRO5 == cot ||
|
||
IEC_101_104_COT_INRO6 == cot || IEC_101_104_COT_INRO7 == cot ||
|
||
IEC_101_104_COT_INRO8 == cot || IEC_101_104_COT_INRO9 == cot ||
|
||
IEC_101_104_COT_INRO10 == cot || IEC_101_104_COT_INRO11 == cot ||
|
||
IEC_101_104_COT_INRO12 == cot || IEC_101_104_COT_INRO13 == cot ||
|
||
IEC_101_104_COT_INRO14 == cot || IEC_101_104_COT_INRO15 == cot ||
|
||
IEC_101_104_COT_INRO16 == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_normalised_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带时标的遥测量,归一化值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_scaled(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //测量值,标度化值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_PER_CYC == cot || IEC_101_104_COT_BACK == cot ||
|
||
IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot ||
|
||
IEC_101_104_COT_INTERROGATION == cot || IEC_101_104_COT_INRO1 == cot ||
|
||
IEC_101_104_COT_INRO2 == cot || IEC_101_104_COT_INRO3 == cot ||
|
||
IEC_101_104_COT_INRO4 == cot || IEC_101_104_COT_INRO5 == cot ||
|
||
IEC_101_104_COT_INRO6 == cot || IEC_101_104_COT_INRO7 == cot ||
|
||
IEC_101_104_COT_INRO8 == cot || IEC_101_104_COT_INRO9 == cot ||
|
||
IEC_101_104_COT_INRO10 == cot || IEC_101_104_COT_INRO11 == cot ||
|
||
IEC_101_104_COT_INRO12 == cot || IEC_101_104_COT_INRO13 == cot ||
|
||
IEC_101_104_COT_INRO14 == cot || IEC_101_104_COT_INRO15 == cot ||
|
||
IEC_101_104_COT_INRO16 == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_scaled_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带时标的遥测量,标度化值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_short_floating_point(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //测量值,短浮点数
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_PER_CYC == cot || IEC_101_104_COT_BACK == cot ||
|
||
IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot ||
|
||
IEC_101_104_COT_INTERROGATION == cot || IEC_101_104_COT_INRO1 == cot ||
|
||
IEC_101_104_COT_INRO2 == cot || IEC_101_104_COT_INRO3 == cot ||
|
||
IEC_101_104_COT_INRO4 == cot || IEC_101_104_COT_INRO5 == cot ||
|
||
IEC_101_104_COT_INRO6 == cot || IEC_101_104_COT_INRO7 == cot ||
|
||
IEC_101_104_COT_INRO8 == cot || IEC_101_104_COT_INRO9 == cot ||
|
||
IEC_101_104_COT_INRO10 == cot || IEC_101_104_COT_INRO11 == cot ||
|
||
IEC_101_104_COT_INRO12 == cot || IEC_101_104_COT_INRO13 == cot ||
|
||
IEC_101_104_COT_INRO14 == cot || IEC_101_104_COT_INRO15 == cot ||
|
||
IEC_101_104_COT_INRO16 == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
DWORD dwValue;
|
||
float fValue;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
dwValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]);
|
||
pData += 4;
|
||
memcpy(&fValue, &dwValue, sizeof(DWORD));
|
||
qds = (*pData & 0xf1); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, fValue, qds);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
dwValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]);
|
||
pData += 4;
|
||
memcpy(&fValue, &dwValue, sizeof(DWORD));
|
||
qds = (*pData & 0xf1); pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, fValue, qds);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_short_floating_point_with_time_tag(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带时标的遥测量值,短浮点数
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
DWORD dwValue;
|
||
float fValue;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
dwValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]);
|
||
pData += 4;
|
||
memcpy(&fValue, &dwValue, sizeof(DWORD));
|
||
qds = (*pData & 0xf1); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, fValue, qds);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_normalised_without_quality(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //测量值,不带品质描述的归一化测量值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_PER_CYC == cot || IEC_101_104_COT_BACK == cot ||
|
||
IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot ||
|
||
IEC_101_104_COT_INTERROGATION == cot || IEC_101_104_COT_INRO1 == cot ||
|
||
IEC_101_104_COT_INRO2 == cot || IEC_101_104_COT_INRO3 == cot ||
|
||
IEC_101_104_COT_INRO4 == cot || IEC_101_104_COT_INRO5 == cot ||
|
||
IEC_101_104_COT_INRO6 == cot || IEC_101_104_COT_INRO7 == cot ||
|
||
IEC_101_104_COT_INRO8 == cot || IEC_101_104_COT_INRO9 == cot ||
|
||
IEC_101_104_COT_INRO10 == cot || IEC_101_104_COT_INRO11 == cot ||
|
||
IEC_101_104_COT_INRO12 == cot || IEC_101_104_COT_INRO13 == cot ||
|
||
IEC_101_104_COT_INRO14 == cot || IEC_101_104_COT_INRO15 == cot ||
|
||
IEC_101_104_COT_INRO16 == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = 0x00;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = 0x00;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSingle_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带CP56Time2a时标的单点信息
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = (*pData & 0x01) == 0x01 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, TRUE, qds);
|
||
SetUnitSOE(uid, point, value, st);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveDouble_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带CP56Time2a时标的双点信息
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot ||
|
||
IEC_101_104_COT_RETREM == cot || IEC_101_104_COT_RETLOC == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = (*pData & 0x03) == 0x02 ? TRUE : FALSE;
|
||
qds = (*pData & 0xf0); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYXPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYX(uid, point, value, TRUE, qds);
|
||
SetUnitSOE(uid, point, value, st);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_normalised_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带CP56Time2a时标的遥测量值,归一化值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_scaled_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带CP56Time2a时标的遥测量值,标度化值
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
short value;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
qds = (*pData & 0xf1); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, (LONG)value, qds);
|
||
}
|
||
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveMeasured_value_short_floating_point_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //带CP56Time2a时标的遥测量值,短浮点数
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQ == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
|
||
DWORD i;
|
||
DWORD information_address;
|
||
DWORD dwValue;
|
||
float fValue;
|
||
BYTE qds;
|
||
BYTE ioa[4];
|
||
unionCP56Time st;
|
||
memcpy(&st, &system32.now, sizeof(st));
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
dwValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]);
|
||
pData += 4;
|
||
memcpy(&fValue, &dwValue, sizeof(DWORD));
|
||
qds = (*pData & 0xf1); pData++;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYCPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYC(uid, point, fValue, qds);
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveIntegrated_totals(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //累积量
|
||
{
|
||
BYTE* pData = pBuf;
|
||
int point;
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if (IEC_101_104_COT_SPONT == cot || IEC_101_104_COT_REQCOGEN == cot ||
|
||
IEC_101_104_COT_REQCO1 == cot || IEC_101_104_COT_REQCO2 == cot ||
|
||
IEC_101_104_COT_REQCO3 == cot || IEC_101_104_COT_REQCO4 == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
|
||
int i;
|
||
DWORD information_address;
|
||
DWORD value;
|
||
BYTE ioa[4];
|
||
if (isSequence) //顺序寻址
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
for (i = 0; i < num; i++, information_address++)
|
||
{
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
value |= (*pData << 16); pData++;
|
||
value |= (*pData << 24); pData++;
|
||
//sn = *pData;
|
||
pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYMPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYM(uid, point, value);
|
||
}
|
||
}
|
||
}
|
||
else //单一寻址
|
||
{
|
||
for (i = 0; i < num; i++)
|
||
{
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
value |= (*pData << 16); pData++;
|
||
value |= (*pData << 24); pData++;
|
||
//sn = *pData;
|
||
pData++;
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYMPointByParam(uid, ioa, 4);
|
||
if (point >= 0)
|
||
{
|
||
SetUnitYM(uid, point, value);
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveInterrogation_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //总召唤
|
||
{
|
||
BYTE* pData = pBuf;
|
||
DWORD information_address;
|
||
BYTE QOI;
|
||
if (IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
if (information_address != 0) return FALSE;
|
||
|
||
QOI = *pData; pData++;
|
||
if (QOI < 20 || QOI > 36)
|
||
{
|
||
return FALSE;
|
||
}
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
return FALSE;
|
||
}
|
||
if (IEC_101_104_COT_ACTCON == cot)
|
||
{
|
||
return TRUE;
|
||
}
|
||
if (IEC_101_104_COT_ACTTREM == cot)
|
||
{ //激活终止
|
||
//总召唤结束
|
||
pItem->interrogation_finish = TRUE;
|
||
return TRUE;
|
||
}
|
||
if (IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
return FALSE;
|
||
}
|
||
if (IEC_101_104_COT_DEACTCON == cot)
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveClock_synchronisation_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //时钟同步
|
||
{
|
||
BYTE* pData = pBuf;
|
||
DWORD information_address;
|
||
unionCP56Time st;
|
||
if (IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_ACTTREM == cot ||
|
||
IEC_101_104_COT_UNKNOWN_TI == cot || IEC_101_104_COT_UNKNOWN_COT == cot ||
|
||
IEC_101_104_COT_UNKNOWN_ASDU == cot || IEC_101_104_COT_UNKNOWN_INFO == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
if (information_address != 0) return FALSE;
|
||
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
if (cot == IEC_101_104_COT_ACTCON)
|
||
{
|
||
pItem->clock_synchronized_finish = TRUE;
|
||
return TRUE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveCounter_Interrogation_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //召唤电度量
|
||
{
|
||
BYTE* pData = pBuf;
|
||
DWORD information_address;
|
||
BYTE QCC;
|
||
if (IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot)
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
if (information_address != 0) return FALSE;
|
||
QCC = *pData; pData++;
|
||
if ((QCC & 0x3f) < 1 || (QCC & 0x3f) > 5) return FALSE;
|
||
if (IEC_101_104_COT_ACT == cot) return FALSE;
|
||
if (IEC_101_104_COT_ACTCON == cot) return TRUE;
|
||
//激活终止
|
||
//召唤电度结束
|
||
if (IEC_101_104_COT_ACTTREM == cot) return TRUE;
|
||
if (IEC_101_104_COT_DEACT == cot) return FALSE;
|
||
if (IEC_101_104_COT_DEACTCON == cot) return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSingle_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //单点遥控
|
||
{
|
||
BYTE* pData = pBuf;
|
||
BYTE SE, value;
|
||
int point;
|
||
DWORD information_address;
|
||
BYTE ioa[4];
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if( IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot )
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYKPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
vLog(LOG_WARN, "Unit(%d) information address error.\n", uid);
|
||
return FALSE;
|
||
}
|
||
SE = (*pData & 0x80) == 0x80 ? TRUE : FALSE;
|
||
value = (*pData & 0x01) == 0x01 ? TRUE : FALSE;
|
||
|
||
BYTE* pYKParam = GetUnitYKParamByPoint(uid, point);
|
||
if (pYKParam == NULL) return FALSE;
|
||
switch (pYKParam[5])
|
||
{
|
||
case 1: //单触点合圈
|
||
if (value != TRUE) return FALSE;
|
||
break;
|
||
case 2: //单触点分圈
|
||
if (value != FALSE) return FALSE;
|
||
break;
|
||
}
|
||
|
||
value = pItem->yk_value;
|
||
if (SE)
|
||
{ //遥控选择
|
||
if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
SetUnitYK(uid, point, value, YKS_SELED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYK(uid, point, value, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP" ));
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
else
|
||
{ //遥控执行
|
||
if (IEC_101_104_COT_ACTTREM == cot)
|
||
{ //激活终止
|
||
SetUnitYK(uid, point, value, YKS_EXEED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYK(uid, point, value, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s ACTCON.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveDouble_command(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //双点遥控
|
||
{
|
||
BYTE* pData = pBuf;
|
||
BYTE SE, value;
|
||
int point;
|
||
DWORD information_address;
|
||
BYTE ioa[4];
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if( IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot )
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYKPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
vLog(LOG_WARN, "Unit(%d) information address error.\n", uid);
|
||
return FALSE;
|
||
}
|
||
SE = (*pData & 0x80) == 0x80 ? TRUE : FALSE;
|
||
value = (*pData & 0x03) == 0x02 ? TRUE : FALSE;
|
||
BYTE* pYKParam = GetUnitYKParamByPoint(uid, point);
|
||
if (pYKParam == NULL) return FALSE;
|
||
switch (pYKParam[5])
|
||
{
|
||
case 1: //单触点合圈
|
||
if (value != TRUE) return FALSE;
|
||
break;
|
||
case 2: //单触点分圈
|
||
if (value != FALSE) return FALSE;
|
||
break;
|
||
}
|
||
|
||
value = pItem->yk_value;
|
||
if (SE)
|
||
{ //遥控选择
|
||
if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
SetUnitYK(uid, point, value, YKS_SELED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYK(uid, point, value, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP" ));
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
else
|
||
{ //遥控执行
|
||
if (IEC_101_104_COT_ACTTREM == cot)
|
||
{ //激活终止
|
||
SetUnitYK(uid, point, value, YKS_EXEED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYK(uid, point, value, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s ACTCON.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSet_point_command_normalized(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //设定归一化值命令
|
||
{
|
||
BYTE* pData = pBuf;
|
||
BYTE SE;
|
||
WORD value;
|
||
int point;
|
||
DWORD information_address;
|
||
BYTE ioa[4];
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if( IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot )
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYTPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
vLog(LOG_WARN, "Unit(%d) information address error.\n", uid);
|
||
return FALSE;
|
||
}
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
SE = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
if (SE)
|
||
{ //遥控选择
|
||
if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
SetUnitYT(uid, point, value, YTS_SELED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYT(uid, point, value, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
else
|
||
{ //遥控执行
|
||
if (IEC_101_104_COT_ACTTREM == cot)
|
||
{ //激活终止
|
||
SetUnitYT(uid, point, value, YTS_EXEED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_EXEED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYT(uid, point, value, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d ACTCON.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSet_point_command_scaled(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //设定标度化值命令
|
||
{
|
||
BYTE* pData = pBuf;
|
||
BYTE SE;
|
||
WORD value;
|
||
int point;
|
||
DWORD information_address;
|
||
BYTE ioa[4];
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if( IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot )
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYTPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
vLog(LOG_WARN, "Unit(%d) information address error.\n", uid);
|
||
return FALSE;
|
||
}
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
SE = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
if (SE)
|
||
{ //遥控选择
|
||
if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
SetUnitYT(uid, point, value, YTS_SELED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYT(uid, point, value, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
else
|
||
{ //遥控执行
|
||
if (IEC_101_104_COT_ACTTREM == cot)
|
||
{ //激活终止
|
||
SetUnitYT(uid, point, value, YTS_EXEED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_EXEED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYT(uid, point, value, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d ACTCON.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::OnReceiveSet_point_command_short_floating(CIEC101ProcessItem* pItem, BYTE* pBuf, BOOLEAN isSequence, BOOLEAN isNegative, BOOLEAN isTest, BYTE num, BYTE cot) //设定短浮点值命令
|
||
{
|
||
BYTE* pData = pBuf;
|
||
BYTE SE;
|
||
DWORD value;
|
||
int point;
|
||
DWORD information_address;
|
||
BYTE ioa[4];
|
||
int uid;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
|
||
if( IEC_101_104_COT_ACTCON == cot || IEC_101_104_COT_DEACTCON == cot ||
|
||
IEC_101_104_COT_ACTTREM == cot || IEC_101_104_COT_UNKNOWN_TI == cot ||
|
||
IEC_101_104_COT_UNKNOWN_COT == cot || IEC_101_104_COT_UNKNOWN_ASDU == cot ||
|
||
IEC_101_104_COT_UNKNOWN_INFO == cot )
|
||
{
|
||
if (isNegative) return FALSE; //否定
|
||
if (isTest) return FALSE; //试验
|
||
if (isSequence) return FALSE; //顺序寻址
|
||
//if (num != 1) return FALSE;
|
||
|
||
information_address = 0;
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pData);
|
||
pData += pItem->applicationlParameters.sizeOfIOA;
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYTPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
vLog(LOG_WARN, "Unit(%d) information address error.\n", uid);
|
||
return FALSE;
|
||
}
|
||
value = *pData; pData++;
|
||
value |= (*pData << 8); pData++;
|
||
value |= (*pData << 16); pData++;
|
||
value |= (*pData << 24); pData++;
|
||
SE = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
if (SE)
|
||
{ //遥控选择
|
||
if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
SetUnitYT(uid, point, value, YTS_SELED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYT(uid, point, value, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
else
|
||
{ //遥控执行
|
||
if (IEC_101_104_COT_ACTTREM == cot)
|
||
{ //激活终止
|
||
SetUnitYT(uid, point, value, YTS_EXEED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_EXEED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_DEACTCON == cot)
|
||
{ //停止激活确认
|
||
SetUnitYT(uid, point, value, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else if (IEC_101_104_COT_ACTCON == cot)
|
||
{ //激活确认
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d ACTCON.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::GetYKFrame(CIEC101ProcessItem* pItem, int ord)
|
||
{
|
||
int uid, order, len;
|
||
DWORD information_address;
|
||
BYTE value, state, result, command, yk_type, relay_type, QU;
|
||
BYTE cause_of_transmission = 0;
|
||
BYTE type_id;
|
||
BYTE buffer[64];
|
||
|
||
|
||
if (NULL == pItem) return FALSE;
|
||
command = 0;
|
||
len = 0;
|
||
memset(buffer, 0, sizeof(buffer));
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
if (!GetUnitYK(uid, order, value, state, result)) return FALSE;
|
||
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s.\n", uid, order, (value ? "CLOSE" : "TRIP"), val_to_str( state, yk_state, "STATE= %d" ), val_to_str( result, yk_result, "RESULT= %d"));
|
||
|
||
//获取遥控信息体地址
|
||
BYTE* pParam = GetUnitYKParamByPoint(uid, order);
|
||
if (NULL == pParam) return FALSE;
|
||
|
||
pItem->yk_value = value;
|
||
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pParam);
|
||
yk_type = pParam[4];
|
||
relay_type = pParam[5];
|
||
QU = pParam[6];
|
||
QU <<= 2; QU &= 0x7c;
|
||
|
||
if (yk_type == USE_YK_DC || yk_type == USE_YK_DEF)
|
||
{ //双点遥控
|
||
command = (value == TRUE) ? DCO_ON: DCO_OFF;
|
||
type_id = C_DC_NA_1;
|
||
//buffer[len++] = C_DC_NA_1;
|
||
}
|
||
else if (yk_type == USE_YK_SC)
|
||
{
|
||
switch (relay_type)
|
||
{
|
||
case 1: //单触点合圈
|
||
command = TRUE;
|
||
break;
|
||
case 2: //单触点分圈
|
||
command = FALSE;
|
||
break;
|
||
default: //双触点线圈
|
||
command = value;
|
||
break;
|
||
}
|
||
//buffer[len++] = C_SC_NA_1;
|
||
type_id = C_SC_NA_1;
|
||
}
|
||
if (YKS_SELREQ == state)
|
||
{
|
||
cause_of_transmission = IEC_101_104_COT_ACT;
|
||
command |= 0x80;
|
||
}
|
||
else if (YKS_EXEREQ == state)
|
||
{
|
||
cause_of_transmission = IEC_101_104_COT_ACT;
|
||
}
|
||
else if ((YKS_ABRREQ == state) || ((YKS_SELING == state || YKS_SELED == state) && YKR_OVER == result))
|
||
{
|
||
cause_of_transmission = IEC_101_104_COT_DEACT;
|
||
command |= 0x80;
|
||
}
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), type_id, FALSE, cause_of_transmission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
ASDU_addNumberOfElements(buffer);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], information_address, FALSE);
|
||
buffer[len++] = (command | QU);
|
||
Master_sendASDU(pItem, buffer, len);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101PrimaryProcess::GetYTFrame(CIEC101ProcessItem* pItem, int ord)
|
||
{
|
||
int uid, order, len, data_length;
|
||
DWORD information_address, value;
|
||
BYTE state, result, yt_type;
|
||
BYTE command = 0;
|
||
BYTE type_id;
|
||
BYTE cause_of_transmission = 0;
|
||
BYTE buffer[64];
|
||
|
||
|
||
if (NULL == pItem) return FALSE;
|
||
data_length = 2;
|
||
len = 0;
|
||
memset(buffer, 0, sizeof(buffer));
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
if (!GetUnitYT(uid, order, value, state, result)) return FALSE;
|
||
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is %s result is %s.\n", uid, order, value, val_to_str( state, yt_state, "STATE= %d" ), val_to_str( result, yt_result, "RESULT= %d"));
|
||
|
||
//获取遥调信息体地址
|
||
BYTE* pParam = GetUnitYTParamByPoint(uid, order);
|
||
if (NULL == pParam) return FALSE;
|
||
|
||
information_address = ASDU_getIOA(&(pItem->applicationlParameters), pParam);
|
||
yt_type = pParam[4];
|
||
|
||
if (yt_type == USE_YT_NA)
|
||
{
|
||
data_length = 2;
|
||
type_id = C_SE_NA_1;
|
||
}
|
||
else if (yt_type == USE_YT_NB)
|
||
{
|
||
data_length = 2;
|
||
type_id = C_SE_NB_1;
|
||
}
|
||
else if (yt_type == USE_YT_NC)
|
||
{
|
||
data_length = 4;
|
||
type_id = C_SE_NC_1;
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) type(%d) error.\n", uid, order, yt_type);
|
||
return FALSE;
|
||
}
|
||
if (YTS_SELREQ == state)
|
||
{
|
||
cause_of_transmission = IEC_101_104_COT_ACT;
|
||
command |= IEC_101_104_SE;
|
||
}
|
||
else if (YTS_EXEREQ == state)
|
||
{
|
||
cause_of_transmission = IEC_101_104_COT_ACT;
|
||
command = 0;
|
||
}
|
||
else if ((YTS_ABRREQ == state) || ((YTS_SELING == state || YTS_SELED == state) && YTR_OVER == result))
|
||
{
|
||
cause_of_transmission = IEC_101_104_COT_DEACT;
|
||
command = 0;
|
||
}
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), type_id, FALSE, cause_of_transmission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
ASDU_addNumberOfElements(buffer);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], information_address, FALSE);
|
||
if (data_length == 2)
|
||
{
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
}
|
||
else if (data_length == 4)
|
||
{
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
buffer[len++] = (value >> 16) & 0xff;
|
||
buffer[len++] = (value >> 24) & 0xff;
|
||
}
|
||
buffer[len++] = command;
|
||
Master_sendASDU(pItem, buffer, len);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/***************************************************************************************/
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::ApplicationLayer_ReceivedData(CIEC101ProcessItem* pItem, BYTE* msg, BOOLEAN isBroadcast, int userDataStart, int userDataLength)
|
||
{
|
||
UNUSED(isBroadcast);
|
||
BYTE *asdu = msg + userDataStart;
|
||
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);
|
||
|
||
int ret = NO_ERROR;
|
||
int uid = pItem->GetUnitID();
|
||
BYTE *pData = asdu + parameters->sizeOfTypeId + parameters->sizeOfVSQ + parameters->sizeOfCOT + parameters->sizeOfCA;
|
||
switch (tid)
|
||
{
|
||
case C_IC_NA_1: //总召唤命令
|
||
return Receive_Interrogation_command(pItem, pData, cot);
|
||
case C_SC_NA_1: //单点遥控命令.没有总召唤,不响应遥控报文
|
||
return Receive_Single_command(pItem, pData, cot);
|
||
case C_DC_NA_1: //双点遥控命令.没有总召唤,不响应遥控报文
|
||
return Receive_Double_command(pItem, pData, cot);
|
||
case C_CI_NA_1: //脉冲量召唤命令
|
||
return Receive_Counter_interrogation_command(pItem, pData, cot);
|
||
case C_CS_NA_1: //时间同步命令
|
||
return Receive_Clock_synchronisation_command(pItem, pData, cot);
|
||
case C_SE_NA_1: //设定命令,归一化值.没有总召唤,不响应设定报文
|
||
return Receive_Set_point_command_normalized(pItem, pData, cot); //设定规一化值命令
|
||
case C_SE_NB_1: //设定命令,标度化值.没有总召唤,不响应设定报文
|
||
return Receive_Set_point_command_scaled(pItem, pData, cot); //设定标度化值命令
|
||
case C_SE_NC_1: //设定命令,短浮点数.没有总召唤,不响应设定报文
|
||
return Receive_Set_point_command_short_floating(pItem, pData, cot); //设定短浮点值命令
|
||
default:
|
||
vLog(LOG_WARN, "Unit(%d) Unsupported I frame type = 0x%02x\n", uid, (int)tid);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::MakeYKFrame(CIEC101ProcessItem* pItem)
|
||
{
|
||
BYTE buffer[32];
|
||
if (NULL == pItem) return -1;
|
||
|
||
int order;
|
||
BYTE value, action, result;
|
||
BYTE command = 0;
|
||
|
||
if (!GetUnitYK(pItem->GetUnitID(), order, value, action, result))
|
||
{
|
||
return FALSE;
|
||
}
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s\n", pItem->GetUnitID(), order, (value ? "CLOSE" : "TRIP"), val_to_str(action, yk_state, "STATE=%d"), val_to_str(result, yk_result, "RESULT=%d"));
|
||
|
||
if (YKS_SELED == action && YKR_FAIL == result)
|
||
{
|
||
command |= IEC_101_104_SE;
|
||
action = YKS_ABRED;
|
||
}
|
||
else if (YKS_SELREQ == action && YKR_OVER == result)
|
||
{
|
||
command |= IEC_101_104_SE;
|
||
action = YKS_ABRED;
|
||
}
|
||
else if (YKS_SELING == action && YKR_OVER == result)
|
||
{
|
||
command |= IEC_101_104_SE;
|
||
action = YKS_ABRED;
|
||
}
|
||
BYTE* param;
|
||
BYTE yk_type;
|
||
DWORD ioa;
|
||
param = GetUnitYKParamByPoint(pItem->GetUnitID(), order);
|
||
ioa = MAKEDWORD(MAKEWORD(param[0], param[1]), MAKEWORD(param[2], param[3]));
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_DC_NA_1, FALSE, 0, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
ASDU_addNumberOfElements(asdu);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], ioa, FALSE);
|
||
|
||
yk_type = param[4];
|
||
if (yk_type == USE_YK_DC || yk_type == USE_YK_DEF)
|
||
{ //双点遥控
|
||
ASDU_setTypeID(asdu, C_DC_NA_1);
|
||
command |= value ? DCO_ON : DCO_OFF;
|
||
}
|
||
else
|
||
{
|
||
ASDU_setTypeID(asdu, C_SC_NA_1);
|
||
command |= value ? SCO_ON : SCO_OFF;
|
||
}
|
||
if (YKS_SELED == action)
|
||
{
|
||
command |= IEC_101_104_SE;
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
}
|
||
else if (YKS_ABRED == action)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
}
|
||
else if (YKS_EXEED == action)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTTREM);
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
asdu[len++] = command;
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::MakeYTFrame(CIEC101ProcessItem* pItem)
|
||
{
|
||
int order;
|
||
BYTE action, result;
|
||
DWORD value;
|
||
BYTE command = 0;
|
||
|
||
if (!GetUnitYT(pItem->GetUnitID(), order, value, action, result))
|
||
{
|
||
return FALSE;
|
||
}
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is %s result is %s\n", pItem->GetUnitID(), order, value, val_to_str(action, yt_state, "STATE=%d"), val_to_str(result, yt_result, "RESULT=%d"));
|
||
|
||
BYTE* param;
|
||
BYTE yt_type;
|
||
DWORD ioa;
|
||
param = GetUnitYTParamByPoint(pItem->GetUnitID(), order);
|
||
ioa = MAKEDWORD(MAKEWORD(param[0], param[1]), MAKEWORD(param[2], param[3]));
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_SE_NA_1, FALSE, 0, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
ASDU_addNumberOfElements(asdu);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], ioa, FALSE);
|
||
yt_type = param[4];
|
||
if (yt_type == USE_YT_NA)
|
||
{ //双点遥控
|
||
ASDU_setTypeID(asdu, C_SE_NA_1);
|
||
asdu[len++] = value & 0xff;
|
||
asdu[len++] = (value >> 8) & 0xff;
|
||
}
|
||
else if (yt_type == USE_YT_NB)
|
||
{
|
||
ASDU_setTypeID(asdu, C_SE_NB_1);
|
||
asdu[len++] = value & 0xff;
|
||
asdu[len++] = (value >> 8) & 0xff;
|
||
}
|
||
else
|
||
{
|
||
ASDU_setTypeID(asdu, C_SE_NC_1);
|
||
asdu[len++] = value & 0xff;
|
||
asdu[len++] = (value >> 8) & 0xff;
|
||
asdu[len++] = (value >> 16) & 0xff;
|
||
asdu[len++] = (value >> 24) & 0xff;
|
||
}
|
||
if (YTS_SELED == action && YTR_FAIL == result)
|
||
{
|
||
command = IEC_101_104_SE;
|
||
action = YTS_ABRED;
|
||
}
|
||
else if (YTS_SELREQ == action && YTR_OVER == result)
|
||
{
|
||
command = IEC_101_104_SE;
|
||
action = YTS_ABRED;
|
||
}
|
||
else if (YTS_SELING == action && YTR_OVER == result)
|
||
{
|
||
command = IEC_101_104_SE;
|
||
action = YTS_ABRED;
|
||
}
|
||
|
||
if (YTS_SELED == action)
|
||
{
|
||
command = IEC_101_104_SE;
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
}
|
||
else if (YTS_ABRED == action)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
}
|
||
else if (YTS_EXEED == action)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTTREM);
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
asdu[len++] = command;
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Interrogation_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //总召唤
|
||
{
|
||
QualifierOfInterrogation QOI;
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
int ioa = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
QOI = *pData;
|
||
|
||
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;
|
||
if (IEC_101_104_COT_ACT == cot || IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
if (QOI < IEC60870_QOI_STATION || QOI > IEC60870_QOI_GROUP_16)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //总召唤,分组召唤
|
||
pItem->call_type = QOI;
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
}
|
||
pItem->interrogation_start = TRUE;
|
||
pItem->interrogation_yx_fin = FALSE;
|
||
pItem->interrogation_yc_fin = FALSE;
|
||
pItem->yx_pos = 0;
|
||
pItem->yc_pos = 0;
|
||
//清空原先YXBW库
|
||
ClearUnitYXBW(pItem->GetUnitID());
|
||
return TRUE;
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE; //传输原因错误
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Clock_synchronisation_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //时钟同步
|
||
{
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
int ioa = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
|
||
unionCP56Time st;
|
||
st.millisecond = *pData; pData++;
|
||
st.millisecond |= (*pData << 8); pData++;
|
||
st.minute = *pData & 0x3f;
|
||
st.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.hour = *pData & 0x1f;
|
||
st.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
|
||
st.dayofmonth = *pData & 0x1f;
|
||
st.dayofweek = ((*pData & 0xe0) >> 5); pData++;
|
||
st.month = *pData & 0x0f; pData++;
|
||
st.year = *pData & 0x7f; pData++;
|
||
|
||
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], st);
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
if (st.IV)
|
||
{
|
||
vLog(LOG_WARN, "Remote Control system time is invalid.\n");
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
if (!IsAcceptTime())
|
||
{
|
||
vLog(LOG_WARN, "Local clock sync is not supported or not configured.\n");
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
set_system_time(&st);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE; //传输原因错误
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Counter_interrogation_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //累积量
|
||
{
|
||
QualifierOfCIC QCC;
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
int ioa = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
QCC = *pData;
|
||
|
||
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;
|
||
|
||
//累计量召唤命令限定词出错
|
||
if ((QCC & 0x3f) < IEC60870_QCC_RQT_GROUP_1 || (QCC & 0x3f) > IEC60870_QCC_RQT_GENERAL)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
pItem->call_type = QCC;
|
||
pItem->ym_pos = 0;
|
||
pItem->pulse_start = TRUE;
|
||
pItem->pulse_fin = FALSE;
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE; //传输原因错误
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Reset_process_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //复位进程
|
||
{
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
return TRUE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Single_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //单点令
|
||
{
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
BYTE command;
|
||
int uid, point;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE SE;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
if (!pItem->interrogation_finish) return TRUE;
|
||
|
||
information_address = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
command = *pData;
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_SC_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], information_address, FALSE);
|
||
asdu[len++] = command;
|
||
|
||
if (IEC_101_104_COT_ACT == cot || IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
uid = pItem->GetUnitID();
|
||
BYTE ioa[4];
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
|
||
point = GetUnitYKPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{ //信息体地址错误
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_INFO);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
SE = GET_SE(command);
|
||
value = GET_SCO(command); pData++;
|
||
//判断该点是否为单点遥控及参数状态
|
||
BYTE* param;
|
||
BYTE yk_type;
|
||
BYTE relay_type;
|
||
param = GetUnitYKParamByPoint(uid, point);
|
||
yk_type = param[4];
|
||
relay_type = param[5];
|
||
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
if (!isSingleCommandChecked(yk_type, relay_type, value))
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活
|
||
if (SE)
|
||
{ //选择
|
||
SetUnitYK(uid, point, value, YKS_SELREQ, YKR_IDLE);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //执行
|
||
SetUnitYK(uid, point, value, YKS_EXEREQ, YKR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
if (!isSingleCommandChecked(yk_type, relay_type, value))
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活终止
|
||
SetUnitYK(uid, point, value, YKS_ABRREQ, YKR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Double_command(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //单点令
|
||
{
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
BYTE command;
|
||
int uid, point;
|
||
DWORD information_address;
|
||
BOOLEAN value;
|
||
BYTE SE;
|
||
|
||
if (!pItem->interrogation_finish) return TRUE;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
information_address = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
command = *pData;
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_DC_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], information_address, FALSE);
|
||
asdu[len++] = command;
|
||
|
||
if (IEC_101_104_COT_ACT == cot || IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
uid = pItem->GetUnitID();
|
||
BYTE ioa[4];
|
||
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
|
||
point = GetUnitYKPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_INFO);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
SE = GET_SE(command);
|
||
value = GET_DCO(command); pData++;
|
||
//判断该点是否为单点遥控及参数状态
|
||
BYTE* param;
|
||
BYTE yk_type;
|
||
param = GetUnitYKParamByPoint(uid, point);
|
||
yk_type = param[4];
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
if (yk_type == USE_YK_SC)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活
|
||
if (SE)
|
||
{ //选择
|
||
SetUnitYK(uid, point, value, YKS_SELREQ, YKR_IDLE);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //执行
|
||
SetUnitYK(uid, point, value, YKS_EXEREQ, YKR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
if (yk_type == USE_YK_SC)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活终止
|
||
SetUnitYK(uid, point, value, YKS_ABRREQ, YKR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Set_point_command_normalized(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //设定规一化值命令
|
||
{
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
BYTE command;
|
||
int uid, point;
|
||
int information_address;
|
||
WORD value = 0;
|
||
BYTE SE;
|
||
|
||
if (!pItem->interrogation_finish) return TRUE;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
information_address = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
value = (WORD)(pData[0] | pData[1] << 8);
|
||
pData += 2;
|
||
command = *pData;
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_SE_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], information_address, FALSE);
|
||
asdu[len++] = value & 0xff;
|
||
asdu[len++] = (value >> 8) & 0xff;
|
||
asdu[len++] = command;
|
||
if (IEC_101_104_COT_ACT == cot || IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
uid = pItem->GetUnitID();
|
||
BYTE ioa[4];
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYTPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_INFO);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
SE = GET_SE(command);
|
||
//判断该点是否为单点遥控及参数状态
|
||
BYTE* param;
|
||
BYTE yt_type;
|
||
param = GetUnitYTParamByPoint(pItem->GetUnitID(), point);
|
||
yt_type = param[4];
|
||
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
if (yt_type != USE_YT_NA)
|
||
{ //遥控类型错误,返回否定确认
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活
|
||
if (SE)
|
||
{ //选择
|
||
SetUnitYT(uid, point, value, YTS_SELREQ, YTR_IDLE);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_SELREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //执行
|
||
SetUnitYT(uid, point, value, YTS_EXEREQ, YTR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
if (yt_type != USE_YT_NA)
|
||
{ //遥控类型错误,返回否定确认
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活终止
|
||
SetUnitYT(uid, point, value, YTS_ABRREQ, YTR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Set_point_command_scaled(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //设定标度化值命令
|
||
{
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
BYTE command;
|
||
int uid, point;
|
||
int information_address;
|
||
WORD value = 0;
|
||
BYTE SE;
|
||
|
||
if (!pItem->interrogation_finish) return TRUE;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
information_address = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
value = (WORD)(pData[0] | pData[1] << 8);
|
||
pData += 2;
|
||
command = *pData;
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_SE_NB_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], information_address, FALSE);
|
||
asdu[len++] = value & 0xff;
|
||
asdu[len++] = (value >> 8) & 0xff;
|
||
asdu[len++] = command;
|
||
if (IEC_101_104_COT_ACT == cot || IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
uid = pItem->GetUnitID();
|
||
BYTE ioa[4];
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYTPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_INFO);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
SE = GET_SE(command);
|
||
//判断该点是否为单点遥控及参数状态
|
||
BYTE* param;
|
||
BYTE yt_type;
|
||
param = GetUnitYTParamByPoint(pItem->GetUnitID(), point);
|
||
yt_type = param[4];
|
||
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
if (yt_type != USE_YT_NB)
|
||
{ //遥控类型错误,返回否定确认
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活
|
||
if (SE)
|
||
{ //选择
|
||
SetUnitYT(uid, point, value, YTS_SELREQ, YTR_IDLE);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_SELREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //执行
|
||
SetUnitYT(uid, point, value, YTS_EXEREQ, YTR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
if (yt_type != USE_YT_NB)
|
||
{ //遥控类型错误,返回否定确认
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活终止
|
||
SetUnitYT(uid, point, value, YTS_ABRREQ, YTR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Receive_Set_point_command_short_floating(CIEC101ProcessItem* pItem, const BYTE* pBuf, BYTE cot) //设定短浮点值命令
|
||
{
|
||
BYTE* pData = (BYTE*)pBuf;
|
||
BYTE command;
|
||
int uid, point;
|
||
int information_address;
|
||
DWORD value;
|
||
BYTE SE;
|
||
|
||
if (!pItem->interrogation_finish) return TRUE;
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
information_address = ASDU_getIOA(parameters, pData);
|
||
pData += parameters->sizeOfIOA;
|
||
value = (DWORD)(pData[0] | (pData[1] << 8) | (pData[2] << 16) | (pData[3] << 24));
|
||
pData += 4;
|
||
command = *pData;
|
||
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_SE_NC_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], information_address, FALSE);
|
||
asdu[len++] = value & 0xff;
|
||
asdu[len++] = (value >> 8) & 0xff;
|
||
asdu[len++] = (value >> 16) & 0xff;
|
||
asdu[len++] = (value >> 24) & 0xff;
|
||
asdu[len++] = command;
|
||
if (IEC_101_104_COT_ACT == cot || IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
uid = pItem->GetUnitID();
|
||
BYTE ioa[4];
|
||
ioa[0] = information_address & 0xff;
|
||
ioa[1] = (information_address >> 8) & 0xff;
|
||
ioa[2] = (information_address >> 16) & 0xff;
|
||
ioa[3] = (information_address >> 24) & 0xff;
|
||
point = GetUnitYTPointByParam(uid, ioa, 4);
|
||
if (point < 0)
|
||
{
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_INFO);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
SE = GET_SE(command);
|
||
//判断该点是否为单点遥控及参数状态
|
||
BYTE* param;
|
||
BYTE yt_type;
|
||
param = GetUnitYTParamByPoint(pItem->GetUnitID(), point);
|
||
yt_type = param[4];
|
||
|
||
if (IEC_101_104_COT_ACT == cot)
|
||
{
|
||
if (yt_type != USE_YT_NC)
|
||
{ //遥控类型错误,返回否定确认
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活
|
||
if (SE)
|
||
{ //选择
|
||
SetUnitYT(uid, point, value, YTS_SELREQ, YTR_IDLE);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_SELREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //执行
|
||
SetUnitYT(uid, point, value, YTS_EXEREQ, YTR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_ACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (IEC_101_104_COT_DEACT == cot)
|
||
{
|
||
if (yt_type != USE_YT_NB)
|
||
{ //遥控类型错误,返回否定确认
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
//激活终止
|
||
SetUnitYT(uid, point, value, YTS_ABRREQ, YTR_IDLE);
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_DEACTCON);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, point, value);
|
||
return TRUE;
|
||
}
|
||
}
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_UNKNOWN_COT);
|
||
ASDU_setNegative(asdu, TRUE);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_End_of_initialisation(CIEC101ProcessItem* pItem)
|
||
{
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), M_EI_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);
|
||
|
||
ASDU_setCOT(asdu, IEC_101_104_COT_INIT);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Single_point_information(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int uid;
|
||
int i, count, len;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_SP_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥信变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 1));
|
||
count = (pItem->yxbws.count > count) ? count : pItem->yxbws.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yxbws.data[i].order + pItem->yx_start_address), FALSE);
|
||
buffer[len++] = pItem->yxbws.data[i].value;
|
||
}
|
||
pItem->yxbws.count -= count;
|
||
if (pItem->yxbws.count <= 0 || pItem->yxbws.count >= DATABASE_YXBW_NUM)
|
||
{ //遥信变位发送结束
|
||
pItem->yxbws.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->yxbws.data, &pItem->yxbws.data[count], sizeof(struYXData) * pItem->yxbws.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = (parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA);
|
||
count = (count > 127) ? 127 : count; //遥信最大为127个信息
|
||
count = (pItem->total_yx - pItem->yx_pos) > count ? count : (pItem->total_yx - pItem->yx_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->yx_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yx_fin = TRUE; //遥信发送完毕
|
||
}
|
||
return FALSE;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yx_pos + pItem->yx_start_address), FALSE);
|
||
|
||
uid = pItem->GetUnitID();
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
buffer[len++] = GetUnitYX(uid, pItem->yx_pos + i) | GetUnitYXQDS(uid, pItem->yx_pos + i);
|
||
}
|
||
pItem->yx_pos += count;
|
||
if (pItem->yx_pos < 0 || pItem->yx_pos >= pItem->total_yx)
|
||
{
|
||
pItem->yx_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yx_fin = TRUE; //遥信发送完毕
|
||
}
|
||
}
|
||
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Single_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_SP_TA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //短时标事件记录
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 4));
|
||
count = (pItem->events.count > count) ? count : pItem->events.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->events.data[i].order + pItem->yx_start_address), FALSE);
|
||
buffer[len++] = pItem->yxbws.data[i].value;
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.millisecond & 0x00ff);;
|
||
buffer[len++] = (BYTE)((pItem->events.data[i].ct.millisecond >> 8)& 0x00ff);
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.minute | (pItem->events.data[i].ct.IV << 7));
|
||
}
|
||
pItem->events.count -= count;
|
||
if (pItem->events.count <= 0 || pItem->events.count >= DATABASE_SOE_NUM)
|
||
{ //事件记录发送结束
|
||
pItem->events.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->events.data, &pItem->events.data[count], sizeof(struEventsData) * pItem->events.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Single_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_SP_TB_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //长时标事件记录
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 8));
|
||
count = (pItem->events.count > count) ? count : pItem->events.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->events.data[i].order + pItem->yx_start_address), FALSE);
|
||
buffer[len++] = pItem->events.data[i].value;
|
||
buffer[len++]= (BYTE)(pItem->events.data[i].ct.millisecond & 0x00ff);
|
||
buffer[len++] = (BYTE)((pItem->events.data[i].ct.millisecond >> 8)& 0x00ff);
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.minute | (pItem->events.data[i].ct.IV << 7));
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.hour | (pItem->events.data[i].ct.SU << 7));
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.dayofmonth | (pItem->events.data[i].ct.dayofweek << 5));
|
||
buffer[len++] = (BYTE)pItem->events.data[i].ct.month;
|
||
buffer[len++] = (BYTE)pItem->events.data[i].ct.year;
|
||
}
|
||
pItem->events.count -= count;
|
||
if (pItem->events.count <= 0 || pItem->events.count >= DATABASE_SOE_NUM)
|
||
{ //事件记录发送结束
|
||
pItem->events.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->events.data, &pItem->events.data[count], sizeof(struEventsData) * pItem->events.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Double_point_information(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int uid;
|
||
int i, count, len;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_DP_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥信变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 1));
|
||
count = (pItem->yxbws.count > count) ? count : pItem->yxbws.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yxbws.data[i].order + pItem->yx_start_address), FALSE);
|
||
buffer[len++] = pItem->yxbws.data[i].value ? DPI_ON : DPI_OFF;
|
||
}
|
||
pItem->yxbws.count -= count;
|
||
if (pItem->yxbws.count <= 0 || pItem->yxbws.count >= DATABASE_YXBW_NUM)
|
||
{ //遥信变位发送结束
|
||
pItem->yxbws.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->yxbws.data, &pItem->yxbws.data[count], sizeof(struYXData) * pItem->yxbws.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = (parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA);
|
||
count = (count > 127) ? 127 : count; //遥信最大为127个信息
|
||
count = (pItem->total_yx - pItem->yx_pos) > count ? count : (pItem->total_yx - pItem->yx_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->yx_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yx_fin = TRUE; //遥信发送完毕
|
||
}
|
||
return FALSE;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yx_pos + pItem->yx_start_address), FALSE);
|
||
|
||
uid = pItem->GetUnitID();
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
buffer[len++] = (GetUnitYX(uid, pItem->yx_pos + i) ? DPI_ON : DPI_OFF) | GetUnitYXQDS(uid, pItem->yx_pos + i);
|
||
}
|
||
pItem->yx_pos += count;
|
||
if (pItem->yx_pos < 0 || pItem->yx_pos >= pItem->total_yx)
|
||
{
|
||
pItem->yx_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yx_fin = TRUE; //遥信发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Double_point_information_with_time_tag(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_DP_TA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //短时标事件记录
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 4));
|
||
count = (pItem->events.count > count) ? count : pItem->events.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->events.data[i].order + pItem->yx_start_address), FALSE);
|
||
buffer[len++] = pItem->yxbws.data[i].value ? DPI_ON : DPI_OFF;
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.millisecond & 0x00ff);;
|
||
buffer[len++] = (BYTE)((pItem->events.data[i].ct.millisecond >> 8)& 0x00ff);
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.minute | (pItem->events.data[i].ct.IV << 7));
|
||
}
|
||
pItem->events.count -= count;
|
||
if (pItem->events.count <= 0 || pItem->events.count >= DATABASE_SOE_NUM)
|
||
{ //事件记录发送结束
|
||
pItem->events.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->events.data, &pItem->events.data[count], sizeof(struEventsData) * pItem->events.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Double_point_information_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_DP_TB_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //长时标事件记录
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 8));
|
||
count = (pItem->events.count > count) ? count : pItem->events.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->events.data[i].order + pItem->yx_start_address), FALSE);
|
||
buffer[len++] = pItem->events.data[i].value ? DPI_ON : DPI_OFF;
|
||
buffer[len++]= (BYTE)(pItem->events.data[i].ct.millisecond & 0x00ff);
|
||
buffer[len++] = (BYTE)((pItem->events.data[i].ct.millisecond >> 8)& 0x00ff);
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.minute | (pItem->events.data[i].ct.IV << 7));
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.hour | (pItem->events.data[i].ct.SU << 7));
|
||
buffer[len++] = (BYTE)(pItem->events.data[i].ct.dayofmonth | (pItem->events.data[i].ct.dayofweek << 5));
|
||
buffer[len++] = (BYTE)pItem->events.data[i].ct.month;
|
||
buffer[len++] = (BYTE)pItem->events.data[i].ct.year;
|
||
}
|
||
pItem->events.count -= count;
|
||
if (pItem->events.count <= 0 || pItem->events.count >= DATABASE_SOE_NUM)
|
||
{ //事件记录发送结束
|
||
pItem->events.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->events.data, &pItem->events.data[count], sizeof(struEventsData) * pItem->events.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Measured_value_normalised(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int uid;
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_ME_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥测变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 3));
|
||
count = (pItem->ycbws.count > count) ? count : pItem->ycbws.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->ycbws.data[i].order + pItem->yc_start_address), FALSE);
|
||
buffer[len++] = pItem->ycbws.data[i].value & 0xff;
|
||
buffer[len++] = (pItem->ycbws.data[i].value >> 8) & 0xff;
|
||
buffer[len++] = 0;
|
||
}
|
||
pItem->ycbws.count -= count;
|
||
if (pItem->ycbws.count <= 0 || pItem->ycbws.count >= UNIT_YC_MAX)
|
||
{ //遥测变位发送结束
|
||
pItem->ycbws.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->ycbws.data, &pItem->ycbws.data[count], sizeof(struYCBW) * pItem->ycbws.count);
|
||
}
|
||
Slave_enqueueUserDataClass2(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA) / 3);
|
||
count = ((pItem->total_yc - pItem->yc_pos) > count) ? count : (pItem->total_yc - pItem->yc_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
return 0;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yc_pos + pItem->yc_start_address), FALSE);
|
||
short value;
|
||
uid = pItem->GetUnitID();
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
value = (short)GetUnitYC(uid, pItem->yc_pos + i);
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
buffer[len++] = GetUnitYCQDS(uid, pItem->yc_pos + i);
|
||
}
|
||
pItem->yc_pos += count;
|
||
if (pItem->yc_pos < 0 || pItem->yc_pos >= pItem->total_yc)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Measured_value_scaled(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int uid;
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_ME_NB_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥测变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 3));
|
||
count = (pItem->ycbws.count > count) ? count : pItem->ycbws.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->ycbws.data[i].order + pItem->yc_start_address), FALSE);
|
||
buffer[len++] = pItem->ycbws.data[i].value & 0xff;
|
||
buffer[len++] = (pItem->ycbws.data[i].value >> 8) & 0xff;
|
||
buffer[len++] = 0;
|
||
}
|
||
pItem->ycbws.count -= count;
|
||
if (pItem->ycbws.count <= 0 || pItem->ycbws.count >= UNIT_YC_MAX)
|
||
{ //遥测变位发送结束
|
||
pItem->ycbws.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->ycbws.data, &pItem->ycbws.data[count], sizeof(struYCBW) * pItem->ycbws.count);
|
||
}
|
||
Slave_enqueueUserDataClass2(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA) / 3);
|
||
count = ((pItem->total_yc - pItem->yc_pos) > count) ? count : (pItem->total_yc - pItem->yc_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
return 0;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yc_pos + pItem->yc_start_address), FALSE);
|
||
short value;
|
||
uid = pItem->GetUnitID();
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
value = (short)GetUnitYC(uid, pItem->yc_pos + i);
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
buffer[len++] = GetUnitYCQDS(uid, pItem->yc_pos + i);
|
||
}
|
||
pItem->yc_pos += count;
|
||
if (pItem->yc_pos < 0 || pItem->yc_pos >= pItem->total_yc)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Measured_value_short_floating_point(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int uid;
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_ME_NC_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥测变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 5));
|
||
count = (pItem->ycbws.count > count) ? count : pItem->ycbws.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->ycbws.data[i].order + pItem->yc_start_address), FALSE);
|
||
buffer[len++] = pItem->ycbws.data[i].code & 0xff;
|
||
buffer[len++] = (pItem->ycbws.data[i].code >> 8) & 0xff;
|
||
buffer[len++] = (pItem->ycbws.data[i].code >> 16) & 0xff;
|
||
buffer[len++] = (pItem->ycbws.data[i].code >> 24) & 0xff;
|
||
buffer[len++] = 0;
|
||
}
|
||
pItem->ycbws.count -= count;
|
||
if (pItem->ycbws.count <= 0 || pItem->ycbws.count >= UNIT_YC_MAX)
|
||
{ //遥测变位发送结束
|
||
pItem->ycbws.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->ycbws.data, &pItem->ycbws.data[count], sizeof(struYCBW) * pItem->ycbws.count);
|
||
}
|
||
Slave_enqueueUserDataClass2(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA) / 5);
|
||
count = ((pItem->total_yc - pItem->yc_pos) > count) ? count : (pItem->total_yc - pItem->yc_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
return 0;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yc_pos + pItem->yc_start_address), FALSE);
|
||
union {
|
||
float flval;
|
||
DWORD code;
|
||
} value;
|
||
uid = pItem->GetUnitID();
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
value.flval = GetUnitYCReal(uid, pItem->yc_pos + i);
|
||
buffer[len++] = value.code & 0xff;
|
||
buffer[len++] = (value.code >> 8) & 0xff;
|
||
buffer[len++] = (value.code >> 16) & 0xff;
|
||
buffer[len++] = (value.code >> 24) & 0xff;
|
||
buffer[len++] = GetUnitYCQDS(uid, pItem->yc_pos + i);
|
||
}
|
||
pItem->yc_pos += count;
|
||
if (pItem->yc_pos < 0 || pItem->yc_pos >= pItem->total_yc)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Measured_value_normalised_without_quality(CIEC101ProcessItem* pItem, BYTE cause_of_transimission /* = IEC_101_104_COT_SPONT */)
|
||
{
|
||
int uid;
|
||
int i, count;
|
||
int len = 0;
|
||
BYTE buffer[268];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_ME_ND_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥测变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 2));
|
||
count = (pItem->ycbws.count > count) ? count : pItem->ycbws.count;
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->ycbws.data[i].order + pItem->yc_start_address), FALSE);
|
||
buffer[len++] = pItem->ycbws.data[i].value & 0xff;
|
||
buffer[len++] = (pItem->ycbws.data[i].value >> 8) & 0xff;
|
||
}
|
||
pItem->ycbws.count -= count;
|
||
if (pItem->ycbws.count <= 0 || pItem->ycbws.count >= UNIT_YC_MAX)
|
||
{ //遥测变位发送结束
|
||
pItem->ycbws.count = 0;
|
||
}
|
||
else
|
||
{
|
||
memcpy(pItem->ycbws.data, &pItem->ycbws.data[count], sizeof(struYCBW) * pItem->ycbws.count);
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA) << 1);
|
||
count = ((pItem->total_yc - pItem->yc_pos) > count) ? count : (pItem->total_yc - pItem->yc_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
return 0;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->yc_pos + pItem->yc_start_address), FALSE);
|
||
short value;
|
||
uid = pItem->GetUnitID();
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
value = (short)GetUnitYC(uid, pItem->yc_pos + i);
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
}
|
||
pItem->yc_pos += count;
|
||
if (pItem->yc_pos < 0 || pItem->yc_pos >= pItem->total_yc)
|
||
{
|
||
pItem->yc_pos = 0;
|
||
if (IEC_101_104_COT_INTERROGATION == cause_of_transimission && pItem->interrogation_start)
|
||
{
|
||
pItem->interrogation_yc_fin = TRUE; //遥测发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Integrated_totals(CIEC101ProcessItem* pItem, BYTE cause_of_transimission)
|
||
{
|
||
int uid, len;
|
||
int i, count;
|
||
DWORD value;
|
||
BYTE buffer[256];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), M_IT_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (IEC_101_104_COT_SPONT == cause_of_transimission)
|
||
{ //遥脉变位
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA) / (parameters->sizeOfIOA + 5));
|
||
count = ((pItem->total_ym - pItem->ym_pos) > count) ? count : (pItem->total_ym - pItem->ym_pos);
|
||
if (count <= 0) return FALSE;
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->ym_pos + pItem->ym_start_address + i), FALSE);
|
||
value = GetUnitYM(uid, pItem->ym_pos + i);
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
buffer[len++] = (value >> 16) & 0xff;
|
||
buffer[len++] = (value >> 24) & 0xff;
|
||
buffer[len++] = (pItem->ym_pos + i ) % 32;
|
||
}
|
||
pItem->ym_pos += count;
|
||
if (pItem->ym_pos < 0 || pItem->ym_pos >= pItem->total_ym)
|
||
{
|
||
pItem->ym_pos = 0;
|
||
if ((IEC_101_104_COT_REQCOGEN == cause_of_transimission || IEC_101_104_COT_INTERROGATION == cause_of_transimission) && pItem->pulse_start)
|
||
{
|
||
pItem->pulse_fin = TRUE; //遥脉发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{ //召唤
|
||
count = ((parameters->maxSizeOfASDU - parameters->sizeOfCOT - parameters->sizeOfCA - parameters->sizeOfIOA) / + 5);
|
||
count = ((pItem->total_ym - pItem->ym_pos) > count) ? count : (pItem->total_ym - pItem->ym_pos);
|
||
if (count <= 0)
|
||
{
|
||
pItem->ym_pos = 0;
|
||
if ((IEC_101_104_COT_REQCOGEN == cause_of_transimission || IEC_101_104_COT_INTERROGATION == cause_of_transimission) && pItem->pulse_start)
|
||
{
|
||
pItem->pulse_fin = TRUE; //遥脉发送完毕
|
||
}
|
||
return 0;
|
||
}
|
||
ASDU_setNumberOfElements(buffer, count);
|
||
ASDU_setSequence(buffer, TRUE);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], (pItem->ym_pos + pItem->ym_start_address), FALSE);
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
value = GetUnitYM(uid, pItem->ym_pos + i);
|
||
buffer[len++] = value & 0xff;
|
||
buffer[len++] = (value >> 8) & 0xff;
|
||
buffer[len++] = (value >> 16) & 0xff;
|
||
buffer[len++] = (value >> 24) & 0xff;
|
||
buffer[len++] = (pItem->ym_pos + i ) % 32;
|
||
}
|
||
pItem->ym_pos += count;
|
||
if (pItem->ym_pos < 0 || pItem->ym_pos >= pItem->total_ym)
|
||
{
|
||
pItem->ym_pos = 0;
|
||
if ((IEC_101_104_COT_REQCOGEN == cause_of_transimission || IEC_101_104_COT_INTERROGATION == cause_of_transimission) && pItem->pulse_start)
|
||
{
|
||
pItem->pulse_fin = TRUE; //遥脉发送完毕
|
||
}
|
||
}
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_FrameInterrogation(CIEC101ProcessItem* pItem, BYTE cause_of_transimission)
|
||
{
|
||
int len;
|
||
BYTE buffer[256];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), C_IC_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
ASDU_addNumberOfElements(buffer);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], 0, FALSE);
|
||
buffer[len++] = pItem->call_type;
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_FrameCounterInterrogation(CIEC101ProcessItem* pItem, BYTE cause_of_transimission)
|
||
{
|
||
int len;
|
||
BYTE buffer[256];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
|
||
pIEC101_AppLayerParameters parameters = &(pItem->applicationlParameters);
|
||
len = ASDU_initialize(buffer, &(pItem->applicationlParameters), C_CI_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
|
||
ASDU_addNumberOfElements(buffer);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &buffer[len], 0, FALSE);
|
||
buffer[len++] = pItem->call_type;
|
||
Slave_enqueueUserDataClass1(pItem, buffer, len);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Test_command(CIEC101ProcessItem* pItem, BYTE cause_of_transimission)
|
||
{
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_TS_NA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
ASDU_addNumberOfElements(asdu);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], 0, FALSE);
|
||
asdu[len++] = 0xAA; asdu[len++] = 0x55;
|
||
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CIEC101SecondaryProcess::Send_Test_command_with_time_tag_cp56time2a(CIEC101ProcessItem* pItem, BYTE cause_of_transimission)
|
||
{
|
||
BYTE asdu[260];
|
||
int len = ASDU_initialize(asdu, &(pItem->applicationlParameters), C_TS_TA_1, FALSE, cause_of_transimission, pItem->applicationlParameters.originatorAddress, pItem->common_address, FALSE, FALSE);
|
||
ASDU_addNumberOfElements(asdu);
|
||
len += InformationObject_setObjectAddress(&(pItem->applicationlParameters), &asdu[len], 0, FALSE);
|
||
asdu[len++] = 0xAA; asdu[len++] = 0x55;
|
||
len += unionCP56TimeToBuf(&asdu[len], system32.now);
|
||
Slave_enqueueUserDataClass1(pItem, asdu, len);
|
||
return TRUE;
|
||
}
|