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

4221 lines
159 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}