Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        /// <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);
        }