map/das-dn/subiec104/sub_iec104.cpp
2024-09-24 15:59:22 +08:00

642 lines
22 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 "sub_iec104.h"
CSubIEC104Process::CSubIEC104Process()
{
last_sec = system32.timers;
memset(&m_nOption, 0, sizeof(m_nOption));
}
CSubIEC104Process::~CSubIEC104Process()
{
}
BOOLEAN CSubIEC104Process::OnPreCreate(int id)
{
if (!CIEC104Process::OnPreCreate(id)) return FALSE;
m_yx_start_address = m_nOption.yx_start_address;
m_yc_start_address = m_nOption.yc_start_address;
m_ym_start_address = m_nOption.ym_start_address;
if (m_yx_start_address <= 0) m_yx_start_address = IEC_101_104_YX_START_ADDR;
if (m_yc_start_address <= 0) m_yc_start_address = IEC_101_104_YC_START_ADDR;
if (m_ym_start_address <= 0) m_ym_start_address = IEC_101_104_YM_START_ADDR;
int i;
int uid;
BYTE phy_addr[6];
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;
if (IsClient())
{
uid = (int)pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
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);
}
}
return TRUE;
}
BOOLEAN CSubIEC104Process::OnCreated(int id)
{
return CIEC104Process::OnCreated(id);
}
BOOLEAN CSubIEC104Process::Run(void)
{
if (!CIEC104Process::Run()) return FALSE;
int i, uid;
CIEC104ProcessItem* pItem;
FeedDog();
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;
if (pItem->interrogation_finish)
{
GetItemYXBWs(pItem);
}
//刷新事件记录库
GetItemEvents(pItem);
//刷新遥测库
FetchUnitYC(i);
//总召唤结束,开始刷新遥测变位缓冲。
if (pItem->interrogation_finish)
{
//刷新遥测变位
if (pItem->ycbws.count <= 0)
{ //当遥测变位发送结束后才更新
GetItemYCBWs(pItem);
}
}
}
return TRUE;
}
BOOLEAN CSubIEC104Process::OnTimer(void)
{
int uid;
int i;
int ret;
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;
if (pItem->GetSock() < 0)
{
if (pItem->end_of_initialisation)
{
//初始化结束,网络断开的情况下保存数据
}
if (IsClient())
{ //如果为客户端则需要区链接服务器
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 (send_start_dt)
{ //客户端发送start dt
if (!SendUFrame(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, i))
{
pItem->Release();
continue;
}
}
if (use_send_test)
{
switch (send_test_type)
{
case C_TS_TA_1:
if (Send_Test_command_with_time_tag_cp56time2a(pItem, i) < 0)
{
pItem->Release();
continue;
}
break;
default:
if (Send_Test_command(pItem, i) < 0)
{
pItem->Release();
continue;
}
break;
}
}
}
}
}
continue;
}
pItem->apdu_t0_begin = system32.timers;
//判断t3超时
if (pItem->apdu_t3_begin > 0 && system32.timers > (pItem->apdu_t3_begin + apdu_t3_max))
{
if (!SendUFrame(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, i))
{
vLog(LOG_ERROR, "Unit(%d) SendUFrame error.\n", uid);
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))
{
vLog(LOG_ERROR, "Unit(%d) SendSFrame error.\n", uid);
pItem->Release();
continue;
}
continue;
}
//如果链路通信未启动则不发送任何报文
if (!pItem->apdu_setup) continue;
//是否已经达到k值,若k值已经达到则不再发送数据报文
if (pItem->apdu_k >= pItem->apdu_k_max) continue;
//总召唤没有结束不响应遥控。不上送遥信变位及SOE
if (pItem->interrogation_finish)
{ //发送遥控返校
ret = MakeYKFrame(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
//发送遥调返校
ret = MakeYTFrame(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
//发送遥信变位
ret = Send_Single_point_information(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
//发送SOE信息
ret = Send_Single_point_information_with_time_tag_cp56time2a(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
//响应总召唤命令
if (pItem->interrogation_start)
{
if (pItem->interrogation_type != IEC_101_104_COT_INTERROGATION)
{ //组召唤
//激活终止
ret = Send_FrameInterrogation(pItem, i);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_FrameInterrogation error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0)
{
pItem->interrogation_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
continue;
}
}
if (!pItem->interrogation_yx_fin)
{
ret = Send_Single_point_information(pItem, i, IEC_101_104_COT_INTERROGATION);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Single_point_information IEC_101_104_COT_INTERROGATION error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
if (!pItem->interrogation_yc_fin)
{
switch (m_nOption.yc_type)
{
case USE_YC_NB: //标度化值
ret = Send_Measured_value_scaled(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
case USE_YC_NC: //短浮点数
ret = Send_Measured_value_short_floating_point(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
case USE_YC_ND: //不带品质归一化值
ret = Send_Measured_value_normalised_without_quality(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
default: //USE_YC_NA: 归一化值
ret = Send_Measured_value_normalised(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
}
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Measured_value IEC_101_104_COT_INTERROGATION error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
//激活终止
ret = Send_FrameInterrogation(pItem, i);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_FrameInterrogation error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0)
{
pItem->interrogation_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
continue;
}
}
//响应召唤电能脉冲
if (pItem->pulse_start)
{
/*
if ((pItem->pulse_type & 0x3f) != 5)
{
continue;
}
*/
if (!pItem->pulse_fin)
{
ret = Send_Integrated_totals(pItem, i, IEC_101_104_COT_REQCOGEN);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Integrated_totals error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
//激活终止
ret = Send_FrameCounterInterrogation(pItem, i);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_FrameCounterInterrogation error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0)
{
pItem->pulse_type = 0;
pItem->pulse_start = FALSE;
pItem->pulse_fin = TRUE;
continue;
}
}
//总召唤没有结束,不上送变位遥测
if (pItem->interrogation_finish)
{ //发送遥测变位
if (sec_changed)
{
switch (m_nOption.yc_type)
{
case USE_YC_NB: //标度化值
ret = Send_Measured_value_scaled(pItem, i);
break;
case USE_YC_NC: //短浮点数
ret = Send_Measured_value_short_floating_point(pItem, i);
break;
case USE_YC_ND: //不带品质归一化值
ret = Send_Measured_value_normalised_without_quality(pItem, i);
break;
default: //USE_YC_NA: 归一化值
ret = Send_Measured_value_normalised(pItem, i);
break;
}
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Measured_value IEC_101_104_COT_SPONT error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
}
}
return TRUE;
}
BOOLEAN CSubIEC104Process::OnIFrameReceived(WORD ns, WORD nr, BYTE* pBuf, int count, int ord)
{
int uid;
CIEC104ProcessItem* pItem = (CIEC104ProcessItem *)GetItem(ord);
if (NULL == pItem) return FALSE;
uid = (int)pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
//处理接收序号
if (!OnDealWithPeerNS(pItem, ns)) return FALSE;
//处理发送序号
if (!OnDealWithPeerNR(pItem, nr)) return FALSE;
//启动t2计时
if (pItem->apdu_t2_begin == 0)
{
pItem->apdu_t2_begin = system32.timers;
}
pItem->apdu_w++;
if (pItem->apdu_w >= pItem->apdu_w_max)
{
if (!SendSFrame(ord)) return FALSE;
}
//重置t3计时
pItem->apdu_t3_begin = system32.timers;
//处理接收到的报文
int ret;
int len;
BYTE buffer[256];
BYTE* pData = pBuf;
BYTE TI;
// BYTE VSQ;
WORD COT;
BYTE cause_of_transmission;
TI = *pData; pData++;
//VSQ = *pData;
pData++;
COT = GetCOT(pData); pData += cot_length;
//判断CA地址是否正确
short apdu_addr = GetAsduAddr(pData); pData += asdu_addr_length;
if (apdu_addr != pItem->apdu_addr)
{
vLog(LOG_WARN, "Unit(%d) invalid CA(%d) received.\n", uid, apdu_addr);
return FALSE;
}
cause_of_transmission = GET_COT(COT);
len = 0;
memset(buffer, 0, sizeof(buffer));
switch (TI)
{
case C_IC_NA_1: //总召唤命令
ret = Receive_Interrogation_command(pItem, pData, cause_of_transmission, buffer, len);
if (NO_ERROR == ret)
{
pItem->interrogation_start = TRUE;
pItem->interrogation_yx_fin = FALSE;
pItem->interrogation_yc_fin = FALSE;
pItem->yx_pos = 0;
pItem->yc_pos = 0;
//清空原先YXBW库
ClearUnitYXBW(uid);
}
break;
case C_SC_NA_1: //单点遥控命令.没有总召唤,不响应遥控报文
if (!pItem->interrogation_finish) return TRUE;
ret = Receive_Single_command(pItem, pData, cause_of_transmission, buffer, len);
break;
case C_DC_NA_1: //双点遥控命令.没有总召唤,不响应遥控报文
if (!pItem->interrogation_finish) return TRUE;
ret = Receive_Double_command(pItem, pData, cause_of_transmission, buffer, len);
break;
case C_CI_NA_1: //脉冲量召唤命令
Receive_Counter_interrogation_command(pItem, pData,cause_of_transmission, buffer, len);
break;
case C_CS_NA_1: //时间同步命令
Receive_Clock_synchronisation_command(pItem, pData, cause_of_transmission, buffer, len);
break;
case C_SE_NA_1: //设定命令,归一化值.没有总召唤,不响应设定报文
if (!pItem->interrogation_finish) return TRUE;
Receive_Set_point_command_normalized(pItem, pData, cause_of_transmission, buffer, len); //设定规一化值命令
break;
case C_SE_NB_1: //设定命令,标度化值.没有总召唤,不响应设定报文
if (!pItem->interrogation_finish) return TRUE;
Receive_Set_point_command_scaled(pItem, pData, cause_of_transmission, buffer, len); //设定标度化值命令
break;
case C_SE_NC_1: //设定命令,短浮点数.没有总召唤,不响应设定报文
if (!pItem->interrogation_finish) return TRUE;
Receive_Set_point_command_short_floating(pItem, pData, cause_of_transmission, buffer, len); //设定短浮点值命令
break;
default:
vLog(LOG_WARN, "Unit(%d) Unsupported I frame type = 0x%02x\n", uid, (int)pBuf[0]);
len = count;
memcpy(buffer, pBuf, count);
buffer[1] = 1;
SetCOT(&buffer[2], (IEC_101_104_COT_UNKNOWN_TI | IEC_101_104_COT_PN));
}
if (len)
{
return SendIFrame(buffer, len, ord);
}
return TRUE;
}
BOOLEAN CSubIEC104Process::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)
{
if (send_start_dt)
{
vLog(LOG_WARN, "UNSUPPORT STARTDT ACT! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (!SendUFrame(FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ord)) return FALSE;
//链路链接建立
if (!IsClient())
{
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->interrogation_start = FALSE;
pItem->interrogation_yx_fin = FALSE;
pItem->interrogation_yc_fin = FALSE;
pItem->total_yx = GetUnitYXCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total yx count is %d.\n", uid, pItem->total_yx);
pItem->total_yc = GetUnitYCCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total yc count is %d.\n", uid, pItem->total_yc);
pItem->total_ym = GetUnitYMCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total ym count is %d.\n", uid, pItem->total_ym);
pItem->yx_pos = 0;
pItem->yc_pos = 0;
pItem->ym_pos = 0;
//初始化结束帧
if (use_send_end_of_initialisation)
{
if (!pItem->end_of_initialisation)
{
pItem->end_of_initialisation = TRUE;
if (!Send_End_of_initialisation(pItem, ord)) return FALSE;
}
}
else
{
pItem->end_of_initialisation = TRUE;
}
}
if (STARTDT_CON)
{
if (!send_start_dt)
{
vLog(LOG_WARN, "UNSUPPORT STARTDT CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
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->interrogation_start = FALSE;
pItem->interrogation_yx_fin = FALSE;
pItem->interrogation_yc_fin = FALSE;
pItem->total_yx = GetUnitYXCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total yx count is %d.\n", uid, pItem->total_yx);
pItem->total_yc = GetUnitYCCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total yc count is %d.\n", uid, pItem->total_yc);
pItem->total_ym = GetUnitYMCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total ym count is %d.\n", uid, pItem->total_ym);
pItem->yx_pos = 0;
pItem->yc_pos = 0;
pItem->ym_pos = 0;
//初始化结束帧
if (use_send_end_of_initialisation)
{
if (!pItem->end_of_initialisation)
{
pItem->end_of_initialisation = TRUE;
if (!Send_End_of_initialisation(pItem, ord)) return FALSE;
}
}
else
{
pItem->end_of_initialisation = TRUE;
}
}
if (STOPDT_ACT)
{
vLog(LOG_WARN, "UNSUPPORT STOPDT COMMAND! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (STOPDT_CON)
{
vLog(LOG_WARN, "UNSUPPORT STOPDT CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (TESTFR_ACT)
{
if (!SendUFrame(FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ord))
{
vLog(LOG_WARN, "Send U Frame Error.\n");
pItem->Release();
return FALSE;
}
pItem->apdu_t1_begin = 0;
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;
}
else
{
vLog(LOG_WARN, "UNSUPPORT TESTFR CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
}
return TRUE;
}