map/das-dn/subiec101unbalanced/sub_iec101_unbalanced.cpp

404 lines
13 KiB
C++
Raw Normal View History

2024-07-08 10:27:17 +08:00
#include "sub_iec101_unbalanced.h"
/***************************************************************************************/
BOOLEAN CIEC101SecondaryUnbalancedProcess::OnPreCreate(int id)
{
if (!CIEC101Process::OnPreCreate(id)) return FALSE;
int i;
int uid;
CIEC101SecondaryUnbalancedProcessItem* pItem;
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC101SecondaryUnbalancedProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
BYTE phy_addr[2];
GetUnitAddr(uid, phy_addr, 2);
pItem->Attach(uid, phy_addr[0], phy_addr[0], m_option.originatorAddress); //默认公共地址和物理地址一致
pItem->setAppLayerParameters(m_option.sizeOfCOT, m_option.sizeOfCA, m_option.sizeOfIOA, m_option.maxSizeOfASDU);
Slave_setLinkLayerAddressOtherStation(pItem, phy_addr[1]);
pItem->setAppLayerIOABase();
pItem->setAppLayerDataCount(GetUnitYXCount(uid), GetUnitYCCount(uid), GetUnitYMCount(uid));
}
last_sec = (time_t)system32.timers;
return TRUE;
}
BOOLEAN CIEC101SecondaryUnbalancedProcess::Run(void)
{
if (!CIEC101Process::Run()) return FALSE;
FeedDog();
if (m_state != LL_STATE_IDLE)
{
if ((getTimeInMs() - m_lastReceivedMsg) > (unsigned int) m_idleTimeout)
{
llsu_setState(LL_STATE_IDLE);
}
}
return TRUE;
}
BOOLEAN CIEC101SecondaryUnbalancedProcess::OnTimer(void)
{
if (!CIEC101Process::OnTimer()) return FALSE;
BOOLEAN sec_changed = FALSE;
if (last_sec != (time_t)system32.timers)
{
last_sec = (time_t)system32.timers;
sec_changed = TRUE;
}
CIEC101ProcessItem* pItem = (CIEC101ProcessItem *)GetCurItem();
if (NULL == pItem) return TRUE;
int uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return TRUE;
//刷新事件记录库
GetItemEvents(pItem);
//刷新遥测库
FetchUnitYC(0);
if (pItem->interrogation_finish)
{
//总召唤结束,开始上送遥信变位
GetItemYXBWs(pItem);
//总召唤结束,开始刷新遥测变位缓冲。
if (pItem->ycbws.count <= 0)
{ //当遥测变位发送结束后才更新
GetItemYCBWs(pItem);
}
//发送遥控返校
if (MakeYKFrame(pItem)) return TRUE;
if (MakeYTFrame(pItem)) return TRUE;
if (Send_Single_point_information(pItem)) return TRUE;
if (Send_Single_point_information_with_time_tag_cp56time2a(pItem)) return TRUE;
if (!pItem->interrogation_start)
{ //变位遥测优先级在总召唤之后。
if (sec_changed)
{
switch (m_option.yc_type)
{
case USE_YC_NB: //标度化值
return Send_Measured_value_scaled(pItem);
case USE_YC_NC: //短浮点数
return Send_Measured_value_short_floating_point(pItem);
case USE_YC_ND: //不带品质归一化值
return Send_Measured_value_normalised_without_quality(pItem);
default: //USE_YC_NA: 归一化值
return Send_Measured_value_normalised(pItem);
}
}
}
}
//响应总召唤命令
if (pItem->interrogation_start)
{
if (pItem->call_type != IEC_101_104_COT_INTERROGATION)
{ //组召唤
//激活终止
Send_FrameInterrogation(pItem);
pItem->call_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
}
else if (!pItem->interrogation_yx_fin)
{
Send_Single_point_information(pItem, IEC_101_104_COT_INTERROGATION);
}
else if (!pItem->interrogation_yc_fin)
{
switch (m_option.yc_type)
{
case USE_YC_NB: //标度化值
return Send_Measured_value_scaled(pItem, IEC_101_104_COT_INTERROGATION);
case USE_YC_NC: //短浮点数
return Send_Measured_value_short_floating_point(pItem, IEC_101_104_COT_INTERROGATION);
case USE_YC_ND: //不带品质归一化值
return Send_Measured_value_normalised_without_quality(pItem, IEC_101_104_COT_INTERROGATION);
default: //USE_YC_NA: 归一化值
return Send_Measured_value_normalised(pItem, IEC_101_104_COT_INTERROGATION);
}
}
else
{
Send_FrameInterrogation(pItem);
pItem->call_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
}
}
else if (pItem->pulse_start)
{
if (!pItem->pulse_fin)
{
Send_Integrated_totals(pItem, IEC_101_104_COT_REQCOGEN);
}
else
{
Send_FrameCounterInterrogation(pItem);
pItem->call_type = 0;
pItem->pulse_start = FALSE;
pItem->pulse_fin = TRUE;
}
}
return TRUE;
}
int CIEC101SecondaryUnbalancedProcess::OnPackageReceived(BYTE* pBuf, int msgSize, int /* ord = -1 */)
{
m_lastReceivedMsg = getTimeInMs();
int userDataLength = 0;
int userDataStart = 0;
BYTE c;
int csStart;
int csIndex;
int address = 0;
int addressLength = m_linkLayer.linkLayerParameters.addressLength;
BYTE* msg = (BYTE *)pBuf;
if (msg [0] == 0x68)
{
if (msg [1] != msg [2])
{
vLog(LOG_DEBUG, "ERROR: L fields differ!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
userDataLength = (int)msg [1] - addressLength - 1;
userDataStart = 5 + addressLength;
csStart = 4;
csIndex = userDataStart + userDataLength;
/* check if message size is reasonable */
if (msgSize != (userDataStart + userDataLength + 2 /* CS + END */))
{
vLog(LOG_DEBUG, "ERROR: Invalid message length\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
c = msg [4];
}
else if (msg [0] == 0x10)
{
c = msg [1];
csStart = 1;
csIndex = 2 + addressLength;
}
else
{
vLog(LOG_DEBUG, "ERROR: Received unexpected message type in unbalanced slave mode!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
BOOLEAN isBroadcast = false;
CIEC101ProcessItem* pItem;
/* check address */
if (addressLength > 0)
{
address = msg[csStart + 1];
if (addressLength > 1)
{
address += msg [csStart + 2] * 0x100;
if (address == 65535) isBroadcast = TRUE;
}
else
{
if (address == 255) isBroadcast = TRUE;
}
}
int fc = c & 0x0f;
if (isBroadcast)
{
if (fc != LL_FC_04_USER_DATA_NO_REPLY)
{
vLog(LOG_DEBUG, "ERROR: Invalid function code for broadcast message!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
}
else
{
int uid = GetUnitByAddr((BYTE *)&address, m_linkLayer.linkLayerParameters.addressLength);
if (uid < 0 || uid >= UNIT_NUM)
{
vLog(LOG_DEBUG, "INFO: unknown link layer address(%i) -> ignore message\n", address);
return 1;
}
pItem = (CIEC101ProcessItem *)GetItem(GetOrderByUnitID(uid));
if (pItem == NULL)
{
vLog(LOG_DEBUG, "INFO: unknown link layer address(%i) -> ignore message\n", address);
return 1;
}
UnitFeedDog(uid);
}
/* check checksum */
BYTE checksum = 0;
int i;
for (i = csStart; i < csIndex; i++) checksum += msg [i];
if (checksum != msg [csIndex])
{
vLog(LOG_DEBUG, "ERROR: checksum invalid!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
/* parse C field bits */
BOOLEAN prm = ((c & 0x40) == 0x40);
if (prm == FALSE)
{
vLog(LOG_DEBUG, "ERROR: Received secondary message in unbalanced slave mode!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
BOOLEAN fcb = ((c & 0x20) == 0x20);
BOOLEAN fcv = ((c & 0x10) == 0x10);
LinkLayerSecondaryUnbalanced_ReceivedMessage(pItem, fc, isBroadcast, fcb, fcv, msg, userDataStart, userDataLength);
return 1;
}
//不平衡方式从协议接收到主站报文
void CIEC101SecondaryUnbalancedProcess::LinkLayerSecondaryUnbalanced_ReceivedMessage(CIEC101ProcessItem* pItem, BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, BYTE* msg, int userDataStart, int userDataLength)
{
pIEC101_LinkLayerSecondaryUnbalanced self = &(pItem->secondaryLinkUnbalanced);
if (fcv)
{
if (checkFCB(self, fcb) == FALSE)
{
vLog(LOG_DEBUG, "SLL - FCB check failed\n");
llsu_setState(LL_STATE_ERROR);
return;
}
}
llsu_setState(LL_STATE_AVAILABLE);
switch (fc)
{
case LL_FC_09_REQUEST_LINK_STATUS:
//vLog(LOG_DEBUG, "SLL - REQUEST LINK STATUS\n");
{
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
SendFixedFrame(LL_FC_11_STATUS_OF_LINK_OR_ACCESS_DEMAND, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
break;
case LL_FC_00_RESET_REMOTE_LINK:
//vLog(LOG_DEBUG, "SLL - RESET REMOTE LINK\n");
{
self->expectedFcb = TRUE;
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, FALSE, FALSE, FALSE);
}
ResetCUReceived(pItem, FALSE);
}
break;
case LL_FC_07_RESET_FCB:
//vLog(LOG_DEBUG, "SLL - RESET FCB\n");
{
self->expectedFcb = TRUE;
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, FALSE, FALSE, FALSE);
}
ResetCUReceived(pItem, TRUE);
}
break;
case LL_FC_11_REQUEST_USER_DATA_CLASS_2:
//vLog(LOG_DEBUG, "SLL - REQUEST USER DATA CLASS 2\n");
{
/* provide a buffer where the application layer can encode the user data */
pIEC101_QueueElement element = GetClass2Data(pItem);
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
if (element)
{
SendVariableLengthFrame(LL_FC_08_RESP_USER_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE, element->buffer, element->size);
}
else
{
if (m_linkLayer.linkLayerParameters.useSingleCharACK && !accessDemand)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_09_RESP_NACK_NO_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
}
}
break;
case LL_FC_10_REQUEST_USER_DATA_CLASS_1:
//vLog(LOG_DEBUG, "SLL - REQUEST USER DATA CLASS 1\n");
{
/* provide a buffer where the application layer can encode the user data */
pIEC101_QueueElement element = GetClass1Data(pItem);
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
if (element)
{
SendVariableLengthFrame(LL_FC_08_RESP_USER_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE, element->buffer, element->size);
}
else
{
if (m_linkLayer.linkLayerParameters.useSingleCharACK && !accessDemand)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_09_RESP_NACK_NO_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
}
}
break;
case LL_FC_03_USER_DATA_CONFIRMED:
//vLog(LOG_DEBUG, "SLL - USER DATA CONFIRMED\n");
if (userDataLength > 0)
{
if (ApplicationLayer_ReceivedData(pItem, msg, isBroadcast, userDataStart, userDataLength))
{
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
if (m_linkLayer.linkLayerParameters.useSingleCharACK && !accessDemand)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
}
}
break;
case LL_FC_04_USER_DATA_NO_REPLY:
//vLog(LOG_DEBUG, "SLL - USER DATA NO REPLY\n");
if (userDataLength > 0)
{
ApplicationLayer_ReceivedData(pItem, msg, isBroadcast, userDataStart, userDataLength);
}
break;
default:
//vLog(LOG_DEBUG, "SLL - UNEXPECTED LINK LAYER MESSAGE\n");
SendFixedFrame(LL_FC_15_SERVICE_NOT_IMPLEMENTED, pItem->address, FALSE, FALSE, FALSE, FALSE);
break;
}
}