public bool HandleFileAsdu(ASDU asdu) { bool handled = true; switch (asdu.TypeId) { case TypeID.F_AF_NA_1: /* 124 - ACK file, ACK section */ logger("Received file/section ACK F_AF_NA_1"); if (asdu.Cot == CauseOfTransmission.FILE_TRANSFER) { if (transferState != FileServerState.UNSELECTED_IDLE) { IFileProvider file = selectedFile.provider; FileACK ack = (FileACK)asdu.GetElement(0); if (ack.AckQualifier == AcknowledgeQualifier.POS_ACK_FILE) { logger("Received positive file ACK"); if (transferState == FileServerState.WAITING_FOR_FILE_ACK) { selectedFile.provider.TransferComplete(true); availableFiles.RemoveFile(selectedFile.provider); selectedFile = null; transferState = FileServerState.UNSELECTED_IDLE; } else { logger("Unexpected file transfer state --> abort file transfer"); transferState = FileServerState.SEND_ABORT; } } else if (ack.AckQualifier == AcknowledgeQualifier.NEG_ACK_FILE) { logger("Received negative file ACK - stop transfer"); if (transferState == FileServerState.WAITING_FOR_FILE_ACK) { selectedFile.provider.TransferComplete(false); selectedFile.selectedBy = null; selectedFile = null; transferState = FileServerState.UNSELECTED_IDLE; } else { logger("Unexpected file transfer state --> abort file transfer"); transferState = FileServerState.SEND_ABORT; } } else if (ack.AckQualifier == AcknowledgeQualifier.NEG_ACK_SECTION) { logger("Received negative file section ACK - repeat section"); if (transferState == FileServerState.WAITING_FOR_SECTION_ACK) { currentSectionOffset = 0; sectionChecksum = 0; ASDU sectionReady = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, file.GetCA(), false); sectionReady.AddInformationObject( new SectionReady(selectedFile.provider.GetIOA(), selectedFile.provider.GetNameOfFile(), currentSectionNumber, currentSectionSize, false)); connection.SendASDU(sectionReady); transferState = FileServerState.TRANSMIT_SECTION; } else { logger("Unexpected file transfer state --> abort file transfer"); transferState = FileServerState.SEND_ABORT; } } else if (ack.AckQualifier == AcknowledgeQualifier.POS_ACK_SECTION) { if (transferState == FileServerState.WAITING_FOR_SECTION_ACK) { currentSectionNumber++; int nextSectionSize = selectedFile.provider.GetSectionSize(currentSectionNumber); ASDU responseAsdu = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, file.GetCA(), false); if (nextSectionSize == -1) { logger("Reveived positive file section ACK - send last section indication"); responseAsdu.AddInformationObject( new FileLastSegmentOrSection(file.GetIOA(), file.GetNameOfFile(), (byte)currentSectionNumber, LastSectionOrSegmentQualifier.FILE_TRANSFER_WITHOUT_DEACT, fileChecksum)); transferState = FileServerState.WAITING_FOR_FILE_ACK; } else { logger("Reveived positive file section ACK - send next section ready indication"); currentSectionSize = nextSectionSize; responseAsdu.AddInformationObject( new SectionReady(selectedFile.provider.GetIOA(), selectedFile.provider.GetNameOfFile(), currentSectionNumber, currentSectionSize, false)); transferState = FileServerState.WAITING_FOR_SECTION_CALL; } connection.SendASDU(responseAsdu); sectionChecksum = 0; } else { logger("Unexpected file transfer state --> abort file transfer"); transferState = FileServerState.SEND_ABORT; } } } else { // No file transmission in progress --> what to do? logger("Unexpected File ACK message -> ignore"); } } else { asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION; connection.SendASDU(asdu); } break; case TypeID.F_SC_NA_1: /* 122 - Call/Select directoy/file/section */ logger("Received call/select F_SC_NA_1"); if (asdu.Cot == CauseOfTransmission.FILE_TRANSFER) { FileCallOrSelect sc = (FileCallOrSelect)asdu.GetElement(0); if (sc.SCQ == SelectAndCallQualifier.SELECT_FILE) { if (transferState == FileServerState.UNSELECTED_IDLE) { logger("Received SELECT FILE"); CS101n104File file = availableFiles.GetFile(asdu.Ca, sc.ObjectAddress, sc.NOF); if (file == null) { asdu.Cot = CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS; connection.SendASDU(asdu); } else { ASDU fileReady = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, asdu.Ca, false); // check if already selected if (file.selectedBy == null) { file.selectedBy = this; fileReady.AddInformationObject(new FileReady(sc.ObjectAddress, sc.NOF, file.provider.GetFileSize(), true)); } else { fileReady.AddInformationObject(new FileReady(sc.ObjectAddress, sc.NOF, 0, false)); } connection.SendASDU(fileReady); selectedFile = file; transferState = FileServerState.WAITING_FOR_FILE_CALL; } } else { logger("Unexpected SELECT FILE message"); } } else if (sc.SCQ == SelectAndCallQualifier.DEACTIVATE_FILE) { logger("Received DEACTIVATE FILE"); if (transferState != FileServerState.UNSELECTED_IDLE) { if (selectedFile != null) { selectedFile.selectedBy = null; selectedFile = null; } transferState = FileServerState.UNSELECTED_IDLE; } else { logger("Unexpected DEACTIVATE FILE message"); } } else if (sc.SCQ == SelectAndCallQualifier.REQUEST_FILE) { logger("Received CALL FILE"); if (transferState == FileServerState.WAITING_FOR_FILE_CALL) { if (selectedFile.provider.GetIOA() != sc.ObjectAddress) { logger("Unkown IOA"); asdu.Cot = CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS; connection.SendASDU(asdu); } else { ASDU sectionReady = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, asdu.Ca, false); sectionReady.AddInformationObject(new SectionReady(sc.ObjectAddress, selectedFile.provider.GetNameOfFile(), 0, 0, false)); connection.SendASDU(sectionReady); logger("Send SECTION READY"); currentSectionNumber = 0; currentSectionOffset = 0; currentSectionSize = selectedFile.provider.GetSectionSize(0); transferState = FileServerState.WAITING_FOR_SECTION_CALL; } } else { logger("Unexpected FILE CALL message"); } } else if (sc.SCQ == SelectAndCallQualifier.REQUEST_SECTION) { logger("Received CALL SECTION"); if (transferState == FileServerState.WAITING_FOR_SECTION_CALL) { if (selectedFile.provider.GetIOA() != sc.ObjectAddress) { logger("Unkown IOA"); asdu.Cot = CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS; connection.SendASDU(asdu); } else { transferState = FileServerState.TRANSMIT_SECTION; } } else { logger("Unexpected SECTION CALL message"); } } } else if (asdu.Cot == CauseOfTransmission.REQUEST) { logger("Call directory received"); availableFiles.SendDirectoy(connection, false); } else { asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION; connection.SendASDU(asdu); } break; default: handled = false; break; } return(handled); }
/// <summary> /// Gets the element (information object) with the specified index /// </summary> /// <returns>the information object at index</returns> /// <param name="index">index of the element (starting with 0)</param> /// <exception cref="lib60870.ASDUParsingException">Thrown when there is a problem parsing the ASDU</exception> public InformationObject GetElement(int index) { if (index >= NumberOfElements) { throw new ASDUParsingException("Index out of range"); } InformationObject retVal = null; int elementSize; switch (typeId) { case TypeID.M_SP_NA_1: /* 1 */ elementSize = 1; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new SinglePointInformation(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new SinglePointInformation(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_SP_TA_1: /* 2 */ elementSize = 4; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new SinglePointWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new SinglePointWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_DP_NA_1: /* 3 */ elementSize = 1; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new DoublePointInformation(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new DoublePointInformation(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_DP_TA_1: /* 4 */ elementSize = 4; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new DoublePointWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new DoublePointWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ST_NA_1: /* 5 */ elementSize = 2; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new StepPositionInformation(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new StepPositionInformation(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ST_TA_1: /* 6 */ elementSize = 5; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new StepPositionWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new StepPositionWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_BO_NA_1: /* 7 */ elementSize = 5; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new Bitstring32(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new Bitstring32(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_BO_TA_1: /* 8 */ elementSize = 8; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new Bitstring32WithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new Bitstring32WithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_NA_1: /* 9 */ elementSize = 3; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueNormalized(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueNormalized(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_TA_1: /* 10 */ elementSize = 6; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueNormalizedWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueNormalizedWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_NB_1: /* 11 */ elementSize = 3; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueScaled(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueScaled(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_TB_1: /* 12 */ elementSize = 6; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueScaledWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueScaledWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_NC_1: /* 13 */ elementSize = 5; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueShort(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueShort(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_TC_1: /* 14 */ elementSize = 8; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueShortWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueShortWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_IT_NA_1: /* 15 */ elementSize = 5; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new IntegratedTotals(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new IntegratedTotals(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_IT_TA_1: /* 16 */ elementSize = 8; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new IntegratedTotalsWithCP24Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new IntegratedTotalsWithCP24Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_EP_TA_1: /* 17 */ elementSize = 3; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new EventOfProtectionEquipment(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new EventOfProtectionEquipment(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_EP_TB_1: /* 18 */ elementSize = 7; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new PackedStartEventsOfProtectionEquipment(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new PackedStartEventsOfProtectionEquipment(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_EP_TC_1: /* 19 */ elementSize = 7; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new PackedOutputCircuitInfo(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new PackedOutputCircuitInfo(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_PS_NA_1: /* 20 */ elementSize = 5; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new PackedSinglePointWithSCD(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new PackedSinglePointWithSCD(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_ND_1: /* 21 */ elementSize = 2; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueNormalizedWithoutQuality(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueNormalizedWithoutQuality(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; /* 22 - 29 reserved */ case TypeID.M_SP_TB_1: /* 30 */ elementSize = 8; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new SinglePointWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new SinglePointWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_DP_TB_1: /* 31 */ elementSize = 8; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new DoublePointWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new DoublePointWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ST_TB_1: /* 32 */ elementSize = 9; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new StepPositionWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new StepPositionWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_BO_TB_1: /* 33 */ elementSize = 12; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new Bitstring32WithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new Bitstring32WithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_TD_1: /* 34 */ elementSize = 10; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueNormalizedWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueNormalizedWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_TE_1: /* 35 */ elementSize = 10; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueScaledWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueScaledWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_ME_TF_1: /* 36 */ elementSize = 12; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new MeasuredValueShortWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new MeasuredValueShortWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_IT_TB_1: /* 37 */ elementSize = 12; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new IntegratedTotalsWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new IntegratedTotalsWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_EP_TD_1: /* 38 */ elementSize = 10; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new EventOfProtectionEquipmentWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new EventOfProtectionEquipmentWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_EP_TE_1: /* 39 */ elementSize = 11; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new PackedStartEventsOfProtectionEquipmentWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new PackedStartEventsOfProtectionEquipmentWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; case TypeID.M_EP_TF_1: /* 40 */ elementSize = 11; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new PackedOutputCircuitInfoWithCP56Time2a(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new PackedOutputCircuitInfoWithCP56Time2a(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; /* 41 - 44 reserved */ case TypeID.C_SC_NA_1: /* 45 */ elementSize = parameters.SizeOfIOA + 1; retVal = new SingleCommand(parameters, payload, index * elementSize); break; case TypeID.C_DC_NA_1: /* 46 */ elementSize = parameters.SizeOfIOA + 1; retVal = new DoubleCommand(parameters, payload, index * elementSize); break; case TypeID.C_RC_NA_1: /* 47 */ elementSize = parameters.SizeOfIOA + 1; retVal = new StepCommand(parameters, payload, index * elementSize); break; case TypeID.C_SE_NA_1: /* 48 - Set-point command, normalized value */ elementSize = parameters.SizeOfIOA + 3; retVal = new SetpointCommandNormalized(parameters, payload, index * elementSize); break; case TypeID.C_SE_NB_1: /* 49 - Set-point command, scaled value */ elementSize = parameters.SizeOfIOA + 3; retVal = new SetpointCommandScaled(parameters, payload, index * elementSize); break; case TypeID.C_SE_NC_1: /* 50 - Set-point command, short floating point number */ elementSize = parameters.SizeOfIOA + 5; retVal = new SetpointCommandShort(parameters, payload, index * elementSize); break; case TypeID.C_BO_NA_1: /* 51 - Bitstring command */ elementSize = parameters.SizeOfIOA + 4; retVal = new Bitstring32Command(parameters, payload, index * elementSize); break; /* 52 - 57 reserved */ case TypeID.C_SC_TA_1: /* 58 - Single command with CP56Time2a */ elementSize = parameters.SizeOfIOA + 8; retVal = new SingleCommandWithCP56Time2a(parameters, payload, index * elementSize); break; case TypeID.C_DC_TA_1: /* 59 - Double command with CP56Time2a */ elementSize = parameters.SizeOfIOA + 8; retVal = new DoubleCommandWithCP56Time2a(parameters, payload, index * elementSize); break; case TypeID.C_RC_TA_1: /* 60 - Step command with CP56Time2a */ elementSize = parameters.SizeOfIOA + 8; retVal = new StepCommandWithCP56Time2a(parameters, payload, index * elementSize); break; case TypeID.C_SE_TA_1: /* 61 - Setpoint command, normalized value with CP56Time2a */ elementSize = parameters.SizeOfIOA + 10; retVal = new SetpointCommandNormalizedWithCP56Time2a(parameters, payload, index * elementSize); break; case TypeID.C_SE_TB_1: /* 62 - Setpoint command, scaled value with CP56Time2a */ elementSize = parameters.SizeOfIOA + 10; retVal = new SetpointCommandScaledWithCP56Time2a(parameters, payload, index * elementSize); break; case TypeID.C_SE_TC_1: /* 63 - Setpoint command, short value with CP56Time2a */ elementSize = parameters.SizeOfIOA + 12; retVal = new SetpointCommandShortWithCP56Time2a(parameters, payload, index * elementSize); break; case TypeID.C_BO_TA_1: /* 64 - Bitstring command with CP56Time2a */ elementSize = parameters.SizeOfIOA + 11; retVal = new Bitstring32CommandWithCP56Time2a(parameters, payload, index * elementSize); break; /* 65 - 69 reserved */ case TypeID.M_EI_NA_1: /* 70 - End of initialization */ elementSize = parameters.SizeOfCA + 1; retVal = new EndOfInitialization(parameters, payload, index * elementSize); break; case TypeID.C_IC_NA_1: /* 100 - Interrogation command */ elementSize = parameters.SizeOfIOA + 1; retVal = new InterrogationCommand(parameters, payload, index * elementSize); break; case TypeID.C_CI_NA_1: /* 101 - Counter interrogation command */ elementSize = parameters.SizeOfIOA + 1; retVal = new CounterInterrogationCommand(parameters, payload, index * elementSize); break; case TypeID.C_RD_NA_1: /* 102 - Read command */ elementSize = parameters.SizeOfIOA; retVal = new ReadCommand(parameters, payload, index * elementSize); break; case TypeID.C_CS_NA_1: /* 103 - Clock synchronization command */ elementSize = parameters.SizeOfIOA + 7; retVal = new ClockSynchronizationCommand(parameters, payload, index * elementSize); break; case TypeID.C_TS_NA_1: /* 104 - Test command */ elementSize = parameters.SizeOfIOA + 2; retVal = new TestCommand(parameters, payload, index * elementSize); break; case TypeID.C_RP_NA_1: /* 105 - Reset process command */ elementSize = parameters.SizeOfIOA + 1; retVal = new ResetProcessCommand(parameters, payload, index * elementSize); break; case TypeID.C_CD_NA_1: /* 106 - Delay acquisition command */ elementSize = parameters.SizeOfIOA + 2; retVal = new DelayAcquisitionCommand(parameters, payload, index * elementSize); break; case TypeID.C_TS_TA_1: /* 107 - Test command with CP56Time2a */ elementSize = parameters.SizeOfIOA + 9; retVal = new TestCommandWithCP56Time2a(parameters, payload, index * elementSize); break; /* C_TS_TA_1 (107) is handled by the stack automatically */ case TypeID.P_ME_NA_1: /* 110 - Parameter of measured values, normalized value */ elementSize = parameters.SizeOfIOA + 3; retVal = new ParameterNormalizedValue(parameters, payload, index * elementSize); break; case TypeID.P_ME_NB_1: /* 111 - Parameter of measured values, scaled value */ elementSize = parameters.SizeOfIOA + 3; retVal = new ParameterScaledValue(parameters, payload, index * elementSize); break; case TypeID.P_ME_NC_1: /* 112 - Parameter of measured values, short floating point number */ elementSize = parameters.SizeOfIOA + 5; retVal = new ParameterFloatValue(parameters, payload, index * elementSize); break; case TypeID.P_AC_NA_1: /* 113 - Parameter for activation */ elementSize = parameters.SizeOfIOA + 1; retVal = new ParameterActivation(parameters, payload, index * elementSize); break; case TypeID.F_FR_NA_1: /* 120 - File ready */ retVal = new FileReady(parameters, payload, 0, false); break; case TypeID.F_SR_NA_1: /* 121 - Section ready */ retVal = new SectionReady(parameters, payload, 0, false); break; case TypeID.F_SC_NA_1: /* 122 - Call directory, select file, call file, call section */ retVal = new FileCallOrSelect(parameters, payload, 0, false); break; case TypeID.F_LS_NA_1: /* 123 - Last section, last segment */ retVal = new FileLastSegmentOrSection(parameters, payload, 0, false); break; case TypeID.F_AF_NA_1: /* 124 - ACK file, ACK section */ retVal = new FileACK(parameters, payload, 0, false); break; case TypeID.F_SG_NA_1: /* 125 - Segment */ retVal = new FileSegment(parameters, payload, 0, false); break; case TypeID.F_DR_TA_1: /* 126 - Directory */ elementSize = 13; if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = new FileDirectory(parameters, payload, parameters.SizeOfIOA + (index * elementSize), true); retVal.ObjectAddress = ioa + index; } else { retVal = new FileDirectory(parameters, payload, index * (parameters.SizeOfIOA + elementSize), false); } break; /* 114 - 119 reserved */ default: if (privateObjectTypes != null) { IPrivateIOFactory ioFactory = privateObjectTypes.GetFactory(typeId); if (ioFactory != null) { elementSize = parameters.SizeOfIOA + ioFactory.GetEncodedSize(); if (IsSequence) { int ioa = InformationObject.ParseInformationObjectAddress(parameters, payload, 0); retVal = ioFactory.Decode(parameters, payload, index * elementSize, true); retVal.ObjectAddress = ioa + index; } else { retVal = ioFactory.Decode(parameters, payload, index * elementSize, false); } } } break; } if (retVal == null) { throw new ASDUParsingException("Unknown ASDU type id:" + typeId); } return(retVal); }