#include "iec104.h" iec_8u iec104_send_buf[IEC104_MAX_BUF_LEN]; iec_8u IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED; iec_8u IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CLOSED; iec_8u IEC104_STATE_FLAG_GROUP = IEC104_FLAG_CLOSED; iec_8u IEC104_STATE_FLAG_CLOCK = IEC104_FLAG_CLOSED; iec_8u IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE; iec_8u IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_CLOSED; iec_32s iec104_build_send_sn = 0; iec_32s iec104_build_recv_sn = 0; iec_32s iec104_deal_send_sn = -1; iec_32s iec104_deal_recv_sn = 0; iec_8u IEC104_Call_AllQoi = 0; iec_8u IEC104_Call_GroupQoi = 0; #define IEC104_CYCLE_TIME_MS 100 /*100ms*/ #define IEC104_RESEND_TIME_MS (30 * 1000) /*30s*/ #define IEC104_S_ACK_TIMEOUT (5 * 1000) /*5s*/ #define IEC104_TESTER_IDLE_TIMEOUT (1 * 30 * 1000) /*2min*/ iec_32u Iec104_TimeCount = 0; iec_32u Iec104_TimeCycle = IEC104_RESEND_TIME_MS; iec_32u Iec104_TimeCycle_S = 0; iec_32u Iec104_TimeCycle_TesterIdle = 0; iec_8u Iec104_TesterCount = 0; iec_32u Iec10x_Update_SeekAddr = 0; iec_16u FirmFlagCount = 0; iec_8u iec104_upload_addr(void) { iec_8u len = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = IEC104_ASDU_TYPE_M_DTU_INF_1; asdu->_num._sq = 0; asdu->_num._num = 1; asdu->_reason._reason = IEC10X_ASDU_COT_UNKNOW; asdu->_addr = iec104_state_addr; /*build info*/ ptr = info->_addr; temp32 = 0; memcpy(ptr, &temp32, 3); ptr = info->_element; temp32 = IEC104_INFO_SIGNATURE; memcpy(ptr, &temp32, 4); ptr += 4; temp32 = iec104_state_addr; memcpy(ptr, &temp32, 2); ptr += 2; /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; dump_hex(Iec104_Sendbuf, len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_init_fin(void) { iec_8u len = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = Iec10x_M_EI_NA_1; asdu->_num._sq = 0; asdu->_num._num = 1; asdu->_reason._reason = IEC10X_ASDU_REASON_INIT; asdu->_addr = iec104_state_addr; /*build info*/ ptr = info->_addr; temp32 = 0; memcpy(ptr, &temp32, 3); ptr = info->_element; // temp32 = 0; // memcpy(ptr, &temp32, 4); info->_element[0] = 0; ptr++; /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; dump_hex(Iec104_Sendbuf, len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_call_ack(iec_8u qoi, iec_8u Prio) { iec_8u len = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = IEC10X_C_IC_NA_1; asdu->_num._sq = 0; asdu->_num._num = 1; asdu->_reason._reason = IEC10X_ASDU_REASON_ACTCON; asdu->_addr = iec104_state_addr; /*build info*/ ptr = info->_addr; temp32 = 0; memcpy(ptr, &temp32, 3); ptr = info->_element; ptr[0] = qoi; ptr += 1; /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; dump_hex(Iec104_Sendbuf, len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_signal_spon(iec_8u time_flag, iec_8u v_signal, iec_16u v_addr) { iec_8u len = 0, asdu_num = 0, i; iec_8u *ptr = NULL; iec_32u temp32 = 0; PCP56Time2a_T time = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /* check Time flag */ if (time_flag != 1 && time_flag != 0) { LOG("-%s-, error time flag(%d) \n", __FUNCTION__, time_flag); return RET_ERROR; } LOG("-%s-, time flag(%d) signalV(%d) \n", __FUNCTION__, time_flag, v_signal); /*get value*/ asdu_num = 1; /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ if (time_flag == 0) asdu->_type = IEC10X_M_SP_NA_1; else asdu->_type = IEC10X_M_SP_TB_1; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = IEC10X_COT_SPONT; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; temp32 = v_addr; memcpy(ptr, &temp32, 3); /*build info value*/ ptr = info->_element; for (i = 0; i < asdu_num; i++) { *ptr = v_signal; ptr++; } if (time_flag == 1) { time = (PCP56Time2a_T)ptr; iec104->get_time(time); ptr += sizeof(CP56Time2a_T); } /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_SPON, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_detect_spont(iec_8u TimeFlag, PIEC10X_DETECT_T detectV, iec_16u addrV) { iec_8u len = 0, asdu_num = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; PIEC10X_DETECT_T detect = NULL; PCP56Time2a_T time = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /* check Time flag */ if (TimeFlag != 1 && TimeFlag != 0) { LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag); return RET_ERROR; } /*get value*/ asdu_num = 1; /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ if (TimeFlag == 0) asdu->_type = IEC10X_M_ME_NA_1; else asdu->_type = IEC10X_M_ME_TD_1; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = IEC10X_COT_SPONT; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; temp32 = addrV; memcpy(ptr, &temp32, 3); /*build info value*/ ptr = info->_element; detect = (PIEC10X_DETECT_T)ptr; detect->_detect = detectV->_detect; detect->_qds = detectV->_qds; ptr += sizeof(IEC10X_DETECT_T); if (TimeFlag == 1) { time = (PCP56Time2a_T)ptr; iec104->get_time(time); ptr += sizeof(CP56Time2a_T); } /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_SPON, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_detect_f_spont(iec_8u TimeFlag, float detectV, iec_16u addrV) { iec_8u len = 0, asdu_num = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; PIEC10X_DETECT_F_T detect = NULL; PCP56Time2a_T time = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /* check Time flag */ if (TimeFlag != 1 && TimeFlag != 0) { LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag); return RET_ERROR; } /*get value*/ asdu_num = 1; /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ if (TimeFlag == 0) asdu->_type = IEC10X_M_ME_NC_1; else asdu->_type = IEC10X_M_ME_TF_1; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = IEC10X_COT_SPONT; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; temp32 = addrV; memcpy(ptr, &temp32, 3); /*build info value*/ ptr = info->_element; detect = (PIEC10X_DETECT_F_T)ptr; detect->_detect = detectV; detect->_qds = 0; ptr += sizeof(IEC10X_DETECT_F_T); if (TimeFlag == 1) { time = (PCP56Time2a_T)ptr; iec104->get_time(time); ptr += sizeof(CP56Time2a_T); } /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_SPON, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_signal(iec_8u reason, iec_8u Prio, iec_8u dev_type) { iec_8u len = 0, asdu_num = 0; iec_16u i = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*get value*/ iec104->get_info_num(&asdu_num, dev_type); LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = IEC10X_M_SP_NA_1; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = reason; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; if (dev_type == ENDDEVICE_TYPE_HXTM) { temp32 = IEC104_INFOADDR_STATE_HXTM; } else if (dev_type == ENDDEVICE_TYPE_HXGF) { temp32 = IEC104_INFOADDR_STATE_HXGF; } else { LOG("-%s-, error dev type:%d \n", __FUNCTION__, dev_type); return RET_ERROR; } memcpy(ptr, &temp32, 3); /*build info value*/ ptr = info->_element; for (i = 0; i < asdu_num; i++) { *ptr = iec104->get_station_state(i, dev_type); ptr++; } /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_detect(iec_8u reason, iec_8u ValueType, iec_8u Prio, iec_8u dev_type) { iec_8u len = 0, asdu_num = 0, i; iec_8u *ptr = NULL; iec_32u temp32 = 0; PIEC10X_DETECT_T detect = NULL; PIEC10X_DETECT_F_T detect_f = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*get value*/ iec104->get_info_num(&asdu_num, dev_type); LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = ValueType; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = reason; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; if (dev_type == ENDDEVICE_TYPE_HXTM) { temp32 = IEC104_INFOADDR_VALUE_HXTM; } else if (dev_type == ENDDEVICE_TYPE_HXGF) { temp32 = IEC104_INFOADDR_VALUE_HXGF; } else { LOG("-%s-, error dev type:%d \n", __FUNCTION__, dev_type); return RET_ERROR; } memcpy(ptr, &temp32, 3); /*Build Detect value*/ ptr = info->_element; for (i = 0; i < asdu_num; i++) { /*short int*/ if (ValueType == IEC10X_M_ME_NA_1) { detect = (PIEC10X_DETECT_T)ptr; detect->_detect = iec104->get_sta_value(i, dev_type); detect->_qds = 0; ptr += sizeof(IEC10X_DETECT_T); } /*float*/ else if (ValueType == IEC10X_M_ME_NC_1) { detect_f = (PIEC10X_DETECT_F_T)ptr; detect_f->_detect = iec104->get_sta_value(i, dev_type); detect_f->_qds = 0; ptr += sizeof(IEC10X_DETECT_F_T); } } /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_upload(iec_8u ValueType, iec_8u Prio, iec_8u dev_type) { iec_8u len = 0, asdu_num = 0, i; iec_8u *ptr = NULL; iec_32u temp32 = 0; PIEC10X_DETECT_T detect = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*get value*/ iec104->get_info_num(&asdu_num, dev_type); LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = ValueType; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = AP_COT_BASE_INFO; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; temp32 = IEC104_INFOADDR_BASE_DEVINFO; memcpy(ptr, &temp32, 3); ptr += 3; /*Build Detect value*/ ptr = info->_element; for (i = 0; i < asdu_num; i++) { detect = (PIEC10X_DETECT_T)ptr; detect->_detect = iec104->get_sta_value(i, dev_type); detect->_qds = 0; ptr += sizeof(IEC10X_DETECT_T); } /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_act_finish(iec_8u qoi, iec_8u Prio) { iec_8u len = 0, asdu_num = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.i.type = 0; Iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; Iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = IEC10X_C_IC_NA_1; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = IEC10X_ASDU_REASON_ACTTERM; asdu->_addr = iec104_state_addr; /*build info addr*/ ptr = info->_addr; temp32 = IEC10X_INFO_ADDR_SIG_BASE + IEC10X_INFO_ADDR_SIG_TEMP_HX_OFF; memcpy(ptr, &temp32, 3); /*Build Detect value*/ ptr = info->_element; ptr[0] = qoi; ptr += 1; /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_u(iec_8u UType, iec_8u Ack) { iec_8u len = 0, Tester, Start, Stop; iec_8u *ptr = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ if (Ack) { Tester = IEC104_U_FUNC_TESTER_ACK; Start = IEC104_U_FUNC_STARTDT_ACK; Stop = IEC104_U_FUNC_STOPDT_ACK; } else { Tester = IEC104_U_FUNC_TESTER; Start = IEC104_U_FUNC_STARTDT; Stop = IEC104_U_FUNC_STOPDT; } switch (UType) { case IEC104_U_FUNC_STARTDT: Iec104_data->ctrl.func.func = Start; break; case IEC104_U_FUNC_STOPDT: Iec104_data->ctrl.func.func = Stop; break; case IEC104_U_FUNC_TESTER: Iec104_data->ctrl.func.func = Tester; break; default: LOG(">%s<, U Type Error(%d) !\n", __FUNCTION__, UType); return RET_ERROR; } /*build ASDU , COT ,Addr*/ ptr = Iec104_data->asdu; /*build info*/ /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } iec_8u iec104_build_s_ack(void) { iec_8u len = 0; iec_8u *ptr = NULL; p_iec104_data_t Iec104_data = (p_iec104_data_t)iec104_send_buf; /*build head*/ Iec104_data->head = IEC104_HEAD; /*build control code*/ Iec104_data->ctrl.s.type_1 = 1; Iec104_data->ctrl.s.type_2 = 0; Iec104_data->ctrl.s.reserve = 0; Iec104_data->ctrl.s.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ ptr = Iec104_data->asdu; /*build info*/ /*len*/ len = ptr - iec104_send_buf; Iec104_data->len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } iec_8u iec104_asdu_call(p_iec10x_asdu_t Iec10x_Asdu) { p_asdu_info_t asdu_info = (p_asdu_info_t)(Iec10x_Asdu->_info); iec_8u qoi = asdu_info->_element[0]; iec_8u Prio = 0; iec_32u InfoAddr = 0; /* check info addrest */ memcpy(&InfoAddr, asdu_info->_addr, 3); if (InfoAddr != 0) { LOG("-%s- call cmd active error addr(%x) \n", __FUNCTION__, InfoAddr); return RET_ERROR; } switch (Iec10x_Asdu->_reason._reason) { case IEC10X_ASDU_REASON_ACT: switch (qoi) { case IEC10X_CALL_QOI_TOTAL: Prio = IEC10X_PRIO_CALLALL; IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CALL_ALLDATA; IEC104_Call_AllQoi = qoi; break; case IEC10X_CALL_QOI_GROUP1: case IEC10X_CALL_QOI_GROUP2: case IEC10X_CALL_QOI_GROUP9: case IEC10X_CALL_QOI_GROUP10: Prio = IEC10X_PRIO_CALLGROUP; IEC104_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROURPDATA; IEC104_Call_GroupQoi = qoi; break; default: LOG("-%s- call cmd error qoi(%d) \n", __FUNCTION__, qoi); return RET_ERROR; } iec104_build_call_ack(qoi, Prio); /**/ iec104_build_signal(qoi, Prio, ENDDEVICE_TYPE_HXTM); iec104_build_detect(qoi, IEC10X_M_ME_NA_1, Prio, ENDDEVICE_TYPE_HXTM); /**/ iec104_build_signal(qoi, Prio, ENDDEVICE_TYPE_HXGF); iec104_build_detect(qoi, IEC10X_M_ME_NA_1, Prio, ENDDEVICE_TYPE_HXGF); iec104_build_act_finish(qoi, Prio); break; default: LOG("-%s- call cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason); break; } return RET_SUCESS; } iec_8u iec104_asdu_clock(p_iec10x_asdu_t Iec10x_Asdu) { p_asdu_info_t asdu_info = (p_asdu_info_t)(Iec10x_Asdu->_info); memcpy(&IEC10X_Cp56time2a, asdu_info->_element, sizeof(CP56Time2a_T)); if (asdu_info->_addr[0] != 0 || asdu_info->_addr[1] != 0 || asdu_info->_addr[2] != 0) { LOG("-%s- Clock cmd error addr(0x%02x:%02x:%02x) \n", __FUNCTION__, asdu_info->_addr[0], asdu_info->_addr[2], asdu_info->_addr[2]); return RET_ERROR; } switch (Iec10x_Asdu->_reason._reason) { case IEC10X_COT_ACT: LOG("-%s- Clock cmd (20%d-%d-%d %d %d:%d:%d) \n", __FUNCTION__, IEC10X_Cp56time2a._year._year, IEC10X_Cp56time2a._month._month, IEC10X_Cp56time2a._day._dayofmonth, IEC10X_Cp56time2a._day._dayofweek, IEC10X_Cp56time2a._hour._hours, IEC10X_Cp56time2a._min._minutes, IEC10X_Cp56time2a._milliseconds); /*get time*/ /*...*/ iec104->set_time(&IEC10X_Cp56time2a); // IEC104_Build_S_Ack(); break; case IEC10X_COT_SPONT: LOG("-%s- Clock cmd spont \n", __FUNCTION__); break; default: LOG("-%s- Clock cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason); break; } return RET_SUCESS; } iec_8u iec104_asdu_set_act(p_iec10x_asdu_t Iec10x_Asdu, iec_8u Type) { p_asdu_info_t asdu_info = (p_asdu_info_t)(Iec10x_Asdu->_info); iec_8u *ptr = NULL; iec_8u n = Iec10x_Asdu->_num._num, Sq = Iec10x_Asdu->_num._sq, i; float Value = 0.0; iec_32u InfoAddr = 0; /* if sq == 1 */ PIEC10X_DETECT_T detect = NULL; PIEC10X_DETECT_F_T detect_f = NULL; /* if sq == 0 */ PIEC10X_DETECT_SQ0_T detect_Sq0 = NULL; PIEC10X_DETECT_SQ0_F_T detect_Sq0_f = NULL; /* check info addrest */ memcpy(&InfoAddr, asdu_info->_addr, 3); switch (Iec10x_Asdu->_reason._reason) { case IEC10X_COT_ACT: switch (Type) { case IEC10X_C_SE_NA_1: if (Sq == 1) { ptr = asdu_info->_element; for (i = 0; i < n; i++) { detect = (PIEC10X_DETECT_T)ptr; Value = (float)(detect->_detect); ptr += sizeof(IEC10X_DETECT_T); iec104->set_config(Value, InfoAddr + i); } } else if (Sq == 0) { ptr = Iec10x_Asdu->_info; for (i = 0; i < n; i++) { detect_Sq0 = (PIEC10X_DETECT_SQ0_T)ptr; Value = (float)(detect_Sq0->_detect); InfoAddr = 0; memcpy(&InfoAddr, detect_Sq0->_addr, 3); iec104->set_config(Value, InfoAddr); ptr += sizeof(IEC10X_DETECT_SQ0_T); } } break; case IEC10X_C_SE_NC_1: if (Sq == 1) { ptr = asdu_info->_element; for (i = 0; i < n; i++) { detect_f = (PIEC10X_DETECT_F_T)ptr; Value = detect_f->_detect; ptr += sizeof(IEC10X_DETECT_F_T); iec104->set_config(Value, InfoAddr + i); } } else if (Sq == 0) { ptr = Iec10x_Asdu->_info; for (i = 0; i < n; i++) { detect_Sq0_f = (PIEC10X_DETECT_SQ0_F_T)ptr; Value = (float)(detect_Sq0_f->_detect); memcpy(&InfoAddr, detect_Sq0_f->_addr, 3); iec104->set_config(Value, InfoAddr); ptr += sizeof(IEC10X_DETECT_SQ0_F_T); } } break; default: LOG("-%s-, Type error !", __FUNCTION__); return RET_ERROR; } break; default: LOG("-%s- , error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason); return RET_ERROR; } return RET_SUCESS; } iec_8u iec104_build_set_ack(iec_8u Prio, iec_8u Type) { iec_8u len = 0; iec_8u *ptr = NULL; p_iec104_data_t iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*build head*/ iec104_data->head = IEC104_HEAD; /*build control code*/ iec104_data->ctrl.i.type = 0; iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = Type; asdu->_num._sq = 0; asdu->_num._num = 0; asdu->_reason._reason = IEC10X_ASDU_REASON_ACTFIN; asdu->_addr = iec104_state_addr; /*build info*/ ptr = info->_addr; /*len*/ len = ptr - iec104_send_buf; iec104_data->len = len - 2; // DumpHEX(Iec104_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8u iec104_deal_sn(iec_16u SendSn, iec_16u RecvSn) { LOG("Receive Pakage I(%d,%d), Send(%d,%d)\n", SendSn, RecvSn, iec104_build_send_sn, iec104_build_recv_sn); #if 0 if(SendSn > Iec104_DealSendSn+1){ LOG("-%s-, error,send last(%d),now(%d) \n",__FUNCTION__,Iec104_DealSendSn,SendSn); IEC104_STATE_FLAG_INIT = IEC104_FLAG_SEND_CLOSED; return RET_ERROR; }else if(SendSn < Iec104_DealSendSn+1){ LOG("-%s-, Retransmit,send last(%d),now(%d) \n",__FUNCTION__,Iec104_DealSendSn,SendSn); return RET_ERROR; } if(RecvSn != Iec104_BuildSendSn){ LOG("-%s-, error,receive last(%d),now(%d) \n",__FUNCTION__,Iec104_BuildSendSn,RecvSn); IEC104_STATE_FLAG_INIT = IEC104_FLAG_SEND_CLOSED; return RET_ERROR; } if(RecvSn < Iec104_DealRecvSn){ LOG("-%s-, error,receive2 last(%d),now(%d) \n",__FUNCTION__,Iec104_DealRecvSn,RecvSn); return RET_ERROR; } #endif if (SendSn < iec104_deal_send_sn || RecvSn < iec104_deal_recv_sn) { LOG("-%s-, error,send last(%d),now(%d). recv last(%d),now(%d) \n", __FUNCTION__, iec104_deal_send_sn, SendSn, iec104_deal_recv_sn, RecvSn); return RET_ERROR; } iec104_build_recv_sn = SendSn + 1; iec104_deal_send_sn = SendSn; iec104_deal_recv_sn = RecvSn; // Iec104_BuildRecvSn++; /* return S ACK */ IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_S_ACK; Iec104_TimeCycle_S = 0; return RET_SUCESS; } iec_8s iec104_build_data_ack(iec_8u TI, iec_16u COT, iec_32u InfoAddr, iec_16u Info, iec_8u Prio) { iec_8u len = 0; iec_8u *ptr = NULL; iec_32u temp32 = 0; /* build head */ p_iec104_data_t iec104_data = (p_iec104_data_t)iec104_send_buf; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(iec104_data->asdu); p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); /*build head*/ iec104_data->head = IEC104_HEAD; /*build control code*/ iec104_data->ctrl.i.type = 0; iec104_data->ctrl.i.send_sn = iec104_build_send_sn++; iec104_data->ctrl.i.recv_sn = iec104_build_recv_sn; /*build ASDU , COT ,Addr*/ asdu->_type = TI; asdu->_num._sq = 0; asdu->_num._num = 1; asdu->_reason._reason = COT; asdu->_addr = iec104_state_addr; /*build info*/ ptr = info->_addr; temp32 = InfoAddr; memcpy(ptr, &temp32, 3); ptr = info->_element; if (COT == IEC10X_COT_ACT_TERMINAL || COT == IEC10X_COT_ACTCON || COT == IEC10X_COT_ACT_TERMINAL_ACK || COT == IEC10X_TI_AP_FIRM_BACKOFF) { ptr[0] = 0; ptr[1] = 0; ptr += 2; } else if (COT == IEC10X_COT_DATA_ACK || COT == IEC10X_COT_DATA_FIN_ACK) { memcpy(ptr, &Info, 2); ptr += 2; } /*len*/ len = ptr - iec104_send_buf; iec104_data->len = len - 2; // DumpHEX(Iec104_Sendbuf,len); /* enqueue to the transmisson queue */ iec104_enqueue(iec104_send_buf, len, Prio, NULL, NULL); return RET_SUCESS; } iec_8s iec104_deal_firmware_update(p_iec10x_asdu_t asdu, iec_8u Len) { iec_16u cot = asdu->_reason._reason; iec_16u FlagNum = 0, i; iec_8u DataLen = Len - IEC104_DATA_LEN - 3; /* flag num 2, check sum 1 byte*/ p_asdu_info_t element = (p_asdu_info_t)(asdu->_info); iec_8u *DataPtr = (iec_8u *)(element->_element) + 3; iec_8u TI = asdu->_type, csum = 0, CsumTemp = 0; iec_32u FirmwareType = 0; iec_8s ret = 0; p_asdu_info_t info = (p_asdu_info_t)(asdu->_info); FlagNum = *(iec_16u *)(info->_element); memcpy(&FirmwareType, asdu->_info, 3); if (Len == 0) { LOG("-%s-,data:%d,Len:%d error!\n", __FUNCTION__, FlagNum, DataLen); return RET_ERROR; } /* reset the flag counter */ if (FlagNum == 1) { FirmFlagCount = 0; Iec10x_Update_SeekAddr = 0; } switch (cot) { case IEC10X_COT_DATA: if (FlagNum == FirmFlagCount + 1) { /* check sum */ csum = info->_element[2]; for (i = 0; i < DataLen; i++) { CsumTemp += DataPtr[i]; } if (CsumTemp == csum) { LOG("-%s-,data:%d,Len:%d,seek:%d \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr); for (i = 0; i < 3; i++) { ret = iec104->save_firmware(DataLen, DataPtr, FirmwareType, Iec10x_Update_SeekAddr); if (ret == RET_SUCESS) break; } if (ret == RET_ERROR) { LOG("save firmware error \n"); break; } FirmFlagCount = FlagNum; Iec10x_Update_SeekAddr += DataLen; } else { LOG("%s, check sum error:%d,need:%d,num:%d\n", __FUNCTION__, CsumTemp, csum, FlagNum); } } else if (FlagNum < FirmFlagCount + 1) { LOG("update flag resend,need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum); } else { LOG("update flag error! need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum); // Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1); } break; case IEC10X_COT_DATA_NEEDACK: if (FlagNum == FirmFlagCount + 1) { /* check sum */ csum = info->_element[2]; for (i = 0; i < DataLen; i++) { CsumTemp += DataPtr[i]; } if (CsumTemp == csum) { LOG("-%s-,data need ack:%d,Len:%d,seek:%d \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr); for (i = 0; i < 3; i++) { ret = iec104->save_firmware(DataLen, DataPtr, FirmwareType, Iec10x_Update_SeekAddr); if (ret == RET_SUCESS) break; } if (ret == RET_ERROR) { LOG("save firmware error \n"); break; } iec104_build_data_ack(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum, 1); FirmFlagCount = FlagNum; Iec10x_Update_SeekAddr += DataLen; } else { LOG("%s,need ack check sum error:%d,need:%d,num...:%d\n", __FUNCTION__, CsumTemp, csum, FlagNum); // Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1); } } else if (FlagNum < FirmFlagCount + 1) { LOG("update flag resend,need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum); iec104_build_data_ack(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum, 1); } else { LOG("update flag error! need:%d,flag:%d\n", FirmFlagCount + 1, FlagNum); // Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1); } break; case IEC10X_COT_DATA_FIN: if (FirmFlagCount == FlagNum) { LOG("-%s-,data finish:%d,Len:%d,Total Len:%d \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr); ret = iec104->check_firmware(FirmwareType, Iec10x_Update_SeekAddr); if (ret == RET_SUCESS) { iec104_build_data_ack(TI, IEC10X_COT_DATA_FIN_ACK, FirmwareType, FlagNum, 1); iec104->update_firmware(FirmwareType); } else { /* check firmware error ,terminal update */ iec104_build_data_ack(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, 0, 1); } } else { LOG("-%s-,data finish error:%d,Len:%d,Total Len:%d,FirmFlagCount:%d,FlagNum:%d, \n", __FUNCTION__, FlagNum, DataLen, Iec10x_Update_SeekAddr, FirmFlagCount, FlagNum); return RET_ERROR; } break; case IEC10X_COT_ACT_TERMINAL: LOG("-%s-, Terminal:%d,Len:%d \n", __FUNCTION__, FlagNum, DataLen); iec104_build_data_ack(TI, IEC10X_COT_ACT_TERMINAL_ACK, FirmwareType, 0, 1); break; case IEC10X_COT_ACT_TERMINAL_ACK: LOG("-%s-, Terminal Ack \n", __FUNCTION__); break; default: LOG("-%s-,data:%d,Len:%d error cot: \n", __FUNCTION__, FlagNum, Len); return RET_ERROR; } return RET_SUCESS; } void iec104_tester_timer(void) { IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE; Iec104_TimeCycle_TesterIdle = 0; } iec_8u iec104_deal_i(p_iec104_data_t Iec104_data, iec_16u len) { iec_8u Type; iec_16u RecvSn, SendSn; iec_32u FirmwareType = 0; p_iec10x_asdu_t asdu = (p_iec10x_asdu_t)(Iec104_data->asdu); SendSn = Iec104_data->ctrl.i.send_sn; RecvSn = Iec104_data->ctrl.i.recv_sn; /* check asdu addrest */ if (iec104_state_addr != asdu->_addr) { LOG("-%s-, error asdu addr(%x)(%x) \n", __FUNCTION__, iec10x_state_addr, asdu->_addr); return RET_ERROR; } /* deal the receive and send serial number */ if (iec104_deal_sn(SendSn, RecvSn) == RET_ERROR) { return RET_ERROR; } /* Start tester timer */ iec104_tester_timer(); Type = asdu->_type; switch (Type) { case IEC10X_C_IC_NA_1: LOG("++++Asdu Type Call cmd... \n"); iec104_asdu_call(asdu); IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_IDLE; break; case IEC10X_C_CS_NA_1: LOG("++++Asdu Type Clock syc cmd... \n"); iec104_asdu_clock(asdu); break; case IEC10X_C_SE_NA_1: case IEC10X_C_SE_NC_1: LOG("++++Asdu Type Set type(%d)... \n", Type); iec104_asdu_set_act(asdu, Type); iec104_build_set_ack(1, Type); break; case IEC10X_TI_FIRM_UPDATE: LOG("++++Asdu Type Firmware Update... \n"); iec104_deal_firmware_update(asdu, len); break; case IEC10X_TI_AP_FIRM_BACKOFF: LOG("++++Asdu Type Firmware Backoff... \n"); memcpy(&FirmwareType, asdu->_info, 3); iec104_build_data_ack(IEC10X_TI_AP_FIRM_BACKOFF, IEC10X_COT_ACTCON, FirmwareType, 0, 1); iec104->backoff_firmware(FirmwareType); break; default: LOG("-%s-, error Type(%d) \n", __FUNCTION__, Type); return RET_ERROR; } return RET_SUCESS; } iec_8u iec104_deal_s(p_iec104_data_t Iec104_data, iec_16u len) { return RET_SUCESS; } iec_8u iec104_deal_u(p_iec104_data_t iec104_data, iec_16u len) { switch (iec104_data->ctrl.func.func) { case IEC104_U_FUNC_STARTDT: LOG(">%s<, function STARTDT \n", __FUNCTION__); IEC104_STATE_FLAG_INIT = IEC104_FLAG_LINK_INIT; Iec104_TimeCycle = 0; Iec104_TimeCount = 0; // IEC104_Build_U(IEC104_U_FUNC_STARTDT,1); // IEC104_Build_InitFin(); break; case IEC104_U_FUNC_STOPDT: LOG(">%s<, function STOPDT \n", __FUNCTION__); iec104->close_link(); iec104_build_u(IEC104_U_FUNC_STOPDT, 1); IEC104_STATE_FLAG_INIT = IEC104_FLAG_RECV_CLOSED; break; case IEC104_U_FUNC_TESTER: LOG(">%s<, function TESTER \n", __FUNCTION__); iec104_build_u(IEC104_U_FUNC_TESTER, 1); break; /* U ACK */ case IEC104_U_FUNC_STARTDT_ACK: LOG(">%s<, function STARTDT ACK\n", __FUNCTION__); break; case IEC104_U_FUNC_STOPDT_ACK: LOG(">%s<, function STOPDT ACK\n", __FUNCTION__); IEC104_STATE_FLAG_INIT = IEC104_FLAG_RECV_CLOSED; break; case IEC104_U_FUNC_TESTER_ACK: LOG(">%s<, function TESTER ACK\n", __FUNCTION__); Iec104_TesterCount = 0; break; default: LOG(">%s<, function ERROR \n", __FUNCTION__); break; } return RET_SUCESS; } void iec104_receive(iec_8u *buf, iec_16u len) { iec_8u *BufTemp = NULL; iec_16s LenRemain, LenTmp; p_iec104_data_t Iec104_data = NULL; if (buf == NULL) { LOG("-%s-,buffer (null)", __FUNCTION__); return; } #if 0 if(len <= 0 || len>IEC104_MAX_BUF_LEN || lenhead == IEC104_HEAD) { LenTmp = Iec104_data->len + 2; if (LenRemain < IEC104_HEAD_LEN) { LOG("_%s_,len error(%d) \n", __FUNCTION__, len); iec104_unlock(); return; } if (Iec104_data->ctrl.type.type_1 == 0) { LOG("-%s-,frame type i \n", __FUNCTION__); iec104_deal_i(Iec104_data, LenTmp); } else if (Iec104_data->ctrl.type.type_1 == 1 && Iec104_data->ctrl.type.type_2 == 0) { LOG("-%s-,frame type s \n", __FUNCTION__); iec104_deal_s(Iec104_data, LenTmp); } else if (Iec104_data->ctrl.type.type_1 == 1 && Iec104_data->ctrl.type.type_2 == 1) { LOG("-%s-,frame type u \n", __FUNCTION__); iec104_deal_u(Iec104_data, LenTmp); } } else { LOG("-%s-,head type error(%d) \n", __FUNCTION__, BufTemp[0]); iec104_unlock(); return; } iec104_unlock(); BufTemp += LenTmp; LenRemain -= LenTmp; } return; } void iec104_reset_flag(void) { IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_IDLE; IEC104_STATE_FLAG_GROUP = IEC104_FLAG_IDLE; IEC104_STATE_FLAG_CLOCK = IEC104_FLAG_IDLE; IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE; iec104_build_send_sn = 0; iec104_build_recv_sn = 0; iec104_deal_send_sn = -1; iec104_deal_recv_sn = 0; Iec104_TesterCount = 0; } iec_32u TestCount_Temp = 0; iec_8u iec104_state_machine(void) { /*Init link*/ switch (IEC104_STATE_FLAG_INIT) { case IEC104_FLAG_CLOSED: IEC104_STATE_FLAG_INIT = IEC104_FLAG_START_LINK; iec104_queue_clear(); iec104_reset_flag(); break; case IEC104_FLAG_SEND_CLOSED: Iec104_TimeCycle += IEC104_CYCLE_TIME_MS; if (Iec104_TimeCycle > IEC104_RESEND_TIME_MS) { Iec104_TimeCycle = 0; Iec104_TimeCount++; iec104_build_u(IEC104_U_FUNC_STOPDT, 0); } if (Iec104_TimeCount >= 3) { Iec104_TimeCount = 0; IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE; iec104->close_link(); } break; case IEC104_FLAG_RECV_CLOSED: iec104_reset_flag(); iec104_queue_clear(); IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS; break; case IEC104_FLAG_LINK_INIT: LOG("Iec104 machine state :IEC104_FLAG_LINK_INIT \n"); iec104_reset_flag(); iec104_state_addr = iec104->get_link_addr(); iec104_build_u(IEC104_U_FUNC_STARTDT, 1); iec104_build_init_fin(); iec104_build_upload(IEC10X_TI_AP_BASE_INFO, IEC10X_PRIO_INITLINK, AP_TYPE_BASE_INFO); IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS; break; case IEC104_FLAG_UPLOAD_ADDR: Iec104_TimeCycle += IEC104_CYCLE_TIME_MS; if (Iec104_TimeCycle > IEC104_RESEND_TIME_MS) { iec104_state_addr = iec104->get_link_addr(); Iec104_TimeCycle = 0; Iec104_TimeCount++; iec104_upload_addr(); } if (Iec104_TimeCount >= 3) { Iec104_TimeCount = 0; IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE; iec104->close_link(); } break; case IEC104_FLAG_CONNECT_SUCESS: case IEC104_FLAG_IDLE: default: break; } if (IEC104_STATE_FLAG_INIT == IEC104_FLAG_CONNECT_SUCESS) { /* Return s ack */ switch (IEC104_STATE_FLAG_S_ACK) { case IEC104_FLAG_S_ACK: Iec104_TimeCycle_S += IEC104_CYCLE_TIME_MS; if (Iec104_TimeCycle_S > IEC104_S_ACK_TIMEOUT) { Iec104_TimeCycle_S = 0; iec104_build_s_ack(); IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_IDLE; } break; case IEC104_FLAG_IDLE: break; default: break; } /* test spon */ #if 1 if (TestCount_Temp++ > (10 * 60 * 20)) { TestCount_Temp = 0; iec104_build_signal_spon(1, 1, IEC104_INFOADDR_STATE_HXGF + 2); iec104_build_detect_f_spont(1, 60.2, IEC104_INFOADDR_VALUE_HXTM + 2); iec104_build_detect_f_spont(1, 61.1, IEC104_INFOADDR_VALUE_HXGF + 2); } #endif } /* Tester */ switch (IEC104_STATE_FLAG_TESTER) { case IEC104_FLAG_TESTER: iec104_build_u(IEC104_U_FUNC_TESTER, 0); IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE; Iec104_TesterCount++; LOG("Tester Count(%d)... \n", Iec104_TesterCount); if (Iec104_TesterCount > 3) { Iec104_TesterCount = 0; LOG("Tester error(%d)... \n", Iec104_TesterCount); IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED; iec104->close_link(); } break; case IEC104_FLAG_TESTER_STOP: break; case IEC104_FLAG_IDLE: Iec104_TimeCycle_TesterIdle += IEC104_CYCLE_TIME_MS; if (Iec104_TimeCycle_TesterIdle > IEC104_TESTER_IDLE_TIMEOUT) { Iec104_TimeCycle_TesterIdle = 0; IEC104_STATE_FLAG_TESTER = IEC104_FLAG_TESTER; } break; default: break; } return RET_SUCESS; }