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