/******************************************************************* Copyright (C): File name : Iec104.c DESCRIPTION : AUTHOR : Version : 1.0 Date : 2014/07/31 Others : History : ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1) Date: 2014/07/31 Author: ChenDajie content: *******************************************************************/ #include "iec104.h" #include "project_var.h" /* * GLOABLE VARIALBLE */ uint8_t Iec104_Sendbuf[IEC104_MAX_BUF_LEN]; /* * STATE * */ uint8_t IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED; uint8_t IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CLOSED; uint8_t IEC104_STATE_FLAG_GROUP = IEC104_FLAG_CLOSED; uint8_t IEC104_STATE_FLAG_CLOCK = IEC104_FLAG_CLOSED; uint8_t IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE; uint8_t IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_CLOSED; /* * receive and send serial number * */ int32_t Iec104_BuildSendSn = 0; int32_t Iec104_BuildRecvSn = 0; int32_t Iec104_DealSendSn = -1; int32_t Iec104_DealRecvSn = 0; uint8_t IEC104_Call_AllQoi = 0; uint8_t 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*/ uint32_t Iec104_TimeCount = 0; uint32_t Iec104_TimeCycle = IEC104_RESEND_TIME_MS; uint32_t Iec104_TimeCycle_S = 0; uint32_t Iec104_TimeCycle_TesterIdle = 0; uint8_t Iec104_TesterCount = 0; uint32_t Iec10x_Update_SeekAddr = 0; uint16_t FirmFlagCount = 0; uint8_t IEC104_UploadAddr(void) { uint8_t len = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_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 = Iec10x_Sta_Addr; memcpy(ptr, &Temp32, 2); ptr += 2; /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_Build_InitFin(void) { uint8_t len = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_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_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildCallACK(uint8_t qoi, uint8_t Prio) { uint8_t len = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_Addr; /*build info*/ ptr = info->_addr; Temp32 = 0; memcpy(ptr, &Temp32, 3); ptr = info->_element; ptr[0] = qoi; ptr += 1; /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; DumpHEX(Iec104_Sendbuf, len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildSignal_Spon(uint8_t TimeFlag, uint8_t signalV, uint16_t addrV) { uint8_t len = 0, asdu_num = 0, i; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PCP56Time2a_T time = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /* check Time flag */ if (TimeFlag != 1 && TimeFlag != 0) { LOG("-%s-, error time flag(%d) \n", __FUNCTION__, TimeFlag); return RET_ERROR; } LOG("-%s-, time flag(%d) signalV(%d) \n", __FUNCTION__, TimeFlag, signalV); /*get value*/ asdu_num = 1; /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*build ASDU , COT ,Addr*/ if (TimeFlag == 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 = Iec10x_Sta_Addr; /*build info addr*/ ptr = info->_addr; Temp32 = addrV; memcpy(ptr, &Temp32, 3); /*build info value*/ ptr = info->_element; for (i = 0; i < asdu_num; i++) { *ptr = signalV; ptr++; } if (TimeFlag == 1) { time = (PCP56Time2a_T)ptr; IEC10X->GetTime(time); ptr += sizeof(CP56Time2a_T); } /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildDetect_Spont(uint8_t TimeFlag, PIEC10X_DETECT_T detectV, uint16_t addrV) { uint8_t len = 0, asdu_num = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC10X_DETECT_T detect = NULL; PCP56Time2a_T time = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_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*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_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; IEC10X->GetTime(time); ptr += sizeof(CP56Time2a_T); } /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildDetectF_Spont(uint8_t TimeFlag, float detectV, uint16_t addrV) { uint8_t len = 0, asdu_num = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC10X_DETECT_F_T detect = NULL; PCP56Time2a_T time = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_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*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_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; IEC10X->GetTime(time); ptr += sizeof(CP56Time2a_T); } /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_SPON, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildSignal(uint8_t reason, uint8_t Prio, uint8_t DevType) { uint8_t len = 0, asdu_num = 0; uint16_t i = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*get value*/ IEC10X->GetInfoNum(&asdu_num, DevType); LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_Addr; /*build info addr*/ ptr = info->_addr; if (DevType == ENDDEVICE_TYPE_HXTM) { Temp32 = IEC104_INFOADDR_STATE_HXTM; } else if (DevType == ENDDEVICE_TYPE_HXGF) { Temp32 = IEC104_INFOADDR_STATE_HXGF; } else { LOG("-%s-, error dev type:%d \n", __FUNCTION__, DevType); return RET_ERROR; } memcpy(ptr, &Temp32, 3); /*build info value*/ ptr = info->_element; for (i = 0; i < asdu_num; i++) { *ptr = IEC10X->GetStationState(i, DevType); ptr++; } /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildDetect(uint8_t reason, uint8_t ValueType, uint8_t Prio, uint8_t DevType) { uint8_t len = 0, asdu_num = 0, i; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC10X_DETECT_T detect = NULL; PIEC10X_DETECT_F_T detect_f = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*get value*/ IEC10X->GetInfoNum(&asdu_num, DevType); LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*build ASDU , COT ,Addr*/ asdu->_type = ValueType; asdu->_num._sq = 1; asdu->_num._num = asdu_num; asdu->_reason._reason = reason; asdu->_addr = Iec10x_Sta_Addr; /*build info addr*/ ptr = info->_addr; if (DevType == ENDDEVICE_TYPE_HXTM) { Temp32 = IEC104_INFOADDR_VALUE_HXTM; } else if (DevType == ENDDEVICE_TYPE_HXGF) { Temp32 = IEC104_INFOADDR_VALUE_HXGF; } else { LOG("-%s-, error dev type:%d \n", __FUNCTION__, DevType); 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 = IEC10X->GetStaValue(i, DevType); 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 = IEC10X->GetStaValue(i, DevType); detect_f->_qds = 0; ptr += sizeof(IEC10X_DETECT_F_T); } } /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildUpload(uint8_t ValueType, uint8_t Prio, uint8_t DevType) { uint8_t len = 0, asdu_num = 0, i; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC10X_DETECT_T detect = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*get value*/ IEC10X->GetInfoNum(&asdu_num, DevType); LOG("-%s- total info (%d) \n\n", __FUNCTION__, asdu_num); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_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 = IEC10X->GetStaValue(i, DevType); detect->_qds = 0; ptr += sizeof(IEC10X_DETECT_T); } /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_BuildActFinish(uint8_t qoi, uint8_t Prio) { uint8_t len = 0, asdu_num = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*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 = Iec10x_Sta_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_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_Build_U(uint8_t UType, uint8_t Ack) { uint8_t len = 0, Tester, Start, Stop; uint8_t *ptr = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; /*build head*/ Iec104Data->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: Iec104Data->Ctrl.Func.Func = Start; break; case IEC104_U_FUNC_STOPDT: Iec104Data->Ctrl.Func.Func = Stop; break; case IEC104_U_FUNC_TESTER: Iec104Data->Ctrl.Func.Func = Tester; break; default: LOG(">%s<, U Type Error(%d) !\n", __FUNCTION__, UType); return RET_ERROR; } /*build ASDU , COT ,Addr*/ ptr = Iec104Data->Asdu; /*build info*/ /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_Build_S_Ack(void) { uint8_t len = 0; uint8_t *ptr = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.S.Type1 = 1; Iec104Data->Ctrl.S.Type2 = 0; Iec104Data->Ctrl.S.Reserve = 0; Iec104Data->Ctrl.S.RecvSn = Iec104_BuildRecvSn; /*build ASDU , COT ,Addr*/ ptr = Iec104Data->Asdu; /*build info*/ /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec101_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, IEC10X_PRIO_INITLINK, NULL, NULL); return RET_SUCESS; } uint8_t IEC104_ASDU_Call(PIEC10X_ASDU_T Iec10x_Asdu) { PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info); uint8_t qoi = asdu_info->_element[0]; uint8_t Prio = 0; uint32_t 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_BuildCallACK(qoi, Prio); /**/ IEC104_BuildSignal(qoi, Prio, ENDDEVICE_TYPE_HXTM); IEC104_BuildDetect(qoi, IEC10X_M_ME_NA_1, Prio, ENDDEVICE_TYPE_HXTM); /**/ IEC104_BuildSignal(qoi, Prio, ENDDEVICE_TYPE_HXGF); IEC104_BuildDetect(qoi, IEC10X_M_ME_NA_1, Prio, ENDDEVICE_TYPE_HXGF); IEC104_BuildActFinish(qoi, Prio); break; default: LOG("-%s- call cmd error reason(%d) \n", __FUNCTION__, Iec10x_Asdu->_reason._reason); break; } return RET_SUCESS; } uint8_t Iec104_Aadu_Clock(PIEC10X_ASDU_T Iec10x_Asdu) { PASDU_INFO_T asdu_info = (PASDU_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*/ /*...*/ IEC10X->SetTime(&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; } uint8_t IEC104_ASDU_SetAct(PIEC10X_ASDU_T Iec10x_Asdu, uint8_t Type) { PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info); uint8_t *ptr = NULL; uint8_t n = Iec10x_Asdu->_num._num, Sq = Iec10x_Asdu->_num._sq, i; float Value = 0.0; uint32_t 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); IEC10X->SetConfig(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); IEC10X->SetConfig(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); IEC10X->SetConfig(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); IEC10X->SetConfig(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; } uint8_t IEC104_Build_SetAck(uint8_t Prio, uint8_t Type) { uint8_t len = 0; uint8_t *ptr = NULL; PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*build ASDU , COT ,Addr*/ asdu->_type = Type; asdu->_num._sq = 0; asdu->_num._num = 0; asdu->_reason._reason = IEC10X_ASDU_REASON_ACTFIN; asdu->_addr = Iec10x_Sta_Addr; /*build info*/ ptr = info->_addr; /*len*/ len = ptr - Iec104_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec104_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } uint8_t Iec104_Deal_SN(uint16_t SendSn, uint16_t RecvSn) { LOG("Receive Pakage I(%d,%d), Send(%d,%d)\n", SendSn, RecvSn, Iec104_BuildSendSn, Iec104_BuildRecvSn); #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_DealSendSn || RecvSn < Iec104_DealRecvSn) { LOG("-%s-, error,send last(%d),now(%d). recv last(%d),now(%d) \n", __FUNCTION__, Iec104_DealSendSn, SendSn, Iec104_DealRecvSn, RecvSn); return RET_ERROR; } Iec104_BuildRecvSn = SendSn + 1; Iec104_DealSendSn = SendSn; Iec104_DealRecvSn = RecvSn; // Iec104_BuildRecvSn++; /* return S ACK */ IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_S_ACK; Iec104_TimeCycle_S = 0; return RET_SUCESS; } int8_t Iec104_BuildDataAck(uint8_t TI, uint16_t COT, uint32_t InfoAddr, uint16_t Info, uint8_t Prio) { uint8_t len = 0; uint8_t *ptr = NULL; uint32_t Temp32 = 0; /* build head */ PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); /*build head*/ Iec104Data->Head = IEC104_HEAD; /*build control code*/ Iec104Data->Ctrl.I.Type = 0; Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++; Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn; /*build ASDU , COT ,Addr*/ asdu->_type = TI; asdu->_num._sq = 0; asdu->_num._num = 1; asdu->_reason._reason = COT; asdu->_addr = Iec10x_Sta_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_Sendbuf; Iec104Data->Len = len - 2; // DumpHEX(Iec104_Sendbuf,len); /* enqueue to the transmisson queue */ IEC10X_Enqueue(Iec104_Sendbuf, len, Prio, NULL, NULL); return RET_SUCESS; } int8_t Iec104_Deal_FirmUpdate(PIEC10X_ASDU_T asdu, uint8_t Len) { uint16_t cot = asdu->_reason._reason; uint16_t FlagNum = 0, i; uint8_t DataLen = Len - IEC104_DATA_LEN - 3; /* flag num 2, check sum 1 byte*/ PASDU_INFO_T element = (PASDU_INFO_T)(asdu->_info); uint8_t *DataPtr = (uint8_t *)(element->_element) + 3; uint8_t TI = asdu->_type, csum = 0, CsumTemp = 0; uint32_t FirmwareType = 0; int8_t ret = 0; PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info); FlagNum = *(uint16_t *)(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 = IEC10X->SaveFirmware(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 = IEC10X->SaveFirmware(DataLen, DataPtr, FirmwareType, Iec10x_Update_SeekAddr); if (ret == RET_SUCESS) break; } if (ret == RET_ERROR) { LOG("save firmware error \n"); break; } Iec104_BuildDataAck(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_BuildDataAck(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 = IEC10X->CheckFirmware(FirmwareType, Iec10x_Update_SeekAddr); if (ret == RET_SUCESS) { Iec104_BuildDataAck(TI, IEC10X_COT_DATA_FIN_ACK, FirmwareType, FlagNum, 1); IEC10X->UpdateFirmware(FirmwareType); } else { /* check firmware error ,terminal update */ Iec104_BuildDataAck(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_BuildDataAck(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; } uint8_t Iec104_Deal_I(PIEC104_DATA_T Iec104Data, uint16_t len) { uint8_t Type; uint16_t RecvSn, SendSn; uint32_t FirmwareType = 0; PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu); SendSn = Iec104Data->Ctrl.I.SendSn; RecvSn = Iec104Data->Ctrl.I.RecvSn; /* check asdu addrest */ if (Iec10x_Sta_Addr != asdu->_addr) { LOG("-%s-, error asdu addr(%x)(%x) \n", __FUNCTION__, Iec10x_Sta_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_Aadu_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_SetAct(asdu, Type); IEC104_Build_SetAck(1, Type); break; case IEC10X_TI_FIRM_UPDATE: LOG("++++Asdu Type Firmware Update... \n"); Iec104_Deal_FirmUpdate(asdu, len); break; case IEC10X_TI_AP_FIRM_BACKOFF: LOG("++++Asdu Type Firmware Backoff... \n"); memcpy(&FirmwareType, asdu->_info, 3); Iec104_BuildDataAck(IEC10X_TI_AP_FIRM_BACKOFF, IEC10X_COT_ACTCON, FirmwareType, 0, 1); IEC10X->BackoffFirmware(FirmwareType); break; default: LOG("-%s-, error Type(%d) \n", __FUNCTION__, Type); return RET_ERROR; } return RET_SUCESS; } uint8_t Iec104_Deal_S(PIEC104_DATA_T Iec104Data, uint16_t len) { return RET_SUCESS; } uint8_t Iec104_Deal_U(PIEC104_DATA_T Iec104Data, uint16_t len) { switch (Iec104Data->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__); IEC10X->CloseLink(); 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 Iex104_Receive(uint8_t *buf, uint16_t len) { uint8_t *BufTemp = NULL; int16_t LenRemain, LenTmp; PIEC104_DATA_T Iec104Data = NULL; if (buf == NULL) { LOG("-%s-,buffer (null)", __FUNCTION__); return; } #if 0 if(len <= 0 || len>IEC104_MAX_BUF_LEN || lenHead == IEC104_HEAD) { LenTmp = Iec104Data->Len + 2; if (LenRemain < IEC104_HEAD_LEN) { LOG("_%s_,len error(%d) \n", __FUNCTION__, len); Iec10x_UnLock(); return; } if (Iec104Data->Ctrl.Type.Type1 == 0) { LOG("-%s-,Frame Type I \n", __FUNCTION__); Iec104_Deal_I(Iec104Data, LenTmp); } else if (Iec104Data->Ctrl.Type.Type1 == 1 && Iec104Data->Ctrl.Type.Type2 == 0) { LOG("-%s-,Frame Type S \n", __FUNCTION__); Iec104_Deal_S(Iec104Data, LenTmp); } else if (Iec104Data->Ctrl.Type.Type1 == 1 && Iec104Data->Ctrl.Type.Type2 == 1) { LOG("-%s-,Frame Type U \n", __FUNCTION__); Iec104_Deal_U(Iec104Data, LenTmp); } } else { LOG("-%s-,head type error(%d) \n", __FUNCTION__, BufTemp[0]); Iec10x_UnLock(); return; } Iec10x_UnLock(); BufTemp += LenTmp; LenRemain -= LenTmp; } return; } void Iec104_ResetFlag(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_BuildSendSn = 0; Iec104_BuildRecvSn = 0; Iec104_DealSendSn = -1; Iec104_DealRecvSn = 0; Iec104_TesterCount = 0; } uint32_t TestCount_Temp = 0; uint8_t Iec104_StateMachine(void) { /*Init link*/ switch (IEC104_STATE_FLAG_INIT) { case IEC104_FLAG_CLOSED: #if defined(IEC104_STM32_FUJIAN_HX) IEC104_STATE_FLAG_INIT = IEC104_FLAG_UPLOAD_ADDR; #else IEC104_STATE_FLAG_INIT = IEC104_FLAG_START_LINK; IEC10X_ClearQ(); Iec104_ResetFlag(); #endif /* IEC104_STM32_FUJIAN_HX */ 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; IEC10X->CloseLink(); } break; case IEC104_FLAG_RECV_CLOSED: Iec104_ResetFlag(); IEC10X_ClearQ(); IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS; break; case IEC104_FLAG_LINK_INIT: LOG("Iec104 machine state :IEC104_FLAG_LINK_INIT \n"); Iec104_ResetFlag(); Iec10x_Sta_Addr = IEC10X->GetLinkAddr(); IEC104_Build_U(IEC104_U_FUNC_STARTDT, 1); IEC104_Build_InitFin(); IEC104_BuildUpload(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) { Iec10x_Sta_Addr = IEC10X->GetLinkAddr(); Iec104_TimeCycle = 0; Iec104_TimeCount++; IEC104_UploadAddr(); } if (Iec104_TimeCount >= 3) { Iec104_TimeCount = 0; IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE; IEC10X->CloseLink(); } 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 0 if(TestCount_Temp++>(10*60*20)){ TestCount_Temp = 0; IEC104_BuildSignal_Spon(1, 1, IEC104_INFOADDR_STATE_HXGF+2); IEC104_BuildDetectF_Spont(1, 60.2, IEC104_INFOADDR_VALUE_HXTM+2); IEC104_BuildDetectF_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; IEC10X->CloseLink(); } 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; }