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