public bool HandleFileAsdu(ASDU asdu) { bool asduHandled = true; switch (asdu.TypeId) { case TypeID.F_SC_NA_1: /* File/Section/Directory Call/Select */ DebugLog("Received SELECT/CALL"); if (state == FileClientState.WAITING_FOR_FILE_READY) { if (asdu.Cot == CauseOfTransmission.UNKNOWN_TYPE_ID) { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.UNKNOWN_SERVICE); } } else if (asdu.Cot == CauseOfTransmission.UNKNOWN_COMMON_ADDRESS_OF_ASDU) { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.UNKNOWN_CA); } } else if (asdu.Cot == CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS) { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.UNKNOWN_IOA); } } else { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.PROTOCOL_ERROR); } } } else { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.PROTOCOL_ERROR); } } ResetStateToIdle(); break; case TypeID.F_FR_NA_1: /* File ready */ DebugLog("Received FILE READY"); if (state == FileClientState.WAITING_FOR_FILE_READY) { //TODO check ca, ioa, nof FileReady fileReady = (FileReady)asdu.GetElement(0); if (fileReady.Positive) { ASDU callFile = NewAsdu(new FileCallOrSelect(ioa, nof, 0, SelectAndCallQualifier.REQUEST_FILE)); master.SendASDU(callFile); DebugLog("Send CALL FILE"); state = FileClientState.WAITING_FOR_SECTION_READY; } else { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.FILE_NOT_READY); } ResetStateToIdle(); } } else if (state == FileClientState.IDLE) { //TODO call user callback to //TODO send positive or negative ACK state = FileClientState.WAITING_FOR_SECTION_READY; } else { AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR); } break; case TypeID.F_SR_NA_1: /* Section ready */ DebugLog("Received SECTION READY"); if (state == FileClientState.WAITING_FOR_SECTION_READY) { SectionReady sc = (SectionReady)asdu.GetElement(0); if (sc.NotReady == false) { ASDU callSection = NewAsdu(new FileCallOrSelect(ioa, nof, 0, SelectAndCallQualifier.REQUEST_SECTION)); master.SendASDU(callSection); DebugLog("Send CALL SECTION"); segmentOffset = 0; state = FileClientState.RECEIVING_SECTION; } else { AbortFileTransfer(FileErrorCode.SECTION_NOT_READY); } } else if (state == FileClientState.IDLE) { } else { if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.PROTOCOL_ERROR); } ResetStateToIdle(); } break; case TypeID.F_SG_NA_1: /* Segment */ DebugLog("Received SEGMENT"); if (state == FileClientState.RECEIVING_SECTION) { FileSegment segment = (FileSegment)asdu.GetElement(0); if (fileReceiver != null) { fileReceiver.SegmentReceived(segment.NameOfSection, segmentOffset, segment.LengthOfSegment, segment.SegmentData); } segmentOffset += segment.LengthOfSegment; } else if (state == FileClientState.IDLE) { } else { AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR); } break; case TypeID.F_LS_NA_1: /* Last segment or section */ DebugLog("Received LAST SEGMENT/SECTION"); if (state != FileClientState.IDLE) { FileLastSegmentOrSection lastSection = (FileLastSegmentOrSection)asdu.GetElement(0); if (lastSection.LSQ == LastSectionOrSegmentQualifier.SECTION_TRANSFER_WITHOUT_DEACT) { if (state == FileClientState.RECEIVING_SECTION) { ASDU segmentAck = NewAsdu(new FileACK(ioa, nof, lastSection.NameOfSection, AcknowledgeQualifier.POS_ACK_SECTION, FileError.DEFAULT)); master.SendASDU(segmentAck); DebugLog("Send SEGMENT ACK"); state = FileClientState.WAITING_FOR_SECTION_READY; } else { AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR); } } else if (lastSection.LSQ == LastSectionOrSegmentQualifier.FILE_TRANSFER_WITH_DEACT) { /* slave aborted transfer */ if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.ABORTED_BY_REMOTE); } ResetStateToIdle(); } else if (lastSection.LSQ == LastSectionOrSegmentQualifier.FILE_TRANSFER_WITHOUT_DEACT) { if (state == FileClientState.WAITING_FOR_SECTION_READY) { ASDU fileAck = NewAsdu(new FileACK(ioa, nof, lastSection.NameOfSection, AcknowledgeQualifier.POS_ACK_FILE, FileError.DEFAULT)); master.SendASDU(fileAck); DebugLog("Send FILE ACK"); if (fileReceiver != null) { fileReceiver.Finished(FileErrorCode.SUCCESS); } ResetStateToIdle(); } else { DebugLog("Illegal state: " + state.ToString()); AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR); } } } break; default: asduHandled = false; break; } return(asduHandled); }
/// <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); }