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

440 lines
15 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 "host_iec104.h"
CHostIEC104Process::CHostIEC104Process()
{
last_sec = system32.timers;
}
CHostIEC104Process::~CHostIEC104Process()
{
}
BOOLEAN CHostIEC104Process::OnPreCreate(int id)
{
if (!CIEC104Process::OnPreCreate(id)) return FALSE;
int i;
CIEC104ProcessItem *pItem;
//更新配置
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC104ProcessItem *)GetItem(i);
if (NULL == pItem) continue;
pItem->apdu_k_max = m_nOption.k;
pItem->apdu_w_max = m_nOption.w;
pItem->apdu_t0_begin = 10;//system32.timers;
}
return TRUE;
}
BOOLEAN CHostIEC104Process::OnCreated(int id)
{
return CIEC104Process::OnCreated(id);
}
BOOLEAN CHostIEC104Process::Run(void)
{
if (!CIEC104Process::Run())
{
return FALSE;
}
FeedDog();
return TRUE;
}
BOOLEAN CHostIEC104Process::OnTimer(void)
{
int uid;
int i;
CIEC104ProcessItem *pItem;
BOOLEAN sec_changed = FALSE;
if (!CIEC104Process::OnTimer()) return FALSE;
if (last_sec != (time_t)system32.timers)
{
last_sec = system32.timers;
sec_changed = TRUE;
}
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC104ProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
int sock = pItem->GetSock();
if (sock < 0)
{ //服务器等待客户端链接
if (!IsClient()) continue;
//需要连接server
if (pItem->apdu_t0_begin > 0 && system32.timers > (pItem->apdu_t0_begin + apdu_t0_max))
{
pItem->apdu_t0_begin = system32.timers;
if (Connect(pItem, i))
{
if (!SendUFrame(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, i))
{
pItem->Release();
continue;
}
}
}
usleep(20000);
continue;
}
pItem->apdu_t0_begin = system32.timers;
//TCP连接就表示该单元通讯正常
UnitFeedDog(uid);
if (pItem->apdu_t3_begin > 0 && system32.timers > (pItem->apdu_t3_begin + apdu_t3_max))
{
//vLog(LOG_DEBUG, "Unit(%d) t3 expired.\n", uid);
if (!SendUFrame(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, i))
{
pItem->Release();
continue;
}
pItem->apdu_t3_begin = 0;
//启动t1计时
pItem->apdu_t1_begin = system32.timers;
pItem->apdu_wait_test = TRUE;
continue;
}
//判断t1超时
if (pItem->apdu_t1_begin > 0 && system32.timers > (pItem->apdu_t1_begin + apdu_t1_max))
{ //直接复位链路
vLog(LOG_ERROR, "Unit(%d) t1 expired (begin at %lu).\n", uid, pItem->apdu_t1_begin);
pItem->Release();
continue;
}
//判断t2超时
if (pItem->apdu_t2_begin > 0 && system32.timers > (pItem->apdu_t2_begin + apdu_t2_max))
{ //发送S帧
//vLog(LOG_DEBUG, "Unit(%d) t2 expired.\n", uid);
if (!SendSFrame(i))
{
pItem->Release();
continue;
}
continue;
}
//如果链路通信未启动则不发送任何报文
if (!pItem->apdu_setup)
{
//vLog(LOG_DEBUG, "apdu is not setup. \n ");
if (IsClient() && !pItem->apdu_setup_sent)
{
pItem->apdu_setup_sent = TRUE;
vLog(LOG_DEBUG, "sent start dt command.\r\n");
if (!SendUFrame(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, i))
{
pItem->Release();
continue;
}
}
continue;
}
//是否已经达到k值,若k值已经达到则不再发送数据报文
if (pItem->apdu_k >= pItem->apdu_k_max) continue;
//遥控报文
if (GetYKFrame(pItem, i)) continue;
//遥调报文
if (GetYTFrame(pItem, i)) continue;
//时钟同步
if (GetSetTimeGap() > 0)
{ //需要对时
if (!pItem->clock_synchronized_start && !pItem->clock_synchronized_finish)
{
pItem->clock_synchronized_start = TRUE;
if (!SendClock_synchronisation_command(pItem, i))
{
pItem->Release();
continue;
}
}
if (!pItem->clock_synchronized_finish) continue;
}
//是否需要总召唤
if (!pItem->interrogation_start)
{
pItem->interrogation_start = TRUE;
//发送总召唤报文
if (!SendInterrogation_command(pItem, i))
{
pItem->Release();
continue;
}
}
//总召唤没有结束
if (!pItem->interrogation_finish) continue;
if (sec_changed)
{
if (pItem->total_ym > 0)
{
if (apdu_t5_max > 0 && system32.timers > (pItem->apdu_t5_begin + apdu_t5_max)) //请求电度
{
pItem->apdu_t5_begin = system32.timers;
if (!SendCounter_Interrogation_command(pItem, i))
{
pItem->Release();
continue;
}
}
}
if (use_cycle_interrogation_command)
{
if (apdu_t4_max > 0 && system32.timers > (pItem->apdu_t4_begin + apdu_t4_max)) //请求总召唤
{
pItem->apdu_t4_begin = system32.timers;
if (!SendInterrogation_command(pItem, i))
{
pItem->Release();
continue;
}
}
}
}
}
return TRUE;
}
BOOLEAN CHostIEC104Process::OnIFrameReceived(WORD ns, WORD nr, BYTE* pBuf, int count, int ord)
{
int uid;
BYTE* pData = pBuf;
CIEC104ProcessItem* pItem = (CIEC104ProcessItem *)GetItem(ord);
if (NULL == pItem) return FALSE;
uid = (int)pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
vLog(LOG_DEBUG, "Unit(%d) On I Frame (%s %s) Received ns = %d, nr = %d\n", uid, val_to_str(pBuf[0], iec_101_104_asdu_types, "UnknowType=%02x"), val_to_str(pBuf[0], iec_101_104_asdu_lngtypes, "UnknowType=%02x"), (int)ns, (int)nr);
//处理接收序号
if (!OnDealWithPeerNS(pItem, ns)) return FALSE;
//处理发送序号
if (!OnDealWithPeerNR(pItem, nr)) return FALSE;
BYTE num, vsq, type;
BOOLEAN sq, pn, test;
WORD cot = 0;
WORD asdu_address = 0;
type = *pData; pData++;
vsq = *pData; pData++;
if (1 == m_nOption.cot_size)
{
cot = *pData; pData++;
}
else if (2 == m_nOption.cot_size)
{
cot = *pData; pData++;
cot |= (*pData << 8); pData++;
}
if (1 == m_nOption.asdu_addr_size)
{
asdu_address = *pData; pData++;
}
if (2 == m_nOption.asdu_addr_size)
{
asdu_address = *pData; pData++;
asdu_address |= (*pData << 8); pData++;
}
num = (vsq & 0x7f);
sq = (vsq & 0x80) == 0x80 ? TRUE : FALSE;
pn = (cot & 0x40) == 0x40 ? TRUE : FALSE;
test = (cot & 0x80) == 0x80 ? TRUE : FALSE;
//判断CA地址是否正确
if (asdu_address != pItem->apdu_addr)
{ //返回未知的应用服务数据单元公共地址
vLog(LOG_WARN, "Unit(%d) CA(%d) received type(%d).\n", uid, asdu_address, type);
return TRUE;
}
//启动t2计时
if (pItem->apdu_t2_begin == 0)
{
pItem->apdu_t2_begin = system32.timers;
}
pItem->apdu_w++;
if (pItem->apdu_w >= pItem->apdu_w_max)
{
//vLog(LOG_DEBUG, "Unit(%d) w value reached.\n", uid);
if (!SendSFrame(ord))
{
pItem->Release();
return FALSE;
}
}
//重置t3计时
pItem->apdu_t3_begin = system32.timers;
//处理接收到的报文
switch (type)
{
case M_SP_NA_1: //单点遥信
OnReceiveSingle_point_information(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_SP_TA_1: //带时标的单点遥信
OnReceiveSingle_point_information_with_time_tag(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_DP_NA_1: //双点遥信
OnReceiveDouble_point_information(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_DP_TA_1: //带时标的双点遥信
OnReceiveDouble_point_information_with_time_tag(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_NA_1: //测量值,归一化值
OnReceiveMeasured_value_normalised(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_TA_1: //带时标的遥测量,归一化值
OnReceiveMeasured_value_normalised_with_time_tag(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_NB_1: //测量值,标度化值
OnReceiveMeasured_value_scaled(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_TB_1: //带时标的遥测量,标度化值
OnReceiveMeasured_value_scaled_with_time_tag(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_NC_1: //测量值,短浮点数
OnReceiveMeasured_value_short_floating_point(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_TC_1: //带时标的遥测量值,短浮点数
OnReceiveMeasured_value_short_floating_point_with_time_tag(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_ND_1: //测量值,不带品质描述的归一化测量值
OnReceiveMeasured_value_normalised_without_quality(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_SP_TB_1: //带CP56Time2a时标的单点信息
OnReceiveSingle_point_information_with_time_tag_cp56time2a(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_DP_TB_1: //带CP56Time2a时标的双点信息
OnReceiveDouble_point_information_with_time_tag_cp56time2a(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_TD_1: //带CP56Time2a时标的遥测量值归一化值
OnReceiveMeasured_value_normalised_with_time_tag_cp56time2a(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_TE_1: //带CP56Time2a时标的遥测量值标度化值
OnReceiveMeasured_value_scaled_with_time_tag_cp56time2a(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_ME_TF_1: //带CP56Time2a时标的遥测量值短浮点数
OnReceiveMeasured_value_short_floating_point_with_time_tag_cp56time2a(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_IT_NA_1: //累积量
OnReceiveIntegrated_totals(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_SC_NA_1: //单点令
OnReceiveSingle_command(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_DC_NA_1: //双点令
OnReceiveDouble_command(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_SE_NA_1: //设定值命令,归一化值
OnReceiveSet_point_command_normalized(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_SE_NB_1: //设定值命令,标度化值
OnReceiveSet_point_command_scaled(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_SE_NC_1: //设定值命令,短浮点数
OnReceiveSet_point_command_short_floating(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_IC_NA_1: //总召唤命令
OnReceiveInterrogation_command(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_CS_NA_1: //时钟同步
OnReceiveClock_synchronisation_command(pItem, uid, pData, sq, pn, test, num, cot);
break;
case C_CI_NA_1:
OnReceiveCounter_Interrogation_command(pItem, uid, pData, sq, pn, test, num, cot);
break;
case M_EI_NA_1:
pItem->end_of_initialisation = TRUE;
break;
default:
vLog(LOG_WARN, "Unit(%d) Unsupported I frame type = 0x%02x\n", uid, (int)pBuf[0]);
break;
}
return TRUE;
}
BOOLEAN CHostIEC104Process::OnUFrameReceived(BOOLEAN STARTDT_ACT, BOOLEAN STARTDT_CON, BOOLEAN STOPDT_ACT, BOOLEAN STOPDT_CON, BOOLEAN TESTFR_ACT, BOOLEAN TESTFR_CON, int ord)
{
int uid;
BYTE phy_addr[6];
CIEC104ProcessItem* pItem = (CIEC104ProcessItem *)GetItem(ord);
if (NULL == pItem) return FALSE;
uid = (int)pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
vLog(LOG_DEBUG, "Unit(%d) Received U Frame%s%s%s%s%s%s\n",
uid,
(STARTDT_ACT ? " STARTDT active": ""),
(STOPDT_ACT ? " STOPDT active": ""),
(TESTFR_ACT ? " TESTFR active": ""),
(STARTDT_CON ? " STARTDT confirm": ""),
(STOPDT_CON ? " STOPDT confirm": ""),
(TESTFR_CON ? " TESTFR confirm": ""));
if (STARTDT_ACT)
{
vLog(LOG_ERROR, "UNSUPPORT STARTDT CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (STARTDT_CON)
{
if (!GetUnitAddr(uid, (BYTE *)phy_addr, 6))
{
pItem->apdu_addr = 0x0001;
}
else
{
pItem->apdu_addr = ((phy_addr[5] << 8) | phy_addr[4]);
}
vLog(LOG_DEBUG, "Unit(%d) apdu_addr(%d)\n", uid, pItem->apdu_addr);
pItem->apdu_setup = TRUE;
pItem->apdu_ns = 0;
pItem->apdu_nr = 0;
pItem->apdu_ack = 0;
pItem->apdu_t3_begin = system32.timers; //启动t3计时
pItem->apdu_wait_test = FALSE;
pItem->apdu_k = 0;
pItem->total_ym = GetUnitYMCount(uid);
}
if (STOPDT_ACT)
{
vLog(LOG_ERROR, "UNSUPPORT STOPDT CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (STOPDT_CON)
{
vLog(LOG_WARN, "UNSUPPORT STOPDT COMMAND! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (TESTFR_ACT)
{
if (!SendUFrame(FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ord))
{
vLog(LOG_ERROR, "Send U Frame Error.\n");
pItem->Release();
return FALSE;
}
pItem->apdu_t1_begin = 0;
pItem->apdu_setup_sent = FALSE;
pItem->apdu_t3_begin = system32.timers; //重置t3计时
}
if (TESTFR_CON)
{
if (pItem->apdu_wait_test)
{
pItem->apdu_t1_begin = 0;
pItem->apdu_t3_begin = system32.timers; //重置t3计时
pItem->apdu_wait_test = FALSE;
pItem->apdu_setup_sent = FALSE;
}
else
{
vLog(LOG_ERROR, "UNSUPPORT TESTFR CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
}
return TRUE;
}